Imported Upstream version 1.10.1 26/273426/1 upstream/1.10.1
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 5 Apr 2022 08:15:00 +0000 (10:15 +0200)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 5 Apr 2022 12:21:10 +0000 (14:21 +0200)
Change-Id: Ifda8904e35b4cafadcc19979a12c6a11736ca896

408 files changed:
.gitignore [new file with mode: 0644]
.mailmap [new file with mode: 0644]
AUTHORS
ChangeLog
LICENSES
Makefile.am
Makefile.in [deleted file]
NEWS
README
VERSION [deleted file]
acinclude.m4
aclocal.m4 [deleted file]
autogen.rc
autogen.sh
build-aux/db2any [new file with mode: 0755]
build-aux/distfiles [new file with mode: 0644]
build-aux/git-hooks/commit-msg [new file with mode: 0755]
cipher/Makefile.am
cipher/Makefile.in [deleted file]
cipher/arcfour-amd64.S
cipher/arcfour.c
cipher/asm-common-aarch64.h [new file with mode: 0644]
cipher/asm-common-amd64.h [new file with mode: 0644]
cipher/asm-common-s390x.h [new file with mode: 0644]
cipher/asm-inline-s390x.h [new file with mode: 0644]
cipher/asm-poly1305-aarch64.h [new file with mode: 0644]
cipher/asm-poly1305-amd64.h [new file with mode: 0644]
cipher/asm-poly1305-s390x.h [new file with mode: 0644]
cipher/bithelp.h
cipher/blake2.c
cipher/blake2b-amd64-avx2.S [new file with mode: 0644]
cipher/blake2s-amd64-avx.S [new file with mode: 0644]
cipher/blowfish-amd64.S
cipher/blowfish.c
cipher/bufhelp.h
cipher/camellia-aarch64.S
cipher/camellia-aesni-avx-amd64.S
cipher/camellia-aesni-avx2-amd64.S
cipher/camellia-aesni-avx2-amd64.h [new file with mode: 0644]
cipher/camellia-glue.c
cipher/camellia-vaes-avx2-amd64.S [new file with mode: 0644]
cipher/cast5-amd64.S
cipher/cast5.c
cipher/chacha20-aarch64.S [new file with mode: 0644]
cipher/chacha20-amd64-avx2.S [new file with mode: 0644]
cipher/chacha20-amd64-ssse3.S [new file with mode: 0644]
cipher/chacha20-armv7-neon.S
cipher/chacha20-avx2-amd64.S [deleted file]
cipher/chacha20-ppc.c [new file with mode: 0644]
cipher/chacha20-s390x.S [new file with mode: 0644]
cipher/chacha20-sse2-amd64.S [deleted file]
cipher/chacha20-ssse3-amd64.S [deleted file]
cipher/chacha20.c
cipher/cipher-aeswrap.c
cipher/cipher-cbc.c
cipher/cipher-ccm.c
cipher/cipher-cfb.c
cipher/cipher-cmac.c
cipher/cipher-ctr.c
cipher/cipher-eax.c [new file with mode: 0644]
cipher/cipher-gcm-armv7-neon.S [new file with mode: 0644]
cipher/cipher-gcm-armv8-aarch32-ce.S
cipher/cipher-gcm-armv8-aarch64-ce.S
cipher/cipher-gcm-intel-pclmul.c
cipher/cipher-gcm-ppc.c [new file with mode: 0644]
cipher/cipher-gcm-siv.c [new file with mode: 0644]
cipher/cipher-gcm.c
cipher/cipher-internal.h
cipher/cipher-ocb.c
cipher/cipher-ofb.c
cipher/cipher-poly1305.c
cipher/cipher-selftest.c
cipher/cipher-selftest.h
cipher/cipher-siv.c [new file with mode: 0644]
cipher/cipher-xts.c
cipher/cipher.c
cipher/crc-armv8-aarch64-ce.S [new file with mode: 0644]
cipher/crc-armv8-ce.c [new file with mode: 0644]
cipher/crc-intel-pclmul.c
cipher/crc-ppc.c [new file with mode: 0644]
cipher/crc.c
cipher/des-amd64.S
cipher/des.c
cipher/dsa-common.c
cipher/dsa.c
cipher/ecc-common.h
cipher/ecc-curves.c
cipher/ecc-ecdh.c [new file with mode: 0644]
cipher/ecc-ecdsa.c
cipher/ecc-eddsa.c
cipher/ecc-gost.c
cipher/ecc-misc.c
cipher/ecc-sm2.c [new file with mode: 0644]
cipher/ecc.c
cipher/elgamal.c
cipher/gost-s-box.c
cipher/gost.h
cipher/gost28147.c
cipher/gostr3411-94.c
cipher/hash-common.c
cipher/hash-common.h
cipher/hmac-tests.c [deleted file]
cipher/idea.c
cipher/kdf-internal.h
cipher/kdf.c
cipher/keccak.c
cipher/mac-cmac.c
cipher/mac-gmac.c
cipher/mac-hmac.c
cipher/mac-internal.h
cipher/mac-poly1305.c
cipher/mac.c
cipher/md.c
cipher/md2.c [new file with mode: 0644]
cipher/md4.c
cipher/md5.c
cipher/poly1305-armv7-neon.S [deleted file]
cipher/poly1305-avx2-amd64.S [deleted file]
cipher/poly1305-internal.h
cipher/poly1305-s390x.S [new file with mode: 0644]
cipher/poly1305-sse2-amd64.S [deleted file]
cipher/poly1305.c
cipher/pubkey-internal.h
cipher/pubkey-util.c
cipher/pubkey.c
cipher/rfc2268.c
cipher/rijndael-aarch64.S
cipher/rijndael-aesni.c
cipher/rijndael-amd64.S
cipher/rijndael-armv8-aarch32-ce.S
cipher/rijndael-armv8-aarch64-ce.S
cipher/rijndael-armv8-ce.c
cipher/rijndael-gcm-p10le.s [new file with mode: 0644]
cipher/rijndael-internal.h
cipher/rijndael-p10le.c [new file with mode: 0644]
cipher/rijndael-padlock.c
cipher/rijndael-ppc-common.h [new file with mode: 0644]
cipher/rijndael-ppc-functions.h [new file with mode: 0644]
cipher/rijndael-ppc.c [new file with mode: 0644]
cipher/rijndael-ppc9le.c [new file with mode: 0644]
cipher/rijndael-s390x.c [new file with mode: 0644]
cipher/rijndael-ssse3-amd64-asm.S
cipher/rijndael-ssse3-amd64.c
cipher/rijndael-tables.h
cipher/rijndael-vaes-avx2-amd64.S [new file with mode: 0644]
cipher/rijndael-vaes.c [new file with mode: 0644]
cipher/rijndael.c
cipher/rmd160.c
cipher/rsa-common.c
cipher/rsa.c
cipher/salsa20-amd64.S
cipher/salsa20.c
cipher/scrypt.c
cipher/seed.c
cipher/serpent-avx2-amd64.S
cipher/serpent-sse2-amd64.S
cipher/serpent.c
cipher/sha1-armv7-neon.S
cipher/sha1-armv8-aarch32-ce.S
cipher/sha1-armv8-aarch64-ce.S
cipher/sha1-avx-amd64.S
cipher/sha1-avx-bmi2-amd64.S
cipher/sha1-avx2-bmi2-amd64.S [new file with mode: 0644]
cipher/sha1-intel-shaext.c [new file with mode: 0644]
cipher/sha1-ssse3-amd64.S
cipher/sha1.c
cipher/sha1.h
cipher/sha256-armv8-aarch32-ce.S
cipher/sha256-armv8-aarch64-ce.S
cipher/sha256-avx-amd64.S
cipher/sha256-avx2-bmi2-amd64.S
cipher/sha256-intel-shaext.c [new file with mode: 0644]
cipher/sha256-ppc.c [new file with mode: 0644]
cipher/sha256-ssse3-amd64.S
cipher/sha256.c
cipher/sha512-armv7-neon.S
cipher/sha512-avx-amd64.S
cipher/sha512-avx2-bmi2-amd64.S
cipher/sha512-ppc.c [new file with mode: 0644]
cipher/sha512-ssse3-amd64.S
cipher/sha512-ssse3-i386.c [new file with mode: 0644]
cipher/sha512.c
cipher/sm3-aarch64.S [new file with mode: 0644]
cipher/sm3-avx-bmi2-amd64.S [new file with mode: 0644]
cipher/sm3.c [new file with mode: 0644]
cipher/sm4-aesni-avx-amd64.S [new file with mode: 0644]
cipher/sm4-aesni-avx2-amd64.S [new file with mode: 0644]
cipher/sm4.c [new file with mode: 0644]
cipher/stribog.c
cipher/test-getrusage.c [new file with mode: 0644]
cipher/tiger.c
cipher/twofish-aarch64.S
cipher/twofish-amd64.S
cipher/twofish-avx2-amd64.S
cipher/twofish.c
cipher/whirlpool-sse2-amd64.S
cipher/whirlpool.c
compat/Makefile.in [deleted file]
compat/compat.c
config.h.in [deleted file]
configure [deleted file]
configure.ac
doc/Makefile.am
doc/Makefile.in [deleted file]
doc/Notes-wk [new file with mode: 0644]
doc/announce-1.4.txt [new file with mode: 0644]
doc/announce.txt [new file with mode: 0644]
doc/fips-fsm.eps [deleted file]
doc/fips-fsm.pdf [deleted file]
doc/fips-fsm.png [deleted file]
doc/gcrypt.info [deleted file]
doc/gcrypt.info-1 [deleted file]
doc/gcrypt.info-2 [deleted file]
doc/gcrypt.texi
doc/libgcrypt-modules.eps [deleted file]
doc/libgcrypt-modules.pdf [deleted file]
doc/libgcrypt-modules.png [deleted file]
doc/stamp-vti [deleted file]
doc/version.texi [deleted file]
libgcrypt.txt [new file with mode: 0644]
m4/Makefile.am
m4/Makefile.in [deleted file]
m4/ax_cc_for_build.m4 [new file with mode: 0644]
m4/gpg-error.m4
m4/libtool.m4
m4/noexecstack.m4
m4/onceonly.m4 [deleted file]
m4/socklen.m4
m4/sys_socket_h.m4 [deleted file]
mpi/Makefile.am
mpi/Makefile.in [deleted file]
mpi/aarch64/mpih-add1.S
mpi/aarch64/mpih-mul1.S
mpi/aarch64/mpih-mul2.S
mpi/aarch64/mpih-mul3.S
mpi/aarch64/mpih-sub1.S
mpi/amd64/func_abi.h
mpi/amd64/mpih-add1.S
mpi/amd64/mpih-lshift.S
mpi/amd64/mpih-mul1.S
mpi/amd64/mpih-mul2.S
mpi/amd64/mpih-mul3.S
mpi/amd64/mpih-rshift.S
mpi/amd64/mpih-sub1.S
mpi/asm-common-aarch64.h [new file with mode: 0644]
mpi/asm-common-amd64.h [new file with mode: 0644]
mpi/config.links
mpi/ec-hw-s390x.c [new file with mode: 0644]
mpi/ec-inline.h [new file with mode: 0644]
mpi/ec-internal.h
mpi/ec-nist.c [new file with mode: 0644]
mpi/ec.c
mpi/i386/mpih-add1.S
mpi/i386/mpih-lshift.S
mpi/i386/mpih-mul1.S
mpi/i386/mpih-mul2.S
mpi/i386/mpih-mul3.S
mpi/i386/mpih-rshift.S
mpi/i386/mpih-sub1.S
mpi/i386/syntax.h
mpi/i586/README [deleted file]
mpi/i586/distfiles [deleted file]
mpi/i586/mpih-add1.S [deleted file]
mpi/i586/mpih-lshift.S [deleted file]
mpi/i586/mpih-mul1.S [deleted file]
mpi/i586/mpih-mul2.S [deleted file]
mpi/i586/mpih-mul3.S [deleted file]
mpi/i586/mpih-rshift.S [deleted file]
mpi/i586/mpih-sub1.S [deleted file]
mpi/longlong.h
mpi/mpi-add.c
mpi/mpi-cmp.c
mpi/mpi-div.c
mpi/mpi-internal.h
mpi/mpi-inv.c
mpi/mpicoder.c
mpi/mpih-const-time.c [new file with mode: 0644]
mpi/mpiutil.c
mpi/pentium4/README [deleted file]
mpi/pentium4/distfiles [deleted file]
mpi/pentium4/mmx/distfiles [deleted file]
mpi/pentium4/mmx/mpih-lshift.S [deleted file]
mpi/pentium4/mmx/mpih-rshift.S [deleted file]
mpi/pentium4/sse2/distfiles [deleted file]
mpi/pentium4/sse2/mpih-add1.S [deleted file]
mpi/pentium4/sse2/mpih-mul1.S [deleted file]
mpi/pentium4/sse2/mpih-mul2.S [deleted file]
mpi/pentium4/sse2/mpih-mul3.S [deleted file]
mpi/pentium4/sse2/mpih-sub1.S [deleted file]
random/Makefile.am
random/Makefile.in [deleted file]
random/jitterentropy-base-user.h
random/jitterentropy-base.c
random/jitterentropy-base.h [new file with mode: 0644]
random/jitterentropy-gcd.c [new file with mode: 0644]
random/jitterentropy-gcd.h [new file with mode: 0644]
random/jitterentropy-health.c [new file with mode: 0644]
random/jitterentropy-health.h [new file with mode: 0644]
random/jitterentropy-noise.c [new file with mode: 0644]
random/jitterentropy-noise.h [new file with mode: 0644]
random/jitterentropy-sha3.c [new file with mode: 0644]
random/jitterentropy-sha3.h [new file with mode: 0644]
random/jitterentropy-timer.c [new file with mode: 0644]
random/jitterentropy-timer.h [new file with mode: 0644]
random/jitterentropy.h
random/rand-internal.h
random/random-csprng.c
random/random-daemon.c [deleted file]
random/random-drbg.c
random/random-system.c
random/random.c
random/random.h
random/rndgetentropy.c [new file with mode: 0644]
random/rndhw.c
random/rndjent.c
random/rndoldlinux.c [moved from random/rndlinux.c with 73% similarity]
random/rndunix.c
random/rndw32.c
random/rndw32ce.c
src/Makefile.am
src/Makefile.in [deleted file]
src/cipher-proto.h
src/cipher.h
src/context.c
src/context.h
src/dumpsexp.c
src/ec-context.h
src/fips.c
src/g10lib.h
src/gcrypt-int.h
src/gcrypt.h.in
src/gen-note-integrity.sh [new file with mode: 0755]
src/global.c
src/hmac256.c
src/hwf-arm.c
src/hwf-common.h
src/hwf-ppc.c [new file with mode: 0644]
src/hwf-s390x.c [new file with mode: 0644]
src/hwf-x86.c
src/hwfeatures.c
src/libgcrypt-config.in
src/libgcrypt.def
src/libgcrypt.m4
src/libgcrypt.pc.in [new file with mode: 0644]
src/libgcrypt.vers
src/misc.c
src/mpi.h
src/mpicalc.c
src/secmem.c
src/sexp.c
src/stdmem.c
src/types.h
src/versioninfo.rc.in
src/visibility.c
src/visibility.h
stamp-h.in [new file with mode: 0644]
tests/Makefile.am
tests/Makefile.in [deleted file]
tests/aeswrap.c
tests/basic.c
tests/basic_all_hwfeature_combinations.sh
tests/bench-slope.c
tests/benchmark.c
tests/cavs_driver.pl [deleted file]
tests/cavs_tests.sh [deleted file]
tests/curves.c
tests/dsa-rfc6979.c
tests/fips186-dsa.c
tests/fipsdrv.c
tests/fipsrngdrv.c [new file with mode: 0644]
tests/gchash.c
tests/hashtest-256g.in
tests/hashtest.c
tests/hmac.c
tests/keygen.c
tests/keygrip.c
tests/mpitests.c
tests/pkbench.c
tests/pkcs1v2.c
tests/pkcstv2c.awk [new file with mode: 0755]
tests/prime.c
tests/pubkey.c
tests/random.c
tests/rsacvt.c
tests/t-common.h
tests/t-convert.c
tests/t-cv25519.c
tests/t-dsa.c [new file with mode: 0644]
tests/t-dsa.inp [new file with mode: 0644]
tests/t-ecdsa.c [new file with mode: 0644]
tests/t-ecdsa.inp [new file with mode: 0644]
tests/t-ed25519.c
tests/t-ed448.c [new file with mode: 0644]
tests/t-ed448.inp [new file with mode: 0644]
tests/t-kdf.c
tests/t-lock.c
tests/t-mpi-bit.c
tests/t-mpi-point.c
tests/t-rsa-15.c [new file with mode: 0644]
tests/t-rsa-15.inp [new file with mode: 0644]
tests/t-rsa-pss.c [new file with mode: 0644]
tests/t-rsa-pss.inp [new file with mode: 0644]
tests/t-secmem.c
tests/t-sexp.c
tests/t-x448.c [new file with mode: 0644]
tests/testapi.c
tests/testdrv.c [new file with mode: 0644]
tests/version.c

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..99741c1
--- /dev/null
@@ -0,0 +1,113 @@
+*.lo
+*.o
+.deps/
+.libs/
+po/*.gmo
+po/messages.mo
+/aclocal.m4
+/autom4te.cache
+/config.h.in
+/config.h
+/config.log
+/config.status
+/configure
+/libtool
+/stamp-h1
+/Makefile.in
+/VERSION
+cipher/Makefile.in
+cipher/gost-s-box
+cipher/gost-sb.h
+compat/Makefile.in
+doc/Makefile.in
+m4/Makefile.in
+mpi/Makefile.in
+random/Makefile.in
+src/Makefile.in
+tests/Makefile.in
+/Makefile
+m4/Makefile
+cipher/Makefile
+cipher/libcipher.la
+compat/Makefile
+compat/libcompat.la
+doc/gcrypt.info
+doc/gcrypt.info-1
+doc/gcrypt.info-2
+doc/stamp-vti
+doc/version.texi
+doc/Makefile
+doc/fips-fsm.eps
+doc/fips-fsm.pdf
+doc/fips-fsm.png
+doc/hmac256.1
+doc/libgcrypt-modules.eps
+doc/libgcrypt-modules.pdf
+doc/libgcrypt-modules.png
+doc/yat2m
+doc/yat2m-stamp
+mpi/Makefile
+mpi/asm-syntax.h
+mpi/libmpi.la
+mpi/mod-source-info.h
+mpi/mpi-asm-defs.h
+mpi/mpih-add1-asm.S
+mpi/mpih-lshift-asm.S
+mpi/mpih-mul1-asm.S
+mpi/mpih-mul2-asm.S
+mpi/mpih-mul3-asm.S
+mpi/mpih-rshift-asm.S
+mpi/mpih-sub1-asm.S
+mpi/sysdep.h
+random/Makefile
+random/librandom.la
+src/Makefile
+src/dumpsexp
+src/gcrypt.h
+src/hmac256
+src/libgcrypt-config
+src/libgcrypt.la
+src/libgcrypt.pc
+src/mpicalc
+src/versioninfo.rc
+src/*.exe
+tests/Makefile
+tests/ac
+tests/ac-data
+tests/ac-schemes
+tests/aeswrap
+tests/basic
+tests/basic-disable-all-hwf
+tests/bench-slope
+tests/benchmark
+tests/curves
+tests/dsa-rfc6979
+tests/fips186-dsa
+tests/fipsdrv
+tests/gchash
+tests/genhashdata
+tests/hashtest
+tests/hashtest-256g
+tests/hmac
+tests/keygen
+tests/keygrip
+tests/mpitests
+tests/pkcs1v2
+tests/prime
+tests/pubkey
+tests/random
+tests/register
+tests/rsacvt
+tests/t-convert
+tests/t-cv25519
+tests/t-ed25519
+tests/t-kdf
+tests/t-lock
+tests/t-mpi-bit
+tests/t-mpi-point
+tests/t-sexp
+tests/t-secmem
+tests/t-x448
+tests/tsexp
+tests/version
+tests/*.exe
diff --git a/.mailmap b/.mailmap
new file mode 100644 (file)
index 0000000..6d3f947
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1 @@
+Dmitry Baryshkov <dbaryshkov@gmail.com>
diff --git a/AUTHORS b/AUTHORS
index ab7a525..80c501a 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -6,6 +6,7 @@ Repository: git://git.gnupg.org/libgcrypt.git
 Maintainer: Werner Koch <wk@gnupg.org>
 Bug reports: https://bugs.gnupg.org
 Security related bug reports: <security@gnupg.org>
+End-of-life: TBD
 License (library): LGPLv2.1+
 License (manual and tools): GPLv2+
 
@@ -29,15 +30,19 @@ List of Copyright holders
   Copyright (C) 1996-1999 Peter Gutmann, Paul Kendall, and Chris Wedgwood
   Copyright (C) 1996-2006 Peter Gutmann, Matt Thomlinson and Blake Coverett
   Copyright (C) 2003 Nikos Mavroyanopoulos
+  Copyright (c) 2006 CRYPTOGAMS
   Copyright (C) 2006-2007 NTT (Nippon Telegraph and Telephone Corporation)
-  Copyright (C) 2012-2018 g10 Code GmbH
+  Copyright (C) 2012-2022 g10 Code GmbH
   Copyright (C) 2012 Simon Josefsson, Niels Möller
   Copyright (c) 2012 Intel Corporation
   Copyright (C) 2013 Christian Grothoff
-  Copyright (C) 2013-2017 Jussi Kivilinna
+  Copyright (C) 2013-2022 Jussi Kivilinna
   Copyright (C) 2013-2014 Dmitry Eremin-Solenikov
   Copyright (C) 2014 Stephan Mueller
-  Copyright (C) 2017 Bundesamt für Sicherheit in der Informationstechnik
+  Copyright (C) 2017 Jia Zhang
+  Copyright (C) 2018 Bundesamt für Sicherheit in der Informationstechnik
+  Copyright (C) 2020 Alibaba Group.
+  Copyright (C) 2020 Tianjia Zhang
 
 
 Authors with a FSF copyright assignment
@@ -151,12 +156,25 @@ Christian Aistleitner <christian@quelltextlich.at>
 Christian Grothoff <christian@grothoff.org>
 2013-03-21:514B5D8A.6040705@grothoff.org:
 
+Clemens Lang <cllang@redhat.com>
+2022-02-10:20220210133844.46581-1-cllang@redhat.com:
+
+Danny Tsen <dtsen@us.ibm.com>
+2021-12-20:OF85D11C2F.7A339D7D-ON002587B1.0042A81E-002587B1.0042B94D@ibm.com
+
+Dmitry Baryshkov <dbaryshkov@gmail.com>
 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 2013-07-13:20130713144407.GA27334@fangorn.rup.mentorg.com:
 
 Dmitry Kasatkin <dmitry.kasatkin@intel.com>
 2012-12-14:50CAE2DB.80302@intel.com:
 
+H.J. Lu <hjl.tools@gmail.com>
+2020-01-19:20200119135241.GA4970@gmail.com:
+
+Jia Zhang <qianyue.zj@alibaba-inc.com>
+2017-10-17:59E56E30.9060503@alibaba-inc.com:
+
 Jérémie Courrèges-Anglas <jca@wxcvbn.org>
 2016-05-26:87bn3ssqg0.fsf@ritchie.wxcvbn.org:
 
@@ -169,12 +187,18 @@ Jussi Kivilinna <jussi.kivilinna@iki.fi>
 Markus Teich <markus dot teich at stusta dot mhn dot de>
 2014-10-08:20141008180509.GA2770@trolle:
 
+Martin Storsjö <martin@martin.st>
+2018-03-28:dc1605ce-a47d-34c5-8851-d9569f9ea5d3@martin.st:
+
 Mathias L. Baumann <mathias.baumann at sociomantic.com>
 2017-01-30:07c06d79-0828-b564-d604-fd16c7c86ebe@sociomantic.com:
 
 Milan Broz <gmazyland@gmail.com>
 2014-01-13:52D44CC6.4050707@gmail.com:
 
+Paul Wolneykien <manowar@altlinux.org>
+2019-11-19:20191119204459.312927aa@rigel.localdomain:
+
 Peter Wu <peter@lekensteyn.nl>
 2015-07-22:20150722191325.GA8113@al:
 
@@ -184,9 +208,15 @@ Rafaël Carré <funman@videolan.org>
 Sergey V. <sftp.mtuci@gmail.com>
 2013-11-07:2066221.5IYa7Yq760@darkstar:
 
+Shawn Landden <shawn@git.icu>
+2019-07-09:2794651562684255@iva4-64850291ca1c.qloud-c.yandex.net:
+
 Stephan Mueller <smueller@chronox.de>
 2014-08-22:2008899.25OeoelVVA@myon.chronox.de:
 
+Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
+2020-01-08:dcda0127-2f45-93a3-0736-27259a33bffa@linux.alibaba.com:
+
 Tomáš Mráz <tm@t8m.info>
 2012-04-16:1334571250.5056.52.camel@vespa.frost.loc:
 
index 46e94ec..555340b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
-2018-10-26  Werner Koch  <wk@gnupg.org>
+No more ChangeLog files
+========================
 
-       Release 1.8.4.
-       + commit 93775172713c00c363187b5d6a88895b04ac7c8e
+Do not modify any of the ChangeLog files in Libgcrypt.  Starting on
+December 1st, 2011 we put change information only in the GIT commit
+log, and generate a top-level ChangeLog file from logs at "make dist"
+time.  As such, there are strict requirements on the form of the
+commit log messages.  See doc/HACKING for details.  The old ChangeLog
+files have all be renamed to ChangeLog-2011.
 
 
-2018-10-26  Daniel Kahn Gillmor  <dkg@fifthhorseman.net>
 
-       random: use getrandom() on Linux where available.
-       + commit 0973c3f9ee7a9ad7c97b77849ed33ecd6789c787
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): use the
-       getrandom() syscall on Linux if it exists, regardless of what kind of
-       entropy was requested.
-
-2018-10-26  Werner Koch  <wk@gnupg.org>
-
-       random: Make sure to re-open /dev/random after a fork.
-       + commit 60885655756dd0427872b8f01c06da14eab5af70
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Detect fork and
-       re-open devices.
-
-       primes: Avoid leaking bits of the prime test to pageable memory.
-       + commit 5b1d022293c5779b1150a7653cce4e3bf494a07c
-       * cipher/primegen.c (gen_prime): Allocate MODS in secure memory.
-
-2018-10-24  Werner Koch  <wk@gnupg.org>
-
-       build: Add release make target.
-       + commit 99a5babfd1e759310db8ab8b11d182f2e139dfb1
-       * Makefile.am (release, sign-release): New targets.
-
-       (cherry picked from commit 03bb25ee7ed6f1076bf788ab981ca68672880daa)
-
-       Fix memory leak in secmem in out of core conditions.
-       + commit abd267bf239345ceae5c0de239d1530b427a53a1
-       * src/secmem.c (_gcry_secmem_malloc_internal): Release pool descriptor
-       if the pool could not be allocated.
-
-       ecc: Fix memory leak in the error case of ecc_encrypt_raw.
-       + commit 60224352f4de1189e0076c6172886dc787a1e6e6
-       * cipher/ecc.c (ecc_encrypt_raw): Add proper error cleanup in the main
-       block.
-
-       ecc: Fix possible memory leakage in parameter check of eddsa.
-       + commit 347987d4cf29b6a611b7fafa14fddeb50c0651d2
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_verify): Fix mem leak.
-
-       ecc: Fix potential unintended freeing of an internal param.
-       + commit be68b3ee4fd1f85edc95eaad11c8fd52ccd27ccd
-       * cipher/ecc-curves.c (_gcry_ecc_get_mpi): Fix c+p error
-
-       sexp: Fix uninitialized use of a var in the error case.
-       + commit 8cc7cac82ec2087c3e1ece56dbd12855a383f090
-       * src/sexp.c (_gcry_sexp_vextract_param): Initialize L1.
-
-2018-06-19  Will Dietz  <w@wdtz.org>
-
-       random: Fix hang of _gcry_rndjent_get_version.
-       + commit 20c034865f2dd15ce2871385b6e29c15d1570539
-       * random/rndjent.c (_gcry_rndjent_get_version): Move locking.
-
-2018-06-13  Werner Koch  <wk@gnupg.org>
-
-       Release 1.8.3.
-       + commit 5600d2d6b23640b0114655214f18959ee81fe58e
-
-
-2018-06-13  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Add blinding for ECDSA.
-       + commit 9be06c6b2e5c96edf40e566bbf51d44c4d46fb07
-       * cipher/ecc-ecdsa.c (_gcry_ecc_ecdsa_sign): Blind secret D with
-       randomized nonce B.
-
-2018-06-11  Werner Koch  <wk@gnupg.org>
-
-       ecc: Improve gcry_mpi_ec_curve_point.
-       + commit 846f8fe8b3be6d235592db184361df1bc2b07a8a
-       * mpi/ec.c (_gcry_mpi_ec_curve_point): Check range of coordinates.
-       * tests/t-mpi-point.c (point_on_curve): New.
-
-       mpi: New internal function _gcry_mpi_cmpabs.
-       + commit 54620a27f4503e703e219e6e11c4be14ce4e3d35
-       * mpi/mpi-cmp.c (_gcry_mpi_cmp): Factor out to ...
-       (do_mpi_cmp): New.  Add arg absmode.
-       (_gcry_mpi_cmpabs): New.
-       * src/gcrypt-int.h (mpi_cmpabs): New macro.
-
-       (cherry picked from commit 6606ae44e0de1069b29dd4215ee9748280940e1b)
-
-2018-04-29  Werner Koch  <wk@gnupg.org>
-
-       build: Convince gcc not to delete NULL ptr checks.
-       + commit 1a0289daa408773e1a6cefb2562288245f49651c
-       * configure.ac: Try to use -fno-delete-null-pointer-checks.
-
-       (cherry picked from commit 61dbb7c08ab11c10060e193b52e3e1d2ec6dd062)
-
-       prime: Avoid rare assertion failure in gcry_prime_check.
-       + commit c5bed9df96337b1553cdcd4a85eec10e78b4d14a
-       * cipher/primegen.c (is_prime): Don't fail on the assert X > 1.
-
-2018-04-17  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Make BMI2 inline assembly check more robust.
-       + commit 22db6237de00cafb85c0112073b55d0d750e6b03
-       * configure.ac (gcry_cv_gcc_inline_asm_bmi2): New assembly test.
-
-2018-04-17  Stephan Mueller  <smueller@chronox.de>
-
-       AES-KW: fix in-place encryption.
-       + commit bbf88f0e9d481486ceca079e2611e84db8d039c7
-       * cipher/cipher-aeswrap.c: move memmove call before KW IV setting
-
-2018-04-17  Werner Koch  <wk@gnupg.org>
-
-       mpi: Fix for buidling for MIPS64 with Clang.
-       + commit a0e016e29409ccd78966a5eb82dea236ad44d9c9
-       * mpi/longlong.h [MIPS64][__clang__]: Use the C version like we
-       already do for 32 bit MIPS.
-
-2018-04-17  NIIBE Yutaka  <gniibe@fsij.org>
-
-       hmac: Use xtrymalloc.
-       + commit 06fdc074eb29faf584ffd13feea4c063936446fb
-       * src/hmac256.c (_gcry_hmac256_new): Use xtrymalloc.
-       (_gcry_hmac256_file): Likewise.
-
-       random: Protect another use of jent_rng_collector.
-       + commit 0da4a237661cd273303ae6baaaba2d9f6292b990
-       * random/rndjent.c (_gcry_rndjent_get_version): Lock the access.
-
-       (cherry picked from commit 0de2a22fcf6607d0aecb550feefa414cee3731b2)
-
-2018-04-17  Martin Storsjö  <martin@martin.st>
-
-       random: Don't assume that _WIN64 implies x86_64.
-       + commit e1695a8f6ca1135d777450cf9ce64628b0778ccb
-       * random/rndw32.c: Change _WIN64 ifdef into __x86_64__.
-
-2018-04-17  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Improve constant-time buffer compare.
-       + commit 4e11e9d988181cf9cd87c7c86fa8e7a0f643a573
-       * cipher/bufhelp.h (buf_eq_const): Rewrite logic.
-
-       Fix incorrect counter overflow handling for GCM.
-       + commit 0a391b259adcd7ea734dc03c2048a135e018166d
-       * cipher/cipher-gcm.c (gcm_ctr_encrypt): New function to handle
-       32-bit CTR increment for GCM.
-       (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt): Do not use
-       generic CTR implementation directly, use gcm_ctr_encrypt instead.
-       * tests/basic.c (_check_gcm_cipher): Add test-vectors for 32-bit
-       CTR overflow.
-       (check_gcm_cipher): Add 'split input to 15 bytes and 17 bytes'
-       test-runs.
-
-       doc: fix double "See" in front of reference.
-       + commit c114ffd6da837e7aace318e37bbcf9325dd985b7
-       * doc/gcrypt.texi: Change @xref to @ref when text already has 'see' in
-       the front.
-
-2017-12-13  Werner Koch  <wk@gnupg.org>
-
-       Release 1.8.2.
-       + commit eb84e429950b6a61c00112e70a584940c1d352e4
-
-
-2017-11-24  Werner Koch  <wk@gnupg.org>
-
-       sexp: Avoid a fatal error in case of ENOMEM in called functions.
-       + commit 59df8d6295426d0a9cf7646c381df2ea29fdb8c5
-       * src/sexp.c (do_vsexp_sscan): Replace BUG() by a proper error
-       return.  Replace sprintf by snprintf.
-       (convert_to_hex): Replace sprintf by snprintf.
-       (convert_to_string): Ditto.
-       (_gcry_sexp_sprint): Ditto.
-
-2017-11-23  Werner Koch  <wk@gnupg.org>
-
-       api: Add auto expand secmem feature.
-       + commit f4582f8c429f22b18f8ca8a40660a91d721f5c96
-       * src/global.c (_gcry_vcontrol): Implement control value 78.
-       * src/secmem.c (auto_expand): New var.
-       (_gcry_secmem_set_auto_expand): New.
-       (_gcry_secmem_malloc_internal): Act upon AUTO_EXPAND.
-
-2017-11-14  NIIBE Yutaka  <gniibe@fsij.org>
-
-       tests: Add HAVE_MMAP check for MinGW.
-       + commit 334e1a1cfc8f59db765a0bff0ca29090aa11b0f6
-       * tests/t-secmem.c (main): Conditionalize with HAVE_MMAP.
-
-2017-11-09  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Fix secmem test for machine with larger page.
-       + commit da127f7505ff7681fc9dbfbf332121d2998e88aa
-       * tests/t-secmem.c (main): Detect page size and setup chunk size.
-       * src/secmem.c (init_pool): Simplify the expression.
-
-2017-08-27  Werner Koch  <wk@gnupg.org>
-
-       Release 1.8.1.
-       + commit 80fd8615048c3897b91a315cca22ab139b056ccd
-       * configure.ac: Set LT version to C22/A2/R1.
-
-2017-08-27  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Add input validation for X25519.
-       + commit bf76acbf0da6b0f245e491bec12c0f0a1b5be7c9
-       * cipher/ecc.c (ecc_decrypt_raw): Add input validation.
-       * mpi/ec.c (ec_p_init): Use scratch buffer for bad points.
-       (_gcry_mpi_ec_bad_point): New.
-
-2017-08-07  Marcus Brinkmann  <marcus.brinkmann@ruhr-uni-bochum.de>
-
-       cipher: Add OID for SHA384WithECDSA.
-       + commit a7bd2cbd3eabda88fb3cac5cbc13c21c97a7b315
-       * cipher/sha512.c (oid_spec_sha384): Add SHA384WithECDSA.
-
-2017-08-02  Werner Koch  <wk@gnupg.org>
-
-       tests: Fix a printf glitch for a Windows test.
-       + commit df1e221b3012e96bbffbc7d5fd70836a9ae1cc19
-       * tests/t-convert.c (check_formats): Fix print format glitch on
-       Windows.
-       * tests/t-ed25519.c: Typo fix.
-
-       tests: Add benchmarking option to tests/random.
-       + commit 21d0f068a721c022f955084c28304934fd198c5e
-       * tests/random.c: Always include unistd.h.
-       (prepend_srcdir): New.
-       (run_benchmark): New.
-       (main): Add options --benchmark and --with-seed-file.  Print whetehr
-       JENT has been used.
-       * tests/t-common.h (split_fields_colon): New. Taken from GnuPG.
-       License of that code changed to LGPLv2.1.
-
-       random: Add more bytes to the pool in addition to the seed file.
-       + commit eea36574f37830a6a80b4fad884825e815b2912f
-       * random/random-csprng.c (read_seed_file): Read 128 or 32 butes
-       depending on whether we have the Jitter RNG.
-
-2017-08-01  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add script to run basic tests with all supported HWF combinations.
-       + commit 94a92a3db909aef0ebcc009c2d7f5a2663e99004
-       * tests/basic_all_hwfeature_combinations.sh: New.
-       * tests/Makefile.am: Add basic_all_hwfeature_combinations.sh.
-
-2017-07-29  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix return value type for _gcry_md_extract.
-       + commit cf1528e7f2761774d06ace0de48f39c96b52dc4f
-       * src/gcrypt-int.h (_gcry_md_extract): Use gpg_err_code_t instead of
-       gpg_error_t for internal function return type.
-
-       Fix building AArch32 CE implementations when target is ARMv6 arch.
-       + commit 4a7aa30ae9f3ce798dd886c2f2d4164c43027748
-       * cipher/cipher-gcm-armv8-aarch32-ce.S: Select ARMv8 architecure.
-       * cipher/rijndael-armv8-aarch32-ce.S: Ditto.
-       * cipher/sha1-armv8-aarch32-ce.S: Ditto.
-       * cipher/sha256-armv8-aarch32-ce.S: Ditto.
-       * configure.ac (gcry_cv_gcc_inline_asm_aarch32_crypto): Ditto.
-
-2017-07-25  NIIBE Yutaka  <gniibe@fsij.org>
-
-       sexp: Add fall through annotation.
-       + commit b7cd44335d9cde43be6f693dca6399ed0762649c
-       * src/dumpsexp.c (parse_and_print): It's fall through.
-
-2017-07-24  Werner Koch  <wk@gnupg.org>
-
-       random: Fix the command line munging for jitterbase.
-       + commit ac39522ab08fcd2483edc223334c6ab9d19e91f3
-       * random/Makefile.am (o_flag_munging): Make the first sed term also
-       global.
-
-2017-07-19  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Remove byte order mark.
-       + commit 1d8e4c2c3a7d0a4154caf5bd720a9a0b04179390
-       * random/jitterentropy-base.c, random/jitterentropy.h: Remove
-       byte order mark.
-
-2017-07-18  Werner Koch  <wk@gnupg.org>
-
-       Release 1.8.0.
-       + commit 850aca744eeda5fd410f478a0778e353045ac962
-
-
-       mac: Add selftests for HMAC-SHA3-xxx.
-       + commit 95194c550443e8d5558856633f920daec8a975c4
-       * cipher/hmac-tests.c (check_one): Add arg trunc and change all
-       callers to pass false.
-       (selftests_sha3): New.
-       (run_selftests): Call new selftests.
-
-       api: New function gcry_mpi_point_copy.
-       + commit ecf73dafb7aafed0d0f339d07235b58c2113f94c
-       * src/gcrypt.h.in (gcry_mpi_point_copy): New.
-       (mpi_point_copy): New macro.
-       * src/visibility.c (gcry_mpi_point_copy): New.
-       * src/libgcrypt.def, src/libgcrypt.vers: Add function.
-       * mpi/ec.c (_gcry_mpi_point_copy): New.
-       * tests/t-mpi-point.c (set_get_point): Add test.
-
-2017-07-17  Werner Koch  <wk@gnupg.org>
-
-       random: Minor fix for getting the rndjent version.
-       + commit 9d99c6b973caa7fdf93b53cf764066214f763803
-       * random/rndjent.c (_gcry_rndjent_get_version): Always set R_ACTIVE.
-       * tests/version.c (test_get_config): Check number of fields for
-       rng-type.
-
-2017-07-07  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: Minor fix of mpi_pow.
-       + commit 61b0f52c1cc85bf8c3cac9aba40e28682e4e1b8b
-       * mpi/mpi-pow.c (_gcry_mpi_powm): Allocate size fix.
-
-       mpi: Fix mpi_pow alternative implementation.
-       + commit 66ed4d53789892def7b237756d8a0ab28df9d222
-       * mpi/mpi-pow.c
-         [USE_ALGORITHM_SIMPLE_EXPONENTIATION] (_gcry_mpi_powm): Use
-         mpi_set_cond.
-
-       Fix mpi_pow alternative implementation.
-       + commit 619ebae9847831f43314a95cc3180f4b329b4d3b
-       * mpi/mpi-pow.c [USE_ALGORITHM_SIMPLE_EXPONENTIATION] (_gcry_mpi_powm):
-       Allocate size fix.
-
-2017-07-06  Werner Koch  <wk@gnupg.org>
-
-       rsa: Use modern MPI allocation function.
-       + commit 208aba6f9a0475ba049f5a66fe02cf9a6214a887
-       * cipher/rsa.c (secret_core_crt): Use modern function _gcry_mpi_snew.
-
-2017-07-05  Werner Koch  <wk@gnupg.org>
-
-       build: Minor API fixes to fix build problems on AIX.
-       + commit 85a9a913da9ecc6b2cd6f743e90e49983251d706
-       * src/gcrypt.h.in (gcry_error_from_errno): Fix return type.
-       * src/visibility.c (gcry_md_extract): Change return type to match the
-       prototype.
-
-       tools: Add left shift to mpicalc.
-       + commit 0d30a4a9791d20c8881b5b12bd44611d9f4274cd
-       * src/mpicalc.c (do_lshift): New.
-       (main): Handle '<'.
-
-2017-07-04  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: Fix mpi_set_secure.
-       + commit 5feaf1cc8f22c1f8d19a34850d86fe190f1432e2
-       * mpi/mpiutil.c (mpi_set_secure): Allocate by ->alloced.
-
-2017-06-29  NIIBE Yutaka  <gniibe@fsij.org>
-           Werner Koch  <wk@gnupg.org>
-
-       rsa: Add exponent blinding.
-       + commit 8725c99ffa41778f382ca97233183bcd687bb0ce
-       * cipher/rsa.c (secret_core_crt): Blind secret D with randomized
-       nonce R for mpi_powm computation.
-
-2017-06-28  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Same computation for square and multiply.
-       + commit 78130828e9a140a9de4dafadbc844dbb64cb709a
-       * mpi/mpi-pow.c (_gcry_mpi_powm): Compare msize for max_u_size.  Move
-       the assignment to base_u into the loop.  Copy content refered by RP to
-       BASE_U except the last of the loop.
-
-2017-06-24  Werner Koch  <wk@gnupg.org>
-
-       rsa: Minor refactoring.
-       + commit e6a3dc9900433bbc8ad362a595a3837318c28fa9
-       * cipher/rsa.c (secret): Factor code out to ...
-       (secret_core_std, secret_core_crt): new functions.
-
-2017-06-23  Werner Koch  <wk@gnupg.org>
-
-       random: Add missing dependency.
-       + commit d091610377b2c92cf385282b1adfc30fa6cd5c75
-       * random/Makefile.am (EXTRA_librandom_la_SOURCES): Fix file name.
-       (rndjent.o, rndjent.lo): Depend on jitterentropy-base-user.h.
-
-       random: Update jitterentropy to 2.1.0.
-       + commit 8dfae89ecd3e9ae0967586cb38d12ef9111fc7cd
-       * random/rndjent.c (jent_get_nstime, jent_zfree)
-       (jent_fips_enabled, jent_zalloc): Move functions and macros to ...
-       * random/jitterentropy-base-user.h: this file.   That files was not
-       used before.
-       * random/Makefile.am (EXTRA_librandom_la_SOURCES): Add
-       jitterentropy-base-user.
-       * random/jitterentropy-base.c: Update to version 2.1.0.
-       * random/jitterentropy.h: Ditto.
-
-2017-06-21  Werner Koch  <wk@gnupg.org>
-
-       api: New function gcry_get_config.
-       + commit 27148e60ba15b0cb73b47a75c688fcb48a1a3444
-       * src/misc.c (_gcry_log_info_with_dummy_fp): Remove.
-       * src/global.c (print_config): New arg WHAT.  Remove arg FNC and use
-       gpgrt_fprintf directly.
-       (_gcry_get_config): New.
-       (_gcry_vcontrol) <GCRYCTL_PRINT_CONFIG>: Use _gcry_get_config instead
-       of print_config.
-       * src/gcrypt.h.in (gcry_get_config): New.
-       * src/libgcrypt.def, src/libgcrypt.vers: Add new function.
-       * src/visibility.c (gcry_get_config): New.
-       * src/visibility.h: Mark new function.
-
-       * tests/version.c (test_get_config): New.
-       (main): Call new test.
-
-       random: Allow building rndjent on non-x86.
-       + commit c2319464b03e61aaf34ef6d5f4b59b0c0483a373
-       * random/jitterentropy-base.c (jent_version): Uncomment function.
-       * random/rndjent.c: Include time.h
-       (JENT_USES_RDTSC): New.
-       (JENT_USES_GETTIME): New.
-       (JENT_USES_READ_REAL_TIME): New.
-       (jent_get_nstime): Support clock_gettime and AIX specific
-       function.  Taken from Stephan Müller's code.
-       (is_rng_available): New.
-       (_gcry_rndjent_dump_stats): Use that function.
-       (_gcry_rndjent_poll): Use that fucntion.  Allow an ADD of NULL for an
-       intialize only mode.
-       (_gcry_rndjent_get_version): New.
-
-2017-06-18  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael-padlock: change asm operands from read-only to read/write.
-       + commit 32b4ab209067f6f08b87b27bc78ec27dc497b708
-       * cipher/rijndael-padlock.c (do_padlock): Change ESI/EDI/ECX to use
-       read/write operands as XCRYPT instruction modifies these registers.
-
-2017-06-16  Werner Koch  <wk@gnupg.org>
-
-       random: Make rndjent.c NTG.1 compliant.
-       + commit 82bc052eda5b3897724c7ad11e54f8203e8e88e9
-       * random/rndjent.c (_gcry_rndjent_poll): Hash the retrieved jitter.
-
-       md: Optimize gcry_md_hash_buffers for SHA-256 and SHA-512.
-       + commit e6f90a392a1fd59b19b16f7a2bc7c439ae369d5f
-       * cipher/sha256.c (_gcry_sha256_hash_buffer): New.
-       (_gcry_sha256_hash_buffers): New.
-       * cipher/sha512.c (_gcry_sha512_hash_buffer): New.
-       (_gcry_sha512_hash_buffers): New.
-       * cipher/md.c (_gcry_md_hash_buffer): Optimize for SHA246 and SHA512.
-       (_gcry_md_hash_buffers): Ditto.
-
-       random: Allow building rndjent.c with stats collecting enabled.
-       + commit ee3a74f5539cbc5182ce089994e37c16ce612149
-       * random/rndjent.c: Change license to the one used by jitterentropy.h.
-       (jent_init_statistic): New.
-       (jent_bit_count): New.
-       (jent_statistic_copy_stat): new.
-       (jent_calc_statistic): New.
-
-       New global config option "only-urandom".
-       + commit 8f6082e95f30c1ba68d2de23da90146f87f0c66c
-       * random/rand-internal.h (RANDOM_CONF_ONLY_URANDOM): New.
-       * random/random.c (_gcry_random_read_conf): Add option "only-urandom".
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Implement that
-       option.
-       * tests/keygen.c (main): Add option --no-quick for better manual
-       tests.
-
-       Implement global config file /etc/gcrypt/random.conf.
-       + commit b05a4abc358b204dba343d9cfbd59fdc828c1686
-       * src/hwfeatures.c (my_isascii): Move macro to ...
-       * src/g10lib.h: here.
-       * tests/random.c (main): Dump random stats.
-       * random/random.c (RANDOM_CONF_FILE): New.
-       (_gcry_random_read_conf): New.
-       (_gcry_random_dump_stats): Call rndjent stats.
-       * random/rndjent.c (jent_rng_totalcalls, jent_rng_totalbytes): New.
-       (_gcry_rndjent_poll): Take care of config option disable-jent.  Wipe
-       buffer.  Bump counters.
-       (_gcry_rndjent_dump_stats): New.
-
-2017-06-14  Werner Koch  <wk@gnupg.org>
-
-       random: Add jitter RND based entropy collector.
-       + commit f5e7763ddca59dcd9ac9f2f4d50cb41b14a34a9e
-       * random/rndjent.c: New.
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Use rndjent.
-       * random/rndw32.c (_gcry_rndw32_gather_random): Use rndjent.
-       (slow_gatherer): Fix compiler warning.
-       * random/Makefile.am (librandom_la_SOURCES): Add rndjent.c
-       (EXTRA_librandom_la_SOURCES): Add jitterentropy-base.c and
-       jitterentropy.h.
-       (rndjent.o, rndjent.lo): New rules.
-       * configure.ac: New option --disbale-jent-support
-       (ENABLE_JENT_SUPPORT): New ac-define.
-
-       cipher: New helper function rol64.
-       + commit 6c882fb1fdb6c7cba2215fa7391110d63e24b9dc
-       * cipher/bithelp.h (rol64): New inline functions.
-
-       New hardware feature flag HWF_INTEL_RDTSC.
-       + commit 06f303a633ea2b992259688bef2b023c3f388f73
-       * src/g10lib.h (HWF_INTEL_RDTSC): New.
-       * src/hwfeatures.c (hwflist): Add "intel-rdtsc".
-       * src/hwf-x86.c (detect_x86_gnuc): Get EDX features and test for TSC.
-
-       random: Changes to original Jitter RNG implementation.
-       + commit a44c45675f8b631e11048a540bb1fbb7a022ebb4
-       * random/jitterentropy-base.c: Change double underscore symbols and
-       make all functions static.
-       * random/jitterentropy.h: Likewise.
-
-2017-06-13  Stephan Mueller  <smueller@chronox.de>
-
-       random: Add original Jitter RNG implementation.
-       + commit f0ae18ecf48fbe2da0b9fb3f354d0dd3173d91d3
-       * random/jitterentropy-base-user.h: New.
-       * random/jitterentropy-base.c: New.
-       * random/jitterentropy.h: New.
-
-2017-06-08  Werner Koch  <wk@gnupg.org>
-
-       build: Fix ChangeLog building for builds from other worktrees.
-       + commit cdfd7ea72a44657f037dd0dbba6e5ea0c2b344aa
-       * Makefile.am (gen-ChangeLog): Test for existance of ".git" regardless
-       on whether it is a file or directory.
-
-2017-06-02  NIIBE Yutaka  <gniibe@fsij.org>
-
-       secmem: Fix SEGV and stat calculation.
-       + commit e0958debe1a7db1bec1283115cdc6a14bf3b43e5
-       * src/secmem (init_pool): Care about the header size.
-       (_gcry_secmem_malloc_internal): Likewise.
-       (_gcry_secmem_malloc_internal): Use mb->size for stats.
-
-2017-06-01  Jo Van Bulck  <jo.vanbulck@cs.kuleuven.be>
-
-       ecc: Store EdDSA session key in secure memory.
-       + commit 5a22de904a0a366ae79f03ff1e13a1232a89e26b
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_sign): use mpi_snew to allocate
-       session key.
-
-2017-05-31  Werner Koch  <wk@gnupg.org>
-
-       api: Deprecate gcry_md_info.
-       + commit 45c39340c9926c2c5801dbab7609687c41e9ff1f
-
-
-2017-05-30  Werner Koch  <wk@gnupg.org>
-
-       mpi: Distribute asm files for aarch64 and asm.
-       + commit c65f9558f12ffa2810538ef616e71b4052dacb81
-       * mpi/aarch64/distfiles: New.
-       * mpi/arm/distfiles: New.
-
-       mpi: Distribute asm definitions for amd64.
-       + commit 87e481137debabb7f989d7fa9b1c21c336e10c98
-       * mpi/amd64/distfiles: Add mpi-asm-defs.h.
-
-2017-05-23  Werner Koch  <wk@gnupg.org>
-
-       cipher: Fix compiler warnings.
-       + commit d764c9894013727ff82eb194da6030209c273528
-       * cipher/poly1305.c (poly1305_default_ops): Move to the top.  Add
-       prototypes and compile only if USE_SSE2 is not defined.
-       (poly1305_init_ext_ref32): Compile only if USE_SSE2 is not defined.
-       (poly1305_blocks_ref32): Ditto.
-       (poly1305_finish_ext_ref32): Ditto.
-
-       doc: Comment fixes.
-       + commit c1bb3d9fdb6fe5f336af1d5a03fc42bfdc1f8b0b
-
-
-2017-05-18  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael-ssse3: fix functions calls from assembly blocks.
-       + commit 4cd94994a9abec9b92fa5972869baf089a28fa76
-       * cipher/rijndael-ssse3-amd64.c (PUSH_STACK_PTR, POP_STACK_PTR): New.
-       (vpaes_ssse3_prepare_enc, vpaes_ssse3_prepare_dec)
-       (_gcry_aes_ssse3_do_setkey, _gcry_aes_ssse3_prepare_decryption)
-       (do_vpaes_ssse3_enc, do_vpaes_ssse3_dec): Use PUSH_STACK_PTR and
-       POP_STACK_PTR.
-
-       chacha20-armv7-neon: fix to use fast code path when memory is aligned.
-       + commit 68861ae5d3e007d7a39f14ea27dc3dd8ef13ba02
-       * cipher/chacha20-armv7-neon.S (UNALIGNED_LDMIA4): Uncomment
-       instruction for jump to aligned code path.
-
-       Move data in AMD64 assembly to text section.
-       + commit 1a094bc5b2aa730833faf593a931d4e5d7f9ab4d
-       * cipher/camellia-aesni-avx-amd64.S: Move data to .text section to
-       ensure that RIP relative addressing of data will work.
-       * cipher/camellia-aesni-avx2-amd64.S: Ditto.
-       * cipher/chacha20-avx2-amd64.S: Ditto.
-       * cipher/chacha20-ssse3-amd64.S: Ditto.
-       * cipher/des-amd64.S: Ditto.
-       * cipher/serpent-avx2-amd64.S: Ditto.
-       * cipher/sha1-avx-amd64.S: Ditto.
-       * cipher/sha1-avx-bmi2-amd64.S: Ditto.
-       * cipher/sha1-ssse3-amd64.S: Ditto.
-       * cipher/sha256-avx-amd64.S: Ditto.
-       * cipher/sha256-avx2-bmi2-amd64.S: Ditto.
-       * cipher/sha256-ssse3-amd64.S: Ditto.
-       * cipher/sha512-avx-amd64.S: Ditto.
-       * cipher/sha512-avx2-bmi2-amd64.S: Ditto.
-       * cipher/sha512-ssse3-amd64.S: Ditto.
-
-       cast5-amd64: use 64-bit relocation with large PIC memory model.
-       + commit ff02fca39c83bcf30c79368611ac65e273e77f6c
-       * cipher/cast5-amd64.S [__code_model_large__]
-       (GET_EXTERN_POINTER): New.
-
-2017-05-13  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix building with x86-64 medium and large memory models.
-       + commit 434d4f2af39033fc626044ba9a060da298522293
-       * cipher/cast5-amd64.S [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS]
-       (GET_EXTERN_POINTER): Load 64-bit address instead of 32-bit.
-       * cipher/rijndael.c (do_encrypt, do_decrypt)
-       [USE_AMD64_ASM && !HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS]: Load
-       table pointer through register instead of generic reference.
-
-2017-04-04  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: Simplify mpi_powm.
-       + commit 719468e53133d3bdf12156c5bfdea2bf15f9f6f1
-       * mpi/mpi-pow.c (_gcry_mpi_powm): Simplify the loop.
-
-2017-03-08  Justus Winter  <justus@g10code.com>
-
-       build: Use macOS' compatibility macros to enable all features.
-       + commit 654024081cfa103c87bb163b117ea3568171d408
-       * configure.ac: On macOS, use the compatibility macros to expose every
-       feature of the libc.  This is the equivalent of _GNU_SOURCE on GNU
-       libc.
-
-2017-02-27  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add BLAKE2b and BLAKE2s hash algorithms (RFC 7693)
-       + commit 5bd530b8a4624f101b8d42e68f1b28bcc13f4f76
-       * cipher/blake2.c: New.
-       * cipher/Makefile.am: Add 'blake2.c'.
-       * cipher/md.c (digest_list, prepare_macpads): Add BLAKE2.
-       (md_setkey): New.
-       (_gcry_md_setkey): Call 'md_setkey' for non-HMAC md.
-       * configure.ac: Add BLAKE2 digest.
-       * doc/gcrypt.texi: Add BLAKE2.
-       * src/cipher.h (_gcry_blake2_init_with_key)
-       (_gcry_digest_spec_blake2b_512, _gcry_digest_spec_blake2b_384)
-       (_gcry_digest_spec_blake2b_256, _gcry_digest_spec_blake2b_160)
-       (_gcry_digest_spec_blake2s_256, _gcry_digest_spec_blake2s_224)
-       (_gcry_digest_spec_blake2s_160, _gcry_digest_spec_blake2s_128): New.
-       * src/gcrypt.h.in (GCRY_MD_BLAKE2B_512, GCRY_MD_BLAKE2B_384)
-       (GCRY_MD_BLAKE2B_256, GCRY_MD_BLAKE2B_160, GCRY_MD_BLAKE2S_256)
-       (GCRY_MD_BLAKE2S_224, GCRY_MD_BLAKE2S_160, GCRY_MD_BLAKE2S_128): New.
-       * tests/basic.c (check_one_md): Add testing for keyed hashes.
-       (check_digests): Add BLAKE2 test vectors; Add testing for keyed hashes.
-       * tests/blake2b.h: New.
-       * tests/blake2s.h: New.
-       * tests/Makefile.am: Add 'blake2b.h' and 'blake2s.h'.
-
-       Fix building with clang on ARM64/FreeBSD.
-       + commit da213db2c6cda6f57e5853e8c591d69bfa1cfa74
-       * cipher/cipher-gcm-armv8-aarch64-ce.S: Use '.cpu generic+simd+crypto'
-       instead of '.arch armv8-a+crypto'.
-       * cipher/rijndael-armv8-aarch64-ce.S: Ditto.
-       * cipher/sha1-armv8-aarch64-ce.S: Ditto.
-       * cipher/sha256-armv8-aarch64-ce.S: Ditto.
-       * configure.ac (gcry_cv_gcc_inline_asm_aarch64_neon): Ditto.
-       (gcry_cv_gcc_inline_asm_aarch64_crypto): Ditto; and include NEON
-       instructions to crypto instructions check.
-
-2017-02-07  Justus Winter  <justus@g10code.com>
-
-       Fix building with a pre C99 compiler.
-       + commit 75d91ffeaf83098ade325bb3b6b2c8a76eb1f6a6
-       * cipher/cipher-cfb.c (_gcry_cipher_cfb8_encrypt): Move the
-       declaration of 'i' out of the loop.
-       (_gcry_cipher_cfb8_decrypt): Likewise.
-
-2017-02-04  Mathias L. Baumann  <mathias.baumann_at_sociomantic.com>
-
-       Implement CFB with 8-bit mode.
-       + commit d1ee9a660571ce4a998c9ab2299d4f2419f99127
-       * cipher/cipher-cfb.c (_gcry_cipher_cfb8_encrypt)
-       (_gcry_cipher_cfg8_decrypt): Add 8-bit variants of decrypt/encrypt
-       functions.
-       * cipher/cipher-internal.h (_gcry_cipher_cfb8_encrypt)
-       (_gcry_cipher_cfg8_decrypt): Ditto.
-       * cipher/cipher.c: Adjust code flow to work with GCRY_CIPHER_MODE_CFB8.
-       * tests/basic.c: Add tests for cfb8 with AES and 3DES.
-
-2017-02-04  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rndhw: add missing "memory" clobbers.
-       + commit c67c728478e8f47b6e8296b643fd35d66d4a1052
-       * random/rndhw.c: (poll_padlock, rdrand_long): Add "memory" to asm
-       clobbers.
-
-       Add UNLIKELY and LIKELY macros.
-       + commit 4b7451d3e8e7b87d8e407fbbd924ad5b13bd0f00
-       * src/g10lib.h (LIKELY, UNLIKELY): New.
-       (gcry_assert): Use LIKELY for assert check.
-       (fast_wipememory2_unaligned_head): Use UNLIKELY for unaligned
-       branching.
-       * cipher/bufhelp.h (buf_cpy, buf_xor, buf_xor_1, buf_xor_2dst)
-       (buf_xor_n_copy_2): Ditto.
-
-       rndhw: avoid type-punching.
-       + commit 37b537600f33fcf8e1c8dc2c658a142fbba44199
-       * random/rndhw.c (rdrand_long, rdrand_nlong): Add 'volatile' for
-       pointer.
-       (poll_drng): Convert buffer to 'unsigned long[]' and make use of DIM
-       macro.
-
-2017-01-28  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       hwf-x86: avoid type-punching.
-       + commit 1407317a6112a23d4fec5827a9d74faef4196f66
-       * src/hwf-x86.c (detect_x86_gnuc): Use union for vendor_id.
-
-       cipher: add explicit blocksize checks to allow better optimization.
-       + commit efa9042f82ffed3d076b8e26ac62d29e00bb756a
-       * cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt)
-       (_gcry_cipher_cbc_decrypt): Add explicit check for cipher blocksize of
-       64-bit or 128-bit.
-       * cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt)
-       (_gcry_cipher_cfb_decrypt): Ditto.
-       * cipher/cipher-cmac.c (cmac_write, cmac_generate_subkeys)
-       (cmac_final): Ditto.
-       * cipher/cipher-ctr.c (_gcry_cipher_ctr_encrypt): Ditto.
-       * cipher/cipher-ofb.c (_gcry_cipher_ofb_encrypt): Ditto.
-
-       bufhelp: use unaligned dword and qword types for endianess helpers.
-       + commit e7b941c3de9c9b6319298c02f844cc0cadbf8562
-       * cipher/bufhelp.h (BUFHELP_UNALIGNED_ACCESS): New, defined
-       if attributes 'packed', 'aligned' and 'may_alias' are supported.
-       (BUFHELP_FAST_UNALIGNED_ACCESS): Define if have
-       BUFHELP_UNALIGNED_ACCESS.
-
-       rijndael-aesni: fix u128_t strict-aliasing rule breaking.
-       + commit 92b4a29d2453712192ced2d7226abc49679dcb1e
-       * cipher/rijndael-aesni.c (u128_t): Add attributes to tell GCC and clang
-       that casting from 'char *' to 'u128_t *' is ok.
-
-       cipher-xts: fix pointer casting to wrong alignment and aliasing.
-       + commit 4f31d816dcc1e95dc647651e92acbdfed53f5c14
-       * cipher/cipher-xts.c (xts_gfmul_byA, xts_inc128): Use buf_get_le64
-       and buf_put_le64 for accessing data; Change parameter pointers to
-       'unsigned char *' type.
-       (_gcry_cipher_xts_crypt): Do not cast buffer pointers to 'u64 *'
-       for helper functions.
-
-       crc-intel-pclmul: fix undefined behavior with unaligned access.
-       + commit 55cf1b5588705cab5f45e2817c4aa1d204dc0042
-       * cipher/crc-intel-pclmul.c (u16_unaligned_s): New.
-       (crc32_reflected_less_than_16, crc32_less_than_16): Use
-       'u16_unaligned_s' for unaligned memory access.
-
-       configure.ac: fix attribute checks.
-       + commit b29b1b9f576f501d4b993be0a751567045274a1a
-       * configure.ac: Add -Werror flag for attribute checks.
-
-       configure.ac: fix may_alias attribute check.
-       + commit 136c8416ea540dd126be3997d94d7063b3aaf577
-       * configure.ac: Test may_alias attribute on type, not on variable.
-
-       bufhelp: add 'may_alias' attribute for properly aligned 'bufhelp_int_t'
-       + commit d1ae52a0e23308f33b78cffeba56005b687f23c0
-       * cipher/bufhelp.h [!BUFHELP_FAST_UNALIGNED_ACCESS]
-       (bufhelp_int_t): Add 'may_alias' attribute.
-
-2017-01-27  Werner Koch  <wk@gnupg.org>
-
-       w32: New envvar GCRYPT_RNDW32_DBG.
-       + commit a351fbde8548ce3f57298c618426f043844fbc78
-       * random/rndw32.c (_gcry_rndw32_gather_random): Use getenv to set
-       DEBUG_ME.
-
-2017-01-23  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael-ssse3-amd64: fix building on x32.
-       + commit 39b9302da5d08bd52688d20befe626fee0b6c41d
-       * cipher/rijndael-ssse3-amd64.c: Use 64-bit call instructions
-       with 64-bit registers.
-
-       bufhelp: use 'may_alias' attribute unaligned pointer types.
-       + commit bf9e0b79e620ca2324224893b07522462b125412
-       * configure.ac (gcry_cv_gcc_attribute_may_alias)
-       (HAVE_GCC_ATTRIBUTE_MAY_ALIAS): New check for 'may_alias' attribute.
-       * cipher/bufhelp.h (BUFHELP_FAST_UNALIGNED_ACCESS): Enable only if
-       HAVE_GCC_ATTRIBUTE_MAY_ALIAS is defined.
-       [BUFHELP_FAST_UNALIGNED_ACCESS] (bufhelp_int_t, bufhelp_u32_t)
-       (bufhelp_u64_t): Add 'may_alias' attribute.
-       * src/g10lib.h (fast_wipememory_t): Add HAVE_GCC_ATTRIBUTE_MAY_ALIAS
-       defined check; Add 'may_alias' attribute.
-
-2017-01-18  Werner Koch  <wk@gnupg.org>
-
-       random: Call getrandom before select and emitting a progress callback.
-       + commit 623aab8a940ea61afe3fef650ad485a755ed9fe7
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Move the getrandom
-       call before the select.
-
-2017-01-06  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       mpi: amd64: fix too large jump alignment in mpih-rshift.
-       + commit ddcfe31e2425e88b280e7cdaf3f0eaaad8ccc023
-       * mpi/amd64/mpih-rshift.S (_gcry_mpih_rshift): Use 16-byte alignment
-       with 'ALIGN(4)' instead of 256-byte.
-
-       rijndael-ssse3: move assembly functions to separate source-file.
-       + commit 54c57bc49edb5c00e9ed8103cc4837bb72c5e863
-       * cipher/Makefile.am: Add 'rinjdael-ssse3-amd64-asm.S'.
-       * cipher/rinjdael-ssse3-amd64-asm.S: Moved assembly functions
-       here ...
-       * cipher/rinjdael-ssse3-amd64.c: ... from this file.
-       (_gcry_aes_ssse3_enc_preload, _gcry_aes_ssse3_dec_preload)
-       (_gcry_aes_ssse3_shedule_core, _gcry_aes_ssse3_encrypt_core)
-       (_gcry_aes_ssse3_decrypt_core): New.
-       (vpaes_ssse3_prepare_enc, vpaes_ssse3_prepare_dec)
-       (_gcry_aes_ssse3_do_setkey, _gcry_aes_ssse3_prepare_decryption)
-       (do_vpaes_ssse3_enc, do_vpaes_ssse3_dec): Update to use external
-       assembly functions; remove 'aes_const_ptr' variable usage.
-       (_gcry_aes_ssse3_encrypt, _gcry_aes_ssse3_decrypt)
-       (_gcry_aes_ssse3_cfb_enc, _gcry_aes_ssse3_cbc_enc)
-       (_gcry_aes_ssse3_ctr_enc, _gcry_aes_ssse3_cfb_dec)
-       (_gcry_aes_ssse3_cbc_dec, ssse3_ocb_enc, ssse3_ocb_dec)
-       (_gcry_aes_ssse3_ocb_auth): Remove 'aes_const_ptr' variable usage.
-       * configure.ac: Add 'rinjdael-ssse3-amd64-asm.lo'.
-
-       Add AVX2/vpgather bulk implementation of Twofish.
-       + commit c59a8ce51ceb9a80169c44ef86a67e95cf8528c3
-       * cipher/Makefile.am: Add 'twofish-avx2-amd64.S'.
-       * cipher/twofish-avx2-amd64.S: New.
-       * cipher/twofish.c (USE_AVX2): New.
-       (TWOFISH_context) [USE_AVX2]: Add 'use_avx2' member.
-       (ASM_FUNC_ABI): New.
-       (twofish_setkey): Add check for AVX2 and fast VPGATHER HW features.
-       (_gcry_twofish_avx2_ctr_enc, _gcry_twofish_avx2_cbc_dec)
-       (_gcry_twofish_avx2_cfb_dec, _gcry_twofish_avx2_ocb_enc)
-       (_gcry_twofish_avx2_ocb_dec, _gcry_twofish_avx2_ocb_auth): New.
-       (_gcry_twofish_ctr_enc, _gcry_twofish_cbc_dec, _gcry_twofish_cfb_dec)
-       (_gcry_twofish_ocb_crypt, _gcry_twofish_ocb_auth): Add AVX2 bulk
-       handling.
-       (selftest_ctr, selftest_cbc, selftest_cfb): Increase nblocks from
-       3+X to 16+X.
-       * configure.ac: Add 'twofish-avx2-amd64.lo'.
-       * src/g10lib.h (HWF_INTEL_FAST_VPGATHER): New.
-       * src/hwf-x86.c (detect_x86_gnuc): Add detection for
-       HWF_INTEL_FAST_VPGATHER.
-       * src/hwfeatures.c (HWF_INTEL_FAST_VPGATHER): Add
-       "intel-fast-vpgather" for HWF_INTEL_FAST_VPGATHER.
-
-       Add XTS cipher mode.
-       + commit 232a129b1f915fc54881506e4b07c89cf84932e6
-       * cipher/Makefile.am: Add 'cipher-xts.c'.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Add 'bulk.xts_crypt'
-       and 'u_mode.xts' members.
-       (_gcry_cipher_xts_crypt): New prototype.
-       * cipher/cipher-xts.c: New.
-       * cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey)
-       (cipher_reset, cipher_encrypt, cipher_decrypt): Add XTS mode handling.
-       * doc/gcrypt.texi: Add XTS mode to documentation.
-       * src/gcrypt.h.in (GCRY_CIPHER_MODE_XTS, GCRY_XTS_BLOCK_LEN): New.
-       * tests/basic.c (do_check_xts_cipher, check_xts_cipher): New.
-       (check_bulk_cipher_modes): Add XTS test-vectors.
-       (check_one_cipher_core, check_one_cipher, check_ciphers): Add XTS
-       testing support.
-       (check_cipher_modes): Add XTS test.
-       * tests/bench-slope.c (bench_xts_encrypt_init)
-       (bench_xts_encrypt_do_bench, bench_xts_decrypt_do_bench)
-       (xts_encrypt_ops, xts_decrypt_ops): New.
-       (cipher_modes, cipher_bench_one): Add XTS.
-       * tests/benchmark.c (cipher_bench): Add XTS testing.
-
-2017-01-04  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael-ssse3: fix counter operand from read-only to read/write.
-       + commit aada604594fd42224d366d3cb98f67fd3b989cd6
-       * cipher/rijndael-ssse3-amd64.c (_gcry_aes_ssse3_ctr_enc): Change
-       'ctrlow' operand from read-only to read-write.
-
-2017-01-03  Werner Koch  <wk@gnupg.org>
-
-       Extend GCRYCTL_PRINT_CONFIG to print compiler version.
-       + commit 98b49695b1ffe3c406ae39a45051b8594f903b9d
-       * src/global.c (print_config): Print version of libgpg-error and used
-       compiler.
-
-       tests: Add option --disable-hwf to the version utility.
-       + commit 3582641469f1c74078f0d758c4d5458cc0ee5649
-       * src/hwfeatures.c (_gcry_disable_hw_feature): Rewrite to allow
-       passing a colon delimited feature set.
-       (parse_hwf_deny_file): Remove unused var I.
-       * tests/version.c (main): Add options --verbose and --disable-hwf.
-
-2016-12-15  Werner Koch  <wk@gnupg.org>
-           Nicolas Porcel  <nicolasporcel06@gmail.com>
-
-       Fix regression in broken mlock detection.
-       + commit 0a90f87799903a3fb97189ef7cba19e7b3534e1c
-       * acinclude.m4 (GNUPG_CHECK_MLOCK): Fix typo EGAIN->EAGAIN.
-
-2016-12-10  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       hwfeatures: add 'all' for disabling all hardware features.
-       + commit c83d0d2a26059cf471d09f5cb8e7fc5d76c4907b
-       * .gitignore: Add 'tests/basic-disable-all-hwf'.
-       * configure.ac: Ditto.
-       * tests/Makefile.am: Ditto.
-       * src/hwfeatures.c (_gcry_disable_hw_feature): Match 'all' for
-       masking all HW features off.
-       (parse_hwf_deny_file): Use '_gcry_disable_hw_feature' for matching.
-       * tests/basic-disable-all-hwf.in: New.
-
-       tests/hashtest-256g: add missing executable extension for Win32.
-       + commit 2b7b227b8a0bd5ff286258bc187782efac180a7e
-       * tests/hashtest-256g.in: Add @EXEEXT@.
-
-       OCB ARM CE: Move ocb_get_l handling to assembly part.
-       + commit 5c418e597f0f20a546d953161695e6caf1f57689
-       * cipher/rijndael-armv8-aarch32-ce.S: Add OCB 'L_{ntz(i)}' calculation.
-       * cipher/rijndael-armv8-aarch64-ce.S: Ditto.
-       * cipher/rijndael-armv8-ce.c (_gcry_aes_ocb_enc_armv8_ce)
-       (_gcry_aes_ocb_dec_armv8_ce, _gcry_aes_ocb_auth_armv8_ce)
-       (ocb_cryt_fn_t): Updated arguments.
-       (_gcry_aes_armv8_ce_ocb_crypt, _gcry_aes_armv8_ce_ocb_auth): Remove
-       'ocb_get_l' handling and splitting input to 32 block chunks, instead
-       pass full buffers to assembly.
-
-       OCB: Move large L handling from bottom to upper level.
-       + commit 2d2e5286d53e1f62fe040dff4c6e01961f00afe2
-       * cipher/cipher-ocb.c (_gcry_cipher_ocb_get_l): Remove.
-       (ocb_get_L_big): New.
-       (_gcry_cipher_ocb_authenticate): L-big handling done in upper
-       processing loop, so that lower level never sees the case where
-       'aad_nblocks % 65536 == 0'; Add missing stack burn.
-       (ocb_aad_finalize): Add missing stack burn.
-       (ocb_crypt): L-big handling done in upper processing loop, so that
-       lower level never sees the case where 'data_nblocks % 65536 == 0'.
-       * cipher/cipher-internal.h (_gcry_cipher_ocb_get_l): Remove.
-       (ocb_get_l): Remove 'l_tmp' usage and simplify since input
-       is more limited now, 'N is not multiple of 65536'.
-       * cipher/rijndael-aesni.c (get_l): Remove.
-       (aesni_ocb_enc, aesni_ocb_dec, _gcry_aes_aesni_ocb_auth): Remove
-       l_tmp; Use 'ocb_get_l'.
-       * cipher/rijndael-ssse3-amd64.c (get_l): Remove.
-       (ssse3_ocb_enc, ssse3_ocb_dec, _gcry_aes_ssse3_ocb_auth): Remove
-       l_tmp; Use 'ocb_get_l'.
-       * cipher/camellia-glue.c: Remove OCB l_tmp usage.
-       * cipher/rijndael-armv8-ce.c: Ditto.
-       * cipher/rijndael.c: Ditto.
-       * cipher/serpent.c: Ditto.
-       * cipher/twofish.c: Ditto.
-
-       OCB: remove 'int64_t' usage.
-       + commit 161d339f48c03be7fd0f4249d730f7f1767ef8e4
-       * cipher/cipher-ocb.c (double_block): Use alternative way to generate
-       sign-bit mask, without 'int64_t'.
-
-       random-drbg: use bufhelp function for big-endian store.
-       + commit 0b03b658bebc69a84d87ef13f9b60a27b0c42305
-       * random/random-drbg.c (drbg_cpu_to_be32): Remove.
-       (drbg_ctr_df, drbg_hash_df): Use 'buf_put_be32' instead of
-       'drbg_cpu_to_be32'.
-
-2016-12-09  Werner Koch  <wk@gnupg.org>
-
-       Improve handling of mlock error codes.
-       + commit 618b8978f46f4011c11512fd5f30c15e01652e2e
-       * acinclude.m4 (GNUPG_CHECK_MLOCK): Check also for EAGAIN which is a
-       legitimate return code and does not indicate a broken mlock().
-       * src/secmem.c (lock_pool_pages): Test ERR instead of ERRNO which
-       could have been overwritten by cap_from+text et al.
-
-2016-12-08  Stephan Mueller  <smueller@chronox.de>
-
-       random: Eliminate unneeded memcpy invocations in the DRBG.
-       + commit 656395ba4cf34f42dda3a120bda3ed1220755a3d
-       * random/random-drbg.c (drbg_hash): Remove arg 'outval' and return a
-       pointer instead.
-       (drbg_instantiate): Reduce size of scratchpad.
-       (drbg_hmac_update): Avoid use of scratch buffers for the hash.
-       (drbg_hmac_generate, drbg_hash_df): Ditto.
-       (drbg_hash_process_addtl): Ditto.
-       (drbg_hash_hashgen): Ditto.
-       (drbg_hash_generate): Ditto.
-
-       random: Add performance improvements for the DRBG.
-       + commit 20886fdcb841b0bf89bb1d44303d42f1804e38cb
-       * random/random-drbg.c (struct drbg_state_ops_s): New function
-       pointers 'crypto_init' and 'crypto-fini'.
-       (struct drbg_state_s): New fields 'priv_data', 'ctr_handle', and
-       'ctr_null'.
-       (drbg_hash_init, drbg_hash_fini): New.
-       (drbg_hmac_init, drbg_hmac_setkey): New.
-       (drbg_sym_fini, drbg_sym_init, drbg_sym_setkey): New.
-       (drbg_sym_ctr): New.
-       (drbg_ctr_bcc): Set the key.
-       (drbg_ctr_df): Ditto.
-       (drbg_hmac_update): Ditto.
-       (drbg_hmac_generate): Replace drgb_hmac by drbg_hash.
-       (drbg_hash_df): Ditto.
-       (drbg_hash_process_addtl): Ditto.
-       (drbg_hash_hashgen): Ditto.
-       (drbg_ctr_update): Rework.
-       (drbg_ctr_generate): Rework.
-       (drbg_ctr_ops): Init new functions pointers.
-       (drbg_uninstantiate): Call fini function.
-       (drbg_instantiate): Call init function.
-
-       cipher: New function for reading the counter in CTR mode.
-       + commit 227099f179df9dcf083d0ef6be9883c775df0874
-       * cipher/cipher.c (gcry_cipher_getctr): New.
-
-2016-12-07  Werner Koch  <wk@gnupg.org>
-
-       Document the overflow pools and add a stupid test case.
-       + commit 95bac312644ad45e486c94c2efd25d0748b9a20b
-       * tests/t-secmem.c (test_secmem_overflow): New func.
-       (main): Disable warning and call new function.
-
-       Implement overflow secmem pools for xmalloc style allocators.
-       + commit b6870cf25c0b1eb9c127a94af8326c446421a472
-       * src/secmem.c (pooldesc_s): Add fields next, cur_alloced, and
-       cur_blocks.
-       (cur_alloced, cur_blocks): Remove vars.
-       (ptr_into_pool_p): Make it inline.
-       (stats_update): Add arg pool and update the new pool specific
-       counters.
-       (_gcry_secmem_malloc_internal): Add arg xhint and allocate overflow
-       pools as needed.
-       (_gcry_secmem_malloc): Pass XHINTS along.
-       (_gcry_secmem_realloc_internal): Ditto.
-       (_gcry_secmem_realloc): Ditto.
-       (_gcry_secmem_free_internal): Take multiple pools in account.  Add
-       return value to indicate whether the arg was freed.
-       (_gcry_secmem_free): Add return value to indicate whether the arg was
-       freed.
-       (_gcry_private_is_secure): Take multiple pools in account.
-       (_gcry_secmem_term): Release all pools.
-       (_gcry_secmem_dump_stats): Print stats for all pools.
-       * src/stdmem.c (_gcry_private_free): Replace _gcry_private_is_secure
-       test with a direct call of _gcry_secmem_free to avoid double checking.
-
-       Give the secmem allocators a hint when a xmalloc calls them.
-       + commit b7df907dca4d525f8930c533b763ffce44ceed87
-       * src/secmem.c (_gcry_secmem_malloc): New not yet used arg XHINT.
-       (_gcry_secmem_realloc): Ditto.
-       * src/stdmem.c (_gcry_private_malloc_secure): New arg XHINT to be
-       passed to the secmem functions.
-       (_gcry_private_realloc): Ditto.
-       * src/g10lib.h (GCRY_ALLOC_FLAG_XHINT): New.
-       * src/global.c (do_malloc): Pass this flag as XHINT to the private
-       allocator.
-       (_gcry_malloc_secure): Factor code out to ...
-       (_gcry_malloc_secure_core): this.  Add arg XHINT.
-       (_gcry_realloc): Factor code out to ...
-       (_gcry_realloc_core): here.  Add arg XHINT.
-       (_gcry_strdup): Factor code out to ...
-       (_gcry_strdup_core): here.  Add arg XHINT.
-       (_gcry_xrealloc): Use the core function and pass true for XHINT.
-       (_gcry_xmalloc_secure): Ditto.
-       (_gcry_xstrdup): Ditto.
-
-       tests: New test t-secmem.
-       + commit e366c19b34922c770af82cd035fd815680b29dee
-       * src/secmem.c (_gcry_secmem_dump_stats): Add arg EXTENDED and adjust
-       caller.
-       * src/gcrypt-testapi.h (PRIV_CTL_DUMP_SECMEM_STATS): New.
-       * src/global.c (_gcry_vcontrol): Implement that.
-       * tests/t-secmem.c: New.
-       * tests/Makefile.am (tests_bin): Add that test.
-
-2016-12-06  Werner Koch  <wk@gnupg.org>
-
-       Fix compiler warning about possible-NULL-dreference.
-       + commit 995ce697308320c6a52a307f83dc49eeb8d784b4
-       * src/mpi.h (mpi_is_const, mpi_is_immutable): Do check arg before
-       deref-ing.  The are only used at places where the arg shall not be NULL.
-
-       Fix possible NULL-deref in gcry_log_debugsxp.
-       + commit 984a97f0750f812f0ad3c343ee6a67560953a504
-       * src/misc.c (_gcry_log_printsxp): Prevent passing NULL to strlen.
-
-       Reorganize code in secmem.c.
-       + commit 603f479a919311f720a05da738150c2192d5e562
-       * src/secmem.c (pooldesc_t): New type to collect information about one
-       pool.
-       (pool_size): Remove.  Now a member of pooldesc_t.
-       (pool_okay): Ditto.
-       (pool_is_mmapped): Ditto.
-       (pool): Rename variable ...
-       (mainpool): And change type to pooldesc_t.
-       (ptr_into_pool_p): Add arg 'pool'.
-       (mb_get_next): Ditto.
-       (mb_get_prev): Ditto.
-       (mb_merge): Ditto.
-       (mb_get_new): Ditto.
-       (init_pool): Ditto.
-       (lock_pool): Rename to ...
-       (look_pool_pages: this.
-       (secmem_init): Rename to ...
-       (_gcry_secmem_init_internal): this.  Add local var POOL and init with
-       address of MAINPOOL.
-       (_gcry_secmem_malloc_internal): Add local var POOL and init with
-       address of MAINPOOL.
-       (_gcry_private_is_secure): Ditto.
-       (_gcry_secmem_term): Ditto.
-       (_gcry_secmem_dump_stats): Ditto.
-       (_gcry_secmem_free_internal): Ditto.  Remove check for NULL arg.
-       (_gcry_secmem_free): Add check for NULL arg before taking the lock.
-       (_gcry_secmem_realloc): Factor most code out to ...
-       (_gcry_secmem_realloc_internal): this.
-
-2016-11-28  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       tests: Add PBKDF2 tests for Stribog512.
-       + commit a0580d446fef648a177ca4ab060d0e449780db84
-       * tests/t-kdf.c (check_pbkdf2): Add Stribog512 test cases from TC26's
-       additions to PKCS#5.
-
-       tests: Add Stribog HMAC tests from TC26ALG.
-       + commit fe6077e6ee8565bfcc91bad14a73e68f45b3c32b
-       * tests/basic.c (check_mac): add HMAC test vectors from TC26ALG document
-       for Stribog.
-
-       cipher: Add Stribog OIDs from TC26 space.
-       + commit ccffacaf6c3abe6120a0898db922981d28ab7af2
-       * cipher/stribog.c (oid_spec_stribog256, oid_spec_stribog512): New.
-
-2016-11-25  Justus Winter  <justus@g10code.com>
-
-       tests: Fix memory leak.
-       + commit 5530a8234d703ce9b685f78fb6e951136eb0aeb2
-       * tests/basic.c (check_gost28147_cipher): Free cipher handles.
-
-2016-11-25  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Cast oid argument of gcry_cipher_set_sbox to disable compiler warning.
-       + commit 1a67e3195896704f8b3ba09e3db1214bab834491
-       * src/gcrypt.h.in (gcry_cipher_set_sbox): Cast oid to (void *).
-
-       gost: Rename tc26 s-box from A to Z.
-       + commit dc8ceb8d2dfef949f3afa14fc75f9de8cd07c7ad
-       * cipher/gost-s-box.c (gost_sboxes): Rename TC26_A to TC26_Z as it is
-       the name that ended up in all standards.
-
-       tests: Add test to verify GOST 28147-89 against known results.
-       + commit 4f5c26c73c66daf2e4aff966e43c22b2db7e0138
-       * tests/basic.c (check_gost28147_cipher): new test function.
-
-2016-11-17  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       cipher/gost28147: Fix CryptoPro-B S-BOX.
-       + commit 5ca63c92825453fdb369a97bbc19cb95b49b4296
-       * cipher/gost-s-box.c: CryptoPro_B s-box missed one line, resulting in
-       incorrect encryption/decryption using that s-box.  Add missing data.
-
-2016-11-12  Werner Koch  <wk@gnupg.org>
-
-       Put blocking calls into Libgpg-error's system call clamp.
-       + commit b829dfe9f0eeff08c956ba3f3a6b559b9d2199dd
-       * src/gcrypt.h.in (GCRYCTL_REINIT_SYSCALL_CLAMP): New.
-       * configure.ac: Require Libgpg-error 1.25.  Set version number to
-       1.8.0.
-       * src/gcrypt-int.h: Remove error code emulation.
-       * src/global.c (pre_syscall_func, post_syscall_func): New.
-       (global_init): Call gpgrt_get_syscall_clamp.
-       (_gcry_vcontrol) <GCRYCTL_REINIT_SYSCALL_CLAMP>: Ditto.
-       (_gcry_pre_syscall, _gcry_post_syscall): New.
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Use the new
-       functions.
-
-2016-11-01  NIIBE Yutaka  <gniibe@fsij.org>
-
-       cipher: Fix IDEA cipher for clearing memory.
-       + commit bf6d5b10cb4173826f47ac080506b68bb001acb2
-       * cipher/idea.c (invert_key): Use wipememory, since this kind of memset
-       may be removed by compiler optimization.
-
-2016-10-09  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       GCM: Add bulk processing for ARMv8/AArch64 implementation.
-       + commit bfd732f53a9b5dfe14217a68a0fa289bf6913ec0
-       * cipher/cipher-gcm-armv8-aarch64-ce.S: Add 6 blocks bulk processing.
-
-       GCM: Add bulk processing for ARMv8/AArch32 implementation.
-       + commit 27747921cb1dfced83c5666cd1c474764724c52b
-       * cipher/cipher-gcm-armv8-aarch32-ce.S: Add 4 blocks bulk processing.
-       * tests/basic.c (check_digests): Print correct data length for "?"
-       tests.
-       (check_one_mac): Add large 1000000 bytes tests, when input is "!" or
-       "?".
-       (check_mac): Add "?" tests vectors for HMAC, CMAC, GMAC and POLY1305.
-
-2016-09-11  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add Aarch64 assembly implementation of Twofish.
-       + commit 5418d9ca4c0e087fd6872ad350a996fe74880d86
-       * cipher/Makefile.am: Add 'twofish-aarch64.S'.
-       * cipher/twofish-aarch64.S: New.
-       * cipher/twofish.c: Enable USE_ARM_ASM if __AARCH64EL__ and
-       HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS defined.
-       * configure.ac [host=aarch64]: Add 'twofish-aarch64.lo'.
-
-2016-09-05  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add Aarch64 assembly implementation of Camellia.
-       + commit de73a2e7237ba7c34ce48bb5fb671aa3993de832
-       * cipher/Makefile.am: Add 'camellia-aarch64.S'.
-       * cipher/camellia-aarch64.S: New.
-       * cipher/camellia-glue.c [USE_ARM_ASM][__aarch64__]: Set stack burn
-       size to zero.
-       * cipher/camellia.h: Enable USE_ARM_ASM if __AARCH64EL__ and
-       HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS defined.
-       * configure.ac [host=aarch64]: Add 'rijndael-aarch64.lo'.
-
-       Add ARMv8/AArch64 Crypto Extension implementation of AES.
-       + commit 4cd8d40d698564d24ece2af24546e34c58bf2961
-       * cipher/Makefile.am: Add 'rijndael-armv-aarch64-ce.S'.
-       * cipher/rijndael-armv8-aarch64-ce.S: New.
-       * cipher/rijndael-internal.h (USE_ARM_CE): Enable for ARMv8/AArch64.
-       * configure.ac: Add 'rijndael-armv-aarch64-ce.lo' and
-       'rijndael-armv8-ce.lo' for ARMv8/AArch64.
-
-       Add ARMv8/AArch64 Crypto Extension implementation of GCM.
-       + commit 0b332c1aef03a735c1fb0df184f74d523deb2f98
-       * cipher/Makefile.am: Add 'cipher-gcm-armv8-aarch64-ce.S'.
-       * cipher/cipher-gcm-armv8-aarch64-ce.S: New.
-       * cipher/cipher-internal.h (GCM_USE_ARM_PMULL): Enable on
-       ARMv8/AArch64.
-
-       Add ARMv8/AArch64 Crypto Extension implementation of SHA-256.
-       + commit 2d4bbc0ad62c54bbdef77799f9db82d344b7219e
-       * cipher/Makefile.am: Add 'sha256-armv8-aarch64-ce.S'.
-       * cipher/sha256-armv8-aarch64-ce.S: New.
-       * cipher/sha256-armv8-aarch32-ce.S: Move round macros to correct
-       section.
-       * cipher/sha256.c (USE_ARM_CE): Enable on ARMv8/AArch64.
-       * configure.ac: Add 'sha256-armv8-aarch64-ce.lo'; Swap places for
-       'sha512-arm.lo' and 'sha256-armv8-aarch32-ce.lo'.
-
-       Add ARMv8/AArch64 Crypto Extension implementation of SHA-1.
-       + commit e4eb03f56683317c908cb55be727832810dc8c72
-       * cipher/Makefile.am: Add 'sha1-armv8-aarch64-ce.S'.
-       * cipher/sha1-armv8-aarch64-ce.S: New.
-       * cipher/sha1.c (USE_ARM_CE): Enable on ARMv8/AArch64.
-       * configure.ac: Add 'sha1-armv8-aarch64-ce.lo'.
-
-2016-09-04  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add AArch64 assembly implementation of AES.
-       + commit 595251ad37bf1968261d7e781752513f67525803
-       * cipher/Makefile.am: Add 'rijndael-aarch64.S'.
-       * cipher/rijndael-aarch64.S: New.
-       * cipher/rijndael-internal.h: Enable USE_ARM_ASM if __AARCH64EL__ and
-       HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS defined.
-       * configure.ac (gcry_cv_gcc_aarch64_platform_as_ok): New check.
-       [host=aarch64]: Add 'rijndael-aarch64.lo'.
-
-2016-08-17  Werner Koch  <wk@gnupg.org>
-
-       Release 1.7.3.
-       + commit f8241874971478bdcd2bc2082d901d05db7b256d
-       * configure.ac: Set LT version to C21/A1/R3.
-
-       random: Hash continuous areas in the csprng pool.
-       + commit 8dd45ad957b54b939c288a68720137386c7f6501
-       * random/random-csprng.c (mix_pool): Store the first hash at the end
-       of the pool.
-
-       random: Improve the diagram showing the random mixing.
-       + commit 2f62103b4bb6d6f9ce806e01afb7fdc58aa33513
-       * random/random-csprng.c (mix_pool): Use DIGESTLEN instead of 20.
-
-2016-07-19  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       crc-intel-pclmul: split assembly block to ease register pressure.
-       + commit f38199dbc290003898a1799adc367265267784c2
-       * cipher/crc-intel-pclmul.c (crc32_less_than_16): Split inline
-       assembly block handling 4 byte input into multiple blocks.
-
-       rijndael-aesni: split assembly block to ease register pressure.
-       + commit a4d1595a2638db63ac4c73e722c8ba95fdd85ff7
-       * cipher/rijndael-aesni.c (do_aesni_ctr_4): Use single register
-       constraint for passing 'bige_addb' to assembly block; split
-       first inline assembly block into two parts.
-
-2016-07-14  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add ARMv8/AArch32 Crypto Extension implementation of AES.
-       + commit 05a4cecae0c02d2b4ee1cadd9c08115beae3a94a
-       * cipher/Makefile.am: Add 'rijndael-armv8-ce.c' and
-       'rijndael-armv-aarch32-ce.S'.
-       * cipher/rijndael-armv8-aarch32-ce.S: New.
-       * cipher/rijndael-armv8-ce.c: New.
-       * cipher/rijndael-internal.h (USE_ARM_CE): New.
-       (RIJNDAEL_context_s): Add 'use_arm_ce'.
-       * cipher/rijndael.c [USE_ARM_CE] (_gcry_aes_armv8_ce_setkey)
-       (_gcry_aes_armv8_ce_prepare_decryption)
-       (_gcry_aes_armv8_ce_encrypt, _gcry_aes_armv8_ce_decrypt)
-       (_gcry_aes_armv8_ce_cfb_enc, _gcry_aes_armv8_ce_cbc_enc)
-       (_gcry_aes_armv8_ce_ctr_enc, _gcry_aes_armv8_ce_cfb_dec)
-       (_gcry_aes_armv8_ce_cbc_dec, _gcry_aes_armv8_ce_ocb_crypt)
-       (_gcry_aes_armv8_ce_ocb_auth): New.
-       (do_setkey) [USE_ARM_CE]: Add ARM CE/AES HW feature check and key
-       setup for ARM CE.
-       (prepare_decryption, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc)
-       (_gcry_aes_ctr_enc, _gcry_aes_cfb_dec, _gcry_aes_cbc_dec)
-       (_gcry_aes_ocb_crypt, _gcry_aes_ocb_auth) [USE_ARM_CE]: Add
-       ARM CE support.
-       * configure.ac: Add 'rijndael-armv8-ce.lo' and
-       'rijndael-armv8-aarch32-ce.lo'.
-
-       Add ARMv8/AArch32 Crypto Extension implementation of GCM.
-       + commit 962b15470663db11e5c35b86768f1b5d8e600017
-       * cipher/Makefile.am: Add 'cipher-gcm-armv8-aarch32-ce.S'.
-       * cipher/cipher-gcm-armv8-aarch32-ce.S: New.
-       * cipher/cipher-gcm.c [GCM_USE_ARM_PMULL]
-       (_gcry_ghash_setup_armv8_ce_pmull, _gcry_ghash_armv8_ce_pmull)
-       (ghash_setup_armv8_ce_pmull, ghash_armv8_ce_pmull): New.
-       (setupM) [GCM_USE_ARM_PMULL]: Enable ARM PMULL implementation if
-       HWF_ARM_PULL HW feature flag is enabled.
-       * cipher/cipher-gcm.h (GCM_USE_ARM_PMULL): New.
-
-       Add ARMv8/AArch32 Crypto Extension implemenation of SHA-256.
-       + commit 34c64eb03178fbfd34190148fec5a189df2b8f83
-       * cipher/Makefile.am: Add 'sha256-armv8-aarch32-ce.S'.
-       * cipher/sha256-armv8-aarch32-ce.S: New.
-       * cipher/sha256.c (USE_ARM_CE): New.
-       (sha256_init, sha224_init): Check features for HWF_ARM_SHA1.
-       [USE_ARM_CE] (_gcry_sha256_transform_armv8_ce): New.
-       (transform) [USE_ARM_CE]: Use ARMv8 CE implementation if HW supports.
-       (SHA256_CONTEXT): Add 'use_arm_ce'.
-       * configure.ac: Add 'sha256-armv8-aarch32-ce.lo'.
-
-       Add ARMv8/AArch32 Crypto Extension implementation of SHA-1.
-       + commit 3d6334f8d94c2a4df10eed203ae928298a4332ef
-       * cipher/Makefile.am: Add 'sha1-armv8-aarch32-ce.S'.
-       * cipher/sha1-armv7-neon.S (_gcry_sha1_transform_armv7_neon): Add
-       missing size.
-       * cipher/sha1-armv8-aarch32-ce.S: New.
-       * cipher/sha1.c (USE_ARM_CE): New.
-       (sha1_init): Check features for HWF_ARM_SHA1.
-       [USE_ARM_CE] (_gcry_sha1_transform_armv8_ce): New.
-       (transform) [USE_ARM_CE]: Use ARMv8 CE implementation if HW supports
-       it.
-       * cipher/sha1.h (SHA1_CONTEXT): Add 'use_arm_ce'.
-       * configure.ac: Add 'sha1-armv8-aarch32-ce.lo'.
-
-       Add HW feature check for ARMv8 AArch64 and crypto extensions.
-       + commit eee78f6e1fbce7d54c43fb7efc5aa8be9f52755f
-       * configure.ac: Add '--disable-arm-crypto-support'; enable hwf-arm
-       module on 64-bit ARM.
-       (armcryptosupport, gcry_cv_gcc_inline_aarch32_crypto)
-       (gcry_cv_inline_asm_aarch64_neon)
-       (gcry_cv_gcc_inline_asm_aarch64_crypto): New.
-       * src/g10lib.h (HWF_ARM_AES, HWF_ARM_SHA1, HWF_ARM_SHA2)
-       (HWF_ARM_PMULL): New.
-       * src/hwf-arm.c [__aarch64__]: Enable building in AArch64 mode.
-       (feature_map_s): New.
-       [__arm__] (AT_HWCAP, AT_HWCAP2, HWCAP2_AES, HWCAP2_PMULL)
-       (HWCAP2_SHA1, HWCAP2_SHA2, arm_features): New.
-       [__aarch64__] (AT_HWCAP, AT_HWCAP2, HWCAP_ASIMD, HWCAP_AES)
-       (HWCAP_PMULL, HWCAP_SHA1, HWCAP_SHA2, arm_features): New.
-       (get_hwcap): Add reading of 'AT_HWCAP2'; Change auxv use
-       'unsigned long'.
-       (detect_arm_at_hwcap): Add mapping of HWCAP/HWCAP2 to HWF flags.
-       (detect_arm_proc_cpuinfo): Add mapping of CPU features to HWF flags.
-       (_gcry_hwf_detect_arm): Use __ARM_NEON instead of legacy __ARM_NEON__.
-       * src/hwfeatures.c (hwflist): Add 'arm-aes', 'arm-sha1', 'arm-sha2'
-       and 'arm-pmull'.
-
-2016-07-14  Werner Koch  <wk@gnupg.org>
-
-       Release 1.7.2.
-       + commit be0bec7d9208b2f2d2ffce9cc2ca6154853e7e59
-       * configure.ac: Set LT version to C21/A1/R2.
-       * Makefile.am (distcheck-hook): New.
-
-2016-07-13  Werner Koch  <wk@gnupg.org>
-
-       build: Update config.{guess,sub} to {2016-05-15,2016-06-20}.
-       + commit e535ea1bdc42309553007d60599d3147b8defe93
-       * build-aux/config.guess: Update.
-       * build-aux/config.sub: Update.
-
-2016-07-08  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix unaligned accesses with ldm/stm in ChaCha20 and Poly1305 ARM/NEON.
-       + commit 1111d311fd6452abd4080d1072c75ddb1b5a3dd1
-       * cipher/chacha20-armv7-neon.S (UNALIGNED_STMIA8)
-       (UNALIGNED_LDMIA4): New.
-       (_gcry_chacha20_armv7_neon_blocks): Use new helper macros instead of
-       ldm/stm instructions directly.
-       * cipher/poly1305-armv7-neon.S (UNALIGNED_LDMIA2)
-       (UNALIGNED_LDMIA4): New.
-       (_gcry_poly1305_armv7_neon_init_ext, _gcry_poly1305_armv7_neon_blocks)
-       (_gcry_poly1305_armv7_neon_finish_ext): Use new helper macros instead
-       of ldm instruction directly.
-
-2016-07-03  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       bench-slope: add unaligned buffer mode.
-       + commit 496790940753226f96b731a43d950bd268acd97a
-       * tests/bench-slope.c (unaligned_mode): New.
-       (do_slope_benchmark): Unalign buffer if in unaligned mode enabled.
-       (print_help, main): Add '--unaligned' parameter.
-
-2016-07-01  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix static build.
-       + commit cb79630ec567a5f2e03e5f863cda168faa7b8cc8
-       * tests/pubkey.c (_gcry_pk_util_get_nbits): Make function 'static'.
-
-2016-06-30  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Disallow encryption/decryption if key is not set.
-       + commit 07de9858032826f5a7b08c372f6bcc73bbb503eb
-       * cipher/cipher.c (cipher_encrypt, cipher_decrypt): If mode is not
-       NONE, make sure that key is set.
-       * cipher/cipher-ccm.c (_gcry_cipher_ccm_set_nonce): Do not clear
-       'marks.key' when reseting state.
-
-       Avoid unaligned accesses with ARM ldm/stm instructions.
-       + commit a6158a01a4d81a5d862e1e0a60bfd6063443311d
-       * cipher/rijndael-arm.S: Remove __ARM_FEATURE_UNALIGNED ifdefs, always
-       compile with unaligned load/store code paths.
-       * cipher/sha512-arm.S: Ditto.
-
-       Fix non-PIC reference in PIC for poly1305/ARMv7-NEON.
-       + commit a09126242a51c4ea4564b0f70b808e4f27fe5a91
-       * cipher/poly1305-armv7-neon.S (GET_DATA_POINTER): New.
-       (_gcry_poly1305_armv7_neon_init_ext): Use GET_DATA_POINTER.
-
-       Fix wrong CPU feature #ifdef for SHA1/AVX.
-       + commit 4a983e3bef58b9d056517e25e0ab10b72d12ceba
-       * cipher/sha1-avx-amd64.S: Check for HAVE_GCC_INLINE_ASM_AVX instead of
-       HAVE_GCC_INLINE_ASM_AVX2 & HAVE_GCC_INLINE_ASM_BMI2.
-
-2016-06-30  Werner Koch  <wk@gnupg.org>
-
-       random: Remove debug message about not supported getrandom syscall.
-       + commit 6965515c73632a088fb126a4a55e95121671fa98
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Remove log_debug
-       for getrandom error ENOSYS.
-
-2016-06-27  Werner Koch  <wk@gnupg.org>
-
-       tests: Do not test SHAKE128 et al with gcry_md_hash_buffer.
-       + commit 4d634a098742ff425b324e9f2a67b9f62de09744
-       * tests/benchmark.c (md_bench): Do not test variable lengths algos
-       with the gcry_md_hash_buffer.
-
-       md: Improve diagnostic when using SHAKE128 with gcry_md_hash_buffer.
-       + commit ae26edf4b60359bfa5fe3a27b2c24b336e7ec35c
-       * cipher/md.c (md_read): Detect missing read function.
-       (_gcry_md_hash_buffers): Return an error.
-
-2016-06-25  Werner Koch  <wk@gnupg.org>
-
-       ecc: Fix memory leak.
-       + commit 7a7f7c147f888367dfee6093d26bfeaf750efc3a
-       * cipher/ecc.c (ecc_check_secret_key): Do not init point if already
-       set.
-
-       doc: Update yat2m.
-       + commit 1feb01940062a74c27230434fc3babdddca8caf4
-       * doc/yat2m.c: Update from Libgpg-error
-
-       tests: Add attributes to helper functions.
-       + commit c870cb5d385c1d6e1e28ca481cf9cf44b3bfeea9
-       * tests/t-common.h (die, fail, info): Add attributes.
-       * tests/random.c (die, inf): Ditto.
-       * tests/pubkey.c (die, fail, info): Add attributes.
-       * tests/fipsdrv.c (die): Add attribute.
-       (main): Take care of missing --key,--iv,--dt options.
-
-       Improve robustness and help lint.
-       + commit 5a5b055b81ee60a22a846bdf2031516b1c24df98
-       * cipher/rsa.c (rsa_encrypt): Check for !DATA.
-       * cipher/md.c (search_oid): Check early for !OID.
-       (md_copy): Use gpg_err_code_from_syserror.  Replace chains of if(!err)
-       tests.
-       * cipher/cipher.c (search_oid): Check early for !OID.
-       * src/misc.c (do_printhex): Allow for BUFFER==NULL even with LENGTH>0.
-       * mpi/mpicoder.c (onecompl): Allow for A==NULL to help static
-       analyzers.
-
-       cipher: Improve fatal error message for bad use of gcry_md_read.
-       + commit 3f98b1e92d5afd720d7cea5b4e8295c5018bf9ac
-       * cipher/md.c (md_read): Use _gcry_fatal_error instead of BUG.
-
-2016-06-16  Niibe Yutaka  <gniibe@fsij.org>
-
-       ecc: Default cofactor 1 for PUBKEY_FLAG_PARAM.
-       + commit b0b70e7fe37b1bf13ec0bfc8effcb5c7f5db6b7d
-       * cipher/ecc.c (ecc_check_secret_key, ecc_sign, ecc_verify)
-       (ecc_encrypt_raw, ecc_decrypt_raw, compute_keygrip): Set default
-       cofactor as 1, when not specified.
-
-       ecc: Default cofactor 1 for PUBKEY_FLAG_PARAM.
-       + commit 0f3a069211d8d24a61aa0dc2cc6c4ef04cc4fab7
-       * cipher/ecc.c (ecc_check_secret_key, ecc_sign, ecc_verify)
-       (ecc_encrypt_raw, ecc_decrypt_raw, compute_keygrip): Set default
-       cofactor as 1, when not specified.
-
-2016-06-15  Werner Koch  <wk@gnupg.org>
-
-       Release 1.7.1.
-       + commit 48aa6d6602564d6ba0cef10cf08f9fb0c59b3223
-
-
-       doc: Describe envvars.
-       + commit c3173bbe3f1a9c73f81a538dd49ccfa0447bfcdc
-       * doc/gcrypt.texi: Add chapter Configuration.
-
-       random: Change names of debug envvars.
-       + commit 131b4f0634cee0e5c47d2250c59f51127b10f7b3
-       * random/rndunix.c (start_gatherer): Change GNUPG_RNDUNIX_DBG to
-       GCRYPT_RNDUNIX_DBG, change GNUPG_RNDUNIX_DBG to GCRYPT_RNDUNIX_DBG.
-       * random/rndw32.c (registry_poll): Change GNUPG_RNDW32_NOPERF to
-       GCRYPT_RNDW32_NOPERF.
-
-2016-06-14  Werner Koch  <wk@gnupg.org>
-
-       cipher: Assign OIDs to the Serpent cipher.
-       + commit e13a6a1ba53127af602713d0c2aaa85c94b3cd7e
-       * cipher/serpent.c (serpent128_oids, serpent192_oids)
-       (serpent256_oids): New. Add them to the specs blow.
-       (serpent128_aliases): Add "SERPENT-128".
-       (serpent256_aliases, serpent192_aliases): New.
-
-       cipher: Assign OIDs to the Serpent cipher.
-       + commit 6cc2100c00a65dff07b095dea7b32cb5c5cd96d4
-       * cipher/serpent.c (serpent128_oids, serpent192_oids)
-       (serpent256_oids): New. Add them to the specs blow.
-       (serpent128_aliases): Add "SERPENT-128".
-       (serpent256_aliases, serpent192_aliases): New.
-
-2016-06-08  Werner Koch  <wk@gnupg.org>
-
-       rsa: Implement blinding also for signing.
-       + commit 1f769e3e8442bae2f1f73c656920bb2df70153c0
-       * cipher/rsa.c (rsa_decrypt): Factor blinding code out to ...
-       (secret_blinded): new.
-       (rsa_sign): Use blinding by default.
-
-       random: Remove debug output for getrandom(2) output.
-       + commit 52cdfb1960808aaad48b5a501bbce0e3141c3961
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Remove debug
-       output.
-
-       Fix gcc portability on Solaris 9 SPARC boxes.
-       + commit b766ea14ad1c27d6160531b200cc70aaa479c6dc
-       * mpi/longlong.h: Use __sparcv8 as alias for __sparc_v8__.
-
-2016-06-08  Jérémie Courrèges-Anglas  <jca@wxcvbn.org>
-
-       Check for compiler SSE4.1 support in PCLMUL CRC code.
-       + commit dc76313308c184c92eb78452b503405b90fc7ebd
-       * cipher/crc-intel-pclmul.c: Build PCLMUL CRC implementation only if
-         compiler supports PCLMUL *and* SSE4.1
-       * cipher/crc.c: Ditto
-       * configure.ac (sse41support, gcry_cv_gcc_inline_asm_sse41): New.
-
-2016-06-08  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Fix ecc_verify for cofactor support.
-       + commit bd39eb9fba47dc8500c83769a679cc8b683d6c6e
-       * cipher/ecc.c (ecc_verify): Fix the argument for cofactor "h".
-
-2016-06-08  Werner Koch  <wk@gnupg.org>
-
-       random: Try to use getrandom() instead of /dev/urandom (Linux only).
-       + commit c05837211e5221d3f56146865e823bc20b4ff1ab
-       * configure.ac: Check for syscall.
-       * random/rndlinux.c [HAVE_SYSCALL]: Include sys/syscall.h.
-       (_gcry_rndlinux_gather_random): Use getrandom is available.
-
-2016-06-03  Werner Koch  <wk@gnupg.org>
-
-       rsa: Implement blinding also for signing.
-       + commit ef6e4d004b10f5740bcd2125fb70e199dd21e3e8
-       * cipher/rsa.c (rsa_decrypt): Factor blinding code out to ...
-       (secret_blinded): new.
-       (rsa_sign): Use blinding by default.
-
-       random: Remove debug output for getrandom(2) output.
-       + commit 82df6c63a72fdd969c3923523f10d0cef5713ac7
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Remove debug
-       output.
-
-2016-06-02  Werner Koch  <wk@gnupg.org>
-
-       Fix gcc portability on Solaris 9 SPARC boxes.
-       + commit 4121f15122501d8946f1589b303d1f7949c15e30
-       * mpi/longlong.h: Use __sparcv8 as alias for __sparc_v8__.
-
-2016-05-28  Jérémie Courrèges-Anglas  <jca@wxcvbn.org>
-
-       Check for compiler SSE4.1 support in PCLMUL CRC code.
-       + commit 3e8074ecd3a534e8bd7f11cf17f0b22d252584c8
-       * cipher/crc-intel-pclmul.c: Build PCLMUL CRC implementation only if
-         compiler supports PCLMUL *and* SSE4.1
-       * cipher/crc.c: Ditto
-       * configure.ac (sse41support, gcry_cv_gcc_inline_asm_sse41): New.
-
-2016-05-06  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Fix ecc_verify for cofactor support.
-       + commit c7430aa752232aa690c5d8f16575a345442ad8d7
-       * cipher/ecc.c (ecc_verify): Fix the argument for cofactor "h".
-
-2016-04-26  Werner Koch  <wk@gnupg.org>
-
-       random: Try to use getrandom() instead of /dev/urandom (Linux only).
-       + commit ee5a32226a7ca4ab067864e06623fc11a1768900
-       * configure.ac: Check for syscall.
-       * random/rndlinux.c [HAVE_SYSCALL]: Include sys/syscall.h.
-       (_gcry_rndlinux_gather_random): Use getrandom is available.
-
-2016-04-19  Werner Koch  <wk@gnupg.org>
-
-       asm fix for older gcc versions.
-       + commit caa9d14c914bf6116ec3f773a322a94e2be0c0fb
-       * cipher/crc-intel-pclmul.c: Remove extra trailing colon from
-       asm statements.
-
-       asm fix for older gcc versions.
-       + commit 4545372c0f8dd35aef2a7abc12b588ed1a4a0363
-       * cipher/crc-intel-pclmul.c: Remove extra trailing colon from
-       asm statements.
-
-2016-04-15  Werner Koch  <wk@gnupg.org>
-
-       Release 1.7.0.
-       + commit 795f9cb090c776658a0e3117996e3fb7e2ebd94a
-
-
-2016-04-14  Werner Koch  <wk@gnupg.org>
-
-       tests: Add test vectors for 256 GiB test of SHA3-256.
-       + commit 1737c546dc7268fa9edcd4a23b7439c56d37ee4f
-       * tests/hashtest.c: Add new test vectros.
-
-2016-04-14  Justus Winter  <justus@g10code.com>
-
-       src: Improve S-expression parsing.
-       + commit 491586bc7f7b9edc6b78331a77e653543983c9e4
-       * src/sexp.c (do_vsexp_sscan): Return an error if a closing
-       parenthesis is encountered with no matching opening parenthesis.
-
-2016-04-14  Werner Koch  <wk@gnupg.org>
-
-       cipher: Add constant for 8 bit CFB mode.
-       + commit 47c6a1f88eb763e9baa394e34d873b761abcebbe
-       * src/gcrypt.h.in (GCRY_CIPHER_MODE_CFB8): New.
-       * tests/basic.c (check_cfb_cipher): Prepare for CFB-8 tests.
-
-       tests: Add a new test for S-expressions.
-       + commit 88c6b98350193abbdcfb227754979b0c097ee09c
-       * tests/t-sexp.c (compare_to_canon): New.
-       (back_and_forth_one): Add another test.
-
-2016-04-13  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Fix corner cases for X25519.
-       + commit 8472b71812e71c69d66e2fcc02a6e21b66755f8b
-       * cipher/ecc.c (ecc_encrypt_raw): For invalid input, returns
-       GPG_ERR_INV_DATA instead of aborting with log_fatal.  For X25519,
-       it's not an error, thus, let it return 0.
-       (ecc_decrypt_raw): Use the flag PUBKEY_FLAG_DJB_TWEAK to distinguish
-       X25519, not by the name of the curve.
-       (ecc_decrypt_raw): For invalid input, returns GPG_ERR_INV_DATA instead
-       of aborting with log_fatal.  For X25519, it's not an error by its
-       definition, but we deliberately let it return the error to detect
-       looks-like-encrypted-message.
-       * tests/t-cv25519.c: Add points to record the issue.
-
-2016-04-12  Werner Koch  <wk@gnupg.org>
-
-       cipher: Buffer data from gcry_cipher_authenticate in OCB mode.
-       + commit b6d2a25a275a35ec4dbd53ecaa9ea0ed7aa99c7b
-       * cipher/cipher-internal.h (gcry_cipher_handle): Add fields
-       aad_leftover and aad_nleftover to u_mode.ocb.
-       * cipher/cipher-ocb.c (_gcry_cipher_ocb_set_nonce): Clear
-       aad_nleftover.
-       (_gcry_cipher_ocb_authenticate): Add buffering and facor some code out
-       to ...
-       (ocb_aad_finalize): new.
-       (compute_tag_if_needed): Call new function.
-       * tests/basic.c (check_ocb_cipher_splitaad): New.
-       (check_ocb_cipher): Call new function.
-       (main): Also call check_cipher_modes with --ciper-modes.
-
-2016-04-12  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Fix X25519 computation on Curve25519.
-       + commit ee7e1a0e835f8ffcfbcba2a44abab8632db8fed5
-       * cipher/ecc.c (ecc_encrypt_raw): Tweak of bits when
-       PUBKEY_FLAG_DJB_TWEAK is enabled.
-       (ecc_decrypt_raw): Return 0 when PUBKEY_FLAG_DJB_TWEAK is enabled.
-       * tests/t-cv25519.c (test_cv): Update by using gcry_pk_encrypt.
-
-       ecc: Fix initialization of EC context.
-       + commit 7fbdb99b8c56360adfd1fb4e7f4c95e0f8aa34de
-       * cipher/ecc.c (test_ecdh_only_keys, ecc_generate)
-       (ecc_check_secret_key, ecc_encrypt_raw, ecc_decrypt_raw): Initialize
-       by _gcry_mpi_ec_p_internal_new should carry FLAGS.
-
-2016-04-06  Werner Koch  <wk@gnupg.org>
-
-       Allow building with configure option --enable-hmac-binary-check.
-       + commit 65c63144b66392f40b991684789b8b793248e3ba
-       * src/Makefile.am (mpicalc_LDADD): Add DL_LIBS.
-       * src/fips.c (check_binary_integrity): Allow use of hmac256 output.
-       * src/hmac256.c (main): Add option --stdkey
-
-2016-04-06  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Positive values in computation.
-       + commit 6f386ceae86a058e26294f744750f1ed2a95e604
-       * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Make sure
-       coefficients A and B are positive.
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_recover_x): For negation, do
-       "P - T" instead of "-T", so that the result will be positive.
-       (_gcry_ecc_eddsa_verify): Likewise.
-       * cipher/ecc.c (ecc_check_secret_key): Use _gcry_ecc_fill_in_curve
-       instead of _gcry_ecc_update_curve_param.
-       * mpi/ec.c (ec_subm): Make sure the result will be positive.
-       (dup_point_edwards, sub_points_edwards, _gcry_mpi_ec_curve_point): Use
-       mpi_sub instead of mpi_neg.
-       (add_points_edwards): Simply use ec_addm.
-       * tests/t-mpi-point.c (test_curve): Define curves with positive
-       coefficients.
-
-2016-04-01  Werner Koch  <wk@gnupg.org>
-
-       mpi: Explicitly limit the allowed input length for gcry_mpi_scan.
-       + commit 862cf19a119427dd7ee7959a36c72d905f5ea5ca
-       * mpi/mpicoder.c (MAX_EXTERN_SCAN_BYTES): New.
-       (mpi_fromstr): Check against this limit.
-       (_gcry_mpi_scan): Ditto.
-       * tests/mpitests.c (test_maxsize): New.
-       (main): Cal that test.
-
-2016-03-31  Werner Koch  <wk@gnupg.org>
-
-       cipher: Remove specialized rmd160 functions.
-       + commit fcce0cb6e8af70b134c6ecc3f56afa07a7d31f27
-       * cipher/rmd160.c: Replace rmd.h by hash-common.h.
-       (RMD160_CONTEXT): Move from rmd.h to here.
-       (_gcry_rmd160_init): Remove.
-       (_gcry_rmd160_mixblock): Remove.
-       (_gcry_rmd160_hash_buffer): Use rmd160_init directly.
-       * cipher/md.c: Remove rmd.h which was not actually used.
-       * cipher/rmd.h: Remove.
-       * cipher/Makefile.am (libcipher_la_SOURCES): Remove rmd.h.
-       * configure.ac (USE_RMD160): Allow to build without RMD160.
-
-       random: Replace RMD160 by SHA-1 for mixing the CSPRNG pool.
-       + commit a9cbe2d1f6a517a831517da8bc1d29e3e0b2c0c0
-       * cipher/sha1.c (_gcry_sha1_mixblock_init): New.
-       (_gcry_sha1_mixblock): New.
-       * random/random-csprng.c: Include sha1.h instead of rmd.h.
-       (mix_pool): Use SHA-1 instead of RIPE-MD-160 for mixing.
-
-       cipher: Move sha1 context definition to a separate file.
-       + commit 142a479a484cb4e84d0561be9b05b44dac9e6fe2
-       * cipher/sha1.c: Replace hash-common.h by sha1.h.
-       (SHA1_CONTEXT): Move to ...
-       * cipher/sha1.h: new.  Always include all flags.
-       * cipher/Makefile.am (libcipher_la_SOURCES): Add sha1.h.
-
-2016-03-29  Werner Koch  <wk@gnupg.org>
-
-       tests: Fix buffer overflow in bench-slope.
-       + commit 48ee918400762281bec5b6fc218a9f0d119aac7c
-       * tests/bench-slope.c (bench_print_result_std): Remove wrong use of
-       strncat.
-
-2016-03-27  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       cipher: GCM: check that length of supplied tag is one of valid lengths.
-       + commit f2260e3a2e962ac80124ef938e54041bbea08561
-       * cipher/cipher-gcm.c (is_tag_length_valid): New.
-       (_gcry_cipher_gcm_tag): Check that 'outbuflen' has valid tag length.
-       * tests/basic.c (_check_gcm_cipher): Add test-vectors with different
-       valid tag lengths and negative test vectors with invalid lengths.
-
-2016-03-24  Peter Wu  <peter@lekensteyn.nl>
-
-       cipher: Fix memleaks in (self)tests.
-       + commit 4a064e2a06fe737f344d1dfd8a45cc4c2abbe4c9
-       * cipher/dsa.c: Release memory for MPI and sexp structures.
-       * cipher/ecc.c: Release memory for sexp structure.
-       * tests/keygen.c: Likewise.
-
-       Mark constant MPIs as non-leaked.
-       + commit 470a30db241a2d567739ef2adb2a2ee64992d8b4
-       * mpi/mpiutil.c: Mark "constant" MPIs as explicitly leaked.
-
-2016-03-23  Werner Koch  <wk@gnupg.org>
-
-       Add new control GCRYCTL_GET_TAGLEN for use with gcry_cipher_info.
-       + commit fea5971488e049f902d7912df22a945bc755ad6d
-       * src/gcrypt.h.in (GCRYCTL_GET_TAGLEN): New.
-       * cipher/cipher.c (_gcry_cipher_info): Add GCRYCTL_GET_TAGLEN feature.
-
-       * tests/basic.c (_check_gcm_cipher): Check that new feature.
-       (_check_poly1305_cipher): Ditto.
-       (check_ccm_cipher): Ditto.
-       (do_check_ocb_cipher): Ditto.
-       (check_ctr_cipher): Add negative test for new feature.
-
-       cipher: Avoid NULL-segv in GCM mode if a key has not been set.
-       + commit e709d86fe596a4bcf235799468947c13ae657d78
-       * cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt): Check that GHASH_FN
-       has been initialized.
-       (_gcry_cipher_gcm_decrypt): Ditto.
-       (_gcry_cipher_gcm_authenticate): Ditto.
-       (_gcry_cipher_gcm_initiv): Ditto.
-       (_gcry_cipher_gcm_tag): Ditto.
-
-       cipher: Check length of supplied tag in _gcry_cipher_poly1305_check_tag.
-       + commit 7c9c82feecf94a455c66d9c38576f36c9c4b484c
-       * cipher/cipher-poly1305.c (_gcry_cipher_poly1305_tag): Check that the
-       provided tag length matches the actual tag length.
-
-2016-03-23  Peter Wu  <peter@lekensteyn.nl>
-
-       Fix buffer overrun in gettag for Poly1305.
-       + commit 6821e1bd94969106a70e3de17b86f6e6181f4e59
-       * cipher/cipher-poly1305.c: copy a fixed length instead of the
-         user-supplied number.
-
-2016-03-23  Werner Koch  <wk@gnupg.org>
-
-       cipher: Check length of supplied tag in _gcry_cipher_gcm_check_tag.
-       + commit 15785bc9fb1787554bf371945ecb191830c15bfd
-       * cipher/cipher-gcm.c (_gcry_cipher_gcm_tag): Check that the provided
-       tag length matches the actual tag length.  Avoid gratuitous return
-       statements.
-
-2016-03-23  Peter Wu  <peter@lekensteyn.nl>
-
-       Fix buffer overrun in gettag for GCM.
-       + commit d3d7bdf8215275b3b20690dfde3f43dbe25b6f85
-       * cipher/cipher-gcm.c: copy a fixed length instead of the user-supplied
-         number.
-
-2016-03-22  Werner Koch  <wk@gnupg.org>
-
-       tests: Add options --fips to keygen for manual tests.
-       + commit d328095dd4de83b839d9d8c4bdbeec0956971016
-       (main): Add option --fips.
-       * tests/keygen.c (check_rsa_keys): Create an 2048 bit key with e=65539
-       because that is valid in FIPS mode.  Check that key generation fails
-       for too short keys in FIPS mode.
-       (check_ecc_keys): Check that key generation fails for Ed25519 keys in
-       FIPS mode.
-
-2016-03-22  Tomáš Mráz  <tmraz@redhat.com>
-
-       rsa: Add FIPS 186-4 compliant RSA probable prime key generator.
-       + commit 5f9b3c2e220ca6d0eaff32324a973ef67933a844
-       * cipher/primegen.c (_gcry_fips186_4_prime_check): New.
-       * cipher/rsa.c (generate_fips): New.
-       (rsa_generate): Use new function in fips mode or with test-parms.
-
-       * tests/keygen.c (check_rsa_keys): Add test using e=65539.
-
-2016-03-20  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix ARM NEON support detection on ARMv6 target.
-       + commit 583919d70763671ed9feeaa14e1f66379aff88cc
-       * configure.ac (gcry_cv_gcc_inline_asm_neon): Use '.arm' directive
-       instead of '.thumb'.
-
-2016-03-18  Werner Koch  <wk@gnupg.org>
-
-       Always require a 64 bit integer type.
-       + commit 897ccd21b7221982806b5c024518f4e989152f14
-       * configure.ac (available_digests_64): Merge with available_digests.
-       (available_kdfs_64): Merge with available_kdfs.
-       <64 bit datatype test>: Bail out if no such type is available.
-       * src/types.h: Emit #error if no u64 can be defined.
-       (PROPERLY_ALIGNED_TYPE): Always add u64 type.
-       * cipher/bithelp.h: Remove all code paths which handle the
-       case of !HAVE_U64_TYPEDEF.
-       * cipher/bufhelp.h: Ditto.
-       * cipher/cipher-ccm.c: Ditto.
-       * cipher/cipher-gcm.c: Ditto.
-       * cipher/cipher-internal.h: Ditto.
-       * cipher/cipher.c: Ditto.
-       * cipher/hash-common.h: Ditto.
-       * cipher/md.c: Ditto.
-       * cipher/poly1305.c: Ditto.
-       * cipher/scrypt.c: Ditto.
-       * cipher/tiger.c: Ditto.
-       * src/g10lib.h: Ditto.
-       * tests/basic.c: Ditto.
-       * tests/bench-slope.c: Ditto.
-       * tests/benchmark.c: Ditto.
-
-2016-03-18  Vitezslav Cizek  <vcizek@suse.com>
-
-       tests: Fix testsuite after the FIPS adjustments.
-       + commit 9ecc2690181ba0bb44f66451a7dce2fc19965793
-       * tests/benchmark.c (ecc_bench): Avoid not approved curves in FIPS.
-       * tests/curves.c (check_get_params): Skip Brainpool curves in FIPS.
-       * tests/keygen.c (check_dsa_keys): Generate 2048 and 3072 bits keys.
-       (check_ecc_keys): Skip Ed25519 in FIPS mode.
-       * tests/random.c (main): Don't switch DRBG in FIPS mode.
-       * tests/t-ed25519.c (main): Ed25519 isn't supported in FIPS mode.
-       * tests/t-kdf.c (check_openpgp): Skip vectors using md5 in FIPS.
-       * tests/t-mpi-point.c (context_param): Skip P-192 and Ed25519 in FIPS.
-       (main): Skip math tests that use P-192 and Ed25519 in FIPS.
-
-       tests: Add new --pss option to fipsdrv.
-       + commit 1a02d741cacc3b57fe3d6ffebd794d53a60c9e97
-       * tests/fipsdrv.c (run_rsa_sign, run_rsa_verify): Set salt-length
-       to 0 for PSS.
-
-       cipher: Add option to specify salt length for PSS verification.
-       + commit 0bd8137e68c201b6c2290710e348aaf57efa2b2e
-       * cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi): Check for
-       salt-length token.
-
-       tests: Add support for RSA keygen tests to fipsdrv.
-       + commit 2e139456369a834cf87d983da4f61241fda76efe
-       * tests/fipsdrv.c (run_rsa_keygen): New.
-       (main): Support RSA keygen and RSA keygen KAT tests.
-
-       tests: Fixes for RSA testsuite in FIPS mode.
-       + commit c690230af5a66b809f8f6fbab1a6262a5ba078cb
-       * tests/basic.c (get_keys_new): Generate 2048 bit key.
-       * tests/benchmark.c (rsa_bench): Skip keys of lengths different
-       than 2048 and 3072 in FIPS mode.
-       * tests/keygen.c (check_rsa_keys): Failure if short keys can be
-       generated in FIPS mode.
-       (check_dsa_keys): Ditto for DSA keys.
-       * tests/pubkey.c (check_x931_derived_key): Skip keys < 2048 in FIPS.
-
-       rsa: Use 2048 bit RSA keys for selftest.
-       + commit 78cec8b4754fdf774edb2d575000cb3e972e244c
-       * cipher/rsa.c (selftests_rsa): Use 2048 bit keys.
-       (selftest_encr_1024): Replaced by selftest_encr_2048.
-       (selftest_sign_1024): Replaced by selftest_sign_2048.
-       (selftest_encr_2048): Add check against known ciphertext.
-       (selftest_sign_2048): Add check against known signature.
-       (selftest_sign_2048): Free SIG_MPI.
-       * tests/pubkey.c (get_keys_new): Generate 2048 bit keys.
-
-       Disable non-allowed algorithms in FIPS mode.
-       + commit ce1cbe16992a7340edcf8e6576973e3508267640
-       * cipher/cipher.c (_gcry_cipher_init),
-       * cipher/mac.c (_gcry_mac_init),
-       * cipher/md.c (_gcry_md_init),
-       * cipher/pubkey.c (_gcry_pk_init): In the FIPS mode, disable all the
-       non-allowed ciphers.
-       * cipher/md5.c: Mark MD5 as not allowed in FIPS.
-       * src/g10lib.h (_gcry_mac_init): New.
-       * src/global.c (global_init): Call the new _gcry_mac_init.
-       * tests/basic.c (check_ciphers): Fix a typo.
-
-2016-03-18  Werner Koch  <wk@gnupg.org>
-
-       kdf: Make PBKDF2 check work on all platforms.
-       + commit c478cf175887c84dc071c4f73a7667603b354789
-       * cipher/kdf.c (_gcry_kdf_pkdf2): Chnage DKLEN to unsigned long.
-
-2016-03-18  Vitezslav Cizek  <vcizek@suse.com>
-
-       kdf: Add upper bound for derived key length in PBKDF2.
-       + commit 0f741b0704bac5c0e2d2a0c2b34b44b35baa76d6
-       * cipher/kdf.c (_gcry_kdf_pkdf2): limit dkLen.
-
-       ecc: ECDSA adjustments for FIPS 186-4.
-       + commit a242e3d9185e6e2dc13902ea9331131755bbba01
-       * cipher/ecc-curves.c: Unmark curve P-192 for FIPS.
-       * cipher/ecc.c: Add ECDSA self test.
-       * cipher/pubkey-util.c (_gcry_pk_util_init_encoding_ctx): Use SHA-2
-       in FIPS mode.
-       * tests/fipsdrv.c: Add support for ECDSA signatures.
-
-2016-03-18  Werner Koch  <wk@gnupg.org>
-
-       dsa: Make regression tests work.
-       + commit e40939b2141306238cc30a340b867b60fa4dc2a3
-       * cipher/dsa.c (sample_secret_key_1024): Comment out unused constant.
-       (ogenerate_fips186): Make it work with use-fips183-2 flag.
-       * cipher/primegen.c (_gcry_generate_fips186_3_prime): Use Emacs
-       standard comment out format.
-       * tests/fips186-dsa.c (check_dsa_gen_186_3): New dummy fucntion.
-       (main): Call it.
-       (main): Compare against current version.
-       * tests/pubkey.c (get_dsa_key_fips186_new): Create 2048 bit key.
-       (get_dsa_key_fips186_with_seed_new): Ditto.
-       (get_dsa_key_fips186_with_domain_new): Comment out.
-       (check_run): Do not call that function.
-
-2016-03-18  Vitezslav Cizek  <vcizek@suse.com>
-
-       dsa: Adjustments to conform with FIPS 186-4.
-       + commit 80e9f95e6f419daa765e4876c858e3e36e808897
-       * cipher/dsa.c (generate_fips186): FIPS 186-4 adjustments.
-       * cipher/primegen.c (_gcry_generate_fips186_3_prime): Fix incorrect
-         buflen passed to _gcry_mpi_scan.
-
-2016-03-16  Justus Winter  <justus@g10code.com>
-
-       Update documentation for 'gcry_sexp_extract_param'.
-       + commit 4051fe7fec6ffdc7a2f5c3856665478866991ee7
-       * doc/gcrypt.texi (gcry_sexp_extract_param): Mention that all MIPs
-       must be set to NULL first, and document how the function behaves in
-       case of errors.
-       * src/sexp.c (_gcry_sexp_extract_param): Likewise.
-       * src/gcrypt.h.in (gcry_sexp_extract_param): Copy the comment from
-       '_gcry_sexp_extract_param'.
-
-       cipher: Update comment.
-       + commit fcf4358a7a7ba8d32bf385ea99ced5f47cbd3ae2
-       * cipher/ecc.c (ecc_get_nbits): Update comment to reflect the fact
-       that a curve parameter can be given.
-
-2016-03-12  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add Intel PCLMUL implementations of CRC algorithms.
-       + commit 5d601dd57fcb41aa2015ab655fd6fc51537da667
-       * cipher/Makefile.am: Add 'crc-intel-pclmul.c'.
-       * cipher/crc-intel-pclmul.c: New.
-       * cipher/crc.c (USE_INTEL_PCLMUL): New macro.
-       (CRC_CONTEXT) [USE_INTEL_PCLMUL]: Add 'use_pclmul'.
-       [USE_INTEL_PCLMUL] (_gcry_crc32_intel_pclmul)
-       (gcry_crc24rfc2440_intel_pclmul): New.
-       (crc32_init, crc32rfc1510_init, crc24rfc2440_init)
-       [USE_INTEL_PCLMUL]: Select PCLMUL implementation if SSE4.1 and PCLMUL
-       HW features detected.
-       (crc32_write, crc24rfc2440_write) [USE_INTEL_PCLMUL]: Use PCLMUL
-       implementation if enabled.
-       (crc24_init): Document storage format of 24-bit CRC.
-       (crc24_next4): Use only 'data' for last table look-up.
-       * configure.ac: Add 'crc-intel-pclmul.lo'.
-       * src/g10lib.h (HWF_*, HWF_INTEL_SSE4_1): Update HWF flags to include
-       Intel SSE4.1.
-       * src/hwf-x86.c (detect_x86_gnuc): Add SSE4.1 detection.
-       * src/hwfeatures.c (hwflist): Add 'intel-sse4.1'.
-       * tests/basic.c (fillbuf_count): New.
-       (check_one_md): Add "?" check (million byte data-set with byte pattern
-       0x00,0x01,0x02,...); Test all buffer sizes 1 to 1000, for "!" and "?"
-       checks.
-       (check_one_md_multi): Skip "?".
-       (check_digests): Add "?" test-vectors for MD5, SHA1, SHA224, SHA256,
-       SHA384, SHA512, SHA3_224, SHA3_256, SHA3_384, SHA3_512, RIPEMD160,
-       CRC32, CRC32_RFC1510, CRC24_RFC2440, TIGER1 and WHIRLPOOL; Add "!"
-       test-vectors for CRC32_RFC1510 and CRC24_RFC2440.
-
-2016-02-25  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: Normalize EXPO for mpi_powm.
-       + commit fdfa5bfefdde316688a3c8021bd3528c5273b0f4
-       * mpi/mpi-pow.c (gcry_mpi_powm): Normalize EP.
-
-2016-02-22  Andreas Metzler  <ametzler@bebt.de>
-
-       Do not ship generated header file in tarball.
-       + commit 2b40a16333fa75f1cee85ab901a5aa9cff845a92
-       * src/Makefile.am: Move gcrypt.h from include_HEADERS to
-         nodist_include_HEADERS to prevent inclusion in release tarball.
-         This could break out-of-tree-builds because the potentially outdated
-         src/gcrypt.h was not updated but was in the compiler search path.
-
-2016-02-20  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix building random-drbg for Win32/64.
-       + commit 531b25aa94c58f6d2168a9537c8cea6c53d7bbe0
-       * random/random-drbg.c: Remove include for sys/types.h and asm/types.h.
-       (DRBG_PREDICTION_RESIST, DRBG_CTRAES, DRBG_CTRSERPENT, DRBG_CTRTWOFISH)
-       (DRBG_HASHSHA1, DRBG_HASHSHA224, DRBG_HASHSHA256, DRBG_HASHSHA384)
-       (DRBG_HASHSHA512, DRBG_HMAC, DRBG_SYM128, DRBG_SYM192)
-       (DRBG_SYM256): Change 'u_int32_t' to 'u32'.
-       (drbg_get_entropy) [USE_RNDUNIX, USE_RNDW32]: Fix parameters
-       'drbg_read_cb' and 'len'.
-
-2016-02-20  Werner Koch  <wk@gnupg.org>
-
-       tests: Do not test DRBG_REINIT from "make check"
-       + commit 839d12c221430b60db5e0d6fbb107f22e0a6837f
-       * tests/random.c (main): Run check_drbg_reinit only if the envvar
-       GCRYPT_IN_REGRESSION_TEST is set.
-
-       doc: Fix possible dependency problem.
-       + commit 3b57e5a1ba68e26dcaea38b763287fddba9b6b7c
-       * doc/Makefile.am (gcrypt.texi): Use the right traget.
-
-2016-02-19  Stephan Mueller  <smueller@chronox.de>
-
-       random: Remove ANSI X9.31 DRNG.
-       + commit e9b692d25d1c149b5417b70e18f2ce173bc25b6d
-       * random-fips.c: Remove.
-
-2016-02-19  Werner Koch  <wk@gnupg.org>
-
-       random: Add a test case for DRBG_REINIT.
-       + commit 934ba2ae5a95a96fdbb3b935b51ba43df66f11df
-       * src/global.c (_gcry_vcontrol) <DRBG_REINIT>: Test for FIPS RNG.
-       * tests/random.c (check_drbg_reinit): New.
-       (main): Call new test.
-
-       random: Allow DRBG_REINIT before initialization.
-       + commit 7cdbd6e6a3cf1ee366b981e148d41b1187a6fdcf
-       * random/random-drbg.c (DRBG_DEFAULT_TYPE): New.
-       (_drbg_init_internal): Set the default type if no type has been set
-       before.
-       (_gcry_rngdrbg_inititialize): Pass 0 for flags to use the default.
-
-       Add new private header gcrypt-testapi.h.
-       + commit 744b030cff61fd25114b0b25394c62782c153343
-       * src/gcrypt-testapi.h: New.
-       * src/Makefile.am (libgcrypt_la_SOURCES): Add new file.
-       * random/random.h: Include gcrypt-testapi.h.
-       (struct gcry_drbg_test_vector) : Move to gcrypt-testapi.h.
-       * src/global.c: Include gcrypt-testapi.h.
-       (_gcry_vcontrol): Use PRIV_CTL_* constants instead of 58, 59, 60, 61.
-       * cipher/cipher.c: Include gcrypt-testapi.h.
-       (_gcry_cipher_ctl): Use PRIV_CIPHERCTL_ constants instead of 61, 62.
-       * tests/fipsdrv.c: Include gcrypt-testapi.h.  Remove definition of
-       PRIV_CTL_ constants and replace their use by the new PRIV_CIPHERCTL_
-       constants.
-       * tests/t-lock.c: Include gcrypt-testapi.h.  Remove
-       PRIV_CTL_EXTERNAL_LOCK_TEST and EXTERNAL_LOCK_TEST_ constants.
-
-       * random/random-drbg.c (gcry_rngdrbg_cavs_test): Rename to ...
-       (_gcry_rngdrbg_cavs_test): this.
-       (gcry_rngdrbg_healthcheck_one): Rename to ...
-       (_gcry_rngdrbg_healthcheck_one): this.
-
-       random: Make the DRBG C-90 clean and use a flag string.
-       + commit 95f1db3affb9f5b8a2c814c211d4a02b30446c15
-       * random/random.h (struct gcry_drbg_test_vector): Rename "flags" to
-       "flagstr" and turn it into a string.
-       * random/random-drbg.c (drbg_test_pr, drbg_test_nopr): Replace use of
-       designated initializers.  Use a string for the flags.
-       (gcry_rngdrbg_cavs_test): Parse the flag string into a flag value.
-       (drbg_healthcheck_sanity): Ditto.
-
-       random: Symbol name cleanup for random-drbg.c.
-       + commit 85ed07790552297586258e8fe09b546eee357a8b
-       * random/random-drbg.c: Rename all static objects and macros from
-       "gcry_drbg" to "drbg".
-       (drbg_string_t): New typedef.
-       (drbg_gen_t): New typedef.
-       (drbg_state_t): New typedef.  Replace all "struct drbg_state_s *" by
-       this.
-       (_drbg_init_internal): Replace xcalloc_secure by xtrycalloc_secure so
-       that an error if actually returned.
-       (gcry_rngdrbg_cavs_test): Ditto.
-       (gcry_drbg_healthcheck_sanity): Ditto.
-
-       random: Use our symbol name pattern also for drbg functions.
-       + commit 7cf3c929331133e4381dbceac53d3addd921c929
-       * random/random-drbg.c: Rename global functions from _gcry_drbg_*
-       to _gcry_rngdrbg_*.
-       * random/random.c: Adjust for this change.
-       * src/global.c: Ditto.
-
-       random: Rename drbg.c to random-drbg.c.
-       + commit e49b3f2c10e012509b5930c0df4d6df378d3b9f4
-       * random/drbg.c: Rename to ...
-       * random/random-drbg.c: this.
-       * random/Makefile.am (librandom_la_SOURCES): Adjust accordingly.
-
-       random: Remove the new API introduced by the new DRBG.
-       + commit dfac2b13d0068b2b1b420d77e9771a49964b81c1
-       * src/gcrypt.h.in (struct gcry_drbg_gen): Move to random/drbg.c.
-       (struct gcry_drbg_string): Ditto.
-       (gcry_drbg_string_fill): Ditto.
-       (gcry_randomize_drbg): Remove.
-       * random/drbg.c (parse_flag_string): New.
-       (_gcry_drbg_reinit): Change the way the arguments are passed.
-       * src/global.c (_gcry_vcontrol) <GCRYCTL_DRBG_REINIT>: Change calling
-       convention.
-
-       Add helper function _gcry_strtokenize.
-       + commit 4e134b6e77f558730ec1eceb6b816b0bcfd845e9
-       * src/misc.c (_gcry_strtokenize): New.
-
-2016-02-18  Werner Koch  <wk@gnupg.org>
-
-       random: Remove DRBG constants from the public API.
-       + commit fd13372fa9069d3a72947ea59c57e33637c936bf
-       * src/gcrypt.h.in (GCRY_DRBG_): Remove all new flags to ...
-       * random/drbg.c: here.
-
-2016-02-18  Stephan Mueller  <smueller@chronox.de>
-
-       random: Add SP800-90A DRBG.
-       + commit ed57fed6de1465e02ec5e3bc0affeabdd35e2eb7
-       * random/drbg.c: New.
-       * random/random.c (_gcry_random_initialize): Replace rngfips init by
-       drbg init.
-       (__gcry_random_close_fds): Likewise.
-       (_gcry_random_dump_stats): Likewise.
-       (_gcry_random_is_faked): Likewise.
-       (do_randomize): Likewise.
-       (_gcry_random_selftest): Likewise.
-       (_gcry_create_nonce): Replace rngfips_create_noce by drbg_randomize.
-       (_gcry_random_init_external_test): Remove.
-       (_gcry_random_run_external_test): Remove.
-       (_gcry_random_deinit_external_test): Remove.
-       * random/random.h (struct gcry_drbg_test_vector): New.
-       * src/gcrypt.h.in (struct gcry_drbg_gen): New.
-       (struct gcry_drbg_string): New.
-       (gcry_drbg_string_fill): New.
-       (gcry_randomize_drbg): New.
-       (GCRY_DRBG_): Lots of new macros.
-       * src/global.c (_gcry_vcontrol) <Init external random test>: Turn into
-       a nop.
-       (_gcry_vcontrol) <Deinit external random test>: Ditto.
-       (_gcry_vcontrol) <Run external random test>: Change.
-       (_gcry_vcontrol) <GCRYCTL_DRBG_REINIT>: New.
-
-2016-02-13  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       bufhelp: disable unaligned memory accesses on powerpc.
-       + commit 1da793d089b65ac8c1ead65dacb6b8699f5b6e69
-       * cipher/bufhelp.h (BUFHELP_FAST_UNALIGNED_ACCESS): Disable for
-       __powerpc__ and __powerpc64__.
-
-2016-02-12  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Not validate input point for Curve25519.
-       + commit 7a019bc7ecdbdfdef51094e090ce95e062da9b64
-       * cipher/ecc.c (ecc_decrypt_raw): Curve25519 is an exception.
-
-2016-02-10  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Fix memory leaks on error.
-       + commit b12dd550fd6af687ef95c584d0d8366c34965cc8
-       * cipher/ecc.c (ecc_decrypt_raw): Go to leave to release memory.
-       * mpi/ec.c (_gcry_mpi_ec_curve_point): Likewise.
-
-2016-02-09  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: input validation on ECDH.
-       + commit 23b72901f8a5ba9a78485b235c7a917fbc8faae0
-       * cipher/ecc.c (ecc_decrypt_raw): Validate the point.
-
-2016-02-08  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add ARM assembly implementation of SHA-512.
-       + commit 8353884bc65c820d5bcacaf1ac23cdee72091a09
-       * cipher/Makefile.am: Add 'sha512-arm.S'.
-       * cipher/sha512-arm.S: New.
-       * cipher/sha512.c (USE_ARM_ASM): New.
-       (_gcry_sha512_transform_arm): New.
-       (transform) [USE_ARM_ASM]: Use ARM assembly implementation instead of
-       generic.
-       * configure.ac: Add 'sha512-arm.lo'.
-
-2016-02-03  NIIBE Yutaka  <gniibe@fsij.org>
-
-       tests: Add a test for Curve25519.
-       + commit b8b3361504950689ef1e779fb3357cecf8a9f739
-       * tests/Makefile.am (tests_bin): Add t-cv25519.
-       * tests/t-cv25519.c: New.
-
-2016-02-02  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Fix Curve25519 for data by older implementation.
-       + commit 6cb6df9dddac6ad246002b83c2ce0aaa0ecf30e5
-       * cipher/ecc-misc.c (gcry_ecc_mont_decodepoint): Fix code path for
-       short length data.
-
-       ecc: more fix of Curve25519.
-       + commit 48ba5a50066611ecacea850ced13f5cb66097a81
-       * cipher/ecc-misc.c (gcry_ecc_mont_decodepoint): Fix removing of
-       prefix.  Clear the MSB, according to RFC7748.
-
-       ecc: Fix ECDH of Curve25519.
-       + commit a2f9afcd7fcdafd5951498b07f34957f9766dce9
-       * cipher/ecc-misc.c (_gcry_ecc_mont_decodepoint): Fix calc of NBITS
-       and prefix detection.
-       * cipher/ecc.c (ecc_generate): Use NBITS instead of CTX->NBITS.
-       (ecc_encrypt_raw): Use NBITS from curve instead of from P.
-       Fix rawmpilen calculation.
-       (ecc_decrypt_raw): Likewise.  Add debug output.
-
-2016-01-29  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Improve performance of generic SHA256 implementation.
-       + commit f3e51161036382429c3491c7c881f36c0a653c7b
-       * cipher/sha256.c (R): Let caller do variable shuffling.
-       (Chro, Maj, Sum0, Sum1): Convert from inline functions to macros.
-       (W, I): New.
-       (transform_blk): Unroll round loop; inline message expansion to rounds
-       to make message expansion buffer smaller.
-
-2016-01-28  Werner Koch  <wk@gnupg.org>
-
-       ecc: New API function gcry_mpi_ec_decode_point.
-       + commit 2cf2ca7bb9741ac86e8aa92d8f03b1c5f5938897
-       * mpi/ec.c (_gcry_mpi_ec_decode_point): New.
-       * cipher/ecc-common.h: Move two prototypes to ...
-       * src/ec-context.h: here.
-       * src/gcrypt.h.in (gcry_mpi_ec_decode_point): New.
-       * src/libgcrypt.def (gcry_mpi_ec_decode_point): New.
-       * src/libgcrypt.vers (gcry_mpi_ec_decode_point): New.
-       * src/visibility.c (gcry_mpi_ec_decode_point): New.
-       * src/visibility.h: Add new function.
-
-2016-01-15  Werner Koch  <wk@gnupg.org>
-
-       Fix build problem for rndegd.c.
-       + commit 191c2e4fe2dc0e00f61aa44e011a9596887e6ce1
-       * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Test all RND modules.
-       * random/rndegd.c (_gcry_rndegd_connect_socket)
-       (my_make_filename): Use functions with '_' prefix.
-
-       random: Fix possible AIX problem with sysconf in rndunix.
-       + commit 6303b0e83856ee89374b447e710f0ab2af61caec
-       * random/rndunix.c [HAVE_STDINT_H]: Include stdint.h.
-       (start_gatherer): Detect misbehaving sysconf.
-
-2015-12-27  Werner Koch  <wk@gnupg.org>
-
-       random: Take at max 25% from RDRAND.
-       + commit 5a78e7f15e0dd96a8bf64e2bb142880bf8ea6965
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Change use of
-       RDRAND from 50% to 25%.
-
-2015-12-07  Justus Winter  <justus@g10code.com>
-
-       cipher: Improve error handling.
-       + commit b9c02fbeb7efb7d0593b33485fb30c298291cf80
-       * cipher/ecc.c (ecc_decrypt_raw): Improve error handling.
-
-       cipher: Initialize 'flags'.
-       + commit ca06cd7f77acb317c2649c58918908f043dfe6bd
-       * cipher/ecc.c (ecc_encrypt_raw): Initialize 'flags' to 0.
-
-2015-12-05  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: CHANGE point representation of Curve25519.
-       + commit dd3d06e7f113cf7608f060ceb043262efd0b0c9d
-       * cipher/ecc-misc.c (_gcry_ecc_mont_decodepoint): Decode point with
-       the prefix 0x40, additional 0x00 by MPI handling, and shorter octets
-       by MPI normalization.
-       * cipher/ecc.c (ecc_generate, ecc_encrypt_raw, ecc_decrypt_raw):
-       Always add the prefix 0x40.
-
-2015-12-03  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       chacha20: fix alignment of self-test context.
-       + commit 6fadbcd088e2af3e48407b95d8d0c2a8b7ad6c38
-       * cipher/chacha20.c (selftest): Ensure 16-byte alignment for chacha20
-       context structure.
-
-       salsa20: fix alignment of self-test context.
-       + commit 2cba0dbda462237f55438d4199eccd10c5e3f6ca
-       * cipher/salsa20.c (selftest): Ensure 16-byte alignment for salsa20
-       context structure.
-
-2015-12-02  Justus Winter  <justus@g10code.com>
-
-       random: Drop fake entropy gathering function.
-       + commit d421ac283ec46d0ecaf6278ba4c24843f65fb2fa
-       * random/random-csprng.c (faked_rng): Drop variable.
-       (gather_faked): Drop prototype and function.
-       (initialize): Drop fallback code.
-       (_gcry_rngcsprng_is_faked): Change accordingly.
-
-       random: Fix selection of entropy gathering function.
-       + commit 468a5796ffb1a7776db4004d534376c1b981d740
-       * random/random-csprng.c (getfnc_gather_random): Do return NULL if no
-       usable entropy gathering function is found.  The callsite then
-       installs the fake gather function.
-
-2015-11-26  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: minor improvement of point multiplication.
-       + commit 3658afd09c3b03b4398aaa5748387220c93b1a94
-       * mpi/ec.c (_gcry_mpi_ec_mul_point): Move ec_subm out of the loop.
-
-2015-11-25  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Constant-time multiplication for Weierstrass curve.
-       + commit 88e1358962e902ff1cbec8d53ba3eee46407851a
-       * mpi/ec.c (_gcry_mpi_ec_mul_point): Use simple left-to-right binary
-       method for Weierstrass curve when SCALAR is secure.
-
-       mpi: fix gcry_mpi_swap_cond.
-       + commit f88adee3e1f3e2de7d63f92f90bfb3078afd3b4f
-       * mpi/mpiutil.c (_gcry_mpi_swap_cond): Relax the condition.
-
-       mpi: Fix mpi_set_cond and mpi_swap_cond .
-       + commit 8ad682c412047d3b9196950709dbd7bd14ac8732
-       * mpi/mpiutil.c (_gcry_mpi_set_cond, _gcry_mpi_swap_cond): Don't use
-       the operator of !!, but assume SET/SWAP is 0 or 1.
-
-       ecc: multiplication of Edwards curve to be constant-time.
-       + commit 295b1c3540752af4fc5e6f41480e6db215222fba
-       * mpi/ec.c (_gcry_mpi_ec_mul_point): Use point_swap_cond.
-
-       ecc: Add point_resize and point_swap_cond.
-       + commit b6015176df6bfae107ac82f9baa29ef2c175c9f9
-       * mpi/ec.c (point_resize, point_swap_cond): New.
-       (_gcry_mpi_ec_mul_point): Use point_resize and point_swap_cond.
-
-2015-11-18  Justus Winter  <justus@g10code.com>
-
-       cipher: Fix error handling.
-       + commit 940dc8adc034a6c6c38742f6bfd7d837a532d537
-       * cipher/cipher.c (_gcry_cipher_ctl): Fix error handling.
-
-2015-11-18  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Tweak Keccak for small speed-up.
-       + commit 6571a64331839d7d952292163afbf34c8bef62e0
-       * cipher/keccak_permute_32.h (KECCAK_F1600_PERMUTE_FUNC_NAME): Track
-       rounds with round constant pointer instead of separate round counter.
-       * cipher/keccak_permute_64.h (KECCAK_F1600_PERMUTE_FUNC_NAME): Ditto.
-       (KECCAK_F1600_ABSORB_FUNC_NAME): Tweak lanes pointer increment for bulk
-       absorb loops.
-
-       Update license information for CRC.
-       + commit 15ea0acf8bb0aa307eccc23024a0bd7878fb8080
-       * LICENSES: Remove 'Simple permissive' and 'IETF permissive' licenses
-       for 'cipher/crc.c' as result of rewrite of CRC implementations.
-
-2015-11-17  Justus Winter  <justus@g10code.com>
-
-       Fix typos found using codespell.
-       + commit 0e395944b70c7a92a6437f6bcc14f287c19ce9de
-       * cipher/cipher-ocb.c: Fix typos.
-       * cipher/des.c: Likewise.
-       * cipher/dsa-common.c: Likewise.
-       * cipher/ecc.c: Likewise.
-       * cipher/pubkey.c: Likewise.
-       * cipher/rsa-common.c: Likewise.
-       * cipher/scrypt.c: Likewise.
-       * random/random-csprng.c: Likewise.
-       * random/random-fips.c: Likewise.
-       * random/rndw32.c: Likewise.
-       * src/cipher-proto.h: Likewise.
-       * src/context.c: Likewise.
-       * src/fips.c: Likewise.
-       * src/gcrypt.h.in: Likewise.
-       * src/global.c: Likewise.
-       * src/sexp.c: Likewise.
-       * tests/mpitests.c: Likewise.
-       * tests/t-lock.c: Likewise.
-
-2015-11-01  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Improve performance of Tiger hash algorithms.
-       + commit 89fa74d6b3e58cd4fcd6e0939a35e46cbaca2ea0
-       * cipher/tiger.c (tiger_round, pass, key_schedule): Convert functions
-       to macros.
-       (transform_blk): Pass variable names instead of pointers to 'pass'.
-
-       Add ARMv7/NEON implementation of Keccak.
-       + commit a1cc7bb15473a2419b24ecac765ae0ce5989a13b
-       * cipher/Makefile.am: Add 'keccak-armv7-neon.S'.
-       * cipher/keccak-armv7-neon.S: New.
-       * cipher/keccak.c (USE_64BIT_ARM_NEON): New.
-       (NEED_COMMON64): Select if USE_64BIT_ARM_NEON.
-       [NEED_COMMON64] (round_consts_64bit): Rename to...
-       [NEED_COMMON64] (_gcry_keccak_round_consts_64bit): ...this; Add
-       terminator at end.
-       [USE_64BIT_ARM_NEON] (_gcry_keccak_permute_armv7_neon)
-       (_gcry_keccak_absorb_lanes64_armv7_neon, keccak_permute64_armv7_neon)
-       (keccak_absorb_lanes64_armv7_neon, keccak_armv7_neon_64_ops): New.
-       (keccak_init) [USE_64BIT_ARM_NEON]: Select ARM/NEON implementation
-       if supported by HW.
-       * cipher/keccak_permute_64.h (KECCAK_F1600_PERMUTE_FUNC_NAME): Update
-       to use new round constant table.
-       * configure.ac: Add 'keccak-armv7-neon.lo'.
-
-       Optimize Keccak 64-bit absorb functions.
-       + commit 2857cb89c6dc1c02266600bc1fd2967a3cd5cf88
-       * cipher/keccak.c [USE_64BIT] [__x86_64__] (absorb_lanes64_8)
-       (absorb_lanes64_4, absorb_lanes64_2, absorb_lanes64_1): New.
-       * cipher/keccak.c [USE_64BIT] [!__x86_64__] (absorb_lanes64_8)
-       (absorb_lanes64_4, absorb_lanes64_2, absorb_lanes64_1): New.
-       [USE_64BIT] (KECCAK_F1600_ABSORB_FUNC_NAME): New.
-       [USE_64BIT] (keccak_absorb_lanes64): Remove.
-       [USE_64BIT_SHLD] (KECCAK_F1600_ABSORB_FUNC_NAME): New.
-       [USE_64BIT_SHLD] (keccak_absorb_lanes64_shld): Remove.
-       [USE_64BIT_BMI2] (KECCAK_F1600_ABSORB_FUNC_NAME): New.
-       [USE_64BIT_BMI2] (keccak_absorb_lanes64_bmi2): Remove.
-       * cipher/keccak_permute_64.h (KECCAK_F1600_ABSORB_FUNC_NAME): New.
-
-2015-10-31  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Enable CRC test vectors with zero bytes.
-       + commit 07e4839e75a7bca3a6c0a94aecfe75efe61d7ff2
-       * tests/basic.c (check_digests): Enable CRC test-vectors with zero
-       bytes.
-
-       Keccak: Add SHAKE Extendable-Output Functions.
-       + commit c0b9eee2d93a13930244f9ce0c14ed6b4aeb6c29
-       * src/hash-common.c (_gcry_hash_selftest_check_one): Add handling for
-       XOFs.
-       * src/keccak.c (keccak_ops_t): Rename 'extract_inplace' to 'extract'
-       and add 'pos' argument.
-       (KECCAK_CONTEXT): Add 'suffix'.
-       (keccak_extract_inplace64): Rename to...
-       (keccak_extract64): ...this; Add handling for 'pos' argument.
-       (keccak_extract_inplace32bi): Rename to...
-       (keccak_extract32bi): ...this; Add handling for 'pos' argument.
-       (keccak_extract_inplace64): Rename to...
-       (keccak_extract64): ...this; Add handling for 'pos' argument.
-       (keccak_extract_inplace32bi_bmi2): Rename to...
-       (keccak_extract32bi_bmi2): ...this; Add handling for 'pos' argument.
-       (keccak_init): Setup 'suffix'; add SHAKE128 & SHAKE256.
-       (shake128_init, shake256_init): New.
-       (keccak_final): Do not initial permute for SHAKE output; use correct
-       suffix for SHAKE.
-       (keccak_extract): New.
-       (keccak_selftests_keccak): Add SHAKE128 & SHAKE256 test-vectors.
-       (run_selftests): Add SHAKE128 & SHAKE256.
-       (shake128_asn, oid_spec_shake128, shake256_asn, oid_spec_shake256)
-       (_gcry_digest_spec_shake128, _gcry_digest_spec_shake256): New.
-       * cipher/md.c (digest_list): Add SHAKE128 & SHAKE256.
-       * doc/gcrypt.texi: Ditto.
-       * src/cipher.h (_gcry_digest_spec_shake128)
-       (_gcry_digest_spec_shake256): New.
-       * src/gcrypt.h.in (GCRY_MD_SHAKE128, GCRY_MD_SHAKE256): New.
-       * tests/basic.c (check_one_md): Add XOF check; Add 'elen' argument.
-       (check_one_md_multi): Skip if algo is XOF.
-       (check_digests): Add SHAKE128 & SHAKE256 test vectors.
-       * tests/bench-slope.c (kdf_bench_one): Skip XOFs.
-
-       Few updates to documentation.
-       + commit 28de6f9e16e386018e81a9cdaee596be7616ccab
-       * doc/gcrypt.text: Add mention of new 'intel-fast-shld' hw feature
-       flag; Add mention of x86 RDRAND support in rndhw.
-
-       Add HMAC-SHA3 test vectors.
-       + commit 92ad19873562cfce7bcc4a0b5aed8195d8284cfc
-       * tests/basic.c (check_mac): Add HMAC_SHA3 test vectors.
-
-2015-10-28  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       md: add variable length output interface.
-       + commit 577dc2b63ceca6a8a716256d034ea4e7414f65fa
-       * cipher/crc.c (_gcry_digest_spec_crc32)
-       (_gcry_digest_spec_crc32_rfc1510, _gcry_digest_spec_crc24_rfc2440): Set
-       'extract' NULL.
-       * cipher/gostr3411-94.c (_gcry_digest_spec_gost3411_94)
-       (_gcry_digest_spec_gost3411_cp): Ditto.
-       * cipher/keccak.c (_gcry_digest_spec_sha3_224)
-       (_gcry_digest_spec_sha3_256, _gcry_digest_spec_sha3_384)
-       (_gcry_digest_spec_sha3_512): Ditto.
-       * cipher/md2.c (_gcry_digest_spec_md2): Ditto.
-       * cipher/md4.c (_gcry_digest_spec_md4): Ditto.
-       * cipher/md5.c (_gcry_digest_spec_md5): Ditto.
-       * cipher/rmd160.c (_gcry_digest_spec_rmd160): Ditto.
-       * cipher/sha1.c (_gcry_digest_spec_sha1): Ditto.
-       * cipher/sha256.c (_gcry_digest_spec_sha224)
-       (_gcry_digest_spec_sha256): Ditto.
-       * cipher/sha512.c (_gcry_digest_spec_sha384)
-       (_gcry_digest_spec_sha512): Ditto.
-       * cipher/stribog.c (_gcry_digest_spec_stribog_256)
-       (_gcry_digest_spec_stribog_512): Ditto.
-       * cipher/tiger.c (_gcry_digest_spec_tiger)
-       (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): Ditto.
-       * cipher/whirlpool.c (_gcry_digest_spec_whirlpool): Ditto.
-       * cipher/md.c (md_enable): Do not allow combination of HMAC and
-       'expandable-output function'.
-       (md_final): Check if spec->read is NULL before calling.
-       (md_read): Ditto.
-       (md_extract, _gcry_md_extract): New.
-       * doc/gcrypt.texi: Add SHA3 algorithms and gcry_md_extract.
-       * src/cipher-proto.h (gcry_md_extract_t): New.
-       (gcry_md_spec_t): Add 'extract'.
-       * src/gcrypt-int.g (_gcry_md_extract): New.
-       * src/gcrypt.h.in (gcry_md_extract): New.
-       * src/libgcrypt.def: Add gcry_md_extract.
-       * src/libgcrypt.vers: Add gcry_md_extract.
-       * src/visibility.c (gcry_md_extract): New.
-       * src/visibility.h (gcry_md_extract): New.
-
-       md: check hmac flag in prepare_macpads.
-       + commit cee2e122ec6c1886957a8d47498eb63a6a921725
-       * cipher/md.c (prepare_macpads): Check hmac flag.
-
-       keccak: rewrite for improved performance.
-       + commit 74184c28fbe7ff58cf57f0094ef957d94045da7d
-       * cipher/Makefile.am: Add 'keccak_permute_32.h' and
-       'keccak_permute_64.h'.
-       * cipher/hash-common.h [USE_SHA3] (MD_BLOCK_MAX_BLOCKSIZE): Remove.
-       * cipher/keccak.c (USE_64BIT, USE_32BIT, USE_64BIT_BMI2)
-       (USE_64BIT_SHLD, USE_32BIT_BMI2, NEED_COMMON64, NEED_COMMON32BI)
-       (keccak_ops_t): New.
-       (KECCAK_STATE): Add 'state64' and 'state32bi' members.
-       (KECCAK_CONTEXT): Remove 'bctx'; add 'blocksize', 'count' and 'ops'.
-       (rol64, keccak_f1600_state_permute): Remove.
-       [NEED_COMMON64] (round_consts_64bit, keccak_extract_inplace64): New.
-       [NEED_COMMON32BI] (round_consts_32bit, keccak_extract_inplace32bi)
-       (keccak_absorb_lane32bi): New.
-       [USE_64BIT] (ANDN64, ROL64, keccak_f1600_state_permute64)
-       (keccak_absorb_lanes64, keccak_generic64_ops): New.
-       [USE_64BIT_SHLD] (ANDN64, ROL64, keccak_f1600_state_permute64_shld)
-       (keccak_absorb_lanes64_shld, keccak_shld_64_ops): New.
-       [USE_64BIT_BMI2] (ANDN64, ROL64, keccak_f1600_state_permute64_bmi2)
-       (keccak_absorb_lanes64_bmi2, keccak_bmi2_64_ops): New.
-       [USE_32BIT] (ANDN64, ROL64, keccak_f1600_state_permute32bi)
-       (keccak_absorb_lanes32bi, keccak_generic32bi_ops): New.
-       [USE_32BIT_BMI2] (ANDN64, ROL64, keccak_f1600_state_permute32bi_bmi2)
-       (pext, pdep, keccak_absorb_lane32bi_bmi2, keccak_absorb_lanes32bi_bmi2)
-       (keccak_extract_inplace32bi_bmi2, keccak_bmi2_32bi_ops): New.
-       (keccak_write): New.
-       (keccak_init): Adjust to KECCAK_CONTEXT changes; add implementation
-       selection based on HWF features.
-       (keccak_final): Adjust to KECCAK_CONTEXT changes; use selected 'ops'
-       for state manipulation.
-       (keccak_read): Adjust to KECCAK_CONTEXT changes.
-       (_gcry_digest_spec_sha3_224, _gcry_digest_spec_sha3_256)
-       (_gcry_digest_spec_sha3_348, _gcry_digest_spec_sha3_512): Use
-       'keccak_write' instead of '_gcry_md_block_write'.
-       * cipher/keccak_permute_32.h: New.
-       * cipher/keccak_permute_64.h: New.
-
-       hwf-x86: add detection for Intel CPUs with fast SHLD instruction.
-       + commit 909644ef5883927262366c356eed530e55aba478
-       * cipher/sha1.c (sha1_init): Use HWF_INTEL_FAST_SHLD instead of
-       HWF_INTEL_CPU.
-       * cipher/sha256.c (sha256_init, sha224_init): Ditto.
-       * cipher/sha512.c (sha512_init, sha384_init): Ditto.
-       * src/g10lib.h (HWF_INTEL_FAST_SHLD): New.
-       (HWF_INTEL_BMI2, HWF_INTEL_SSSE3, HWF_INTEL_PCLMUL, HWF_INTEL_AESNI)
-       (HWF_INTEL_RDRAND, HWF_INTEL_AVX, HWF_INTEL_AVX2)
-       (HWF_ARM_NEON): Update.
-       * src/hwf-x86.c (detect_x86_gnuc): Add detection of Intel Core
-       CPUs with fast SHLD/SHRD instruction.
-       * src/hwfeatures.c (hwflist): Add "intel-fast-shld".
-
-       Fix OCB amd64 assembly implementations for x32.
-       + commit 16fd540f4d01eb6dc23d9509ae549353617c7a67
-       * cipher/camellia-glue.c (_gcry_camellia_aesni_avx_ocb_enc)
-       (_gcry_camellia_aesni_avx_ocb_dec, _gcry_camellia_aesni_avx_ocb_auth)
-       (_gcry_camellia_aesni_avx2_ocb_enc, _gcry_camellia_aesni_avx2_ocb_dec)
-       (_gcry_camellia_aesni_avx2_ocb_auth, _gcry_camellia_ocb_crypt)
-       (_gcry_camellia_ocb_auth): Change 'Ls' from pointer array to u64 array.
-       * cipher/serpent.c (_gcry_serpent_sse2_ocb_enc)
-       (_gcry_serpent_sse2_ocb_dec, _gcry_serpent_sse2_ocb_auth)
-       (_gcry_serpent_avx2_ocb_enc, _gcry_serpent_avx2_ocb_dec)
-       (_gcry_serpent_ocb_crypt, _gcry_serpent_ocb_auth): Ditto.
-       * cipher/twofish.c (_gcry_twofish_amd64_ocb_enc)
-       (_gcry_twofish_amd64_ocb_dec, _gcry_twofish_amd64_ocb_auth)
-       (twofish_amd64_ocb_enc, twofish_amd64_ocb_dec, twofish_amd64_ocb_auth)
-       (_gcry_twofish_ocb_crypt, _gcry_twofish_ocb_auth): Ditto.
-
-       bench-slope: add KDF/PBKDF2 benchmark.
-       + commit ae40af427fd2a856b24ec2a41323ec8b80ffc9c0
-       * tests/bench-slope.c (bench_kdf_mode, bench_kdf_init, bench_kdf_free)
-       (bench_kdf_do_bench, kdf_ops, kdf_bench_one, kdf_bench): New.
-       (print_help): Add 'kdf'.
-       (main): Add KDF benchmarks.
-
-2015-10-22  NIIBE Yutaka  <gniibe@fsij.org>
-
-       md: keep contexts for HMAC in GcryDigestEntry.
-       + commit f7505b550dd591e33d3a3fab9277c43c460f1bad
-       * cipher/md.c (struct gcry_md_context): Add flags.hmac.
-       Remove macpads and mcpads_Bsize.
-       (md_open): Initialize flags.hmac.  Remove macpads initialization.
-       (md_enable): Allocate contexts when flags.hmac is enabled.
-       (md_copy): Remove macpads copying.  Add copying contexts.
-       (_gcry_md_reset): When flags.hmac is enabled, restore precomputed
-       context with input pad
-       (md_close): Remove macpads wiping.
-       (md_final): When flags.hmac is enabled, compute hmac by precomputed
-       context with output pad.
-       (prepare_macpads): Prepare precomputed contexts with input pad and
-       output pad for each registered digest entry.
-       (_gcry_md_setkey): Just call prepare_macpads.
-
-2015-10-15  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Fix double free on error.
-       + commit 1c6d2698a84e4bf82735287c1d64954bfc1a1982
-       * src/hmac256.c (_gcry_hmac256_finalize): Don't free HD.
-
-2015-10-14  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Fix gpg_error_t and gpg_err_code_t confusion.
-       + commit 813565a07ca575c87e1252c6ed26018653ecd338
-       * src/gcrypt-int.h (_gcry_sexp_extract_param): Revert the change.
-       * cipher/dsa.c (dsa_check_secret_key): Ditto.
-       * src/sexp.c (_gcry_sexp_extract_param): Return gpg_err_code_t.
-
-       * src/gcrypt-int.h (_gcry_err_make_from_errno)
-       (_gcry_error_from_errno): Return gpg_error_t.
-       * cipher/cipher.c (_gcry_cipher_open_internal)
-       (_gcry_cipher_ctl, _gcry_cipher_ctl): Don't use gcry_error.
-       * src/global.c (_gcry_vcontrol): Likewise.
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_genkey): Use
-        gpg_err_code_from_syserror.
-       * cipher/mac.c (mac_reset, mac_setkey, mac_setiv, mac_write)
-       (mac_read, mac_verify): Return gcry_err_code_t.
-       * cipher/rsa-common.c (mgf1): Use gcry_err_code_t for ERR.
-       * src/visibility.c (gcry_error_from_errno): Return gpg_error_t.
-
-2015-10-13  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix compiling AES/AES-NI implementation on linux-i386.
-       + commit fa94b6111948a614ebdcb67f7942eced8b84c579
-       * cipher/rijndael-aesni.c (do_aesni_ctr_4): Split assembly block in
-       two parts to reduce number of register constraints needed.
-
-2015-10-13  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Fix declaration of return type.
-       + commit 73374fdd27c7ba28b19f9672c68a6f5b72252fe5
-       * src/gcrypt-int.h (_gcry_sexp_extract_param): Return gpg_error_t.
-       * cipher/dsa.c (dsa_generate): Fix call to _gcry_sexp_extract_param.
-       * src/g10lib.h (_gcry_vcontrol): Return gcry_err_code_t.
-       * src/visibility.c (gcry_mpi_snatch): Fix call to _gcry_mpi_snatch.
-
-2015-09-07  Werner Koch  <wk@gnupg.org>
-
-       Improve GCRYCTL_DISABLE_PRIV_DROP by also disabling cap_ calls.
-       + commit 3a3d5410cc83f7069c7cb1ab384905f382292d32
-       * src/secmem.c (lock_pool, secmem_init): Do not call any cap_
-       functions if NO_PRIV_DROP is set.
-
-2015-09-04  Werner Koch  <wk@gnupg.org>
-
-       w32: Avoid a few compiler warnings.
-       + commit e97c62a4a687b56d00a2d0a63e072a977f8eb81c
-       * cipher/cipher-selftest.c (_gcry_selftest_helper_cbc)
-       (_gcry_selftest_helper_cfb, _gcry_selftest_helper_ctr): Mark variable
-       as unused.
-       * random/rndw32.c (slow_gatherer): Avoid signed pointer mismatch
-       warning.
-       * src/secmem.c (init_pool): Avoid unused variable warning.
-       * tests/random.c (writen, readn): Include on if needed.
-
-       w32: Fix alignment problem with AESNI on Windows >= 8.
-       + commit e2785a2268702312529521df3bd2f4e6b43cea3a
-       * cipher/cipher-selftest.c (_gcry_cipher_selftest_alloc_ctx): New.
-       * cipher/rijndael.c (selftest_basic_128, selftest_basic_192)
-       (selftest_basic_256): Allocate context on the heap.
-
-2015-08-31  Werner Koch  <wk@gnupg.org>
-
-       rsa: Add verify after sign to avoid Lenstra's CRT attack.
-       + commit c17f84bd02d7ee93845e92e20f6ddba814961588
-       * cipher/rsa.c (rsa_sign): Check the CRT.
-
-       Add pubkey algo id for EdDSA.
-       + commit dd87639abd38afc91a6f27af33f0ba17402ad02d
-       * src/gcrypt.h.in (GCRY_PK_EDDSA): New.
-
-2015-08-25  Werner Koch  <wk@gnupg.org>
-
-       Add configure option --enable-build-timestamp.
-       + commit a785cc3db0c4e8eb8ebbf784b833a40d2c42ec3e
-       * configure.ac (BUILD_TIMESTAMP): Set to "<none>" by default.
-
-2015-08-23  Werner Koch  <wk@gnupg.org>
-
-       tests: Add missing files for the make distcheck target.
-       + commit fb3cb47b0a29d3e73150297aa4495c20915e4a75
-       * tests/Makefile.am (EXTRA_DIST): Add sha3-x test vector files.
-
-2015-08-19  Werner Koch  <wk@gnupg.org>
-
-       Change SHA-3 algorithm ids.
-       + commit 65639ecaaeba642e40487446c40d045482001285
-       * src/gcrypt.h.in (GCRY_MD_SHA3_224, GCRY_MD_SHA3_256)
-       (GCRY_MD_SHA3_384, GCRY_MD_SHA3_512): Change values.
-
-2015-08-12  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Keccak: Fix array indexes in θ step.
-       + commit 48822ae0b436bcea0fe92dbf0d88475ba3179320
-       * cipher/keccak.c (keccak_f1600_state_permute): Fix indexes for D[5].
-
-       Simplify OCB offset calculation for parallel implementations.
-       + commit 24ebf53f1e8a8afa27dcd768339bda70a740bb03
-       * cipher/camellia-glue.c (_gcry_camellia_ocb_crypt)
-       (_gcry_camellia_ocb_auth): Precalculate Ls array always, instead of
-       just if 'blkn % <parallel blocks> == 0'.
-       * cipher/serpent.c (_gcry_serpent_ocb_crypt)
-       (_gcry_serpent_ocb_auth): Ditto.
-       * cipher/rijndael-aesni.c (get_l): Remove low-bit checks.
-       (aes_ocb_enc, aes_ocb_dec, _gcry_aes_aesni_ocb_auth): Handle leading
-       blocks until block counter is multiple of 4, so that parallel block
-       processing loop can use 'c->u_mode.ocb.L' array directly.
-       * tests/basic.c (check_ocb_cipher_largebuf): Rename to...
-       (check_ocb_cipher_largebuf_split): ...this and add option to process
-       large buffer as two split buffers.
-       (check_ocb_cipher_largebuf): New.
-
-       Add carryless 8-bit addition fast-path for AES-NI CTR mode.
-       + commit e11895da1f4af9782d89e92ba2e6b1a63235b54b
-       * cipher/rijndael-aesni.c (do_aesni_ctr_4): Do addition using
-       CTR in big-endian form, if least-significant byte does not overflow.
-
-2015-08-10  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add additional SHA3 test-vectors.
-       + commit 80321eb3a63a20f86734d6eebb3f419c0ec895aa
-       * tests/basic.c (check_digests): Allow datalen to be specified so that
-       input data can have byte with value 0x00; Include sha3-*.h header files
-       to test-vector structure.
-       * tests/sha3-224.h: New.
-       * tests/sha3-256.h: New.
-       * tests/sha3-384.h: New.
-       * tests/sha3-512.h: New.
-
-       Add generic SHA3 implementation.
-       + commit 434ba17d1d5ad59c70d721ad3ecb376c2403a7e5
-       * cipher/hash-common.h (MD_BLOCK_MAX_BLOCKSIZE): Increase blocksize
-       USE_SHA3 enabled.
-       * cipher/keccak.c (SHA3_DELIMITED_SUFFIX, SHAKE_DELIMITED_SUFFIX): New.
-       (KECCAK_STATE): Add proper state.
-       (KECCAK_CONTEXT): Add 'outlen'.
-       (rol64, keccak_f1600_state_permute, transform_blk, transform): New.
-       (keccak_init): Add proper initialization.
-       (keccak_final): Add proper finalization.
-       (selftests_keccak): Add selftests.
-       (oid_spec_sha3_224, oid_spec_sha3_256, oid_spec_sha3_384)
-       (oid_spec_sha3_512): Add OID.
-       (_gcry_digest_spec_sha3_224, _gcry_digest_spec_sha3_256)
-       (_gcry_digest_spec_sha3_384, _gcry_digest_spec_sha3_512): Fix output
-       length.
-       * cipher/mac-hmac.c (map_mac_algo_to_md): Fix mapping for SHA3-512.
-       (hmac_get_keylen): Return proper blocksizes for SHA3 algorithms.
-       [USE_SHA3] (_gcry_mac_type_spec_hmac_sha3_224)
-       (_gcry_mac_type_spec_hmac_sha3_256, _gcry_mac_type_spec_hmac_sha3_384)
-       (_gcry_mac_type_spec_hmac_sha3_512): New.
-       * cipher/mac-internal [USE_SHA3] (_gcry_mac_type_spec_hmac_sha3_224)
-       (_gcry_mac_type_spec_hmac_sha3_256, _gcry_mac_type_spec_hmac_sha3_384)
-       (_gcry_mac_type_spec_hmac_sha3_512): New.
-       * cipher/mac.c (mac_list) [USE_SHA3]: Add SHA3 algorithms.
-       * cipher/md.c (md_open): Use proper SHA-3 blocksizes for HMAC macpads.
-       * tests/basic.c (check_digests): Add SHA3 test vectors.
-
-       Optimize OCB offset calculation.
-       + commit 49f52c67fb42c0656c8f9af655087f444562ca82
-       * cipher/cipher-internal.h (ocb_get_l): New.
-       * cipher/cipher-ocb.c (_gcry_cipher_ocb_authenticate)
-       (ocb_crypt): Use 'ocb_get_l' instead of '_gcry_cipher_ocb_get_l'.
-       * cipher/camellia-glue.c (get_l): Remove.
-       (_gcry_camellia_ocb_crypt, _gcry_camellia_ocb_auth): Precalculate
-       offset array when block count matches parallel operation size; Use
-       'ocb_get_l' instead of 'get_l'.
-       * cipher/rijndael-aesni.c (get_l): Add fast path for 75% most common
-       offsets.
-       (aesni_ocb_enc, aesni_ocb_dec, _gcry_aes_aesni_ocb_auth): Precalculate
-       offset array when block count matches parallel operation size.
-       * cipher/rijndael-ssse3-amd64.c (get_l): Add fast path for 75% most
-       common offsets.
-       * cipher/rijndael.c (_gcry_aes_ocb_crypt, _gcry_aes_ocb_auth): Use
-       'ocb_get_l' instead of '_gcry_cipher_ocb_get_l'.
-       * cipher/serpent.c (get_l): Remove.
-       (_gcry_serpent_ocb_crypt, _gcry_serpent_ocb_auth): Precalculate
-       offset array when block count matches parallel operation size; Use
-       'ocb_get_l' instead of 'get_l'.
-       * cipher/twofish.c (get_l): Remove.
-       (_gcry_twofish_ocb_crypt, _gcry_twofish_ocb_auth): Use 'ocb_get_l'
-       instead of 'get_l'.
-
-2015-08-10  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: fix Montgomery curve bugs.
-       + commit ce746936b6c210e602d106cfbf45cf60b408d871
-       * cipher/ecc.c (check_secret_key): Y1 should not be NULL when check.
-       (ecc_check_secret_key): Support Montgomery curve.
-       * mpi/ec.c (_gcry_mpi_ec_curve_point): Fix condition.
-
-2015-08-08  Werner Koch  <wk@gnupg.org>
-
-       Add framework to eventually support SHA3.
-       + commit 0e17f7a05bba309a87811992aa47a77af9935b99
-       * src/gcrypt.h.in (GCRY_MD_SHA3_224, GCRY_MD_SHA3_256)
-       (GCRY_MD_SHA3_384, GCRY_MD_SHA3_512): New.
-       (GCRY_MAC_HMAC_SHA3_224, GCRY_MAC_HMAC_SHA3_256)
-       (GCRY_MAC_HMAC_SHA3_384, GCRY_MAC_HMAC_SHA3_512): New.
-       * cipher/keccak.c: New with stub functions.
-       * cipher/Makefile.am (EXTRA_libcipher_la_SOURCES): Add keccak.c.
-       * configure.ac (available_digests): Add sha3.
-       (USE_SHA3): New.
-       * src/fips.c (run_hmac_selftests): Add SHA3 to the required selftests.
-       * cipher/md.c (digest_list) [USE_SHA3]: Add standard SHA3 algos.
-       (md_open): Ditto for hmac processing.
-       * cipher/mac-hmac.c (map_mac_algo_to_md): Add mapping.
-       * cipher/hmac-tests.c (run_selftests): Prepare for tests.
-       * cipher/pubkey-util.c (get_hash_algo): Add "sha3-xxx".
-
-2015-08-06  Werner Koch  <wk@gnupg.org>
-
-       tools: Fix memory leak for functions "I" and "G".
-       + commit 10789e3cdda7b944acb4b59624c34a2ccfaea6e5
-       * src/mpicalc.c (do_inv, do_gcd): Init A after stack check.
-
-2015-08-06  Ismo Puustinen  <ismo.puustinen@intel.com>
-
-       ecc: Free memory also when in error branch.
-       + commit 1d896371fbc94c605fce35eabcde01e24dd22892
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_sign): Init DISGEST and goto
-       leave on error.
-
-2015-08-06  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Add Curve25519 support.
-       + commit e93f4c21c59756604440ad8cbf27e67d29c99ffd
-       * cipher/ecc-curves.c (curve_aliases, domain_parms): Add Curve25519.
-       * tests/curves.c (N_CURVES): It's 22 now.
-       * src/cipher.h (PUBKEY_FLAG_DJB_TWEAK): New.
-       * cipher/ecc-common.h (_gcry_ecc_mont_decodepoint): New.
-       * cipher/ecc-misc.c (_gcry_ecc_mont_decodepoint): New.
-       * cipher/ecc.c (nist_generate_key): Handle the case of
-       PUBKEY_FLAG_DJB_TWEAK and Montgomery curve.
-       (test_ecdh_only_keys, check_secret_key): Likewise.
-       (ecc_generate): Support Curve25519 which is Montgomery curve with flag
-       PUBKEY_FLAG_DJB_TWEAK and PUBKEY_FLAG_COMP.
-       (ecc_encrypt_raw): Get flags from KEYPARMS and handle
-       PUBKEY_FLAG_DJB_TWEAK and Montgomery curve.
-       (ecc_decrypt_raw): Likewise.
-       (compute_keygrip): Handle the case of PUBKEY_FLAG_DJB_TWEAK.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist):
-       PUBKEY_FLAG_EDDSA implies PUBKEY_FLAG_DJB_TWEAK.
-       Parse "djb-tweak" for PUBKEY_FLAG_DJB_TWEAK.
-
-2015-07-27  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Reduce code size for Twofish key-setup and remove key dependend branch.
-       + commit b4b1d872ba651bc44761b35d245b1a519a33f515
-       * cipher/twofish.c (poly_to_exp): Increase size by one, change type
-       from byte to u16 and insert '492' to index 0.
-       (exp_to_poly): Increase size by 256, let new cells have zero value.
-       (CALC_S): Execute unconditionally with help of modified tables.
-       (do_twofish_setkey): Change type for 'tmp' to 'unsigned int'; Un-unroll
-       CALC_K256 and CALC_K phases to reduce generated object size.
-
-       Reduce amount of duplicated code in OCB bulk implementations.
-       + commit e950052bc6f5ff11a7c23091ff3f6b5cc431e875
-       * cipher/cipher-ocb.c (_gcry_cipher_ocb_authenticate)
-       (ocb_crypt): Change bulk function to return number of unprocessed
-       blocks.
-       * src/cipher.h (_gcry_aes_ocb_crypt, _gcry_aes_ocb_auth)
-       (_gcry_camellia_ocb_crypt, _gcry_camellia_ocb_auth)
-       (_gcry_serpent_ocb_crypt, _gcry_serpent_ocb_auth)
-       (_gcry_twofish_ocb_crypt, _gcry_twofish_ocb_auth): Change return type
-       to 'size_t'.
-       * cipher/camellia-glue.c (get_l): Only if USE_AESNI_AVX or
-       USE_AESNI_AVX2 defined.
-       (_gcry_camellia_ocb_crypt, _gcry_camellia_ocb_auth): Change return type
-       to 'size_t' and return remaining blocks; Remove unaccelerated common
-       code path. Enable remaining common code only if USE_AESNI_AVX or
-       USE_AESNI_AVX2 defined; Remove unaccelerated common code.
-       * cipher/rijndael.c (_gcry_aes_ocb_crypt, _gcry_aes_ocb_auth): Change
-       return type to 'size_t' and return zero.
-       * cipher/serpent.c (get_l): Only if USE_SSE2, USE_AVX2 or USE_NEON
-       defined.
-       (_gcry_serpent_ocb_crypt, _gcry_serpent_ocb_auth): Change return type
-       to 'size_t' and return remaining blocks; Remove unaccelerated common
-       code path. Enable remaining common code only if USE_SSE2, USE_AVX2 or
-       USE_NEON defined; Remove unaccelerated common code.
-       * cipher/twofish.c (get_l): Only if USE_AMD64_ASM defined.
-       (_gcry_twofish_ocb_crypt, _gcry_twofish_ocb_auth): Change return type
-       to 'size_t' and return remaining blocks; Remove unaccelerated common
-       code path. Enable remaining common code only if USE_AMD64_ASM defined;
-       Remove unaccelerated common code.
-
-       Add bulk OCB for Serpent SSE2, AVX2 and NEON implementations.
-       + commit adbdca0d58f9c06dc3850b95e3455e179c1e6960
-       * cipher/cipher.c (_gcry_cipher_open_internal): Setup OCB bulk
-       functions for Serpent.
-       * cipher/serpent-armv7-neon.S: Add OCB assembly functions.
-       * cipher/serpent-avx2-amd64.S: Add OCB assembly functions.
-       * cipher/serpent-sse2-amd64.S: Add OCB assembly functions.
-       * cipher/serpent.c (_gcry_serpent_sse2_ocb_enc)
-       (_gcry_serpent_sse2_ocb_dec, _gcry_serpent_sse2_ocb_auth)
-       (_gcry_serpent_neon_ocb_enc, _gcry_serpent_neon_ocb_dec)
-       (_gcry_serpent_neon_ocb_auth, _gcry_serpent_avx2_ocb_enc)
-       (_gcry_serpent_avx2_ocb_dec, _gcry_serpent_avx2_ocb_auth): New
-       prototypes.
-       (get_l, _gcry_serpent_ocb_crypt, _gcry_serpent_ocb_auth): New.
-       * src/cipher.h (_gcry_serpent_ocb_crypt)
-       (_gcry_serpent_ocb_auth): New.
-       * tests/basic.c (check_ocb_cipher): Add test-vector for serpent.
-
-       Add bulk OCB for Twofish AMD64 implementation.
-       + commit 7f6804c37c4b41d85fb26aa723b1c41e4a3cf278
-       * cipher/cipher.c (_gcry_cipher_open_internal): Setup OCB bulk
-       functions for Twofish.
-       * cipher/twofish-amd64.S: Add OCB assembly functions.
-       * cipher/twofish.c (_gcry_twofish_amd64_ocb_enc)
-       (_gcry_twofish_amd64_ocb_dec, _gcry_twofish_amd64_ocb_auth): New
-       prototypes.
-       (call_sysv_fn5, call_sysv_fn6, twofish_amd64_ocb_enc)
-       (twofish_amd64_ocb_dec, twofish_amd64_ocb_auth, get_l)
-       (_gcry_twofish_ocb_crypt, _gcry_twofish_ocb_auth): New.
-       * src/cipher.h (_gcry_twofish_ocb_crypt)
-       (_gcry_twofish_ocb_auth): New.
-       * tests/basic.c (check_ocb_cipher): Add test-vector for Twofish.
-
-       Add bulk OCB for Camellia AES-NI/AVX and AES-NI/AVX2 implementations.
-       + commit bb088c6b1620504fdc79e89af27c2bf3fb02b4b4
-       * cipher/camellia-aesni-avx-amd64.S: Add OCB assembly functions.
-       * cipher/camellia-aesni-avx2-amd64.S: Add OCB assembly functions.
-       * cipher/camellia-glue.c (_gcry_camellia_aesni_avx_ocb_enc)
-       (_gcry_camellia_aesni_avx_ocb_dec, _gcry_camellia_aesni_avx_ocb_auth)
-       (_gcry_camellia_aesni_avx2_ocb_enc, _gcry_camellia_aesni_avx2_ocb_dec)
-       (_gcry_camellia_aesni_avx2_ocb_auth): New prototypes.
-       (get_l, _gcry_camellia_ocb_crypt, _gcry_camellia_ocb_auth): New.
-       * cipher/cipher.c (_gcry_cipher_open_internal): Setup OCB bulk
-       functions for Camellia.
-       * src/cipher.h (_gcry_camellia_ocb_crypt)
-       (_gcry_camellia_ocb_auth): New.
-       * tests/basic.c (check_ocb_cipher): Add test-vector for Camellia.
-
-2015-07-26  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add OCB bulk mode for AES SSSE3 implementation.
-       + commit 620e1e0300c79943a1846a49563b04386dc60546
-       * cipher/rijndael-ssse3-amd64.c (SSSE3_STATE_SIZE): New.
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS] (vpaes_ssse3_prepare): Use
-       'ssse3_state' for storing current SSSE3 state.
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS]
-       (vpaes_ssse3_cleanup): Restore SSSE3 state from 'ssse3_state'.
-       (_gcry_aes_ssse3_do_setkey, _gcry_aes_ssse3_prepare_decryption)
-       (_gcry_aes_ssse3_encrypt, _gcry_aes_ssse3_cfb_enc)
-       (_gcry_aes_ssse3_cbc_enc, _gcry_aes_ssse3_ctr_enc)
-       (_gcry_aes_ssse3_decrypt, _gcry_aes_ssse3_cfb_dec)
-       (_gcry_aes_ssse3_cbc_dec, _gcry_aes_ssse3_cbc_dec): Add 'ssse3_state'
-       array.
-       (get_l, ssse3_ocb_enc, ssse3_ocb_dec, _gcry_aes_ssse3_ocb_crypt)
-       (_gcry_aes_ssse3_ocb_auth): New.
-       * cipher/rijndael.c (_gcry_aes_ssse3_ocb_crypt)
-       (_gcry_aes_ssse3_ocb_auth): New.
-       (_gcry_aes_ocb_crypt, _gcry_aes_ocb_auth) [USE_SSSE3]: Use SSSE3
-       implementation for OCB.
-
-2015-07-26  Peter Wu  <peter@lekensteyn.nl>
-
-       Fix undefined behavior wrt memcpy.
-       + commit 46c072669eb81ed610cc5b3c0dc0c75a143afbb4
-       * cipher/cipher-gcm.c: Do not copy zero bytes from an empty buffer. Let
-       the function continue to add padding as needed though.
-       * cipher/mac-poly1305.c: If the caller requested to finish the hash
-       function without a copy of the result, return immediately.
-
-2015-07-23  Peter Wu  <peter@lekensteyn.nl>
-
-       build: ignore scissor line for the commit-msg hook.
-       + commit ada0a7d302cca97b327faaacac7a5d0b8043df88
-       * build-aux/git-hooks/commit-msg: Stop processing more lines when the
-         scissor line is encountered.
-
-2015-07-16  Peter Wu  <peter@lekensteyn.nl>
-
-       rsa: Fix error in comments.
-       + commit 9cd55e8e948f0049cb23495f536decf797d072f7
-       * cipher/rsa.c: Fix.
-
-2015-07-14  Peter Wu  <peter@lekensteyn.nl>
-
-       sexp: Fix invalid deallocation in error path.
-       + commit 0f9532b186c1e0b54d7e7a6d76bce82b6226122b
-       * src/sexp.c: Fix wrong condition.
-
-2015-07-10  Peter Wu  <peter@lekensteyn.nl>
-
-       ecc: fix memory leak.
-       + commit 2a7aa3ea4d03a9c808d5888f5509c08cd27aa27c
-       * cipher/ecc.c (ecc_verify): Release memory which was allocated before
-       by _gcry_pk_util_preparse_sigval.
-       (ecc_decrypt_raw): Likewise.
-
-2015-07-06  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: fix memory leaks.
-       + commit 0a7547e487a8bc4e7ac9599c55579eb2e4a13f06
-       cipher/ecc.c (ecc_generate): Fix memory leak on error of
-       _gcry_pk_util_parse_flaglist and _gcry_ecc_eddsa_encodepoint.
-       (ecc_check_secret_key): Fix memory leak on error of
-       _gcry_ecc_update_curve_param.
-       (ecc_sign, ecc_verify, ecc_encrypt_raw, ecc_decrypt_raw): Remove
-       unnecessary sexp_release and fix memory leak on error of
-       _gcry_ecc_fill_in_curve.
-       (ecc_decrypt_raw): Fix double free of the point kG and memory leak
-       on error of _gcry_ecc_os2ec.
-
-2015-06-11  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: Support FreeBSD 10 or later.
-       + commit a36ee7501f68ad7ebcfe31f9659430b9d2c3ddd1
-       * mpi/config.links: Include FreeBSD 10 to 29.
-
-2015-05-21  Werner Koch  <wk@gnupg.org>
-
-       ecc: Add key generation flag "no-keytest".
-       + commit 2bddd947fd1c11b4ec461576db65a5e34fea1b07
-       * src/cipher.h (PUBKEY_FLAG_NO_KEYTEST): New.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Add flag
-       "no-keytest".  Return an error for invalid flags of length 10.
-
-       * cipher/ecc.c (nist_generate_key): Replace arg random_level by flags
-       set random level depending on flags.
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_genkey): Ditto.
-       * cipher/ecc.c (ecc_generate): Pass flags to generate fucntion and
-       remove var random_level.
-       (nist_generate_key): Implement "no-keytest" flag.
-
-       * tests/keygen.c (check_ecc_keys): Add tests for transient-key and
-       no-keytest.
-
-       ecc: Avoid double conversion to affine coordinates in keygen.
-       + commit 102d68b3bd77813a3ff989526855bb1e283bf9d7
-       * cipher/ecc.c (nist_generate_key): Add args r_x and r_y.
-       (ecc_generate): Rename vars.  Convert to affine coordinates only if
-       not returned by the lower level generation function.
-
-       random: Change initial extra seeding from 2400 bits to 128 bits.
-       + commit 8124e357b732a719696bfd5271def4e528f2a1e1
-       * random/random-csprng.c (read_pool): Reduce initial seeding.
-
-2015-05-14  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Enable AMD64 Twofish implementation on WIN64.
-       + commit 9b0c6c8141ae9bd056392a3f6b5704b505fc8501
-       * cipher/twofish-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/twofish.c (USE_AMD64_ASM): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS] (call_sysv_fn): New.
-       (twofish_amd64_encrypt_block, twofish_amd64_decrypt_block)
-       (twofish_amd64_ctr_enc, twofish_amd64_cbc_dec)
-       (twofish_amd64_cfb_dec): New wrapper functions for AMD64
-       assembly functions.
-
-       Enable AMD64 Serpent implementations on WIN64.
-       + commit eb0ed576893b6c7990dbcb568510f831d246cea6
-       * cipher/serpent-avx2-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/serpent-sse2-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/chacha20.c (USE_SSE2, USE_AVX2): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [USE_SSE2 || USE_AVX2] (ASM_FUNC_ABI): New.
-       (_gcry_serpent_sse2_ctr_enc, _gcry_serpent_sse2_cbc_dec)
-       (_gcry_serpent_sse2_cfb_dec, _gcry_serpent_avx2_ctr_enc)
-       (_gcry_serpent_avx2_cbc_dec, _gcry_serpent_avx2_cfb_dec): Add
-       ASM_FUNC_ABI.
-
-       Enable AMD64 Salsa20 implementation on WIN64.
-       + commit 12bc93ca8187b8061c2e705427ef22f5a71d29b0
-       * cipher/salsa20-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/salsa20.c (USE_AMD64): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [USE_AMD64] (ASM_FUNC_ABI, ASM_EXTRA_STACK): New.
-       (_gcry_salsa20_amd64_keysetup, _gcry_salsa20_amd64_ivsetup)
-       (_gcry_salsa20_amd64_encrypt_blocks): Add ASM_FUNC_ABI.
-       [USE_AMD64] (salsa20_core): Add ASM_EXTRA_STACK.
-       (salsa20_do_encrypt_stream) [USE_AMD64]: Add ASM_EXTRA_STACK.
-
-       Enable AMD64 Poly1305 implementations on WIN64.
-       + commit 8d7de4dbf7732c6eb9e9853ad7c19c89075ace6f
-       * cipher/poly1305-avx2-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/poly1305-sse2-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/poly1305-internal.h (POLY1305_SYSV_FUNC_ABI): New.
-       (POLY1305_USE_SSE2, POLY1305_USE_AVX2): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (OPS_FUNC_ABI): New.
-       (poly1305_ops_t): Use OPS_FUNC_ABI.
-       * cipher/poly1305.c (_gcry_poly1305_amd64_sse2_init_ext)
-       (_gcry_poly1305_amd64_sse2_finish_ext)
-       (_gcry_poly1305_amd64_sse2_blocks, _gcry_poly1305_amd64_avx2_init_ext)
-       (_gcry_poly1305_amd64_avx2_finish_ext)
-       (_gcry_poly1305_amd64_avx2_blocks, _gcry_poly1305_armv7_neon_init_ext)
-       (_gcry_poly1305_armv7_neon_finish_ext)
-       (_gcry_poly1305_armv7_neon_blocks, poly1305_init_ext_ref32)
-       (poly1305_blocks_ref32, poly1305_finish_ext_ref32)
-       (poly1305_init_ext_ref8, poly1305_blocks_ref8)
-       (poly1305_finish_ext_ref8): Use OPS_FUNC_ABI.
-
-       Enable AMD64 3DES implementation on WIN64.
-       + commit b65e9e71d5ee992db5c96793c6af999545daad28
-       * cipher/des-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/des.c (USE_AMD64_ASM): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS] (call_sysv_fn): New.
-       (tripledes_ecb_crypt) [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS]: Call
-       assembly function through 'call_sysv_fn'.
-       (tripledes_amd64_ctr_enc, tripledes_amd64_cbc_dec)
-       (tripledes_amd64_cfb_dec): New wrapper functions for bulk
-       assembly functions.
-
-       Enable AMD64 ChaCha20 implementations on WIN64.
-       + commit 9597cfddf03c467825da152be5ca0d12a8c30d88
-       * cipher/chacha20-avx2-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/chacha20-sse2-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/chacha20-ssse3-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/chacha20.c (USE_SSE2, USE_SSSE3, USE_AVX2): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ASM_FUNC_ABI, ASM_EXTRA_STACK): New.
-       (chacha20_blocks_t, _gcry_chacha20_amd64_sse2_blocks)
-       (_gcry_chacha20_amd64_ssse3_blocks, _gcry_chacha20_amd64_avx2_blocks)
-       (_gcry_chacha20_armv7_neon_blocks, chacha20_blocks): Add ASM_FUNC_ABI.
-       (chacha20_core): Add ASM_EXTRA_STACK.
-
-       Enable AMD64 CAST5 implementation on WIN64.
-       + commit 6a6646df80386204675d8b149ab60e74d7ca124c
-       * cipher/cast5-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (RIP): Remove.
-       (GET_EXTERN_POINTER): Use 'leaq' version on WIN64.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/cast5.c (USE_AMD64_ASM): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS] (call_sysv_fn): New.
-       (do_encrypt_block, do_decrypt_block)
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS]: Call assembly
-       function through 'call_sysv_fn'.
-       (cast5_amd64_ctr_enc, cast5_amd64_cbc_dec)
-       (cast5_amd64_cfb_dec): New wrapper functions for bulk
-       assembly functions.
-
-       Enable AMD64 Camellia implementations on WIN64.
-       + commit 9a4fb3709864bf3e3918800d44ff576590cd4e92
-       * cipher/camellia-aesni-avx-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/camellia-aesni-avx2-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/camellia-glue.c (USE_AESNI_AVX, USE_AESNI_AVX2): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [USE_AESNI_AVX || USE_AESNI_AVX2] (ASM_FUNC_ABI, ASM_EXTRA_STACK): New.
-       (_gcry_camellia_aesni_avx_ctr_enc, _gcry_camellia_aesni_avx_cbc_dec)
-       (_gcry_camellia_aesni_avx_cfb_dec, _gcry_camellia_aesni_avx_keygen)
-       (_gcry_camellia_aesni_avx2_ctr_enc, _gcry_camellia_aesni_avx2_cbc_dec)
-       (_gcry_camellia_aesni_avx2_cfb_dec): Add ASM_FUNC_ABI.
-
-       Enable AMD64 Blowfish implementation on WIN64.
-       + commit e05682093ffb003b589a697428d918d755ac631d
-       * cipher/blowfish-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/blowfish.c (USE_AMD64_ASM): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS] (call_sysv_fn): New.
-       (do_encrypt, do_encrypt_block, do_decrypt_block)
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS]: Call assembly
-       function through 'call_sysv_fn'.
-       (blowfish_amd64_ctr_enc, blowfish_amd64_cbc_dec)
-       (blowfish_amd64_cfb_dec): New wrapper functions for bulk
-       assembly functions.
-       ..
-
-       Enable AMD64 arcfour implementation on WIN64.
-       + commit c46b015bedba7ce0db68929bd33a86a54ab3d919
-       * cipher/arcfour-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/arcfour.c (USE_AMD64_ASM): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (do_encrypt, do_decrypt) [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS]: Use
-       assembly block to call AMD64 assembly function.
-
-       Update documentation for Poly1305-ChaCha20 AEAD, RFC-7539.
-       + commit ee8fc4edcb3466b03246c8720b90731bf274ff1d
-       * cipher/cipher-poly1305.c: Add RFC-7539 to header.
-       * doc/gcrypt.texi: Update Poly1305 AEAD documentation with mention of
-       RFC-7539; Drop Salsa from supported stream ciphers for Poly1305 AEAD.
-
-       hwf-x86: use edi for passing value to ebx for i386 cpuid.
-       + commit bac42c68b069f17abcca810a21439c7233815747
-       * src/hwf-x86.c [__i386__] (get_cpuid): Use '=D' for regs[1] instead
-       of '=r'.
-
-       hwf-x86: add EDX as output register for xgetbv asm block.
-       + commit e15beb584a5ebdfc363e1ff15f87102508652d71
-       * src/hwf-x86.c (get_xgetbv): Add EDX as output.
-
-2015-05-04  Werner Koch  <wk@gnupg.org>
-
-       build: Update build-aux files.
-       + commit 5a7d55eed3316f40ca61acbee032bfc285e28803
-
-
-       Fix possible regression on old 32 bit mingw compilers.
-       + commit 090ca7435156b5f52064357dd59059570d466f46
-       * acinclude.m4: Add new pattern for mingw32.
-
-       build: Add new file.
-       + commit 4af52b2e72ce004b7d8f99e09c4324e3c2a84379
-       * mpi/amd64/distfiles: Add func_abi.h.
-
-2015-05-03  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix WIN64 assembly glue for AES.
-       + commit 24a769a7c7601dbb85332e550f6fbd121b56df5f
-       * cipher/rinjdael.c (do_encrypt, do_decrypt)
-       [!HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS]: Change input operands to
-       input+output to mark volatile nature of the used registers.
-
-       Add '1 million a characters' test vectors.
-       + commit 2f4fefdbc62857b6e2da26ce111ee140a068c471
-       * tests/basic.c (check_digests): Add "!" test vectors for MD5, SHA-384,
-       SHA-512, RIPEMD160 and CRC32.
-
-2015-05-02  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       More optimized CRC implementations.
-       + commit 06e122baa3321483a47bbf82fd2a4540becfa0c9
-       * cipher/crc.c (crc32_table, crc24_table): Replace with new table
-       contents.
-       (update_crc32, CRC24_INIT, CRC24_POLY): Remove.
-       (crc32_next, crc32_next4, crc24_init, crc24_next, crc24_next4)
-       (crc24_final): New.
-       (crc24rfc2440_init): Use crc24_init.
-       (crc32_write): Rewrite to use crc32_next & crc32_next4.
-       (crc24_write): Rewrite to use crc24_next & crc24_next4.
-       (crc32_final, crc32rfc1510_final): Use buf_put_be32.
-       (crc24rfc2440_final): Use crc24_final & buf_put_le32.
-       * tests/basic.c (check_digests): Add CRC "123456789" tests.
-
-       Enable AMD64 AES implementation for WIN64.
-       + commit 66129b3334a5aa54ff8a97981507e4704f759571
-       * cipher/rijndael-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/rijndael-internal.h (USE_AMD64_ASM): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (do_encrypt, do_decrypt)
-       [USE_AMD64_ASM && !HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS]: Use
-       assembly block to call AMD64 assembly encrypt/decrypt function.
-
-       Enable AMD64 Whirlpool implementation for WIN64.
-       + commit 8422d5d699265b960bd1ca837044ee052fc5b614
-       * cipher/whirlpool-sse2-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/whirlpool.c (USE_AMD64_ASM): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [USE_AMD64_ASM] (ASM_FUNC_ABI, ASM_EXTRA_STACK): New.
-       [USE_AMD64_ASM] (_gcry_whirlpool_transform_amd64): Add ASM_FUNC_ABI to
-       prototype.
-       [USE_AMD64_ASM] (whirlpool_transform): Add ASM_EXTRA_STACK to stack
-       burn value.
-
-       Enable AMD64 SHA512 implementations for WIN64.
-       + commit 1089a13073c26a9a456e43ec38d937e6ee7f4077
-       * cipher/sha512-avx-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/sha512-avx-bmi2-amd64.S: Ditto.
-       * cipher/sha512-ssse3-amd64.S: Ditto.
-       * cipher/sha512.c (USE_SSSE3, USE_AVX, USE_AVX2): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [USE_SSSE3 || USE_AVX || USE_AVX2] (ASM_FUNC_ABI)
-       (ASM_EXTRA_STACK): New.
-       (_gcry_sha512_transform_amd64_ssse3, _gcry_sha512_transform_amd64_avx)
-       (_gcry_sha512_transform_amd64_avx_bmi2): Add ASM_FUNC_ABI to
-       prototypes.
-       (transform): Add ASM_EXTRA_STACK to stack burn value.
-
-       Enable AMD64 SHA256 implementations for WIN64.
-       + commit 022959099644f64df5f2a83ade21159864f64837
-       * cipher/sha256-avx-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/sha256-avx2-bmi2-amd64.S: Ditto.
-       * cipher/sha256-ssse3-amd64.S: Ditto.
-       * cipher/sha256.c (USE_SSSE3, USE_AVX, USE_AVX2): Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [USE_SSSE3 || USE_AVX || USE_AVX2] (ASM_FUNC_ABI)
-       (ASM_EXTRA_STACK): New.
-       (_gcry_sha256_transform_amd64_ssse3, _gcry_sha256_transform_amd64_avx)
-       (_gcry_sha256_transform_amd64_avx2): Add ASM_FUNC_ABI to prototypes.
-       (transform): Add ASM_EXTRA_STACK to stack burn value.
-
-       Enable AMD64 SHA1 implementations for WIN64.
-       + commit e433676a899fa0d274d40547166b03c7c8bd8e78
-       * cipher/sha1-avx-amd64.S: Enable when
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       (ELF): New macro to mask lines with ELF specific commands.
-       * cipher/sha1-avx-bmi2-amd64.S: Ditto.
-       * cipher/sha1-ssse3-amd64.S: Ditto.
-       * cipher/sha1.c (USE_SSSE3, USE_AVX, USE_BMI2): Enable
-       when HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined.
-       [USE_SSSE3 || USE_AVX || USE_BMI2] (ASM_FUNC_ABI)
-       (ASM_EXTRA_STACK): New.
-       (_gcry_sha1_transform_amd64_ssse3, _gcry_sha1_transform_amd64_avx)
-       (_gcry_sha1_transform_amd64_avx_bmi2): Add ASM_FUNC_ABI to
-       prototypes.
-       (transform): Add ASM_EXTRA_STACK to stack burn value.
-
-2015-05-01  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Enable AES/AES-NI, AES/SSSE3 and GCM/PCLMUL implementations on WIN64.
-       + commit 4e09aaa36d151c3312019724a77fc09aa345b82f
-       * cipher/cipher-gcm-intel-pclmul.c (_gcry_ghash_intel_pclmul)
-       ( _gcry_ghash_intel_pclmul) [__WIN64__]: Store non-volatile vector
-       registers before use and restore after.
-       * cipher/cipher-internal.h (GCM_USE_INTEL_PCLMUL): Remove dependency
-       on !defined(__WIN64__).
-       * cipher/rijndael-aesni.c [__WIN64__] (aesni_prepare_2_6_variable,
-       aesni_prepare, aesni_prepare_2_6, aesni_cleanup)
-       ( aesni_cleanup_2_6): New.
-       [!__WIN64__] (aesni_prepare_2_6_variable, aesni_prepare_2_6): New.
-       (_gcry_aes_aesni_do_setkey, _gcry_aes_aesni_cbc_enc)
-       (_gcry_aesni_ctr_enc, _gcry_aesni_cfb_dec, _gcry_aesni_cbc_dec)
-       (_gcry_aesni_ocb_crypt, _gcry_aesni_ocb_auth): Use
-       'aesni_prepare_2_6'.
-       * cipher/rijndael-internal.h (USE_SSSE3): Enable if
-       HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS or
-       HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS.
-       (USE_AESNI): Remove dependency on !defined(__WIN64__)
-       * cipher/rijndael-ssse3-amd64.c [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS]
-       (vpaes_ssse3_prepare, vpaes_ssse3_cleanup): New.
-       [!HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS] (vpaes_ssse3_prepare): New.
-       (vpaes_ssse3_prepare_enc, vpaes_ssse3_prepare_dec): Use
-       'vpaes_ssse3_prepare'.
-       (_gcry_aes_ssse3_do_setkey, _gcry_aes_ssse3_prepare_decryption): Use
-       'vpaes_ssse3_prepare' and 'vpaes_ssse3_cleanup'.
-       [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS] (X): Add masking macro to
-       exclude '.type' and '.size' markers from assembly code, as they are
-       not support on WIN64/COFF objects.
-       * configure.ac (gcry_cv_gcc_attribute_ms_abi)
-       (gcry_cv_gcc_attribute_sysv_abi, gcry_cv_gcc_default_abi_is_ms_abi)
-       (gcry_cv_gcc_default_abi_is_sysv_abi)
-       (gcry_cv_gcc_win64_platform_as_ok): New checks.
-
-       Add W64 support for mpi amd64 assembly.
-       + commit 460355f23e770637d29e3af7b998a957a2b5bc88
-       acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Set
-       'ac_cv_sys_symbol_underscore=no' on MingW-W64.
-       mpi/amd64/func_abi.h: New.
-       mpi/amd64/mpih-add1.S (_gcry_mpih_add_n): Add FUNC_ENTRY and FUNC_EXIT.
-       mpi/amd64/mpih-lshift.S (_gcry_mpih_lshift): Ditto.
-       mpi/amd64/mpih-mul1.S (_gcry_mpih_mul_1): Ditto.
-       mpi/amd64/mpih-mul2.S (_gcry_mpih_addmul_1): Ditto.
-       mpi/amd64/mpih-mul3.S (_gcry_mpih_submul_1): Ditto.
-       mpi/amd64/mpih-rshift.S (_gcry_mpih_rshift): Ditto.
-       mpi/amd64/mpih-sub1.S (_gcry_mpih_sub_n): Ditto.
-       mpi/config.links [host=x86_64-*mingw*]: Enable assembly modules.
-       [host=x86_64-*-*]: Append mpi/amd64/func_abi.h to mpi/asm-syntax.h.
-
-       DES: Silence compiler warnings on Windows.
-       + commit 6c21cf5fed1ad430fa41445eac2350802bc8aaed
-       * cipher/des.c (working_memcmp): Make pointer arguments 'const void *'.
-
-       Cast pointers to integers using uintptr_t instead of long.
-       + commit 9cf224322007d90193d4910f0da6e0e29ce01d70
-
-
-       Fix rndhw for 64-bit Windows build.
-       + commit d5a7e00b6b222566a5650639ef29684b047c1909
-       * configure.ac: Add sizeof check for 'void *'.
-       * random/rndhw.c (poll_padlock): Check for SIZEOF_VOID_P == 8
-       instead of defined(__LP64__).
-       (RDRAND_LONG): Check for SIZEOF_UNSIGNED_LONG == 8 instead of
-       defined(__LP64__).
-
-       Prepare random/win32.c fast poll for 64-bit Windows.
-       + commit 0cdd24456b33defc7f8176fa82ab694fbc284385
-       * random/win32.c (_gcry_rndw32_gather_random_fast) [ADD]: Rename to
-       ADDINT.
-       (_gcry_rndw32_gather_random_fast): Add ADDPTR.
-       (_gcry_rndw32_gather_random_fast): Disable entropy gathering from
-       GetQueueStatus(QS_ALLEVENTS).
-       (_gcry_rndw32_gather_random_fast): Change minimumWorkingSetSize and
-       maximumWorkingSetSize to SIZE_T from DWORD.
-       (_gcry_rndw32_gather_random_fast): Only add lower 32-bits of
-       minimumWorkingSetSize and maximumWorkingSetSize to random poll.
-       (_gcry_rndw32_gather_random_fast) [__WIN64__]: Read TSC directly
-       using intrinsic.
-
-       Disable GCM and AES-NI assembly implementations for WIN64.
-       + commit f701954555340a503f6e52cc18d58b0c515427b7
-       * cipher/cipher-internal.h (GCM_USE_INTEL_PCLMUL): Do not enable when
-       __WIN64__ defined.
-       * cipher/rijndael-internal.h (USE_AESNI): Ditto.
-
-       Disable building mpi assembly routines on WIN64.
-       + commit e78560a4b717f7154f910a8ce4128de152f586da
-       * mpi/config.links: Disable assembly for host 'x86_64-*mingw32*'.
-
-       Fix packed attribute check for Windows targets.
-       + commit e886e4f5e73fe6a9f9191f5155852ce5d8bb88fe
-       * configure.ac (gcry_cv_gcc_attribute_packed): Move 'long b' to its
-       own packed structure.
-
-       Fix tail handling in buf_xor_1.
-       + commit c2dba93e639639bdac139b3a3a456d10ddc61f79
-       * cipher/bufhelp.h (buf_xor_1): Increment source pointer at tail
-       handling.
-
-       Add --disable-hwf for basic tests.
-       + commit 839a3bbe2bb045139223b32753d656cc6c3d4669
-       * tests/basic.c (main): Add handling for '--disable-hwf'.
-
-       Use more odd chuck sizes for check_one_md.
-       + commit 9f086ffa43f2507b9d17522a0a2e394cb273baf8
-       * tests/basic.c (check_one_md): Make chuck size vary oddly, instead
-       of using fixed length of 1000 bytes.
-
-       Enable more modes in basic ciphers test.
-       + commit e40eff94f9f8654c3d29e03bbb7e5ee6a43c1435
-       * src/gcrypt.h.in (GCRY_OCB_BLOCK_LEN): New.
-       * tests/basic.c (check_one_cipher_core_reset): New.
-       (check_one_cipher_core): Use check_one_cipher_core_reset inplace of
-       gcry_cipher_reset.
-       (check_ciphers): Add CCM and OCB modes for block cipher tests.
-
-       Fix reseting cipher in OCB mode.
-       + commit 88842cbc68beb4f73c87fdbcb74182cba818f789
-       * cipher/cipher.c (cipher_reset): Setup default taglen for OCB after
-       clearing state.
-
-2015-04-30  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix buggy RC4 AMD64 assembly and add test to notice similar issues.
-       + commit 124dfce7c5a2d9405fa2b2832e91ac1267943830
-       * cipher/arcfour-amd64.S (_gcry_arcfour_amd64): Fix swapped store of
-       'x' and 'y'.
-       * tests/basic.c (get_algo_mode_blklen): New.
-       (check_one_cipher_core): Add new tests for split buffer input on
-       encryption and decryption.
-
-2015-04-26  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Disallow compiler from generating SSE instructions in mixed C+asm source
-       + commit f88266c0f868d7bf51a215d5531bb9f2b4dad19e
-       * cipher/cipher-gcm-intel-pclmul.c [gcc-version >= 4.4]: Add GCC target
-       pragma to disable compiler use of SSE.
-       * cipher/rijndael-aesni.c [gcc-version >= 4.4]: Ditto.
-       * cipher/rijndael-ssse3-amd64.c [gcc-version >= 4.4]: Ditto.
-
-2015-04-18  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add OCB bulk crypt/auth functions for AES/AES-NI.
-       + commit 305cc878d395475c46b4ef52f4764bd0c85bf8ac
-       * cipher/cipher-internal.h (gcry_cipher_handle): Add bulk.ocb_crypt
-       and bulk.ocb_auth.
-       (_gcry_cipher_ocb_get_l): New prototype.
-       * cipher/cipher-ocb.c (get_l): Rename to ...
-       (_gcry_cipher_ocb_get_l): ... this.
-       (_gcry_cipher_ocb_authenticate, ocb_crypt): Use bulk function when
-       available.
-       * cipher/cipher.c (_gcry_cipher_open_internal): Setup OCB bulk
-       functions for AES.
-       * cipher/rijndael-aesni.c (get_l, aesni_ocb_enc, aes_ocb_dec)
-       (_gcry_aes_aesni_ocb_crypt, _gcry_aes_aesni_ocb_auth): New.
-       * cipher/rijndael.c [USE_AESNI] (_gcry_aes_aesni_ocb_crypt)
-       (_gcry_aes_aesni_ocb_auth): New prototypes.
-       (_gcry_aes_ocb_crypt, _gcry_aes_ocb_auth): New.
-       * src/cipher.h (_gcry_aes_ocb_crypt, _gcry_aes_ocb_auth): New
-       prototypes.
-       * tests/basic.c (check_ocb_cipher_largebuf): New.
-       (check_ocb_cipher): Add large buffer encryption/decryption test.
-
-2015-04-15  Werner Koch  <wk@gnupg.org>
-
-       tests: Add option to time the S2K function.
-       + commit fe38d3815b4cd203cd529949e244aca80d32897f
-       * tests/t-kdf.c: Include stopwatch.h.
-       (dummy_consumer): new.
-       (bench_s2k): New.
-       (main): Add option parser and option --s2k.
-
-       tests: Improve stopwatch.h.
-       + commit 3b03a3b493233a472da531d8d9582d1be6d376b0
-       * tests/stopwatch.h (elapsed_time): Add arg divisor.
-
-2015-04-13  Werner Koch  <wk@gnupg.org>
-
-       mpi: Fix gcry_mpi_copy for NULL opaque data.
-       + commit 9fca46864e1b5a9c788072113589454adb89fa97
-       * mpi/mpiutil.c (_gcry_mpi_copy): Copy opaque only if needed.
-
-2015-03-21  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       wipememory: use one-byte aligned type for unaligned memory accesses.
-       + commit a06fbc0d1e98eb1218eff55ad2f37d471e4f33b2
-       * src/g10lib.h (fast_wipememory2_unaligned_head): Enable unaligned
-       access only when HAVE_GCC_ATTRIBUTE_PACKED and
-       HAVE_GCC_ATTRIBUTE_ALIGNED defined.
-       (fast_wipememory_t): New.
-       (fast_wipememory2): Use 'fast_wipememory_t'.
-
-       bufhelp: use one-byte aligned type for unaligned memory accesses.
-       + commit 92fa5f16d69707e302c0f85b2e5e80af8dc037f1
-       * cipher/bufhelp.h (BUFHELP_FAST_UNALIGNED_ACCESS): Enable only when
-       HAVE_GCC_ATTRIBUTE_PACKED and HAVE_GCC_ATTRIBUTE_ALIGNED are defined.
-       (bufhelp_int_t): New type.
-       (buf_cpy, buf_xor, buf_xor_1, buf_xor_2dst, buf_xor_n_copy_2): Use
-       'bufhelp_int_t'.
-       [BUFHELP_FAST_UNALIGNED_ACCESS] (bufhelp_u32_t, bufhelp_u64_t): New.
-       [BUFHELP_FAST_UNALIGNED_ACCESS] (buf_get_be32, buf_get_le32)
-       (buf_put_be32, buf_put_le32, buf_get_be64, buf_get_le64)
-       (buf_put_be64, buf_put_le64): Use 'bufhelp_uXX_t'.
-       * configure.ac (gcry_cv_gcc_attribute_packed): New.
-
-       tests/bench-slope: fix memory-leak and use-after-free bugs.
-       + commit aa234561d00c3fb15fe501df4bf58f3db7c7c06b
-       * tests/bench-slope.c (do_slope_benchmark): Free 'measurements' at end.
-       (bench_mac_init): Move 'key' free at end of function.
-
-2015-03-19  Werner Koch  <wk@gnupg.org>
-
-       Fix two pedantic warnings.
-       + commit f5832285b0e420d77be1b8da10a1e1d86583b414
-       * src/gcrypt.h.in (gcry_mpi_flag, gcry_mac_algos): Remove trailing
-       comma.
-
-2015-03-16  Werner Koch  <wk@gnupg.org>
-
-       Use well defined type instead of size_t in secmem.c.
-       + commit db8ae3616987fa288173446398a107e31e2e28aa
-       * src/secmem.c (ptr_into_pool_p): Replace size_t by uintptr_t.
-
-       Make uintptr_t global available.
-       + commit f0f60c1a04d664936bcf52e8f46705bdc63e7ad9
-       * cipher/bufhelp.h: Move include for uintptr_t to ...
-       * src/types.h: here.  Check that config.h has been included.
-
-       mpi: Remove useless condition.
-       + commit 0a9cdb8ae092d050ca12a7a4f2f50e25b82154ec
-       * mpi/mpi-pow.c: Remove condition rp==mp.
-
-       cipher: Remove useless NULL check.
-       + commit fbb97dcf763e28e81e01092ad4c934b3eaf88cc8
-       * cipher/hash-common.c (_gcry_md_block_write): Remove NUL check for
-       hd->buf.
-
-2015-02-28  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix in-place encryption for OCB mode.
-       + commit 5e66a4f8d5a63f58caeee367433dd8dd32346083
-       * cipher/cipher-ocb.c (ocb_checksum): New.
-       (ocb_crypt): Move checksum calculation outside main crypt loop, do
-       checksum calculation for encryption before inbuf is overwritten.
-       * tests/basic.c (check_ocb_cipher): Rename to ...
-       (do_check_ocb_cipher): ... to this and add argument for testing
-       in-place encryption/decryption.
-       (check_ocb_cipher): New.
-
-2015-02-27  NIIBE Yutaka  <gniibe@fsij.org>
-
-       tests: fix t-sexp.c.
-       + commit 505decf5369970219ddc9e78a20f97c623957b78
-       * tests/t-sexp.c (bug_1594): Free N and PUBKEY.
-
-       mpi: Avoid data-dependent timing variations in mpi_powm.
-       + commit 6636c4fd0c6ceab9f79827bf96967d1e112c0b82
-       * mpi/mpi-pow.c (mpi_powm): Access all data in the table by
-       mpi_set_cond.
-
-       mpi: Revise mpi_powm.
-       + commit 1fa8cdb933505960d4e4b4842b122d4e06953e88
-       * mpi/mpi-pow.c (_gcry_mpi_powm): Rename the table to PRECOMP.
-
-2015-02-23  Werner Koch  <wk@gnupg.org>
-
-       cipher: Use ciphertext blinding for Elgamal decryption.
-       + commit 410d70bad9a650e3837055e36f157894ae49a57d
-       * cipher/elgamal.c (USE_BLINDING): New.
-       (decrypt): Rewrite to use ciphertext blinding.
-
-2015-02-12  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: Add mpi_set_cond.
-       + commit 653a9fa1a3a4c35a4dc1841cb57d7e2a318f3288
-       * mpi/mpiutil.c (_gcry_mpi_set_cond): New.
-       (_gcry_mpi_swap_cond): Fix types.
-       * src/mpi.h (mpi_set_cond): New.
-
-2015-01-30  Werner Koch  <wk@gnupg.org>
-
-       w32: Use -static-libgcc to avoid linking to libgcc_s_sjlj-1.dll.
-       + commit 40a7bdf50e19faaf106470897fed72af623adc50
-       * src/Makefile.am (extra_ltoptions): New.
-       (libgcrypt_la_LDFLAGS): Use it.
-
-2015-01-28  Werner Koch  <wk@gnupg.org>
-
-       Fix building of GOST s-boxes when cross-compiling.
-       + commit 2564d204e408b296425ac0660c6bdc6270575fb6
-       * cipher/Makefile.am (gost-s-box): USe CC_FOR_BUILD.
-       (noinst_PROGRAMS): Remove.
-       (EXTRA_DIST): New.
-       (CLEANFILES): New.
-
-2015-01-20  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael: fix wrong ifdef for SSSE3 setkey.
-       + commit ceaa97f0d849c07f3a15b642fc3a2b0a477b4a47
-       * cipher/rijndael.c (do_setkey): Use USE_SSSE3 instead of USE_AESNI
-       around SSSE3 setkey selection.
-
-2015-01-16  Werner Koch  <wk@gnupg.org>
-
-       Add OCB cipher mode.
-       + commit 067d7d8752d4d8a98f8e0e5e9b1a5b13e1b7ff9c
-       * cipher/cipher-ocb.c: New.
-       * cipher/Makefile.am (libcipher_la_SOURCES): Add cipher-ocb.c
-       * cipher/cipher-internal.h (OCB_BLOCK_LEN, OCB_L_TABLE_SIZE): New.
-       (gcry_cipher_handle): Add fields marks.finalize and u_mode.ocb.
-       * cipher/cipher.c (_gcry_cipher_open_internal): Add OCB mode.
-       (_gcry_cipher_open_internal): Setup default taglen of OCB.
-       (cipher_reset): Clear OCB specific data.
-       (cipher_encrypt, cipher_decrypt, _gcry_cipher_authenticate)
-       (_gcry_cipher_gettag, _gcry_cipher_checktag): Call OCB functions.
-       (_gcry_cipher_setiv): Add OCB specific nonce setting.
-       (_gcry_cipher_ctl): Add GCRYCTL_FINALIZE and GCRYCTL_SET_TAGLEN
-
-       * src/gcrypt.h.in (GCRYCTL_SET_TAGLEN): New.
-       (gcry_cipher_final): New.
-
-       * cipher/bufhelp.h (buf_xor_1): New.
-
-       * tests/basic.c (hex2buffer): New.
-       (check_ocb_cipher): New.
-       (main): Call it here.  Add option --cipher-modes.
-       * tests/bench-slope.c (bench_aead_encrypt_do_bench): Call
-       gcry_cipher_final.
-       (bench_aead_decrypt_do_bench): Ditto.
-       (bench_aead_authenticate_do_bench): Ditto.  Check error code.
-       (bench_ocb_encrypt_do_bench): New.
-       (bench_ocb_decrypt_do_bench): New.
-       (bench_ocb_authenticate_do_bench): New.
-       (ocb_encrypt_ops): New.
-       (ocb_decrypt_ops): New.
-       (ocb_authenticate_ops): New.
-       (cipher_modes): Add them.
-       (cipher_bench_one): Skip wrong block length for OCB.
-       * tests/benchmark.c (cipher_bench): Add field noncelen to MODES.  Add
-       OCB support.
-
-2015-01-15  Werner Koch  <wk@gnupg.org>
-
-       Add functions to count trailing zero bits in a word.
-       + commit 9d2a22c94ae99f9301321082c4fb8d73f4085fda
-       * cipher/bithelp.h (_gcry_ctz, _gcry_ctz64): New.
-       * configure.ac (HAVE_BUILTIN_CTZ): Add new test.
-
-2015-01-08  Werner Koch  <wk@gnupg.org>
-
-       cipher: Prepare for OCB mode.
-       + commit 9d328962660da72f094dc5424d5ef67abbaffdf6
-       * src/gcrypt.h.in (GCRY_CIPHER_MODE_OCB): New.
-
-2015-01-06  Werner Koch  <wk@gnupg.org>
-
-       Make make distcheck work again.
-       + commit 4f7dcdc25af269b12275126edeef30b262fb891d
-       * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Remove --enable-ciphers.
-       * cipher/Makefile.am (DISTCLEANFILES): Add gost-sb.h.
-
-2015-01-06  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       stribog: Reduce table size to the needed one.
-       + commit e4de52378a85cf383994ded8edf0d5cf98dcb10c
-       * cipher/stribog.c (C16): Avoid allocating superfluous space.
-
-       gostr3411-94: Fix the iteration count for length filling loop.
-       + commit 05dc5bcd234909ae9c9366b653346076b9a834ed
-       * cipher/gostr3411-94.c (gost3411_final): Fix loop
-
-2015-01-05  Werner Koch  <wk@gnupg.org>
-
-       random: Silent warning under NetBSD using rndunix.
-       + commit 817472358a093438e802380caecf7139406400cf
-       * random/rndunix.c (STDERR_FILENO): Define if needed.
-       (start_gatherer): Re-open standard descriptors.  Fix an
-       unsigned/signed pointer warning.
-
-       primegen: Fix memory leak for invalid call sequences.
-       + commit 8c5eee51d9a25b143e41ffb7ff4a6b2a29b82d83
-       * cipher/primegen.c (prime_generate_internal): Refactor generator code
-       to not leak memory for non-implemented feature.
-       (_gcry_prime_group_generator): Refactor to not leak memory for invalid
-       args.  Also make sure that R_G is set as soon as possible.
-
-       doc: Update yat2m to current upstream version (GnuPG).
-       + commit dd5df198727ea5d8f6b04288e14fd732051453c8
-
-
-       build: Require automake 1.14.
-       + commit f65276970a6dcd6d9bca94cecc49b68acdcc9492
-       * configure.ac (AM_INIT_AUTOMAKE): Add serial-tests.
-
-       Replace camel case of internal scrypt functions.
-       + commit 1a6d65ac0aab335541726d02f2046d883a768ec3
-       * cipher/scrypt.c (_salsa20_core): Rename to salsa20_core.  Change
-       callers.
-       (_scryptBlockMix): Rename to scrypt_block_mix.  Change callers.
-       (_scryptROMix): Rename to scrypt_ro_mix. Change callers.
-
-2015-01-02  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rmd160: restore native-endian store in _gcry_rmd160_mixblock.
-       + commit d7c7453cf5e6b8f3c6b522a30e680f844a28c9de
-       * cipher/rmd160.c (_gcry_rmd160_mixblock): Store result to buffer in
-       native-endianess.
-
-2014-12-27  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add Intel SSSE3 based vector permutation AES implementation.
-       + commit 8eabecc883332156adffc1df42d27f614c157e06
-       * cipher/Makefile.am: Add 'rijndael-ssse3-amd64.c'.
-       * cipher/rijndael-internal.h (USE_SSSE3): New.
-       (RIJNDAEL_context_s) [USE_SSSE3]: Add 'use_ssse3'.
-       * cipher/rijndael-ssse3-amd64.c: New.
-       * cipher/rijndael.c [USE_SSSE3] (_gcry_aes_ssse3_do_setkey)
-       (_gcry_aes_ssse3_prepare_decryption, _gcry_aes_ssse3_encrypt)
-       (_gcry_aes_ssse3_decrypt, _gcry_aes_ssse3_cfb_enc)
-       (_gcry_aes_ssse3_cbc_enc, _gcry_aes_ssse3_ctr_enc)
-       (_gcry_aes_ssse3_cfb_dec, _gcry_aes_ssse3_cbc_dec): New.
-       (do_setkey): Add HWF check for SSSE3 and setup for SSSE3
-       implementation.
-       (prepare_decryption, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc)
-       (_gcry_aes_ctr_enc, _gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Add
-       selection for SSSE3 implementation.
-       * configure.ac [host=x86_64]: Add 'rijndael-ssse3-amd64.lo'.
-
-2014-12-25  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       random-csprng: fix compiler warnings on ARM.
-       + commit c2e1f8fea271f3ef8027809547c4a52e0b1e24a2
-       * random/random-csprng.c (_gcry_rngcsprng_update_seed_file)
-       (read_pool): Cast keypool and rndpool to 'unsigned long *' through
-       'void *'.
-
-       scrypt: fix compiler warnings on ARM.
-       + commit 1dab4c9422bf0f3cdc7a4d3ccf9db090abd90e94
-       * cipher/scrypt.c (_scryptBlockMix): Cast X to 'u32 *' through 'void *'.
-
-       secmem: fix compiler warnings on ARM.
-       + commit 99faf9cb34f872144313403f29f3379798debfc9
-       * src/secmem.c (ADDR_TO_BLOCK, mb_get_next, mb_get_new): Cast pointer
-       from 'char *' to 'memblock_t *' through 'void *'.
-       (MB_WIPE_OUT): Remove unneeded cast to 'memblock_t *'.
-
-       hash: fix compiler warning on ARM.
-       + commit 4515315f61fbf79413e150fbd1d5f5a2435f2bc5
-       * cipher/md.c (md_open, md_copy): Cast 'char *' to ctx through
-       'void *'.
-       * cipher/md4.c (md4_final): Use buf_put_* helper instead of
-       converting 'char *' to 'u32 *'.
-       * cipher/md5.c (md5_final): Ditto.
-       * cipher/rmd160.c (_gcry_rmd160_mixblock, rmd160_final): Ditto.
-       * cipher/sha1.c (sha1_final): Ditto.
-       * cipher/sha256.c (sha256_final): Ditto.
-       * cipher/sha512.c (sha512_final): Ditto.
-       * cipher/tiger.c (tiger_final): Ditto.
-
-       rijndael: fix compiler warnings on ARM.
-       + commit cc26106dbebeb84d481661813edc3e5aea9a7d99
-       * cipher/rijndael-internal.h (RIJNDAEL_context_s): Add u32 variants of
-       keyschedule arrays to unions u1 and u2.
-       (keyschedenc32, keyscheddec32): New.
-       * cipher/rijndael.c (u32_a_t): Remove.
-       (do_setkey): Add and use tkk[].data32, k_u32, tk_u32 and W_u32; Remove
-       casting byte arrays to u32_a_t.
-       (prepare_decryption, do_encrypt_fn, do_decrypt_fn): Use keyschedenc32
-       and keyscheddec32; Remove casting byte arrays to u32_a_t.
-
-2014-12-23  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Poly1305-AEAD: updated implementation to match draft-irtf-cfrg-chacha20-poly1305-03
-       + commit 520070e02e2e6ee7228945015573a6e1f4895ec3
-       * cipher/cipher-internal.h (gcry_cipher_handle): Use separate byte
-       counters for AAD and data in Poly1305.
-       * cipher/cipher-poly1305.c (poly1305_fill_bytecount): Remove.
-       (poly1305_fill_bytecounts, poly1305_do_padding): New.
-       (poly1305_aad_finish): Fill padding to Poly1305 and do not fill AAD
-       length.
-       (_gcry_cipher_poly1305_authenticate, _gcry_cipher_poly1305_encrypt)
-       (_gcry_cipher_poly1305_decrypt): Update AAD and data length separately.
-       (_gcry_cipher_poly1305_tag): Fill padding and bytecounts to Poly1305.
-       (_gcry_cipher_poly1305_setkey, _gcry_cipher_poly1305_setiv): Reset
-       AAD and data byte counts; only allow 96-bit IV.
-       * cipher/cipher.c (_gcry_cipher_open_internal): Limit Poly1305-AEAD to
-       ChaCha20 cipher.
-       * tests/basic.c (_check_poly1305_cipher): Update test-vectors.
-       (check_ciphers): Limit Poly1305-AEAD checks to ChaCha20.
-       * tests/bench-slope.c (cipher_bench_one): Ditto.
-
-       chacha20: allow setting counter for stream random access.
-       + commit 11b8d2d449a7bc664b4371ae14c57caa6704d272
-       * cipher/chacha20.c (CHACHA20_CTR_SIZE): New.
-       (chacha20_ivsetup): Add setup for full counter.
-       (chacha20_setiv): Allow ivlen == CHACHA20_CTR_SIZE.
-
-       gcm: do not pass extra key pointer for setupM/fillM.
-       + commit c964321c8a1328e89d636d899a45d68802f5ac9f
-       * cipher/cipher-gcm-intel-pclmul.c
-       (_gcry_ghash_setup_intel_pclmul): Remove 'h' parameter.
-       * cipher/cipher-gcm.c (_gcry_ghash_setup_intel_pclmul): Ditto.
-       (fillM): Get 'h' pointer from 'c'.
-       (setupM): Remome 'h' parameter.
-       (_gcry_cipher_gcm_setkey): Only pass 'c' to setupM.
-
-       rijndael: use more compact look-up tables and add table prefetching.
-       + commit 2374753938df64f6fd8015b44613806a326eff1a
-       * cipher/rijndael-internal.h (rijndael_prefetchfn_t): New.
-       (RIJNDAEL_context): Add 'prefetch_enc_fn' and 'prefetch_dec_fn'.
-       * cipher/rijndael-tables.h (S, T1, T2, T3, T4, T5, T6, T7, T8, S5, U1)
-       (U2, U3, U4): Remove.
-       (encT, dec_tables, decT, inv_sbox): Add.
-       * cipher/rijndael.c (_gcry_aes_amd64_encrypt_block)
-       (_gcry_aes_amd64_decrypt_block, _gcry_aes_arm_encrypt_block)
-       (_gcry_aes_arm_encrypt_block): Add parameter for passing table pointer
-       to assembly implementation.
-       (prefetch_table, prefetch_enc, prefetch_dec): New.
-       (do_setkey): Setup context prefetch functions depending on selected
-       rijndael implementation; Use new tables for key setup.
-       (prepare_decryption): Use new tables for decryption key setup.
-       (do_encrypt_aligned): Rename to...
-       (do_encrypt_fn): ... to this, change to use new compact tables,
-       make handle unaligned input and unroll rounds loop by two.
-       (do_encrypt): Remove handling of unaligned input/output; pass table
-       pointer to assembly implementations.
-       (rijndael_encrypt, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc)
-       (_gcry_aes_ctr_enc, _gcry_aes_cfb_dec): Prefetch encryption tables
-       before encryption.
-       (do_decrypt_aligned): Rename to...
-       (do_decrypt_fn): ... to this, change to use new compact tables,
-       make handle unaligned input and unroll rounds loop by two.
-       (do_decrypt): Remove handling of unaligned input/output; pass table
-       pointer to assembly implementations.
-       (rijndael_decrypt, _gcry_aes_cbc_dec): Prefetch decryption tables
-       before decryption.
-       * cipher/rijndael-amd64.S: Use 1+1.25 KiB tables for
-       encryption+decryption; remove tables from assembly file.
-       * cipher/rijndael-arm.S: Ditto.
-
-2014-12-15  Werner Koch  <wk@gnupg.org>
-
-       build: Add configure option --disable-doc.
-       + commit ad50e360ef4851e66e51a03fc420175636336b58
-       * Makefile.am (AUTOMAKE_OPTIONS): Remove.
-       (doc) [!BUILD_DOC]: Do not recurse into the dir.
-       * configure.ac (AM_INIT_AUTOMAKE): Add option formerly in Makefile.am.
-       (BUILD_DOC): Add new am_conditional.
-
-2014-12-12  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael: further optimizations for AES-NI accelerated CBC and CFB bulk modes
-       + commit 4f46374502eb988d701b904f83819e2cf7b1755c
-       * cipher/rijndael-aesni.c (do_aesni_enc, do_aesni_dec): Pass
-       input/output through SSE register XMM0.
-       (do_aesni_cfb): Remove.
-       (_gcry_aes_aesni_encrypt, _gcry_aes_aesni_decrypt): Add loading/storing
-       input/output to/from XMM0.
-       (_gcry_aes_aesni_cfb_enc, _gcry_aes_aesni_cbc_enc)
-       (_gcry_aes_aesni_cfb_dec): Update to use renewed 'do_aesni_enc' and
-       move IV loading/storing outside loop.
-       (_gcry_aes_aesni_cbc_dec): Update to use renewed 'do_aesni_dec'.
-
-       GCM: move Intel PCLMUL accelerated implementation to separate file.
-       + commit 4a0795af021305f9240f23626a3796157db46bd7
-       * cipher/Makefile.am: Add 'cipher-gcm-intel-pclmul.c'.
-       * cipher/cipher-gcm-intel-pclmul.c: New.
-       * cipher/cipher-gcm.c [GCM_USE_INTEL_PCLMUL]
-       (_gcry_ghash_setup_intel_pclmul, _gcry_ghash_intel_pclmul): New
-       prototypes.
-       [GCM_USE_INTEL_PCLMUL] (gfmul_pclmul, gfmul_pclmul_aggr4): Move
-       to 'cipher-gcm-intel-pclmul.c'.
-       (ghash): Rename to...
-       (ghash_internal): ...this and move GCM_USE_INTEL_PCLMUL part to new
-       function in 'cipher-gcm-intel-pclmul.c'.
-       (setupM): Move GCM_USE_INTEL_PCLMUL part to new function in
-       'cipher-gcm-intel-pclmul.c'; Add selection of ghash function based
-       on available HW acceleration.
-       (do_ghash_buf): Change use of 'ghash' to 'c->u_mode.gcm.ghash_fn'.
-       * cipher/internal.h (ghash_fn_t): New.
-       (gcry_cipher_handle): Remove 'use_intel_pclmul'; Add 'ghash_fn'.
-
-2014-12-06  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael: split Padlock part to separate file.
-       + commit cbf4c8cb6bbda15eea61885279f2a6f1d4bcedfd
-       * cipher/Makefile.am: Add 'rijndael-padlock.c'.
-       * cipher/rijndael-padlock.c: New.
-       * cipher/rijndael.c (do_padlock, do_padlock_encrypt)
-       (do_padlock_decrypt): Move to 'rijndael-padlock.c'.
-       * configure.ac [mpi_cpu_arch=x86]: Add 'rijndael-padlock.lo'.
-
-2014-12-01  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael: refactor to reduce number of #ifdefs and branches.
-       + commit 3d5b51786e2050c461e9791b59142a731462b66d
-       * cipher/rijndael-aesni.c (_gcry_aes_aesni_encrypt)
-       (_gcry_aes_aesni_decrypt): Make return stack burn depth.
-       * cipher/rijndael-amd64.S (_gcry_aes_amd64_encrypt_block)
-       (_gcry_aes_amd64_decrypt_block): Ditto.
-       * cipher/rijndael-arm.S (_gcry_aes_arm_encrypt_block)
-       (_gcry_aes_arm_decrypt_block): Ditto.
-       * cipher/rijndael-internal.h (RIJNDAEL_context_s)
-       (rijndael_cryptfn_t): New.
-       (RIJNDAEL_context): New members 'encrypt_fn' and 'decrypt_fn'.
-       * cipher/rijndael.c (_gcry_aes_amd64_encrypt_block)
-       (_gcry_aes_amd64_decrypt_block, _gcry_aes_aesni_encrypt)
-       (_gcry_aes_aesni_decrypt, _gcry_aes_arm_encrypt_block)
-       (_gcry_aes_arm_decrypt_block): Change prototypes.
-       (do_padlock_encrypt, do_padlock_decrypt): New.
-       (do_setkey): Separate key-length to rounds conversion from
-       HW features check; Add selection for ctx->encrypt_fn and
-       ctx->decrypt_fn.
-       (do_encrypt_aligned, do_decrypt_aligned): Move inside
-       '[!USE_AMD64_ASM && !USE_ARM_ASM]'; Move USE_AMD64_ASM and
-       USE_ARM_ASM to...
-       (do_encrypt, do_decrypt): ...here; Return stack depth; Remove second
-       temporary buffer from non-aligned input/output case.
-       (do_padlock): Move decrypt_flag to last argument; Return stack depth.
-       (rijndael_encrypt): Remove #ifdefs, just call ctx->encrypt_fn.
-       (_gcry_aes_cfb_enc, _gcry_aes_cbc_enc): Remove USE_PADLOCK; Call
-       ctx->encrypt_fn in place of do_encrypt/do_encrypt_aligned.
-       (_gcry_aes_ctr_enc): Call ctx->encrypt_fn in place of
-       do_encrypt_aligned; Make tmp buffer 16-byte aligned and wipe buffer
-       after use.
-       (rijndael_encrypt): Remove #ifdefs, just call ctx->decrypt_fn.
-       (_gcry_aes_cfb_dec): Remove USE_PADLOCK; Call ctx->decrypt_fn in place
-       of do_decrypt/do_decrypt_aligned.
-       (_gcry_aes_cbc_dec): Ditto; Make savebuf buffer 16-byte aligned.
-
-       rijndael: move AES-NI blocks before Padlock.
-       + commit dbf9e95dd3891f6e6ad370e8ab78fec03595687b
-       * cipher/rijndael.c (do_setkey, rijndael_encrypt, _gcry_aes_cfb_enc)
-       (rijndael_decrypt, _gcry_aes_cfb_dec): Move USE_AESNI before
-       USE_PADLOCK.
-       (check_decryption_praparation) [USE_PADLOCK]: Move to...
-       (prepare_decryption) [USE_PADLOCK]: ...here.
-
-       rijndael: split AES-NI functions to separate file.
-       + commit 67d529630e838daeb8cb9c6d7ef660c01ef34fee
-       * cipher/Makefile.in: Add 'rijndael-aesni.c'.
-       * cipher/rijndael-aesni.c: New.
-       * cipher/rijndael-internal.h: New.
-       * cipher/rijndael.c (MAXKC, MAXROUNDS, BLOCKSIZE, ATTR_ALIGNED_16)
-       (USE_AMD64_ASM, USE_ARM_ASM, USE_PADLOCK, USE_AESNI, RIJNDAEL_context)
-       (keyschenc, keyschdec, padlockkey): Move to 'rijndael-internal.h'.
-       (u128_s, aesni_prepare, aesni_cleanup, aesni_cleanup_2_6)
-       (aesni_do_setkey, do_aesni_enc, do_aesni_dec, do_aesni_enc_vec4)
-       (do_aesni_dec_vec4, do_aesni_cfb, do_aesni_ctr, do_aesni_ctr_4): Move
-       to 'rijndael-aesni.c'.
-       (prepare_decryption, rijndael_encrypt, _gcry_aes_cfb_enc)
-       (_gcry_aes_cbc_enc, _gcry_aes_ctr_enc, rijndael_decrypt)
-       (_gcry_aes_cfb_dec, _gcry_aes_cbc_dec) [USE_AESNI]: Move to functions
-       in 'rijdael-aesni.c'.
-       * configure.ac [mpi_cpu_arch=x86]: Add 'rijndael-aesni.lo'.
-
-2014-11-24  Werner Koch  <wk@gnupg.org>
-
-       Remove duplicated prototypes.
-       + commit d53ea84bed37b973f7ce59262c50b33700cd8311
-       * src/gcrypt-int.h (_gcry_mpi_ec_new, _gcry_mpi_ec_set_mpi)
-       (gcry_mpi_ec_set_point): Remove.
-
-       tests: Add a prime mode to benchmark.
-       + commit 1b4210c204a5ef5e631187509e011b8468a134ef
-       * tests/benchmark.c (progress_cb): Add a single char mode.
-       (prime_bench): New.
-       (main): Add a "prime" mode.  Factor with_progress out to file scope.
-
-2014-11-19  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Improve Montgomery curve implementation.
-       + commit e6130034506013d6153465a2bedb6fb08a43f74d
-       * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Support
-       MPI_EC_MONTGOMERY.
-       * cipher/ecc.c (test_ecdh_only_keys): New.
-       (nist_generate_key): Call test_ecdh_only_keys for MPI_EC_MONTGOMERY.
-       (check_secret_key): Handle Montgomery curve of x-coordinate only.
-       * mpi/ec.c (_gcry_mpi_ec_mul_point): Resize points before the loop.
-       Simplify, using pointers of Q1, Q2, PRD, and SUM.
-
-2014-11-02  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Disable NEON for CPUs that are known to have broken NEON implementation.
-       + commit 95eef21583d8e998efc48f22898c1ae31b77cb48
-       * src/hwf-arm.c (detect_arm_proc_cpuinfo): Add parsing for CPU version
-       information and check if CPU is known to have broken NEON
-       implementation.
-       (_gcry_hwf_detect_arm): Filter out broken HW features.
-
-       Add ARM/NEON implementation of Poly1305.
-       + commit 0b520128551054d83fb0bb2db8873394f38de498
-       * cipher/Makefile.am: Add 'poly1305-armv7-neon.S'.
-       * cipher/poly1305-armv7-neon.S: New.
-       * cipher/poly1305-internal.h (POLY1305_USE_NEON)
-       (POLY1305_NEON_BLOCKSIZE, POLY1305_NEON_STATESIZE)
-       (POLY1305_NEON_ALIGNMENT): New.
-       * cipher/poly1305.c [POLY1305_USE_NEON]
-       (_gcry_poly1305_armv7_neon_init_ext)
-       (_gcry_poly1305_armv7_neon_finish_ext)
-       (_gcry_poly1305_armv7_neon_blocks, poly1305_armv7_neon_ops): New.
-       (_gcry_poly1305_init) [POLY1305_USE_NEON]: Select NEON implementation
-       if HWF_ARM_NEON set.
-       * configure.ac [neonsupport=yes]: Add 'poly1305-armv7-neon.lo'.
-
-       chacha20: add ARMv7/NEON implementation.
-       + commit c584f44543883346d5a565581ff99a0afce9c5e1
-       * cipher/Makefile.am: Add 'chacha20-armv7-neon.S'.
-       * cipher/chacha20-armv7-neon.S: New.
-       * cipher/chacha20.c (USE_NEON): New.
-       [USE_NEON] (_gcry_chacha20_armv7_neon_blocks): New.
-       (chacha20_do_setkey) [USE_NEON]: Use Neon implementation if
-       HWF_ARM_NEON flag set.
-       (selftest): Self-test encrypting buffer byte by byte.
-       * configure.ac [neonsupport=yes]: Add 'chacha20-armv7-neon.lo'.
-
-2014-10-08  Markus Teich  <markus.teich@stusta.mhn.de>
-
-       mpi: Add gcry_mpi_ec_sub.
-       + commit 23ecadf309f8056c35cc092e58df801ac0eab862
-       * NEWS (gcry_mpi_ec_sub): New.
-       * doc/gcrypt.texi (gcry_mpi_ec_sub): New.
-       * mpi/ec.c (_gcry_mpi_ec_sub, sub_points_edwards): New.
-       (sub_points_montgomery, sub_points_weierstrass): New stubs.
-       * src/gcrypt-int.h (_gcry_mpi_ec_sub): New.
-       * src/gcrypt.h.in (gcry_mpi_ec_sub): New.
-       * src/libgcrypt.def (gcry_mpi_ec_sub): New.
-       * src/libgcrypt.vers (gcry_mpi_ec_sub): New.
-       * src/mpi.h (_gcry_mpi_ec_sub_points): New.
-       * src/visibility.c (gcry_mpi_ec_sub): New.
-       * src/visibility.h (gcry_mpi_ec_sub): New.
-
-2014-10-08  Werner Koch  <wk@gnupg.org>
-
-       Fix prime test for 2 and lower and add check command to mpicalc.
-       + commit 5c906e2cdb14e93fb4915fdc69c7353a5fa35709
-       * cipher/primegen.c (check_prime): Return true for the small primes.
-       (_gcry_prime_check): Return correct values for 2 and lower numbers.
-
-       * src/mpicalc.c (do_primecheck): New.
-       (main): Add command 'P'.
-       (main): Allow for larger input data.
-
-2014-10-04  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add Whirlpool AMD64/SSE2 assembly implementation.
-       + commit de0ccd4dce7ec185a678d78878d4538dd609ca0f
-       * cipher/Makefile.am: Add 'whirlpool-sse2-amd64.S'.
-       * cipher/whirlpool-sse2-amd64.S: New.
-       * cipher/whirlpool.c (USE_AMD64_ASM): New.
-       (whirlpool_tables_s): New.
-       (rc, C0, C1, C2, C3, C4, C5, C6, C7): Combine these tables into single
-       structure and replace old tables with macros of same name.
-       (tab): New structure containing above tables.
-       [USE_AMD64_ASM] (_gcry_whirlpool_transform_amd64)
-       (whirlpool_transform): New.
-       * configure.ac [host=x86_64]: Add 'whirlpool-sse2-amd64.lo'.
-
-2014-10-04  Andrei Scherer  <andsch@inbox.com>
-
-       Improved ripemd160 performance.
-       + commit 30bd759f398f45b04d0a783b875f59ce9bd1e51d
-       * cipher/rmd160.c (transform): Interleave the left and right lane
-       rounds to introduce more instruction level parallelism.
-
-2014-10-02  Werner Koch  <wk@gnupg.org>
-
-       build: Document SYSROOT.
-       + commit 0ecd136a6ca02252f63ad229fa5240897bfe6544
-       * configure.ac: Mark SYSROOT as arg var.
-
-       build: Support SYSROOT based config script finding.
-       + commit 1e8b86494cf8fa045696bd447b16267ffd1797f0
-       * src/libgcrypt.m4: Add support for SYSROOT and set
-       gpg_config_script_warn.  Use AC_PATH_PROG instead of AC_PATH_TOOL
-       because the config script is not expected to be installed with a
-       prefix for its name
-       * configure.ac: Print a library mismatch warning.
-       * m4/gpg-error.m4: Update from git master.
-
-2014-09-30  Werner Koch  <wk@gnupg.org>
-
-       mac: Fix gcry_mac_close to allow for a NULL handle.
-       + commit 51dae8c8c4b63bb5e1685cbd8722e35342524737
-       * cipher/mac.c (_gcry_mac_close): Check for NULL.
-
-2014-09-03  Werner Koch  <wk@gnupg.org>
-
-       Add a constant for a forthcoming new RNG.
-       + commit 8b960a807d168000d2690897a7634bd384ac1346
-       * src/gcrypt.h.in (GCRYCTL_DRBG_REINIT): New constant.
-
-2014-09-02  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add new Poly1305 MAC test vectors.
-       + commit 8a2a328742012a7c528dd007437185e4584c1e48
-       * tests/basic.c (check_mac): Add new test vectors for Poly1305 MAC.
-
-2014-09-02  Werner Koch  <wk@gnupg.org>
-
-       asm: Allow building x86 and amd64 using old compilers.
-       + commit 5eec04a43e6c562e956353449be931dd43dfe1cc
-       * src/hwf-x86.c (get_xgetbv): Build only if AVX support is enabled.
-
-2014-08-21  Werner Koch  <wk@gnupg.org>
-
-       sexp: Check args of gcry_sexp_build.
-       + commit e606d5f1bada1f2d21faeedd3fa2cf2dca7b274c
-       * src/sexp.c (do_vsexp_sscan): Return error for invalid args.
-
-       cipher: Fix a segv in case of calling with wrong parameters.
-       + commit f850add813d783f31ca6a60459dea25ef71bce7e
-       * cipher/md.c (_gcry_md_info): Fix arg testing.
-
-       cipher: Fix possible NULL deref in call to prime generator.
-       + commit 18056ace7f466cb8c1eaf08e5dc0400516d83b4c
-       * cipher/primegen.c (_gcry_generate_elg_prime): Change to return an
-       error code.
-       * cipher/dsa.c (generate): Take care of new return code.
-       * cipher/elgamal.c (generate): Change to return an error code.  Take
-       care of _gcry_generate_elg_prime return code.
-       (generate_using_x): Take care of _gcry_generate_elg_prime return code.
-       (elg_generate): Propagate return code from generate.
-
-2014-08-12  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Support Montgomery curve for gcry_mpi_ec_mul_point.
-       + commit 34bb55ee36df3aca3ebca88f8b61c786cd0c0701
-       * mpi/ec.c (_gcry_mpi_ec_get_affine): Support Montgomery curve.
-       (montgomery_ladder): New.
-       (_gcry_mpi_ec_mul_point): Implemention using montgomery_ladder.
-       (_gcry_mpi_ec_curve_point): Check x-coordinate is valid.
-
-2014-08-09  Werner Koch  <wk@gnupg.org>
-
-       tests: Add a benchmark for Elgamal.
-       + commit e6d354865bf8f3d4c1bb5e8157a76fdd442cff41
-       * tests/benchmark.c (sample_public_elg_key_1024): New.
-       (sample_private_elg_key_1024): New.
-       (sample_public_elg_key_2048, sample_private_elg_key_2048): New.
-       (sample_public_elg_key_3072, sample_private_elg_key_3072): New.
-       (elg_bench): New.
-       (main): Add elg_bench.  Add commands "elg" and "public".
-
-2014-08-08  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Add cofactor to domain parameters.
-       + commit 9933b9e5e1a3f5b1019c75f93bd265d4a1ecc270
-       * src/ec-context.h (mpi_ec_ctx_s): Add cofactor 'h'.
-       * cipher/ecc-common.h (elliptic_curve_t): Add cofactor 'h'.
-       (_gcry_ecc_update_curve_param): New API adding cofactor.
-
-       * cipher/ecc-curves.c (ecc_domain_parms_t): Add cofactor 'h'.
-       (ecc_domain_parms_t domain_parms): Add cofactors.
-       (_gcry_ecc_fill_in_curve, _gcry_ecc_update_curve_param)
-       (_gcry_ecc_get_curve, _gcry_mpi_ec_new, _gcry_ecc_get_param_sexp)
-       (_gcry_ecc_get_mpi): Handle cofactor.
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_genkey): Likewise.
-       * cipher/ecc-misc.c (_gcry_ecc_curve_free)
-       (_gcry_ecc_curve_copy): Likewise.
-       * cipher/ecc.c (nist_generate_key, ecc_generate)
-       (ecc_check_secret_key, ecc_sign, ecc_verify, ecc_encrypt_raw)
-       (ecc_decrypt_raw, _gcry_pk_ecc_get_sexp, _gcry_pubkey_spec_ecc):
-       Likewise.
-       (compute_keygrip): Handle cofactor, but skip it for its computation.
-       * mpi/ec.c (ec_deinit): Likewise.
-       * tests/t-mpi-point.c (context_param): Likewise.
-       (test_curve): Add cofactors.
-       * tests/curves.c (sample_key_1, sample_key_2): Add cofactors.
-       * tests/keygrip.c (key_grips): Add cofactors.
-
-2014-08-05  Werner Koch  <wk@gnupg.org>
-
-       mpi: Fix regression for powerpc-apple-darwin detection.
-       + commit 4ce77b0a810d3c889c07dfb385127d90fa1ae36a
-       * mpi/config.links: Add separate entry for powerpc-apple-darwin.
-
-       Fix bug inhibiting the use of the sentinel attribute.
-       + commit d2d28298ccc0d0f3c0b03fd323deb1e8808ef74f
-       * src/gcrypt.h.in: Fix typo in macro.
-
-       mpi: Use BSD syntax for x86_64-apple-darwin.
-       + commit 71939faa7c54e7b4b28d115e748a85f134876a02
-       * mpi/config.links: Add case for x86_64-apple-darwin.
-
-2014-08-05  Kristian Fiskerstrand  <kf@sumptuouscapital.com>
-
-       Fix building for the x32 target without asm modules.
-       + commit a17c29844b63e9e869f7855d901bc9d859234ead
-       * mpi/generic/mpi-asm-defs.h: Use a fixed value for the x32 ABI.
-
-2014-07-25  Werner Koch  <wk@gnupg.org>
-
-       ecc: Support the non-standard 0x40 compression flag for EdDSA.
-       + commit 4556f9b19c024f16bdf542da7173395c0741b91d
-       * cipher/ecc.c (ecc_generate): Check the "comp" flag for EdDSA.
-       * cipher/ecc-eddsa.c (eddsa_encode_x_y): Add arg WITH_PREFIX.
-       (_gcry_ecc_eddsa_encodepoint): Ditto.
-       (_gcry_ecc_eddsa_ensure_compact): Handle the 0x40 compression prefix.
-       (_gcry_ecc_eddsa_decodepoint): Ditto.
-       * tests/keygrip.c: Check an compresssed with prefix Ed25519 key.
-       * tests/t-ed25519.inp: Ditto.
-
-       mpi: Extend the internal mpi_get_buffer.
-       + commit 0e10902ad7584277ac966367efc712b183784532
-       * mpi/mpicoder.c (do_get_buffer): Add arg EXTRAALLOC.
-       (_gcry_mpi_get_buffer_extra): New.
-
-       cipher: Fix compiler warning for chacha20.
-       + commit 4e0bf1b9190ce08fb23eb3ae0c3be58954ff36ab
-       * cipher/chacha20.c (chacha20_blocks) [!USE_SSE2]: Do not build.
-
-2014-07-16  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: Add mpi_swap_cond.
-       + commit 4846e52728970e3117f3a046ef9010be089a3ae4
-       * mpi/mpiutil.c (_gcry_mpi_swap_cond): New.
-       * src/mpi.h (mpi_swap_cond): New.
-
-2014-06-29  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Speed-up SHA-1 NEON assembly implementation.
-       + commit 1b9b00bbe41bbed32563f1102049521e703e72bd
-       * cipher/sha1-armv7-neon.S: Tweak implementation for speed-up.
-
-2014-06-28  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       gostr3411_94: rewrite to use u32 mathematic.
-       + commit 066f068bd0bc4d8e01f1f18b6153cdc8d2c245d7
-       * cipher/gost28147.c (_gcry_gost_enc_data): New.
-       * cipher/gostr3411-94.c: Rewrite implementation to use u32 mathematic
-         internally.
-       * cipher/gost28147.c (_gcry_gost_enc_one): Remove.
-
-       gost28147: use bufhelp helpers.
-       + commit 7aeba6c449169926076df83b01ddbfa6b41fe411
-       * cipher/gost28147.c (gost_setkey, gost_encrypt_block, gost_decrypt_block):
-         use buf_get_le32/buf_put_le32 helpers.
-
-       Fixup curve name in the GOST2012 test case.
-       + commit b78d504fa8745b8b04589acbbcf7dd5fe9279d13
-       * tests/basic.c (check_pubkey): fixup curve name in public key.
-
-       Update PBKDF2 tests with GOST R 34.11-94 test cases.
-       + commit 7533b2ad46f42e98d9dba52e88e79c0311d2d3b7
-       * tests/t-kdf.c (check_pbkdf2): Add MD_GOSTR3411_CP test cases.
-
-       Add GOST R 34.11-94 variant using id-GostR3411-94-CryptoProParamSet.
-       + commit 25d6af77e2336b5979ddbe8b90978fe5b61dfaf9
-       * src/gcrypt.h.in (GCRY_MD_GOSTR3411_CP): New.
-       * src/cipher.h (_gcry_digest_spec_gost3411_cp): New.
-       * cipher/gost28147.c (_gcry_gost_enc_one): Differentiate between
-         CryptoPro and Test S-Boxes.
-       * cipher/gostr3411-94.c (_gcry_digest_spec_gost3411_cp,
-         gost3411_cp_init): New.
-       * cipher/md.c (md_open): GCRY_MD_GOSTR3411_CP also uses B=32.
-
-       gost28147: support GCRYCTL_SET_SBOX.
-       + commit 5ee35a04362c94e680ef3633fa83b72e0aee8626
-       cipher/gost28147.c (gost_set_extra_info, gost_set_sbox): New.
-
-       Support setting s-box for the ciphers that require it.
-       + commit fb074d113fcbf66a5c20592625cb19051f3430f5
-       * src/gcrypt.h.in (GCRYCTL_SET_SBOX, gcry_cipher_set_sbox): New.
-       * cipher/cipher.c (_gcry_cipher_ctl): pass GCRYCTL_SET_SBOX to
-         set_extra_info callback.
-
-       cipher/gost28147: generate optimized s-boxes from compact ones.
-       + commit 164738a0292b3f32c7747099ad9cadace58e5eda
-       * cipher/gost-s-box.c: New. Outputs optimized expanded representation of
-         s-boxes (4x256) from compact 16x8 representation.
-       * cipher/Makefile.am: Add gost-sb.h dependency to gost28147.lo
-       * cipher/gost.h: Add sbox to the GOST28147_context structure.
-       * cipher/gost28147.c (gost_setkey): Set default s-box to test s-box from
-         GOST R 34.11 (this was the only one S-box before).
-       * cipher/gost28147.c (gost_val): Use sbox from the context.
-
-       gost28147: add OIDs used to define cipher mode.
-       + commit 34a58010000288515636706811c3837f32957b2e
-       * cipher/gost28147 (oids_gost28147): Add OID from RFC4357.
-
-       GOST R 34.11-94 add OIDs.
-       + commit 8b221cf5ce233c8c49a4e4ecebb70d523fc37837
-       * cipher/gostr3411-94.c: Add OIDs for GOST R 34.11-94 from RFC 4357.
-
-2014-05-21  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       tests: add larger test-vectors for hash algorithms.
-       + commit f14fb5b427b5159fcd9603d2b3cde936889cf430
-       * tests/basic.c (check_digests): Add large test-vectors for MD5, SHA1,
-       SHA224, SHA256, SHA384, RMD160, CRC32, TIGER1, WHIRLPOOL and
-       GOSTR3411_94.
-
-       sha512: fix ARM/NEON implementation.
-       + commit beb901575f0d6cd6a0a27506ebea9a725754d0cc
-       * cipher/sha512-armv7-neon.S
-       (_gcry_sha512_transform_armv7_neon): Byte-swap RW67q and RW1011q
-       correctly in multi-block loop.
-       * tests/basic.c (check_digests): Add large test vector for SHA512.
-
-2014-05-20  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix ARM assembly when building __PIC__
-       + commit 994c758d8f5471c7e9c38c2834742cca2502d35f
-       * cipher/camellia-arm.S (GET_DATA_POINTER): New.
-       (_gcry_camellia_arm_encrypt_block): Use GET_DATA_POINTER.
-       (_gcry_camellia_arm_decrypt_block): Ditto.
-       * cipher/cast5-arm.S (GET_DATA_POINTER): New.
-       (_gcry_cast5_arm_encrypt_block, _gcry_cast5_arm_decrypt_block)
-       (_gcry_cast5_arm_enc_blk2, _gcry_cast5_arm_dec_blk2): Use
-       GET_DATA_POINTER.
-       * cipher/rijndael-arm.S (GET_DATA_POINTER): New.
-       (_gcry_aes_arm_encrypt_block, _gcry_aes_arm_decrypt_block): Use
-       GET_DATA_POINTER.
-       * cipher/sha1-armv7-neon.S (GET_DATA_POINTER): New.
-       (.LK_VEC): Move from .text to .data section.
-       (_gcry_sha1_transform_armv7_neon): Use GET_DATA_POINTER.
-
-2014-05-17  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add Poly1305 to documentation.
-       + commit bf4943932dae95a0573b63bf32a9b9acd5a6ddf3
-       * doc/gcrypt.texi: Add documentation for Poly1305 MACs and AEAD mode.
-
-2014-05-16  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       chacha20: add SSE2/AMD64 optimized implementation.
-       + commit 323b1eb80ff3396d83fedbe5bba9a4e6c412d192
-       * cipher/Makefile.am: Add 'chacha20-sse2-amd64.S'.
-       * cipher/chacha20-sse2-amd64.S: New.
-       * cipher/chacha20.c (USE_SSE2): New.
-       [USE_SSE2] (_gcry_chacha20_amd64_sse2_blocks): New.
-       (chacha20_do_setkey) [USE_SSE2]: Use SSE2 implementation for blocks
-       function.
-       * configure.ac [host=x86-64]: Add 'chacha20-sse2-amd64.lo'.
-
-       poly1305: add AMD64/AVX2 optimized implementation.
-       + commit 98f021961ee65669037bc8bb552a69fd78f610fc
-       * cipher/Makefile.am: Add 'poly1305-avx2-amd64.S'.
-       * cipher/poly1305-avx2-amd64.S: New.
-       * cipher/poly1305-internal.h (POLY1305_USE_AVX2)
-       (POLY1305_AVX2_BLOCKSIZE, POLY1305_AVX2_STATESIZE)
-       (POLY1305_AVX2_ALIGNMENT): New.
-       (POLY1305_LARGEST_BLOCKSIZE, POLY1305_LARGEST_STATESIZE)
-       (POLY1305_STATE_ALIGNMENT): Use AVX2 versions when needed.
-       * cipher/poly1305.c [POLY1305_USE_AVX2]
-       (_gcry_poly1305_amd64_avx2_init_ext)
-       (_gcry_poly1305_amd64_avx2_finish_ext)
-       (_gcry_poly1305_amd64_avx2_blocks, poly1305_amd64_avx2_ops): New.
-       (_gcry_poly1305_init) [POLY1305_USE_AVX2]: Use AVX2 implementation if
-       AVX2 supported by CPU.
-       * configure.ac [host=x86_64]: Add 'poly1305-avx2-amd64.lo'.
-
-2014-05-12  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       poly1305: add AMD64/SSE2 optimized implementation.
-       + commit 297532602ed2d881d8fdc393d1961068a143a891
-       * cipher/Makefile.am: Add 'poly1305-sse2-amd64.S'.
-       * cipher/poly1305-internal.h (POLY1305_USE_SSE2)
-       (POLY1305_SSE2_BLOCKSIZE, POLY1305_SSE2_STATESIZE)
-       (POLY1305_SSE2_ALIGNMENT): New.
-       (POLY1305_LARGEST_BLOCKSIZE, POLY1305_LARGEST_STATESIZE)
-       (POLY1305_STATE_ALIGNMENT): Use SSE2 versions when needed.
-       * cipher/poly1305-sse2-amd64.S: New.
-       * cipher/poly1305.c [POLY1305_USE_SSE2]
-       (_gcry_poly1305_amd64_sse2_init_ext)
-       (_gcry_poly1305_amd64_sse2_finish_ext)
-       (_gcry_poly1305_amd64_sse2_blocks, poly1305_amd64_sse2_ops): New.
-       (_gcry_polu1305_init) [POLY1305_USE_SSE2]: Use SSE2 version.
-       * configure.ac [host=x86_64]: Add 'poly1305-sse2-amd64.lo'.
-
-       Add Poly1305 based cipher AEAD mode.
-       + commit e813958419b0ec4439e6caf07d3b2234cffa2bfa
-       * cipher/Makefile.am: Add 'cipher-poly1305.c'.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode.poly1305'.
-       (_gcry_cipher_poly1305_encrypt, _gcry_cipher_poly1305_decrypt)
-       (_gcry_cipher_poly1305_setiv, _gcry_cipher_poly1305_authenticate)
-       (_gcry_cipher_poly1305_get_tag, _gcry_cipher_poly1305_check_tag): New.
-       * cipher/cipher-poly1305.c: New.
-       * cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey)
-       (cipher_reset, cipher_encrypt, cipher_decrypt, _gcry_cipher_setiv)
-       (_gcry_cipher_authenticate, _gcry_cipher_gettag)
-       (_gcry_cipher_checktag): Handle 'GCRY_CIPHER_MODE_POLY1305'.
-       (cipher_setiv): Move handling of 'GCRY_CIPHER_MODE_GCM' to ...
-       (_gcry_cipher_setiv): ... here, as with other modes.
-       * src/gcrypt.h.in: Add 'GCRY_CIPHER_MODE_POLY1305'.
-       * tests/basic.c (_check_poly1305_cipher, check_poly1305_cipher): New.
-       (check_ciphers): Add Poly1305 check.
-       (check_cipher_modes): Call 'check_poly1305_cipher'.
-       * tests/bench-slope.c (bench_gcm_encrypt_do_bench): Rename to
-       bench_aead_... and take nonce as argument.
-       (bench_gcm_decrypt_do_bench, bench_gcm_authenticate_do_bench): Ditto.
-       (bench_gcm_encrypt_do_bench, bench_gcm_decrypt_do_bench)
-       (bench_gcm_authenticate_do_bench, bench_poly1305_encrypt_do_bench)
-       (bench_poly1305_decrypt_do_bench)
-       (bench_poly1305_authenticate_do_bench, poly1305_encrypt_ops)
-       (poly1305_decrypt_ops, poly1305_authenticate_ops): New.
-       (cipher_modes): Add Poly1305.
-       (cipher_bench_one): Add special handling for Poly1305.
-
-       Add Poly1305-AES (-Camellia, etc) MACs.
-       + commit 73b3b75c2221a6e3bed4117e0a206a1193acd2ed
-       * cipher/mac-internal.h (_gcry_mac_type_spec_poly1305_aes)
-       (_gcry_mac_type_spec_poly1305_camellia)
-       (_gcry_mac_type_spec_poly1305_twofish)
-       (_gcry_mac_type_spec_poly1305_serpent)
-       (_gcry_mac_type_spec_poly1305_seed): New.
-       * cipher/mac-poly1305.c (poly1305mac_context_s): Add 'hd' and
-       'nonce_set'.
-       (poly1305mac_open, poly1305mac_close, poly1305mac_setkey): Add handling
-       for Poly1305-*** MACs.
-       (poly1305mac_prepare_key, poly1305mac_setiv): New.
-       (poly1305mac_reset, poly1305mac_write, poly1305mac_read): Add handling
-       for 'nonce_set'.
-       (poly1305mac_ops): Add 'poly1305mac_setiv'.
-       (_gcry_mac_type_spec_poly1305_aes)
-       (_gcry_mac_type_spec_poly1305_camellia)
-       (_gcry_mac_type_spec_poly1305_twofish)
-       (_gcry_mac_type_spec_poly1305_serpent)
-       (_gcry_mac_type_spec_poly1305_seed): New.
-       * cipher/mac.c (mac_list): Add Poly1305-AES, Poly1305-Twofish,
-       Poly1305-Serpent, Poly1305-SEED and Poly1305-Camellia.
-       * src/gcrypt.h.in: Add 'GCRY_MAC_POLY1305_AES',
-       'GCRY_MAC_POLY1305_CAMELLIA', 'GCRY_MAC_POLY1305_TWOFISH',
-       'GCRY_MAC_POLY1305_SERPENT' and 'GCRY_MAC_POLY1305_SEED'.
-       * tests/basic.c (check_mac): Add Poly1305-AES test vectors.
-       * tests/bench-slope.c (bench_mac_init): Set IV for Poly1305-*** MACs.
-       * tests/bench-slope.c (mac_bench): Set IV for Poly1305-*** MACs.
-
-       Add Poly1305 MAC.
-       + commit b8794fed68ebe7567f4617141f0996ad290d9120
-       * cipher/Makefile.am: Add 'mac-poly1305.c', 'poly1305.c' and
-       'poly1305-internal.h'.
-       * cipher/mac-internal.h (poly1305mac_context_s): New.
-       (gcry_mac_handle): Add 'u.poly1305mac'.
-       (_gcry_mac_type_spec_poly1305mac): New.
-       * cipher/mac-poly1305.c: New.
-       * cipher/mac.c (mac_list): Add Poly1305.
-       * cipher/poly1305-internal.h: New.
-       * cipher/poly1305.c: New.
-       * src/gcrypt.h.in: Add 'GCRY_MAC_POLY1305'.
-       * tests/basic.c (check_mac): Add Poly1035 test vectors; Allow
-       overriding lengths of data and key buffers.
-       * tests/bench-slope.c (mac_bench): Increase max algo number from 500 to
-       600.
-       * tests/benchmark.c (mac_bench): Ditto.
-
-       chacha20/AVX2: clear upper-halfs of YMM registers on entry.
-       + commit c20daeeb05329bfc6cc2c562cbd4b965291fe0e1
-       * cipher/chacha20-avx2-amd64.S (_gcry_chacha20_amd64_avx2_blocks): Add
-       'vzeroupper' at beginning.
-
-       chacha20/AVX2: check for ENABLE_AVX2_SUPPORT instead of HAVE_GCC_INLINE_ASM_AVX2
-       + commit a3062db748f272e0f7346e1ed9e0bf7ed61a4eae
-       * cipher/chacha20.c (USE_AVX2): Enable depending on
-       ENABLE_AVX2_SUPPORT, not HAVE_GCC_INLINE_ASM_AVX2.
-       * cipher/chacha20-avx2-amd64.S: Ditto.
-
-       chacha20/SSSE3: clear XMM registers after use.
-       + commit a7d9eeeba632b7eb4a5b15ff17f6565181642f3c
-       * cipher/chacha20-ssse3-amd64.S (_gcry_chacha20_amd64_ssse3_blocks): On
-       return, clear XMM registers.
-
-2014-05-11  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       chacha20: add AVX2/AMD64 assembly implementation.
-       + commit a39ee7555691d18cae97560f130aaf952bfbd278
-       * cipher/Makefile.am: Add 'chacha20-avx2-amd64.S'.
-       * cipher/chacha20-avx2-amd64.S: New.
-       * cipher/chacha20.c (USE_AVX2): New macro.
-       [USE_AVX2] (_gcry_chacha20_amd64_avx2_blocks): New.
-       (chacha20_do_setkey): Select AVX2 implementation if there is HW
-       support.
-       (selftest): Increase size of buf by 256.
-       * configure.ac [host=x86-64]: Add 'chacha20-avx2-amd64.lo'.
-
-       chacha20: add SSSE3 assembly implementation.
-       + commit def7d4cad386271c6d4e2f10aabe0cb4abd871e4
-       * cipher/Makefile.am: Add 'chacha20-ssse3-amd64.S'.
-       * cipher/chacha20-ssse3-amd64.S: New.
-       * cipher/chacha20.c (USE_SSSE3): New macro.
-       [USE_SSSE3] (_gcry_chacha20_amd64_ssse3_blocks): New.
-       (chacha20_do_setkey): Select SSSE3 implementation if there is HW
-       support.
-       * configure.ac [host=x86-64]: Add 'chacha20-ssse3-amd64.lo'.
-
-       Add ChaCha20 stream cipher.
-       + commit 23f33d57c9b6f2295a8ddfc9a8eee5a2c30cf406
-       * cipher/Makefile.am: Add 'chacha20.c'.
-       * cipher/chacha20.c: New.
-       * cipher/cipher.c (cipher_list): Add ChaCha20.
-       * configure.ac: Add ChaCha20.
-       * doc/gcrypt.texi: Add ChaCha20.
-       * src/cipher.h (_gcry_cipher_spec_chacha20): New.
-       * src/gcrypt.h.in (GCRY_CIPHER_CHACHA20): Add new algo.
-       * tests/basic.c (MAX_DATA_LEN): Increase to 128 from 100.
-       (check_stream_cipher): Add ChaCha20 test-vectors.
-       (check_ciphers): Add ChaCha20.
-
-2014-05-09  Werner Koch  <wk@gnupg.org>
-
-       mpi: Fix a subtle bug setting spurious bits with in mpi_set_bit.
-       + commit 246b7aaae1ee459f440260bbc4ec2c01c5dc3362
-       * mpi/mpi-bit.c (_gcry_mpi_set_bit, _gcry_mpi_set_highbit): Clear
-       allocated but not used bits before resizing.
-       * tests/t-mpi-bits.c (set_bit_with_resize): New.
-
-2014-05-07  Werner Koch  <wk@gnupg.org>
-
-       Bump LT version.
-       + commit fc6ff6f73a51bcbbbb3757dc1386da40aa3ae75d
-       * configure.ac: Bumb LT version to C21/A1/R0.
-
-2014-04-22  Werner Koch  <wk@gnupg.org>
-
-       random: Small patch for consistency and really burn the stack.
-       + commit a79c4ad7c56ee4410f17beb73eeb58b0dd36bfc6
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): s/int/size_t/.
-       (_gcry_rndlinux_gather_random): Replace memset by wipememory.
-
-2014-04-16  Werner Koch  <wk@gnupg.org>
-
-       pubkey: Re-map all depreccated RSA algo numbers.
-       + commit 773e23698218755e9172d2507031a8263c47cc0b
-       * cipher/pubkey.c (map_algo): Mape RSA_E and RSA_S.
-
-2014-04-15  Werner Koch  <wk@gnupg.org>
-
-       cipher: Fix possible NULL dereference.
-       + commit ae1fbce6dacf14747af0126e640bd4e54cb8c680
-       * cipher/md.c (_gcry_md_selftest): Check for spec being NULL.
-
-2014-03-30  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       3des: add amd64 assembly implementation for 3DES.
-       + commit b76b632a453b8d100d024e2439b4358454dc286e
-       * cipher/Makefile.am: Add 'des-amd64.S'.
-       * cipher/cipher-selftests.c (_gcry_selftest_helper_cbc)
-       (_gcry_selftest_helper_cfb, _gcry_selftest_helper_ctr): Handle failures
-       from 'setkey' function.
-       * cipher/cipher.c (_gcry_cipher_open_internal) [USE_DES]: Setup bulk
-       functions for 3DES.
-       * cipher/des-amd64.S: New file.
-       * cipher/des.c (USE_AMD64_ASM, ATTR_ALIGNED_16): New macros.
-       [USE_AMD64_ASM] (_gcry_3des_amd64_crypt_block)
-       (_gcry_3des_amd64_ctr_enc), _gcry_3des_amd64_cbc_dec)
-       (_gcry_3des_amd64_cfb_dec): New prototypes.
-       [USE_AMD64_ASM] (tripledes_ecb_crypt): New function.
-       (TRIPLEDES_ECB_BURN_STACK): New macro.
-       (_gcry_3des_ctr_enc, _gcry_3des_cbc_dec, _gcry_3des_cfb_dec)
-       (bulk_selftest_setkey, selftest_ctr, selftest_cbc, selftest_cfb): New
-       functions.
-       (selftest): Add call to CTR, CBC and CFB selftest functions.
-       (do_tripledes_encrypt, do_tripledes_decrypt): Use
-       TRIPLEDES_ECB_BURN_STACK.
-       * configure.ac [host=x86-64]: Add 'des-amd64.lo'.
-       * src/cipher.h (_gcry_3des_ctr_enc, _gcry_3des_cbc_dec)
-       (_gcry_3des_cfb_dec): New prototypes.
-
-2014-03-13  Werner Koch  <wk@gnupg.org>
-
-       tests: Print diagnostics for skipped tests.
-       + commit 50aeee51a0b1a09dd9fff2bb71749a816fe7a791
-       * tests/basic.c (show_note): New.
-       (show_md_not_available):
-       (show_old_hmac_not_available):
-       (show_mac_not_available):
-       (check_digests): Remove USE_foo cpp tests from the test table.  Call
-       show_md_not_available if algo is not available.
-       (check_hmac): Likewise.
-       (check_mac): Likewise.
-
-2014-03-11  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Add MD2 message digest implementation.
-       + commit 5a8e1504bf8a2ffbc018be576dea77b685200444
-       * cipher/md2.c: New.
-       * cipher/md.c (digest_list): add _gcry_digest_spec_md2.
-       * tests/basic.c (check_digests): add MD2 test vectors.
-       * configure.ac (default_digests): disable md2 by default.
-
-2014-03-04  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Add an utility to calculate hashes over a set of files.
-       + commit 2b5403c408dfbd71be24c7635f5fa0b61ab4c9bb
-       * tests/gchash.c: New.
-
-       Add a simple (raw) PKCS#1 padding mode.
-       + commit ea8d597726305274214224757b32730644e12bd8
-       * src/cipher.h (PUBKEY_ENC_PKCS1_RAW): New.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Handle pkcs1-raw
-         flag.
-       * cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi):
-         Handle s-exp like (data (flags pkcs1-raw) (value xxxxx))
-       * cipher/rsa-common.c (_gcry_rsa_pkcs1_encode_raw_for_sig):
-         PKCS#1-encode data with embedded hash OID for signature verification.
-       * tests/basic.c (check_pubkey_sign): Add tests for s-exps with pkcs1-raw
-         flag.
-
-2014-02-04  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix ARMv6 detection when CFLAGS modify target CPU architecture.
-       + commit 6be3032048ee2466511d2384fcf2d28b856219b2
-       * configure.ac (gcry_cv_cc_arm_arch_is_v6): Use compiler test instead
-       of preprocessor test.
-
-2014-01-29  Werner Koch  <wk@gnupg.org>
-
-       Reserve control code for FIPS extensions.
-       + commit aea96a64fbc58a0b6f9f435e97e93294c6eb1052
-       * src/gcrypt.h.in (GCRYCTL_INACTIVATE_FIPS_FLAG): New.
-       (GCRYCTL_REACTIVATE_FIPS_FLAG): New.
-       * src/global.c (_gcry_vcontrol): Add them but return not_implemented.
-
-2014-01-29  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Fix RSA Blinding.
-       + commit 121a90d8931944974054f7d94f63b7f89df87fa5
-       * cipher/rsa.c (rsa_decrypt): Loop to get multiplicative inverse.
-
-2014-01-28  Werner Koch  <wk@gnupg.org>
-
-       cipher: Take care of ENABLE_NEON_SUPPORT.
-       + commit 52f7c48c901a3de51bd690a218f3de2f71e8d790
-       * cipher/salsa20.c (USE_ARM_NEON_ASM): Define only if
-       ENABLE_NEON_SUPPORT is defined.
-       * cipher/serpent.c (USE_NEON): Ditto.
-       * cipher/sha1.c (USE_NEON): Ditto.
-       * cipher/sha512.c (USE_ARM_NEON_ASM): Ditto.
-
-       sexp: Fix broken gcry_sexp_nth.
-       + commit cbdc355415f83ed62da4f3618767eba54d7e6d37
-       * src/sexp.c (_gcry_sexp_nth): Return a valid S-expression for a data
-       element.
-       (NODE): Remove unused typedef.
-       (ST_HINT): Comment unused macro.
-
-       * tests/t-sexp.c (bug_1594): New.
-       (main): Run new test.
-
-2014-01-27  Werner Koch  <wk@gnupg.org>
-
-       tests: Improve t-common.h.
-       + commit 7460e9243b3cc050631c37ed4f2713ae7bcb6762
-       * tests/t-common.h: Add couple of macros.  Check that config.h has
-       been included.
-       (show): Rename to info.
-       * tests/t-lock.c, tests/t-sexp.c: Adjust for changes.
-
-       mpi: Minor fix for Atari-mint.
-       + commit 3caa0f1319dc4779e0d6eee4460c1af2a12b2c3c
-       * mpi/config.links [m68k-atari-mint]: Do not assume 68020.  Suggested
-       by Alan Hourihane.
-
-       (cherry picked from commit 420f42a5752e90a8b27d58ffa1ddfe6e4ab341e8)
-
-2014-01-27  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Fix most of memory leaks in tests code.
-       + commit 5c150ece094bf0a504a111ce6c7b72e8d0b0457a
-       * tests/basic.c (check_ccm_cipher): Close cipher after use.
-       * tests/basic.c (check_one_cipher): Correct length of used buffer.
-       * tests/benchmark.c (cipher_bench): Use xcalloc to make buffer
-         initialized.
-       * tests/keygen.c (check_ecc_keys): Release generated key.
-       * tests/t-mpi-point.c (context_param): Release mpi Q.
-       * tests/t-sexp.c (check_extract_param): Release extracted number.
-
-       Fix memory leaks in ecc code.
-       + commit 6d87e6abdfb7552323a95401f14e6367398a3e5a
-       * cipher/ecc-curves.c (_gcry_ecc_update_curve_param): Release passed mpi
-         values.
-       * cipher/ecc.c (compute_keygrip): Fix potential memory leak in error
-         path.
-       * cipher/ecc.c (_gcry_ecc_get_curve): Release temporary mpi.
-
-       Fix number of blocks passed used in _gcry_rmd160_mixblock.
-       + commit 5d23e7b9a77421f3ebfda4a84c459a8729f3bb41
-       * cipher/rmd160.c (_gcry_rmd160_mixblock): pass 1 to transform
-
-2014-01-27  Werner Koch  <wk@gnupg.org>
-
-       Small Windows build tweaks.
-       + commit f7df906171854b6b6506b82d4fee2c2ebb0327ea
-       * configure.ac (HAVE_PTHREAD): Do test when building for Windows.
-
-       * tests/basic.c: Replace "%zi" by "%z" and a cast to make it work
-       under Windows.
-
-       Update gpg-error autoconf macros to fix threading problems.
-       + commit 79da0358fd555361e1ce4202f55494a8918eb8ae
-       * m4/gpg-error.m4: Update to version 2014-01-24.
-       * tests/Makefile.am (t_lock_LDADD): Use MT Libs.
-
-2014-01-24  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       tests: Pass -no-install to libtool.
-       + commit bf34bfa5c458ee5ece91f25e3b4194d768498ab6
-       * tests/Makefile.am: add AM_LDFLAGS = -no-install
-
-2014-01-24  Werner Koch  <wk@gnupg.org>
-
-       tests: Add a test for the internal locking.
-       + commit ff91ec934ed52294cddcd7dcfacc04721a0487bf
-       * src/global.c (external_lock_test): New.
-       (_gcry_vcontrol): Call new function with formerly reserved code 61.
-
-       * tests/t-common.h: New. Taken from current libgpg-error.
-       * tests/t-lock.c: New.  Based on t-lock.c from libgpg-error.
-       * configure.ac (HAVE_PTHREAD): Set macro to 1 if defined.
-       (AC_CHECK_FUNCS): Check for flockfile.
-       * tests/Makefile.am (tests_bin): Add t-lock.
-       (noinst_HEADERS): Add t-common.h
-       (LDADD): Move value to ...
-       (default_ldadd): new.
-       (t_lock_LDADD): New.
-
-       Check compiler features only for the relevant platform.
-       + commit 24e65d715812cea28732397870cb1585b8435521
-       * mpi/config.links (mpi_cpu_arch): Always set for ARM.  Set for HPPA.
-       Set to "undefined" for unknown platforms.
-       (try_asm_modules): Act upon only after having detected the CPU.
-       * configure.ac: Move the call to config.links before the platform
-       specific compiler checks.  Check platform specific features only if
-       the platform is targeted.
-
-2014-01-23  Werner Koch  <wk@gnupg.org>
-
-       Support building using the latest mingw-w64 toolchain.
-       + commit 4ad3417acab5021db1f722c314314ce4b781833a
-       * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Change mingw detection.
-
-2014-01-20  Werner Koch  <wk@gnupg.org>
-
-       cipher: Fix commit 94030e44.
-       + commit dad06e4d1b835bac778b87090b1d3894b7535b14
-       * cipher/tiger.c (tiger_init): Add arg FLAGS.
-       (tiger1_init, tiger2_init): Ditto.
-
-       tests: Rename tsexp.c.
-       + commit 192e77d123fdb04c459c998b9eb1731618a833fa
-       * tests/tsexp.c: Rename to t-sexp.c
-
-2014-01-19  Werner Koch  <wk@gnupg.org>
-
-       md: Add Whirlpool bug emulation feature.
-       + commit 94030e44aaff805d754e368507f16dd51a531b72
-       * src/gcrypt.h.in (GCRY_MD_FLAG_BUGEMU1): New.
-       * src/cipher-proto.h (gcry_md_init_t): Add arg FLAGS.  Change all code
-       to implement that flag.
-       * cipher/md.c (gcry_md_context):  Replace SECURE and FINALIZED by bit
-       field FLAGS.  Add flag BUGEMU1.  Change all users.
-       (md_open): Replace args SECURE and HMAC by FLAGS.  Init flags.bugemu1.
-       (_gcry_md_open): Add for GCRY_MD_FLAG_BUGEMU1.
-       (md_enable): Pass bugemu1 flag to the hash init function.
-       (_gcry_md_reset): Ditto.
-
-2014-01-17  Werner Koch  <wk@gnupg.org>
-
-       Actually check for uint64_t.
-       + commit c3b30bae7d1e157f8b65e32ba1b3a516f2bbf58b
-       * configure.ac: Check size of uint64_t and the UINT64_C macro.
-
-2014-01-16  Werner Koch  <wk@gnupg.org>
-
-       Replace ath based mutexes by gpgrt based locks.
-       + commit cfc151ba637200e4fc05d9481a8df2071b2f9a47
-       * configure.ac (NEED_GPG_ERROR_VERSION): Require 1.13.
-       (gl_LOCK): Remove.
-       * src/ath.c, src/ath.h: Remove.  Remove from all files.  Replace all
-       mutexes by gpgrt based statically initialized locks.
-       * src/global.c (global_init): Remove ath_init.
-       (_gcry_vcontrol): Make ath install a dummy function.
-       (print_config): Remove threads info line.
-
-       * doc/gcrypt.texi: Simplify the multi-thread related documentation.
-
-2014-01-15  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Fix _gcry_mpi_ec_p_new to allow secp256k1.
-       + commit 49edeebb43174865cf4fa2c170a42a8e4274c4f0
-       * mpi/ec.c (_gcry_mpi_ec_p_new): Remove checking a!=0.
-       * tests/t-mpi-point.c (context_alloc): Remove two spurious tests.
-
-2014-01-14  Milan Broz  <gmazyland@gmail.com>
-
-       PBKDF2: Use gcry_md_reset to speed up calculation.
-       + commit 04cda6b7cc16f3f52c12d9d3e46c56701003496e
-       * cipher/kdf.c (_gcry_kdf_pkdf2): Use gcry_md_reset
-       to speed up calculation.
-
-2014-01-13  Werner Koch  <wk@gnupg.org>
-
-       Fix macro conflict in NetBSD.
-       + commit 5f2af6c26bc04975c0b518881532871d7387d7ce
-       * cipher/bithelp.h (bswap32): Rename to _gcry_bswap32.
-       (bswap64): Rename to _gcry_bswap64.
-
-       Use internal malloc function in fips.c.
-       + commit 518ae274a1845ce626b2b4223a9b3805cbbab1a7
-       * src/fips.c (check_binary_integrity): s/gcry_malloc/xtrymalloc/.
-
-2014-01-13  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Truncate hash values for ECDSA signature scheme.
-       + commit 9edcf1090e0485f9f383b6c54b18ea8ca3d4a225
-       * cipher/dsa-common (_gcry_dsa_normalize_hash): New. Truncate opaque
-         mpis as required for DSA and ECDSA signature schemas.
-       * cipher/dsa.c (verify): Return gpg_err_code_t value from verify() to
-         behave like the rest of internal sign/verify functions.
-       * cipher/dsa.c (sign, verify, dsa_verify): Factor out hash truncation.
-       * cipher/ecc-ecdsa.c (_gcry_ecc_ecdsa_sign): Factor out hash truncation.
-       * cipher/ecc-ecdsa.c (_gcry_ecc_ecdsa_verify):
-         as required by ECDSA scheme, truncate hash values to bitlength of
-         used curve.
-       * tests/pubkey.c (check_ecc_sample_key): add a testcase for hash
-         truncation.
-
-       Add GOST R 34.10-2012 curves proposed by TC26.
-       + commit 2c5ec803100ed8261e51442fb93b75367b7725ea
-       * cipher/ecc-curves.c (domain_parmss): Add two GOST R 34.10-2012 curves
-         proposed/pending to standardization by TC26 (Russian cryptography
-         technical comitee).
-       * cipher/ecc-curves.c (curve_alias): Add OID aliases.
-       * tests/curves.c: Increase N_CURVES.
-
-       Add GOST R 34.10-2001 curves per RFC4357.
-       + commit 9bedc5c3b646dfe481678ca58f5466ac46decaf7
-       * cipher/ecc-curves.c (domain_parms): Add 3 curves defined in rfc4357.
-       * cipher/ecc-curves.c (curve_aliases): Add OID and Xch aliases for GOST
-         curves.
-       * tests/curves.c (N_CURVES): Update value.
-
-       Fix typo in search_oid.
-       + commit 7edcb574d8d6dffb6e234c2ba1996a9a04923859
-       * cipher/md.c (search_oid): Invert condition on oid comparison.
-
-       Add MD2-HMAC calculation support.
-       + commit 653b58cb5e85511b6c04c3f85ef3e372c2e9f74f
-       * src/gcrypt.h.in (GCRY_MAC_HMAC_MD2): New.
-       * cipher/mac-hmac.c: Support GCRY_MAC_HMAC_MD2.
-
-       Add a function to retrieve algorithm used by MAC handler.
-       + commit 8439a379c86ef1088465ea70ac10840759a1638e
-       * cipher/mac.c (_gcry_mac_get_algo): New function, returns used algo.
-       * src/visibility.c (gcry_mac_get_algo): New wrapper.
-       * src/visibility.h: Hanlde gcry_mac_get_algo.
-       * src/gcrypt-int.h (_gcry_mac_get_algo): New.
-       * src/gcrypt.h.in (gcry_mac_get_algo): New.
-       * src/libgcrypt.def (gcry_mac_get_algo): New.
-       * src/libgcrypt.vers (gcry_mac_get_algo): New.
-       * doc/gcrypt.texi: Document gcry_mac_get_algo.
-       * tests/basic.c (check_one_mac): Verify gcry_mac_get_algo.
-
-       Correct formatting of gcry_mac_get_algo_keylen documentation.
-       + commit 36c9e0e4eb4f935da90df1c8df484d1940bda5eb
-       * doc/gcrypt.texi: add braces near gcry_mac_get_algo_keylen
-         documentation.
-
-       Use braces around unsigned int in gcry_mac_get_algo_keylen
-       documentation, otherwise texinfo breaks that and uses 'int' as a
-       function definition.
-
-2014-01-13  Werner Koch  <wk@gnupg.org>
-
-       ecc: Make a macro shorter.
-       + commit 2ef48ba59c32bfa1a9265d5eea8ab225a658903a
-       * src/mpi.h (MPI_EC_TWISTEDEDWARDS): Rename to MPI_EC_EDWARDS.  CHnage
-       all users.
-       * cipher/ecc-curves.c (domain_parms): Add parameters for Curve3617 as
-       comment.
-       * mpi/ec.c (dup_point_twistededwards): Rename to dup_point_edwards.
-       (add_points_twistededwards): Rename to add_points_edwards.
-
-2014-01-12  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix assembly division check.
-       + commit ef3e66e168c4b9b86bfc4903001631e53a7125d8
-       * configure.ac (gcry_cv_gcc_as_const_division_ok): Correct variable
-       name mismatch at '--Wa,--divide' workaround check.
-
-2014-01-12  NIIBE Yutaka  <gniibe@fsij.org>
-
-       Add secp256k1 curve.
-       + commit 019e0e9e8c77a2edf283745e05e9301673ea6a0a
-       * cipher/ecc-curves.c (curve_aliases): Add secp256k1 and its OID.
-       (domain_parms): Add secp256k1's domain paramerter.
-
-       * tests/basic.c (check_pubkey): Add a key of secp256k1.
-
-       * tests/curves.c (N_CURVES): Updated.
-
-2014-01-12  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix constant division for AMD64 assembly on Solaris/x86.
-       + commit 43376891c01f4aff1fbfb23beafebb5adfd0868c
-       * configure.ac (gcry_cv_gcc_as_const_division_ok): Add new check for
-       constant division in assembly and test for "-Wa,--divide" workaround.
-       (gcry_cv_gcc_amd64_platform_as_ok): Check for also constant division.
-
-2014-01-10  Werner Koch  <wk@gnupg.org>
-
-       Use the generic autogen.sh script.
-       + commit b0ac1f9b143aa15855914ba93fef900288d45c9c
-       * autogen.rc: New.
-       * Makefile.am (EXTRA_DIST): Add it.
-       * autogen.sh: Update from current GnuPG.
-
-       Move all helper scripts to build-aux/
-       + commit df9b4eabf52faee6f289a4bc62219684442ae383
-       * scripts/: Rename to build-aux/.
-       * compile, config.guess, config.rpath, config.sub
-       * depcomp, doc/mdate-sh, doc/texinfo.tex
-       * install-sh, ltmain.sh, missing: Move to build-aux/.
-       * Makefile.am (EXTRA_DIST): Adjust.
-       * configure.ac (AC_CONFIG_AUX_DIR): New.
-       (AM_SILENT_RULES): New.
-
-2013-12-30  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add blowfish/serpent ARM assembly files to Makefile.am.
-       + commit 7fef7f481c0a1542be34d1dc831f58d41846ac29
-       * cipher/Makefile.am: Add 'blowfish-arm.S' and 'serpent-armv7-neon.S'.
-
-       Add AMD64 assembly implementation for arcfour.
-       + commit 7547898109c72a97e3102b2a045ee4fdb2aa40bf
-       * cipher/Makefile.am: Add 'arcfour-amd64.S'.
-       * cipher/arcfour-amd64.S: New.
-       * cipher/arcfour.c (USE_AMD64_ASM): New.
-       [USE_AMD64_ASM] (ARCFOUR_context, _gcry_arcfour_amd64)
-       (encrypt_stream): New.
-       * configure.ac [host=x86_64]: Add 'arcfour-amd64.lo'.
-
-       Parse /proc/cpuinfo for ARM HW features.
-       + commit a05be441d8cd89b90d8d58e3a343a436dae377d0
-       * src/hwf-arm.c [__linux__] (HAS_PROC_CPUINFO)
-       (detect_arm_proc_cpuinfo): New.
-       (_gcry_hwf_detect_arm) [HAS_PROC_CPUINFO]: Check '/proc/cpuinfo' for
-       HW features.
-
-       Fix buggy/incomplete detection of AVX/AVX2 support.
-       + commit bbcb12187afb1756cb27296166b57fa19ee45d4d
-       * configure.ac: Also check for 'xgetbv' instruction in AVX and AVX2
-       inline assembly checks.
-       * src/hwf-x86.c [__i386__] (get_xgetbv): New function.
-       [__x86_64__] (get_xgetbv): New function.
-       [HAS_X86_CPUID] (detect_x86_gnuc): Check for OSXSAVE and OS support for
-       XMM&YMM registers and enable AVX/AVX2 only if XMM&YMM registers are
-       supported by OS.
-
-2013-12-18  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Change utf-8 copyright characters to '(C)'
-       + commit b7e814f93ee40fcfe17a187a8989c07fde2ba0cd
-       cipher/blowfish-amd64.S: Change utf-8 encoded copyright character to
-       '(C)'.
-       cipher/blowfish-arm.S: Ditto.
-       cipher/bufhelp.h: Ditto.
-       cipher/camellia-aesni-avx-amd64.S: Ditto.
-       cipher/camellia-aesni-avx2-amd64.S: Ditto.
-       cipher/camellia-arm.S: Ditto.
-       cipher/cast5-amd64.S: Ditto.
-       cipher/cast5-arm.S: Ditto.
-       cipher/cipher-ccm.c: Ditto.
-       cipher/cipher-cmac.c: Ditto.
-       cipher/cipher-gcm.c: Ditto.
-       cipher/cipher-selftest.c: Ditto.
-       cipher/cipher-selftest.h: Ditto.
-       cipher/mac-cmac.c: Ditto.
-       cipher/mac-gmac.c: Ditto.
-       cipher/mac-hmac.c: Ditto.
-       cipher/mac-internal.h: Ditto.
-       cipher/mac.c: Ditto.
-       cipher/rijndael-amd64.S: Ditto.
-       cipher/rijndael-arm.S: Ditto.
-       cipher/salsa20-amd64.S: Ditto.
-       cipher/salsa20-armv7-neon.S: Ditto.
-       cipher/serpent-armv7-neon.S: Ditto.
-       cipher/serpent-avx2-amd64.S: Ditto.
-       cipher/serpent-sse2-amd64.S: Ditto.
-
-       Add ARM/NEON implementation for SHA-1.
-       + commit fc7dcf616937afaf73cfda1bf7bd79566a96b130
-       * cipher/Makefile.am: Add 'sha1-armv7-neon.S'.
-       * cipher/sha1-armv7-neon.S: New.
-       * cipher/sha1.c (USE_NEON): New.
-       (SHA1_CONTEXT, sha1_init) [USE_NEON]: Add and initialize 'use_neon'.
-       [USE_NEON] (_gcry_sha1_transform_armv7_neon): New.
-       (transform) [USE_NEON]: Use ARM/NEON assembly if enabled.
-       * configure.ac: Add 'sha1-armv7-neon.lo'.
-
-       Improve performance of SHA-512/ARM/NEON implementation.
-       + commit df629ba53a662427ebd3ddca90c3fe9ddd6511d3
-       * cipher/sha512-armv7-neon.S (RT01q, RT23q, RT45q, RT67q): New.
-       (round_0_63, round_64_79): Remove.
-       (rounds2_0_63, rounds2_64_79): New.
-       (_gcry_sha512_transform_armv7_neon): Add 'nblks' input; Handle multiple
-       input blocks; Use new round macros.
-       * cipher/sha512.c [USE_ARM_NEON_ASM]
-       (_gcry_sha512_transform_armv7_neon): Add 'num_blks'.
-       (transform) [USE_ARM_NEON_ASM]: Pass nblks to assembly.
-
-       Add AVX and AVX2/BMI implementations for SHA-256.
-       + commit a5c2bbfe0db515d739ab683297903c77b1eec124
-       * LICENSES: Add 'cipher/sha256-avx-amd64.S' and
-       'cipher/sha256-avx2-bmi2-amd64.S'.
-       * cipher/Makefile.am: Add 'sha256-avx-amd64.S' and
-       'sha256-avx2-bmi2-amd64.S'.
-       * cipher/sha256-avx-amd64.S: New.
-       * cipher/sha256-avx2-bmi2-amd64.S: New.
-       * cipher/sha256-ssse3-amd64.S: Use 'lea' instead of 'add' in few
-       places for tiny speed improvement.
-       * cipher/sha256.c (USE_AVX, USE_AVX2): New.
-       (SHA256_CONTEXT) [USE_AVX, USE_AVX2]: Add 'use_avx' and 'use_avx2'.
-       (sha256_init, sha224_init) [USE_AVX, USE_AVX2]: Initialize above
-       new context members.
-       [USE_AVX] (_gcry_sha256_transform_amd64_avx): New.
-       [USE_AVX2] (_gcry_sha256_transform_amd64_avx2): New.
-       (transform) [USE_AVX2]: Use AVX2 assembly if enabled.
-       (transform) [USE_AVX]: Use AVX assembly if enabled.
-       * configure.ac: Add 'sha256-avx-amd64.lo' and
-       'sha256-avx2-bmi2-amd64.lo'.
-
-2013-12-17  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add AVX and AVX/BMI2 implementations for SHA-1.
-       + commit e4e458465b124e25b6aec7a60174bf1ca32dc5fd
-       * cipher/Makefile.am: Add 'sha1-avx-amd64.S' and
-       'sha1-avx-bmi2-amd64.S'.
-       * cipher/sha1-avx-amd64.S: New.
-       * cipher/sha1-avx-bmi2-amd64.S: New.
-       * cipher/sha1.c (USE_AVX, USE_BMI2): New.
-       (SHA1_CONTEXT) [USE_AVX]: Add 'use_avx'.
-       (SHA1_CONTEXT) [USE_BMI2]: Add 'use_bmi2'.
-       (sha1_init): Initialize 'use_avx' and 'use_bmi2'.
-       [USE_AVX] (_gcry_sha1_transform_amd64_avx): New.
-       [USE_BMI2] (_gcry_sha1_transform_amd64_bmi2): New.
-       (transform) [USE_BMI2]: Use BMI2 assembly if enabled.
-       (transform) [USE_AVX]: Use AVX assembly if enabled.
-       * configure.ac: Add 'sha1-avx-amd64.lo' and 'sha1-avx-bmi2-amd64.lo'.
-
-       SHA-1/SSSE3: Improve performance on large buffers.
-       + commit 6fd0dd2a5f1362f91e2861cd9d300341a43842a5
-       * cipher/sha1-ssse3-amd64.S (RNBLKS): New.
-       (_gcry_sha1_transform_amd64_ssse3): Handle multiple input blocks, with
-       software pipelining of next data block processing.
-       * cipher/sha1.c [USE_SSSE3] (_gcry_sha1_transform_amd64_ssse3): Add
-       'nblks'.
-       (transform) [USE_SSSE3]: Pass nblks to assembly function.
-
-       Add bulk processing for hash transform functions.
-       + commit 50b8c8342d023038a4b528af83153293dd2756ea
-       * cipher/hash-common.c (_gcry_md_block_write): Preload 'hd->blocksize'
-       to stack, pass number of blocks to 'hd->bwrite'.
-       * cipher/hash-common.c (_gcry_md_block_write_t): Add 'nblks'.
-       * cipher/gostr3411-94.c: Rename 'transform' function to
-       'transform_blk', add new 'transform' function with 'nblks' as
-       additional input.
-       * cipher/md4.c: Ditto.
-       * cipher/md5.c: Ditto.
-       * cipher/md4.c: Ditto.
-       * cipher/rmd160.c: Ditto.
-       * cipher/sha1.c: Ditto.
-       * cipher/sha256.c: Ditto.
-       * cipher/sha512.c: Ditto.
-       * cipher/stribog.c: Ditto.
-       * cipher/tiger.c: Ditto.
-       * cipher/whirlpool.c: Ditto.
-
-2013-12-16  Werner Koch  <wk@gnupg.org>
-
-       Release 1.6.0.
-       + commit 0ea9731e1c93a962f6266004ab0e7418c19d6277
-
-
-       doc: Change yat2m to allow arbitrary condition names.
-       + commit 9a912f8c4f366c53f1cdb94513b67b937e87178b
-       * doc/yat2m.c (MAX_CONDITION_NESTING): New.
-       (gpgone_defined): Remove.
-       (condition_s, condition_stack, condition_stack_idx): New.
-       (cond_is_active, cond_in_verbatim): New.
-       (add_predefined_macro, set_macro, macro_set_p): New.
-       (evaluate_conditions, push_condition, pop_condition): New.
-       (parse_file): Rewrite to use the condition stack.
-       (top_parse_file): Set prefined macros.
-       (main): Change -D to define arbitrary macros.
-
-       tests: Add SHA-512 to the long hash test.
-       + commit 0d3bd23d7f730b9bbc81fc8da8d99f4853c36020
-       * tests/hashtest.c (testvectors): Add vectors for 256GiB SHA-512.
-       * tests/hashtest-256g.in (algos): Add test for SHA-512.
-
-       Add configure option --enable-large-data-tests.
-       + commit a6b9304a889397ac98e1c2c4ac3e178669d94492
-       * configure.ac: Add option --enable-large-data-tests.
-       * tests/hashtest-256g.in: New.
-       * tests/Makefile.am (EXTRA_DIST): Add hashtest-256g.in.
-       (TESTS): Split up into tests_bin, tests_bin_last, tests_sh, and
-       tests_sh_last.
-       (tests_sh_last): Add hashtest-256g
-       (noinst_PROGRAMS): Add only tests_bin and tests_bin_last.
-       (bench-slope.log, hashtest-256g.log): New rules to enforce serial run.
-
-       random: Call random progress handler more often.
-       + commit 5a7ce59396fe56f0d681df314bfbdb5f7732d4b1
-       * random/rndlinux.c (_gcry_rndlinux_gather_random): Update progress
-       indicator earlier.
-
-       cipher: Normalize the MPIs used as input to secret key functions.
-       + commit dec048b2ec79271a2f4405be5b87b1e768b3f1a9
-       * cipher/dsa.c (sign): Normalize INPUT.
-       * cipher/elgamal.c (decrypt): Normalize A and B.
-       * cipher/rsa.c (secret): Normalize the INPUT.
-       (rsa_decrypt): Reduce DATA before passing to secret.
-
-2013-12-16  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Change dummy variable in mpih-div.c to mpi_limb_t type.
-       + commit 953535a7de68cf62b5b1ad6f96ea3a9edd83762c
-       * mpi/mpih-div.c (_gcry_mpih_mod_1, _gcry_mpih_divmod_1): Change dummy
-       variable to 'mpi_limb_t' type from 'int'.
-
-       Remove duplicate gcry_mac_hd_t typedef.
-       + commit 5c31990214b58c4e17edb01fbbe6d9f573975a22
-       * cipher/mac-internal.h (gcry_mac_hd_t): Remove.
-
-2013-12-15  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Use u64 for CCM data lengths.
-       + commit 110fed2d6b0bbc97cb5cc0a3a564e05fc42afa2d
-       * cipher/cipher-ccm.c: Move code inside [HAVE_U64_TYPEDEF].
-       [HAVE_U64_TYPEDEF] (_gcry_cipher_ccm_set_lengths): Use 'u64' for
-       data lengths.
-       [!HAVE_U64_TYPEDEF] (_gcry_cipher_ccm_encrypt)
-       (_gcry_cipher_ccm_decrypt, _gcry_cipher_ccm_set_nonce)
-       (_gcry_cipher_ccm_authenticate, _gcry_cipher_ccm_get_tag)
-       (_gcry_cipher_ccm_check_tag): Dummy functions returning
-       GPG_ERROR_NOT_SUPPORTED.
-       * cipher/cipher-internal.h (gcry_cipher_handle.u_mode.ccm)
-       (_gcry_cipher_ccm_set_lengths): Move inside [HAVE_U64_TYPEDEF] and use
-       u64 instead of size_t for CCM data lengths.
-       * cipher/cipher.c (_gcry_cipher_open_internal, cipher_reset)
-       (_gcry_cipher_ctl) [!HAVE_U64_TYPEDEF]: Return GPG_ERR_NOT_SUPPORTED
-       for CCM.
-       (_gcry_cipher_ctl) [HAVE_U64_TYPEDEF]: Use u64 for
-       GCRYCTL_SET_CCM_LENGTHS length parameters.
-       * tests/basic.c: Do not use CCM if !HAVE_U64_TYPEDEF.
-       * tests/bench-slope.c: Ditto.
-       * tests/benchmark.c: Ditto.
-
-2013-12-14  Werner Koch  <wk@gnupg.org>
-
-       tests: Prevent rare failure of gcry_pk_decrypt test.
-       + commit bfb43a17d8db571fca4ed433ee8be5c366745844
-       * tests/basic.c (check_pubkey_crypt): Add special mode 1.
-       (main): Add option --loop.
-
-2013-12-14  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Minor fixes to SHA assembly implementations.
-       + commit ffd9b2aa5abda7f4d7790ed48116ed5d71ab9995
-       * cipher/Makefile.am: Correct 'sha256-avx*.S' to 'sha512-avx*.S'.
-       * cipher/sha1-ssse3-amd64.S: First line, correct filename.
-       * cipher/sha256-ssse3-amd64.S: Return correct stack burn depth.
-       * cipher/sha512-avx-amd64.S: Use 'vzeroall' to clear registers.
-       * cipher/sha512-avx2-bmi2-amd64.S: Ditto and return correct stack burn
-       depth.
-
-       SHA-1/SSSE3: Do not check for Intel syntax assembly support.
-       + commit c86c35534a153b13e880d0bb0ea3e48e1c0ecaf9
-       * cipher/sha1-ssse3-amd64.S: Remove check for
-       HAVE_INTEL_SYNTAX_PLATFORM_AS.
-       * cipher/sha1.c [USE_SSSE3]: Ditto.
-
-2013-12-13  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Convert SHA-1 SSSE3 implementation from mixed asm&C to pure asm.
-       + commit d2b853246c2ed056a92096d89c3ca057e45c9c92
-       * cipher/Makefile.am: Change 'sha1-ssse3-amd64.c' to
-       'sha1-ssse3-amd64.S'.
-       * cipher/sha1-ssse3-amd64.c: Remove.
-       * cipher/sha1-ssse3-amd64.S: New.
-
-       SHA-1: Add SSSE3 implementation.
-       + commit be2238f68abcc6f2b4e8c38ad9141376ce622a22
-       * cipher/Makefile.am: Add 'sha1-ssse3-amd64.c'.
-       * cipher/sha1-ssse3-amd64.c: New.
-       * cipher/sha1.c (USE_SSSE3): New.
-       (SHA1_CONTEXT) [USE_SSSE3]: Add 'use_ssse3'.
-       (sha1_init) [USE_SSSE3]: Initialize 'use_ssse3'.
-       (transform): Rename to...
-       (_transform): this.
-       (transform): New.
-       * configure.ac [host=x86_64]: Add 'sha1-ssse3-amd64.lo'.
-
-       Add missing register clearing in to SHA-256 and SHA-512 assembly.
-       + commit 04615cc6803cdede25fa92e3ff697e252a23cd7a
-       * cipher/sha256-ssse3-amd64.S: Clear used XMM/YMM registers at return.
-       * cipher/sha512-avx-amd64.S: Ditto.
-       * cipher/sha512-avx2-bmi2-amd64.S: Ditto.
-       * cipher/sha512-ssse3-amd64.S: Ditto.
-
-2013-12-13  Werner Koch  <wk@gnupg.org>
-
-       Update license information.
-       + commit 764643a3d5634bcbc47790bd8505f6a1a5280d9c
-       * LICENSES: New.
-       * Makefile.am (EXTRA_DIST): Add LICENSES.
-       * AUTHORS: Add list of copyright holders.
-       * README: Reference AUTHORS.
-
-2013-12-13  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix empty clobber in AVX2 assembly check.
-       + commit e41d605ee41469e8a33cdc4d38f742cfb931f835
-       * configure.ac (gcry_cv_gcc_inline_asm_avx2): Add "cc" as assembly
-       globber.
-
-       Fix W32 build.
-       + commit a71b810ddd67ca3a1773d8f929d162551abb58eb
-       * random/rndw32.c (register_poll, slow_gatherer): Change gcry_xmalloc to
-       xmalloc, and gcry_xrealloc to xrealloc.
-
-2013-12-12  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       SHA-512: Add AVX and AVX2 implementations for x86-64.
-       + commit 2e4253dc8eb512cd0e807360926dc6ba912c95b4
-       * cipher/Makefile.am: Add 'sha512-avx-amd64.S' and
-       'sha512-avx2-bmi2-amd64.S'.
-       * cipher/sha512-avx-amd64.S: New.
-       * cipher/sha512-avx2-bmi2-amd64.S: New.
-       * cipher/sha512.c (USE_AVX, USE_AVX2): New.
-       (SHA512_CONTEXT) [USE_AVX]: Add 'use_avx'.
-       (SHA512_CONTEXT) [USE_AVX2]: Add 'use_avx2'.
-       (sha512_init, sha384_init) [USE_AVX]: Initialize 'use_avx'.
-       (sha512_init, sha384_init) [USE_AVX2]: Initialize 'use_avx2'.
-       [USE_AVX] (_gcry_sha512_transform_amd64_avx): New.
-       [USE_AVX2] (_gcry_sha512_transform_amd64_avx2): New.
-       (transform) [USE_AVX2]: Add call for AVX2 implementation.
-       (transform) [USE_AVX]: Add call for AVX implementation.
-       * configure.ac (HAVE_GCC_INLINE_ASM_BMI2): New check.
-       (sha512): Add 'sha512-avx-amd64.lo' and 'sha512-avx2-bmi2-amd64.lo'.
-       * doc/gcrypt.texi: Document 'intel-cpu' and 'intel-bmi2'.
-       * src/g10lib.h (HWF_INTEL_CPU, HWF_INTEL_BMI2): New.
-       * src/hwfeatures.c (hwflist): Add "intel-cpu" and "intel-bmi2".
-       * src/hwf-x86.c (detect_x86_gnuc): Check for HWF_INTEL_CPU and
-       HWF_INTEL_BMI2.
-
-       SHA-512: Add SSSE3 implementation for x86-64.
-       + commit 69a6d0f9562fcd26112a589318c13de66ce1700e
-       * cipher/Makefile.am: Add 'sha512-ssse3-amd64.S'.
-       * cipher/sha512-ssse3-amd64.S: New.
-       * cipher/sha512.c (USE_SSSE3): New.
-       (SHA512_CONTEXT) [USE_SSSE3]: Add 'use_ssse3'.
-       (sha512_init, sha384_init) [USE_SSSE3]: Initialize 'use_ssse3'.
-       [USE_SSSE3] (_gcry_sha512_transform_amd64_ssse3): New.
-       (transform) [USE_SSSE3]: Call SSSE3 implementation.
-       * configure.ac (sha512): Add 'sha512-ssse3-amd64.lo'.
-
-       SHA-256: Add SSSE3 implementation for x86-64.
-       + commit e1a3931263e67aacec3c0bfcaa86c7d1441d5c6a
-       * cipher/Makefile.am: Add 'sha256-ssse3-amd64.S'.
-       * cipher/sha256-ssse3-amd64.S: New.
-       * cipher/sha256.c (USE_SSSE3): New.
-       (SHA256_CONTEXT) [USE_SSSE3]: Add 'use_ssse3'.
-       (sha256_init, sha224_init) [USE_SSSE3]: Initialize 'use_ssse3'.
-       (transform): Rename to...
-       (_transform): This.
-       [USE_SSSE3] (_gcry_sha256_transform_amd64_ssse3): New.
-       (transform): New.
-       * configure.ac (HAVE_INTEL_SYNTAX_PLATFORM_AS): New check.
-       (sha256): Add 'sha256-ssse3-amd64.lo'.
-       * doc/gcrypt.texi: Document 'intel-ssse3'.
-       * src/g10lib.h (HWF_INTEL_SSSE3): New.
-       * src/hwfeatures.c (hwflist): Add "intel-ssse3".
-       * src/hwf-x86.c (detect_x86_gnuc): Test for SSSE3.
-
-2013-12-12  Werner Koch  <wk@gnupg.org>
-
-       Add a configuration file to disable hardware features.
-       + commit 5e1239b1e2948211ff2675f45cce2b28c3379cfb
-       * src/hwfeatures.c: Inclyde syslog.h and ctype.h.
-       (HWF_DENY_FILE): New.
-       (my_isascii): New.
-       (parse_hwf_deny_file): New.
-       (_gcry_detect_hw_features): Call it.
-
-       * src/mpicalc.c (main): Correctly initialize Libgcrypt.  Add options
-       "--print-config" and "--disable-hwf".
-
-       Move list of hardware features to hwfeatures.c.
-       + commit 4ae77322b681a13da62d01274bcab25be2af12d0
-       * src/global.c (hwflist, disabled_hw_features): Move to ..
-       * src/hwfeatures.c: here.
-       (_gcry_disable_hw_feature): New.
-       (_gcry_enum_hw_features): New.
-       (_gcry_detect_hw_features): Remove arg DISABLED_FEATURES.
-       * src/global.c (print_config, _gcry_vcontrol, global_init): Adjust
-       accordingly.
-
-       Remove macro hacks for internal vs. external functions.  Part 2 and last.
-       + commit 3b30e9840d4b351c4de73b126e561154cb7df4cc
-       * src/visibility.h: Remove remaining define/undef hacks for symbol
-       visibility.  Add macros to detect the use of the public functions.
-       Change all affected functions by replacing them by the x-macros.
-       * src/g10lib.h: Add internal prototypes.
-       (xtrymalloc, xtrycalloc, xtrymalloc_secure, xtrycalloc_secure)
-       (xtryrealloc, xtrystrdup, xmalloc, xcalloc, xmalloc_secure)
-       (xcalloc_secure, xrealloc, xstrdup, xfree): New macros.
-
-2013-12-11  Werner Koch  <wk@gnupg.org>
-
-       random: Add a feature to close device file descriptors.
-       + commit cd548ba2dc777b8b27d8d33182ba733c20222120
-       * src/gcrypt.h.in (GCRYCTL_CLOSE_RANDOM_DEVICE): New.
-       * src/global.c (_gcry_vcontrol): Call _gcry_random_close_fds.
-       * random/random.c (_gcry_random_close_fds): New.
-       * random/random-csprng.c (_gcry_rngcsprng_close_fds): New.
-       * random/random-fips.c (_gcry_rngfips_close_fds): New.
-       * random/random-system.c (_gcry_rngsystem_close_fds): New.
-       * random/rndlinux.c (open_device): Add arg retry.
-       (_gcry_rndlinux_gather_random): Add mode to close open fds.
-
-       * tests/random.c (check_close_random_device): New.
-       (main): Call new test.
-
-2013-12-10  Werner Koch  <wk@gnupg.org>
-
-       Fix last commit (9a37470c)
-       + commit eae1e7712e1b687bd77eb37d0eb505fc9d46d93c
-       * src/secmem.c (lock_pool): Remove remaining line.  Reported by Ian
-       Goldberg.
-
-2013-12-09  Werner Koch  <wk@gnupg.org>
-
-       Fix one-off memory leak when build with Linux capability support.
-       + commit 9a37470c50ee9966cb2652617a404ddd54a9c096
-       * src/secmem.c (lock_pool, secmem_init): Use cap_free.  Reported by
-       Mike Crowe <mac@mcrowe.com>.
-
-2013-12-09  David 'Digit' Turner  <digit@google.com>
-
-       Update libtool to support Android.
-       + commit 2516f0b660b1a7181ad38c44310c627f4f498595
-       * m4/libtool.m4: Add "linux*android*" case.  Taken from the libtool
-       repository.
-
-2013-12-09  Werner Koch  <wk@gnupg.org>
-
-       tests: Speed up benchmarks in regression test mode.
-       + commit 2e5354fe8db5288939733d0fb63ad4c87bc20105
-       * tests/tsexp.c (check_extract_param): Fix compiler warning.
-       * tests/Makefile.am (TESTS_ENVIRONMENT): Set GCRYPT_IN_REGRESSION_TEST.
-       * tests/bench-slope.c (main): Speed up if in regression test mode.
-       * tests/benchmark.c (main): Ditto.
-
-       tests: Add --csv option to bench-slope.
-       + commit 8072e9fa4b42ae8e65e266aa158fd903f1bb0927
-       * tests/bench-slope.c (STR, STR2): New.
-       (cvs_mode): New.
-       (num_measurement_repetitions): New.  Replace use of
-       NUM_MEASUREMENT_REPETITIONS by this.
-       (current_section_name, current_algo_name, current_mode_name): New.
-       (bench_print_result_csv): New.
-       (bench_print_result_std): Rename from bench_print_result.
-       (bench_print_result): New. Divert depending on CSV_MODE.
-       (bench_print_header, bench_print_footer): take care of CSV_MODE.
-       (bench_print_algo, bench_print_mode): New.  Use them instead of
-       explicit printfs.
-       (main): Add options --csv and --repetitions.
-
-2013-12-07  Werner Koch  <wk@gnupg.org>
-
-       sexp: Allow long names and white space in gcry_sexp_extract_param.
-       + commit d4555433b6e422fa69a85cae99961f513e55d82b
-       * src/sexp.c (_gcry_sexp_vextract_param): Skip white space.  Support
-       long parameter names.
-       * tests/tsexp.c (check_extract_param): Add test cases for long parameter
-       names and white space.
-
-2013-12-06  Werner Koch  <wk@gnupg.org>
-
-       ecc: Merge partly duplicated code.
-       + commit 405021cb6d4e470337302c65dec5bc91491a89c1
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_sign): Factor A hashing out to ...
-       (_gcry_ecc_eddsa_compute_h_d): new function.
-       * cipher/ecc-misc.c (_gcry_ecc_compute_public): Use new function.
-       (reverse_buffer): Remove.
-
-       ecc: Remove unused internal function.
-       + commit 4cf2c65fe15173c8d68a141a01b34fc1fb9080b7
-       * src/cipher-proto.h (gcry_pk_spec): Remove get_param.
-       * cipher/ecc-curves.c (_gcry_ecc_get_param_sexp): Merge in code from
-       _gcry_ecc_get_param.
-       (_gcry_ecc_get_param): Remove.
-       * cipher/ecc.c (_gcry_pubkey_spec_ecc): Remove _gcry_ecc_get_param.
-
-2013-12-06  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix building on mingw32.
-       + commit 5917ce34e3b3eac4c15f62577e4723974024f818
-       * src/gcrypt-int.h: Include <types.h>.
-
-2013-12-05  Werner Koch  <wk@gnupg.org>
-
-       ecc: Change OID for Ed25519.
-       + commit 7ef43d1eebb4f8226e860982dfe5fa2e2c82ad0f
-       * cipher/ecc-curves.c (curve_aliased): Add more suitable OID for
-       Ed25519.
-
-       Remove macro hacks for internal vs. external functions.  Part 1.
-       + commit 7bacf1812b55fa78db63abaa1f5a9220e9c6cccc
-       * src/visibility.h: Remove almost all define/undef hacks for symbol
-       visibility.  Add macros to detect the use of the public functions.
-       Change all affected functions by prefixing them explicitly with an
-       underscore and change all internal callers to call the underscore
-       prefixed versions.  Provide convenience macros from sexp and mpi
-       functions.
-       * src/visibility.c: Change all functions to use only gpg_err_code_t
-       and translate to gpg_error_t only in visibility.c.
-
-2013-12-04  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       mpi: add inline assembly for x86-64.
-       + commit 85bb0a98ea5add0296cbcc415d557eaa1f6bd294
-       * mpi/longlong.h [__x86_64] (add_ssaaaa, sub_ddmmss, umul_ppmm)
-       (udiv_qrnnd, count_leading_zeros, count_trailing_zeros): New.
-
-2013-12-04  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: fix gcry_mpi_powm for negative base.
-       + commit c56080c26186d25dec05f01831494c77d8d07e13
-       * mpi/mpi-pow.c (gcry_mpi_powm) [USE_ALGORITHM_SIMPLE_EXPONENTIATION]:
-       Fix for the case where BASE is negative.
-       * tests/mpitests.c (test_powm): Add a test case of (-17)^6 mod 19.
-
-2013-12-03  Werner Koch  <wk@gnupg.org>
-
-       Add build support for ppc64le.
-       + commit 2ff86db2e1b0f6cc22a1ca86037b526c5fa3be51
-       * config.guess, config.sub: Update to latest version (2013-11-29).
-       * m4/libtool.m4: Add patches for ppc64le.
-
-2013-12-03  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael: fix compiler warning on aarch64.
-       + commit 59b1a1b7ee2923e1bf091071ae716d180c6c6006
-       * cipher/rijndael.c (do_setkey): Use braces for empty if statement
-       instead of semicolon.
-
-       Add aarch64 (arm64) mpi assembly.
-       + commit 80896bc8f5e6ed9a627374e34f040ad5f3617584
-       * mpi/aarch64/mpi-asm-defs.h: New.
-       * mpi/aarch64/mpih-add1.S: New.
-       * mpi/aarch64/mpih-mul1.S: New.
-       * mpi/aarch64/mpih-mul2.S: New.
-       * mpi/aarch64/mpih-mul3.S: New.
-       * mpi/aarch64/mpih-sub1.S: New.
-       * mpi/config.links [host=aarch64-*-*]: Add configguration for aarch64
-       assembly.
-       * mpi/longlong.h [__aarch64__] (add_ssaaaa, sub_ddmmss, umul_ppmm)
-       (count_leading_zeros): New.
-
-2013-12-02  Werner Koch  <wk@gnupg.org>
-
-       ecc: Use constant time point operation for Twisted Edwards.
-       + commit d4ce0cfe0d35d7ec69c115456848b5b735c928ea
-       * mpi/ec.c (_gcry_mpi_ec_mul_point): Try to do a constant time
-       operation if needed.
-       * tests/benchmark.c (main): Add option --use-secmem.
-
-       ecc: Make gcry_pk_testkey work for Ed25519.
-       + commit 14ae6224b1b17abbfc80c26ad0f4c60f1e8635e2
-       * cipher/ecc-misc.c (_gcry_ecc_compute_public): Add optional args G
-       and d.  Change all callers.
-       * cipher/ecc.c (gen_y_2): Remove.
-       (check_secret_key): Use generic public key compute function.  Adjust
-       for use with Ed25519 and EdDSA.
-       (nist_generate_key): Do not use the compliant key thingy for Ed25519.
-       (ecc_check_secret_key): Make parameter parsing similar to the other
-       functions.
-       * cipher/ecc-curves.c (domain_parms): Zero prefix some parameters so
-       that _gcry_ecc_update_curve_param works correctly.
-       * tests/keygen.c (check_ecc_keys): Add "param" flag.  Check all
-       Ed25519 keys.
-
-       ecc: Fix eddsa point decompression.
-       + commit 485f35124b1a74af0bad321ed70be3a79d8d11d7
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_recover_x): Fix the negative
-       case.
-
-       ecc: Fix gcry_mpi_ec_curve_point for Weierstrass.
-       + commit ecb90f8e7c6f2516080d27ed7da6a25f2314da3c
-       * mpi/ec.c (_gcry_mpi_ec_curve_point): Use correct equation.
-       (ec_pow3): New.
-       (ec_p_init): Always copy B.
-
-       mpi: Introduce 4 user flags for gcry_mpi_t.
-       + commit 29eddc2558d4cf39995f66d5fccd62f584d5b203
-       * src/gcrypt.h.in (GCRYMPI_FLAG_USER1, GCRYMPI_FLAG_USER2)
-       (GCRYMPI_FLAG_USER3, GCRYMPI_FLAG_USER4): New.
-       * mpi/mpiutil.c (gcry_mpi_set_flag, gcry_mpi_clear_flag)
-       (gcry_mpi_get_flag, _gcry_mpi_free): Implement them.
-       (gcry_mpi_set_opaque): Keep user flags.
-
-2013-11-29  Vladimir 'φ-coder/phcoder' Serbinenko  <phcoder@gmail.com>
-
-       Fix armv3 compile error.
-       + commit 3b1cc9e6c357574f54160298d731c18f3d717b6c
-       * mpi/longlong.h [__arm__ && __ARM_ARCH < 4] (umul_ppmm): Use
-       __AND_CLOBBER_CC instead of __CLOBBER_CC.
-
-       longlong.h on mips with clang.
-       + commit 1ecbd0bca31d462719a2a6590c1d03244e76ef89
-       * mpi/longlong.h [__mips__]: Use C-language version with clang.
-
-2013-11-24  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Camellia: Tweaks for AES-NI implementations.
-       + commit 3ef21e7e1b8003db9792155044db95f9d9ced184
-       * cipher/camellia-aesni-avx-amd64.S: Align stack to 16 bytes; tweak
-       key-setup for small speed up.
-       * cipher/camellia-aesni-avx2-amd64.S: Use vmovdqu even with aligned
-       stack; reorder vinsert128 instructions; use rbp for stack frame.
-
-2013-11-21  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add GMAC to MAC API.
-       + commit a34448c929b13bfb7b66d69169c89e7319a18b31
-       * cipher/Makefile.am: Add 'mac-gmac.c'.
-       * cipher/mac-gmac.c: New.
-       * cipher/mac-internal.h (gcry_mac_handle): Add 'u.gcm'.
-       (_gcry_mac_type_spec_gmac_aes, _gcry_mac_type_spec_gmac_twofish)
-       (_gcry_mac_type_spec_gmac_serpent, _gcry_mac_type_spec_gmac_seed)
-       (_gcry_mac_type_spec_gmac_camellia): New externs.
-       * cipher/mac.c (mac_list): Add GMAC specifications.
-       * doc/gcrypt.texi: Add mention of GMAC.
-       * src/gcrypt.h.in (gcry_mac_algos): Add GCM algorithms.
-       * tests/basic.c (check_one_mac): Add support for MAC IVs.
-       (check_mac): Add support for MAC IVs and add GMAC test vectors.
-       * tests/bench-slope.c (mac_bench): Iterate algorithm numbers to 499.
-       * tests/benchmark.c (mac_bench): Iterate algorithm numbers to 499.
-
-       GCM: Move gcm_table initialization to setkey.
-       + commit dbfa651618693da7ea73b4d2d00d4efd411bfb46
-       * cipher/cipher-gcm.c: Change all 'c->u_iv.iv' to
-       'c->u_mode.gcm.u_ghash_key.key'.
-       (_gcry_cipher_gcm_setkey): New.
-       (_gcry_cipher_gcm_initiv): Move ghash initialization to function above.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Add
-       'u_mode.gcm.u_ghash_key'; Reorder 'u_mode.gcm' members for partial
-       clearing in gcry_cipher_reset.
-       (_gcry_cipher_gcm_setkey): New prototype.
-       * cipher/cipher.c (cipher_setkey): Add GCM setkey.
-       (cipher_reset): Clear 'u_mode' only partially for GCM.
-
-2013-11-20  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       GCM: Add support for split data buffers and online operation.
-       + commit fb1e52e3fe231671de546eacd6becd31c26c4f7b
-       * cipher/cipher-gcm.c (do_ghash_buf): Add buffering for less than
-       blocksize length input and padding handling.
-       (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt): Add handling
-       for AAD padding and check if data has already being padded.
-       (_gcry_cipher_gcm_authenticate): Check that AAD or data has not being
-       padded yet.
-       (_gcry_cipher_gcm_initiv): Clear padding marks.
-       (_gcry_cipher_gcm_tag): Add finalization and padding; Clear sensitive
-       data from cipher handle, since they are not used after generating tag.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode.gcm.macbuf',
-       'u_mode.gcm.mac_unused', 'u_mode.gcm.ghash_data_finalized' and
-       'u_mode.gcm.ghash_aad_finalized'.
-       * tests/basic.c (check_gcm_cipher): Rename to...
-       (_check_gcm_cipher): ...this and add handling for different buffer step
-       lengths; Enable per byte buffer testing.
-       (check_gcm_cipher): Call _check_gcm_cipher with different buffer step
-       sizes.
-
-       GCM: Use size_t for buffer sizes.
-       + commit 2d870a9142e8c8b3f008e1ad8e83e4bdf7a8e4e7
-       * cipher/cipher-gcm.c (ghash, gcm_bytecounter_add, do_ghash_buf)
-       (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt)
-       (_gcry_cipher_gcm_authenticate, _gcry_cipher_gcm_geniv)
-       (_gcry_cipher_gcm_tag): Use size_t for buffer lengths.
-       * cipher/cipher-internal.h (_gcry_cipher_gcm_encrypt)
-       (_gcry_cipher_gcm_decrypt, _gcry_cipher_gcm_authenticate): Use size_t
-       for buffer lengths.
-
-       GCM: add FIPS mode restrictions.
-       + commit 56d352d6bdcf7abaa33c3399741f5063e2ddc32a
-       * cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt)
-       (_gcry_cipher_gcm_get_tag): Do not allow using in FIPS mode is setiv
-       was invocated directly.
-       (_gcry_cipher_gcm_setiv): Rename to...
-       (_gcry_cipher_gcm_initiv): ...this.
-       (_gcry_cipher_gcm_setiv): New setiv function with check for FIPS mode.
-       [TODO] (_gcry_cipher_gcm_getiv): New.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Add
-       'u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode'.
-
-       GCM: Add clearing and checking of marks.tag.
-       + commit 32a2da9abc91394b23cf565c1c833fa964394083
-       * cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt)
-       (_gcry_cipher_gcm_decrypt, _gcry_cipher_gcm_authenticate): Make sure
-       that tag has not been finalized yet.
-       (_gcry_cipher_gcm_setiv): Clear 'marks.tag'.
-
-       GCM: Add stack burning.
-       + commit 018f08354b1b116672e82f9ce942884b288aaf9e
-       * cipher/cipher-gcm.c (do_ghash, ghash): Return stack burn depth.
-       (setupM): Wipe 'tmp' buffer.
-       (do_ghash_buf): Wipe 'tmp' buffer and add stack burning.
-
-       Add aggregated bulk processing for GCM on x86-64.
-       + commit c9537fbf8ff0af919cff2bebadc4c6e7caea8076
-       * cipher/cipher-gcm.c [__x86_64__] (gfmul_pclmul_aggr4): New.
-       (ghash) [GCM_USE_INTEL_PCLMUL]: Add aggregated bulk processing
-       for __x86_64__.
-       (setupM) [__x86_64__]: Add initialization for aggregated bulk
-       processing.
-
-       GCM: Tweak Intel PCLMUL ghash loop for small speed-up.
-       + commit 9b6764944284fed733c2f88619b3d9eb5d5c259a
-       * cipher/cipher-gcm.c (do_ghash): Mark 'inline'.
-       [GCM_USE_INTEL_PCLMUL] (do_ghash_pclmul): Rename to...
-       [GCM_USE_INTEL_PCLMUL] (gfmul_pclmul): ..this and make inline function.
-       (ghash) [GCM_USE_INTEL_PCLMUL]: Preload data before ghash-pclmul loop.
-
-       GCM: Use counter mode code for speed-up.
-       + commit bd4bd23a2511a4bce63c3217cca0d4ecf0c79532
-       * cipher/cipher-gcm.c (ghash): Add process for multiple blocks.
-       (gcm_bytecounter_add, gcm_add32_be128, gcm_check_datalen)
-       (gcm_check_aadlen_or_ivlen, do_ghash_buf): New functions.
-       (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt)
-       (_gcry_cipher_gcm_authenticate, _gcry_cipher_gcm_set_iv)
-       (_gcry_cipher_gcm_tag): Adjust to use above new functions and
-       counter mode functions for encryption/decryption.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Remove 'length'; Add
-       'u_mode.gcm.(addlen|datalen|tagiv|datalen_over_limits)'.
-       (_gcry_cipher_gcm_setiv): Return gcry_err_code_t.
-       * cipher/cipher.c (cipher_setiv): Return error code.
-       (_gcry_cipher_setiv): Handle error code from 'cipher_setiv'.
-
-       Add Intel PCLMUL acceleration for GCM.
-       + commit 5a65ffabadd50f174ab7375faad7a726cce49e61
-       * cipher/cipher-gcm.c (fillM): Rename...
-       (do_fillM): ...to this.
-       (ghash): Remove.
-       (fillM): New macro.
-       (GHASH): Use 'do_ghash' instead of 'ghash'.
-       [GCM_USE_INTEL_PCLMUL] (do_ghash_pclmul): New.
-       (ghash): New.
-       (setupM): New.
-       (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt)
-       (_gcry_cipher_gcm_authenticate, _gcry_cipher_gcm_setiv)
-       (_gcry_cipher_gcm_tag): Use 'ghash' instead of 'GHASH' and
-       'c->u_mode.gcm.u_tag.tag' instead of 'c->u_tag.tag'.
-       * cipher/cipher-internal.h (GCM_USE_INTEL_PCLMUL): New.
-       (gcry_cipher_handle): Move 'u_tag' and 'gcm_table' under
-       'u_mode.gcm'.
-       * configure.ac (pclmulsupport, gcry_cv_gcc_inline_asm_pclmul): New.
-       * src/g10lib.h (HWF_INTEL_PCLMUL): New.
-       * src/global.c: Add "intel-pclmul".
-       * src/hwf-x86.c (detect_x86_gnuc): Add check for Intel PCLMUL.
-
-       GCM: GHASH optimizations.
-       + commit 0e9e7d72f3c9eb7ac832746c3034855faaf8d02c
-       * cipher/cipher-gcm.c [GCM_USE_TABLES] (gcmR, ghash): Replace with new.
-       [GCM_USE_TABLES] [GCM_TABLES_USE_U64] (bshift, fillM, do_ghash): New.
-       [GCM_USE_TABLES] [!GCM_TABLES_USE_U64] (bshift, fillM): Replace with
-       new.
-       [GCM_USE_TABLES] [!GCM_TABLES_USE_U64] (do_ghash): New.
-       (_gcry_cipher_gcm_tag): Remove extra memcpy to outbuf and use
-       buf_eq_const for comparing authentication tag.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Different 'gcm_table'
-       for 32-bit and 64-bit platforms.
-
-       Add some documentation for GCM mode.
-       + commit 332da0ed7c8fab6c2bee841c94d8364c2ab4e30d
-       * doc/gcrypt.texi: Add mention of GCM mode.
-
-2013-11-19  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Initial implementation of GCM.
-       + commit 90cce18b9eced4f412ceeec5bcae18c4493322df
-       * cipher/Makefile.am: Add 'cipher-gcm.c'.
-       * cipher/cipher-ccm.c (_gcry_ciphert_ccm_set_lengths)
-       (_gcry_cipher_ccm_authenticate, _gcry_cipher_ccm_tag)
-       (_gcry_cipher_ccm_encrypt, _gcry_cipher_ccm_decrypt): Change
-       'c->u_mode.ccm.tag' to 'c->marks.tag'.
-       * cipher/cipher-gcm.c: New.
-       * cipher/cipher-internal.h (GCM_USE_TABLES): New.
-       (gcry_cipher_handle): Add 'marks.tag', 'u_tag', 'length' and
-       'gcm_table'; Remove 'u_mode.ccm.tag'.
-       (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt)
-       (_gcry_cipher_gcm_setiv, _gcry_cipher_gcm_authenticate)
-       (_gcry_cipher_gcm_get_tag, _gcry_cipher_gcm_check_tag): New.
-       * cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey)
-       (cipher_encrypt, cipher_decrypt, _gcry_cipher_authenticate)
-       (_gcry_cipher_gettag, _gcry_cipher_checktag): Add GCM mode handling.
-       * src/gcrypt.h.in (gcry_cipher_modes): Add GCRY_CIPHER_MODE_GCM.
-       (GCRY_GCM_BLOCK_LEN): New.
-       * tests/basic.c (check_gcm_cipher): New.
-       (check_ciphers): Add GCM check.
-       (check_cipher_modes): Call 'check_gcm_cipher'.
-       * tests/bench-slope.c (bench_gcm_encrypt_do_bench)
-       (bench_gcm_decrypt_do_bench, bench_gcm_authenticate_do_bench)
-       (gcm_encrypt_ops, gcm_decrypt_ops, gcm_authenticate_ops): New.
-       (cipher_modes): Add GCM enc/dec/auth.
-       (cipher_bench_one): Limit GCM to block ciphers with 16 byte block-size.
-       * tests/benchmark.c (cipher_bench): Add GCM.
-
-2013-11-19  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Camellia: fix compiler warning.
-       + commit 9816ae9d9931b75e4fdc9a5be10e6af447132313
-       * cipher/camellia-glue.c (camellia_setkey): Use braces around empty if
-       statement.
-
-       Tweak Camellia-AVX key-setup for small speed-up.
-       + commit 77922a82c3f2e30eca04511fa5a355208349c657
-       * cipher/camellia-aesni-avx-amd64.S (camellia_f): Merge S-function output
-       rotation with P-function.
-
-       Add CMAC (Cipher-based MAC) to MAC API.
-       + commit b49cd64aaaff2e5488a84665362ef7150683226c
-       * cipher/Makefile.am: Add 'cipher-cmac.c' and 'mac-cmac.c'.
-       * cipher/cipher-cmac.c: New.
-       * cipher/cipher-internal.h (gcry_cipher_handle.u_mode): Add 'cmac'.
-       * cipher/cipher.c (gcry_cipher_open): Rename to...
-       (_gcry_cipher_open_internal): ...this and add CMAC.
-       (gcry_cipher_open): New wrapper that disallows use of internal
-       modes (CMAC) from outside.
-       (cipher_setkey, cipher_encrypt, cipher_decrypt)
-       (_gcry_cipher_authenticate, _gcry_cipher_gettag)
-       (_gcry_cipher_checktag): Add handling for CMAC mode.
-       (cipher_reset): Do not reset 'marks.key' and do not clear subkeys in
-       'u_mode' in CMAC mode.
-       * cipher/mac-cmac.c: New.
-       * cipher/mac-internal.h: Add CMAC support and algorithms.
-       * cipher/mac.c: Add CMAC algorithms.
-       * doc/gcrypt.texi: Add documentation for CMAC.
-       * src/cipher.h (gcry_cipher_internal_modes): New.
-       (_gcry_cipher_open_internal, _gcry_cipher_cmac_authenticate)
-       (_gcry_cipher_cmac_get_tag, _gcry_cipher_cmac_check_tag)
-       (_gcry_cipher_cmac_set_subkeys): New prototypes.
-       * src/gcrypt.h.in (gcry_mac_algos): Add CMAC algorithms.
-       * tests/basic.c (check_mac): Add CMAC test vectors.
-
-2013-11-16  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add new MAC API, initially with HMAC.
-       + commit fcd6da37d55f248d3558ee0ff385b41b866e7ded
-       * cipher/Makefile.am: Add 'mac.c', 'mac-internal.h' and 'mac-hmac.c'.
-       * cipher/bufhelp.h (buf_eq_const): New.
-       * cipher/cipher-ccm.c (_gcry_cipher_ccm_tag): Use 'buf_eq_const' for
-       constant-time compare.
-       * cipher/mac-hmac.c: New.
-       * cipher/mac-internal.h: New.
-       * cipher/mac.c: New.
-       * doc/gcrypt.texi: Add documentation for MAC API.
-       * src/gcrypt-int.h [GPG_ERROR_VERSION_NUMBER < 1.13]
-       (GPG_ERR_MAC_ALGO): New.
-       * src/gcrypt.h.in (gcry_mac_handle, gcry_mac_hd_t, gcry_mac_algos)
-       (gcry_mac_flags, gcry_mac_open, gcry_mac_close, gcry_mac_ctl)
-       (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write)
-       (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen)
-       (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name)
-       (gcry_mac_reset, gcry_mac_test_algo): New.
-       * src/libgcrypt.def (gcry_mac_open, gcry_mac_close, gcry_mac_ctl)
-       (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write)
-       (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen)
-       (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New.
-       * src/libgcrypt.vers (gcry_mac_open, gcry_mac_close, gcry_mac_ctl)
-       (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write)
-       (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen)
-       (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New.
-       * src/visibility.c (gcry_mac_open, gcry_mac_close, gcry_mac_ctl)
-       (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write)
-       (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen)
-       (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New.
-       * src/visibility.h (gcry_mac_open, gcry_mac_close, gcry_mac_ctl)
-       (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write)
-       (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen)
-       (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New.
-       * tests/basic.c (check_one_mac, check_mac): New.
-       (main): Call 'check_mac'.
-       * tests/bench-slope.c (bench_print_header, bench_print_footer): Allow
-       variable algorithm name width.
-       (_cipher_bench, hash_bench): Update to above change.
-       (bench_hash_do_bench): Add 'gcry_md_reset'.
-       (bench_mac_mode, bench_mac_init, bench_mac_free, bench_mac_do_bench)
-       (mac_ops, mac_modes, mac_bench_one, _mac_bench, mac_bench): New.
-       (main): Add 'mac' benchmark options.
-       * tests/benchmark.c (mac_repetitions, mac_bench): New.
-       (main): Add 'mac' benchmark options.
-
-       Use correct blocksize of 32 bytes for GOSTR3411-94 HMAC.
-       + commit b95a557a43aeed68ea5e5ce02aca42ee97bfdb3b
-       * cipher/md.c (md_open): Set macpads_Bsize to 32 for
-       GCRY_MD_GOST24311_94.
-
-2013-11-15  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       cipher: use size_t for internal buffer lengths.
-       + commit b787657a9d2c1d8e19f9fcb0b21e31cb062630cf
-       * cipher/arcfour.c (do_encrypt_stream, encrypt_stream): Use 'size_t'
-       for buffer lengths.
-       * cipher/blowfish.c (_gcry_blowfish_ctr_enc, _gcry_blowfish_cbc_dec)
-       (_gcry_blowfish_cfb_dec): Ditto.
-       * cipher/camellia-glue.c (_gcry_camellia_ctr_enc)
-       (_gcry_camellia_cbc_dec, _gcry_blowfish_cfb_dec): Ditto.
-       * cipher/cast5.c (_gcry_cast5_ctr_enc, _gcry_cast5_cbc_dec)
-       (_gcry_cast5_cfb_dec): Ditto.
-       * cipher/cipher-aeswrap.c (_gcry_cipher_aeswrap_encrypt)
-       (_gcry_cipher_aeswrap_decrypt): Ditto.
-       * cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt)
-       (_gcry_cipher_cbc_decrypt): Ditto.
-       * cipher/cipher-ccm.c (_gcry_cipher_ccm_encrypt)
-       (_gcry_cipher_ccm_decrypt): Ditto.
-       * cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt)
-       (_gcry_cipher_cfb_decrypt): Ditto.
-       * cipher/cipher-ctr.c (_gcry_cipher_ctr_encrypt): Ditto.
-       * cipher/cipher-internal.h (gcry_cipher_handle->bulk)
-       (_gcry_cipher_cbc_encrypt, _gcry_cipher_cbc_decrypt)
-       (_gcry_cipher_cfb_encrypt, _gcry_cipher_cfb_decrypt)
-       (_gcry_cipher_ofb_encrypt, _gcry_cipher_ctr_encrypt)
-       (_gcry_cipher_aeswrap_encrypt, _gcry_cipher_aeswrap_decrypt)
-       (_gcry_cipher_ccm_encrypt, _gcry_cipher_ccm_decrypt): Ditto.
-       * cipher/cipher-ofb.c (_gcry_cipher_cbc_encrypt): Ditto.
-       * cipher/cipher-selftest.h (gcry_cipher_bulk_cbc_dec_t)
-       (gcry_cipher_bulk_cfb_dec_t, gcry_cipher_bulk_ctr_enc_t): Ditto.
-       * cipher/cipher.c (cipher_setkey, cipher_setiv, do_ecb_crypt)
-       (do_ecb_encrypt, do_ecb_decrypt, cipher_encrypt)
-       (cipher_decrypt): Ditto.
-       * cipher/rijndael.c (_gcry_aes_ctr_enc, _gcry_aes_cbc_dec)
-       (_gcry_aes_cfb_dec, _gcry_aes_cbc_enc, _gcry_aes_cfb_enc): Ditto.
-       * cipher/salsa20.c (salsa20_setiv, salsa20_do_encrypt_stream)
-       (salsa20_encrypt_stream, salsa20r12_encrypt_stream): Ditto.
-       * cipher/serpent.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec)
-       (_gcry_serpent_cfb_dec): Ditto.
-       * cipher/twofish.c (_gcry_twofish_ctr_enc, _gcry_twofish_cbc_dec)
-       (_gcry_twofish_cfb_dec): Ditto.
-       * src/cipher-proto.h (gcry_cipher_stencrypt_t)
-       (gcry_cipher_stdecrypt_t, cipher_setiv_fuct_t): Ditto.
-       * src/cipher.h (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec)
-       (_gcry_aes_cbc_enc, _gcry_aes_cbc_dec, _gcry_aes_ctr_enc)
-       (_gcry_blowfish_cfb_dec, _gcry_blowfish_cbc_dec)
-       (_gcry_blowfish_ctr_enc, _gcry_cast5_cfb_dec, _gcry_cast5_cbc_dec)
-       (_gcry_cast5_ctr_enc, _gcry_camellia_cfb_dec, _gcry_camellia_cbc_dec)
-       (_gcry_camellia_ctr_enc, _gcry_serpent_cfb_dec, _gcry_serpent_cbc_dec)
-       (_gcry_serpent_ctr_enc, _gcry_twofish_cfb_dec, _gcry_twofish_cbc_dec)
-       (_gcry_twofish_ctr_enc): Ditto.
-
-       Camellia: Add AVX/AES-NI key setup.
-       + commit ef9f52cbb39e46918c96200b09c21e931eff174f
-       * cipher/camellia-aesni-avx-amd64.S (key_bitlength, key_table): New
-       order of fields in ctx.
-       (camellia_f, vec_rol128, vec_ror128): New macros.
-       (__camellia_avx_setup128, __camellia_avx_setup256)
-       (_gcry_camellia_aesni_avx_keygen): New functions.
-       * cipher/camellia-aesni-avx2-amd64.S (key_bitlength, key_table): New
-       order of fields in ctx.
-       * cipher/camellia-arm.S (CAMELLIA_TABLE_BYTE_LEN, key_length): Remove
-       unused macros.
-       * cipher/camellia-glue.c (CAMELLIA_context): Move keytable to head for
-       better alignment; Make 'use_aesni_avx' and 'use_aesni_avx2' bitfield
-       members.
-       [USE_AESNI_AVX] (_gcry_camellia_aesni_avx_keygen): New prototype.
-       (camellia_setkey) [USE_AESNI_AVX || USE_AESNI_AVX2]: Read hw features
-       to variable 'hwf' and match features from it.
-       (camellia_setkey) [USE_AESNI_AVX]: Use AES-NI/AVX key setup if
-       available.
-
-       Avoid unneeded stack burning with AES-NI and reduce number of 'decryption_prepared' checks
-       + commit c8ad83fb605fdbf6dc0b0dbcc8aedfbd477640da
-       * cipher/rijndael.c (RIJNDAEL_context): Make 'decryption_prepared',
-       'use_padlock' and 'use_aesni' 1-bit members in bitfield.
-       (do_setkey): Move 'hwfeatures' inside [USE_AESNI || USE_PADLOCK].
-       (do_aesni_enc_aligned): Rename to...
-       (do_aesni_enc): ...this, as function does not require aligned input.
-       (do_aesni_dec_aligned): Rename to...
-       (do_aesni_dec): ...this, as function does not require aligned input.
-       (do_aesni): Remove.
-       (rijndael_encrypt): Call 'do_aesni_enc' instead of 'do_aesni'.
-       (rijndael_decrypt): Call 'do_aesni_dec' instead of 'do_aesni'.
-       (check_decryption_preparation): New.
-       (do_decrypt): Remove 'decryption_prepared' check.
-       (rijndael_decrypt): Ditto and call 'check_decryption_preparation'.
-       (_gcry_aes_cbc_dec): Ditto.
-       (_gcry_aes_cfb_enc): Add 'burn_depth' and burn stack only when needed.
-       (_gcry_aes_cbc_enc): Ditto.
-       (_gcry_aes_ctr_enc): Ditto.
-       (_gcry_aes_cfb_dec): Ditto.
-       (_gcry_aes_cbc_dec): Ditto and correct clearing of 'savebuf'.
-
-2013-11-14  Werner Koch  <wk@gnupg.org>
-
-       md: Fix hashing for data >= 256 GB.
-       + commit c43a8c0d81a711161f7a81b24ef7c33a1353eee0
-       * cipher/hash-common.h (gcry_md_block_ctx): Add "nblocks_high".
-       * cipher/hash-common.c (_gcry_md_block_write): Bump NBLOCKS_HIGH.
-       * cipher/md4.c (md4_init, md4_final): Take care of NBLOCKS_HIGH.
-       * cipher/md5.c (md5_init, md5_final): Ditto.
-       * cipher/rmd160.c (_gcry_rmd160_init, rmd160_final): Ditto.
-       * cipher/sha1.c (sha1_init, sha1_final): Ditto.
-       * cipher/sha256.c (sha256_init, sha224_init, sha256_final): Ditto.
-       * cipher/sha512.c (sha512_init, sha384_init, sha512_final): Ditto.
-       * cipher/tiger.c (do_init, tiger_final): Ditto.
-       * cipher/whirlpool.c (whirlpool_final): Ditto.
-
-       * cipher/md.c (gcry_md_algo_info): Add GCRYCTL_SELFTEST.
-       (_gcry_md_selftest): Return "not implemented" as required.
-       * tests/hashtest.c: New.
-       * tests/genhashdata.c: New.
-       * tests/Makefile.am (TESTS): Add hashtest.
-       (noinst_PROGRAMS): Add genhashdata
-
-2013-11-13  Christian Grothoff  <christian@grothoff.org>
-
-       ecc: Fix key generation for a plain Ed25519 key.
-       + commit 7d91e99bcd30a463dd4faed014b8521a663d8316
-       * cipher/ecc.c (nist_generate_key): Use custom code for ED25519.
-
-       ecc: Fix some memory leaks.
-       + commit c4f9af49f228df59c218381a25fa3c0f93ccbeae
-       * cipher/ecc-curves.c (_gcry_mpi_ec_new): Free ec->b before assigning.
-       * cipher/ecc.c (nist_generate_key): Release Q.
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_genkey): Ditto.
-
-2013-11-11  Werner Koch  <wk@gnupg.org>
-
-       ecc: Change keygrip computation for Ed25519+EdDSA.
-       + commit 4fb3c8e5a7fc6a1568f54bcc0be17fecf75e0742
-       * cipher/ecc.c (compute_keygrip): Rework.
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_ensure_compact): New.
-       * cipher/ecc-curves.c (_gcry_ecc_update_curve_param): New.
-       * tests/keygrip.c (key_grips): Add flag param and test cases for
-       Ed25519.
-
-       mpi: Add special format GCRYMPI_FMT_OPAQUE.
-       + commit 8b3eecee2d89179297e43de7d650f74759c61a58
-       * src/gcrypt.h.in (GCRYMPI_FMT_OPAQUE): New.
-       (_gcry_sexp_nth_opaque_mpi): Remove.
-       * src/sexp.c (gcry_sexp_nth_mpi): Add support for GCRYMPI_FMT_OPAQUE.
-       (_gcry_sexp_vextract_param): Replace removed function by
-       GCRYMPI_FMT_OPAQUE.
-
-2013-11-10  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix error output in CTR selftest.
-       + commit 7b26586e35a6d407ca31b41528b0810b1408fd4b
-       * cipher/cipher-selftest.c (_gcry_selftest_helper_ctr): Change
-       fprintf(stderr,...) to syslog(); Correct error output for bulk
-       IV check, plaintext mismatch => ciphertext mismatch.
-
-2013-11-09  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix Serpent-AVX2 and Camellia-AVX2 counter modes.
-       + commit df29831d008e32faf74091d080a415731418d158
-       * cipher/camellia-aesni-avx2-amd64.S
-       (_gcry_camellia_aesni_avx2_ctr_enc): Byte-swap before checking for
-       overflow handling.
-       * cipher/camellia-glue.c (selftest_ctr_128, selftest_cfb_128)
-       (selftest_cbc_128): Add 16 to nblocks.
-       * cipher/cipher-selftest.c (_gcry_selftest_helper_ctr): Add test with
-       non-overflowing IV and modify overflow IV to detect broken endianness
-       handling.
-       * cipher/serpent-avx2-amd64.S (_gcry_serpent_avx2_ctr_enc): Byte-swap
-       before checking for overflow handling; Fix crazy-mixed-endian IV
-       construction to big-endian.
-       * cipher/serpent.c (selftest_ctr_128, selftest_cfb_128)
-       (selftest_cbc_128): Add 8 to nblocks.
-
-2013-11-09  Sergey V  <sftp.mtuci@gmail.com>
-
-       cipher/gost28147: optimization: use precomputed S-box tables.
-       + commit 51501b638546665163bbb85a14308fdb99211a28
-       * cipher/gost.h (GOST28147_context): Remove unneeded subst and
-       subst_set members.
-       * cipher/gost28147.c (max): Remove unneeded macro.
-       (test_sbox): Replace with new precomputed tables.
-       (gost_set_subst): Remove function.
-       (gost_val): Use new S-box tables.
-       (gost_encrypt_block, gost_decrypt_block): Tweak to use new ctx and
-       S-box tables.
-
-2013-11-09  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix tail handling for AES-NI counter mode.
-       + commit 60ed0abbbc7cb15812f1e713143c72555acea69e
-       * cipher/rijndael.c (do_aesni_ctr): Fix outputting of updated
-       counter-IV.
-
-2013-11-08  Werner Koch  <wk@gnupg.org>
-
-       ecc: Improve gcry_pk_get_curve.
-       + commit 03aed1acec611362285db5156a6b92c91604fba4
-       * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Factor some code out
-       to ..
-       (find_domain_parms_idx): new.
-       (_gcry_ecc_get_curve): Find by curve name on error.
-
-       cipher: Avoid signed divisions in idea.c.
-       + commit e241dde1420475459e32608137829e52748d0212
-       * cipher/idea.c (mul_inv): Use unsigned division.
-
-       ecc: Implement the "nocomp" flag for key generation.
-       + commit 9f63c0f7a3b2c15c7e258cd17395cabd0a8f00cc
-       * cipher/ecc.c (ecc_generate): Support the "nocomp" flag.
-       * tests/keygen.c (check_ecc_keys): Add a test for it.
-
-       ecc: Make "noparam" the default and replace by "param".
-       + commit ed45fd2e60c88e2f005282e6eadd018b59dcf65b
-       * src/cipher.h (PUBKEY_FLAG_NOCOMP): New.
-       (PUBKEY_FLAG_NOPARAM): Remove.
-       (PUBKEY_FLAG_PARAM): New.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Support the new
-       flags and ignore the obsolete "noparam" flag.
-       * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Return the curve name
-       also for curves selected by NBITS.
-       (_gcry_mpi_ec_new): Support the "param" flag.
-       * cipher/ecc.c (ecc_generate, ecc_sign, ecc_verify): Ditto.
-       * tests/keygen.c (check_ecc_keys): Remove the "noparam" flag.
-
-2013-11-07  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix decryption function size in AES AMD64 assembly.
-       + commit bfe4f6523b80bae0040328ef324b9000ee5b38a4
-       * cipher/rijndael-amd64.S (_gcry_aes_amd64_decrypt_block): Set '.size'
-       for '_gcry_aes_amd64_decrypt_block', not '..._encrypt_block'.
-
-       Change 64-bit shift to 32-bit in AES AMD64 assembly.
-       + commit 57b296ea3a5204cd3711b7bf57c8fb14d8542402
-       * cipher/rijndael-amd64.S (do16bit_shr): Change 'shrq' to 'shrl'.
-
-2013-11-06  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Speed-up AES-NI key setup.
-       + commit f702d62d888b30e24c19f203566a1473098b2b31
-       * cipher/rijndael.c [USE_AESNI] (m128i_t): Remove.
-       [USE_AESNI] (u128_t): New.
-       [USE_AESNI] (aesni_do_setkey): New.
-       (do_setkey) [USE_AESNI]: Move AES-NI accelerated key setup to
-       'aesni_do_setkey'.
-       (do_setkey): Call _gcry_get_hw_features only once. Clear stack after
-       use in generic key setup part.
-       (rijndael_setkey): Remove stack burning.
-       (prepare_decryption) [USE_AESNI]: Use 'u128_t' instead of 'm128i_t' to
-       avoid compiler generated SSE2 instructions and XMM register usage,
-       unroll 'aesimc' setup loop
-       (prepare_decryption): Clear stack after use.
-       [USE_AESNI] (do_aesni_enc_aligned): Update comment about alignment.
-       (do_decrypt): Do not burning stack after prepare_decryption.
-
-       Avoid burn stack in Arcfour setkey.
-       + commit a50a6ba3540f49fc7dcdb32e691327d5942e3509
-       * cipher/arcfour.c (arcfour_setkey): Remove stack burning.
-
-       Avoid burn_stack in CAST5 setkey.
-       + commit 5797ebc268b4e953cedd0c729c5cdb1f8fd764e4
-       * cipher/cast5.c (do_cast_setkey): Use wipememory instead of memset.
-       (cast_setkey): Remove stack burning.
-
-       Improve Serpent key setup speed.
-       + commit 9897ccb381503455edc490679b2e9251a09ac5cb
-       * cipher/serpent.c (SBOX, SBOX_INVERSE): Remove index argument.
-       (serpent_subkeys_generate): Use smaller temporary arrays for subkey
-       generation and perform stack clearing locally.
-       (serpent_setkey_internal): Use wipememory to clear stack and remove
-       _gcry_burn_stack.
-       (serpent_setkey): Remove unneeded _gcry_burn_stack.
-
-       Modify encrypt/decrypt arguments for in-place.
-       + commit b8515aa70b00baba3fba8121ed305edcd029c8c7
-       * cipher/cipher.c (gcry_cipher_encrypt, gcry_cipher_decrypt): Modify
-       local arguments if in-place operation.
-
-       Speed up Stribog.
-       + commit a48d07ccadee4cb8b666a9a4ba2f00129bad5b2f
-       * cipher/stribog.c (STRIBOG_TABLES): Remove.
-       (Pi): Remove.
-       [!STRIBOG_TABLES] (A, strido): Remove.
-       (stribog_table): New table pre-reordered with Pi values.
-       (strido): Rewrite for new table.
-       (LPSX): Rewrite for new table.
-       (xor): Remove.
-       (g): Small tweaks.
-
-       Tweak AES-NI bulk CTR mode slightly.
-       + commit 3b5058b58a183fa23ecf3ef819e2ae6ac64c0216
-       * cipher/rijndael.c [USE_AESNI] (aesni_cleanup_2_5): Rename to...
-       (aesni_cleanup_2_6): ...this and clear also 'xmm6'.
-       [USE_AESNI && __i386__] (do_aesni_ctr, do_aesni_ctr_4): Prevent
-       inlining only on i386, allow on AMD64.
-       [USE_AESNI] (do_aesni_ctr, do_aesni_ctr_4): Use counter block from
-       'xmm5' and byte-swap mask from 'xmm6'.
-       (_gcry_aes_ctr_enc) [USE_AESNI]: Preload counter block to 'xmm5' and
-       byte-swap mask to 'xmm6'.
-       (_gcry_aes_ctr_enc, _gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use
-       'aesni_cleanup_2_6'.
-
-       Tweak bench-slope parameters.
-       + commit 7e98eecc1a955bc253765f92a166b6560f085b8c
-       * tests/bench-slope.c (BUF_STEP_SIZE): Half step size to 64.
-       (NUM_MEASUREMENT_REPETITIONS): Double repetitions to 64.
-
-       Optimize Blowfish weak key check.
-       + commit 8e1c0f9b894c39b6554c544208dc000682f520c7
-       * cipher/blowfish.c (hashset_elem, val_to_hidx, add_val): New.
-       (do_bf_setkey): Use faster algorithm for detecting weak keys.
-       (bf_setkey): Move stack burning to do_bf_setkey.
-
-       Fix __builtin_bswap32/64 checks.
-       + commit 2590a5df6f5fc884614c8c379324027d2d61b9b5
-       * configure.ac (gcry_cv_have_builtin_bswap32)
-       (gcry_cv_have_builtin_bswap64): Change compile checks to link checks.
-
-       Fix 'u32' build error with Camellia.
-       + commit 84bcb400e7db7268abfc29b5ab1513b0c063b293
-       * cipher/camellia.c: Add include for <config.h> and "types.h".
-       (u32): Remove.
-       (u8): Typedef as 'byte'.
-
-2013-11-06  Werner Koch  <wk@gnupg.org>
-
-       pubkey: Add forward compatibility feature.
-       + commit 6d169b654c7ff04c10f73afe80b2c70cefa410c1
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Add
-       "igninvflag".
-
-2013-11-05  Werner Koch  <wk@gnupg.org>
-
-       ecc: Require "eddsa" flag for curve Ed25519.
-       + commit b9fd3988b54b50109f4e7179e7fe0739bb1d97c5
-       * src/cipher.h (PUBKEY_FLAG_ECDSA): Remove.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Remove "ecdsa".
-       * cipher/ecc.c (ecc_generate, ecc_sign, ecc_verify): Require "eddsa" flag.
-       * cipher/ecc-misc.c (_gcry_ecc_compute_public): Depend "eddsa" flag.
-       * tests/benchmark.c, tests/keygen.c, tests/pubkey.c
-       * tests/t-ed25519.c, tests/t-mpi-point.c: Adjust for changed flags.
-
-       ecc: Fully implement Ed25519 compression in ECDSA mode.
-       + commit f09ffe8a4802af65a116e79eceeb1cb4ed4fa2f4
-       * src/ec-context.h (mpi_ec_ctx_s): Add field FLAGS.
-       * mpi/ec.c (ec_p_init): Add arg FLAGS.  Change all callers to pass it.
-       * cipher/ecc-curves.c (point_from_keyparam): Add arg EC, parse as
-        opaque mpi and use eddsa decoding depending on the flag.
-       (_gcry_mpi_ec_new): Rearrange to parse Q and D after knowing the
-       curve.
-
-       mpi: Add function gcry_mpi_set_opaque_copy.
-       + commit 630aca794ddf057fb7265b7dc346374743036af4
-       * src/gcrypt.h.in (gcry_mpi_set_opaque_copy): New.
-       * src/visibility.c (gcry_mpi_set_opaque_copy): New.
-       * src/visibility.h (gcry_mpi_set_opaque_copy): Mark visible.
-       * src/libgcrypt.def, src/libgcrypt.vers: Add new API.
-       * tests/mpitests.c (test_opaque): Add test.
-
-2013-11-04  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Make test vectors 'static const'
-       + commit d50a88d1e29124d038196fec6082fd093e922604
-       * cipher/arcfour.c (selftest): Change test vectors to 'static const'.
-       * cipher/blowfish.c (selftest): Ditto.
-       * cipher/camellia-glue.c (selftest): Ditto.
-       * cipher/cast5.c (selftest): Ditto.
-       * cipher/des.c (selftest): Ditto.
-       * cipher/rijndael.c (selftest): Ditto.
-       * tests/basic.c (cipher_cbc_mac_cipher, check_aes128_cbc_cts_cipher)
-       (check_ctr_cipher, check_cfb_cipher, check_ofb_cipher)
-       (check_ccm_cipher, check_stream_cipher)
-       (check_stream_cipher_large_block, check_bulk_cipher_modes)
-       (check_ciphers, check_digests, check_hmac, check_pubkey_sign)
-       (check_pubkey_sign_ecdsa, check_pubkey_crypt, check_pubkey): Ditto.
-
-2013-11-03  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Make jump labels local in Salsa20 assembly.
-       + commit d4697862266f3c96b6946dc92139dd8f3e81e5f6
-       * cipher/salsa20-amd64.S: Rename '._labels' to '.L_labels'.
-       * cipher/salsa20-armv7-neon.S: Ditto.
-
-2013-10-30  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       bithelp: fix undefined behaviour with rol and ror.
-       + commit d1cadd145199040299538891ab2ccd1208f7776e
-       * cipher/bithelp.h (rol, ror): Mask shift with 31.
-
-2013-10-29  Werner Koch  <wk@gnupg.org>
-
-       tests: Add feature to skip benchmarks.
-       + commit ba6bffafd17bea11985afc500022d66da261d59a
-       * tests/benchmark.c (main): Add feature to skip the test.
-       * tests/bench-slope.c (main): Ditto.
-       (get_slope): Repace C++ style comment.
-       (double_cmp, cipher_bench, _hash_bench): Repalce system reserved
-       symbols.
-
-       ecc: Finish Ed25519/ECDSA hack.
-       + commit c284f15db99e9cb135612de710199abb23baafd3
-       * cipher/ecc.c (ecc_generate): Fix Ed25519/ECDSA case.
-       (ecc_verify): Implement ED25519/ECDSA uncompression.
-
-       ecc: Add flags "noparam" and "comp".
-       + commit ba892a0a874c8b2a83dbf0940608cd7e2911ce01
-       * src/cipher.h (PUBKEY_FLAG_NOPARAM, PUBKEY_FLAG_COMP): New.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Parse new flags
-       and change code for possible faster parsing.
-       * cipher/ecc.c (ecc_generate): Implement the "noparam" flag.
-       (ecc_sign): Ditto.
-       (ecc_verify): Ditto.
-       * tests/keygen.c (check_ecc_keys): Use the "noparam" flag.
-
-       * cipher/ecc.c (ecc_generate): Fix parsing of the deprecated
-       transient-flag parameter.
-       (ecc_verify): Do not make Q optional in the extract-param call.
-
-2013-10-28  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix typos in documentation.
-       + commit 1faa61845f180bd47e037e400dde2d864ee83c89
-       * doc/gcrypt.texi: Fix some typos.
-
-       Add ARM NEON assembly implementation of Serpent.
-       + commit 2cb6e1f323d24359b1c5b113be5c2f79a2a4cded
-       * cipher/Makefile.am: Add 'serpent-armv7-neon.S'.
-       * cipher/serpent-armv7-neon.S: New.
-       * cipher/serpent.c (USE_NEON): New macro.
-       (serpent_context_t) [USE_NEON]: Add 'use_neon'.
-       [USE_NEON] (_gcry_serpent_neon_ctr_enc, _gcry_serpent_neon_cfb_dec)
-       (_gcry_serpent_neon_cbc_dec): New prototypes.
-       (serpent_setkey_internal) [USE_NEON]: Detect NEON support.
-       (_gcry_serpent_neon_ctr_enc, _gcry_serpent_neon_cfb_dec)
-       (_gcry_serpent_neon_cbc_dec) [USE_NEON]: Use NEON implementations
-       to process eight blocks in parallel.
-       * configure.ac [neonsupport]: Add 'serpent-armv7-neon.lo'.
-
-       Add ARM NEON assembly implementation of Salsa20.
-       + commit 3ff9d2571c18cd7a34359f9c60a10d3b0f932b23
-       * cipher/Makefile.am: Add 'salsa20-armv7-neon.S'.
-       * cipher/salsa20-armv7-neon.S: New.
-       * cipher/salsa20.c [USE_ARM_NEON_ASM]: New macro.
-       (struct SALSA20_context_s, salsa20_core_t, salsa20_keysetup_t)
-       (salsa20_ivsetup_t): New.
-       (SALSA20_context_t) [USE_ARM_NEON_ASM]: Add 'use_neon'.
-       (SALSA20_context_t): Add 'keysetup', 'ivsetup' and 'core'.
-       (salsa20_core): Change 'src' argument to 'ctx'.
-       [USE_ARM_NEON_ASM] (_gcry_arm_neon_salsa20_encrypt): New prototype.
-       [USE_ARM_NEON_ASM] (salsa20_core_neon, salsa20_keysetup_neon)
-       (salsa20_ivsetup_neon): New.
-       (salsa20_do_setkey): Setup keysetup, ivsetup and core with default
-       functions.
-       (salsa20_do_setkey) [USE_ARM_NEON_ASM]: When NEON support detect,
-       set keysetup, ivsetup and core with ARM NEON functions.
-       (salsa20_do_setkey): Call 'ctx->keysetup'.
-       (salsa20_setiv): Call 'ctx->ivsetup'.
-       (salsa20_do_encrypt_stream) [USE_ARM_NEON_ASM]: Process large buffers
-       in ARM NEON implementation.
-       (salsa20_do_encrypt_stream): Call 'ctx->core' instead of directly
-       calling 'salsa20_core'.
-       (selftest): Add test to check large buffer processing and block counter
-       updating.
-       * configure.ac [neonsupport]: 'Add salsa20-armv7-neon.lo'.
-
-       Add AMD64 assembly implementation of Salsa20.
-       + commit 5a3d43485efdc09912be0967ee0a3ce345b3b15a
-       * cipher/Makefile.am: Add 'salsa20-amd64.S'.
-       * cipher/salsa20-amd64.S: New.
-       * cipher/salsa20.c (USE_AMD64): New macro.
-       [USE_AMD64] (_gcry_salsa20_amd64_keysetup, _gcry_salsa20_amd64_ivsetup)
-       (_gcry_salsa20_amd64_encrypt_blocks): New prototypes.
-       [USE_AMD64] (salsa20_keysetup, salsa20_ivsetup, salsa20_core): New.
-       [!USE_AMD64] (salsa20_core): Change 'src' to non-constant, update block
-       counter in 'salsa20_core' and return burn stack depth.
-       [!USE_AMD64] (salsa20_keysetup, salsa20_ivsetup): New.
-       (salsa20_do_setkey): Move generic key setup to 'salsa20_keysetup'.
-       (salsa20_setkey): Fix burn stack depth.
-       (salsa20_setiv): Move generic IV setup to 'salsa20_ivsetup'.
-       (salsa20_do_encrypt_stream) [USE_AMD64]: Process large buffers in AMD64
-       implementation.
-       (salsa20_do_encrypt_stream): Move stack burning to this function...
-       (salsa20_encrypt_stream, salsa20r12_encrypt_stream): ...from these
-       functions.
-       * configure.ac [x86-64]: Add 'salsa20-amd64.lo'.
-
-       Add new benchmarking utility, bench-slope.
-       + commit e214e8392671dd30e9c33260717b5e756debf3bf
-       * tests/Makefile.am (TESTS): Add 'bench-slope'.
-       * tests/bench-slope.c: New.
-
-       Change .global to .globl in assembly files.
-       + commit ebc8abfcb09d6106fcfce40f240a513e276f46e9
-       * cipher/blowfish-arm.S: Change '.global' to '.globl'.
-       * cipher/camellia-aesni-avx-amd64.S: Ditto.
-       * cipher/camellia-aesni-avx2-amd64.S: Ditto.
-       * cipher/camellia-arm.S: Ditto.
-       * cipher/cast5-amd64.S: Ditto.
-       * cipher/rijndael-amd64.S: Ditto.
-       * cipher/rijndael-arm.S: Ditto.
-       * cipher/serpent-avx2-amd64.S: Ditto.
-       * cipher/serpent-sse2-amd64.S: Ditto.
-       * cipher/twofish-amd64.S: Ditto.
-       * cipher/twofish-arm.S: Ditto.
-
-2013-10-26  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Deduplicate code for ECB encryption and decryption.
-       + commit 51f1beab3d1e879942a95f58b08de7dbcce75dce
-       * cipher/cipher.c (do_ecb_crypt): New, based on old 'do_ecb_encrypt'.
-       (do_ecb_encrypt): Use 'do_ecb_crypt', pass encryption function.
-       (do_ecb_decrypt): Use 'do_ecb_crypt', pass decryption function.
-
-2013-10-26  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Drop _gcry_cipher_ofb_decrypt as it duplicates _gcry_cipher_ofb_encrypt.
-       + commit d9431725952e40f201c7eda000d3c8511ebd5b33
-       * cipher/cipher.c (cipher_decrypt): Use _gcry_cipher_ofb_encrypt for OFB
-         decryption.
-       * cipher/cipher-internal.h: Remove _gcry_cipher_ofb_decrypt declaration.
-       * cipher/cipher-ofb.c (_gcry_cipher_ofb_decrypt): Remove.
-         (_gcry_cipher_ofb_encrypt): remove copying of IV to lastiv, it's
-         unused there.
-
-2013-10-25  Werner Koch  <wk@gnupg.org>
-
-       tests: Add tests for mpi_cmp.
-       + commit 6c6d4810927de7310ae7bac61b4ff5467d7cb485
-       * tests/mpitests.c (die): Modernize.
-       (fail): New.
-       (test_opaque, test_add, test_sub, test_mul): Use gcry_log_xx
-       (main): Return error count.
-       (test_cmp): New.
-
-2013-10-24  Werner Koch  <wk@gnupg.org>
-
-       ecc: Change algorithm for Ed25519 x recovery.
-       + commit c630fd71b336eb9209e914d24dc1e26a34521882
-       * cipher/ecc-eddsa.c (scanval): Add as temporary hack.
-       (_gcry_ecc_eddsa_recover_x): Use the algorithm from page 15 of the
-       paper.  Return an error code.
-       (_gcry_ecc_eddsa_decodepoint): Take care of the error code.
-       * mpi/mpi-mul.c (gcry_mpi_mulm): Use truncated division.
-
-       ecc: Refactor _gcry_ecc_eddsa_decodepoint.
-       + commit 1cf5699b6febab1ef9d300531acc2ee33a7df739
-       * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_decodepoint): Factor some code
-       out to ..
-       (_gcry_ecc_eddsa_recover_x): new.
-
-2013-10-24  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       ecc-gost: Add missing include.
-       + commit 9ce54e5b512418ddf45ce18f2cbd48cdced779f5
-       * ecc-gost.c: Include "pubkey-internal.h".
-
-2013-10-23  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Replace architecture specific fast_wipememory2 with generic.
-       + commit 54df6fcd806f8c150cffe6cc09925bb8b638bb5b
-       * src/g10lib.h (fast_wipememory2): Remove architecture specific
-       implementations and add generic implementation.
-
-       Improve the speed of the cipher mode code.
-       + commit 293e93672fdabc829e35cc624c397276342bafe4
-       * cipher/bufhelp.h (buf_cpy): New.
-       (buf_xor, buf_xor_2dst): If buffers unaligned, always jump to per-byte
-       processing.
-       (buf_xor_n_copy_2): New.
-       (buf_xor_n_copy): Use 'buf_xor_n_copy_2'.
-       * cipher/blowfish.c (_gcry_blowfish_cbc_dec): Avoid extra memory copy
-       and use new 'buf_xor_n_copy_2'.
-       * cipher/camellia-glue.c (_gcry_camellia_cbc_dec): Ditto.
-       * cipher/cast5.c (_gcry_cast_cbc_dec): Ditto.
-       * cipher/serpent.c (_gcry_serpent_cbc_dec): Ditto.
-       * cipher/twofish.c (_gcry_twofish_cbc_dec): Ditto.
-       * cipher/rijndael.c (_gcry_aes_cbc_dec): Ditto.
-       (do_encrypt, do_decrypt): Use 'buf_cpy' instead of 'memcpy'.
-       (_gcry_aes_cbc_enc): Avoid copying IV, use 'last_iv' pointer instead.
-       * cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt): Avoid copying IV,
-       update pointer to IV instead.
-       (_gcry_cipher_cbc_decrypt): Avoid extra memory copy and use new
-       'buf_xor_n_copy_2'.
-       (_gcry_cipher_cbc_encrypt, _gcry_cipher_cbc_decrypt): Avoid extra
-       accesses to c->spec, use 'buf_cpy' instead of memcpy.
-       * cipher/cipher-ccm.c (do_cbc_mac): Ditto.
-       * cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt)
-       (_gcry_cipher_cfb_decrypt): Ditto.
-       * cipher/cipher-ctr.c (_gcry_cipher_ctr_encrypt): Ditto.
-       * cipher/cipher-ofb.c (_gcry_cipher_ofb_encrypt)
-       (_gcry_cipher_ofb_decrypt): Ditto.
-       * cipher/cipher.c (do_ecb_encrypt, do_ecb_decrypt): Ditto.
-
-       bufhelp: enable unaligned memory accesses for AArch64 (64-bit ARM)
-       + commit 2901a10dbf1264707debc8402546c07eeac60932
-       * cipher/bufhelp.h [__aarch64__] (BUFHELP_FAST_UNALIGNED_ACCESS): Set
-       macro on AArch64.
-
-2013-10-23  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Enable assembler optimizations on earlier ARM cores.
-       + commit 2fd83faa876d0be91ab7884b1a9eaa7793559eb9
-       * cipher/blowfish-armv6.S => cipher/blowfish-arm.S: adapt to pre-armv6 CPUs.
-       * cipher/blowfish.c: enable assembly on armv4/armv5 little-endian CPUs.
-       * cipher/camellia-armv6.S => cipher/camellia-arm.S: adapt to pre-armv6 CPUs.
-       * cipher/camellia.c, cipher-camellia-glue.c: enable assembly on armv4/armv5
-         little-endian CPUs.
-       * cipher/cast5-armv6.S => cipher/cast5-arm.S: adapt to pre-armv6 CPUs.
-       * cipher/cast5.c: enable assembly on armv4/armv5 little-endian CPUs.
-       * cipher/rijndael-armv6.S => cipher/rijndael-arm.S: adapt to pre-armv6 CPUs.
-       * cipher/rijndael.c: enable assembly on armv4/armv5 little-endian CPUs.
-       * cipher/twofish-armv6.S => cipher/twofish-arm.S: adapt to pre-armv6 CPUs.
-       * cipher/twofish.c: enable assembly on armv4/armv5 little-endian CPUs.
-
-       mpi: enable assembler on all arm architectures.
-       + commit 0b39fce7e3ce6761d6bd5195d093ec6857edb7c2
-       * mpi/config.links: remove check for arm >= v6
-       * mpi/armv6 => mpi/arm: rename directory to reflect that is is generic
-         enough
-
-       Correct ASM assembly test in configure.ac.
-       + commit 10bf6a7e16ed193f90d2749970a420f00d1d3320
-       * configure.ac: correct HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS test to
-         require neither ARMv6, nor thumb mode. Our assembly code works
-         perfectly even on ARMv4 now.
-
-2013-10-23  Werner Koch  <wk@gnupg.org>
-
-       ecc: Refactor ecc.c.
-       + commit 164eb8c85d773ef4f0939115ec45f5e4b47c1700
-       * cipher/ecc-ecdsa.c, cipher/ecc-eddsa.c, cipher/ecc-gost.c: New.
-       * cipher/Makefile.am (EXTRA_libcipher_la_SOURCES): Add new files.
-       * configure.ac (GCRYPT_PUBKEY_CIPHERS): Add new files.
-       * cipher/ecc.c (point_init, point_free): Move to ecc-common.h.
-       (sign_ecdsa): Move to ecc-ecdsa.c as _gcry_ecc_ecdsa_sign.
-       (verify_ecdsa): Move to ecc-ecdsa.c as _gcry_ecc_ecdsa_verify.
-       (sign_gost): Move to ecc-gots.c as _gcry_ecc_gost_sign.
-       (verify_gost): Move to ecc-gost.c as _gcry_ecc_gost_verify.
-       (sign_eddsa): Move to ecc-eddsa.c as _gcry_ecc_eddsa_sign.
-       (verify_eddsa): Move to ecc-eddsa.c as _gcry_ecc_eddsa_verify.
-       (eddsa_generate_key): Move to ecc-eddsa.c as _gcry_ecc_eddsa_genkey.
-       (reverse_buffer): Move to ecc-eddsa.c.
-       (eddsa_encodempi, eddsa_encode_x_y): Ditto.
-       (_gcry_ecc_eddsa_encodepoint, _gcry_ecc_eddsa_decodepoint): Ditto.
-
-       mpi: Fix scanning of negative SSH formats and add more tests.
-       + commit 45f6e6268bfdc4b608beaba6b7086b2286e33c71
-       * mpi/mpicoder.c (gcry_mpi_scan): Fix sign setting for SSH format.
-       * tests/t-convert.c (negative_zero): Test all formats.
-       (check_formats): Add tests for PGP and scan tests for SSH and USG.
-
-       * src/gcrypt.h.in (mpi_is_neg): Fix macro.
-
-       * mpi/mpi-scan.c (_gcry_mpi_getbyte, _gcry_mpi_putbyte): Comment out
-       these unused functions.
-
-2013-10-22  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       twofish: add ARMv6 assembly implementation.
-       + commit 98674fdaa30ab22a3ac86ca05d688b5b6112895d
-       * cipher/Makefile.am: Add 'twofish-armv6.S'.
-       * cipher/twofish-armv6.S: New.
-       * cipher/twofish.c (USE_ARMV6_ASM): New macro.
-       [USE_ARMV6_ASM] (_gcry_twofish_armv6_encrypt_block)
-       (_gcry_twofish_armv6_decrypt_block): New prototypes.
-       [USE_AMDV6_ASM] (twofish_encrypt, twofish_decrypt): Add.
-       [USE_AMD64_ASM] (do_twofish_encrypt, do_twofish_decrypt): Remove.
-       (_gcry_twofish_ctr_enc, _gcry_twofish_cfb_dec): Use 'twofish_encrypt'
-       instead of 'do_twofish_encrypt'.
-       (_gcry_twofish_cbc_dec): Use 'twofish_decrypt' instead of
-       'do_twofish_decrypt'.
-       * configure.ac [arm]: Add 'twofish-armv6.lo'.
-
-       mpi: allow building with clang on ARM.
-       + commit e67c67321ce240c93dd0fa2b21c649c0a8e233f7
-       * mpi/longlong.h [__arm__] (add_ssaaaa, sub_ddmmss, umul_ppmm)
-       (count_leading_zeros): Do not cast assembly output arguments.
-       [__arm__] (umul_ppmm): Remove the extra '%' ahead of assembly comment.
-       [_ARM_ARCH >= 4] (umul_ppmm): Use correct inputs and outputs instead of
-       registers.
-
-       serpent-amd64: do not use GAS macros.
-       + commit c7efaa5fe0ee92e321a7b49d56752cc12eb75fe0
-       * cipher/serpent-avx2-amd64.S: Remove use of GAS macros.
-       * cipher/serpent-sse2-amd64.S: Ditto.
-       * configure.ac [HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS]: Do not check
-       for GAS macros.
-
-       Add Counter with CBC-MAC mode (CCM)
-       + commit 335d9bf7b035815750b63a3a8334d6ce44dc4449
-       * cipher/Makefile.am: Add 'cipher-ccm.c'.
-       * cipher/cipher-ccm.c: New.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode'.
-       (_gcry_cipher_ccm_encrypt, _gcry_cipher_ccm_decrypt)
-       (_gcry_cipher_ccm_set_nonce, _gcry_cipher_ccm_authenticate)
-       (_gcry_cipher_ccm_get_tag, _gcry_cipher_ccm_check_tag)
-       (_gcry_cipher_ccm_set_lengths): New prototypes.
-       * cipher/cipher.c (gcry_cipher_open, cipher_encrypt, cipher_decrypt)
-       (_gcry_cipher_setiv, _gcry_cipher_authenticate, _gcry_cipher_gettag)
-       (_gcry_cipher_checktag, gry_cipher_ctl): Add handling for CCM mode.
-       * doc/gcrypt.texi: Add documentation for GCRY_CIPHER_MODE_CCM.
-       * src/gcrypt.h.in (gcry_cipher_modes): Add 'GCRY_CIPHER_MODE_CCM'.
-       (gcry_ctl_cmds): Add 'GCRYCTL_SET_CCM_LENGTHS'.
-       (GCRY_CCM_BLOCK_LEN): New.
-       * tests/basic.c (check_ccm_cipher): New.
-       (check_cipher_modes): Call 'check_ccm_cipher'.
-       * tests/benchmark.c (ccm_aead_init): New.
-       (cipher_bench): Add handling for AEAD modes and add CCM benchmarking.
-
-       Add API to support AEAD cipher modes.
-       + commit 95654041f2aa62f71aac4d8614dafe8433d10f95
-       * cipher/cipher.c (_gcry_cipher_authenticate, _gcry_cipher_checktag)
-       (_gcry_cipher_gettag): New.
-       * doc/gcrypt.texi: Add documentation for new API functions.
-       * src/visibility.c (gcry_cipher_authenticate, gcry_cipher_checktag)
-       (gcry_cipher_gettag): New.
-       * src/gcrypt.h.in, src/visibility.h: add declarations of these
-       functions.
-       * src/libgcrypt.defs, src/libgcrypt.vers: export functions.
-
-2013-10-22  NIIBE Yutaka  <gniibe@fsij.org>
-
-       ecc: Correct compliant key generation for Edwards curves.
-       + commit a5a277a9016ccb34f1858a65e0ed1791b2fc3db3
-       * cipher/ecc.c: Add case for Edwards curves.
-
-2013-10-17  Werner Koch  <wk@gnupg.org>
-
-       tests: Add test options to keygen.
-       + commit f7711e6eb5f02d03c74911f6f037ab28075e7c0d
-       * tests/keygen.c (usage): New.
-       (main): Print usage info.  Allow running just one algo.
-
-       mpi: Do not clear the sign of the mpi_mod result.
-       + commit 91e007606f1f6f8e1416c403fe809d47fddf9b1f
-       * mpi/mpi-mod.c (_gcry_mpi_mod): Remove sign setting.
-
-       ecc: Put the curve name again into the output of gcry_pk_genkey.
-       + commit 4776dcd394ce59fa50d959921857b3427c5a63c8
-       * cipher/ecc.c (ecc_generate): Use the correct var.  Release
-       CURVE_FLAGS.
-
-       ecc: Support Weierstrass curves in gcry_mpi_ec_curve_point.
-       + commit b22417158c50ec3a0b2ff55b4ade063b42a87e8f
-       * mpi/ec.c (_gcry_mpi_ec_curve_point): Support MPI_EC_WEIERSTRASS.
-
-2013-10-16  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       arcfour: more optimized version for non-i386 architectures.
-       + commit f9371c026aad09ff48746d22c8333746c886e773
-       * cipher/arcfour.c (ARCFOUR_context): Reorder members.
-       (do_encrypt_stream) [!__i386__]: Faster implementation for non-i386.
-       (do_arcfour_setkey): Avoid modulo operations.
-
-       Avoid void* pointer arithmetic.
-       + commit c89ab921ccfaefe6c4f6a724d01e0df41a1a381f
-       * tests/tsexp.c (check_extract_param): Cast void* pointers to char*
-       before doing arithmetics.
-
-2013-10-16  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       ecc: Add support for GOST R 34.10-2001/-2012 signatures.
-       + commit 83902f1f1dbc8263a0c3f61be59cd2eb95293c97
-       * src/cipher.h: define PUBKEY_FLAG_GOST
-       * cipher/ecc-curves.c: Add GOST2001-test and GOST2012-test curves
-         defined in standards. Typical applications would use either those
-         curves, or curves defined in RFC 4357 (will be added later).
-       * cipher/ecc.c (sign_gost, verify_gost): New.
-         (ecc_sign, ecc_verify): use sign_gost/verify_gost if PUBKEY_FLAG_GOST
-         is set.
-         (ecc_names): add "gost" for gost signatures.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist,
-         _gcry_pk_util_preparse_sigval): set PUBKEY_FLAG_GOST if gost flag
-         is present in s-exp.
-       * tests/benchmark.c (ecc_bench): also benchmark GOST signatures.
-       * tests/basic.c (check_pubkey): add two public keys from
-         GOST R 34.10-2012 standard.
-         (check_pubkey_sign_ecdsa): add two data sets to check gost signatures.
-       * tests/curves.c: correct N_CURVES as we now have 2 more curves.
-
-
-       Removed some comments from the new curve definitions in ecc-curves.c
-       to avoid line wrapping.  Eventually we will develop a precompiler to
-       avoid parsing those hex strings. -wk
-
-       Fix 256-bit ecdsa test key definition.
-       + commit 187b2bb541b985255aee262d181434a7cb4ae2e7
-       * tests/basic.c (check_pubkey): fix nistp256 testing key declaration -
-         add missing comma.
-
-2013-10-16  Werner Koch  <wk@gnupg.org>
-
-       sexp: Add function gcry_sexp_extract_param.
-       + commit a329b6abf00c990faf1986f9fbad7b4d71c13bcb
-       * src/gcrypt.h.in (_GCRY_GCC_ATTR_SENTINEL): New.
-       (gcry_sexp_extract_param): New.
-       * src/visibility.c (gcry_sexp_extract_param): New.
-       * src/visibility.h (gcry_sexp_extract_param): Add hack to detect
-       internal use.
-       * cipher/pubkey-util.c (_gcry_pk_util_extract_mpis): Move and split
-       into ...
-       * src/sexp.c (_gcry_sexp_vextract_param)
-       (_gcry_sexp_extract_param): this.  Change all callers.  Add support for buffer
-       descriptors and a path option/
-
-       * tests/tsexp.c (die, hex2buffer, hex2mpi, hex2mpiopa): New.
-       (cmp_mpihex, cmp_bufhex): New.
-       (check_extract_param): New.
-
-2013-10-16  NIIBE Yutaka  <gniibe@fsij.org>
-
-       mpi: mpi-pow improvement.
-       + commit 45aa6131e93fac89d46733b3436d960f35fb99b2
-       * mpi/mpi-pow.c (gcry_mpi_powm): New implementation of left-to-right
-       k-ary exponentiation.
-
-2013-10-15  Werner Koch  <wk@gnupg.org>
-
-       ecc:  Support use of Ed25519 with ECDSA.
-       + commit 537969fbbb1104b8305a7edb331b7666d54eff2c
-       * src/cipher.h (PUBKEY_FLAG_ECDSA): New.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Add flag "ecdsa".
-       * cipher/ecc.c (verify_ecdsa, verify_eddsa): Remove some debug output.
-       (ecc_generate, ecc_sign, ecc_verify): Support Ed25519 with ECDSA.
-       * tests/keygen.c (check_ecc_keys): Create such a test key.
-       * tests/pubkey.c (fail, info, data_from_hex, extract_cmp_data): New.
-       Take from dsa-6979.c
-       (check_ed25519ecdsa_sample_key): new.
-       (main): Call new test.
-
-2013-10-14  Werner Koch  <wk@gnupg.org>
-
-       pubkey: Support flags list in gcry_pk_genkey.
-       + commit d3a605d7827b8a73ef844e9e5183590bd6b1389a
-       * src/cipher.h (PUBKEY_FLAG_TRANSIENT_KEY): New.
-       (PUBKEY_FLAG_USE_X931): New.
-       (PUBKEY_FLAG_USE_FIPS186): New.
-       (PUBKEY_FLAG_USE_FIPS186_2): New.
-       * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Rename from
-       parse_flags_list.  Parse new flags.
-       * cipher/dsa.c (dsa_generate): Support flag list.
-       * cipher/ecc.c (ecc_generate): Ditto.
-       * cipher/rsa.c (rsa_generate): Ditto.
-
-       pubkey: Remove duplicated flag parsing code.
-       + commit 5be2345ddec4147e535d5b039ee74f84bcacf9e4
-       * cipher/pubkey-util.c (_gcry_pk_util_preparse_encval)
-       (_gcry_pk_util_data_to_mpi): Factor flag parsing code out to ..
-       (parse_flag_list): New.
-       * src/cipher.h (PUBKEY_FLAG_RAW_FLAG): New.
-
-       mpicalc: Accept lowercase hex digits.
-       + commit 0cd551faa775ad5309a40629ae30bf86b75fca09
-       * src/mpicalc.c (main): Test for lowercase hex digits.
-
-2013-10-11  Werner Koch  <wk@gnupg.org>
-
-       pubkey: Move sexp parsing of remaining fucntions to the modules.
-       + commit a951c061523e1c13f1358c9760fc3a9d787ab2d4
-       * cipher/pubkey.c (release_mpi_array): Remove.
-       (pubkey_check_secret_key): Remove.
-       (sexp_elements_extract): Remove.
-       (sexp_elements_extract_ecc): Remove.
-       (sexp_to_key): Remove.
-       (get_hash_algo): Remove.
-       (gcry_pk_testkey): Revamp.
-       (gcry_pk_get_curve): Revamp.
-       * cipher/rsa.c (rsa_check_secret_key): Revamp.
-       * cipher/elgamal.c (elg_check_secret_key): Revamp.
-       * cipher/dsa.c (dsa_check_secret_key): Revamp.
-       * cipher/ecc.c (ecc_check_secret_key): Revamp.
-       * cipher/ecc-curves.c: Include cipher.h and pubkey-internal.h
-       (_gcry_ecc_get_curve): Revamp.
-
-       * cipher/pubkey-util.c (_gcry_pk_util_extract_mpis): Set passed and
-       used parameters on error to NULL.
-
-       pubkey: Move sexp parsing for gcry_pk_decrypt to the modules.
-       + commit 07950c865a901afc48acb46f0695040cadfd5068
-       * cipher/rsa.c (rsa_decrypt): Revamp.
-       * cipher/elgamal.c (elg_decrypt): Revamp.
-       * cipher/ecc.c (ecc_decrypt_raw): Revamp.
-       * cipher/pubkey.c (gcry_pk_decrypt): Simplify.
-       (sexp_to_enc): Remove.
-       * cipher/pubkey-util.c (_gcry_pk_util_preparse_encval): New.
-
-       pubkey: Move sexp parsing for gcry_pk_encrypt to the modules.
-       + commit 6bd5d18c45a4a3ce8f0f66f56c83b80594877f53
-       * cipher/rsa.c (rsa_encrypt): Revamp.
-       * cipher/elgamal.c (elg_encrypt): Revamp.
-       * cipher/ecc.c (ecc_encrypt_raw): Revamp.
-       * cipher/pubkey.c (gcry_pk_encrypt): Simplify.
-
-       * tests/basic.c (check_pubkey_crypt): Init plain, ciph, and data so
-       that they are initialized even after an encrypt failure.
-
-       pubkey: Move sexp parsing for gcry_pk_sign to the modules.
-       + commit d0ae6635e4e6ae273c3a137c513d518f28f6eab3
-       * cipher/rsa.c (rsa_sign): Revamp.
-       * cipher/dsa.c (dsa_sign): Revamp.
-       * cipher/elgamal.c (elg_sign): Revamp.
-       * cipher/ecc.c (ecc_sign): Revamp.
-       * cipher/pubkey.c (gcry_pk_sign): Simplify.
-
-2013-10-10  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Prevent tail call optimization with _gcry_burn_stack.
-       + commit 150c0313f971bcea62d2802f0389c883e11ebb31
-       * configure.ac: New check, HAVE_GCC_ASM_VOLATILE_MEMORY.
-       * src/g10lib.h (_gcry_burn_stack): Rename to __gcry_burn_stack.
-       (__gcry_burn_stack_dummy): New.
-       (_gcry_burn_stack): New macro.
-       * src/misc.c (_gcry_burn_stack): Rename to __gcry_burn_stack.
-       (__gcry_burn_stack_dummy): New.
-
-2013-10-09  Werner Koch  <wk@gnupg.org>
-
-       pubkey: Move sexp parsing for gcry_pk_verify to the modules.
-       + commit 94b652ecb006c29fa2ffb1badc9f02b758581737
-       * cipher/rsa.c (rsa_verify): Revamp.
-       * cipher/dsa.c (dsa_verify): Revamp.
-       * cipher/elgamal.c (elg_verify): Revamp.
-       * cipher/ecc.c (ecc_verify): Revamp.
-       * cipher/pubkey.c (sexp_to_sig): Remove.
-       (pss_verify_cmp): Move to pubkey-util.c
-       (sexp_data_to_mpi): Ditto.
-       (init_encoding_ctx): Ditto.
-       (gcry_pk_verify): Simplify.
-       * cipher/pubkey-util.c (_gcry_pk_util_init_encoding_ctx): Add. Take
-       from pubkey.c
-       (get_hash_algo): Ditto.
-       (_gcry_pk_util_data_to_mpi): Ditto.
-       (pss_verify_cmp): Ditto.
-       (_gcry_pk_util_extract_mpis): New.
-       (_gcry_pk_util_preparse_sigval): New.
-       (_gcry_pk_util_free_encoding_ctx): New.
-       * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Make curve init
-       optional.
-
-       * src/g10lib.h (GCC_ATTR_SENTINEL): New.
-
-       * tests/basic.c (check_pubkey_sign): Print the algo name.
-       (main): Add option --pubkey.
-
-2013-10-08  Werner Koch  <wk@gnupg.org>
-
-       pubkey: Move sexp parsing for gcry_pk_get_nbits to the modules.
-       + commit 4645f3728bb0900591b0aef85831fdee52c59e3c
-       * cipher/pubkey.c (spec_from_sexp): New.
-       (gcry_pk_get_nbits): Simplify.
-       * cipher/rsa.c (rsa_get_nbits): Take only PARMS as args and do sexp
-       parsing here.
-       * cipher/dsa.c (dsa_get_nbits): Ditto.
-       * cipher/elgamal.c (elg_get_nbits): Ditto.
-       * cipher/ecc.c (ecc_get_nbits): Ditto.
-       * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Allow NULL for arg
-       CURVE.
-
-       pubkey: Move sexp parsing for gcry_pk_getkey to the modules.
-       + commit 3816e46ce211e63adf46dbc775510aa137572248
-       * cipher/pubkey-util.c: New.
-       (_gcry_pk_util_get_nbits): New.  Based on code from gcry_pk_genkey.
-       (_gcry_pk_util_get_rsa_use_e): Ditto.
-       * cipher/pubkey.c (gcry_pk_genkey): Strip most code and pass.
-       * cipher/rsa.c (rsa_generate): Remove args ALGO, NBITS and EVALUE.
-       Call new fucntions to get these values.
-       * cipher/dsa.c (dsa_generate): Remove args ALGO, NBITS and EVALUE.
-       Call _gcry_pk_util_get_nbits to get nbits.  Always parse genparms.
-       * cipher/elgamal.c (elg_generate): Ditto.
-       * cipher/ecc.c (ecc_generate): Ditto.
-
-       cipher: Deprecate GCRY_PK_ELG_E.
-       + commit f79d3e13d3229115c47cbe5007647cb44105fe3f
-       * cipher/elgamal.c (_gcry_pubkey_spec_elg_e): Remove.
-       * cipher/pubkey.c (pubkey_list): Remove double included
-       _gcry_pubkey_spec_elg.
-       (map_algo): MAke ELG_E to ELG.
-
-2013-10-02  Werner Koch  <wk@gnupg.org>
-
-       Provide Pth compatiblity for use with GnuPG 2.0.
-       + commit 2f767f6a17f7e99da4075882f7fe3ca597b31bdb
-       * src/ath.c (ath_install): Call ath_init and declare Pth as
-       compatible.
-
-2013-10-02  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       sha512: fix building on ARM.
-       + commit 6410152338a2b2ac1216e70c153cd16f9199c94e
-       * cipher/sha512.c (transform) [USE_ARM_NEON_ASM]: Fix 'hd' to 'ctx'.
-
-2013-10-02  Werner Koch  <wk@gnupg.org>
-
-       Remove deprecated control codes.
-       + commit f04a1db22d982627ba87da4e5df52df9b994c779
-       * src/gcrypt.h.in (GCRYCTL_SET_KEY): Remove.
-       (GCRYCTL_SET_IV): Remove.
-       (GCRYCTL_SET_CTR): Remove.
-       * cipher/md.c (gcry_md_ctl): Remove deprecated GCRYCTL_SET_KEY.
-       * cipher/cipher.c (gcry_cipher_ctl): Remove deprecated
-       GCRYCTL_SET_KEY, GCRYCTL_SET_IV, GCRYCTL_SET_CTR.
-
-2013-10-02  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Fix errors when building with Clang on PPC.
-       + commit 33757c1e03f1d885920633edf543cd1c77999455
-       * mpi/longlong.h (add_ssaaaa, sub_ddmmss, count_leading_zeros,
-         umul_ppmm): Do not cast asm output to USItype.
-
-2013-10-02  Werner Koch  <wk@gnupg.org>
-
-       Remove last remains of the former module system.
-       + commit 628ed5ba0ef4b1f04b5a77e29e4bc49a1fe13c07
-       * src/gcrypt-module.h, src/module.c: Remove.
-       * src/visibility.h: Do not include gcrypt-module.h.
-       * src/g10lib.h: Remove all prototypes from module.c
-       (gcry_module): Remove.
-       * cipher/cipher-internal.h (gcry_cipher_handle): Remove unused field.
-
-       Fix missing prototype warning in visibility.c.
-       + commit 52783d483293d48cd468143ae6ae2cccbfe17200
-       * src/ec-context.h (_gcry_mpi_ec_new): Move prototype to mpi.h.
-
-       md: Simplify the message digest dispatcher md.c.
-       + commit 0d39997932617ba20656f8bcc230ba744b76c87e
-       * src/gcrypt-module.h (gcry_md_spec_t):  Move to ...
-       * src/cipher-proto.h: here.  Merge with md_extra_spec_t.  Add fields
-       ALGO and FLAGS.  Set these fields in all digest modules.
-       * cipher/md.c: Change most code to replace the former module
-       system by a simpler system to gain information about the algorithms.
-
-2013-10-01  Werner Koch  <wk@gnupg.org>
-
-       cipher: Simplify the cipher dispatcher cipher.c.
-       + commit 3ca180b25e8df252fc16f802cfdc27496e307830
-       * src/gcrypt-module.h (gcry_cipher_spec_t):  Move to ...
-       * src/cipher-proto.h (gcry_cipher_spec_t): here.  Merge with
-       cipher_extra_spec_t.  Add fields ALGO and FLAGS.  Set these fields in
-       all cipher modules.
-       * cipher/cipher.c: Change most code to replace the former module
-       system by a simpler system to gain information about the algorithms.
-       (disable_pubkey_algo): Simplified.  Not anymore thread-safe, though.
-
-       * cipher/md.c (_gcry_md_selftest): Use correct structure.  Not a real
-       problem because both define the same function as their first field.
-
-       * cipher/pubkey.c (_gcry_pk_selftest): Take care of the disabled flag.
-
-       mpi: Fix gcry_mpi_neg.
-       + commit 4153fa859816e799e506055321a22e6450aacdcc
-       * mpi/mpiutil.c (_gcry_mpi_neg): Copy U to W.
-
-2013-10-01  Peter Wu  <lekensteyn@gmail.com>
-
-       cipher: Add support for 128-bit keys in RC2.
-       + commit 738177ec0eae05069ec61bc4f724a69d4e052e42
-       * cipher/rfc2268.c (oids_rfc2268_128): New
-       (_gcry_cipher_spec_rfc2268_128): New.
-       * cipher/cipher.c (cipher_table_entry): Add GCRY_CIPHER_RFC2268_128.
-
-2013-09-30  Werner Koch  <wk@gnupg.org>
-
-       ecc: Use faster b parameter for Ed25519.
-       + commit 1d85452412b65e7976bc94969fc513ff6b880ed8
-       * cipher/ecc-curves.c (domain_parms): Replace b.
-       * tests/t-mpi-point.c (test_curve): Ditto.
-
-       ecc: Prepare for future Ed25519 optimization.
-       + commit a2618c822e666d4121cba29bee3fd50bf70c9743
-       * mpi/ec-ed25519.c: New but empty file.
-       * mpi/ec-internal.h: New.
-       * mpi/ec.c: Include ec-internal.h.
-       (ec_mod): New.
-       (ec_addm): Use ec_mod.
-       (ec_mulm): Remove commented code.  Use ec_mod.
-       (ec_subm): Call simple sub.
-       (ec_pow2): Use ec_mulm.
-       (ec_mul2): New.
-       (dup_point_weierstrass): Use ec_mul2.
-       (dup_point_twistededwards): Add special case for a == -1.  Use
-       ec_mul2.
-       (add_points_weierstrass): Use ec_mul2.
-       (add_points_twistededwards): Add special case for a == -1.
-       (_gcry_mpi_ec_curve_point): Ditto.
-       (ec_p_init): Add hack to test Barrett functions.
-       * src/ec-context.h (mpi_ec_ctx_s): Add P_BARRETT.
-
-       * mpi/mpi-mod.c (_gcry_mpi_mod_barrett): Fix sign problem.
-
-       ecc: Fix recomputing of Q for Ed25519.
-       + commit c325adb8f5092b80a626bd3bb5e49cf7f3a29fc8
-       * cipher/ecc-misc.c (reverse_buffer): New.
-       (_gcry_ecc_compute_public): Add ED255519 specific code.
-       * cipher/ecc.c (sign_eddsa): Allocate DIGEST in secure memory.  Get
-       rid of HASH_D.
-       * tests/t-mpi-point.c (context_param): Test recomputing of Q for
-       Ed25519.
-
-       log: Try to print s-expressions in a more compact format.
-       + commit d69a13d3d1c14ad6a6aa7cd349d6d2dfb152d422
-       * src/misc.c (count_closing_parens): New.
-       (_gcry_log_printsxp): Use new function.
-       * mpi/ec.c (_gcry_mpi_point_log): Take care of a NULL point.
-
-2013-09-30  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Make Whirlpool use the _gcry_md_block_write helper.
-       + commit 68cefd0f1d60ac33b58031df9b1d165cb1bf0f14
-       * cipher/whirlpool.c (whirlpool_context_t): Add 'bctx', remove
-       'buffer', 'count' and 'nblocks'.
-       (whirlpool_init): Initialize 'bctx'.
-       (whirlpool_transform): Adjust context argument type and burn stack
-       depth.
-       (whirlpool_add): Remove.
-       (whirlpool_write): Use _gcry_md_block_write.
-       (whirlpool_final, whirlpool_read): Adjust for 'bctx' usage.
-
-       whirlpool: add stack burning after transform.
-       + commit a96d622e1a36d40d1504b7ada567e90ec9957443
-       * cipher/whirlpool.c (whirlpool_transform): Return burn stack depth.
-       (whirlpool_add): Do burn_stack.
-
-       whirlpool: do bitcount calculation in finalization part.
-       + commit 10d7351411f19bb2c03d2e24ca5a38dabe45023b
-       * cipher/whirlpool.c (whirlpool_context_t): Remove 'length', add
-       'nblocks'.
-       (whirlpool_add): Update 'nblocks' instead of 'length', and add early
-       return at one spot.
-       (whirlpool_write): Check for 'nblocks' overflow.
-       (whirlpool_final): Convert 'nblocks' to bit-counter, and use
-       whirlpool_write instead of whirlpool_add.
-
-2013-09-30  Werner Koch  <wk@gnupg.org>
-
-       Add logging functions to the API.
-       + commit d2076f27bb7c5d505abf25fc622d21794c4a5df3
-       * src/gcrypt.h.in (_GCRY_GCC_ATTR_PRINTF): New.
-       (gcry_log_debug, gcry_log_debughex, gcry_log_debugmpi): New.
-       (gcry_log_debugpnt, gcry_log_debugsxp): New.
-       * src/visibility.c (gcry_log_debug): New.
-       (gcry_log_debughex, gcry_log_debugmpi, gcry_log_debugpnt): New.
-       (gcry_log_debugsxp): New.
-       * src/libgcrypt.def, src/libgcrypt.vers: Add new functions.
-       * src/misc.c (_gcry_logv): Make public.
-       (_gcry_log_printsxp): New.
-       * src/g10lib.h (log_printsxp): New macro.
-
-2013-09-26  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Make libgcrypt build with Clang on i386.
-       + commit db60d828137c4f3682ca4ca2a54fe3d96d3db5f9
-       * cipher/longlong.h [__i386__] (add_ssaaaa, sub_ddmmss)
-       (umul_ppmm, udiv_qrnnd): Do not cast asm output to USItype.
-
-2013-09-25  Werner Koch  <wk@gnupg.org>
-
-       mpi: Change not yet used _gcry_mpi_set_opaque_copy.
-       + commit 1c6660debdbf1e4c3e80074c846a3e3097f214bb
-       * mpi/mpiutil.c (_gcry_mpi_set_opaque_copy): Change prototype.
-       (_gcry_mpi_get_opaque_copy): Take care of gcry_malloc failure.
-
-       sexp: Improve printing of data with a leading zero.
-       + commit 9b7c49971588edf6acfc74bfb797eb79d19cb350
-       * src/sexp.c (suitable_encoding): Detect leading zero byte.
-
-       ecc: Allow the name "q@eddsa" to get/set the public key.
-       + commit d6683d2a6065986a9198d2d2eaa02c005b68cea4
-       * cipher/ecc-curves.c (_gcry_ecc_get_mpi): Support "q@eddsa".
-       (_gcry_ecc_set_mpi): Support "q".
-       * cipher/ecc.c (eddsa_encodepoint): Rename to ...
-       (_gcry_ecc_eddsa_encodepoint): this and make global.  Remove arg
-       MINLEN and take from context.
-       (eddsa_decodepoint): Rename to
-       (_gcry_ecc_eddsa_decodepoint): this and make global. Remove arg LEN
-       and take from context.
-       (sign_eddsa, verify_eddsa): Take B from context.
-       (ecc_sign, ecc_verify): Add hack to set DIALECT.
-       (_gcry_pk_ecc_get_sexp): Use _gcry_ecc_compute_public.  Handle EdDSA.
-       * src/ec-context.h (mpi_ec_ctx_s): Add field NBITS.
-       * mpi/ec.c (ec_p_init): Init NBITS.
-       * tests/t-mpi-point.c (test_curve): Add Ed25519.
-       (sample_ed25519_q): New.
-       (context_param): Check new sample key.
-       (hex2buffer, hex2mpiopa): New.
-       (cmp_mpihex): Take care of opaque MPIs.
-
-       mpicalc: Add statement to compute the number of bits.
-       + commit 9a4447ccd1b90bcd701941e80a7f484a1825fcea
-       * src/mpicalc.c (do_nbits): New.
-       (main): Add statement 'b'.
-
-       ecc: Refactor low-level access functions.
-       + commit 64a7d347847d606eb5f4c156e24ba060271b8f6b
-       * mpi/ec.c (point_copy): Move to cipher/ecc-curves.c.
-       (ec_get_reset): Rename to _gcry_mpi_ec_get_reset and make global.
-       (_gcry_mpi_ec_get_mpi): Factor most code out to _gcry_ecc_get_mpi.
-       (_gcry_mpi_ec_get_point): Factor most code out to _gcry_ecc_get_point.
-       (_gcry_mpi_ec_set_mpi): Factor most code out to _gcry_ecc_set_mpi.
-       (_gcry_mpi_ec_set_point): Factor most code out to _gcry_ecc_set_point.
-       * cipher/ecc-curves.c (_gcry_ecc_get_mpi): New.
-       (_gcry_ecc_get_point, _gcry_ecc_set_mpi, _gcry_ecc_set_point): New.
-       * cipher/ecc-misc.c (_gcry_ecc_compute_public): New.
-
-       ecc: Fix highly unlikely endless loop in sign_ecdsa.
-       + commit 1f5f4452e5bca105ec2197a4facbf9778e7dc31e
-       * cipher/ecc.c (sign_ecdsa): Turn while-do into do-while loops.
-
-2013-09-24  Werner Koch  <wk@gnupg.org>
-
-       ecc: Allow the use of an uncompressed public key.
-       + commit df013c9820709421ef9550158ac5df0060d73379
-       * cipher/ecc.c (eddsa_encodepoint): Factor most code out to ...
-       (eddsa_encode_x_y): new fucntion.
-       (eddsa_decodepoint): Allow use of an uncompressed public key.
-       * tests/t-ed25519.c (N_TESTS): Adjust.
-       * tests/t-ed25519.inp: Add test 1025.
-
-2013-09-23  Werner Koch  <wk@gnupg.org>
-
-       pk: Add algo id GCRY_PK_ECC and deprecate ECDSA and ECDH.
-       + commit d5f91466695c5736f441c9bf1998436184a4bf61
-       * src/gcrypt.h.in (GCRY_PK_ECC): New.
-       * cipher/pubkey.c (map_algo): New.
-       (spec_from_algo, gcry_pk_get_param, _gcry_pk_selftest): Use it.
-       * cipher/ecc.c (selftests_ecdsa): Report using GCRY_PK_ECC.
-       (run_selftests): Simplify.
-       (ecdh_names, ecdsa_names): Merge into a new ecc_names.
-       (_gcry_pubkey_spec_ecdh, _gcry_pubkey_spec_ecdsa): Merge into new
-       _gcry_pubkey_spec_ecc.
-
-       ec: Use mpi_mulm instead of mpi_powm.
-       + commit 4552437bb3c5ff96a889fd31e4bc504b2a12fac7
-       * mpi/ec.c (ec_pow2): New.
-       (ec_powm): Remove call to mpi_abs.
-       (dup_point_weierstrass, dup_point_twistededwards)
-       (add_points_weierstrass, add_points_twistededwards)
-       (_gcry_mpi_ec_curve_point): Use ec_pow2.
-
-2013-09-21  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       bufhelp: enable fast unaligned memory accesses on powerpc.
-       + commit 925d4fb3e8f2df3c5566ec6b5df7620a3d3504e5
-       * cipher/bufhelp.h [__powerpc__] (BUFHELP_FAST_UNALIGNED_ACCESS): Set
-       macro enabled.
-       [__powerpc64__] (BUFHELP_FAST_UNALIGNED_ACCESS): Ditto.
-
-       Remove i386 inline assembly version of rotation functions.
-       + commit cfea5c28a3822e1e7e401e5107ebe07ba7fdcf37
-       * cipher/bithelp.h (rol, ror): Remove i386 version, change
-       macros to inline functions.
-       * src/hmac256.c (ror): Ditto.
-
-       Optimize and cleanup 32-bit and 64-bit endianess transforms.
-       + commit 9337e03824a5bdd3bbbcb8382cabefe6d6c32e1e
-       * cipher/bithelp.h (bswap32, bswap64, le_bswap32, be_bswap32)
-       (le_bswap64, be_bswap64): New.
-       * cipher/bufhelp.h (buf_get_be32, buf_get_le32, buf_put_le32)
-       (buf_put_be32, buf_get_be64, buf_get_le64, buf_put_be64)
-       (buf_put_le64): New.
-       * cipher/blowfish.c (do_encrypt_block, do_decrypt_block): Use new
-       endian conversion helpers.
-       (do_bf_setkey): Turn endian specific code to generic.
-       * cipher/camellia.c (GETU32, PUTU32): Use new endian conversion
-       helpers.
-       * cipher/cast5.c (rol): Remove, use rol from bithelp.
-       (F1, F2, F3): Fix to use rol from bithelp.
-       (do_encrypt_block, do_decrypt_block, do_cast_setkey): Use new endian
-       conversion helpers.
-       * cipher/des.c (READ_64BIT_DATA, WRITE_64BIT_DATA): Ditto.
-       * cipher/md4.c (transform, md4_final): Ditto.
-       * cipher/md5.c (transform, md5_final): Ditto.
-       * cipher/rmd160.c (transform, rmd160_final): Ditto.
-       * cipher/salsa20.c (LE_SWAP32, LE_READ_UINT32): Ditto.
-       * cipher/scrypt.c (READ_UINT64, LE_READ_UINT64, LE_SWAP32): Ditto.
-       * cipher/seed.c (GETU32, PUTU32): Ditto.
-       * cipher/serpent.c (byte_swap_32): Remove.
-       (serpent_key_prepare, serpent_encrypt_internal)
-       (serpent_decrypt_internal): Use new endian conversion helpers.
-       * cipher/sha1.c (transform, sha1_final): Ditto.
-       * cipher/sha256.c (transform, sha256_final): Ditto.
-       * cipher/sha512.c (__transform, sha512_final): Ditto.
-       * cipher/stribog.c (transform, stribog_final): Ditto.
-       * cipher/tiger.c (transform, tiger_final): Ditto.
-       * cipher/twofish.c (INPACK, OUTUNPACK): Ditto.
-       * cipher/whirlpool.c (buffer_to_block, block_to_buffer): Ditto.
-       * configure.ac (gcry_cv_have_builtin_bswap32): Check for compiler
-       provided __builtin_bswap32.
-       (gcry_cv_have_builtin_bswap64): Check for compiler provided
-       __builtin_bswap64.
-
-       gostr3411_94: set better burn stack depth estimate.
-       + commit 7409de7bc28ff8847c9d71d8c3e35e1968d59d60
-       * cipher/gost28147.c (_gcry_gost_enc_one): Account function stack to
-       burn stack depth.
-       * cipher/gostr3411-94.c (max): New macro.
-       (do_hash_step, transform): Return stack burn depth.
-
-       Use hash transform function return type for passing burn stack depth.
-       + commit 592c2ab3deeeccbb6d3b078ed7bf0e6627c8e1fb
-       * cipher/gostr4311-94.c (transform): Return stack burn depth.
-       * cipher/hash-common.c (_gcry_md_block_write): Use stack burn depth
-       returned by 'hd->bwrite'.
-       * cipher/hash-common.h (_gcry_md_block_write_t): Change return type to
-       'unsigned int'.
-       (gry_md_block_ctx_t): Remove 'stack_burn'.
-       * cipher/md4.c (transform): Return stack burn depth.
-       (md4_final): Use stack burn depth from transform.
-       * cipher/md5.c (transform): Return stack burn depth.
-       (md5_final): Use stack burn depth from transform.
-       * cipher/rmd160.c (transform): Return stack burn depth.
-       (rmd160_final): Use stack burn depth from transform.
-       * cipher/sha1.c (transform): Return stack burn depth.
-       (sha1_final): Use stack burn depth from transform.
-       * cipher/sha256.c (transform): Return stack burn depth.
-       (sha256_final): Use stack burn depth from transform.
-       * cipher/sha512.c (__transform, transform): Return stack burn depth.
-       (sha512_final): Use stack burn depth from transform.
-       * cipher/stribog.c (transform64): Return stack burn depth.
-       * cipher/tiger.c (transform): Return stack burn depth.
-       (tiger_final): Use stack burn depth from transform.
-
-       Make STRIBOG use the new _gcry_md_block_write helper.
-       + commit 902ea6052c11108bd19333c31b03e084bed1fb86
-       * cipher/stribog.c (STRIBOG_STRUCT): Add 'bctx' and remove 'buf' and
-       'count'.
-       (stribog_init_512): Initialize 'bctx'.
-       (transform64): New function.
-       (stribog_write): Remove.
-       (stribog_final): Use _gcry_md_block_write and bctx.
-       (_gcry_digest_spec_stribog_256, _gcry_digest_spec_stribog_512): Use
-       _gcry_md_block_write.
-
-       Make SHA-512 use the new _gcry_md_block_write helper.
-       + commit cce7449efe471b076c5a97929ac8907162011394
-       * cipher/hash-common.c (_gcry_md_block_write): Check that hd->buf is
-       large enough.
-       * cipher/hash-common.h (MD_BLOCK_MAX_BLOCKSIZE, MD_NBLOCKS_TYPE): New
-       macros.
-       (gcry_md_block_ctx_t): Use above macros for 'nblocks' and 'buf'.
-       * cipher/sha512.c (SHA512_STATE): New struct.
-       (SHA512_CONTEXT): Add 'bctx' and 'state'.
-       (sha512_init, sha384_init): Initialize 'bctx'.
-       (__transform, _gcry_sha512_transform_armv7_neon): Use SHA512_STATE for
-       'hd'.
-       (transform): For now, do not return burn stack.
-       (sha512_write): Remove.
-       (sha512_final): Use _gcry_md_block_write and bctx.
-       (_gcry_digest_spec_sha512, _gcry_digest_spec_sha384): Use
-       _gcry_md_block_write.
-
-2013-09-20  Werner Koch  <wk@gnupg.org>
-
-       sexp: Change internal versions to always use gpg_err_code_t.
-       + commit 3e5cfa20acfeccb9df2c3fae2730344b40b36104
-       * src/sexp.c (gcry_sexp_new, gcry_sexp_create, gcry_sexp_build)
-       (gcry_sexp_build_array, gcry_sexp_canon_len): Change error return type
-       from gpg_error_t to gpg_err_code_t.  Remove all calls to gpg_error.
-       * src/visibility.c (gcry_sexp_new, gcry_sexp_create, gcry_sexp_sscan)
-       (gcry_sexp_build, gcry_sexp_build_array, gcry_sexp_canon_len): Map
-       error codes via gpg_error.
-       * cipher/dsa.c, cipher/ecc.c, cipher/elgamal.c, cipher/rsa.c: Remove
-       use gpg_err_code wrappers.
-
-       pk: Move s-exp creation for gcry_pk_decrypt to the modules.
-       + commit 722bfc1e5f2268453db62f38cc46b5ec6ef3adee
-       * cipher/pubkey.c (sexp_to_enc): Remove RET_MODERN arg and merge it
-       into FLAGS.
-       (gcry_pk_decrypt): Move result s-exp building into the modules.
-       * src/cipher-proto.h (gcry_pk_decrypt_t): Add some args.
-       * cipher/ecc.c (ecc_decrypt_raw): Change to return an s-exp.
-       * cipher/elgamal.c (elg_decrypt): Ditto.
-       * cipher/rsa.c (rsa_decrypt): Ditto.
-       (rsa_blind, rsa_unblind): Merge into rsa_decrypt.  This saves several
-       extra MPI allocations.
-
-       pk: Remove unused function.
-       + commit 64cd7ab93da7c95cc8aa320c61c6e29f9e2399c4
-       * cipher/pubkey.c (_gcry_pk_aliased_algo_name): Remove
-
-2013-09-19  Werner Koch  <wk@gnupg.org>
-
-       Beautify debug output of the prime generator.
-       + commit 6576f0a7684292cb5691bfcabad0acca4c06c014
-       * cipher/primegen.c: Adjust output of log_mpidump to recently changed
-       log_mpidump code changes.
-
-       pk: Move s-expr creation for genkey to the modules.
-       + commit 1bf08850bf9343146c938bc03917417e16393e9a
-       * cipher/pubkey.c (pubkey_generate): Fold into gcry_pk_genkey
-       (gcry_pk_genkey): Move result s-exp creation into the modules.
-       * cipher/dsa.c (dsa_generate): Create result as s-exp.
-       * cipher/elgamal.c (elg_generate): Ditto.
-       * cipher/rsa.c (rsa_generate): Ditto.
-       * cipher/ecc.c (ecc_generate): Ditto.
-       * src/cipher-proto.h (pk_ext_generate_t): Remove type
-       (gcry_pk_spec): and remove from struct.
-
-       tests: Beautify some diagnostics.
-       + commit 2fe084873333c4d67bcfba0b527d63cd3cff6c47
-       * tests/benchmark.c (ecc_bench): Print the key sexp in very verbose
-       mode.
-       (main): Add option --pk-count.
-       * tests/keygen.c: Add Elgamal generation and improved diagnostics.
-       * tests/t-ed25519.c (check_ed25519): Print running number of tests
-       done.
-
-       sexp: Improve printing data representing a negative number.
-       + commit b3f3d47d347c14ed41d755cee580f000309b9c03
-       * src/sexp.c (suitable_encoding): Detect a negative number.
-
-       pk: Move RSA encoding functions to a new file.
-       + commit 071f70b9a766187fc70f6abc6a69d50752449285
-       * cipher/rsa-common: New.
-       * cipher/pubkey.c (pkcs1_encode_for_encryption): Move to rsa-common.c
-       and rename to _gcry_rsa_pkcs1_encode_for_enc.
-       (pkcs1_decode_for_encryption): Move to rsa-common.c and rename to
-       _gcry_rsa_pkcs1_decode_for_enc.
-       (pkcs1_encode_for_signature): Move to rsa-common.c and rename to
-       _gcry_rsa_pkcs1_encode_for_sig.
-       (oaep_encode): Move to rsa-common.c and rename to
-       _gcry_rsa_oaep_encode.
-       (oaep_decode): Move to rsa-common.c and rename to
-       _gcry_rsa_oaep_decode.
-       (pss_encode): Move to rsa-common.c and rename to _gcry_rsa_pss_encode.
-       (pss_verify): Move to rsa-common.c and rename to _gcry_rsa_pss_decode.
-       (octet_string_from_mpi, mgf1): Move to rsa-common.c.
-
-       pk: Move s-expr creation for sign and encrypt to the modules.
-       + commit eca9e2e50ddd4c9020fe1d4a9a3c77d20ebb90f6
-       * cipher/pubkey.c (pubkey_encrypt): Fold into gcry_pk_encrypt.
-       (pubkey_decrypt): Fold into gcry_pk_decrypt.
-       (pubkey_sign): Fold into gcry_pk_sign.
-       (pubkey_verify): Fold into gcry_pk_verify.
-       (octet_string_from_mpi): Make it a wrapper and factor code out to ...
-       * mpi/mpicoder.c (_gcry_mpi_to_octet_string): New function.
-
-       * src/cipher.h (PUBKEY_FLAG_FIXEDLEN): New.
-       * cipher/pubkey.c (sexp_data_to_mpi): Set flag for some encodings.
-       (gcry_pk_encrypt): Simply by moving the s-expr generation to the modules.
-       (gcry_pk_sign): Ditto.
-       * cipher/dsa.c (dsa_sign): Create s-expr.
-       * cipher/elgamal.c (elg_encrypt, elg_sign): Ditto.
-       * cipher/rsa.c (rsa_encrypt, rsa_sign): Ditto.
-       * cipher/ecc.c (ecc_sign, ecc_encrypt_raw): Ditto.
-       (ecdsa_names): Add "eddsa".
-       * tests/t-ed25519.c (one_test): Expect "eddsa" token.
-
-2013-09-19  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Fix Stribog digest on bigendian platforms.
-       + commit d399faf5db71d429bfd6fa4a9cfc82e2a55055f0
-       * cipher/stribog.c (stribog_final): swap bytes in the result of digest
-       calculations.
-
-2013-09-18  Werner Koch  <wk@gnupg.org>
-
-       pk: Simplify the public key dispatcher pubkey.c.
-       + commit 85722afb379f7a392a8117b895de273fd88c4ebc
-       * src/cipher-proto.h (gcry_pk_spec_t): Add fields ALGO and FLAGS.
-       * cipher/dsa.c (_gcry_pubkey_spec_dsa): Set these fields.
-       * cipher/ecc.c (_gcry_pubkey_spec_ecdsa): Ditto.
-       (_gcry_pubkey_spec_ecdh): Ditto.
-       * cipher/rsa.c (_gcry_pubkey_spec_rsa): Ditto.
-       * cipher/elgamal.c (_gcry_pubkey_spec_elg): Ditto
-       (_gcry_pubkey_spec_elg_e): New.
-       * cipher/pubkey.c: Change most code to replace the former module
-       system by a simpler system to gain information about the algorithms.
-       (disable_pubkey_algo): SImplified.  Not anymore thread-safe, though.
-
-       pk: Merge extraspecs struct with standard specs struct.
-       + commit 89103ce00e862cc709e80fa41f2ee13d54093ec5
-       * src/gcrypt-module.h (gcry_pk_spec_t): Move this typedef and the
-       corresponding function typedefs to ...
-       * src/cipher-proto.h: here.
-       (pk_extra_spec_t): Remove typedef and merge fields into
-       gcry_pk_spec_t.
-       * cipher/rsa.c, cipher/dsa.c, cipher/elg.c, cipher/ecc.c: Ditto.
-       * cipher/pubkey.c: Change accordingly.
-       * src/cipher.h (_gcry_pubkey_extraspec_rsa): Remove.
-       (_gcry_pubkey_extraspec_dsa): Remove.
-       (_gcry_pubkey_extraspec_elg): Remove.
-       (_gcry_pubkey_extraspec_ecdsa): Remove.
-
-2013-09-18  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix encryption/decryption return type for GOST28147.
-       + commit 2ad7ea9cb388fd31e4b0852b68d77f599ef4adce
-       * cipher/gost.h (_gcry_gost_enc_one): Change return type to
-       'unsigned int'.
-       * cipher/gost28147.c (max): New macro.
-       (gost_encrypt_block, gost_decrypt_block): Return burn stack depth.
-       (_gcry_gost_enc_one): Return burn stack depth from gost_encrypt_block.
-
-2013-09-18  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       doc: fix building of ps and pdf documentation.
-       + commit bd33fa21c9afc6c81e0da24016fc13001e9c7390
-       * doc/gcrypt.texi, doc/gpl.texi, doc/lgpl.texi: fix texinfo errors.
-
-       Add GOST R 34.11-2012 implementation (Stribog)
-       + commit c22064bdd773a807801e300aa9214b2fdcafcf20
-       * src/gcrypt.h.in (GCRY_MD_GOSTR3411_12_256)
-       (GCRY_MD_GOSTR3411_12_512): New.
-       * cipher/stribog.c: New.
-       * configure.ac (available_digests_64): Add stribog.
-       * src/cipher.h: Declare Stribog declarations.
-       * cipher/md.c: Register Stribog digest.
-       * tests/basic.c (check_digests) Add 4 testcases for Stribog from
-       standard.
-       * doc/gcrypt.texi: Document new constants.
-
-       Add basic implementation of GOST R 34.11-94 message digest.
-       + commit b0579baaa04fb91eabbbdc295bcabea04cf84056
-       * src/gcrypt.h.in (GCRY_MD_GOSTR3411_94): New.
-       * cipher/gostr3411-94.c: New.
-       * configure.ac (available_digests): Add gostr3411-94.
-       * src/cipher.h: Add gostr3411-94 definitions.
-       * cipher/md.c: Register GOST R 34.11-94.
-       * tests/basic.c (check_digests): Add 4 tests for GOST R 34.11-94
-         hash algo. Two are  defined in the standard itself, two other are
-         more or less common tests - an empty string an exclamation mark.
-       * doc/gcrypt.texi: Add an entry describing GOST R 34.11-94 to the MD
-         algorithms table.
-
-       Separate common md block code.
-       + commit ecde77ad98690540abb21db08e5531297ed72bd0
-       * cipher/hash-common.c (_gcry_md_block_write): New function to handle
-       block md operations.  The current implementation is limited to 64 byte
-       buffer and u32 block counter.
-
-       * cipher/md4.c, cipher/md5.c, cipher/rmd.h, cipher/rmd160.c
-       *cipher/sha1.c, cipher/sha256.c, cipher/tiger.c: Convert to use
-       _gcry_md_block_write.
-
-       Add limited implementation of GOST 28147-89 cipher.
-       + commit 56b5949f71f501744998f5ebc12488ebf6f1c0b5
-       * src/gcrypt.h.in (GCRY_CIPHER_GOST28147): New.
-       * cipher/gost.h, cipher/gost28147.c: New.
-       * configure.ac (available_ciphers): Add gost28147.
-       * src/cipher.h: Add gost28147 definitions.
-       * cipher/cipher.c: Register gost28147.
-       * tests/basic.c (check_ciphers): Enable simple test for gost28147.
-       * doc/gcrypt.texi: document GCRY_CIPHER_GOST28147.
-
-2013-09-18  Werner Koch  <wk@gnupg.org>
-
-       ecc: Add Ed25519 key generation and prepare for optimizations.
-       + commit 63cd3474425cb5a7ec4d1a56be15b248ecda4680
-       * src/mpi.h (enum ecc_dialects): New.
-       * src/ec-context.h (mpi_ec_ctx_s): Add field DIALECT.
-       * cipher/ecc-common.h (elliptic_curve_t): Ditto.
-       * cipher/ecc-curves.c (ecc_domain_parms_t): Ditto.
-       (domain_parms): Add dialect values.
-       (_gcry_ecc_fill_in_curve): Set dialect.
-       (_gcry_ecc_get_curve): Ditto.
-       (_gcry_mpi_ec_new): Ditto.
-       (_gcry_ecc_get_param): Use ECC_DIALECT_STANDARD for now.
-       * cipher/ecc-misc.c (_gcry_ecc_curve_copy): Copy dialect.
-       (_gcry_ecc_dialect2str): New.
-       * mpi/ec.c (ec_p_init): Add arg DIALECT.
-       (_gcry_mpi_ec_p_internal_new): Ditto.
-       (_gcry_mpi_ec_p_new): Ditto.
-
-       * mpi/mpiutil.c (gcry_mpi_set_opaque): Set the secure flag.
-       (_gcry_mpi_set_opaque_copy): New.
-
-       * cipher/ecc-misc.c (_gcry_ecc_os2ec): Take care of an opaque MPI.
-       * cipher/ecc.c (eddsa_generate_key): New.
-       (generate_key): Rename to nist_generate_key and factor some code out
-       to ...
-       (ecc_generate_ext): here.  Divert to eddsa_generate_key if desired.
-       (eddsa_decodepoint): Take care of an opaque MPI.
-       (ecc_check_secret_key): Ditto.
-       (ecc_sign): Ditto.
-       * cipher/pubkey.c (sexp_elements_extract_ecc): Store public and secret
-       key as opaque MPIs.
-       (gcry_pk_genkey): Add the curve_name also to the private key part of
-       the result.
-
-       * tests/benchmark.c (ecc_bench): Support Ed25519.
-       (main): Add option --debug.
-       * tests/curves.c (sample_key_2): Make sure that P and N are positive.
-       * tests/keygen.c (show): New.
-       (check_ecc_keys): Support Ed25519.
-
-2013-09-17  Werner Koch  <wk@gnupg.org>
-
-       mpi: Support printing of negative numbers.
-       + commit 89fe2173649a72019d75e059e6c6938efd10421f
-       * mpi/mpicoder.c (twocompl, onecompl): New.
-       (gcry_mpi_print): Use it for STD and SSH.
-       (gcry_mpi_scan): Use it for STD and SSH.  Always set NSCANNED.
-       (gcry_mpi_aprint): Clear the extra allocated byte.
-       * tests/t-convert.c (showhex, showmpi): New.
-       (mpi2bitstr_nlz): New.
-       (check_formats): New.
-       (main): Call new test.
-
-2013-09-16  Werner Koch  <wk@gnupg.org>
-
-       Fix bug in _gcry_mpi_tdiv_q_2exp.
-       + commit a7a9cdcaaf3979baa18dad51e722882581349f45
-       * mpi/mpi-internal.h (MPN_COPY_INCR): Make it work.
-
-       ecc: Implement Curve Ed25519 signing and verification.
-       + commit bc5199a02abe428ad377443280b3eda60141a1d6
-       * cipher/ecc-curves.c (domain_parms): Add curve "Ed25519".
-       * cipher/ecc.c (reverse_buffer): New.
-       (eddsa_encodempi): New.
-       (eddsa_encodepoint): New.
-       (eddsa_decodepoint): New.
-       (sign_eddsa): Implement.
-       (verify_eddsa): Implement.
-       (ecc_sign): Init unused Q.  Pass public key to sign_eddsa.
-       (ecc_verify): Init pk.Q if not used.  Pass public key verbatim to
-       verify_eddsa.
-       * cipher/pubkey.c (sexp_elements_extract): Add arg OPAQUE.  Change all
-       callers to pass 0.
-       (sexp_to_sig): Add arg OPAQUE and pass it to sexp_elements_extract.
-       (sexp_data_to_mpi): Allow for a zero length "value".
-       (gcry_pk_verify): Reorder parameter processing.  Pass OPAQUE flag as
-       required.
-       * mpi/ec.c (ec_invm): Print a warning if the inverse does not exist.
-       (_gcry_mpi_ec_get_affine): Implement for our Twisted Edwards curve
-       model.
-       (dup_point_twistededwards): Implement.
-       (add_points_twistededwards): Implement.
-       (_gcry_mpi_ec_mul_point): Support Twisted Edwards.
-
-       * mpi/mpicoder.c (do_get_buffer): Add arg FILL_LE.
-       (_gcry_mpi_get_buffer): Ditto.  Change all callers.
-       (_gcry_mpi_get_secure_buffer): Ditto.
-
-       * src/sexp.c (_gcry_sexp_nth_opaque_mpi): New.
-
-       * tests/t-ed25519.c: New.
-       * tests/t-ed25519.inp: New.
-       * tests/t-mpi-point.c (basic_ec_math_simplified): Print some output
-       only in debug mode.
-       (twistededwards_math): New test.
-       (main): Call new test.
-
-       mpi: Add internal convenience function.
-       + commit 44a2c34e90ed7de149952398787906d8823b636b
-       * mpi/mpiutil.c (_gcry_mpi_get_opaque_copy): New.
-
-       mpi: Add debug function to print a point.
-       + commit 8ebc94d11a1eb93f2365c93f555e958700fdfbd4
-       * mpi/ec.c (_gcry_mpi_point_log): New.
-       * src/mpi.h (log_printpnt): new macro.
-
-       tests: Factor time measurement code out.
-       + commit 58eaf0c4332ac2f645ede28c4d18337389dfa753
-       * tests/benchmark.c (started_at, stopped_at, start_timer, stop_timer)
-       (elapsed time): Factor out to ..
-       * tests/stopwatch.h: new file.
-
-2013-09-12  Werner Koch  <wk@gnupg.org>
-
-       Fix _gcry_log_printmpi to print 00 instead of a sole sign.
-       + commit 1c76349c69c70a62b516a4f837c6287def640807
-       * src/misc.c: Special case an mpi length of 0.
-
-2013-09-11  Werner Koch  <wk@gnupg.org>
-
-       Streamline the use of the internal mpi and hex debug functions.
-       + commit e35ed615acc624a8b6c07576ea0650aac2bdb0db
-       * mpi/mpicoder.c (gcry_mpi_dump): Remove.
-       (_gcry_log_mpidump): Remove.
-       * src/misc.c (_gcry_log_printhex): Factor all code out to ...
-       (do_printhex): new.  Add line wrapping a and compact printing.
-       (_gcry_log_printmpi): New.
-       * src/mpi.h (log_mpidump): Remove macro.
-       * src/g10lib.h (log_mpidump): Add compatibility macro.
-       (log_printmpi): New macro
-       * src/visibility.c (gcry_mpi_dump): Call _gcry_log_printmpi.
-       * cipher/primegen.c (prime_generate_internal): Replace gcry_mpi_dump
-       by log_printmpi.
-       (gcry_prime_group_generator): Ditto.
-       * cipher/pubkey.c: Remove extra colons from log_mpidump call.
-       * cipher/rsa.c (stronger_key_check): Use log_printmpi.
-
-2013-09-10  Werner Koch  <wk@gnupg.org>
-
-       md: Add function gcry_md_hash_buffers.
-       + commit f3bca0c77c4979504f95fdbc618f7458e61e3e45
-       * src/gcrypt.h.in (gcry_buffer_t): new.
-       (gcry_md_hash_buffers): New.
-       * src/visibility.c, src/visibility.h: Add wrapper for new function.
-       * src/libgcrypt.def, src/libgcrypt.vers: Export new function.
-       * cipher/md.c (gcry_md_hash_buffers): New.
-       * cipher/sha1.c (_gcry_sha1_hash_buffers): New.
-       * tests/basic.c (check_one_md_multi): New.
-       (check_digests): Run that test.
-       * tests/hmac.c (check_hmac_multi): New.
-       (main): Run that test.
-
-       md: Fix Whirlpool flaw.
-       + commit 0a28b2d2c9181a536fc894e24626714832619923
-       * cipher/whirlpool.c (whirlpool_add): Remove shortcut return so that
-       byte counter is always properly updated.
-
-2013-09-07  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix static build on AMD64.
-       + commit 90fdf25f0dcc5feac7195ede55bd15948a11363e
-       * cipher/rijndael-amd64.S: Correct 'RIP' macro for non-PIC build.
-
-       scrypt: fix for big-endian systems.
-       + commit 38a038a135d82231eff9d84f1ae3c4a25c6a5e75
-       * cipher/scrypt.c (_salsa20_core): Fix endianess issues.
-
-2013-09-07  Werner Koch  <wk@gnupg.org>
-
-       Use gcc "unused" attribute only with gcc >= 3.5.
-       + commit f7135e299e659d78906aac3dfdf30f380b5cf9c6
-       * src/g10lib.h (GCC_ATTR_UNUSED): Fix gcc version detection.
-
-2013-09-07  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Add support for Salsa20/12 - 12 round version of Salsa20.
-       + commit ae6f6c47d2e0c536f3eab0823b5f23d26956cda2
-       * src/gcrypt.h.in (GCRY_CIPHER_SALSA20R12): New.
-       * src/salsa20.c (salsa20_core, salsa20_do_encrypt_stream): Add support
-       for reduced round versions.
-         (salsa20r12_encrypt_stream, _gcry_cipher_spec_salsa20r12): Implement
-       Salsa20/12 - a 12 round version of Salsa20 selected by eStream.
-       * src/cipher.h: Declsare Salsa20/12 definition.
-       * cipher/cipher.c: Register Salsa20/12
-       * tests/basic.c: (check_stream_cipher, check_stream_cipher_large_block):
-       Populate Salsa20/12 tests with test vectors from ecrypt
-       (check_ciphers): Add simple test for Salsa20/12
-
-2013-09-07  Werner Koch  <wk@gnupg.org>
-
-       Add configure option --disable-amd64-as-feature-detection.
-       + commit 49d5b9dcd622cdc87fb02a211bd51e3d46345bf2
-       * configure.ac: Implement new disable flag.
-
-       mpi: Improve support for non-Weierstrass support.
-       + commit 4d8c8c7aa88cddb1624301957e6245405f46d027
-       * mpi/ec.c (ec_p_init): Add args MODEL and P.  Change all callers.
-       (_gcry_mpi_ec_p_internal_new): Ditto.
-       (_gcry_mpi_ec_p_new): Ditto.
-       * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Return
-       GPG_ERR_UNKNOWN_CURVE instead of invalid value.  Init curve model.
-       * cipher/ecc.c (ecc_verify, ecc_encrypt_raw): Ditto.
-       * cipher/pubkey.c (sexp_data_to_mpi): Fix EDDSA flag error checking.
-
-       mpi: Add gcry_mpi_ec_curve_point.
-       + commit ddfefe429660cc5d798f3517208936449247ae5c
-       * mpi/ec.c (_gcry_mpi_ec_curve_point): New.
-       (ec_powm): Return the absolute value.
-       * src/visibility.c, src/visibility.c: Add wrappers.
-       * src/libgcrypt.def, src/libgcrypt.vers: Export them.
-
-       mpi: Add functions to manipulate the sign.
-       + commit 1bd2c67aa55b40589654d3fa5dea05cf1ed7dc5f
-       * src/gcrypt.h.in (gcry_mpi_is_neg): New.
-       (gcry_mpi_neg, gcry_mpi_abs): New.
-       * mpi/mpiutil.c (_gcry_mpi_is_neg): New.
-       (_gcry_mpi_neg, _gcry_mpi_abs): New.
-       * src/visibility.c, src/visibility.h: Add wrappers.
-       * src/libgcrypt.def, src/libgcrypt.vers: Export them.
-       * src/mpi.h (mpi_is_neg): New.  Rename old macro to mpi_has_sign.
-       * mpi/mpi-mod.c (_gcry_mpi_mod_barrett): Use mpi_has_sign.
-       * mpi/mpi-mpow.c (calc_barrett): Ditto.
-       * cipher/primegen.c (_gcry_derive_x931_prime): Ditto
-       * cipher/rsa.c (secret): Ditto.
-
-2013-09-06  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Tune armv6 mpi assembly.
-       + commit 4e4440153258e2f0dfdcaa8443820af06984ecb1
-       * mpi/armv6/mpih-mul1.S: Tune assembly for Cortex-A8.
-       * mpi/armv6/mpih-mul2.S: Ditto.
-       * mpi/armv6/mpih-mul3.S: Ditto.
-
-2013-09-05  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Change _gcry_burn_stack take burn depth as unsigned integer.
-       + commit e0ae31fcce3bd57b24751ff3c82cba820e493c3a
-       * src/misc.c (_gcry_burn_stack): Change to handle 'unsigned int' bytes.
-
-       mpicalc: fix building on linux and win32.
-       + commit 50ec983666f0ca9d50c84aa1afad0d7bd5810779
-       * src/Makefile.am (mpicalc): Adjust CFLAGS and LDADD.
-
-2013-09-04  Werner Koch  <wk@gnupg.org>
-
-       Change mpicalc to use Libgcrypt and install it.
-       + commit 1d23040b659661b4086c079cb9fd5f37189a7020
-       * src/mpicalc.c: Make use of gcry_ functions.
-       (MPICALC_VERSION): New.  Set to 2.0.
-       (strusage): Remove.
-       (scan_mpi): New.  Replaces mpi_fromstr.
-       (print_mpi): New.  Replaces mpi_print.
-       (my_getc): New.
-       (print_help): New.
-       (main): Use simple option parser and print version info.
-       * src/Makefile.am (bin_PROGRAMS): Add mpicalc.
-       (mpicalc_SOURCES, mpicalc_CFLAGS, mpicalc_LDADD): New.
-
-       Add mpicalc.c to help with testing.
-       + commit a70c46e29c480fa0f56ab4814666a5b115f84fd7
-       * src/mpicalc.c: Take from GnuPG 1.4
-
-       Prepare support for EdDSA.
-       + commit c47d4001033f68212d2847b3074a0bdda990342e
-       * src/cipher.h (PUBKEY_FLAG_EDDSA): New.
-       * cipher/pubkey.c (pubkey_verify): Repalce args CMP and OPAQUEV by
-       CTX.  Pass flags and hash algo to the verify function.  Change all
-       verify functions to accept these args.
-       (sexp_data_to_mpi): Implement new flag "eddsa".
-       (gcry_pk_verify): Pass CTX instead of the compare function to
-       pubkey_verify.
-       * cipher/ecc.c (sign): Rename to sign_ecdsa.  Change all callers.
-       (verify): Rename to verify_ecdsa.  Change all callers.
-       (sign_eddsa, verify_eddsa): New stub functions.
-       (ecc_sign): Divert to sign_ecdsa or sign_eddsa.
-       (ecc_verify): Divert to verify_ecdsa or verify_eddsa.
-
-       Prepare support for non-Weierstrass EC equations.
-       + commit c26be7a337d0bf98193bc58e043209e46d0769bb
-       * src/mpi.h (gcry_mpi_ec_models): New.
-       * src/ec-context.h (mpi_ec_ctx_s): Add MODEL.
-       * cipher/ecc-common.h (elliptic_curve_t): Ditto.
-       * cipher/ecc-curves.c (ecc_domain_parms_t): Ditto.
-       (domain_parms): Mark als as Weierstrass.
-       (_gcry_ecc_fill_in_curve): Check model.
-       (_gcry_ecc_get_curve): Set model to Weierstrass.
-       * cipher/ecc-misc.c (_gcry_ecc_model2str): New.
-       * cipher/ecc.c (generate_key, ecc_generate_ext): Print model in the
-       debug output.
-
-       * mpi/ec.c (_gcry_mpi_ec_dup_point): Switch depending on model.
-       Factor code out to ...
-       (dup_point_weierstrass): new.
-       (dup_point_montgomery, dup_point_twistededwards): New stub functions.
-       (_gcry_mpi_ec_add_points): Switch depending on model.  Factor code out
-       to ...
-       (add_points_weierstrass): new.
-       (add_points_montgomery, add_points_twistededwards): New stub
-       functions.
-
-       * tests/Makefile.am (TESTS): Reorder tests.
-
-       mpi: Suppress newer gcc warnings.
-       + commit 8698530b2f9ef95542f1dd550961de7af86cc256
-       * src/g10lib.h (GCC_ATTR_UNUSED): Define for gcc >= 3.5.
-       * mpi/mpih-div.c (_gcry_mpih_mod_1, _gcry_mpih_divmod_1): Mark dummy
-       as unused.
-       * mpi/mpi-internal.h (UDIV_QRNND_PREINV): Mark _ql as unused.
-
-       Do not check with cpp for typedefed constants.
-       + commit b28b1f732e1b4f9c62a9de87c22c6bb0d3f8fdb8
-       * src/gcrypt-int.h: Include error code replacements depeding on the
-       version of libgpg-error.
-
-2013-09-04  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Make _gcry_burn_stack use variable length array.
-       + commit 4b0edf53440239d3bcc95941980c062a0801a149
-       * configure.ac (HAVE_VLA): Add check.
-       * src/misc.c (_gcry_burn_stack) [HAVE_VLA]: Add VLA code.
-
-       Move stack burning from block ciphers to cipher modes.
-       + commit a3aaa6ad03388ea3eaa24304b604cb864633332f
-       * src/gcrypt-module.h (gcry_cipher_encrypt_t)
-       (gcry_cipher_decrypt_t): Return 'unsigned int'.
-       * cipher/cipher.c (dummy_encrypt_block, dummy_decrypt_block): Return
-       zero.
-       (do_ecb_encrypt, do_ecb_decrypt): Get largest stack burn depth from
-       block cipher crypt function and burn stack at end.
-       * cipher/cipher-aeswrap.c (_gcry_cipher_aeswrap_encrypt)
-       (_gcry_cipher_aeswrap_decrypt): Ditto.
-       * cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt)
-       (_gcry_cipher_cbc_decrypt): Ditto.
-       * cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt)
-       (_gcry_cipher_cfb_decrypt): Ditto.
-       * cipher/cipher-ctr.c (_gcry_cipher_cbc_encrypt): Ditto.
-       * cipher/cipher-ofb.c (_gcry_cipher_ofb_encrypt)
-       (_gcry_cipher_ofb_decrypt): Ditto.
-       * cipher/blowfish.c (encrypt_block, decrypt_block): Return burn stack
-       depth.
-       * cipher/camellia-glue.c (camellia_encrypt, camellia_decrypt): Ditto.
-       * cipher/cast5.c (encrypt_block, decrypt_block): Ditto.
-       * cipher/des.c (do_tripledes_encrypt, do_tripledes_decrypt)
-       (do_des_encrypt, do_des_decrypt): Ditto.
-       * cipher/idea.c (idea_encrypt, idea_decrypt): Ditto.
-       * cipher/rijndael.c (rijndael_encrypt, rijndael_decrypt): Ditto.
-       * cipher/seed.c (seed_encrypt, seed_decrypt): Ditto.
-       * cipher/serpent.c (serpent_encrypt, serpent_decrypt): Ditto.
-       * cipher/twofish.c (twofish_encrypt, twofish_decrypt): Ditto.
-       * cipher/rfc2268.c (encrypt_block, decrypt_block): New.
-       (_gcry_cipher_spec_rfc2268_40): Use encrypt_block and decrypt_block.
-
-2013-09-01  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       camellia-aesni-avx2-amd64: Move register clearing to assembly functions.
-       + commit f3515240de9513ead975985c9f8ab714022cac8e
-       * cipher/camellia-aesni-avx2-amd64.S
-       (_gcry_camellia_aesni_avx2_ctr_enc): Add 'vzeroall'.
-       (_gcry_camellia_aesni_avx2_cbc_dec)
-       (_gcry_camellia_aesni_avx2_cfb_dec): Add 'vzeroupper' at head and
-       'vzeroall' at tail.
-       * cipher/camellia-glue.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec)
-       (_gcry_serpent_avx2_cfb_dec) [USE_AESNI_AVX2]: Remove register
-       clearing.
-
-       camellia-aesni-avx-amd64: Move register clearing to assembly functions.
-       + commit 8b735cb563dff7aafbf8a970972522b5621e665c
-       * cipher/camellia-aesni-avx-amd64.S (_gcry_camellia_aesni_avx_ctr_enc)
-       (_gcry_camellia_aesni_avx_cbc_dec)
-       (_gcry_camellia_aesni_avx_cfb_dec): Add 'vzeroupper' at head and
-       'vzeroall' at tail.
-       * cipher/camellia-glue.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec)
-       (_gcry_serpent_avx2_cfb_dec) [USE_AESNI_AVX]: Remove register clearing.
-
-       serpent-avx2-amd64: Move register clearing to assembly.
-       + commit d12828cd821a4b4428eae19de5aee02cf536e536
-       * cipher/serpent-avx2-amd64.S (_gcry_serpent_avx2_ctr_enc)
-       (_gcry_serpent_avx2_cbc_dec, _gcry_serpent_avx2_cfb_dec): Change last
-       'vzeroupper' to 'vzeroall'.
-       * cipher/serpent.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec)
-       (_gcry_serpent_avx2_cfb_dec) [USE_AVX2]: Remove register clearing with
-       'vzeroall'.
-
-       Fix building for x32 target.
-       + commit fd6721c235a5bdcb332c8eb708fbd4f96e52e824
-       * mpi/amd64/mpi-asm-defs.h: New file.
-       * random/rndhw.c (poll_padlock) [__x86_64__]: Also check if __LP64__ is
-       defined.
-       [USE_DRNG, __x86_64__]: Also check if __LP64__ is defined.
-
-2013-08-31  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       sha512: add ARM/NEON assembly version of transform function.
-       + commit 99d15543b8d94a8f1ef66c6ccb862b0ce82c514d
-       * cipher/Makefile.am: Add 'sha512-armv7-neon.S'.
-       * cipher/sha512-armv7-neon.S: New file.
-       * cipher/sha512.c (USE_ARM_NEON_ASM): New macro.
-       (SHA512_CONTEXT) [USE_ARM_NEON_ASM]: Add 'use_neon'.
-       (sha512_init, sha384_init) [USE_ARM_NEON_ASM]: Enable 'use_neon' if
-       CPU support NEON instructions.
-       (k): Round constant array moved outside of 'transform' function.
-       (__transform): Renamed from 'tranform' function.
-       [USE_ARM_NEON_ASM] (_gcry_sha512_transform_armv7_neon): New prototype.
-       (transform): New wrapper function for different transform versions.
-       (sha512_write, sha512_final): Burn stack by the amount returned by
-       transform function.
-       * configure.ac (sha512) [neonsupport]: Add 'sha512-armv7-neon.lo'.
-
-       sha512: reduce stack use in transform function by 512 bytes.
-       + commit 03da7f8ba3ec24d4639a2bcebbc0d9d831734c08
-       * cipher/sha512.c (transform): Change 'u64 w[80]' to 'u64 w[16]' and
-       inline input expansion to first 64 rounds.
-       (sha512_write, sha512_final): Reduce burn_stack depth by 512 bytes.
-
-       Add ARM HW feature detection module and add NEON detection.
-       + commit 9c95be105f518d18407115c2c06893857c24b116
-       * configure.ac: Add option --disable-neon-support.
-       (HAVE_GCC_INLINE_ASM_NEON): New.
-       (ENABLE_NEON_SUPPORT): New.
-       [arm]: Add 'hwf-arm.lo' as HW feature module.
-       * src/Makefile.am: Add 'hwf-arm.c'.
-       * src/g10lib.h (HWF_ARM_NEON): New macro.
-       * src/global.c (hwflist): Add HWF_ARM_NEON entry.
-       * src/hwf-arm.c: New file.
-       * src/hwf-common.h (_gcry_hwf_detect_arm): New prototype.
-       * src/hwfeatures.c (_gcry_detect_hw_features) [HAVE_CPU_ARCH_ARM]: Add
-       call to _gcry_hwf_detect_arm.
-
-       Correct mpi_cpu_arch for ARMv6.
-       + commit 7b0ebe69fe35f2ee13e1e1beb2766a1eaadb7f0c
-       * mpi/config.links [armv6]: Set mpi_cpu_arch to "arm", instead of
-       "armv6".
-
-2013-08-30  Werner Koch  <wk@gnupg.org>
-
-       mpi: Make gcry_mpi_print work with negative zeroes.
-       + commit e9b711e6ddb480a71d2996465074e436c752c005
-       * mpi/mpicoder.c (gcry_mpi_print): Take care of negative zero.
-       (gcry_mpi_aprint): Allocate at least 1 byte.
-       * tests/t-convert.c: New.
-       * tests/Makefile.am (TESTS): Add t-convert.
-
-       Refactor the ECC code into 3 files.
-       + commit 800d4e01376d52a94a157b53978c7c3f957fc476
-       * cipher/ecc-common.h, cipher/ecc-curves.c, cipher/ecc-misc.c: New.
-       * cipher/Makefile.am (EXTRA_libcipher_la_SOURCES): Add new files.
-       * configure.ac (GCRYPT_PUBKEY_CIPHERS): Add new .c files.
-       * cipher/ecc.c (curve_aliases, ecc_domain_parms_t, domain_parms)
-       (scanval): Move to ecc-curves.c.
-       (fill_in_curve): Move to ecc-curve.c as _gcry_ecc_fill_in_curve.
-       (ecc_get_curve): Move to ecc-curve.c as _gcry_ecc_get_curve.
-       (_gcry_mpi_ec_ec2os): Move to ecc-misc.c.
-       (ec2os): Move to ecc-misc.c as _gcry_ecc_ec2os.
-       (os2ec): Move to ecc-misc.c as _gcry_ecc_os2ec.
-       (point_set): Move as inline function to ecc-common.h.
-       (_gcry_ecc_curve_free): Move to ecc-misc.c as _gcry_ecc_curve_free.
-       (_gcry_ecc_curve_copy): Move to ecc-misc.c as _gcry_ecc_curve_copy.
-       (mpi_from_keyparam, point_from_keyparam): Move to ecc-curves.c.
-       (_gcry_mpi_ec_new): Move to ecc-curves.c.
-       (ecc_get_param): Move to ecc-curves.c as _gcry_ecc_get_param.
-       (ecc_get_param_sexp): Move to ecc-curves.c as _gcry_ecc_get_param_sexp.
-
-2013-08-22  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       serpent-sse2-amd64: Move register clearing to assembly functions.
-       + commit 040aa7688296e93659cb32ca31e9a001a6ab1edd
-       cipher/serpent-sse2-amd64.S (_gcry_serpent_sse2_ctr_enc)
-       (_gcry_serpent_sse2_cbc_dec, _gcry_serpent_sse2_cfb_dec): Clear used
-       XMM registers.
-       cipher/serpent.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec)
-       ( _gcry_serpent_cfb_dec) [USE_SSE2]: Remove XMM register clearing from
-       bulk functions.
-
-       twofish-amd64: do not make __twofish_dec_blk3 global.
-       + commit 82db04a6a0058cf870485459abe7c1659b138ec5
-       * cipher/twofish-amd64.S (__twofish_dec_blk3): Do not export symbol as
-       global.
-       (__twofish_dec_blk3): Mark symbol as function.
-
-2013-08-20  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       mpi: add ARMv6 assembly.
-       + commit da327aef3fe24fdf98fffbc8aea69de42ed12456
-       * mpi/armv6/mpi-asm-defs.h: New.
-       * mpi/armv6/mpih-add1.S: New.
-       * mpi/armv6/mpih-mul1.S: New.
-       * mpi/armv6/mpih-mul2.S: New.
-       * mpi/armv6/mpih-mul3.S: New.
-       * mpi/armv6/mpih-sub1.S: New.
-       * mpi/config.links [arm]: Enable ARMv6 assembly.
-
-       Move ARMv6 detection to configure.ac.
-       + commit 151f1e518be2d16bed748ba832384b0472ddcf9b
-       * cipher/blowfish-armv6.S: Replace __ARM_ARCH >= 6 checks with
-       HAVE_ARM_ARCH_V6.
-       * cipher/blowfish.c: Ditto.
-       * cipher/camellia-armv6.S: Ditto.
-       * cipher/camellia.h: Ditto.
-       * cipher/cast5-armv6.S: Ditto.
-       * cipher/cast5.c: Ditto.
-       * cipher/rijndael-armv6.S: Ditto.
-       * cipher/rijndael.c: Ditto.
-       * configure.ac: Add HAVE_ARM_ARCH_V6 check.
-
-2013-08-19  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add optimized wipememory for ARM.
-       + commit c030e33533fb819afe195eff5f89ec39863b1fbc
-       src/g10lib.h [__arm__] (fast_wipememory2_unaligned_head)
-       (fast_wipememory2): New macros.
-
-       cipher: bufhelp: allow unaligned memory accesses on ARM.
-       + commit 796dda37b957b20dba391343937c6325a8c8b288
-       * cipher/bufhelp.h [__arm__ && __ARM_FEATURE_UNALIGNED]: Enable
-       BUFHELP_FAST_UNALIGNED_ACCESS.
-
-2013-08-17  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Remove burn_stack optimization.
-       + commit 79895b9459b9bf8c60cb7abf09d5bf16ed0cf6e3
-       * src/misc.c (_gcry_burn_stack): Remove SIZEOF_UNSIGNED_LONG == 4 or 8
-       optimization.
-
-2013-08-16  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       camellia: add ARMv6 assembly implementation.
-       + commit cafadc1e4fb97581262b0081ba251e05613d4394
-       * cipher/Makefile.am: Add 'camellia-armv6.S'.
-       * cipher/camellia-armv6.S: New file.
-       * cipher/camellia-glue.c [USE_ARMV6_ASM]
-       (_gcry_camellia_armv6_encrypt_block)
-       (_gcry_camellia_armv6_decrypt_block): New prototypes.
-       [USE_ARMV6_ASM] (Camellia_EncryptBlock, Camellia_DecryptBlock)
-       (camellia_encrypt, camellia_decrypt): New functions.
-       * cipher/camellia.c [!USE_ARMV6_ASM]: Compile encryption and decryption
-       routines if USE_ARMV6_ASM macro is _not_ defined.
-       * cipher/camellia.h (USE_ARMV6_ASM): New macro.
-       [!USE_ARMV6_ASM] (Camellia_EncryptBlock, Camellia_DecryptBlock): If
-       USE_ARMV6_ASM is defined, disable these function prototypes.
-       (camellia) [arm]: Add 'camellia-armv6.lo'.
-
-       blowfish: add ARMv6 assembly implementation.
-       + commit 31e4b1a96a07e9a3698fcb7be0643a136ebb8e5c
-       * cipher/Makefile.am: Add 'blowfish-armv6.S'.
-       * cipher/blowfish-armv6.S: New file.
-       * cipher/blowfish.c (USE_ARMV6_ASM): New macro.
-       [USE_ARMV6_ASM] (_gcry_blowfish_armv6_do_encrypt)
-       (_gcry_blowfish_armv6_encrypt_block)
-       (_gcry_blowfish_armv6_decrypt_block, _gcry_blowfish_armv6_ctr_enc)
-       (_gcry_blowfish_armv6_cbc_dec, _gcry_blowfish_armv6_cfb_dec): New
-       prototypes.
-       [USE_ARMV6_ASM] (do_encrypt, do_encrypt_block, do_decrypt_block)
-       (encrypt_block, decrypt_block): New functions.
-       (_gcry_blowfish_ctr_enc) [USE_ARMV6_ASM]: Use ARMv6 assembly function.
-       (_gcry_blowfish_cbc_dec) [USE_ARMV6_ASM]: Use ARMv6 assembly function.
-       (_gcry_blowfish_cfb_dec) [USE_ARMV6_ASM]: Use ARMv6 assembly function.
-       * configure.ac (blowfish) [arm]: Add 'blowfish-armv6.lo'.
-
-       cast5: add ARMv6 assembly implementation.
-       + commit 8d1faf56714598301580ce370e0bfa6d65e73644
-       * cipher/Makefile.am: Add 'cast5-armv6.S'.
-       * cipher/cast5-armv6.S: New file.
-       * cipher/cast5.c (USE_ARMV6_ASM): New macro.
-       (CAST5_context) [USE_ARMV6_ASM]: New members 'Kr_arm_enc' and
-       'Kr_arm_dec'.
-       [USE_ARMV6_ASM] (_gcry_cast5_armv6_encrypt_block)
-       (_gcry_cast5_armv6_decrypt_block, _gcry_cast5_armv6_ctr_enc)
-       (_gcry_cast5_armv6_cbc_dec, _gcry_cast5_armv6_cfb_dec): New prototypes.
-       [USE_ARMV6_ASM] (do_encrypt_block, do_decrypt_block, encrypt_block)
-       (decrypt_block): New functions.
-       (_gcry_cast5_ctr_enc) [USE_ARMV6_ASM]: Use ARMv6 assembly function.
-       (_gcry_cast5_cbc_dec) [USE_ARMV6_ASM]: Use ARMv6 assembly function.
-       (_gcry_cast5_cfb_dec) [USE_ARMV6_ASM]: Use ARMv6 assembly function.
-       (do_cast_setkey) [USE_ARMV6_ASM]: Initialize 'Kr_arm_enc' and
-       'Kr_arm_dec'.
-       * configure.ac (cast5) [arm]: Add 'cast5-armv6.lo'.
-
-2013-08-14  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rijndael: add ARMv6 assembly implementation.
-       + commit f365961422f1c8b3d89b8bcd9c99828f38c1f158
-       * cipher/Makefile.am: Add 'rijndael-armv6.S'.
-       * cipher/rijndael-armv6.S: New file.
-       * cipher/rijndael.c (USE_ARMV6_ASM): New macro.
-       [USE_ARMV6_ASM] (_gcry_aes_armv6_encrypt_block)
-       (_gcry_aes_armv6_decrypt_block): New prototypes.
-       (do_encrypt_aligned) [USE_ARMV6_ASM]: Use ARMv6 assembly function.
-       (do_encrypt): Disable input/output alignment when USE_ARMV6_ASM.
-       (do_decrypt_aligned) [USE_ARMV6_ASM]: Use ARMv6 assembly function.
-       (do_decrypt): Disable input/output alignment when USE_ARMV6_ASM.
-       * configure.ac (HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS): New check for
-       gcc/as compatibility with ARM assembly implementations.
-       (aes) [arm]: Add 'rijndael-armv6.lo'.
-
-2013-08-09  NIIBE Yutaka  <gniibe@fsij.org>
-
-       cipher: fix memory leak.
-       + commit 2b5bbe264fcd61e5e458e5f71a6507ba0271c729
-       * cipher/pubkey.c (gcry_pk_sign): Handle the specific case of ECC,
-       where there is NULL whichi is not the sentinel.
-
-2013-08-08  Werner Koch  <wk@gnupg.org>
-
-       mpi: Clear immutable flag on the result of gcry_mpi_set.
-       + commit 426cbc9feca0c8f46208fb3670adab95f9e46087
-       * mpi/mpiutil.c (gcry_mpi_set): Reset immutable and const flags.
-       * tests/mpitests.c (test_const_and_immutable): Add a test for this.
-
-2013-08-07  NIIBE Yutaka  <gniibe@fsij.org>
-
-       tests: fix memory leaks.
-       + commit cc082642c1b0f2a3e9ca78e1ffd3f64417c204bd
-       * tests/benchmark.c (dsa_bench): Release SIG.
-
-       * tests/mpitests.c (test_powm): Release BASE, EXP, MOD, and RES.
-
-       * tests/prime.c (check_primes): Release PRIME.
-
-       * tests/tsexp.c (basic): Use intermediate variable M for constant.
-       Release S1, S2 and A.
-
-2013-08-07  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix building on W32 (cannot export symbol 'gcry_sexp_get_buffer')
-       + commit 065d446478bf68553339fc77a89b8369bd110a18
-       * src/libgcrypt.def: Change 'gcry_sexp_get_buffer' to
-       'gcry_sexp_nth_buffer'.
-
-2013-08-06  NIIBE Yutaka  <gniibe@fsij.org>
-
-       cipher: fix another memory leak.
-       + commit 9a421813123a2f5db0a91eaee4a45138efc9ad34
-       * cipher/ecc.c (ecc_get_curve): Free TMP.
-
-       tests: fix memory leaks.
-       + commit 87eddc31ccba6decbddd1761dd42a208666cd311
-       * tests/pubkey.c (check_keys_crypt): Release L, X0, and X1.
-       (check_keys): Release X.
-
-       cipher: fix memory leaks.
-       + commit ae6ffd9af38cbcac57c220960f683aab91db85cb
-       * cipher/elgamal.c (elg_generate_ext): Free XVALUE.
-
-       * cipher/pubkey.c (sexp_elements_extract): Don't use IDX for loop.
-       Call mpi_free.
-       (sexp_elements_extract_ecc): Call mpi_free.
-
-2013-08-05  Werner Koch  <wk@gnupg.org>
-
-       mpi: Improve gcry_mpi_invm to detect bad input.
-       + commit d8e99a04dba6a606e879464cd11deee760d1e000
-       * mpi/mpi-inv.c (gcry_mpi_invm): Return 0 for bad input.
-
-2013-07-31  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Correct checks for ecc secret key.
-       + commit 10dfa41b43a906031bc674ea41cd3073701011f3
-       * cipher/ecc.c (check_secret_key): replace wrong comparison of Q and
-       sk->Q points with correct one.
-
-2013-07-29  Werner Koch  <wk@gnupg.org>
-
-       sexp: Allow white space anywhere in a hex format.
-       + commit 43320961a8751ee28dc95cdb0ae01ea8a7ff7f91
-       * src/sexp.c (hextobyte): Remove.
-       (hextonibble): New.
-       (vsexp_sscan): Skip whtespace between hex nibbles.
-
-       Implement deterministic ECDSA as specified by rfc-6979.
-       + commit 6e0a9786637d649b48aae0e611a12e12beef9b3b
-       * cipher/ecc.c (sign): Add args FLAGS and HASHALGO.  Convert an opaque
-       MPI as INPUT.  Implement rfc-6979.
-       (ecc_sign): Remove the opaque MPI code and pass FLAGS to sign.
-       (verify): Do not allocate and compute Y; it is not used.
-       (ecc_verify): Truncate the hash value if needed.
-       * tests/dsa-rfc6979.c (check_dsa_rfc6979): Add ECDSA test cases.
-
-2013-07-26  Werner Koch  <wk@gnupg.org>
-
-       Implement deterministic DSA as specified by rfc-6979.
-       + commit 1cfa79aabc5d0fd8d124901054475e90ab7d9cde
-       * cipher/dsa.c (dsa_sign): Move opaque mpi extraction to sign.
-       (sign): Add args FLAGS and HASHALGO.  Implement deterministic DSA.
-       Add code path for R==0 to comply with the standard.
-       (dsa_verify): Left fill opaque mpi based hash values.
-       * cipher/dsa-common.c (int2octets, bits2octets): New.
-       (_gcry_dsa_gen_rfc6979_k): New.
-       * tests/dsa-rfc6979.c: New.
-       * tests/Makefile.am (TESTS): Add dsa-rfc6979.
-
-       Allow the use of a private-key s-expression with gcry_pk_verify.
-       + commit b72d312ad11887fc416aa821786f6bdb663c0f4a
-       * cipher/pubkey.c (sexp_to_key): Fallback to private key.
-
-2013-07-25  Werner Koch  <wk@gnupg.org>
-
-       Mitigate a flush+reload cache attack on RSA secret exponents.
-       + commit 287bf0e543f244d784cf8b58340bf0ab3c6aba97
-       * mpi/mpi-pow.c (gcry_mpi_powm): Always perfrom the mpi_mul for
-       exponents in secure memory.
-
-2013-07-19  Werner Koch  <wk@gnupg.org>
-
-       pk: Allow the use of a hash element for DSA sign and verify.
-       + commit 37d0a1ebdc2dc74df4fb6bf0621045018122a68f
-       * cipher/pubkey.c (pubkey_sign): Add arg ctx and pass it to the sign
-       module.
-       (gcry_pk_sign): Pass CTX to pubkey_sign.
-       (sexp_data_to_mpi): Add flag rfc6979 and code to alls hash with *DSA
-       * cipher/rsa.c (rsa_sign, rsa_verify): Return an error if an opaque
-       MPI is given for DATA/HASH.
-       * cipher/elgamal.c (elg_sign, elg_verify): Ditto.
-       * cipher/dsa.c (dsa_sign, dsa_verify): Convert a given opaque MPI.
-       * cipher/ecc.c (ecc_sign, ecc_verify): Ditto.
-       * tests/basic.c (check_pubkey_sign_ecdsa): Add a test for using a hash
-       element with DSA.
-
-       sexp: Add function gcry_sexp_nth_buffer.
-       + commit 2d3e8d4d9562d666420aadd9ffa8ac0456a1cd91
-       * src/sexp.c (gcry_sexp_nth_buffer): New.
-       * src/visibility.c, src/visibility.h: Add function wrapper.
-       * src/libgcrypt.vers, src/libgcrypt.def: Add to API.
-       * src/gcrypt.h.in: Add prototype.
-
-2013-07-18  Werner Koch  <wk@gnupg.org>
-
-       Add support for Salsa20.
-       + commit c4885092088431e7928e4459fda20cc0e8ceb201
-       * src/gcrypt.h.in (GCRY_CIPHER_SALSA20): New.
-       * cipher/salsa20.c: New.
-       * configure.ac (available_ciphers): Add Salsa20.
-       * cipher/cipher.c: Register Salsa20.
-       (cipher_setiv): Allow to divert an IV to a cipher module.
-       * src/cipher-proto.h (cipher_setiv_func_t): New.
-       (cipher_extra_spec): Add field setiv.
-       * src/cipher.h: Declare Salsa20 definitions.
-       * tests/basic.c (check_stream_cipher): New.
-       (check_stream_cipher_large_block): New.
-       (check_cipher_modes): Run new test functions.
-       (check_ciphers): Add simple test for Salsa20.
-
-2013-07-17  Werner Koch  <wk@gnupg.org>
-
-       Allow gcry_mpi_dump to print opaque MPIs.
-       + commit 364d019e3ffedfcb434576702f73e767cb9389ef
-       * mpi/mpicoder.c (gcry_mpi_dump): Detect abd print opaque MPIs.
-       * tests/mpitests.c (test_opaque): New.
-       (main): Call new test.
-
-       cipher: Prepare to pass extra info to the sign functions.
-       + commit 5940e66cbefea3de5924f494f18aed69bb694bff
-       * src/gcrypt-module.h (gcry_pk_sign_t): Add parms flags and hashalgo.
-       * cipher/rsa.c (rsa_sign): Add parms and mark them as unused.
-       * cipher/dsa.c (dsa_sign): Ditto.
-       * cipher/elgamal.c (elg_sign): Ditto.
-       * cipher/pubkey.c (dummy_sign): Ditto.
-       (pubkey_sign): Pass 0 for the new args.
-
-       Fix a special case bug in mpi_powm for e==0.
-       + commit 6e1adb05d290aeeb1c230c763970695f4a538526
-       * mpi/mpi-pow.c (gcry_mpi_powm): For a zero exponent, make sure that
-       the result has been allocated.
-
-2013-07-15  Dmitry Eremin-Solenikov  <dbaryshkov@gmail.com>
-
-       Fix memory leak in t-mpi-point test.
-       + commit a7b80e9fba6b1b095f7c53469747967b40ebfbfd
-       * tests/t-mpi-point.c (basic_ec_math, basic_ec_math_simplified): add
-       calls to gcry_ctx_release() to free contexts after they become unused.
-
-2013-07-10  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Fix 'Please include winsock2.h before windows.h' warnings with mingw32.
-       + commit d6c9c86cb7f571ae0bd9aee4efa01a0f9c4c3104
-       * random/rndw32.c: include winsock2.h before windows.h.
-       * src/ath.h [_WIN32]: Ditto.
-       * tests/benchmark.c [_WIN32]: Ditto.
-
-       Remove duplicate header from mpi/amd64/mpih-mul2.S.
-       + commit c64a0dcbefc5b0055954e37a3c86b32ff7a1b1da
-       * mpi/amd64/mpih-mul2.S: remove duplicated header.
-
-       Fix i386/amd64 inline assembly "cc" clobbers.
-       + commit ed0a598172208ec67234a4edd73189bf6808fd04
-       * cipher/bithelp.h [__GNUC__, __i386__] (rol, ror): add "cc" globber
-       for inline assembly.
-       * cipher/cast5.c [__GNUC__, __i386__] (rol): Ditto.
-       * random/rndhw.c [USE_DRNG] (rdrand_long): Ditto.
-       * src/hmac256.c [__GNUC__, __i386__] (ror): Ditto.
-       * mpi/longlong.c [__i386__] (add_ssaaaa, sub_ddmmss, umul_ppmm)
-       (udiv_qrnnd, count_leading_zeros, count_trailing_zeros): Ditto.
-
-       bufhelp: Suppress 'cast increases required alignment' warning.
-       + commit c3902a6b5cea9acef2e15fbee24eb601eeb25168
-       * cipher/bufhelp.h (buf_xor, buf_xor_2dst, buf_xor_n_copy): Cast
-       to larger element pointer through (void *) to suppress -Wcast-error.
-
-       mpi: Add __ARM_ARCH for older GCC.
-       + commit 97f392f43cf2e4da1297cbecacbfbff33a869478
-       * mpi/longlong.h [__arm__]: Construct __ARM_ARCH if not provided by
-       compiler.
-
-       mpi: add missing "cc" clobber for ARM assembly.
-       + commit 8aa4f2161cf643ce36d87d2e2786b546736f8232
-       * mpi/longlong.h [__arm__] (add_ssaaaa, sub_ddmmss): Add __CLOBBER_CC.
-       [__arm__][__ARM_ARCH <= 3] (umul_ppmm): Ditto.
-
-       Tweak ARM inline assembly for mpi.
-       + commit 71dda4507053379433dc8b0fc6462c15de7299df
-       mpi/longlong.h [__arm__]: Enable inline assembly if __thumb2__ is
-       defined.
-       [__arm__]: Use __ARCH_ARM when defined.
-       [__arm__] [__ARM_ARCH >= 5] (count_leading_zeros): New.
-
-2013-06-26  Werner Koch  <wk@gnupg.org>
-
-       Make gpg-error replacement defines more robust.
-       + commit 6540b84a6e9113813e7e49e3ad2024d4a0073300
-       * configure.ac (AH_BOTTOM): Move GPG_ERR_ replacement defines to ...
-       * src/gcrypt-int.h: new file.
-       * src/visibility.h, src/cipher.h: Replace gcrypt.h by gcrypt-int.h.
-       * tests/: Ditto for all test files.
-
-2013-06-20  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Check if assembler is compatible with AMD64 assembly implementations.
-       + commit 3544fa8aa63bef9a35abf236e9376191b5ec206b
-       * cipher/blowfish-amd64.S: Enable only if
-       HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS is defined.
-       * cipher/camellia-aesni-avx-amd64.S: Ditto.
-       * cipher/camellia-aesni-avx2-amd64.S: Ditto.
-       * cipher/cast5-amd64.S: Ditto.
-       * cipher/rinjdael-amd64.S: Ditto.
-       * cipher/serpent-avx2-amd64.S: Ditto.
-       * cipher/serpent-sse2-amd64.S: Ditto.
-       * cipher/twofish-amd64.S: Ditto.
-       * cipher/blowfish.c: Use AMD64 assembly implementation only if
-       HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS is defined
-       * cipher/camellia-glue.c: Ditto.
-       * cipher/cast5.c: Ditto.
-       * cipher/rijndael.c: Ditto.
-       * cipher/serpent.c: Ditto.
-       * cipher/twofish.c: Ditto.
-       * configure.ac: Check gcc/as compatibility with AMD64 assembly
-       implementations.
-
-2013-06-09  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Optimize _gcry_burn_stack for 32-bit and 64-bit architectures.
-       + commit ec2f8de409a93c80efa658134df22074a9bca5a4
-       * src/misc.c (_gcry_burn_stack): Add optimization for 32-bit and 64-bit
-       architectures.
-
-       Add Camellia AES-NI/AVX2 implementation.
-       + commit d94ec5f5f8a5d40a7d344025aa466f276f9718df
-       * cipher/Makefile.am: Add 'camellia-aesni-avx2-amd64.S'.
-       * cipher/camellia-aesni-avx2-amd64.S: New file.
-       * cipher/camellia-glue.c (USE_AESNI_AVX2): New macro.
-       (CAMELLIA_context) [USE_AESNI_AVX2]: Add 'use_aesni_avx2'.
-       [USE_AESNI_AVX2] (_gcry_camellia_aesni_avx2_ctr_enc)
-       (_gcry_camellia_aesni_avx2_cbc_dec)
-       (_gcry_camellia_aesni_avx2_cfb_dec): New prototypes.
-       (camellia_setkey) [USE_AESNI_AVX2]: Check AVX2+AES-NI capable hardware
-       and set 'ctx->use_aesni_avx2'.
-       (_gcry_camellia_ctr_enc) [USE_AESNI_AVX2]: Add AVX2 accelerated code.
-       (_gcry_camellia_cbc_dec) [USE_AESNI_AVX2]: Add AVX2 accelerated code.
-       (_gcry_camellia_cfb_dec) [USE_AESNI_AVX2]: Add AVX2 accelerated code.
-       (selftest_ctr_128, selftest_cbc_128, selftest_cfb_128): Grow 'nblocks'
-       so that AVX2 codepaths get tested.
-       * configure.ac (camellia) [avx2support, aesnisupport]: Add
-       'camellia-aesni-avx2-amd64.lo'.
-
-       Add Serpent AVX2 implementation.
-       + commit e7ab4e1a7396f4609b9033207015b239ab4a5140
-       * cipher/Makefile.am: Add 'serpent-avx2-amd64.S'.
-       * cipher/serpent-avx2-amd64.S: New file.
-       * cipher/serpent.c (USE_AVX2): New macro.
-       (serpent_context_t) [USE_AVX2]: Add 'use_avx2'.
-       [USE_AVX2] (_gcry_serpent_avx2_ctr_enc, _gcry_serpent_avx2_cbc_dec)
-       (_gcry_serpent_avx2_cfb_dec): New prototypes.
-       (serpent_setkey_internal) [USE_AVX2]: Check for AVX2 capable hardware
-       and set 'use_avx2'.
-       (_gcry_serpent_ctr_enc) [USE_AVX2]: Use AVX2 accelerated functions.
-       (_gcry_serpent_cbc_dec) [USE_AVX2]: Use AVX2 accelerated functions.
-       (_gcry_serpent_cfb_dec) [USE_AVX2]: Use AVX2 accelerated functions.
-       (selftest_ctr_128, selftest_cbc_128, selftest_cfb_128): Grow 'nblocks'
-       so that AVX2 codepaths are tested.
-       * configure.ac (serpent) [avx2support]: Add 'serpent-avx2-amd64.lo'.
-
-       Add detection for Intel AVX2 instruction set.
-       + commit 3289bca708bdd02c69a331095ac6ca9a1efd74cc
-       * configure.ac: Add option --disable-avx2-support.
-       (HAVE_GCC_INLINE_ASM_AVX2): New.
-       (ENABLE_AVX2_SUPPORT): New.
-       * src/g10lib.h (HWF_INTEL_AVX2): New.
-       * src/global.c (hwflist): Add HWF_INTEL_AVX2.
-       * src/hwf-x86.c [__i386__] (get_cpuid): Initialize registers to zero
-       before cpuid.
-       [__x86_64__] (get_cpuid): Initialize registers to zero before cpuid.
-       (detect_x86_gnuc): Store maximum cpuid level.
-       (detect_x86_gnuc) [ENABLE_AVX2_SUPPORT]: Add detection for AVX2.
-
-       twofish: add amd64 assembly implementation.
-       + commit d325ab5d86e6107a46007a4d0131122bbd719f8c
-       * cipher/Makefile.am: Add 'twofish-amd64.S'.
-       * cipher/twofish-amd64.S: New file.
-       * cipher/twofish.c (USE_AMD64_ASM): New macro.
-       [USE_AMD64_ASM] (_gcry_twofish_amd64_encrypt_block)
-       (_gcry_twofish_amd64_decrypt_block, _gcry_twofish_amd64_ctr_enc)
-       (_gcry_twofish_amd64_cbc_dec, _gcry_twofish_amd64_cfb_dec): New
-       prototypes.
-       [USE_AMD64_ASM] (do_twofish_encrypt, do_twofish_decrypt)
-       (twofish_encrypt, twofish_decrypt): New functions.
-       (_gcry_twofish_ctr_enc, _gcry_twofish_cbc_dec, _gcry_twofish_cfb_dec)
-       (selftest_ctr, selftest_cbc, selftest_cfb): New functions.
-       (selftest): Call new bulk selftests.
-       * cipher/cipher.c (gcry_cipher_open) [USE_TWOFISH]: Register Twofish
-       bulk functions for ctr-enc, cbc-dec and cfb-dec.
-       * configure.ac (twofish) [x86_64]: Add 'twofish-amd64.lo'.
-       * src/cipher.h (_gcry_twofish_ctr_enc, _gcry_twofish_cbc_dec)
-       (gcry_twofish_cfb_dec): New prototypes.
-
-2013-05-29  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       rinjdael: add amd64 assembly implementation.
-       + commit 7317fcfadf00789df140e51c0d16b60f6b144b59
-       * cipher/Makefile.am: Add 'rijndael-amd64.S'.
-       * cipher/rijndael-amd64.S: New file.
-       * cipher/rijndael.c (USE_AMD64_ASM): New macro.
-       [USE_AMD64_ASM] (_gcry_aes_amd64_encrypt_block)
-       (_gcry_aes_amd64_decrypt_block): New prototypes.
-       (do_encrypt_aligned) [USE_AMD64_ASM]: Use amd64 assembly function.
-       (do_encrypt): Disable input/output alignment when USE_AMD64_ASM is set.
-       (do_decrypt_aligned) [USE_AMD64_ASM]: Use amd64 assembly function.
-       (do_decrypt): Disable input/output alignment when USE_AMD64_AES is set.
-       * configure.ac (aes) [x86-64]: Add 'rijndael-amd64.lo'.
-
-       blowfish: add amd64 assembly implementation.
-       + commit 9a61edd1f00cefe8ffa3ad54a53eed163883053c
-       * cipher/Makefile.am: Add 'blowfish-amd64.S'.
-       * cipher/blowfish-amd64.S: New file.
-       * cipher/blowfish.c (USE_AMD64_ASM): New macro.
-       [USE_AMD64_ASM] (_gcry_blowfish_amd64_do_encrypt)
-       (_gcry_blowfish_amd64_encrypt_block)
-       (_gcry_blowfish_amd64_decrypt_block, _gcry_blowfish_amd64_ctr_enc)
-       (_gcry_blowfish_amd64_cbc_dec, _gcry_blowfish_amd64_cfb_dec): New
-       prototypes.
-       [USE_AMD64_ASM] (do_encrypt, do_encrypt_block, do_decrypt_block)
-       (encrypt_block, decrypt_block): New functions.
-       (_gcry_blowfish_ctr_enc, _gcry_blowfish_cbc_dec)
-       (_gcry_blowfish_cfb_dec, selftest_ctr, selftest_cbc, selftest_cfb): New
-       functions.
-       (selftest): Call new bulk selftests.
-       * cipher/cipher.c (gcry_cipher_open) [USE_BLOWFISH]: Register Blowfish
-       bulk functions for ctr-enc, cbc-dec and cfb-dec.
-       * configure.ac (blowfish) [x86_64]: Add 'blowfish-amd64.lo'.
-       * src/cipher.h (_gcry_blowfish_ctr_enc, _gcry_blowfish_cbc_dec)
-       (gcry_blowfish_cfb_dec): New prototypes.
-
-2013-05-24  Werner Koch  <wk@gnupg.org>
-
-       ecc: Simplify the compliant point generation.
-       + commit 99b18aa536703ef90c9a1f5c8f40bc68b2064593
-       * cipher/ecc.c (generate_key): Use point_snatch_set, replaces unneeded
-       variable copies, etc.
-
-       ecc: Fix a minor flaw in the generation of K.
-       + commit 9711384f75564a71979e3fb971b5f4cadcf1afef
-       * cipher/dsa.c (gen_k): Factor code out to ..
-       * cipher/dsa-common.c (_gcry_dsa_gen_k): new file and function.  Add
-       arg security_level and re-indent a bit.
-       * cipher/ecc.c (gen_k): Remove and change callers to _gcry_dsa_gen_k.
-       * cipher/dsa.c: Include pubkey-internal.
-       * cipher/Makefile.am (libcipher_la_SOURCES): Add dsa-common.c
-
-2013-05-24  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       cast5: add amd64 assembly implementation.
-       + commit 0bdf26eea8cdbffefe7e37578f8f896c4f5f5275
-       * cipher/Makefile.am: Add 'cast5-amd64.S'.
-       * cipher/cast5-amd64.S: New file.
-       * cipher/cast5.c (USE_AMD64_ASM): New macro.
-       (_gcry_cast5_s1tos4): Merge arrays s1, s2, s3, s4 to single array to
-       simplify access from assembly implementation.
-       (s1, s2, s3, s4): New macros pointing to subarrays in
-       _gcry_cast5_s1tos4.
-       [USE_AMD64_ASM] (_gcry_cast5_amd64_encrypt_block)
-       (_gcry_cast5_amd64_decrypt_block, _gcry_cast5_amd64_ctr_enc)
-       (_gcry_cast5_amd64_cbc_dec, _gcry_cast5_amd64_cfb_dec): New prototypes.
-       [USE_AMD64_ASM] (do_encrypt_block, do_decrypt_block, encrypt_block)
-       (decrypt_block): New functions.
-       (_gcry_cast5_ctr_enc, _gcry_cast5_cbc_dec, _gcry_cast5_cfb_dec)
-       (selftest_ctr, selftest_cbc, selftest_cfb): New functions.
-       (selftest): Call new bulk selftests.
-       * cipher/cipher.c (gcry_cipher_open) [USE_CAST5]: Register CAST5 bulk
-       functions for ctr-enc, cbc-dec and cfb-dec.
-       * configure.ac (cast5) [x86_64]: Add 'cast5-amd64.lo'.
-       * src/cipher.h (_gcry_cast5_ctr_enc, _gcry_cast5_cbc_dec)
-       (gcry_cast5_cfb_dec): New prototypes.
-
-       cipher-selftest: make selftest work with any block-size.
-       + commit ab8fc70b5f0c396a5bc941267f59166e860b8c5d
-       * cipher/cipher-selftest.c (_gcry_selftest_helper_cbc_128)
-       (_gcry_selftest_helper_cfb_128, _gcry_selftest_helper_ctr_128): Renamed
-       functions from '<name>_128' to '<name>'.
-       (_gcry_selftest_helper_cbc, _gcry_selftest_helper_cfb)
-       (_gcry_selftest_helper_ctr): Make work with different block sizes.
-       * cipher/cipher-selftest.h (_gcry_selftest_helper_cbc_128)
-       (_gcry_selftest_helper_cfb_128, _gcry_selftest_helper_ctr_128): Renamed
-       prototypes from '<name>_128' to '<name>'.
-       * cipher/camellia-glue.c (selftest_ctr_128, selftest_cfb_128)
-       (selftest_ctr_128): Change to use new function names.
-       * cipher/rijndael.c (selftest_ctr_128, selftest_cfb_128)
-       (selftest_ctr_128): Change to use new function names.
-       * cipher/serpent.c (selftest_ctr_128, selftest_cfb_128)
-       (selftest_ctr_128): Change to use new function names.
-
-2013-05-23  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       serpent: add parallel processing for CFB decryption.
-       + commit 6deb0ccdf718a0670f80e6762a3842caf76437d6
-       * cipher/cipher.c (gcry_cipher_open): Add bulf CFB decryption function
-       for Serpent.
-       * cipher/serpent-sse2-amd64.S (_gcry_serpent_sse2_cfb_dec): New
-       function.
-       * cipher/serpent.c (_gcry_serpent_sse2_cfb_dec): New prototype.
-       (_gcry_serpent_cfb_dec) New function.
-       (selftest_cfb_128) New function.
-       (selftest) Call selftest_cfb_128.
-       * src/cipher.h (_gcry_serpent_cfb_dec): New prototype.
-
-       camellia: add parallel processing for CFB decryption.
-       + commit b60f06f70227c1e69e1010da8b47ea51ade48145
-       * cipher/camellia-aesni-avx-amd64.S
-       (_gcry_camellia_aesni_avx_cfb_dec): New function.
-       * cipher/camellia-glue.c (_gcry_camellia_aesni_avx_cfb_dec): New
-       prototype.
-       (_gcry_camellia_cfb_dec): New function.
-       (selftest_cfb_128): New function.
-       (selftest): Call selftest_cfb_128.
-       * cipher/cipher.c (gry_cipher_open): Add bulk CFB decryption function
-       for Camellia.
-       * src/cipher.h (_gcry_camellia_cfb_dec): New prototype.
-
-       rinjdael: add parallel processing for CFB decryption with AES-NI.
-       + commit 319ee14f2aab8db56a830fd7ac8926f91b4f738a
-       * cipher/cipher-selftest.c (_gcry_selftest_helper_cfb_128): New
-       function for CFB selftests.
-       * cipher/cipher-selftest.h (_gcry_selftest_helper_cfb_128): New
-       prototype.
-       * cipher/rijndael.c [USE_AESNI] (do_aesni_enc_vec4): New function.
-       (_gcry_aes_cfb_dec) [USE_AESNI]: Add parallelized CFB decryption.
-       (selftest_cfb_128): New function.
-       (selftest): Call selftest_cfb_128.
-
-2013-05-23  Werner Koch  <wk@gnupg.org>
-
-       Avoid compiler warning due to the global symbol setkey.
-       + commit b402de8b9c4a9f269faf03ca952b1eb68a1f33c8
-       * cipher/cipher-selftest.c (_gcry_selftest_helper_cbc_128)
-       (_gcry_selftest_helper_ctr_128): Rename setkey to setkey_func.
-
-2013-05-23  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       serpent: add SSE2 accelerated amd64 implementation.
-       + commit 2fd06e207dcea1d8a7f0e7e92f3359615a99421b
-       * configure.ac (serpent): Add 'serpent-sse2-amd64.lo'.
-       * cipher/Makefile.am (EXTRA_libcipher_la_SOURCES): Add
-       'serpent-sse2-amd64.S'.
-       * cipher/cipher.c (gcry_cipher_open) [USE_SERPENT]: Register bulk
-       functions for CBC-decryption and CTR-mode.
-       * cipher/serpent.c (USE_SSE2): New macro.
-       [USE_SSE2] (_gcry_serpent_sse2_ctr_enc, _gcry_serpent_sse2_cbc_dec):
-       New prototypes to assembler functions.
-       (serpent_setkey): Set 'serpent_init_done' before calling serpent_test.
-       (_gcry_serpent_ctr_enc): New function.
-       (_gcry_serpent_cbc_dec): New function.
-       (selftest_ctr_128): New function.
-       (selftest_cbc_128): New function.
-       (selftest): Call selftest_ctr_128 and selftest_cbc_128.
-       * cipher/serpent-sse2-amd64.S: New file.
-       * src/cipher.h (_gcry_serpent_ctr_enc): New prototype.
-       (_gcry_serpent_cbc_dec): New prototype.
-
-       Serpent: faster S-box implementation.
-       + commit c85501af8222913f0a1e20e77fceb88e93417925
-       * cipher/serpent.c (SBOX0, SBOX1, SBOX2, SBOX3, SBOX4, SBOX5, SBOX6)
-       (SBOX7, SBOX0_INVERSE, SBOX1_INVERSE, SBOX2_INVERSE, SBOX3_INVERSE)
-       (SBOX4_INVERSE, SBOX5_INVERSE, SBOX6_INVERSE, SBOX7_INVERSE): Replace
-       with new definitions.
-
-2013-05-22  Werner Koch  <wk@gnupg.org>
-
-       w32: Fix installing of .def file.
-       + commit 4e46d8bc78008ba06f106b368cefb0dddf15fe38
-       * src/Makefile.am (install-def-file): Create libdir first.
-
-       Add control commands to disable mlock and setuid dropping.
-       + commit 2b8014af202c9e0f7619f7a4377f5eb752235220
-       * src/gcrypt.h.in (GCRYCTL_DISABLE_LOCKED_SECMEM): New.
-       (GCRYCTL_DISABLE_PRIV_DROP): New.
-       * src/global.c (_gcry_vcontrol): Implement them.
-       * src/secmem.h (GCRY_SECMEM_FLAG_NO_MLOCK): New.
-       (GCRY_SECMEM_FLAG_NO_PRIV_DROP): New.
-       * src/secmem.c (no_mlock, no_priv_drop): New.
-       (_gcry_secmem_set_flags, _gcry_secmem_get_flags): Set and get them.
-       (lock_pool): Handle no_mlock and no_priv_drop.
-
-       Fix libtool 2.4.2 to correctly detect .def files.
-       + commit 05b3e2dda61d3d532a7f1ffd2487a85ed1c4f3ab
-       * ltmain.sh (sed_uncomment_deffile): New.
-       (orig_export_symbols): Uncomment def file before testing for EXPORTS.
-       * m4/libtool.m4: Do the same for the generated code.
-
-2013-05-22  Jussi Kivilinna  <jussi.kivilinna@iki.fi>
-
-       Add AES bulk CBC decryption selftest.
-       + commit b65281a1b76d7898eb7607932246b78277d8570b
-       * cipher/rinjdael.c (selftest_cbc_128): New.
-       (selftest): Call selftest_cbc_128.
-
-       Change AES bulk CTR encryption selftest use new selftest helper function
-       + commit 3637bdbb5f30a5e06745d448a6a8ad00e5cdd740
-       * cipher/rinjdael.c: (selftest_ctr_128): Change to use new selftest
-       helper function.
-
-       Convert bulk CTR and CBC selftest functions in Camellia to generic selftest helper functions
-       + commit eed4042fa028b3f73bad6a768f5b0a82f642e545
-       * cipher/Makefile.am (libcipher_la_SOURCES): Add cipher-selftest files.
-       * cipher/camellia-glue.c (selftest_ctr_128, selftest_cbc_128): Change
-       to use the new selftest helper functions.
-       * cipher/cipher-selftest.c: New.
-       * cipher/cipher-selftest.h: New.
-
-       camellia: add bulk CBC decryption selftest.
-       + commit f2986f03d1ae59f973bae56ce4333e5457003de5
-       * cipher/camellia-glue.c: (selftest_cbc_128): New selftest function for
-       bulk CBC decryption.
-       (selftest): Add call to selftest_cbc_128.
-
-       camellia: Rename camellia_aesni_avx_x86-64.S to camellia-aesni-avx-amd64.S
-       + commit 194ae35da7830a76b96e9b21121a2e1248762d3f
-       * cipher/camellia_aesni_avx_x86-64.S: Remove.
-       * cipher/camellia-aesni-avx-amd64.S: New.
-       * cipher/Makefile.am: Use the new filename.
-       * configure.ac: Use the new filename.
-
-2013-05-21  Werner Koch  <wk@gnupg.org>
-
-       Fix indentation and save on string space.
-       + commit 2ac3a7c2b7154379738d17cfde8cd9017dc142f0
-       * cipher/ecc.c (generate_key): Use the same string for both fatal
-       messages.
-
-2013-05-20  Andrey  <andrey@brainhub.org>
-
-       cipher: Fix segv in last ECC change.
-       + commit eb4937914db3fb7317502e97e4f0e40c1857f59d
-       * cipher/ecc.c (generate_key): Make sure R is initialized.
-
-2013-05-09  Andrey  <andrey@brainhub.org>
-
-       cipher: Generate compliant ECC keys.
-       + commit 296f38a2bd2e25788643a42e4881faed00884a40
-       * cipher/ecc.c (generate_key): Make sure a key is compliant for
-       using the compact representation.
-
-2013-04-18  Werner Koch  <wk@gnupg.org>
-
-       cipher: Fix regression in Padlock support.
-       + commit 6c942ec4d63032539f1fc56c3b970cfec2369e2b
-       * cipher/rijndael.c (do_setkey): Remove dummy padlock key generation case
-       and use the standard one.
-
-       mpi: Yet another fix to get option flag munging right.
-       + commit 03557687a09b9c8878c77cbfdd0f5049940c72da
-       * cipher/Makefile.am (o_flag_munging): Yet another fix.
-
-       mpi: Make using gcc's -Ofast easier.
-       + commit 1ab26bc304c559b0a8d29823d656f7ad8d10a59d
-       * cipher/Makefile.am (o_flag_munging): Take -Ofast in account.
-
-       Fix alignment problem in idea.c.
-       + commit 3271b0dfda67e26c381d7ed667737f08f865ee40
-       * cipher/idea.c (cipher): Rework parameter use to fix alignment
-       problems.
-
-       * cipher/idea.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Remove unused macros.
-
-       Fix alignment problem in idea.c.
-
-       * cipher/idea.c (cipher): Rework parameter use to fix alignment
-       problems.
-
-       * cipher/idea.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Remove unused macros.
-
-
-       (cherry picked from 4cd279556777e02eda79973f68efaa4b741f9175)
-
-2013-04-18  Vladimir Serbinenko  <phcoder@gmail.com>
-
-       Add some const attributes.
-       + commit ff0b94c22b36600fff1db9f1d48f9de61f9038f7
-       * cipher/md4.c (transform): Add const attribute.
-       * cipher/md5.c (transform): Ditto.
-       * cipher/rmd160.c (transform): Ditto.
-
-       Fix alignment problem in serpent.c.
-       + commit 86e72b490a5790a9c23341067c7e4d3e38be1634
-       * cipher/serpent.c (serpent_key_prepare): Fix misaligned access.
-       (serpent_setkey): Likewise.
-       (serpent_encrypt_internal): Likewise.
-       (serpent_decrypt_internal): Likewise.
-       (serpent_encrypt): Don't put an alignment-increasing cast.
-       (serpent_decrypt): Likewise.
-       (serpent_test): Likewise.
-
-2013-04-16  Werner Koch  <wk@wheatstone.g10code.de>
-
-       Fix multiply by zero in gcry_mpi_ec_mul.
-       + commit 78cd0ba8a8eceee9d0b3397a2ab3bda6ba37c8a4
-       * mpi/ec.c (_gcry_mpi_ec_mul_point): Handle case of SCALAR == 0.
-       * tests/t-mpi-point.c (basic_ec_math): Add a test case for this.
-
-2013-04-15  Werner Koch  <wk@gnupg.org>
-
-       Add macros to return pre-defined MPIs.
-       + commit bd3afc27459a44df8cf501a7e1ae37bb849a8b0e
-       * src/gcrypt.h.in (GCRYMPI_CONST_ONE, GCRYMPI_CONST_TWO)
-       (GCRYMPI_CONST_THREE, GCRYMPI_CONST_FOUR, GCRYMPI_CONST_EIGHT): New.
-       (_gcry_mpi_get_const): New private function.
-       * src/visibility.c (_gcry_mpi_get_const): New.
-       * src/visibility.h: Mark it visible.
-
-       Fix addition of EC points.
-       + commit 71b25a5562f68aad81eae52cc1bab9ca7731a7e9
-       * mpi/ec.c (_gcry_mpi_ec_add_points): Fix case of P1 given in affine
-       coordinates.
-
-2013-04-12  Werner Koch  <wk@gnupg.org>
-
-       Add hack to allow using an "ecc" key for "ecdsa" or "ecdh".
-       + commit af8a79aea80217a0c85a592db1fa001792a6bf0f
-       * cipher/pubkey.c (sexp_to_key): Add optional arg USE.
-       (gcry_pk_encrypt, gcry_pk_decrypt): Call sexp_to_key with usage sign.
-       (gcry_pk_sign, gcry_pk_verify): Call sexp_to_key with usage encrypt.
-       * tests/basic.c (show_sexp): New.
-       (check_pubkey_sign): Print test number and add cases for ecc.
-       (check_pubkey_sign_ecdsa): New.
-       (do_check_one_pubkey): Divert to new function.
-
-2013-04-11  Werner Koch  <wk@gnupg.org>
-
-       Add gcry_pubkey_get_sexp.
-       + commit 1f3cfad66456dd6f2e48f20b8eb0c51343449a1c
-       * src/gcrypt.h.in (GCRY_PK_GET_PUBKEY): New.
-       (GCRY_PK_GET_SECKEY): New.
-       (gcry_pubkey_get_sexp): New.
-       * src/visibility.c (gcry_pubkey_get_sexp): New.
-       * src/visibility.h (gcry_pubkey_get_sexp): Mark visible.
-       * src/libgcrypt.def, src/libgcrypt.vers: Add new function.
-       * cipher/pubkey-internal.h: New.
-       * cipher/Makefile.am (libcipher_la_SOURCES): Add new file.
-       * cipher/ecc.c: Include pubkey-internal.h
-       (_gcry_pk_ecc_get_sexp): New.
-       * cipher/pubkey.c: Include pubkey-internal.h and context.h.
-       (_gcry_pubkey_get_sexp): New.
-       * src/context.c (_gcry_ctx_find_pointer): New.
-       * src/cipher-proto.h: Add _gcry_pubkey_get_sexp.
-       * tests/t-mpi-point.c (print_sexp): New.
-       (context_param, basic_ec_math_simplified): Add tests for the new
-       function.
-
-       * configure.ac (NEED_GPG_ERROR_VERSION): Set to 1.11.
-       (AH_BOTTOM) Add error codes from gpg-error 1.12
-       * src/g10lib.h (fips_not_operational): Use GPG_ERR_NOT_OPERATIONAL.
-
-       * mpi/ec.c (_gcry_mpi_ec_get_mpi): Fix computation of Q.
-       (_gcry_mpi_ec_get_point): Ditto.
-
-       Remove unused code.
-       + commit 7524da2ba83d83a766c22d704006380c893e1c49
-       * cipher/pubkey.c (_gcry_pk_module_lookup, _gcry_pk_module_release)
-       (_gcry_pk_get_elements): Remove.
-
-2013-04-05  Werner Koch  <wk@gnupg.org>
-
-       Make the Q parameter optional for ECC signing.
-       + commit fe91a642c7c257aca095b96406fbcace88fa3df4
-       * cipher/ecc.c (ecc_sign): Remove the need for Q.
-       * cipher/pubkey.c (sexp_elements_extract_ecc): Make Q optional for a
-       private key.
-       (sexp_to_key): Add optional arg R_IS_ECC.
-       (gcry_pk_sign): Do not call gcry_pk_get_nbits for ECC keys.
-       * tests/pubkey.c (die): Make sure to print a LF.
-       (check_ecc_sample_key): New.
-       (main): Call new test.
-
-       Add test case for SCRYPT and rework the code.
-       + commit f23a068bcb6ec9788710698578d8be0a2a006dbc
-       * tests/t-kdf.c (check_scrypt): New.
-       (main): Call new test.
-
-       * configure.ac: Support disabling of the scrypt algorithm.  Make KDF
-       enabling similar to the other algorithm classes.  Disable scrypt if we
-       don't have a 64 bit type.
-       * cipher/memxor.c, cipher/memxor.h: Remove.
-       * cipher/scrypt.h: Remove.
-       * cipher/kdf-internal.h: New.
-       * cipher/Makefile.am: Remove files.  Add new file.  Move scrypt.c to
-       EXTRA_libcipher_la_SOURCES.
-       (GCRYPT_MODULES): Add GCRYPT_KDFS.
-       * src/gcrypt.h.in (GCRY_KDF_SCRYPT): Change value.
-       * cipher/kdf.c (pkdf2): Rename to _gcry_kdf_pkdf2.
-       (_gcry_kdf_pkdf2): Don't bail out for SALTLEN==0.
-       (gcry_kdf_derive): Allow for a passwordlen of zero for scrypt.  Check
-       for SALTLEN > 0 for GCRY_KDF_PBKDF2.  Pass algo to _gcry_kdf_scrypt.
-       (gcry_kdf_derive) [!USE_SCRYPT]: Return an error.
-       * cipher/scrypt.c: Replace memxor.h by bufhelp.h.  Replace scrypt.h by
-       kdf-internal.h.  Enable code only if HAVE_U64_TYPEDEF is defined.
-       Replace C99 types uint64_t, uint32_t, and uint8_t by libgcrypt types.
-       (_SALSA20_INPUT_LENGTH): Remove underscore from identifier.
-       (_scryptBlockMix): Replace memxor by buf_xor.
-       (_gcry_kdf_scrypt): Use gcry_malloc and gcry_free.  Check for integer
-       overflow.  Add hack to support blocksize of 1 for tests.  Return
-       errors from calls to _gcry_kdf_pkdf2.
-
-       * cipher/kdf.c (openpgp_s2k): Make static.
-
-2013-04-04  Christian Grothoff  <christian@grothoff.org>
-
-       Add the SCRYPT KDF function.
-       + commit 855b1a8f81b5a3b5b31d0c3c303675425f58a5af
-       * scrypt.c, scrypt.h: New files.
-       * memxor.c, memxor.h: New files.
-       * cipher/Makefile.am: Add new files.
-       * cipher/kdf.c (gcry_kdf_derive): Support GCRY_KDF_SCRYPT.
-       * src/gcrypt.h.in (GCRY_KDF_SCRYPT): New.
-
-2013-03-22  Werner Koch  <wk@gnupg.org>
-
-       Replace deprecated AM_CONFIG_HEADER macro.
-       + commit d0c8fda5af45354ac32928c9a01e688d6893599d
-       * configure.ac: s/AM_CONFIG_HEADER/AC_CONFIG_HEADER/
-
-       Disable AES-NI support if as does not support SSSE3.
-       + commit 9f4df1612ae21a5ce70d98930cb194e5193f5e2d
-       * configure.ac (HAVE_GCC_INLINE_ASM_SSSE3): New test.
-       (ENABLE_AESNI_SUPPORT): Do not define without SSSE3 support.
-       (HAVE_GCC_INLINE_ASM_SSSE3, ENABLE_AVX_SUPPORT): Split up detection
-       and definition.
-
-2013-03-21  Werner Koch  <wk@gnupg.org>
-
-       Fix make dependency regression.
-       + commit 2a1e03c5a481689c43d197dd8034a1d73de0a1a4
-       * src/Makefile.am (libgcrypt_la_DEPENDENCIES): Add missing backslash.
-       Reported by LRN.
-
-2013-03-20  Werner Koch  <wk@gnupg.org>
-
-       Use finer grained on-the-fly helper computations for EC.
-       + commit 5fb3501aa0cf5f2b2a9012706bb9ad2b1c4bfd7d
-       * src/ec-context.h (mpi_ec_ctx_s): Replace NEED_SYNC by a bitfield.
-       * mpi/ec.c (ec_p_sync): Remove.
-       (ec_get_reset, ec_get_a_is_pminus3, ec_get_two_inv_p): New.
-       (ec_p_init): Use ec_get_reset.
-       (_gcry_mpi_ec_set_mpi, _gcry_mpi_ec_dup_point)
-       (_gcry_mpi_ec_add_points): Replace ec_p_sync by the ec_get_ accessors.
-
-       Allow building with w64-mingw32.
-       + commit b402e550041782b770a6ae267c7c28ca8324a12e
-       * autogen.sh <--build-w32>: Support the w64-mingw32 toolchain.  Also
-       prepare for 64 bit building.
-
-       Provide GCRYPT_VERSION_NUMBER macro, add build info to the binary.
-       + commit 1eaad0a8c4cab227685a6a8768e539df2f1f4dac
-       * src/gcrypt.h.in (GCRYPT_VERSION_NUMBER): New.
-       * configure.ac (VERSION_NUMBER): New ac_subst.
-       * src/global.c (_gcry_vcontrol): Move call to above function ...
-       (gcry_check_version): .. here.
-
-       * configure.ac (BUILD_REVISION, BUILD_FILEVERSION)
-       (BUILD_TIMESTAMP): Define on all platforms.
-       * compat/compat.c (_gcry_compat_identification): Include revision and
-       timestamp.
-
-       Fix a memory leak in the new EC code.
-       + commit de07974d807b703a2554d6ba885ea249e648bd44
-       * cipher/ecc.c (point_from_keyparam): Always call mpi_free on A.
-
-2013-03-19  Werner Koch  <wk@gnupg.org>
-
-       Extend the new EC interface and fix two bugs.
-       + commit 931e409e877d1e444edd53dead327ec8e64daf9a
-       * src/ec-context.h (mpi_ec_ctx_s): Add field NEED_SYNC.
-       * mpi/ec.c (ec_p_sync): New.
-       (ec_p_init): Only set NEED_SYNC.
-       (_gcry_mpi_ec_set_mpi): Set NEED_SYNC for 'p' and 'a'.
-       (_gcry_mpi_ec_dup_point, _gcry_mpi_ec_add_points)
-       (_gcry_mpi_ec_mul_point): Call ec_p_sync.
-       (_gcry_mpi_ec_get_point): Recompute 'q' is needed.
-       (_gcry_mpi_ec_get_mpi): Ditto.  Also allow for names 'q', 'q.x',
-       'q.y', and 'g'.
-       * cipher/ecc.c (_gcry_mpi_ec_ec2os): New.
-
-       * cipher/ecc.c (_gcry_mpi_ec_new): Fix init from parameters 'Q'->'q',
-       'G'->'q'.
-
-2013-03-15  Werner Koch  <wk@gnupg.org>
-
-       mpi: Add functions to manipulate an EC context.
-       + commit 229f3219f80c9369ed9624242c0436ae6d293201
-       * src/gcrypt.h.in (gcry_mpi_ec_p_new): Remove.
-       (gcry_mpi_ec_new): New.
-       (gcry_mpi_ec_get_mpi): New.
-       (gcry_mpi_ec_get_point): New.
-       (gcry_mpi_ec_set_mpi): New.
-       (gcry_mpi_ec_set_point): New.
-       * src/visibility.c (gcry_mpi_ec_p_new): Remove.
-       * mpi/ec.c (_gcry_mpi_ec_p_new): Make it an internal function and
-       change to return an error code.
-       (_gcry_mpi_ec_get_mpi): New.
-       (_gcry_mpi_ec_get_point): New.
-       (_gcry_mpi_ec_set_mpi): New.
-       (_gcry_mpi_ec_set_point): New.
-       * src/mpi.h: Add new prototypes.
-       * src/ec-context.h: New.
-       * mpi/ec.c: Include that header.
-       (mpi_ec_ctx_s): Move to ec-context.h, add new fields, and put some
-       fields into an inner struct.
-       (point_copy): New.
-       * cipher/ecc.c (fill_in_curve): Allow passing NULL for R_NBITS.
-       (mpi_from_keyparam, point_from_keyparam): New.
-       (_gcry_mpi_ec_new): New.
-
-       * tests/t-mpi-point.c (test-curve): New.
-       (ec_p_new): New.  Use it instead of the removed gcry_mpi_ec_p_new.
-       (get_and_cmp_mpi, get_and_cmp_point): New.
-       (context_param): New test.
-       (basic_ec_math_simplified): New test.
-       (main): Call new tests.
-
-       * src/context.c (_gcry_ctx_get_pointer): Check for a NULL CTX.
-
-2013-03-13  Werner Koch  <wk@gnupg.org>
-
-       Add GCRYMPI_FLAG_CONST and make use constants.
-       + commit e005629bd7bebb3e13945645c6e1230b44ab16a2
-       * src/gcrypt.h.in (GCRYMPI_FLAG_CONST): New.
-       * src/mpi.h (mpi_is_const, mpi_const): New.
-       (enum gcry_mpi_constants, MPI_NUMBER_OF_CONSTANTS): New.
-       * mpi/mpiutil.c (_gcry_mpi_init): New.
-       (constants): New.
-       (_gcry_mpi_free): Do not release a constant flagged MPI.
-       (gcry_mpi_copy): Clear the const and immutable flags.
-       (gcry_mpi_set_flag, gcry_mpi_clear_flag, gcry_mpi_get_flag): Support
-       GCRYMPI_FLAG_CONST.
-       (_gcry_mpi_const): New.
-       * src/global.c (global_init): Call _gcry_mpi_init.
-       * mpi/ec.c (mpi_ec_ctx_s): Remove fields one, two, three, four, and
-       eight.  Change all users to call mpi_const() instead.
-
-       * src/mpiutils.c (gcry_mpi_set_opaque): Check the immutable flag.
-
-       Add GCRYMPI_FLAG_IMMUTABLE to help debugging.
-       + commit 1fecae98ee7e0fa49b29f98efa6817ca121ed98a
-       * src/gcrypt.h.in (GCRYMPI_FLAG_IMMUTABLE): New.
-       * src/mpi.h (mpi_is_immutable): New macro.
-       * mpi/mpiutil.c (gcry_mpi_set_flag, gcry_mpi_clear_flag)
-       (gcry_mpi_get_flag): Implement new flag
-       (_gcry_mpi_immutable_failed): New.
-
-       * mpi/mpiutil.c (_gcry_mpi_clear, _gcry_mpi_free, gcry_mpi_snatch)
-       (gcry_mpi_set, gcry_mpi_randomize): Act upon the immutable flag.
-       * mpi/mpi-bit.c (gcry_mpi_set_bit, gcry_mpi_set_highbit)
-       (gcry_mpi_clear_highbit, gcry_mpi_clear_bit)
-       (_gcry_mpi_rshift_limbs, gcry_mpi_lshift): Ditto.
-       * mpi/mpicoder.c (_gcry_mpi_set_buffer): Ditto.
-
-2013-03-08  Werner Koch  <wk@gnupg.org>
-
-       mpi: Add an API for EC math.
-       + commit 8ac9e756d3ca545a9b97e61ad3d42fc2e877d788
-       * src/context.c, src/context.h: New.
-       * src/Makefile.am (libgcrypt_la_SOURCES): Add new files.
-       * src/gcrypt.h.in (struct gcry_context, gcry_ctx_t): New types.
-       (gcry_ctx_release): New prototype.
-       (gcry_mpi_ec_p_new, gcry_mpi_ec_get_affine, gcry_mpi_ec_dup)
-       (gcry_mpi_ec_add, gcry_mpi_ec_mul): New prototypes.
-       * mpi/ec.c: Include errno.h and context.h.
-       (_gcry_mpi_ec_init): Rename to ..
-       (ec_p_init): this, make static, remove allocation and add arg CTX.
-       (_gcry_mpi_ec_p_internal_new): New; to replace _gcry_mpi_ec_init.
-       Change all callers to use this func.
-       (_gcry_mpi_ec_free): Factor code out to ..
-       (ec_deinit): New func.
-       (gcry_mpi_ec_p_new): New.
-       * src/visibility.c: Include context.h and mpi.h.
-       (gcry_mpi_ec_p_new, gcry_mpi_ec_get_affine, gcry_mpi_ec_dup)
-       (gcry_mpi_ec_add, gcry_mpi_ec_mul)
-       (gcry_ctx_release): New wrapper functions.
-       * src/visibility.h: Mark new wrapper functions visible.
-       * src/libgcrypt.def, src/libgcrypt.vers: Add new symbols.
-       * tests/t-mpi-point.c (print_mpi, hex2mpi, cmp_mpihex): New.
-       (context_alloc): New.
-       (make_point, basic_ec_math): New.
-
-       mpi: Add an API for EC point operations.
-       + commit 7cce620acddac2df024ca421ed3abc32a88f3738
-       * mpi/ec.c (gcry_mpi_point_new, gcry_mpi_point_release): New.
-       (gcry_mpi_point_get, gcry_mpi_point_snatch_get): New.
-       (gcry_mpi_point_set, gcry_mpi_point_snatch_set): New.
-       * src/visibility.h, src/visibility.c: Add corresponding macros and
-       wrappers.
-       * src/gcrypt.h.in (struct gcry_mpi_point, gcry_mpi_point_t): New.
-       (gcry_mpi_point_new, gcry_mpi_point_release, gcry_mpi_point_get)
-       (gcry_mpi_point_snatch_get, gcry_mpi_point_set)
-       (gcry_mpi_point_snatch_set): New prototypes.
-       (mpi_point_new, mpi_point_release, mpi_point_get, mpi_point_snatch_get)
-       (mpi_point_set, mpi_point_snatch_set): New macros.
-       * src/libgcrypt.vers (gcry_mpi_point_new, gcry_mpi_point_release)
-       (gcry_mpi_point_get, gcry_mpi_point_snatch_get, gcry_mpi_point_set)
-       (gcry_mpi_point_snatch_set): New symbols.
-       * src/libgcrypt.def: Ditto.
-       * tests/t-mpi-point.c: New.
-       * tests/Makefile.am (TESTS): Add t-mpi-point
-
-2013-03-07  Werner Koch  <wk@gnupg.org>
-
-       mpi: Add mpi_snatch and change an internal typedef.
-       + commit 6c4767637c512127a4362732b3ec51068554d328
-       * src/mpi.h (struct mpi_point_s): Rename to struct gcry_mpi_point.
-       (mpi_point_struct): New typedef.
-       (mpi_point_t): Change typedef to a pointer.  Replace all occurrences
-       to use mpi_point_struct.
-       * mpi/ec.c (_gcry_mpi_ec_point_init): Rename to ..
-       (_gcry_mpi_point_init): this.  Change all callers.
-       (_gcry_mpi_ec_point_free): Rename to ..
-       (_gcry_mpi_point_free_parts): this.  Change all callers.
-
-       * mpi/mpiutil.c (gcry_mpi_snatch): New function.
-       * src/gcrypt.h.in (gcry_mpi_snatch, mpi_snatch): Add protoype and
-       macro.
-       * src/visibility.c (gcry_mpi_snatch): Add wrapper.
-       * src/visibility.h (gcry_mpi_snatch): Add macro magic.
-       * src/libgcrypt.def, src/libgcrypt.vers: Add new function.
-
-       Pretty print the configure feedback.
-       + commit c620099e4ab2f35e0196b395a805bb655c984ac2
-       * acinclude.m4 (GNUPG_MSG_PRINT): Remove.
-       (GCRY_MSG_SHOW, GCRY_MSG_WRAP): New.
-       * configure.ac: Use new macros for the feedback.
-
-2013-02-20  Werner Koch  <wk@gnupg.org>
-
-       Fix building of hwf-x86.c.
-       + commit 70dcac663de06b012417015c175973d64e6980df
-       * src/Makefile.am (AM_CFLAGS): Set to GPG_ERROR_CFLAGS
-       (AM_CCASFLAGS): Set NOEXECSTACK_FLAGS.
-
-       Remove build hacks for FreeBSD.
-       + commit fb48ebf7081400a24ee48f8a9894a361e8834b6e
-       * configure.ac [freebsd]: Do not add /usr/local to CPPFLAGS and
-       LDFLAGS.
-
-2013-02-19  Jussi Kivilinna  <jussi.kivilinna@mbnet.fi>
-
-       Rinjdael: Fix use of SSE2 outside USE_AESNI/ctx->use_aesni.
-       + commit 0da77955a097bfd2469ad084b3e9fcac4fb1e3fa
-       * cipher/rijndael.c (_gcry_aes_cbc_enc): Check if AES-NI is enabled before
-       calling aesni_prepare() and aesni_cleanup().
-
-       Add AES-NI/AVX accelerated Camellia implementation.
-       + commit 63ac3ba07dba82fde040d31b90b4eff627bd92b9
-       * configure.ac: Add option --disable-avx-support.
-       (HAVE_GCC_INLINE_ASM_AVX): New.
-       (ENABLE_AVX_SUPPORT): New.
-       (camellia) [ENABLE_AVX_SUPPORT, ENABLE_AESNI_SUPPORT]: Add
-       camellia_aesni_avx_x86-64.lo.
-       * cipher/Makefile.am (AM_CCASFLAGS): Add.
-       (EXTRA_libcipher_la_SOURCES): Add camellia_aesni_avx_x86-64.S
-       * cipher/camellia-glue.c [ENABLE_AESNI_SUPPORT, ENABLE_AVX_SUPPORT]
-       [__x86_64__] (USE_AESNI_AVX): Add macro.
-       (struct Camellia_context) [USE_AESNI_AVX]: Add use_aesni_avx.
-       [USE_AESNI_AVX] (_gcry_camellia_aesni_avx_ctr_enc)
-       (_gcry_camellia_aesni_avx_cbc_dec): New prototypes to assembly
-       functions.
-       (camellia_setkey) [USE_AESNI_AVX]: Enable AES-NI/AVX if hardware
-       support both.
-       (_gcry_camellia_ctr_enc) [USE_AESNI_AVX]: Add AES-NI/AVX code.
-       (_gcry_camellia_cbc_dec) [USE_AESNI_AVX]: Add AES-NI/AVX code.
-       * cipher/camellia_aesni_avx_x86-64.S: New.
-       * src/g10lib.h (HWF_INTEL_AVX): New.
-       * src/global.c (hwflist): Add HWF_INTEL_AVX.
-       * src/hwf-x86.c (detect_x86_gnuc) [ENABLE_AVX_SUPPORT]: Add detection
-       for AVX.
-
-       camellia.c: Prepare for AES-NI/AVX implementation.
-       + commit 4de62d80644228fc5db2a9f9c94a7eb633d8de2e
-       * cipher/camellia-glue.c (CAMELLIA_encrypt_stack_burn_size)
-       (CAMELLIA_decrypt_stack_burn_size): Increase stack burn size.
-       * cipher/camellia.c (CAMELLIA_ROUNDSM): Move key-material mixing in
-       the front.
-       (camellia_setup128, camellia_setup256): Remove now unneeded
-       key-material mangling.
-       (camellia_encrypt128, camellia_decrypt128, amellia_encrypt256)
-       (camellia_decrypt256): Copy block to stack, so that compiler can
-       optimize it for register usage.
-
-       Camellia, prepare glue code for AES-NI/AVX implementation.
-       + commit 537f12ce072d568f9fa344c447d32b2e0efffbe8
-       * cipher/camellia-glue.c (ATTR_ALIGNED_16): Add macro.
-       (CAMELLIA_encrypt_stack_burn_size): Add macro.
-       (camellia_encrypt): Use macro above for stack burn size.
-       (CAMELLIA_decrypt_stack_burn_size): Add macro.
-       (camellia_decrypt): Use macro above for stack burn size.
-       (_gcry_camellia_ctr_enc): New function.
-       (_gcry_camellia_cbc_dec): New function.
-       (selftest_ctr_128): New function.
-       (selftest): Call function above.
-       * cipher/cipher.c (gcry_cipher_open) [USE_CAMELLIA]: Register bulk
-       functions for CBC-decryption and CTR-mode.
-       * src/cipher.h (_gcry_camellia_ctr_enc): New prototype.
-       (_gcry_camellia_cbc_dec): New prototype.
-
-2012-12-21  Werner Koch  <wk@gnupg.org>
-
-       Prepare for hardware feature detection on other platforms.
-       + commit 09ac5d87d11aa0b1fa0e0a4184ab03b3671a73e2
-       * configure.ac (GCRYPT_HWF_MODULES): New.
-       (HAVE_CPU_ARCH_X86, HAVE_CPU_ARCH_ALPHA, HAVE_CPU_ARCH_SPARC)
-       (HAVE_CPU_ARCH_MIPS, HAVE_CPU_ARCH_M68K, HAVE_CPU_ARCH_PPC)
-       (HAVE_CPU_ARCH_ARM): New AC_DEFINEs.
-       * mpi/config.links (mpi_cpu_arch): New.
-       * src/global.c (print_config): Print new tag "cpu-arch".
-       * src/Makefile.am (libgcrypt_la_SOURCES): Add hwf-common.h
-       (EXTRA_libgcrypt_la_SOURCES): New.
-       (gcrypt_hwf_modules): New.
-       (libgcrypt_la_DEPENDENCIES, libgcrypt_la_LIBADD): Add that one.
-       * src/hwfeatures.c: Factor most code out to ...
-       * src/hwf-x86.c: New file.
-       (detect_x86_gnuc): Return the feature vector.
-       (_gcry_hwf_detect_x86): New.
-       * src/hwf-common.h: New.
-       * src/hwfeatures.c (_gcry_detect_hw_features): Dispatch using
-       HAVE_CPU_ARCH_ macros.
-
-2012-12-21  Jussi Kivilinna  <jussi.kivilinna@mbnet.fi>
-
-       Clean up i386/x86-64 cpuid usage in hwfeatures.c.
-       + commit d842eea55e22c05da3959a7a4422b5fcd7884f60
-       * src/hwfeatures.c [__i386__ && __GNUC__] (detect_ia32_gnuc): Remove.
-       [__x86_64__ && __GNUC__] (detect_x86_64_gnuc): Remove.
-       [__i386__ && __GNUC__] (is_cpuid_available, get_cpuid)
-       (HAS_X86_CPUID): New.
-       [__x86_64__ && __GNUC__] (is_cpuid_available, get_cpuid)
-       (HAS_X86_CPUID): New.
-       [HAS_X86_CPUID] (detect_x86_gnuc): New.
-       (_gcry_detect_hw_features) [__i386__ && GNUC]: Remove detect_ia32_gnuc
-       call.
-       (_gcry_detect_hw_features) [__x86_64__ && GNUC]: Remove
-       detect_x86_64_gnuc call.
-       (_gcry_detect_hw_features) [HAS_X86_CPUID]: Add detect_x86_gnuc call.
-
-2012-12-18  Dmitry Kasatkin  <dmitry.kasatkin@intel.com>
-
-       Add support for using DRNG random number generator.
-       + commit efd7002188e6d50013e4d9a920a8b9afa9d210e5
-       * configure.ac: Add option --disable-drng-support.
-       (ENABLE_DRNG_SUPPORT): New.
-       * random/rndhw.c (USE_DRNG): New.
-       (rdrand_long, rdrand_nlong, poll_drng): New.
-       (_gcry_rndhw_poll_fast, _gcry_rndhw_poll_slow): Call poll function.
-       * src/g10lib.h (HWF_INTEL_RDRAND): New.
-       * src/global.c (hwflist): Add "intel-rdrand".
-       * src/hwfeatures.c (detect_x86_64_gnuc) [ENABLE_DRNG_SUPPORT]: Detect
-       RDRAND.
-       (detect_ia32_gnuc) [ENABLE_DRNG_SUPPORT]: Detect RDRAND.
-
-2012-12-03  Werner Koch  <wk@gnupg.org>
-
-       random: Add a RNG selection interface and system RNG wrapper.
-       + commit 7607ab81504ce44060ed0b331d309606f5da1e75
-       * random/random-system.c: New.
-       * random/Makefile.am (librandom_la_SOURCES): Add new module.
-       * random/random.c (struct rng_types): New.
-       (_gcry_set_preferred_rng_type, _gcry_get_rng_type): New.
-       (_gcry_random_initialize, gcry_random_add_bytes, do_randomize)
-       (_gcry_set_random_seed_file, _gcry_update_random_seed_file)
-       (_gcry_fast_random_poll): Dispatch to the actual RNG.
-       * src/gcrypt.h.in (GCRYCTL_SET_PREFERRED_RNG_TYPE): New.
-       GCRYCTL_GET_CURRENT_RNG_TYPE): New.
-       (gcry_rng_types): New.
-       * src/global.c (print_config): Print the TNG type.
-       (global_init, _gcry_vcontrol): Implement the new control codes.
-       * doc/gcrypt.texi (Controlling the library): Document the new control
-       codes.
-
-       * tests/benchmark.c (main): Add options to test the RNG types.
-       * tests/random.c (main): Add new options.
-       (print_hex): Print to stderr.
-       (progress_cb, rng_type): New.
-       (check_rng_type_switching, check_early_rng_type_switching): New.
-       (run_all_rng_tests): New.
-
-       tests: Allow use of random.c under Windows.
-       + commit 76c622e24a07f7c826812be173aa173b4334776b
-       * tests/Makefile.am (TESTS): Always include random.c
-       * tests/random.c [!W32]: Include sys/wait.h.
-       (inf): New.
-       (check_forking, check_nonce_forking): Print a notice what will be done.
-       (main) [W32]: Do not call signal.
-
-       Make random-fips.c work multi-threaded.
-       + commit 75760021b511ba438606af746431223357e7a155
-       * random/random-fips.c (basic_initialization): Fix reversed logic.
-
-       Move nonce creation from csprng backend to random main module.
-       + commit c324644aa14e54fc7051983b38222db32b8ab227
-       * random/random-csprng.c (_gcry_rngcsprng_create_nonce): Remove.
-       (nonce_buffer_lock): Remove.
-       (initialize_basics): Remove init of nonce_buffer_lock.
-       * random/random.c: Add a few header files.
-       (nonce_buffer_lock):  New.
-       (_gcry_random_initialize): Init nonce_buffer_lock.
-       (gcry_create_nonce): Add code from _gcry_rngcsprng_create_nonce.
-
-       * random/random-daemon.c (_gcry_daemon_create_nonce): Remove.
-
-2012-12-03  Jussi Kivilinna  <jussi.kivilinna@mbnet.fi>
-
-       Fix building with CC="gcc -std=c90".
-       + commit f851b9a932ee64fa5a06000d1ac763ba4349f07d
-       * configure.ac: Add check for missing 'asm' keyword in C90 mode and
-       replacement with '__asm__'.
-
-2012-12-03  Werner Koch  <wk@gnupg.org>
-
-       Try to use inttypes.h if stdint.h is not available.
-       + commit d9ec7aec1301b13a89e5c9c54d7ad52e1a29b846
-       * cipher/bufhelp.h [HAVE_INTTYPES_H]: Include inttypes.h
-
-2012-12-03  Jussi Kivilinna  <jussi.kivilinna@mbnet.fi>
-
-       Optimize buffer xoring.
-       + commit 162791bc08f4fc9b3882671e68ecdfd9e130ae59
-       * cipher/Makefile.am (libcipher_la_SOURCES): Add 'bufhelp.h'.
-       * cipher/bufhelp.h: New.
-       * cipher/cipher-aeswrap.c (_gcry_cipher_aeswrap_encrypt)
-       (_gcry_cipher_aeswrap_decrypt): Use 'buf_xor' for buffer xoring.
-       * cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt)
-       (_gcry_cipher_cbc_decrypt): Use 'buf_xor' for buffer xoring and remove
-       resulting unused variables.
-       * cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt) Use 'buf_xor_2dst'
-       for buffer xoring and remove resulting unused variables.
-       (_gcry_cipher_cfb_decrypt): Use 'buf_xor_n_copy' for buffer xoring and
-       remove resulting unused variables.
-       * cipher/cipher-ctr.c (_gcry_cipher_ctr_encrypt): Use 'buf_xor' for
-       buffer xoring and remove resulting unused variables.
-       * cipher/cipher-ofb.c (_gcry_cipher_ofb_encrypt)
-       (_gcry_cipher_ofb_decrypt): Use 'buf_xor' for buffer xoring and remove
-       resulting used variables.
-       * cipher/rijndael.c (_gry_aes_cfb_enc): Use 'buf_xor_2dst' for buffer
-       xoring and remove resulting unused variables.
-       (_gry_aes_cfb_dev): Use 'buf_xor_n_copy' for buffer xoring and remove
-       resulting unused variables.
-       (_gry_aes_cbc_enc, _gry_aes_ctr_enc, _gry_aes_cbc_dec): Use 'buf_xor'
-       for buffer xoring and remove resulting unused variables.
-
-2012-11-29  Jussi Kivilinna  <jussi.kivilinna@mbnet.fi>
-
-       Optimize AES-NI CTR mode.
-       + commit 9ee9e25f519696d509b1a5c1cc04ab0121e98a51
-       * cipher/rijndael.c [USE_AESNI] (do_aesni_ctr, do_aesni_ctr_4): Make
-       handling of 64-bit overflow and carry conditional. Avoid generic to
-       vector register passing of value '1'. Generate and use '-1' instead.
-
-2012-11-28  Werner Koch  <wk@gnupg.org>
-
-       Make a cpp conditional in rijndael.c better readable.
-       + commit 6765e0a8618000d3dc7bda035163e0708c43791b
-       * cipher/rijndael.c (USE_AESNI): Modify cpp conditionals for better
-       readability.
-
-2012-11-28  Jussi Kivilinna  <jussi.kivilinna@mbnet.fi>
-
-       Fix building with Clang on x86-64 and i386.
-       + commit 99e272d938fe23efec25af409bdb91dae0e659e5
-       * cipher/rijndael.c [USE_AESNI] (do_aesni_enc_aligned)
-       (do_aesni_dec_vec4, do_aesni_cfb, do_aesni_ctr, do_aesni_ctr_4): Add
-       explicit suffix to 'cmp' instructions.
-
-2012-11-26  Jussi Kivilinna  <jussi.kivilinna@mbnet.fi>
-
-       Optimize wipememory2 for i386 and x86-64.
-       + commit faec12e23f03c7cd1614594bfdd51f1302cadb42
-       * src/g10lib.h (wipememory2): Add call to fast_wipememory2.
-       (fast_wipememory2): New macros for i386 and x86-64 architectures.
-       Empty macro provided for other architectures.
-
-       Fix missing 64bit carry handling in AES-NI CTR mode.
-       + commit fc37e805c6394c2e635d1a033670be961f36a6d2
-       * cipher/rijndael.c [USE_AESNI] (do_aesni_ctr, do_aesni_ctr_4): Add
-       carry handling to 64-bit addition.
-       (selftest_ctr_128): New function for testing IV handling in bulk CTR
-       function.
-       (selftest): Add call to selftest_ctr_128.
-
-       Add parallelized AES-NI CBC decryption.
-       + commit 35aff0cd43885b5f5c076432ec614698abeb63d8
-       * cipher/rijndael.c [USE_AESNI] (aesni_cleanup_5): New macro.
-       [USE_AESNI] (do_aesni_dec_vec4): New function.
-       (_gcry_aes_cbc_dec) [USE_AESNI]: Add parallelized CBC loop.
-       (_gcry_aes_cbc_dec) [USE_AESNI]: Change IV storage register from xmm3
-       to xmm5.
-
-       Clear xmm5 after use in AES-NI CTR mode.
-       + commit 5acd0e5ae2a58dda51c2b56c879b80a1a6d2c42f
-       * cipher/rijndael.c [USE_AESNI]: Rename aesni_cleanup_2_4 to
-       aesni_cleanup_2_5.
-       [USE_AESNI] (aesni_cleanup_2_5): Clear xmm5 register.
-       (_gcry_aes_ctr_enc, _gcry_aes_cbc_dec) [USE_AESNI]: Use
-       aesni_cleanup_2_5 instead of aesni_cleanup_2_4.
-
-       Optimize AES-NI CBC encryption.
-       + commit be3768994ad362dfc849a8cd0146b4c9bb287d20
-       * cipher/rijndeal.c (_gcry_aes_cbc_enc) [USE_AESNI]: Add AES-NI
-       spesific loop and use SSE2 assembler for xoring and copying of
-       blocks.
-
-       Improve parallelizability of CBC decryption for AES-NI.
-       + commit 3369d960158ab4231b83926a0f982e2a8819f173
-       * cipher/rijndael.c (_gcry_aes_cbc_dec) [USE_AESNI]: Add AES-NI
-       specific CBC mode loop with temporary block and IV stored in free SSE
-       registers.
-
-       Extend test of chained modes for 128bit ciphers.
-       + commit 55b96be08531664ed3f4230acebe0f45954bbc33
-       * tests/basic.c (check_one_cipher_core, check_one_cipher): Increase
-       input and output buffer sizes from 16 bytes to 1024+16=1040 bytes.
-       (check_one_cipher_core): Add asserts to verify sizes of temporary
-       buffers.
-
-2012-11-21  Werner Koch  <wk@gnupg.org>
-
-       Fix for strict aliasing rules.
-       + commit dfb4673da8ee52d95e0a62c9f49ca8599943f22e
-       * cipher/rijndael.c (do_setkey, prepare_decryption): Use u32_a_t for
-       casting.
-
-       Do not detect AES-NI support if disabled by configure.
-       + commit 3047795794eb238aa684bd0729acf64c82a19e09
-       * src/hwfeatures.c (detect_ia32_gnuc): Detect AESNI support only if
-       that support has been enabled.
-
-2012-11-21  Jussi Kivilinna  <jussi.kivilinna@mbnet.fi>
-
-       Fix too large burn_stack in camellia-glue.c.
-       + commit 8afabc2813948778a3db52d9dee9a041a3dd50d4
-       * cipher/camellia-glue.c (camellia_encrypt, camellia_decrypt): Do not
-       take full array size of KEY_TABLE_TYPE, but argument size instead.
-
-       Add x86_64 support for AES-NI.
-       + commit d8bdfa42ed582655c180e7db9b16d4e756a12a6e
-       * cipher/rijndael.c [ENABLE_AESNI_SUPPORT]: Enable USE_AESNI on x86-64.
-       (do_setkey) [USE_AESNI_is_disabled_here]: Use %[key] and %[ksch]
-       directly as registers instead of using temporary register %%esi.
-       [USE_AESNI] (do_aesni_enc_aligned, do_aesni_dec_aligned, do_aesni_cfb,
-       do_aesni_ctr, do_aesni_ctr_4): Use %[key] directly as register instead
-       of using temporary register %%esi.
-       [USE_AESNI] (do_aesni_cfb, do_aesni_ctr, do_aesni_ctr_4): Change %[key]
-       from generic "g" type to register "r".
-       * src/hwfeatures.c (_gcry_detect_hw_features) [__x86_64__]: Do not
-       clear AES-NI feature flag.
-
-       Fix cpuid vendor-id check for i386 and x86-64.
-       + commit 9e1552517f68459a165ddebbba85e7cf37ff4f0c
-       * src/hwfeatures.c (detect_x86_64_gnuc, detect_ia32_gnuc): Allow
-       Intel features be detect from CPU by other vendors too.
-
-       Fix hwdetect assembler clobbers.
-       + commit 19b9efd1f47a5de9c450ce8212dfa3174a029c7a
-       * src/hwfeatures.c (detect_x86_64_gnuc): Add missing %ebx assembler
-       clobbers.
-       (detect_x86_64_gnuc, detect_ia32_gnuc) [ENABLE_PADLOCK_SUPPORT]: Add
-       missing %ecx assembler clobbers.
-
-2012-11-21  Werner Koch  <wk@gnupg.org>
-
-       Use configure test for aligned attribute.
-       + commit 6368ed542150956ff4ba8170a15bbc534143675c
-       * configure.ac (HAVE_GCC_ATTRIBUTE_ALIGNED): New test and ac_define.
-       * cipher/cipher-internal.h, cipher/rijndael.c, random/rndhw.c: Use new
-       macro instead of a fixed test for __GNUC__.
-
-       Fix segv with AES-NI on some platforms.
-       + commit a96974de734beb51a733a89b3283bcf7b433b54c
-       * cipher/rijndael.c (RIJNDAEL_context): Align on 16 bytes.
-
-2012-11-16  Werner Koch  <wk@gnupg.org>
-
-       Improve parsing of the GIT revision number.
-       + commit 4b18e530f417d4af401a3fd721ad2a07e5310e3e
-       * configure.ac (mmm4_revision): Use git rev-parse.
-
-2012-11-08  Werner Koch  <wk@gnupg.org>
-
-       Fix extern inline use for gcc > 4.3 in c99 mode.
-       + commit 5abc06114e91beca0177331e1c79815f5fb6d7be
-       * mpi/mpi-inline.h [!G10_MPI_INLINE_DECL]: Take care of changed extern
-       inline semantics in gcc.
-
-2012-11-07  Werner Koch  <wk@gnupg.org>
-
-       Fix memory leak in gcry_pk_testkey for ECC.
-       + commit 8cbbad5f94f6e0429fffe66d689aea20f7e35957
-       * cipher/ecc.c (check_secret_key): Restructure for easier allocation
-       tracking.  Fix memory leak.
-
-2012-11-05  Werner Koch  <wk@gnupg.org>
-
-       Prepare for a backported interface in 1.5.1.
-       + commit 7af98ef78d45e813f47ae4e180a02757a379953f
-       * configure.ac: Bump LT version at C20/A0/R0 to adjust for a planned
-       API update in 1.5.1.
-
-       Adjust for stricter autoconf requirements.
-       + commit 1241fbbc896e9bbad68f1007a17b20493f6cd1af
-       * configure.ac: Fix usage of AC_LANG_PROGRAM.
-
-       Update build helper scripts.
-       + commit a5c4d45e8d12737cd21b095c81da5c18e2afc39e
-       * config.guess, config.sub: Update to version 2012-07-31.
-       * ltmain.sh: Update to version 2.4.2.
-       * install-sh, m4/libtool.m4, m4/ltoptions.m4, m4/ltversion.m4
-       * m4/lt~obsolete.m4: Update to autoconf 2.69 versions.
-
-       Do not distribute a copy of gitlog-to-changelog.
-       + commit 40976d7da5420453bf93a9c99f0cc4c7044d0774
-       * Makefile.am (GITLOG_TO_CHANGELOG): New.
-       (gen-ChangeLog): Require an installed gitlog-to-changelog.
-       * scripts/gitlog-to-changelog: Remove.
-
-       * README.SVN: Remove.
-       * REMOVE.GIT: New.
-
-       Allow building with w64-mingw32.
-       + commit 4f6fb150558d0ed250bfbd50352c258a4456ba50
-       * autogen.sh <--build-w32>: Support the w64-mingw32 toolchain.  Also
-       prepare for 64 bit building.
-       <git-setup>: Remove option -c from chmod.
-
-       Switch to the new automagic beta numbering scheme.
-       + commit 7d5195be76d9dd4adc28976ad153e8f7761c5855
-       * configure.ac: Add all the required m4 magic.
-
-       Avoid dereferencing pointer right after the end.
-       + commit 79502e2c1982047dcf2b776f52826f38bbd9b1fe
-       * mpi/mpicoder.c (do_get_buffer): Check the length before derefing P.
-
-2012-10-30  Werner Koch  <wk@gnupg.org>
-
-       Make ancient test program useful again.
-       + commit 66adf76e634423bb72ce1f0b5ed78f4e4798f190
-       * tests/testapi.c (test_sexp): Adjust to current API.  Print the
-       return code.  Mark unused args.
-       (test_genkey): Mark unused args.
-       (main): Do not pass NULL to printf.
-
-       tests: Add ECC key generation tests.
-       + commit c13164884ade6b1e945cddacce2d244fd881de6b
-       * tests/keygen.c (check_generated_ecc_key): New.
-       (check_ecc_keys): New.
-       (main): Call simple ECC checks.
-
-2012-10-30  Milan Broz  <mbroz@redhat.com>
-
-       PBKDF2: Allow empty passphrase.
-       + commit 8528f1ba40e587dc17e02822e529fbd7ac69a189
-       * cipher/kdf.c (gcry_kdf_derive): Allow empty passphrase for PBKDF2.
-       * tests/t-kdf.c (check_pbkdf2): Add test case for above.
-
-2012-08-16  Xi Wang  <xi.wang@gmail.com>
-
-       Replace deliberate division by zero with _gcry_divide_by_zero.
-       + commit 2c54c4da19d3a79e9f749740828026dd41f0521a
-       * mpi/mpi-pow.c: Replace 1 / msize.
-       * mpi/mpih-div.c: Replace 1 / dsize.
-       * src/misc.c: Add _gcry_divide_by_zero.
-
-2012-06-21  Werner Koch  <wk@gnupg.org>
-
-       Clear AESNI feature flag for x86_64.
-       + commit 2196728e2252917849c1be94417258076767021b
-       * src/hwfeatures.c (_gcry_detect_hw_features) [__x86_64__]: Clear
-       AESNI feature flag.
-
-       Beautify last change.
-       + commit 20e423212c9710ee663e12dd0f62580ceb245a6f
-       * cipher/rijndael.c: Replace C99 feature from last patch.  Keep cpp
-       lines short.
-       * random/rndhw.c: Keep cpp lines short.
-       * src/hwfeatures.c (_gcry_detect_hw_features): Make cpp def chain
-       better readable.
-
-2012-06-21  Rafaël Carré  <funman@videolan.org>
-
-       Enable VIA Padlock on x86_64 platforms.
-       + commit baf0dc7e9c26167ab43ba2adebcf2f1abc9d9b3b
-         * cipher/rijndael.c: Duplicate x86 assembly and convert to x86_64.
-         * random/rndhw.c: Likewise.
-         * src/hwfeatures.c: Likewise.
-
-2012-05-14  Werner Koch  <wk@gnupg.org>
-
-       Add curve aliases from RFC-5656.
-       + commit 39c123b729a472ace039f8536d07f8b9a5f4675a
-       * cipher/ecc.c (curve_aliases): Add "nistp???" entries.
-
-2012-04-16  Werner Koch  <wk@gnupg.org>
-
-       State new contribution rules.
-       + commit 3bb858551cd5d84e43b800edfa2b07d1529718a9
-       * doc/DCO: New.
-       * doc/HACKING: Document new rules.
-
-2012-04-04  Tomas Mraz  <tmraz@fedoraproject.org>
-
-       Add GCRYCTL_SET_ENFORCED_FIPS_FLAG command.
-       + commit 90e49a11733bfba9c3c505ac487282d35757f682
-       * doc/gcrypt.texi: Add documentation of the new command.
-       * src/fips.c (_gcry_enforced_fips_mode): Report the enforced fips mode
-       only when fips mode is enabled.
-       (_gcry_set_enforced_fips_mode): New function.
-       * src/g10lib.h: Add the _gcry_set_enforced_fips_mode prototype.
-       * src/gcrypt.h.in: Add the GCRYCTL_SET_ENFORCED_FIPS_FLAG.
-       * src/global.c (_gcry_vcontrol): Handle the new command.
-
-2012-02-17  Ulrich Müller  <ulm@gentoo.org>
-
-       Rework selftest in idea.c.
-       + commit 70cca617ed75ea292e1fed769114dda5cc1d76f1
-       * cipher/idea.c (do_setkey): Execute selftest when first called.
-       (decrypt_block): Remove commented-out code.
-       (selftest): Execute all selftests. Return NULL on success, or
-       string in case of error.
-
-2012-02-16  Werner Koch  <wk@gnupg.org>
-
-       Fix missing prototype.
-       + commit 46035d28c9b413851d43a4008fdc8e4cdf5d686b
-       * src/g10lib.h (_gcry_secmem_module_init): Make it a real prototype.
-
-2012-02-16  Ulrich Müller  <ulm@gentoo.org>
-
-       Add support for the IDEA cipher.
-       + commit 318fd85f377c060908d371f792d41e599b3b7483
-       Adapt idea.c to the Libgcrypt framework.
-       Add IDEA to cipher_table and to the build system.
-
-       Patents on IDEA have expired:
-         Europe: EP0482154 on 2011-05-16,
-         Japan:  JP3225440 on 2011-05-16,
-         U.S.:   5,214,703 on 2012-01-07.
-
-       * configure.ac: Add idea to the list of available ciphers.
-       Define USE_IDEA if idea is enabled.
-       * cipher/cipher.c (cipher_table): Add entry for IDEA.
-       * cipher/idea.c: Update comment about patents.
-       Include proper header files and remove redundant declarations.
-       (expand_key, cipher, do_setkey, encrypt_block, decrypt_block):
-       Define function arguments as const where appropriate.
-       (cipher): Test for !WORDS_BIGENDIAN instead of LITTLE_ENDIAN_HOST.
-       (do_setkey, decrypt_block): Don't call selftest.
-       (idea_setkey): New function, wrapper for do_setkey.
-       (idea_encrypt): New function, wrapper for encrypt_block.
-       (_gcry_cipher_spec_idea): Define.
-       * cipher/Makefile.am (EXTRA_libcipher_la_SOURCES): Add idea.c.
-       * src/cipher.h (_gcry_cipher_spec_idea): Declare.
-       * tests/basic.c (check_ciphers): Add GCRY_CIPHER_IDEA.
-
-2012-01-09  Werner Koch  <wk@gnupg.org>
-
-       Include an IDEA implementation.
-       + commit 6078b05f5340d886e0b9e6cee1d9b5043e0cb210
-       The code is the old IDEA test code, written by me back in 1997 and
-       distributed on a Danish FTP server.  This commit is only for
-       reference.  To use the code it has to be adjusted to the Libgcrypt
-       framework.
-
-2012-01-03  Marcus Brinkmann  <marcus.brinkmann@ruhr-uni-bochum.de>
-
-       Fix pthread locking and remove defunctional support for static lock init.
-       + commit 38fcd59ce774eaa3d65f2f7534c989afd860eb56
-       * src/ath.c: Include assert.h.
-       (ath_mutex_destroy, ath_mutex_lock, ath_mutex_unlock): Dereference LOCK.
-       * src/g10lib.h (_gcry_secmem_module_init): New declaration.
-       * src/global.c (global_init): Call _gcry_secmem_module_init.
-       * src/secmem.c (_gcry_secmem_module_init): New function.
-
-2011-12-16  Werner Koch  <wk@gnupg.org>
-
-       Add alignment tests for the cipher tests.
-       + commit 14cf1f7e338fedb8edaff5631441746605152bd6
-       * tests/basic.c (check_one_cipher): Factor most code out to
-       check_one_cipher_core.  Call that core function several times using
-       different alignment settings.
-       (check_one_cipher_core): New.  Add extra args to allow alignment
-       testing.
-
-2011-12-07  Werner Koch  <wk@gnupg.org>
-
-       tests/prime: Add option to create a well known private key.
-       + commit 16f5654643d584e3bc739b636752d779176b2191
-       * tests/prime.c (print_mpi, create_42prime): New.
-       (main): Add option --42.
-
-2011-12-01  Werner Koch  <wk@gnupg.org>
-
-       Do not build the random-daemon by make distcheck.
-       + commit ea1fb538d99f1ec093f2fef86f4f29176ec27826
-       * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Disable building of the
-       random daemon
-
-       Generate the ChangeLog from commit logs.
-       + commit 137d73191c904926ba529376144ee8239af4ca02
-       * scripts/gitlog-to-changelog: New script.  Taken from gnulib.
-       * scripts/git-log-fix: New file.
-       * scripts/git-log-footer: New file.
-       * doc/HACKING: Describe the ChangeLog policy
-       * ChangeLog: New file.
-       * Makefile.am (EXTRA_DIST): Add new files.
-       (gen-ChangeLog): New.
-       (dist-hook): Run gen-ChangeLog.
-
-       Rename all ChangeLog files to ChangeLog-2011.
-
-2011-12-01  Werner Koch  <wk@gnupg.org>
-
-       NB: Changes done before December 1st, 2011 are described in
-       per directory files named ChangeLog-2011.  See doc/HACKING for
-       details.
-
-        -----
-       Copyright (C) 2011 Free Software Foundation, Inc.
-
-       Copying and distribution of this file and/or the original GIT
-       commit log messages, with or without modification, are
-       permitted provided the copyright notice and this notice are
-       preserved.
+Local Variables:
+buffer-read-only: t
+mode: text
+End:
index f6733a6..8be7fb2 100644 (file)
--- a/LICENSES
+++ b/LICENSES
@@ -18,6 +18,7 @@ with any binary distributions derived from the GNU C Library.
   - cipher/sha512-avx-amd64.S
   - cipher/sha512-avx2-bmi2-amd64.S
   - cipher/sha512-ssse3-amd64.S
+  - cipher/sha512-ssse3-i386.c
 
 #+begin_quote
   Copyright (c) 2012, Intel Corporation
@@ -54,49 +55,97 @@ with any binary distributions derived from the GNU C Library.
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #+end_quote
 
-
   For files:
   - random/jitterentropy-base.c
+  - random/jitterentropy-gcd.c
+  - random/jitterentropy-gcd.h
+  - random/jitterentropy-health.c
+  - random/jitterentropy-health.h
+  - random/jitterentropy-noise.c
+  - random/jitterentropy-noise.h
+  - random/jitterentropy-sha3.c
+  - random/jitterentropy-sha3.h
+  - random/jitterentropy-timer.c
+  - random/jitterentropy-timer.h
   - random/jitterentropy.h
   - random/rndjent.c (plus common Libgcrypt copyright holders)
 
 #+begin_quote
- * Copyright Stephan Mueller <smueller@chronox.de>, 2013
- *
- * License
- * =======
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, and the entire permission notice in its entirety,
- *    including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
- *
- * ALTERNATIVELY, this product may be distributed under the terms of
- * the GNU General Public License, in which case the provisions of the GPL are
- * required INSTEAD OF the above restrictions.  (This clause is
- * necessary due to a potential bad interaction between the GPL and
- * the restrictions contained in a BSD-style copyright.)
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
+ Copyright (C) 2017 - 2021, Stephan Mueller <smueller@chronox.de>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, and the entire permission notice in its entirety,
+    including the disclaimer of warranties.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote
+    products derived from this software without specific prior
+    written permission.
+
+ ALTERNATIVELY, this product may be distributed under the terms of
+ the GNU General Public License, in which case the provisions of the GPL2
+ are required INSTEAD OF the above restrictions.  (This clause is
+ necessary due to a potential bad interaction between the GPL and
+ the restrictions contained in a BSD-style copyright.)
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
+#+end_quote
+
+  For files:
+  - cipher/cipher-gcm-ppc.c
+
+#+begin_quote
+ Copyright (c) 2006, CRYPTOGAMS by <appro@openssl.org>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+       * Redistributions of source code must retain copyright notices,
+         this list of conditions and the following disclaimer.
+
+       * Redistributions in binary form must reproduce the above
+         copyright notice, this list of conditions and the following
+         disclaimer in the documentation and/or other materials
+         provided with the distribution.
+
+       * Neither the name of the CRYPTOGAMS nor the names of its
+         copyright holder and contributors may be used to endorse or
+         promote products derived from this software without specific
+         prior written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this
+ product may be distributed under the terms of the GNU General Public
+ License (GPL), in which case the provisions of the GPL apply INSTEAD OF
+ those given above.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #+end_quote
 
 * X License
index 452cb96..77355d1 100644 (file)
 # License along with this program; if not, see <http://www.gnu.org/licenses/>.
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
-# Location of the released tarball archives.  Note that this is an
-# internal archive and before uploading this to the public server,
-# manual tests should be run and the git release tagged and pushed.
-# Adjust as needed.
-RELEASE_ARCHIVE_DIR  = wk@vigenere:tarballs/libgpg-error/
-# The key used to sign the released sources.  Adjust as needed.
-RELEASE_SIGNING_KEY  = D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
+# Location of the released tarball archives.  This is prefixed by
+# the variable RELEASE_ARCHIVE in ~/.gnupg-autogen.rc.  For example:
+# RELEASE_ARCHIVE=wk@somehost:archive/tarballs
+RELEASE_ARCHIVE_SUFFIX  = libgcrypt/v1.10
+# The variable RELEASE_SIGNING_KEY in ~/.gnupg-autogen.rc is used
+# to specify the key for signing.  For example:
+# RELEASE_SIGNKEY=D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
 
 
 ACLOCAL_AMFLAGS = -I m4
+AM_DISTCHECK_DVI_TARGET = pdf
 DISTCHECK_CONFIGURE_FLAGS = --disable-random-daemon --enable-doc \
                             --enable-random=auto
 
@@ -47,14 +48,12 @@ EXTRA_DIST = autogen.sh autogen.rc README.GIT LICENSES                         \
              ChangeLog-2011 build-aux/ChangeLog-2011 doc/ChangeLog-2011    \
              m4/ChangeLog-2011 cipher/ChangeLog-2011 src/ChangeLog-2011    \
              random/ChangeLog-2011 tests/ChangeLog-2011 mpi/ChangeLog-2011 \
-             build-aux/git-log-footer build-aux/git-log-fix
+             build-aux/git-log-footer build-aux/git-log-fix VERSION
 
 DISTCLEANFILES =
 
 
-# Add all the files listed in "distfiles" files to the distribution,
-# apply version number s to some files and create a VERSION file which
-# we need for the Prereq: patch file trick.
+# Add all the files listed in "distfiles" files to the distribution
 dist-hook: gen-ChangeLog
        @set -e; \
         for file in `cd $(top_srcdir); \
@@ -65,8 +64,6 @@ dist-hook: gen-ChangeLog
                || cp -p $(top_srcdir)/$$dir/$$i $(distdir)/$$dir/$$i; \
            done ; \
        done
-       @set -e; \
-       echo "$(VERSION)" > $(distdir)/VERSION
 
 distcheck-hook:
        set -e; ( \
@@ -127,7 +124,19 @@ release:
 
 sign-release:
         +(set -e; \
-         cd dist; \
+         test $$(pwd | sed 's,.*/,,') = dist || cd dist; \
+         x=$$(grep '^RELEASE_ARCHIVE=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
+          if [ -z "$$x" ]; then \
+             echo "error: RELEASE_ARCHIVE missing in ~/.gnupg-autogen.rc">&2; \
+             exit 2;\
+          fi;\
+          myarchive="$$x/$(RELEASE_ARCHIVE_SUFFIX)";\
+         x=$$(grep '^RELEASE_SIGNKEY=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
+          if [ -z "$$x" ]; then \
+             echo "error: RELEASE_SIGNKEY missing in ~/.gnupg-autogen.rc">&2; \
+             exit 2;\
+          fi;\
+         mysignkey="$$x";\
          files1="$(RELEASE_NAME).tar.bz2 \
                  $(RELEASE_NAME).tar.gz" ; \
          files2="$(RELEASE_NAME).tar.bz2.sig \
@@ -135,15 +144,15 @@ sign-release:
                  $(RELEASE_NAME).swdb \
                  $(RELEASE_NAME).buildlog" ;\
          echo "/* Signing the source tarball ..." ;\
-         gpg -sbu $(RELEASE_SIGNING_KEY) $(RELEASE_NAME).tar.bz2 ;\
-         gpg -sbu $(RELEASE_SIGNING_KEY) $(RELEASE_NAME).tar.gz  ;\
+         gpg -sbu $$mysignkey $(RELEASE_NAME).tar.bz2 ;\
+         gpg -sbu $$mysignkey $(RELEASE_NAME).tar.gz  ;\
          cat $(RELEASE_NAME).swdb >swdb.snippet;\
          echo >>swdb.snippet ;\
          sha1sum $${files1} >>swdb.snippet ;\
           cat "../$(RELEASE_NAME).buildlog" swdb.snippet \
                | gzip >$(RELEASE_NAME).buildlog ;\
-          echo "Copying to local archive ..." ;\
-         scp -p $${files1} $${files2} $(RELEASE_ARCHIVE_DIR)/ || true;\
+          echo "Copying to archive $$myarchive ..." ;\
+         scp -p $${files1} $${files2} $${myarchive}/ || true;\
          echo '/*' ;\
          echo ' * All done; for checksums see dist/swdb.snippet' ;\
          echo ' */' ;\
diff --git a/Makefile.in b/Makefile.in
deleted file mode 100644 (file)
index 5bdfbdc..0000000
+++ /dev/null
@@ -1,994 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Copyright (C) 1992, 1999, 2000, 2002 Free Software Foundation, Inc.
-#
-# 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 <http://www.gnu.org/licenses/>.
-# SPDX-License-Identifier: LGPL-2.1-or-later
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = .
-DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
-       $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-       $(top_srcdir)/configure $(am__configure_deps) \
-       $(srcdir)/config.h.in COPYING COPYING.LIB THANKS TODO \
-       build-aux/compile build-aux/config.guess \
-       build-aux/config.rpath build-aux/config.sub build-aux/depcomp \
-       build-aux/install-sh build-aux/mdate-sh build-aux/missing \
-       mkinstalldirs build-aux/texinfo.tex build-aux/ltmain.sh \
-       $(top_srcdir)/build-aux/compile \
-       $(top_srcdir)/build-aux/config.guess \
-       $(top_srcdir)/build-aux/config.sub \
-       $(top_srcdir)/build-aux/install-sh \
-       $(top_srcdir)/build-aux/ltmain.sh \
-       $(top_srcdir)/build-aux/missing
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
- configure.lineno config.status.lineno
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-SOURCES =
-DIST_SOURCES =
-RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
-       ctags-recursive dvi-recursive html-recursive info-recursive \
-       install-data-recursive install-dvi-recursive \
-       install-exec-recursive install-html-recursive \
-       install-info-recursive install-pdf-recursive \
-       install-ps-recursive install-recursive installcheck-recursive \
-       installdirs-recursive pdf-recursive ps-recursive \
-       tags-recursive uninstall-recursive
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
-  distclean-recursive maintainer-clean-recursive
-am__recursive_targets = \
-  $(RECURSIVE_TARGETS) \
-  $(RECURSIVE_CLEAN_TARGETS) \
-  $(am__extra_recursive_targets)
-AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
-       cscope distdir dist dist-all distcheck
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
-       $(LISP)config.h.in
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-CSCOPE = cscope
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-distdir = $(PACKAGE)-$(VERSION)
-top_distdir = $(distdir)
-am__remove_distdir = \
-  if test -d "$(distdir)"; then \
-    find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
-      && rm -rf "$(distdir)" \
-      || { sleep 5 && rm -rf "$(distdir)"; }; \
-  else :; fi
-am__post_remove_distdir = $(am__remove_distdir)
-am__relativize = \
-  dir0=`pwd`; \
-  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
-  sed_rest='s,^[^/]*/*,,'; \
-  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
-  sed_butlast='s,/*[^/]*$$,,'; \
-  while test -n "$$dir1"; do \
-    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
-    if test "$$first" != "."; then \
-      if test "$$first" = ".."; then \
-        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
-        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
-      else \
-        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
-        if test "$$first2" = "$$first"; then \
-          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
-        else \
-          dir2="../$$dir2"; \
-        fi; \
-        dir0="$$dir0"/"$$first"; \
-      fi; \
-    fi; \
-    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
-  done; \
-  reldir="$$dir2"
-DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
-GZIP_ENV = --best
-DIST_TARGETS = dist-bzip2 dist-gzip
-distuninstallcheck_listfiles = find . -type f -print
-am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
-  | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
-distcleancheck_listfiles = find . -type f -print
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-
-# Location of the released tarball archives.  Note that this is an
-# internal archive and before uploading this to the public server,
-# manual tests should be run and the git release tagged and pushed.
-# Adjust as needed.
-RELEASE_ARCHIVE_DIR = wk@vigenere:tarballs/libgpg-error/
-# The key used to sign the released sources.  Adjust as needed.
-RELEASE_SIGNING_KEY = D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
-ACLOCAL_AMFLAGS = -I m4
-DISTCHECK_CONFIGURE_FLAGS = --disable-random-daemon --enable-doc \
-                            --enable-random=auto
-
-
-# (A suitable gitlog-to-changelog script can be found in GnuPG master.)
-GITLOG_TO_CHANGELOG = gitlog-to-changelog
-@BUILD_DOC_FALSE@doc = 
-@BUILD_DOC_TRUE@doc = doc
-DIST_SUBDIRS = m4 compat mpi cipher random src doc tests
-SUBDIRS = compat mpi cipher random src $(doc) tests
-EXTRA_DIST = autogen.sh autogen.rc README.GIT LICENSES                    \
-             ChangeLog-2011 build-aux/ChangeLog-2011 doc/ChangeLog-2011    \
-             m4/ChangeLog-2011 cipher/ChangeLog-2011 src/ChangeLog-2011    \
-             random/ChangeLog-2011 tests/ChangeLog-2011 mpi/ChangeLog-2011 \
-             build-aux/git-log-footer build-aux/git-log-fix
-
-DISTCLEANFILES = 
-gen_start_date = 2011-12-01T14:00:00
-
-# Macro to help the release target.
-RELEASE_NAME = $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)
-all: config.h
-       $(MAKE) $(AM_MAKEFLAGS) all-recursive
-
-.SUFFIXES:
-am--refresh: Makefile
-       @:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
-             $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
-               && exit 0; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           echo ' $(SHELL) ./config.status'; \
-           $(SHELL) ./config.status;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       $(SHELL) ./config.status --recheck
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       $(am__cd) $(srcdir) && $(AUTOCONF)
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
-$(am__aclocal_m4_deps):
-
-config.h: stamp-h1
-       @test -f $@ || rm -f stamp-h1
-       @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
-
-stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
-       @rm -f stamp-h1
-       cd $(top_builddir) && $(SHELL) ./config.status config.h
-$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
-       ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
-       rm -f stamp-h1
-       touch $@
-
-distclean-hdr:
-       -rm -f config.h stamp-h1
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-
-distclean-libtool:
-       -rm -f libtool config.lt
-
-# This directory's subdirectories are mostly independent; you can cd
-# into them and run 'make' without going through this Makefile.
-# To change the values of 'make' variables: instead of editing Makefiles,
-# (1) if the variable is set in 'config.status', edit 'config.status'
-#     (which will cause the Makefiles to be regenerated when you run 'make');
-# (2) otherwise, pass the desired values on the 'make' command line.
-$(am__recursive_targets):
-       @fail=; \
-       if $(am__make_keepgoing); then \
-         failcom='fail=yes'; \
-       else \
-         failcom='exit 1'; \
-       fi; \
-       dot_seen=no; \
-       target=`echo $@ | sed s/-recursive//`; \
-       case "$@" in \
-         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
-         *) list='$(SUBDIRS)' ;; \
-       esac; \
-       for subdir in $$list; do \
-         echo "Making $$target in $$subdir"; \
-         if test "$$subdir" = "."; then \
-           dot_seen=yes; \
-           local_target="$$target-am"; \
-         else \
-           local_target="$$target"; \
-         fi; \
-         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
-         || eval $$failcom; \
-       done; \
-       if test "$$dot_seen" = "no"; then \
-         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
-       fi; test -z "$$fail"
-
-ID: $(am__tagged_files)
-       $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-recursive
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       set x; \
-       here=`pwd`; \
-       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
-         include_option=--etags-include; \
-         empty_fix=.; \
-       else \
-         include_option=--include; \
-         empty_fix=; \
-       fi; \
-       list='$(SUBDIRS)'; for subdir in $$list; do \
-         if test "$$subdir" = .; then :; else \
-           test ! -f $$subdir/TAGS || \
-             set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
-         fi; \
-       done; \
-       $(am__define_uniq_tagged_files); \
-       shift; \
-       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-         test -n "$$unique" || unique=$$empty_fix; \
-         if test $$# -gt 0; then \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             "$$@" $$unique; \
-         else \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             $$unique; \
-         fi; \
-       fi
-ctags: ctags-recursive
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       $(am__define_uniq_tagged_files); \
-       test -z "$(CTAGS_ARGS)$$unique" \
-         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$unique
-
-GTAGS:
-       here=`$(am__cd) $(top_builddir) && pwd` \
-         && $(am__cd) $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) "$$here"
-cscope: cscope.files
-       test ! -s cscope.files \
-         || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
-clean-cscope:
-       -rm -f cscope.files
-cscope.files: clean-cscope cscopelist
-cscopelist: cscopelist-recursive
-
-cscopelist-am: $(am__tagged_files)
-       list='$(am__tagged_files)'; \
-       case "$(srcdir)" in \
-         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-         *) sdir=$(subdir)/$(srcdir) ;; \
-       esac; \
-       for i in $$list; do \
-         if test -f "$$i"; then \
-           echo "$(subdir)/$$i"; \
-         else \
-           echo "$$sdir/$$i"; \
-         fi; \
-       done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-       -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
-
-distdir: $(DISTFILES)
-       $(am__remove_distdir)
-       test -d "$(distdir)" || mkdir "$(distdir)"
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
-         if test "$$subdir" = .; then :; else \
-           $(am__make_dryrun) \
-             || test -d "$(distdir)/$$subdir" \
-             || $(MKDIR_P) "$(distdir)/$$subdir" \
-             || exit 1; \
-           dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
-           $(am__relativize); \
-           new_distdir=$$reldir; \
-           dir1=$$subdir; dir2="$(top_distdir)"; \
-           $(am__relativize); \
-           new_top_distdir=$$reldir; \
-           echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
-           echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
-           ($(am__cd) $$subdir && \
-             $(MAKE) $(AM_MAKEFLAGS) \
-               top_distdir="$$new_top_distdir" \
-               distdir="$$new_distdir" \
-               am__remove_distdir=: \
-               am__skip_length_check=: \
-               am__skip_mode_fix=: \
-               distdir) \
-             || exit 1; \
-         fi; \
-       done
-       $(MAKE) $(AM_MAKEFLAGS) \
-         top_distdir="$(top_distdir)" distdir="$(distdir)" \
-         dist-hook
-       -test -n "$(am__skip_mode_fix)" \
-       || find "$(distdir)" -type d ! -perm -755 \
-               -exec chmod u+rwx,go+rx {} \; -o \
-         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
-         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
-         ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
-       || chmod -R a+r "$(distdir)"
-dist-gzip: distdir
-       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
-       $(am__post_remove_distdir)
-dist-bzip2: distdir
-       tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
-       $(am__post_remove_distdir)
-
-dist-lzip: distdir
-       tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
-       $(am__post_remove_distdir)
-
-dist-xz: distdir
-       tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
-       $(am__post_remove_distdir)
-
-dist-tarZ: distdir
-       @echo WARNING: "Support for shar distribution archives is" \
-                      "deprecated." >&2
-       @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
-       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
-       $(am__post_remove_distdir)
-
-dist-shar: distdir
-       @echo WARNING: "Support for distribution archives compressed with" \
-                      "legacy program 'compress' is deprecated." >&2
-       @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
-       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
-       $(am__post_remove_distdir)
-
-dist-zip: distdir
-       -rm -f $(distdir).zip
-       zip -rq $(distdir).zip $(distdir)
-       $(am__post_remove_distdir)
-
-dist dist-all:
-       $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
-       $(am__post_remove_distdir)
-
-# This target untars the dist file and tries a VPATH configuration.  Then
-# it guarantees that the distribution is self-contained by making another
-# tarfile.
-distcheck: dist
-       case '$(DIST_ARCHIVES)' in \
-       *.tar.gz*) \
-         GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
-       *.tar.bz2*) \
-         bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
-       *.tar.lz*) \
-         lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
-       *.tar.xz*) \
-         xz -dc $(distdir).tar.xz | $(am__untar) ;;\
-       *.tar.Z*) \
-         uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
-       *.shar.gz*) \
-         GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
-       *.zip*) \
-         unzip $(distdir).zip ;;\
-       esac
-       chmod -R a-w $(distdir)
-       chmod u+w $(distdir)
-       mkdir $(distdir)/_build $(distdir)/_inst
-       chmod a-w $(distdir)
-       test -d $(distdir)/_build || exit 0; \
-       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
-         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
-         && $(MAKE) $(AM_MAKEFLAGS) distcheck-hook \
-         && am__cwd=`pwd` \
-         && $(am__cd) $(distdir)/_build \
-         && ../configure \
-           $(AM_DISTCHECK_CONFIGURE_FLAGS) \
-           $(DISTCHECK_CONFIGURE_FLAGS) \
-           --srcdir=.. --prefix="$$dc_install_base" \
-         && $(MAKE) $(AM_MAKEFLAGS) \
-         && $(MAKE) $(AM_MAKEFLAGS) dvi \
-         && $(MAKE) $(AM_MAKEFLAGS) check \
-         && $(MAKE) $(AM_MAKEFLAGS) install \
-         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
-         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
-         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
-               distuninstallcheck \
-         && chmod -R a-w "$$dc_install_base" \
-         && ({ \
-              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
-              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
-              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
-              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
-                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
-             } || { rm -rf "$$dc_destdir"; exit 1; }) \
-         && rm -rf "$$dc_destdir" \
-         && $(MAKE) $(AM_MAKEFLAGS) dist \
-         && rm -rf $(DIST_ARCHIVES) \
-         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
-         && cd "$$am__cwd" \
-         || exit 1
-       $(am__post_remove_distdir)
-       @(echo "$(distdir) archives ready for distribution: "; \
-         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
-         sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
-distuninstallcheck:
-       @test -n '$(distuninstallcheck_dir)' || { \
-         echo 'ERROR: trying to run $@ with an empty' \
-              '$$(distuninstallcheck_dir)' >&2; \
-         exit 1; \
-       }; \
-       $(am__cd) '$(distuninstallcheck_dir)' || { \
-         echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
-         exit 1; \
-       }; \
-       test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
-          || { echo "ERROR: files left after uninstall:" ; \
-               if test -n "$(DESTDIR)"; then \
-                 echo "  (check DESTDIR support)"; \
-               fi ; \
-               $(distuninstallcheck_listfiles) ; \
-               exit 1; } >&2
-distcleancheck: distclean
-       @if test '$(srcdir)' = . ; then \
-         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
-         exit 1 ; \
-       fi
-       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
-         || { echo "ERROR: files left in build directory after distclean:" ; \
-              $(distcleancheck_listfiles) ; \
-              exit 1; } >&2
-check-am: all-am
-check: check-recursive
-all-am: Makefile config.h
-installdirs: installdirs-recursive
-installdirs-am:
-install: install-recursive
-install-exec: install-exec-recursive
-install-data: install-data-recursive
-uninstall: uninstall-recursive
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-recursive
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-clean: clean-recursive
-
-clean-am: clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-recursive
-       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
-       -rm -f Makefile
-distclean-am: clean-am distclean-generic distclean-hdr \
-       distclean-libtool distclean-tags
-
-dvi: dvi-recursive
-
-dvi-am:
-
-html: html-recursive
-
-html-am:
-
-info: info-recursive
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-recursive
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-recursive
-
-install-html-am:
-
-install-info: install-info-recursive
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-recursive
-
-install-pdf-am:
-
-install-ps: install-ps-recursive
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-recursive
-       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
-       -rm -rf $(top_srcdir)/autom4te.cache
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-recursive
-
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-
-pdf: pdf-recursive
-
-pdf-am:
-
-ps: ps-recursive
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: $(am__recursive_targets) all install-am install-strip
-
-.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
-       am--refresh check check-am clean clean-cscope clean-generic \
-       clean-libtool cscope cscopelist-am ctags ctags-am dist \
-       dist-all dist-bzip2 dist-gzip dist-hook dist-lzip dist-shar \
-       dist-tarZ dist-xz dist-zip distcheck distclean \
-       distclean-generic distclean-hdr distclean-libtool \
-       distclean-tags distcleancheck distdir distuninstallcheck dvi \
-       dvi-am html html-am info info-am install install-am \
-       install-data install-data-am install-dvi install-dvi-am \
-       install-exec install-exec-am install-html install-html-am \
-       install-info install-info-am install-man install-pdf \
-       install-pdf-am install-ps install-ps-am install-strip \
-       installcheck installcheck-am installdirs installdirs-am \
-       maintainer-clean maintainer-clean-generic mostlyclean \
-       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-       tags tags-am uninstall uninstall-am
-
-
-# Add all the files listed in "distfiles" files to the distribution,
-# apply version number s to some files and create a VERSION file which
-# we need for the Prereq: patch file trick.
-dist-hook: gen-ChangeLog
-       @set -e; \
-        for file in `cd $(top_srcdir); \
-             find mpi -type f -name distfiles`; do \
-           dir=`dirname $$file` ; $(mkinstalldirs) $(distdir)/$$dir ; \
-           for i in distfiles `cat $(top_srcdir)/$$file` ; do \
-               ln $(top_srcdir)/$$dir/$$i $(distdir)/$$dir/$$i 2> /dev/null \
-               || cp -p $(top_srcdir)/$$dir/$$i $(distdir)/$$dir/$$i; \
-           done ; \
-       done
-       @set -e; \
-       echo "$(VERSION)" > $(distdir)/VERSION
-
-distcheck-hook:
-       set -e; ( \
-       pref="#+macro: $$(echo $(PACKAGE_NAME)|tr '-' '_')_" ;\
-       reldate="$$(date -u +%Y-%m-%d)" ;\
-        echo "$${pref}ver  $(PACKAGE_VERSION)"  ;\
-        echo "$${pref}date $${reldate}" ;\
-        list='$(DIST_ARCHIVES)'; for i in $$list; do \
-         case "$$i" in *.tar.bz2) \
-            echo "$${pref}size $$(wc -c <$$i|awk '{print int($$1/1024)}')k" ;\
-           echo "$${pref}sha1 $$(sha1sum <$$i|cut -d' ' -f1)" ;\
-           echo "$${pref}sha2 $$(sha256sum <$$i|cut -d' ' -f1)" ;;\
-         esac;\
-       done ) | tee $(distdir).swdb
-.PHONY: gen-ChangeLog
-gen-ChangeLog:
-       if test -e $(top_srcdir)/.git; then                             \
-         (cd $(top_srcdir) &&                                          \
-           $(GITLOG_TO_CHANGELOG) --append-dot --tear-off              \
-           --amend=build-aux/git-log-fix                               \
-           --since=$(gen_start_date) ) > $(distdir)/cl-t;              \
-          cat $(top_srcdir)/build-aux/git-log-footer >> $(distdir)/cl-t;\
-         rm -f $(distdir)/ChangeLog;                                   \
-         mv $(distdir)/cl-t $(distdir)/ChangeLog;                      \
-       fi
-
-stowinstall:
-       $(MAKE) $(AM_MAKEFLAGS) install prefix=/usr/local/stow/libgcrypt
-
-release:
-       +(set -e;\
-        if [ "$(abs_top_builddir)" = "$(abs_top_srcdir)" ]; then \
-           echo "error: build directory must not be the source directory" >&2;\
-          exit 2;\
-         fi ;\
-        echo "/* Build started at $$(date -uIseconds) */" ;\
-        cd $(top_srcdir); \
-        ./autogen.sh --force; \
-        cd $(abs_top_builddir); \
-        rm -rf dist; mkdir dist ; cd dist ; \
-        $(abs_top_srcdir)/configure --enable-maintainer-mode; \
-        $(MAKE) distcheck; \
-        echo "/* Build finished at $$(date -uIseconds) */" ;\
-         echo "/*" ;\
-        echo " * Please run the final step interactivly:" ;\
-        echo " *   make sign-release" ;\
-        echo " */" ;\
-       ) 2>&1 | tee "$(RELEASE_NAME).buildlog"
-
-sign-release:
-        +(set -e; \
-         cd dist; \
-         files1="$(RELEASE_NAME).tar.bz2 \
-                 $(RELEASE_NAME).tar.gz" ; \
-         files2="$(RELEASE_NAME).tar.bz2.sig \
-                 $(RELEASE_NAME).tar.gz.sig  \
-                 $(RELEASE_NAME).swdb \
-                 $(RELEASE_NAME).buildlog" ;\
-         echo "/* Signing the source tarball ..." ;\
-         gpg -sbu $(RELEASE_SIGNING_KEY) $(RELEASE_NAME).tar.bz2 ;\
-         gpg -sbu $(RELEASE_SIGNING_KEY) $(RELEASE_NAME).tar.gz  ;\
-         cat $(RELEASE_NAME).swdb >swdb.snippet;\
-         echo >>swdb.snippet ;\
-         sha1sum $${files1} >>swdb.snippet ;\
-          cat "../$(RELEASE_NAME).buildlog" swdb.snippet \
-               | gzip >$(RELEASE_NAME).buildlog ;\
-          echo "Copying to local archive ..." ;\
-         scp -p $${files1} $${files2} $(RELEASE_ARCHIVE_DIR)/ || true;\
-         echo '/*' ;\
-         echo ' * All done; for checksums see dist/swdb.snippet' ;\
-         echo ' */' ;\
-         )
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/NEWS b/NEWS
index a4c5e20..03132c2 100644 (file)
--- a/NEWS
+++ b/NEWS
-Noteworthy changes in version 1.8.4 (2018-10-26)  [C22/A2/R4]
+Noteworthy changes in version 1.10.1 (2022-03-28)  [C24/A4/R1]
+-------------------------------------------------
+
+ * Bug fixes:
+
+   - Fix minor memory leaks in FIPS mode.
+
+   - Build fixes for MUSL libc.  [rCffaef0be61]
+
+ * Other:
+
+   - More portable integrity check in FIPS mode.  [rC9fa4c8946a,T5835]
+
+   - Add X9.62 OIDs to sha256 and sha512 modules.  [rC52fd2305ba]
+
+ Release-info: https://dev.gnupg.org/T5810
+
+
+Noteworthy changes in version 1.10.0 (2022-02-01)  [C24/A4/R0]
+-------------------------------------------------
+
+ * New and extended interfaces:
+
+   - New control codes to check for FIPS 140-3 approved algorithms.
+
+   - New control code to switch into non-FIPS mode.
+
+   - New cipher modes SIV and GCM-SIV as specified by RFC-5297.
+
+   - Extended cipher mode AESWRAP with padding as specified by
+     RFC-5649.  [T5752]
+
+   - New set of KDF functions.
+
+   - New KDF modes Argon2 and Balloon.
+
+   - New functions for combining hashing and signing/verification.  [T4894]
+
+ * Performance:
+
+   - Improved support for PowerPC architectures.
+
+   - Improved ECC performance on zSeries/s390x by using accelerated
+     scalar multiplication.
+
+   - Many more assembler performance improvements for several
+     architectures.
+
+ * Bug fixes:
+
+   - Fix Elgamal encryption for other implementations.
+     [R5328,CVE-2021-40528]
+
+   - Fix alignment problem on macOS.  [T5440]
+
+   - Check the input length of the point in ECDH.  [T5423]
+
+   - Fix an abort in gcry_pk_get_param for "Curve25519".  [T5490]
+
+ * Other features:
+
+   - The control code GCRYCTL_SET_ENFORCED_FIPS_FLAG is ignored
+     because it is useless with the FIPS 140-3 related changes.
+
+   - Update of the jitter entropy RNG code.  [T5523]
+
+   - Simplification of the entropy gatherer when using the getentropy
+     system call.
+
+ * Interface changes relative to the 1.10.0 release:
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   GCRYCTL_SET_DECRYPTION_TAG            NEW control code.
+   GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER NEW control code.
+   GCRYCTL_FIPS_SERVICE_INDICATOR_KDF    NEW control code.
+   GCRYCTL_NO_FIPS_MODE = 83             NEW control code.
+   GCRY_CIPHER_MODE_SIV                  NEW mode.
+   GCRY_CIPHER_MODE_GCM_SIV              NEW mode.
+   GCRY_CIPHER_EXTENDED                  NEW flag.
+   GCRY_SIV_BLOCK_LEN                    NEW macro.
+   gcry_cipher_set_decryption_tag        NEW macro.
+   GCRY_KDF_ARGON2                       NEW constant.
+   GCRY_KDF_BALLOON                      NEW constant.
+   GCRY_KDF_ARGON2D                      NEW constant.
+   GCRY_KDF_ARGON2I                      NEW constant.
+   GCRY_KDF_ARGON2ID                     NEW constant.
+   gcry_kdf_hd_t                         NEW type.
+   gcry_kdf_job_fn_t                     NEW type.
+   gcry_kdf_dispatch_job_fn_t            NEW type.
+   gcry_kdf_wait_all_jobs_fn_t           NEW type.
+   struct gcry_kdf_thread_ops            NEW struct.
+   gcry_kdf_open                         NEW function.
+   gcry_kdf_compute                      NEW function.
+   gcry_kdf_final                        NEW function.
+   gcry_kdf_close                        NEW function.
+   gcry_pk_hash_sign                     NEW function.
+   gcry_pk_hash_verify                   NEW function.
+   gcry_pk_random_override_new           NEW function.
+
+ Release-info: https://dev.gnupg.org/T5691
+
+ Release dates of 1.9.x versions:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   Version 1.9.4 (2021-08-22)
+
+
+Noteworthy changes in version 1.9.3 (2021-04-19)  [C23/A3/R3]
 ------------------------------------------------
 
  * Bug fixes:
 
-   - Fix infinite loop due to applications using fork the wrong
-     way.  [#3491]
+   - Fix build problems on i386 using gcc-4.7.
 
-   - Fix possible leak of a few bits of secret primes to pageable
-     memory.  [#3848]
+   - Fix checksum calculation in OCB decryption for AES on s390.
+     [#5356]
 
-   - Fix possible hang in the RNG (1.8.3 only).  [#4034]
+   - Fix a regression in gcry_mpi_ec_add related to certain usages of
+     curve 25519.  [#5372]
 
-   - Several minor fixes.  [#4102,#4208,#4209,#4210,#4211,#4212]
+   - Fix a symbol not found problem on Apple M1.  [#5370]
+
+   - Fix for Apple iOS getentropy peculiarity.  [#5375]
+
+   - Make keygrip computation work for compressed points.  [#4961]
 
  * Performance:
 
-   - On Linux always make use of getrandom if possible and then use
-     its /dev/urandom behaviour.  [#3894]
+   - Add x86_64 VAES/AVX2 accelerated implementation of Camellia.
+     [0e7e60241a]
+
+   - Add x86_64 VAES/AVX2 accelerated implementation of AES.
+     [e72498a54f]
+
+   - Add VPMSUMD acceleration for GCM mode on PPC.  [#5040]
+
+ * Internal changes.
+
+   - Harden MPI conditional code against EM leakage.  [#5330]
+
+   - Harden Elgamal by introducing exponent blinding.  [#5328]
 
- Release-info: https://dev.gnupg.org/T4234
+   - Fix memory leaks in the error code paths of EdDSA.  [#5385]
 
+ Release-info: https://dev.gnupg.org/T5305
 
-Noteworthy changes in version 1.8.3 (2018-06-13)  [C22/A2/R3]
+
+Noteworthy changes in version 1.9.2 (2021-02-17)  [C23/A3/R2]
 ------------------------------------------------
 
  * Bug fixes:
 
-   - Use blinding for ECDSA signing to mitigate a novel side-channel
-     attack.  [#4011,CVE-2018-0495]
+   - Fix build problem for macOS in the random code.  [#5268]
 
-   - Fix incorrect counter overflow handling for GCM when using an IV
-     size other than 96 bit.  [#3764]
+   - Fix building with --disable-asm on x86.  [#5277]
 
-   - Fix incorrect output of AES-keywrap mode for in-place encryption
-     on some platforms.
+   - Check public key for ECDSA verify operation.  [#5282]
 
-   - Fix the gcry_mpi_ec_curve_point point validation function.
+   - Make sure gcry_get_config (NULL) returns a nul-terminated string.
+     [8716e4b2ad]
+
+   - Fix a memory leak in the ECDH code.  [289543544e]
+
+   - Fix a reading beyond end of input buffer in SHA2-avx2.
+     [24af2a55d8]
+
+ * Other features:
+
+   - New test driver to allow for standalone regression
+     tests. [b142da4c88]
+
+ Release-info: https://dev.gnupg.org/T5276
+
+
+Noteworthy changes in version 1.9.1 (2021-01-29)  [C23/A3/R1]
+------------------------------------------------
+
+ * Bug fixes:
+
+   - Fix exploitable bug in hash functions introduced with 1.9.0.
+     [#5275]
+
+   - Return an error if a negative MPI is used with sexp scan
+     functions.  [#4964]
+
+   - Check for operational FIPS in the random and KDF functions.
+     [#5243]
+
+   - Fix compile error on ARMv7 with NEON disabled.  [#5251]
+
+   - Fix self-test in KDF module.  [#5254]
+
+   - Improve assembler checks for better LTO support.  [#5255]
+
+   - Fix assember problem on macOS running on M1.  [#5157]
+
+   - Support older macOS without posix_spawn. [#5159]
+
+   - Fix 32-bit cross build on x86.  [#5257]
+
+   - Fix non-NEON ARM assembly implementation for SHA512.  [#5263]
+
+   - Fix build problems with the cipher_bulk_ops_t typedef.  [#5264]
 
-   - Fix rare assertion failure in gcry_prime_check.
+   - Fix Ed25519 private key handling for preceding ZEROs. [#5267]
 
- Release-info: https://dev.gnupg.org/T4016
+   - Fix overflow in modular inverse implementation.  [#5269]
 
+   - Fix register access for AVX/AVX2 implementations of Blake2.
+     [#5271].
 
-Noteworthy changes in version 1.8.2 (2017-12-13)  [C22/A2/R2]
+ * Performance:
+
+   - Add optimized cipher and hash functions for s390x/zSeries.
+
+   - Use hardware bit counting functions when available.
+
+ * Internal changes:
+
+   - The macOS getentropy syscall is used when available.  [#5268]
+
+   - Update DSA functions to match FIPS 186-3.  [30ed9593f6]
+
+   - New self-tests for CMACs and KDFs.  [385a89e35b,7a0da24925]
+
+   - Add bulk cipher functions for OFB and GCM modes.
+     [f12b6788f2,f4e63e92dc]
+
+ Release-info: https://dev.gnupg.org/T5259
+
+
+Noteworthy changes in version 1.9.0 (2021-01-19)  [C23/A3/R0]
 ------------------------------------------------
 
+ * New and extended interfaces:
+
+   - New curves Ed448, X448, and SM2.
+
+   - New cipher mode EAX.
+
+   - New cipher algo SM4.
+
+   - New hash algo SM3.
+
+   - New hash algo variants SHA512/224 and SHA512/256.
+
+   - New MAC algos for Blake-2 algorithms, the new SHA512 variants,
+     SM3, SM4 and for a GOST variant.
+
+   - New convenience function gcry_mpi_get_ui.
+
+   - gcry_sexp_extract_param understands new format specifiers to
+     directly store to integers and strings.
+
+   - New function gcry_ecc_mul_point and curve constants for Curve448
+     and Curve25519.  [#4293]
+
+   - New function gcry_ecc_get_algo_keylen.
+
+   - New control code GCRYCTL_AUTO_EXPAND_SECMEM to allow growing the
+     secure memory area.  Also in 1.8.2 as an undocumented feature.
+
+ * Performance:
+
+   - Optimized implementations for Aarch64.
+
+   - Faster implementations for Poly1305 and ChaCha.  Also for
+     PowerPC.  [b9a471ccf5,172ad09cbe,#4460]
+
+   - Optimized implementations of AES and SHA-256 on PowerPC.
+     [#4529,#4530]
+
+   - Improved use of AES-NI to speed up AES-XTS (6 times faster).
+     [a00c5b2988]
+
+   - Improved use of AES-NI for OCB.  [eacbd59b13,e924ce456d]
+
+   - Speedup AES-XTS on ARMv8/CE (2.5 times faster).  [93503c127a]
+
+   - New AVX and AVX2 implementations for Blake-2 (1.3/1.4 times
+     faster).  [af7fc732f9, da58a62ac1]
+
+   - Use Intel SHA extension for SHA-1 and SHA-256 (4.0/3.7 times
+     faster).  [d02958bd30, 0b3ec359e2]
+
+   - Use ARMv7/NEON accelerated GCM implementation (3 times faster).
+     [2445cf7431]
+
+   - Use of i386/SSSE3 for SHA-512 (4.5 times faster on Ryzen 7).
+     [b52dde8609]
+
+   - Use 64 bit ARMv8/CE PMULL for CRC (7 times faster).  [14c8a593ed]
+
+   - Improve CAST5 (40% to 70% faster).  [4ec566b368]
+
+   - Improve Blowfish (60% to 80% faster).  [ced7508c85]
+
  * Bug fixes:
 
-   - Do not use /dev/srandom on OpenBSD.
+   - Fix infinite loop due to applications using fork the wrong
+     way.  [#3491][also in 1.8.4]
+
+   - Fix possible leak of a few bits of secret primes to pageable
+     memory.  [#3848][also in 1.8.4]
+
+   - Fix possible hang in the RNG (1.8.3 only).  [#4034][also in 1.8.4]
+
+   - Several minor fixes.  [#4102,#4208,#4209,#4210,#4211,#4212]
+     [also in 1.8.4]
+
+   - On Linux always make use of getrandom if possible and then use
+     its /dev/urandom behaviour.  [#3894][also in 1.8.4]
+
+   - Use blinding for ECDSA signing to mitigate a novel side-channel
+     attack.  [#4011,CVE-2018-0495] [also in 1.8.3, 1.7.10]
+
+   - Fix incorrect counter overflow handling for GCM when using an IV
+     size other than 96 bit.  [#3764] [also in 1.8.3, 1.7.10]
+
+   - Fix incorrect output of AES-keywrap mode for in-place encryption
+     on some platforms.  [also in 1.8.3, 1.7.10]
+
+   - Fix the gcry_mpi_ec_curve_point point validation function.
+     [also in 1.8.3, 1.7.10]
+
+   - Fix rare assertion failure in gcry_prime_check.  [also in 1.8.3]
+
+   - Do not use /dev/srandom on OpenBSD.  [also in 1.8.2]
 
    - Fix test suite failure on systems with large pages. [#3351]
+     [also in 1.8.2]
 
-   - Fix test suite to not use mmap on Windows.
+   - Fix test suite to not use mmap on Windows.  [also in 1.8.2]
 
    - Fix fatal out of secure memory status in the s-expression parser
-     on heavy loaded systems.
+     on heavy loaded systems.  [also in 1.8.2]
 
- * Other:
+   - Fix build problems on OpenIndiana et al. [#4818, also in 1.8.6]
+
+   - Fix GCM bug on arm64 which troubles for example OMEMO.  [#4986,
+     also in 1.8.6]
+
+   - Detect a div-by-zero in a debug helper tool.  [#4868, also in 1.8.6]
+
+   - Use a constant time mpi_inv and related changes.  [#4869, partly
+     also in 1.8.6]
+
+   - Fix mpi_copy to correctly handle flags of opaque MPIs.
+     [also in 1.8.6]
+
+   - Fix mpi_cmp to consider +0 and -0 the same.  [also in 1.8.6]
+
+   - Fix extra entropy collection via clock_gettime.  Note that this
+     fallback code path is not used on any decent hardware.  [#4966,
+     also in 1.8.7]
 
-   - Backport the auto expand secmem feature from master for use by
-     the forthcoming GnuPG 2.2.4.
+   - Support opaque MPI with gcry_mpi_print.  [#4872, also in 1.8.7]
+
+   - Allow for a Unicode random seed file on Windows.  [#5098, also in
+     1.8.7]
+
+ * Other features:
+
+   - Add OIDs from RFC-8410 as aliases for Ed25519 and Curve25519.
+     [also in 1.8.6]
+
+   - Add mitigation against ECC timing attack CVE-2019-13627.  [#4626]
+
+   - Internal cleanup of the ECC implementation.
+
+   - Support reading EC point in compressed format for some curves.
+     [#4951]
+
+ * Interface changes relative to the 1.8.0 release:
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   gcry_mpi_get_ui                 NEW function.
+   GCRYCTL_AUTO_EXPAND_SECMEM      NEW control code.
+   gcry_sexp_extract_param         EXTENDED.
+   GCRY_CIPHER_GOST28147_MESH      NEW cipher algo.
+   GCRY_CIPHER_SM4                 NEW cipher algo.
+   GCRY_CIPHER_MODE_EAX            NEW mode.
+   GCRY_ECC_CURVE25519             NEW curve id.
+   GCRY_ECC_CURVE448               NEW curve id.
+   gcry_ecc_get_algo_keylen        NEW function.
+   gcry_ecc_mul_point              NEW function.
+   GCRY_MD_SM3                     NEW hash algo.
+   GCRY_MD_SHA512_256              NEW hash algo.
+   GCRY_MD_SHA512_224              NEW hash algo.
+   GCRY_MAC_GOST28147_IMIT         NEW mac algo.
+   GCRY_MAC_HMAC_GOSTR3411_CP      NEW mac algo.
+   GCRY_MAC_HMAC_BLAKE2B_512       NEW mac algo.
+   GCRY_MAC_HMAC_BLAKE2B_384       NEW mac algo.
+   GCRY_MAC_HMAC_BLAKE2B_256       NEW mac algo.
+   GCRY_MAC_HMAC_BLAKE2B_160       NEW mac algo.
+   GCRY_MAC_HMAC_BLAKE2S_256       NEW mac algo.
+   GCRY_MAC_HMAC_BLAKE2S_224       NEW mac algo.
+   GCRY_MAC_HMAC_BLAKE2S_160       NEW mac algo.
+   GCRY_MAC_HMAC_BLAKE2S_128       NEW mac algo.
+   GCRY_MAC_HMAC_SM3               NEW mac algo.
+   GCRY_MAC_HMAC_SHA512_256        NEW mac algo.
+   GCRY_MAC_HMAC_SHA512_224        NEW mac algo.
+   GCRY_MAC_CMAC_SM4               NEW mac algo.
+
+ Release-info: https://dev.gnupg.org/T4294
+
+ Release dates of 1.8.x versions:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   Version 1.8.2 (2017-12-13)
+   Version 1.8.3 (2018-06-13)
+   Version 1.8.4 (2018-10-26)
+   Version 1.8.5 (2019-08-29)
+   Version 1.8.6 (2020-07-06)
+   Version 1.8.7 (2020-10-23)
 
 
 Noteworthy changes in version 1.8.1 (2017-08-27)  [C22/A2/R1]
@@ -183,11 +532,13 @@ Noteworthy changes in version 1.8.0 (2017-07-18)  [C22/A2/R0]
 
  * Release dates of 1.7.x versions:
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-   Version 1.7.8 (2017-06-29)  [C21/A1/R8]
-   Version 1.7.7 (2017-06-02)  [C21/A1/R7]
-   Version 1.7.6 (2017-01-18)  [C21/A1/R6]
-   Version 1.7.5 (2016-12-15)  [C21/A1/R5]
-   Version 1.7.4 (2016-12-09)  [C21/A1/R4]
+   Version 1.7.10 (2018-06-13) [C21/A1/R10]
+   Version 1.7.9  (2017-08-27) [C21/A1/R9]
+   Version 1.7.8  (2017-06-29) [C21/A1/R8]
+   Version 1.7.7  (2017-06-02) [C21/A1/R7]
+   Version 1.7.6  (2017-01-18) [C21/A1/R6]
+   Version 1.7.5  (2016-12-15) [C21/A1/R5]
+   Version 1.7.4  (2016-12-09) [C21/A1/R4]
 
 
 Noteworthy changes in version 1.7.3 (2016-08-17)  [C21/A1/R3]
diff --git a/README b/README
index 8a3f2aa..d42e58b 100644 (file)
--- a/README
+++ b/README
@@ -1,10 +1,10 @@
                    Libgcrypt - The GNU Crypto Library
                   ------------------------------------
-                             Version 1.8
+                             Version 1.10
 
        Copyright (C) 1989,1991-2018 Free Software Foundation, Inc.
-       Copyright (C) 2012-2018 g10 Code GmbH
-       Copyright (C) 2013-2018 Jussi Kivilinna
+       Copyright (C) 2012-2022 g10 Code GmbH
+       Copyright (C) 2013-2022 Jussi Kivilinna
 
     Libgcrypt is free software.  See the file AUTHORS for full copying
     notices, and LICENSES for notices about contributions that require
      --enable-hmac-binary-check
                      Include support to check the binary at runtime
                      against a HMAC checksum.  This works only in FIPS
-                     mode and on systems providing the dladdr function.
+                     mode on systems providing the dladdr function and using
+                     the ELF binary format.
+
+     --with-fips-module-version=version
+                     Specify a string used as a module version for FIPS
+                     certification purposes.
 
      --disable-padlock-support
                      Disable support for the PadLock engine of VIA
 
     Specific problems on some machines:
 
+      * AArch64 (GCC 11.1 and 11.2)
+
+       Because of the bug in GCC (fixed in 11.3), with the option
+       -O3, vectorization results wrong code for the function
+       buf_eq_const.  Please use -O2 or -fno-tree-loop-vectorize.
+
       * IBM RS/6000 running AIX
 
        Due to a change in gcc (since version 2.8) the MPI stuff may
     Commercial grade support for Libgcrypt is available; for a listing
     of offers see https://www.gnupg.org/service.html .
 
-    Maintenance and development of Libgcrypt is mostly financed by
-    donations.  We currently employ 3 full-time developers, one
-    part-timer, and one contractor.  They all work on GnuPG and
-    closely related software like Libgcrypt.  Please visit
-    https://gnupg.org/donate/ to see out how you can help.
-
+    Since 2001 maintenance and development of Libgcrypt is done by
+    g10 Code GmbH and until 2021 mostly financed by donations.
 
   This file is Free Software; as a special exception the authors gives
   unlimited permission to copy and/or distribute it, with or without
diff --git a/VERSION b/VERSION
deleted file mode 100644 (file)
index bfa363e..0000000
--- a/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-1.8.4
index fc208c5..05bf88a 100644 (file)
@@ -111,14 +111,10 @@ case "${host}" in
         ac_cv_sys_symbol_underscore=yes
         ;;
     *)
-      if test "$cross_compiling" = yes; then
-        if test "x$ac_cv_sys_symbol_underscore" = x ; then
-           ac_cv_sys_symbol_underscore=yes
-        fi
-      else
+      if test "$cross_compiling" != yes; then
          tmp_do_check="yes"
       fi
-       ;;
+      ;;
 esac
 if test "$tmp_do_check" = "yes"; then
   AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])
@@ -140,15 +136,15 @@ EOF
         if egrep '^nm_test_func ' "$ac_nlist" >/dev/null; then
           :
         else
-          echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC
+          echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD
         fi
       fi
     else
-      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC
+      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
     fi
   else
-    echo "configure: failed program was:" >&AC_FD_CC
-    cat conftest.c >&AC_FD_CC
+    echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.c >&AS_MESSAGE_LOG_FD
   fi
   rm -rf conftest*
   ])
@@ -180,12 +176,13 @@ define(GNUPG_CHECK_MLOCK,
             AC_CHECK_LIB(rt, memlk)
             AC_CACHE_CHECK([whether mlock is in sys/mman.h],
                             gnupg_cv_mlock_is_in_sys_mman,
-                [AC_TRY_LINK([
+                [AC_LINK_IFELSE(
+                   [AC_LANG_PROGRAM([[
                     #include <assert.h>
                     #ifdef HAVE_SYS_MMAN_H
                     #include <sys/mman.h>
                     #endif
-                ], [
+                    ]], [[
 int i;
 
 /* glibc defines this for functions which it implements
@@ -198,7 +195,7 @@ choke me
 mlock(&i, 4);
 #endif
 ; return 0;
-                ],
+                    ]])],
                 gnupg_cv_mlock_is_in_sys_mman=yes,
                 gnupg_cv_mlock_is_in_sys_mman=no)])
             if test "$gnupg_cv_mlock_is_in_sys_mman" = "yes"; then
@@ -211,7 +208,7 @@ mlock(&i, 4);
         AC_CHECK_FUNCS(sysconf getpagesize)
         AC_MSG_CHECKING(whether mlock is broken)
           AC_CACHE_VAL(gnupg_cv_have_broken_mlock,
-             AC_TRY_RUN([
+             AC_RUN_IFELSE([AC_LANG_SOURCE([[
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
@@ -239,7 +236,7 @@ int main()
     pool = malloc( 4096 + pgsize );
     if( !pool )
         return 2;
-    pool += (pgsize - ((long int)pool % pgsize));
+    pool += (pgsize - ((size_t)pool % pgsize));
 
     err = mlock( pool, 4096 );
     if( !err || errno == EPERM || errno == EAGAIN)
@@ -247,8 +244,7 @@ int main()
 
     return 1;  /* hmmm */
 }
-
-            ],
+            ]])],
             gnupg_cv_have_broken_mlock="no",
             gnupg_cv_have_broken_mlock="yes",
             gnupg_cv_have_broken_mlock="assume-no"
diff --git a/aclocal.m4 b/aclocal.m4
deleted file mode 100644 (file)
index 73804e9..0000000
+++ /dev/null
@@ -1,1216 +0,0 @@
-# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
-
-# Copyright (C) 1996-2013 Free Software Foundation, Inc.
-
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
-m4_ifndef([AC_AUTOCONF_VERSION],
-  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
-[m4_warning([this file was generated for autoconf 2.69.
-You have another version of autoconf.  It may work, but is not guaranteed to.
-If you have problems, you may need to regenerate the build system entirely.
-To do so, use the procedure documented by the package, typically 'autoreconf'.])])
-
-# Copyright (C) 2002-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_AUTOMAKE_VERSION(VERSION)
-# ----------------------------
-# Automake X.Y traces this macro to ensure aclocal.m4 has been
-# generated from the m4 files accompanying Automake X.Y.
-# (This private macro should not be called outside this file.)
-AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.14'
-dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
-dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.14.1], [],
-      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
-])
-
-# _AM_AUTOCONF_VERSION(VERSION)
-# -----------------------------
-# aclocal traces this macro to find the Autoconf version.
-# This is a private macro too.  Using m4_define simplifies
-# the logic in aclocal, which can simply ignore this definition.
-m4_define([_AM_AUTOCONF_VERSION], [])
-
-# AM_SET_CURRENT_AUTOMAKE_VERSION
-# -------------------------------
-# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
-# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
-AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.14.1])dnl
-m4_ifndef([AC_AUTOCONF_VERSION],
-  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
-
-# Figure out how to run the assembler.                      -*- Autoconf -*-
-
-# Copyright (C) 2001-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_PROG_AS
-# ----------
-AC_DEFUN([AM_PROG_AS],
-[# By default we simply use the C compiler to build assembly code.
-AC_REQUIRE([AC_PROG_CC])
-test "${CCAS+set}" = set || CCAS=$CC
-test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
-AC_ARG_VAR([CCAS],      [assembler compiler command (defaults to CC)])
-AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)])
-_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl
-])
-
-# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
-
-# Copyright (C) 2001-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
-# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
-# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
-#
-# Of course, Automake must honor this variable whenever it calls a
-# tool from the auxiliary directory.  The problem is that $srcdir (and
-# therefore $ac_aux_dir as well) can be either absolute or relative,
-# depending on how configure is run.  This is pretty annoying, since
-# it makes $ac_aux_dir quite unusable in subdirectories: in the top
-# source directory, any form will work fine, but in subdirectories a
-# relative path needs to be adjusted first.
-#
-# $ac_aux_dir/missing
-#    fails when called from a subdirectory if $ac_aux_dir is relative
-# $top_srcdir/$ac_aux_dir/missing
-#    fails if $ac_aux_dir is absolute,
-#    fails when called from a subdirectory in a VPATH build with
-#          a relative $ac_aux_dir
-#
-# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
-# are both prefixed by $srcdir.  In an in-source build this is usually
-# harmless because $srcdir is '.', but things will broke when you
-# start a VPATH build or use an absolute $srcdir.
-#
-# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
-# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
-#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
-# and then we would define $MISSING as
-#   MISSING="\${SHELL} $am_aux_dir/missing"
-# This will work as long as MISSING is not called from configure, because
-# unfortunately $(top_srcdir) has no meaning in configure.
-# However there are other variables, like CC, which are often used in
-# configure, and could therefore not use this "fixed" $ac_aux_dir.
-#
-# Another solution, used here, is to always expand $ac_aux_dir to an
-# absolute PATH.  The drawback is that using absolute paths prevent a
-# configured tree to be moved without reconfiguration.
-
-AC_DEFUN([AM_AUX_DIR_EXPAND],
-[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
-# Expand $ac_aux_dir to an absolute path.
-am_aux_dir=`cd "$ac_aux_dir" && pwd`
-])
-
-# AM_CONDITIONAL                                            -*- Autoconf -*-
-
-# Copyright (C) 1997-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_CONDITIONAL(NAME, SHELL-CONDITION)
-# -------------------------------------
-# Define a conditional.
-AC_DEFUN([AM_CONDITIONAL],
-[AC_PREREQ([2.52])dnl
- m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
-       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
-AC_SUBST([$1_TRUE])dnl
-AC_SUBST([$1_FALSE])dnl
-_AM_SUBST_NOTMAKE([$1_TRUE])dnl
-_AM_SUBST_NOTMAKE([$1_FALSE])dnl
-m4_define([_AM_COND_VALUE_$1], [$2])dnl
-if $2; then
-  $1_TRUE=
-  $1_FALSE='#'
-else
-  $1_TRUE='#'
-  $1_FALSE=
-fi
-AC_CONFIG_COMMANDS_PRE(
-[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
-  AC_MSG_ERROR([[conditional "$1" was never defined.
-Usually this means the macro was only invoked conditionally.]])
-fi])])
-
-# Copyright (C) 1999-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-
-# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
-# written in clear, in which case automake, when reading aclocal.m4,
-# will think it sees a *use*, and therefore will trigger all it's
-# C support machinery.  Also note that it means that autoscan, seeing
-# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
-
-
-# _AM_DEPENDENCIES(NAME)
-# ----------------------
-# See how the compiler implements dependency checking.
-# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
-# We try a few techniques and use that to set a single cache variable.
-#
-# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
-# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
-# dependency, and given that the user is not expected to run this macro,
-# just rely on AC_PROG_CC.
-AC_DEFUN([_AM_DEPENDENCIES],
-[AC_REQUIRE([AM_SET_DEPDIR])dnl
-AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
-AC_REQUIRE([AM_MAKE_INCLUDE])dnl
-AC_REQUIRE([AM_DEP_TRACK])dnl
-
-m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
-      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
-      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
-      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
-      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
-      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
-                    [depcc="$$1"   am_compiler_list=])
-
-AC_CACHE_CHECK([dependency style of $depcc],
-               [am_cv_$1_dependencies_compiler_type],
-[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
-  # We make a subdir and do the tests there.  Otherwise we can end up
-  # making bogus files that we don't know about and never remove.  For
-  # instance it was reported that on HP-UX the gcc test will end up
-  # making a dummy file named 'D' -- because '-MD' means "put the output
-  # in D".
-  rm -rf conftest.dir
-  mkdir conftest.dir
-  # Copy depcomp to subdir because otherwise we won't find it if we're
-  # using a relative directory.
-  cp "$am_depcomp" conftest.dir
-  cd conftest.dir
-  # We will build objects and dependencies in a subdirectory because
-  # it helps to detect inapplicable dependency modes.  For instance
-  # both Tru64's cc and ICC support -MD to output dependencies as a
-  # side effect of compilation, but ICC will put the dependencies in
-  # the current directory while Tru64 will put them in the object
-  # directory.
-  mkdir sub
-
-  am_cv_$1_dependencies_compiler_type=none
-  if test "$am_compiler_list" = ""; then
-     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
-  fi
-  am__universal=false
-  m4_case([$1], [CC],
-    [case " $depcc " in #(
-     *\ -arch\ *\ -arch\ *) am__universal=true ;;
-     esac],
-    [CXX],
-    [case " $depcc " in #(
-     *\ -arch\ *\ -arch\ *) am__universal=true ;;
-     esac])
-
-  for depmode in $am_compiler_list; do
-    # Setup a source with many dependencies, because some compilers
-    # like to wrap large dependency lists on column 80 (with \), and
-    # we should not choose a depcomp mode which is confused by this.
-    #
-    # We need to recreate these files for each test, as the compiler may
-    # overwrite some of them when testing with obscure command lines.
-    # This happens at least with the AIX C compiler.
-    : > sub/conftest.c
-    for i in 1 2 3 4 5 6; do
-      echo '#include "conftst'$i'.h"' >> sub/conftest.c
-      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
-      # Solaris 10 /bin/sh.
-      echo '/* dummy */' > sub/conftst$i.h
-    done
-    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
-
-    # We check with '-c' and '-o' for the sake of the "dashmstdout"
-    # mode.  It turns out that the SunPro C++ compiler does not properly
-    # handle '-M -o', and we need to detect this.  Also, some Intel
-    # versions had trouble with output in subdirs.
-    am__obj=sub/conftest.${OBJEXT-o}
-    am__minus_obj="-o $am__obj"
-    case $depmode in
-    gcc)
-      # This depmode causes a compiler race in universal mode.
-      test "$am__universal" = false || continue
-      ;;
-    nosideeffect)
-      # After this tag, mechanisms are not by side-effect, so they'll
-      # only be used when explicitly requested.
-      if test "x$enable_dependency_tracking" = xyes; then
-       continue
-      else
-       break
-      fi
-      ;;
-    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
-      # This compiler won't grok '-c -o', but also, the minuso test has
-      # not run yet.  These depmodes are late enough in the game, and
-      # so weak that their functioning should not be impacted.
-      am__obj=conftest.${OBJEXT-o}
-      am__minus_obj=
-      ;;
-    none) break ;;
-    esac
-    if depmode=$depmode \
-       source=sub/conftest.c object=$am__obj \
-       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
-       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
-         >/dev/null 2>conftest.err &&
-       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
-       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
-       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
-       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
-      # icc doesn't choke on unknown options, it will just issue warnings
-      # or remarks (even with -Werror).  So we grep stderr for any message
-      # that says an option was ignored or not supported.
-      # When given -MP, icc 7.0 and 7.1 complain thusly:
-      #   icc: Command line warning: ignoring option '-M'; no argument required
-      # The diagnosis changed in icc 8.0:
-      #   icc: Command line remark: option '-MP' not supported
-      if (grep 'ignoring option' conftest.err ||
-          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
-        am_cv_$1_dependencies_compiler_type=$depmode
-        break
-      fi
-    fi
-  done
-
-  cd ..
-  rm -rf conftest.dir
-else
-  am_cv_$1_dependencies_compiler_type=none
-fi
-])
-AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
-AM_CONDITIONAL([am__fastdep$1], [
-  test "x$enable_dependency_tracking" != xno \
-  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
-])
-
-
-# AM_SET_DEPDIR
-# -------------
-# Choose a directory name for dependency files.
-# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
-AC_DEFUN([AM_SET_DEPDIR],
-[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
-AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
-])
-
-
-# AM_DEP_TRACK
-# ------------
-AC_DEFUN([AM_DEP_TRACK],
-[AC_ARG_ENABLE([dependency-tracking], [dnl
-AS_HELP_STRING(
-  [--enable-dependency-tracking],
-  [do not reject slow dependency extractors])
-AS_HELP_STRING(
-  [--disable-dependency-tracking],
-  [speeds up one-time build])])
-if test "x$enable_dependency_tracking" != xno; then
-  am_depcomp="$ac_aux_dir/depcomp"
-  AMDEPBACKSLASH='\'
-  am__nodep='_no'
-fi
-AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
-AC_SUBST([AMDEPBACKSLASH])dnl
-_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
-AC_SUBST([am__nodep])dnl
-_AM_SUBST_NOTMAKE([am__nodep])dnl
-])
-
-# Generate code to set up dependency tracking.              -*- Autoconf -*-
-
-# Copyright (C) 1999-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-
-# _AM_OUTPUT_DEPENDENCY_COMMANDS
-# ------------------------------
-AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
-[{
-  # Older Autoconf quotes --file arguments for eval, but not when files
-  # are listed without --file.  Let's play safe and only enable the eval
-  # if we detect the quoting.
-  case $CONFIG_FILES in
-  *\'*) eval set x "$CONFIG_FILES" ;;
-  *)   set x $CONFIG_FILES ;;
-  esac
-  shift
-  for mf
-  do
-    # Strip MF so we end up with the name of the file.
-    mf=`echo "$mf" | sed -e 's/:.*$//'`
-    # Check whether this is an Automake generated Makefile or not.
-    # We used to match only the files named 'Makefile.in', but
-    # some people rename them; so instead we look at the file content.
-    # Grep'ing the first line is not enough: some people post-process
-    # each Makefile.in and add a new line on top of each file to say so.
-    # Grep'ing the whole file is not good either: AIX grep has a line
-    # limit of 2048, but all sed's we know have understand at least 4000.
-    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
-      dirpart=`AS_DIRNAME("$mf")`
-    else
-      continue
-    fi
-    # Extract the definition of DEPDIR, am__include, and am__quote
-    # from the Makefile without running 'make'.
-    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
-    test -z "$DEPDIR" && continue
-    am__include=`sed -n 's/^am__include = //p' < "$mf"`
-    test -z "$am__include" && continue
-    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
-    # Find all dependency output files, they are included files with
-    # $(DEPDIR) in their names.  We invoke sed twice because it is the
-    # simplest approach to changing $(DEPDIR) to its actual value in the
-    # expansion.
-    for file in `sed -n "
-      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
-        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
-      # Make sure the directory exists.
-      test -f "$dirpart/$file" && continue
-      fdir=`AS_DIRNAME(["$file"])`
-      AS_MKDIR_P([$dirpart/$fdir])
-      # echo "creating $dirpart/$file"
-      echo '# dummy' > "$dirpart/$file"
-    done
-  done
-}
-])# _AM_OUTPUT_DEPENDENCY_COMMANDS
-
-
-# AM_OUTPUT_DEPENDENCY_COMMANDS
-# -----------------------------
-# This macro should only be invoked once -- use via AC_REQUIRE.
-#
-# This code is only required when automatic dependency tracking
-# is enabled.  FIXME.  This creates each '.P' file that we will
-# need in order to bootstrap the dependency handling code.
-AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
-[AC_CONFIG_COMMANDS([depfiles],
-     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
-     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
-])
-
-# Do all the work for Automake.                             -*- Autoconf -*-
-
-# Copyright (C) 1996-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This macro actually does too much.  Some checks are only needed if
-# your package does certain things.  But this isn't really a big deal.
-
-dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
-m4_define([AC_PROG_CC],
-m4_defn([AC_PROG_CC])
-[_AM_PROG_CC_C_O
-])
-
-# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
-# AM_INIT_AUTOMAKE([OPTIONS])
-# -----------------------------------------------
-# The call with PACKAGE and VERSION arguments is the old style
-# call (pre autoconf-2.50), which is being phased out.  PACKAGE
-# and VERSION should now be passed to AC_INIT and removed from
-# the call to AM_INIT_AUTOMAKE.
-# We support both call styles for the transition.  After
-# the next Automake release, Autoconf can make the AC_INIT
-# arguments mandatory, and then we can depend on a new Autoconf
-# release and drop the old call support.
-AC_DEFUN([AM_INIT_AUTOMAKE],
-[AC_PREREQ([2.65])dnl
-dnl Autoconf wants to disallow AM_ names.  We explicitly allow
-dnl the ones we care about.
-m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
-AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
-AC_REQUIRE([AC_PROG_INSTALL])dnl
-if test "`cd $srcdir && pwd`" != "`pwd`"; then
-  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
-  # is not polluted with repeated "-I."
-  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
-  # test to see if srcdir already configured
-  if test -f $srcdir/config.status; then
-    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
-  fi
-fi
-
-# test whether we have cygpath
-if test -z "$CYGPATH_W"; then
-  if (cygpath --version) >/dev/null 2>/dev/null; then
-    CYGPATH_W='cygpath -w'
-  else
-    CYGPATH_W=echo
-  fi
-fi
-AC_SUBST([CYGPATH_W])
-
-# Define the identity of the package.
-dnl Distinguish between old-style and new-style calls.
-m4_ifval([$2],
-[AC_DIAGNOSE([obsolete],
-             [$0: two- and three-arguments forms are deprecated.])
-m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
- AC_SUBST([PACKAGE], [$1])dnl
- AC_SUBST([VERSION], [$2])],
-[_AM_SET_OPTIONS([$1])dnl
-dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
-m4_if(
-  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
-  [ok:ok],,
-  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
- AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
- AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
-
-_AM_IF_OPTION([no-define],,
-[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
- AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
-
-# Some tools Automake needs.
-AC_REQUIRE([AM_SANITY_CHECK])dnl
-AC_REQUIRE([AC_ARG_PROGRAM])dnl
-AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
-AM_MISSING_PROG([AUTOCONF], [autoconf])
-AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
-AM_MISSING_PROG([AUTOHEADER], [autoheader])
-AM_MISSING_PROG([MAKEINFO], [makeinfo])
-AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
-AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
-AC_REQUIRE([AC_PROG_MKDIR_P])dnl
-# For better backward compatibility.  To be removed once Automake 1.9.x
-# dies out for good.  For more background, see:
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
-AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
-# We need awk for the "check" target.  The system "awk" is bad on
-# some platforms.
-AC_REQUIRE([AC_PROG_AWK])dnl
-AC_REQUIRE([AC_PROG_MAKE_SET])dnl
-AC_REQUIRE([AM_SET_LEADING_DOT])dnl
-_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
-             [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
-                            [_AM_PROG_TAR([v7])])])
-_AM_IF_OPTION([no-dependencies],,
-[AC_PROVIDE_IFELSE([AC_PROG_CC],
-                 [_AM_DEPENDENCIES([CC])],
-                 [m4_define([AC_PROG_CC],
-                            m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
-AC_PROVIDE_IFELSE([AC_PROG_CXX],
-                 [_AM_DEPENDENCIES([CXX])],
-                 [m4_define([AC_PROG_CXX],
-                            m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
-AC_PROVIDE_IFELSE([AC_PROG_OBJC],
-                 [_AM_DEPENDENCIES([OBJC])],
-                 [m4_define([AC_PROG_OBJC],
-                            m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
-AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
-                 [_AM_DEPENDENCIES([OBJCXX])],
-                 [m4_define([AC_PROG_OBJCXX],
-                            m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
-])
-AC_REQUIRE([AM_SILENT_RULES])dnl
-dnl The testsuite driver may need to know about EXEEXT, so add the
-dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
-dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
-AC_CONFIG_COMMANDS_PRE(dnl
-[m4_provide_if([_AM_COMPILER_EXEEXT],
-  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
-
-# POSIX will say in a future version that running "rm -f" with no argument
-# is OK; and we want to be able to make that assumption in our Makefile
-# recipes.  So use an aggressive probe to check that the usage we want is
-# actually supported "in the wild" to an acceptable degree.
-# See automake bug#10828.
-# To make any issue more visible, cause the running configure to be aborted
-# by default if the 'rm' program in use doesn't match our expectations; the
-# user can still override this though.
-if rm -f && rm -fr && rm -rf; then : OK; else
-  cat >&2 <<'END'
-Oops!
-
-Your 'rm' program seems unable to run without file operands specified
-on the command line, even when the '-f' option is present.  This is contrary
-to the behaviour of most rm programs out there, and not conforming with
-the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
-
-Please tell bug-automake@gnu.org about your system, including the value
-of your $PATH and any error possibly output before this message.  This
-can help us improve future automake versions.
-
-END
-  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
-    echo 'Configuration will proceed anyway, since you have set the' >&2
-    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
-    echo >&2
-  else
-    cat >&2 <<'END'
-Aborting the configuration process, to ensure you take notice of the issue.
-
-You can download and install GNU coreutils to get an 'rm' implementation
-that behaves properly: <http://www.gnu.org/software/coreutils/>.
-
-If you want to complete the configuration process using your problematic
-'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
-to "yes", and re-run configure.
-
-END
-    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
-  fi
-fi
-])
-
-dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
-dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
-dnl mangled by Autoconf and run in a shell conditional statement.
-m4_define([_AC_COMPILER_EXEEXT],
-m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
-
-# When config.status generates a header, we must update the stamp-h file.
-# This file resides in the same directory as the config header
-# that is generated.  The stamp files are numbered to have different names.
-
-# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
-# loop where config.status creates the headers, so we can generate
-# our stamp files there.
-AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
-[# Compute $1's index in $config_headers.
-_am_arg=$1
-_am_stamp_count=1
-for _am_header in $config_headers :; do
-  case $_am_header in
-    $_am_arg | $_am_arg:* )
-      break ;;
-    * )
-      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
-  esac
-done
-echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-
-# Copyright (C) 2001-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_PROG_INSTALL_SH
-# ------------------
-# Define $install_sh.
-AC_DEFUN([AM_PROG_INSTALL_SH],
-[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-if test x"${install_sh}" != xset; then
-  case $am_aux_dir in
-  *\ * | *\    *)
-    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
-  *)
-    install_sh="\${SHELL} $am_aux_dir/install-sh"
-  esac
-fi
-AC_SUBST([install_sh])])
-
-# Copyright (C) 2003-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# Check whether the underlying file-system supports filenames
-# with a leading dot.  For instance MS-DOS doesn't.
-AC_DEFUN([AM_SET_LEADING_DOT],
-[rm -rf .tst 2>/dev/null
-mkdir .tst 2>/dev/null
-if test -d .tst; then
-  am__leading_dot=.
-else
-  am__leading_dot=_
-fi
-rmdir .tst 2>/dev/null
-AC_SUBST([am__leading_dot])])
-
-# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
-# From Jim Meyering
-
-# Copyright (C) 1996-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_MAINTAINER_MODE([DEFAULT-MODE])
-# ----------------------------------
-# Control maintainer-specific portions of Makefiles.
-# Default is to disable them, unless 'enable' is passed literally.
-# For symmetry, 'disable' may be passed as well.  Anyway, the user
-# can override the default with the --enable/--disable switch.
-AC_DEFUN([AM_MAINTAINER_MODE],
-[m4_case(m4_default([$1], [disable]),
-       [enable], [m4_define([am_maintainer_other], [disable])],
-       [disable], [m4_define([am_maintainer_other], [enable])],
-       [m4_define([am_maintainer_other], [enable])
-        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
-AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
-  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
-  AC_ARG_ENABLE([maintainer-mode],
-    [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
-      am_maintainer_other[ make rules and dependencies not useful
-      (and sometimes confusing) to the casual installer])],
-    [USE_MAINTAINER_MODE=$enableval],
-    [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
-  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
-  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
-  MAINT=$MAINTAINER_MODE_TRUE
-  AC_SUBST([MAINT])dnl
-]
-)
-
-# Check to see how 'make' treats includes.                 -*- Autoconf -*-
-
-# Copyright (C) 2001-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_MAKE_INCLUDE()
-# -----------------
-# Check to see how make treats includes.
-AC_DEFUN([AM_MAKE_INCLUDE],
-[am_make=${MAKE-make}
-cat > confinc << 'END'
-am__doit:
-       @echo this is the am__doit target
-.PHONY: am__doit
-END
-# If we don't find an include directive, just comment out the code.
-AC_MSG_CHECKING([for style of include used by $am_make])
-am__include="#"
-am__quote=
-_am_result=none
-# First try GNU make style include.
-echo "include confinc" > confmf
-# Ignore all kinds of additional output from 'make'.
-case `$am_make -s -f confmf 2> /dev/null` in #(
-*the\ am__doit\ target*)
-  am__include=include
-  am__quote=
-  _am_result=GNU
-  ;;
-esac
-# Now try BSD make style include.
-if test "$am__include" = "#"; then
-   echo '.include "confinc"' > confmf
-   case `$am_make -s -f confmf 2> /dev/null` in #(
-   *the\ am__doit\ target*)
-     am__include=.include
-     am__quote="\""
-     _am_result=BSD
-     ;;
-   esac
-fi
-AC_SUBST([am__include])
-AC_SUBST([am__quote])
-AC_MSG_RESULT([$_am_result])
-rm -f confinc confmf
-])
-
-# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
-
-# Copyright (C) 1997-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_MISSING_PROG(NAME, PROGRAM)
-# ------------------------------
-AC_DEFUN([AM_MISSING_PROG],
-[AC_REQUIRE([AM_MISSING_HAS_RUN])
-$1=${$1-"${am_missing_run}$2"}
-AC_SUBST($1)])
-
-# AM_MISSING_HAS_RUN
-# ------------------
-# Define MISSING if not defined so far and test if it is modern enough.
-# If it is, set am_missing_run to use it, otherwise, to nothing.
-AC_DEFUN([AM_MISSING_HAS_RUN],
-[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-AC_REQUIRE_AUX_FILE([missing])dnl
-if test x"${MISSING+set}" != xset; then
-  case $am_aux_dir in
-  *\ * | *\    *)
-    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
-  *)
-    MISSING="\${SHELL} $am_aux_dir/missing" ;;
-  esac
-fi
-# Use eval to expand $SHELL
-if eval "$MISSING --is-lightweight"; then
-  am_missing_run="$MISSING "
-else
-  am_missing_run=
-  AC_MSG_WARN(['missing' script is too old or missing])
-fi
-])
-
-# Helper functions for option handling.                     -*- Autoconf -*-
-
-# Copyright (C) 2001-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# _AM_MANGLE_OPTION(NAME)
-# -----------------------
-AC_DEFUN([_AM_MANGLE_OPTION],
-[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
-
-# _AM_SET_OPTION(NAME)
-# --------------------
-# Set option NAME.  Presently that only means defining a flag for this option.
-AC_DEFUN([_AM_SET_OPTION],
-[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
-
-# _AM_SET_OPTIONS(OPTIONS)
-# ------------------------
-# OPTIONS is a space-separated list of Automake options.
-AC_DEFUN([_AM_SET_OPTIONS],
-[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
-
-# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
-# -------------------------------------------
-# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
-AC_DEFUN([_AM_IF_OPTION],
-[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
-
-# Copyright (C) 1999-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# _AM_PROG_CC_C_O
-# ---------------
-# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
-# to automatically call this.
-AC_DEFUN([_AM_PROG_CC_C_O],
-[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-AC_REQUIRE_AUX_FILE([compile])dnl
-AC_LANG_PUSH([C])dnl
-AC_CACHE_CHECK(
-  [whether $CC understands -c and -o together],
-  [am_cv_prog_cc_c_o],
-  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
-  # Make sure it works both with $CC and with simple cc.
-  # Following AC_PROG_CC_C_O, we do the test twice because some
-  # compilers refuse to overwrite an existing .o file with -o,
-  # though they will create one.
-  am_cv_prog_cc_c_o=yes
-  for am_i in 1 2; do
-    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
-         && test -f conftest2.$ac_objext; then
-      : OK
-    else
-      am_cv_prog_cc_c_o=no
-      break
-    fi
-  done
-  rm -f core conftest*
-  unset am_i])
-if test "$am_cv_prog_cc_c_o" != yes; then
-   # Losing compiler, so override with the script.
-   # FIXME: It is wrong to rewrite CC.
-   # But if we don't then we get into trouble of one sort or another.
-   # A longer-term fix would be to have automake use am__CC in this case,
-   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
-   CC="$am_aux_dir/compile $CC"
-fi
-AC_LANG_POP([C])])
-
-# For backward compatibility.
-AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
-
-# Copyright (C) 2001-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_RUN_LOG(COMMAND)
-# -------------------
-# Run COMMAND, save the exit status in ac_status, and log it.
-# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
-AC_DEFUN([AM_RUN_LOG],
-[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
-   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
-   ac_status=$?
-   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
-   (exit $ac_status); }])
-
-# Check to make sure that the build environment is sane.    -*- Autoconf -*-
-
-# Copyright (C) 1996-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_SANITY_CHECK
-# ---------------
-AC_DEFUN([AM_SANITY_CHECK],
-[AC_MSG_CHECKING([whether build environment is sane])
-# Reject unsafe characters in $srcdir or the absolute working directory
-# name.  Accept space and tab only in the latter.
-am_lf='
-'
-case `pwd` in
-  *[[\\\"\#\$\&\'\`$am_lf]]*)
-    AC_MSG_ERROR([unsafe absolute working directory name]);;
-esac
-case $srcdir in
-  *[[\\\"\#\$\&\'\`$am_lf\ \   ]]*)
-    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
-esac
-
-# Do 'set' in a subshell so we don't clobber the current shell's
-# arguments.  Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
-   am_has_slept=no
-   for am_try in 1 2; do
-     echo "timestamp, slept: $am_has_slept" > conftest.file
-     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
-     if test "$[*]" = "X"; then
-       # -L didn't work.
-       set X `ls -t "$srcdir/configure" conftest.file`
-     fi
-     if test "$[*]" != "X $srcdir/configure conftest.file" \
-       && test "$[*]" != "X conftest.file $srcdir/configure"; then
-
-       # If neither matched, then we have a broken ls.  This can happen
-       # if, for instance, CONFIG_SHELL is bash and it inherits a
-       # broken ls alias from the environment.  This has actually
-       # happened.  Such a system could not be considered "sane".
-       AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
-  alias in your environment])
-     fi
-     if test "$[2]" = conftest.file || test $am_try -eq 2; then
-       break
-     fi
-     # Just in case.
-     sleep 1
-     am_has_slept=yes
-   done
-   test "$[2]" = conftest.file
-   )
-then
-   # Ok.
-   :
-else
-   AC_MSG_ERROR([newly created file is older than distributed files!
-Check your system clock])
-fi
-AC_MSG_RESULT([yes])
-# If we didn't sleep, we still need to ensure time stamps of config.status and
-# generated files are strictly newer.
-am_sleep_pid=
-if grep 'slept: no' conftest.file >/dev/null 2>&1; then
-  ( sleep 1 ) &
-  am_sleep_pid=$!
-fi
-AC_CONFIG_COMMANDS_PRE(
-  [AC_MSG_CHECKING([that generated files are newer than configure])
-   if test -n "$am_sleep_pid"; then
-     # Hide warnings about reused PIDs.
-     wait $am_sleep_pid 2>/dev/null
-   fi
-   AC_MSG_RESULT([done])])
-rm -f conftest.file
-])
-
-# Copyright (C) 2009-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_SILENT_RULES([DEFAULT])
-# --------------------------
-# Enable less verbose build rules; with the default set to DEFAULT
-# ("yes" being less verbose, "no" or empty being verbose).
-AC_DEFUN([AM_SILENT_RULES],
-[AC_ARG_ENABLE([silent-rules], [dnl
-AS_HELP_STRING(
-  [--enable-silent-rules],
-  [less verbose build output (undo: "make V=1")])
-AS_HELP_STRING(
-  [--disable-silent-rules],
-  [verbose build output (undo: "make V=0")])dnl
-])
-case $enable_silent_rules in @%:@ (((
-  yes) AM_DEFAULT_VERBOSITY=0;;
-   no) AM_DEFAULT_VERBOSITY=1;;
-    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
-esac
-dnl
-dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
-dnl do not support nested variable expansions.
-dnl See automake bug#9928 and bug#10237.
-am_make=${MAKE-make}
-AC_CACHE_CHECK([whether $am_make supports nested variables],
-   [am_cv_make_support_nested_variables],
-   [if AS_ECHO([['TRUE=$(BAR$(V))
-BAR0=false
-BAR1=true
-V=1
-am__doit:
-       @$(TRUE)
-.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
-  am_cv_make_support_nested_variables=yes
-else
-  am_cv_make_support_nested_variables=no
-fi])
-if test $am_cv_make_support_nested_variables = yes; then
-  dnl Using '$V' instead of '$(V)' breaks IRIX make.
-  AM_V='$(V)'
-  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
-else
-  AM_V=$AM_DEFAULT_VERBOSITY
-  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
-fi
-AC_SUBST([AM_V])dnl
-AM_SUBST_NOTMAKE([AM_V])dnl
-AC_SUBST([AM_DEFAULT_V])dnl
-AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
-AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
-AM_BACKSLASH='\'
-AC_SUBST([AM_BACKSLASH])dnl
-_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
-])
-
-# Copyright (C) 2001-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# AM_PROG_INSTALL_STRIP
-# ---------------------
-# One issue with vendor 'install' (even GNU) is that you can't
-# specify the program used to strip binaries.  This is especially
-# annoying in cross-compiling environments, where the build's strip
-# is unlikely to handle the host's binaries.
-# Fortunately install-sh will honor a STRIPPROG variable, so we
-# always use install-sh in "make install-strip", and initialize
-# STRIPPROG with the value of the STRIP variable (set by the user).
-AC_DEFUN([AM_PROG_INSTALL_STRIP],
-[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
-# Installed binaries are usually stripped using 'strip' when the user
-# run "make install-strip".  However 'strip' might not be the right
-# tool to use in cross-compilation environments, therefore Automake
-# will honor the 'STRIP' environment variable to overrule this program.
-dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
-if test "$cross_compiling" != no; then
-  AC_CHECK_TOOL([STRIP], [strip], :)
-fi
-INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
-AC_SUBST([INSTALL_STRIP_PROGRAM])])
-
-# Copyright (C) 2006-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# _AM_SUBST_NOTMAKE(VARIABLE)
-# ---------------------------
-# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
-# This macro is traced by Automake.
-AC_DEFUN([_AM_SUBST_NOTMAKE])
-
-# AM_SUBST_NOTMAKE(VARIABLE)
-# --------------------------
-# Public sister of _AM_SUBST_NOTMAKE.
-AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
-
-# Check how to create a tarball.                            -*- Autoconf -*-
-
-# Copyright (C) 2004-2013 Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# _AM_PROG_TAR(FORMAT)
-# --------------------
-# Check how to create a tarball in format FORMAT.
-# FORMAT should be one of 'v7', 'ustar', or 'pax'.
-#
-# Substitute a variable $(am__tar) that is a command
-# writing to stdout a FORMAT-tarball containing the directory
-# $tardir.
-#     tardir=directory && $(am__tar) > result.tar
-#
-# Substitute a variable $(am__untar) that extract such
-# a tarball read from stdin.
-#     $(am__untar) < result.tar
-#
-AC_DEFUN([_AM_PROG_TAR],
-[# Always define AMTAR for backward compatibility.  Yes, it's still used
-# in the wild :-(  We should find a proper way to deprecate it ...
-AC_SUBST([AMTAR], ['$${TAR-tar}'])
-
-# We'll loop over all known methods to create a tar archive until one works.
-_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
-
-m4_if([$1], [v7],
-  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
-
-  [m4_case([$1],
-    [ustar],
-     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
-      # There is notably a 21 bits limit for the UID and the GID.  In fact,
-      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
-      # and bug#13588).
-      am_max_uid=2097151 # 2^21 - 1
-      am_max_gid=$am_max_uid
-      # The $UID and $GID variables are not portable, so we need to resort
-      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
-      # below are definitely unexpected, so allow the users to see them
-      # (that is, avoid stderr redirection).
-      am_uid=`id -u || echo unknown`
-      am_gid=`id -g || echo unknown`
-      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
-      if test $am_uid -le $am_max_uid; then
-         AC_MSG_RESULT([yes])
-      else
-         AC_MSG_RESULT([no])
-         _am_tools=none
-      fi
-      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
-      if test $am_gid -le $am_max_gid; then
-         AC_MSG_RESULT([yes])
-      else
-        AC_MSG_RESULT([no])
-        _am_tools=none
-      fi],
-
-  [pax],
-    [],
-
-  [m4_fatal([Unknown tar format])])
-
-  AC_MSG_CHECKING([how to create a $1 tar archive])
-
-  # Go ahead even if we have the value already cached.  We do so because we
-  # need to set the values for the 'am__tar' and 'am__untar' variables.
-  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
-
-  for _am_tool in $_am_tools; do
-    case $_am_tool in
-    gnutar)
-      for _am_tar in tar gnutar gtar; do
-        AM_RUN_LOG([$_am_tar --version]) && break
-      done
-      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
-      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
-      am__untar="$_am_tar -xf -"
-      ;;
-    plaintar)
-      # Must skip GNU tar: if it does not support --format= it doesn't create
-      # ustar tarball either.
-      (tar --version) >/dev/null 2>&1 && continue
-      am__tar='tar chf - "$$tardir"'
-      am__tar_='tar chf - "$tardir"'
-      am__untar='tar xf -'
-      ;;
-    pax)
-      am__tar='pax -L -x $1 -w "$$tardir"'
-      am__tar_='pax -L -x $1 -w "$tardir"'
-      am__untar='pax -r'
-      ;;
-    cpio)
-      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
-      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
-      am__untar='cpio -i -H $1 -d'
-      ;;
-    none)
-      am__tar=false
-      am__tar_=false
-      am__untar=false
-      ;;
-    esac
-
-    # If the value was cached, stop now.  We just wanted to have am__tar
-    # and am__untar set.
-    test -n "${am_cv_prog_tar_$1}" && break
-
-    # tar/untar a dummy directory, and stop if the command works.
-    rm -rf conftest.dir
-    mkdir conftest.dir
-    echo GrepMe > conftest.dir/file
-    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
-    rm -rf conftest.dir
-    if test -s conftest.tar; then
-      AM_RUN_LOG([$am__untar <conftest.tar])
-      AM_RUN_LOG([cat conftest.dir/file])
-      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
-    fi
-  done
-  rm -rf conftest.dir
-
-  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
-  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
-
-AC_SUBST([am__tar])
-AC_SUBST([am__untar])
-]) # _AM_PROG_TAR
-
-m4_include([m4/gpg-error.m4])
-m4_include([m4/libtool.m4])
-m4_include([m4/ltoptions.m4])
-m4_include([m4/ltsugar.m4])
-m4_include([m4/ltversion.m4])
-m4_include([m4/lt~obsolete.m4])
-m4_include([m4/noexecstack.m4])
-m4_include([m4/onceonly.m4])
-m4_include([m4/socklen.m4])
-m4_include([m4/sys_socket_h.m4])
-m4_include([acinclude.m4])
index 09a9b9c..646f659 100644 (file)
@@ -2,15 +2,11 @@
 
 case "$myhost" in
   w32)
-    configure_opts="
-      --with-gpg-error-prefix=@SYSROOT@
-      "
+    configure_opts=""
     ;;
 
   amd64)
-    configure_opts="
-      --with-gpg-error-prefix=@SYSROOT@
-     "
+    configure_opts=""
     ;;
 esac
 
index 471193c..9b36158 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # autogen.sh
-# Copyright (C) 2003, 2014 g10 Code GmbH
+# Copyright (C) 2003, 2014, 2017, 2018 g10 Code GmbH
 #
 # This file is free software; as a special exception the author gives
 # unlimited permission to copy and/or distribute it, with or without
@@ -15,7 +15,7 @@
 # configure it for the respective package.  It is maintained as part of
 # GnuPG and source copied by other packages.
 #
-# Version: 2014-01-10
+# Version: 2018-07-10
 
 configure_ac="configure.ac"
 
@@ -41,7 +41,7 @@ fatal () {
 
 info () {
     if [ -z "${SILENT}" ]; then
-      echo "autogen.sh:" "$*"
+      echo "autogen.sh:" "$*" >&2
     fi
 }
 
@@ -70,6 +70,8 @@ MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX}
 DIE=no
 FORCE=
 SILENT=
+PRINT_HOST=no
+PRINT_BUILD=no
 tmp=$(dirname "$0")
 tsdir=$(cd "${tmp}"; pwd)
 
@@ -77,7 +79,18 @@ if [ -n "${AUTOGEN_SH_SILENT}" ]; then
   SILENT=" --silent"
 fi
 if test x"$1" = x"--help"; then
-  echo "usage: ./autogen.sh [--silent] [--force] [--build-TYPE] [ARGS]"
+  echo "usage: ./autogen.sh [OPTIONS] [ARGS]"
+  echo "  Options:"
+  echo "    --silent       Silent operation"
+  echo "    --force        Pass --force to autoconf"
+  echo "    --find-version Helper for configure.ac"
+  echo "    --git-build    Run all commands to  build from a Git"
+  echo "    --print-host   Print only the host triplet"
+  echo "    --print-build  Print only the build platform triplet"
+  echo "    --build-TYPE   Configure to cross build for TYPE"
+  echo ""
+  echo "  ARGS are passed to configure in --build-TYPE mode."
+  echo "  Configuration for this script is expected in autogen.rc"
   exit 0
 fi
 if test x"$1" = x"--silent"; then
@@ -88,6 +101,14 @@ if test x"$1" = x"--force"; then
   FORCE=" --force"
   shift
 fi
+if test x"$1" = x"--print-host"; then
+  PRINT_HOST=yes
+  shift
+fi
+if test x"$1" = x"--print-build"; then
+  PRINT_BUILD=yes
+  shift
+fi
 
 
 # Reject unsafe characters in $HOME, $tsdir and cwd.  We consider spaces
@@ -133,6 +154,15 @@ amd64_toolprefixes=
 myhost=""
 myhostsub=""
 case "$1" in
+    --find-version)
+        myhost="find-version"
+        SILENT=" --silent"
+        shift
+        ;;
+    --git-build)
+        myhost="git-build"
+        shift
+        ;;
     --build-w32)
         myhost="w32"
         shift
@@ -161,6 +191,25 @@ esac
 die_p
 
 
+# **** GIT BUILD ****
+# This is a helper to build from git.
+if [ "$myhost" = "git-build" ]; then
+    tmp="$(pwd)"
+    cd "$tsdir" || fatal "error cd-ing to $tsdir"
+    ./autogen.sh || fatal "error running ./autogen.sh"
+    cd "$tmp"   || fatal "error cd-ing back to $tmp"
+    die_p
+    "$tsdir"/configure || fatal "error running $tsdir/configure"
+    die_p
+    make || fatal "error running make"
+    die_p
+    make check || fatal "error running male check"
+    die_p
+    exit 0
+fi
+# **** end GIT BUILD ****
+
+
 # Source our configuration
 if [ -f "${tsdir}/autogen.rc" ]; then
     . "${tsdir}/autogen.rc"
@@ -172,16 +221,78 @@ if [ -f "$HOME/.gnupg-autogen.rc" ]; then
     . "$HOME/.gnupg-autogen.rc"
 fi
 
+
+# **** FIND VERSION ****
+# This is a helper for the configure.ac M4 magic
+# Called
+#   ./autogen.sh --find-version PACKAGE MAJOR MINOR [MICRO]
+# returns a complete version string with automatic beta numbering.
+if [ "$myhost" = "find-version" ]; then
+    package="$1"
+    major="$2"
+    minor="$3"
+    micro="$4"
+
+    if [ -z "$package" -o -z "$major" -o -z "$minor" ]; then
+      echo "usage: ./autogen.sh --find-version PACKAGE MAJOR MINOR [MICRO]" >&2
+      exit 1
+    fi
+
+    if [ -z "$micro" ]; then
+      matchstr1="$package-$major.[0-9]*"
+      matchstr2="$package-$major-base"
+      vers="$major.$minor"
+    else
+      matchstr1="$package-$major.$minor.[0-9]*"
+      matchstr2="$package-$major.$minor-base"
+      vers="$major.$minor.$micro"
+    fi
+
+    beta=no
+    if [ -e .git ]; then
+      ingit=yes
+      tmp=$(git describe --match "${matchstr1}" --long 2>/dev/null)
+      tmp=$(echo "$tmp" | sed s/^"$package"//)
+      if [ -n "$tmp" ]; then
+          tmp=$(echo "$tmp" | sed s/^"$package"//  \
+                | awk -F- '$3!=0 && $3 !~ /^beta/ {print"-beta"$3}')
+      else
+          tmp=$(git describe --match "${matchstr2}" --long 2>/dev/null \
+                | awk -F- '$4!=0{print"-beta"$4}')
+      fi
+      [ -n "$tmp" ] && beta=yes
+      rev=$(git rev-parse --short HEAD | tr -d '\n\r')
+      rvd=$((0x$(echo ${rev} | dd bs=1 count=4 2>/dev/null)))
+    else
+      ingit=no
+      beta=yes
+      tmp="-unknown"
+      rev="0000000"
+      rvd="0"
+    fi
+
+    echo "$package-$vers$tmp:$beta:$ingit:$vers$tmp:$vers:$tmp:$rev:$rvd:"
+    exit 0
+fi
+# **** end FIND VERSION ****
+
+
+if [ ! -f "$tsdir/build-aux/config.guess" ]; then
+    fatal "$tsdir/build-aux/config.guess not found"
+    exit 1
+fi
+build=`$tsdir/build-aux/config.guess`
+if [ $PRINT_BUILD = yes ]; then
+    echo "$build"
+    exit 0
+fi
+
+
+
 # ******************
 #  W32 build script
 # ******************
 if [ "$myhost" = "w32" ]; then
-    if [ ! -f "$tsdir/build-aux/config.guess" ]; then
-        fatal "$tsdir/build-aux/config.guess not found"
-        exit 1
-    fi
-    build=`$tsdir/build-aux/config.guess`
-
     case $myhostsub in
         ce)
           w32root="$w32ce_root"
@@ -222,6 +333,10 @@ if [ "$myhost" = "w32" ]; then
         fi
         die_p
     fi
+    if [ $PRINT_HOST = yes ]; then
+        echo "$host"
+        exit 0
+    fi
 
     if [ -f "$tsdir/config.log" ]; then
         if ! head $tsdir/config.log | grep "$host" >/dev/null; then
@@ -232,7 +347,8 @@ if [ "$myhost" = "w32" ]; then
 
     $tsdir/configure --enable-maintainer-mode ${SILENT} \
              --prefix=${w32root}  \
-             --host=${host} --build=${build} \
+             --host=${host} --build=${build} SYSROOT=${w32root} \
+             PKG_CONFIG_LIBDIR=${w32root}/lib/pkgconfig \
              ${configure_opts} ${extraoptions} "$@"
     rc=$?
     exit $rc
@@ -242,13 +358,6 @@ fi
 # ***** AMD64 cross build script *******
 # Used to cross-compile for AMD64 (for testing)
 if [ "$myhost" = "amd64" ]; then
-    shift
-    if [ ! -f $tsdir/build-aux/config.guess ]; then
-        echo "$tsdir/build-aux/config.guess not found" >&2
-        exit 1
-    fi
-    build=`$tsdir/build-aux/config.guess`
-
     [ -z "$amd64root" ] && amd64root="$HOME/amd64root"
     info "Using $amd64root as standard install directory"
     replace_sysroot
@@ -269,6 +378,10 @@ if [ "$myhost" = "amd64" ]; then
         echo "Stop." >&2
         exit 1
     fi
+    if [ $PRINT_HOST = yes ]; then
+        echo "$host"
+        exit 0
+    fi
 
     if [ -f "$tsdir/config.log" ]; then
         if ! head $tsdir/config.log | grep "$host" >/dev/null; then
@@ -341,13 +454,16 @@ fi
 
 # Check the git setup.
 if [ -d .git ]; then
-  CP="cp -a"
-  [ -z "${SILENT}" ] && CP="$CP -v"
+  CP="cp -p"
+  # If we have a GNU cp we can add -v
+  if cp --version >/dev/null 2>/dev/null; then
+    [ -z "${SILENT}" ] && CP="$CP -v"
+  fi
   if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then
     [ -z "${SILENT}" ] && cat <<EOF
 *** Activating trailing whitespace git pre-commit hook. ***
     For more information see this thread:
-      http://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084html
+      https://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084.html
     To deactivate this pre-commit hook again move .git/hooks/pre-commit
     and .git/hooks/pre-commit.sample out of the way.
 EOF
@@ -371,6 +487,10 @@ EOF
 EOF
       $CP build-aux/git-hooks/commit-msg .git/hooks/commit-msg
       chmod +x  .git/hooks/commit-msg
+      if [ x"${display_name}" != x ]; then
+         git config format.subjectPrefix "PATCH ${display_name}"
+         git config sendemail.to "${patches_to}"
+      fi
   fi
 fi
 
diff --git a/build-aux/db2any b/build-aux/db2any
new file mode 100755 (executable)
index 0000000..a240aaa
--- /dev/null
@@ -0,0 +1,489 @@
+#!/bin/sh
+# db2any - Docbook to html/ps/info rendering
+#
+#      Copyright (C) 2000, 2001 Free Software Foundation, Inc
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+#
+# Note: This requires a Posix shell
+#
+# $Id$
+
+pgm="db2any"
+version="0.7.3"
+
+usage () {
+    echo 'usage: db2any [--help] [options] filename' >&2
+    exit 1
+}
+
+show_banner () {
+       cat <<EOF
+$pgm $version
+Copyright (C) 2001 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+EOF
+}
+
+show_help () {
+    show_banner
+    cat <<EOF
+usage: db2any [options] docbookfile
+
+Options:
+    --mode    select the mode (one of: ${all_modes})
+    --help
+    --nosplit
+    --copyfiles
+    --systemcheck
+    --verbose
+    --draft
+    --manvolume n
+    --usestyle file
+    --ignore-xref      [not yet implemented]
+
+EOF
+    exit 0
+}
+
+# a list of all possible stylesheet locations
+stylesheet_dirs='
+/usr/local/lib/dsssl/stylesheets/docbook
+/usr/local/share/dsssl/stylesheets/docbook
+/usr/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh
+/usr/local/share/sgml/stylesheet/dsssl/docbook/nwalsh
+/usr/lib/dsssl/stylesheets/docbook
+/usr/share/dsssl/stylesheets/docbook
+/usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh
+/usr/share/sgml/stylesheet/dsssl/docbook/nwalsh
+/usr/lib/sgml/stylesheets/nwalsh-modular
+/usr/share/sgml/stylesheets/nwalsh-modular
+'
+
+all_modes="check tex html man texinfo"
+input=
+verbose=no
+draft=no
+nosplit=no
+copyfiles=no
+systemcheck_only=no
+mode=none
+manvolume="man"
+usestyle=""
+expected_args=1
+ignore_xref=no
+while test "`echo $1 | head -c1`" = "-"; do
+    case $1 in
+      --version)
+       echo "$pgm $version"
+       exit 0
+       ;;
+      --help|-h|-help)
+       show_help
+       exit 0
+       ;;
+      --nosplit)
+       nosplit=yes
+       ;;
+      --copyfiles)
+       copyfiles=yes
+       ;;
+      --systemcheck)
+       systemcheck_only=yes
+       expected_args=0
+       ;;
+      --mode)
+       shift
+       if [ $# = 0 ]; then
+          echo "$pgm: missing argument for --mode" >&2
+          exit 1
+       fi
+       mode="$1"
+       ;;
+      --manvolume)
+       shift
+       if [ $# = 0 ]; then
+          echo "$pgm: missing argument for --manvolume" >&2
+          exit 1
+       fi
+       manvolume="$1"
+       ;;
+      --usestyle)
+       shift
+       if [ $# = 0 ]; then
+          echo "$pgm: missing argument for --usestyle" >&2
+          exit 1
+       fi
+       usestyle="$1"
+       ;;
+      --verbose)
+       verbose=yes
+       ;;
+      --draft)
+       draft=yes
+       ;;
+      --ignore-xref)
+        ignore_xref=yes
+        ;;
+      --)
+       shift
+       break
+       ;;
+      *)
+       echo "$pgm: invalid option $1" >&2
+       exit 1
+       ;;
+    esac
+    shift
+done
+
+if [ $# = $expected_args ]; then
+    if [ $# = 1 ]; then
+       input="$1"
+    fi
+else
+   usage
+fi
+
+# check the mode
+case "$mode" in
+    html|HTML)
+       mode=html
+       ;;
+    tex|TEX|TeX|dvi)
+       mode=dvi
+       ;;
+    man|MAN)
+       mode=man
+       ;;
+    texi|TEXI|texinfo|TEXINFO)
+       mode=texinfo
+       ;;
+    check)
+       ;;
+    none)
+       if [ $systemcheck_only != yes ]; then
+           echo "$pgm: no mode specified; use one of: ${all_modes}" >&2
+           exit 1
+       fi
+       ;;
+    *)
+       echo "$pgm: invalid mode $mode" >&2
+       echo "$pgm: valid modes are: ${all_modes}"  >&2
+       exit 1
+       ;;
+esac
+
+if [ -n $usestyle ]; then
+   if [ ! -f $usestyle ]; then
+      echo "$pgm: cannot access local stylesteet" >&2
+      exit 1
+   fi
+fi
+
+#######################################
+#   Options are all parsed here       #
+#######################################
+
+# check whether the given program is availbale in the path
+check_prog () {
+    tmp="$1"
+    save_ifs="$IFS"; IFS=":"
+    for i in $PATH; do
+        test -z "$i" && i=.
+        if test -f $i/$tmp; then
+             IFS="$save_ifs"
+             return 0
+        fi
+    done
+    IFS="$save_ifs"
+    return 1
+}
+
+
+# Figure out all what we need to know about the system we are
+# running on and where the Docbook tools are installed.
+# Tell about it when running in verbose mode.
+do_systemcheck () {
+    # look for Jade
+    jade_version=`jade -v </dev/null 2>&1 | \
+                  sed -n 's/.*:I:.*Jade version "\([0-9.]*\)"/\1/p'`
+    if [ -z "$jade_version" ]; then
+       echo "$pgm: error: jade not found" >&2
+       exit 1
+    fi
+    [ $verbose = yes ] && echo "$pgm: Jade version $jade_version found" >&2
+
+    # look for JadeTeX
+    if ! jadetex -v 2>/dev/null | grep -q '^TeX' ; then
+       echo "$pgm: error: jadetex not found" >&2
+       exit 1
+    fi
+
+    # look for the docbook-to-man script. Fixme: we should check that it
+    # it is a recent version.
+    if ! docbook-to-man 2>&1 | grep -q '^usage' ; then
+       echo "$pgm: error: docbook-to-man not found" >&2
+       exit 1
+    fi
+    [ $verbose = yes ] && echo "$pgm: docbook-to-man found" >&2
+
+    # look for the docbook-to-texi scripts.
+    if ! check_prog docbook2texi ;  then
+       echo "$pgm: error: docbook2texi not found" >&2
+       exit 1
+    fi
+    [ $verbose = yes ] && echo "$pgm: docbook2texi found" >&2
+    if ! sgml2xml -v /dev/null 2>&1 | grep 'SP version' >/dev/null 2>&1 ; then
+       echo "$pgm: error: sgml2xml not found" >&2
+       exit 1
+    fi
+    [ $verbose = yes ] && echo "$pgm: sgml2xml found" >&2
+
+    # figure out where our stylesheets are
+    tex_stylesheet=none
+    for d in ${stylesheet_dirs}; do
+       file=${d}/print/docbook.dsl
+       if [ -f $file ]; then
+           tex_stylesheet=$file
+           break
+       fi
+    done
+    [ $verbose = yes ] && echo "$pgm: TeX stylesheet: ${tex_stylesheet}" >&2
+    html_stylesheet=none
+    for d in ${stylesheet_dirs}; do
+       file=${d}/html/docbook.dsl
+       if [ -f $file ]; then
+           html_stylesheet=$file
+           break
+       fi
+    done
+    [ $verbose = yes ] && echo "$pgm: HTML stylesheet: ${html_stylesheet}" >&2
+    if [ $tex_stylesheet = none -o $html_stylesheet = none ]; then
+       echo "$pgm: error: stylesheets not found" >&2
+       exit 1
+    fi
+
+}
+
+
+# Render the docbook as HTML
+render_html () {
+    output="`basename $input| sed 's/\.sgml$//'`.html"
+
+    if [ -n "$usestyle" ]; then
+       tmpstyle="`pwd`/`basename $usestyle`-html.tmp"
+       if [ ! -f $tmpstyle -o $usestyle -nt $tmpstyle ]; then
+           sed "s%@DOCBOOK_DSL@%$html_stylesheet%" $usestyle > $tmpstyle
+       fi
+    else
+       tmpstyle="$tex_stylesheet"
+    fi
+
+
+    # --nosplts creates just one HTML file
+    if test $nosplit = yes; then
+       echo "running jade on '$input' ..." >&2
+       jade -D . -d $tmpstyle -t sgml -i html -V nochunks $input > $output
+       echo "$output created"
+       return 0
+    fi
+
+    # Make sure that we have a html subdir
+    if test -d html ; then
+       :
+    else
+       if mkdir html; then
+           echo "'html' directory created" >&2
+       else
+           echo "failed to create 'html' directory" >&2
+           exit 1
+       fi
+    fi
+
+    outputdir="html/`basename $input| sed 's/\.sgml$//'`"
+
+    if test -d $outputdir ; then
+       :
+    else
+       if mkdir $outputdir; then
+           echo "'$outputdir' created" >&2
+       else
+           echo "failed to create '$outputdir'" >&2
+           exit 1
+       fi
+    fi
+    echo "creating html pages in '$outputdir' ..." >&2
+    if test "$input" = "`basename $input`"; then
+       inp="../../$input"
+    else
+       inp="$input"
+    fi
+
+    [ $verbose = yes ] && echo "running jade on '$inp' ..." >&2
+    (cd $outputdir && jade -D . -t sgml -i html -d $tmpstyle $inp )
+    [ $verbose = yes ] && echo "html version in '$outputdir' created" >&2
+
+    # break out all filerefs and copy them to the outputdirectory
+    # fixme: handling of path components is wrong
+    if test $copyfiles = yes; then
+       echo "looking for filerefs ..." >&2
+       for file in `nsgmls -i html $input \
+                       | awk '/^AFILEREF[ \t]+CDATA/ {print $3}'`; do
+           d=$outputdir/`basename $file`
+           if cat $file > $outputdir/`basename $file` ; then
+               echo "  $file -> $d" >&2
+           fi
+       done
+    fi
+
+    mainfile=`ls $outputdir/${doctype}* | head -1`
+
+    # create a html index file for it, so that we can more easy
+    # find the rendred pages
+    cat > $output <<EOF
+<html><title>$output</title>
+<body>
+
+<a href="$mainfile">$mainfile</a>
+
+</body>
+</html>
+EOF
+
+    [ $verbose = yes ] && echo "$output created with link to '$mainfile'" >&2
+}
+
+
+# This function expects the source file in $texfile and
+# the name of the logfle in $logfile
+run_jadetex () {
+    [ -f $logfile ] && rm $logfile
+    jadetex $texfile
+    if ! tail $logfile | grep -q '^Output written on'; then
+       echo "JadeTeX failed" >&2
+       exit 1
+    fi
+}
+
+# Render the docbook to DVI
+render_dvi () {
+    output="`basename $input| sed 's/\.sgml$//'`.dvi"
+    texfile="`basename $input| sed 's/\.sgml$//'`.tex"
+    logfile="`basename $input| sed 's/\.sgml$//'`.log"
+    auxfile="`basename $input| sed 's/\.sgml$//'`.aux"
+
+    if [ -n "$usestyle" ]; then
+       tmpstyle="`basename $usestyle`-tex.tmp"
+       if [ ! -f $tmpstyle -o $usestyle -nt $tmpstyle ]; then
+           sed "s%@DOCBOOK_DSL@%$tex_stylesheet%" $usestyle > $tmpstyle
+       fi
+    else
+       tmpstyle="$tex_stylesheet"
+    fi
+    [ $verbose = yes ] && echo "running jade on '$input' ..." >&2
+    jade -D . -t tex -i tex -d $tmpstyle -o $texfile $input
+    if ! tail $texfile | grep -q '\\endFOT{}'; then
+       echo "Jade failed" >&2
+       exit 1
+    fi
+
+    # Better delete the aux file first
+    [ -f $auxfile ] && rm $auxfile
+    # The first run won't get the references right, so we have to
+    # run it 2 or 3 times.  JadeTex doesn't indicate whether a third
+    # run is required, so we do it always.
+    run_jadetex
+    if [ $draft = no ]; then
+       if tail -100 $logfile \
+          | grep -q '^LaTeX Warning: There were undefined references'; then
+          echo 'running JadeTeX a second and third 2time' >&2
+          run_jadetex
+          run_jadetex
+       fi
+    fi
+
+    [ $verbose = yes ] && echo "$output created as '$output'" >&2
+}
+
+# Render the docbook to troff
+render_man () {
+    output="`basename $input| sed 's/\.sgml$//'`.$manvolume"
+
+    [ $verbose = yes ] && echo "running docbook-to-man on '$input' ..." >&2
+    docbook-to-man $input > $output
+    [ $verbose = yes ] && echo "man page '$output' created" >&2
+}
+
+# Render the docbook to texinfo
+render_texinfo () {
+    output="`basename $input| sed 's/\.sgml$/.texi/'`"
+    tmpxml="`basename $input| sed 's/\.sgml$/.xml/'`"
+
+    [ $verbose = yes ] && echo "running sgml2xml on '$input' ..." >&2
+    sgml2xml -x lower $input > $tmpxml
+    [ $verbose = yes ] && echo "running docbook2texi on '$tmpxml' ..." >&2
+    docbook2texi $tmpxml | sed 's,--,---,' >$output
+    rm $tmpxml
+    [ $verbose = yes ] && echo "texinfo '$output' created" >&2
+
+}
+
+#######################################
+#       main function                #
+#######################################
+
+do_systemcheck
+[ $systemcheck_only = yes ] && exit 0
+
+if [ ! -f "$input" ]; then
+    input="$input.sgml"
+    if [ ! -f "$input" ]; then
+       echo "$pgm: '$input': no such file" >&2
+       exit 1
+    fi
+fi
+
+# grep the document type
+doctype=`grep -i '\<doctype' $input|awk 'NR==1 {print $2}'| tr '[A-Z]' '[a-z]'`
+if test -z "$doctype"; then
+    echo "$pgm: error: no DOCTYPE declaration found" >&2
+    exit 1
+fi
+[ $verbose = yes ] &&  echo "$input: DOCTYPE is '$doctype'" >&2
+
+case $mode in
+    check)
+       nsgmls -vs $input
+       exit $?
+       ;;
+    html)
+       render_html
+       ;;
+    dvi)
+       render_dvi
+       ;;
+    man)
+       render_man
+       ;;
+    texinfo)
+       render_texinfo
+       ;;
+esac
+
+
+exit 0
diff --git a/build-aux/distfiles b/build-aux/distfiles
new file mode 100644 (file)
index 0000000..80e4f79
--- /dev/null
@@ -0,0 +1 @@
+db2any
diff --git a/build-aux/git-hooks/commit-msg b/build-aux/git-hooks/commit-msg
new file mode 100755 (executable)
index 0000000..3ca918b
--- /dev/null
@@ -0,0 +1,133 @@
+eval '(exit $?0)' && eval 'exec perl -w "$0" ${1+"$@"}'
+  & eval 'exec perl -w "$0" $argv:q'
+    if 0;
+
+# An hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, copy it to "~/.git/hooks/commit-msg".
+#
+# This script is based on the one from GNU coreutils.
+
+use strict;
+use warnings;
+(my $ME = $0) =~ s|.*/||;
+
+my $editor = $ENV{EDITOR} || 'vi';
+$ENV{PATH} = '/bin:/usr/bin';
+
+# Rewrite the $LOG_FILE (old contents in @$LINE_REF) with an additional
+# commented diagnostic "# $ERR" line at the top.
+sub rewrite($$$)
+{
+  my ($log_file, $err, $line_ref) = @_;
+  local *LOG;
+  open LOG, '>', $log_file
+    or die "$ME: $log_file: failed to open for writing: $!";
+  print LOG "# $err";
+  print LOG @$line_ref;
+  close LOG
+    or die "$ME: $log_file: failed to rewrite: $!\n";
+}
+
+sub re_edit($)
+{
+  my ($log_file) = @_;
+
+  warn "Interrupt (Ctrl-C) to abort...\n";
+
+  system 'sh', '-c', "$editor $log_file";
+  ($? & 127) || ($? >> 8)
+    and die "$ME: $log_file: the editor ($editor) failed, aborting\n";
+}
+
+# Given a $LOG_FILE name and a \@LINE buffer,
+# read the contents of the file into the buffer and analyze it.
+# If the log message passes muster, return the empty string.
+# If not, return a diagnostic.
+sub check_msg($$)
+{
+  my ($log_file, $line_ref) = @_;
+
+  local *LOG;
+  open LOG, '<', $log_file
+    or return "failed to open for reading: $!";
+  @$line_ref = <LOG>;
+  close LOG;
+
+  my @line = @$line_ref;
+  chomp @line;
+
+  # Don't filter out blank or comment lines; git does that already,
+  # and if we were to ignore them here, it could lead to committing
+  # with lines that start with "#" in the log.
+
+  # Filter out leading blank and comment lines.
+  # while (@line && $line[0] =~ /^(?:#.*|[ \t]*)$/) { shift @line; }
+
+  # Filter out blank and comment lines at EOF.
+  # while (@line && $line[$#line] =~ /^(?:#.*|[ \t]*)$/) { pop @line; }
+
+  @line == 0
+    and return 'no log message';
+
+  # The first line should not be too short
+  8 < length $line[0] || return 'summary line too short';
+
+  # The first line should not start with an asterisk or a hash sign.
+  # An asterisk might indicate that a change entry was started right
+  # at the first line.
+  $line[0] =~ /^[*#]/ && return "summary line starts with an * or #";
+
+  # Second line should be blank or not present.
+  2 <= @line && length $line[1]
+    and return 'second line must be empty';
+
+  # See git-commit(1), this is the --cleanup=scissors option. Everything
+  # after and including this line gets ignored.
+  my $marker = '# ------------------------ >8 ------------------------';
+
+  # Limit line length to allow for the ChangeLog's leading TAB.
+  foreach my $line (@line)
+    {
+      72 < length $line && $line =~ /^[^#]/
+        and return 'line longer than 72 characters';
+
+      last if $line eq $marker;
+    }
+
+  return '';
+}
+
+{
+  @ARGV == 1
+    or die;
+
+  my $log_file = $ARGV[0];
+
+  while (1)
+    {
+      my @line;
+      my $err = check_msg $log_file, \@line;
+      $err eq ''
+        and last;
+      $err = "$ME: $err\n";
+      warn $err;
+      exit 1;
+
+      # Insert the diagnostic as a comment on the first line of $log_file.
+      #rewrite $log_file, $err, \@line;
+      #re_edit $log_file;
+      #
+      ## Stop if our parent is killed.
+      #getppid() == 1
+      #  and last;
+    }
+}
+
+# Local Variables:
+# mode: perl
+# End:
index 95c4510..264b3d3 100644 (file)
@@ -21,7 +21,7 @@
 
 # Need to include ../src in addition to top_srcdir because gcrypt.h is
 # a built header.
-AM_CPPFLAGS = -I../src -I$(top_srcdir)/src
+AM_CPPFLAGS = -I../src -I$(top_srcdir)/src -I../mpi -I$(top_srcdir)/mpi
 AM_CFLAGS = $(GPG_ERROR_CFLAGS)
 
 AM_CCASFLAGS = $(NOEXECSTACK_FLAGS)
@@ -40,91 +40,237 @@ libcipher_la_DEPENDENCIES = $(GCRYPT_MODULES)
 libcipher_la_LIBADD = $(GCRYPT_MODULES)
 
 libcipher_la_SOURCES = \
-cipher.c cipher-internal.h \
-cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \
-cipher-ccm.c cipher-cmac.c cipher-gcm.c cipher-gcm-intel-pclmul.c \
-  cipher-gcm-armv8-aarch32-ce.S cipher-gcm-armv8-aarch64-ce.S \
-cipher-poly1305.c cipher-ocb.c cipher-xts.c \
-cipher-selftest.c cipher-selftest.h \
-pubkey.c pubkey-internal.h pubkey-util.c \
-md.c \
-mac.c mac-internal.h \
-mac-hmac.c mac-cmac.c mac-gmac.c mac-poly1305.c \
-poly1305.c poly1305-internal.h \
-kdf.c kdf-internal.h \
-hmac-tests.c \
-bithelp.h  \
-bufhelp.h  \
-primegen.c  \
-hash-common.c hash-common.h \
-dsa-common.c rsa-common.c \
-sha1.h
+       cipher.c cipher-internal.h \
+       cipher-cbc.c \
+       cipher-cfb.c \
+       cipher-ofb.c \
+       cipher-ctr.c \
+       cipher-aeswrap.c \
+       cipher-ccm.c \
+       cipher-cmac.c \
+       cipher-gcm.c \
+       cipher-poly1305.c \
+       cipher-ocb.c \
+       cipher-xts.c \
+       cipher-eax.c \
+       cipher-siv.c \
+       cipher-gcm-siv.c \
+       cipher-selftest.c cipher-selftest.h \
+       pubkey.c pubkey-internal.h pubkey-util.c \
+       md.c \
+       mac.c mac-internal.h \
+       mac-hmac.c mac-cmac.c mac-gmac.c mac-poly1305.c \
+       poly1305.c poly1305-internal.h \
+       kdf.c kdf-internal.h \
+       bithelp.h  \
+       bufhelp.h  \
+       primegen.c  \
+       hash-common.c hash-common.h \
+       dsa-common.c rsa-common.c \
+       sha1.h
 
 EXTRA_libcipher_la_SOURCES = \
-arcfour.c arcfour-amd64.S \
-blowfish.c blowfish-amd64.S blowfish-arm.S \
-cast5.c cast5-amd64.S cast5-arm.S \
-chacha20.c chacha20-sse2-amd64.S chacha20-ssse3-amd64.S chacha20-avx2-amd64.S \
-  chacha20-armv7-neon.S \
-crc.c \
-  crc-intel-pclmul.c \
-des.c des-amd64.S \
-dsa.c \
-elgamal.c \
-ecc.c ecc-curves.c ecc-misc.c ecc-common.h \
-ecc-ecdsa.c ecc-eddsa.c ecc-gost.c \
-idea.c \
-gost28147.c gost.h \
-gostr3411-94.c \
-md4.c \
-md5.c \
-poly1305-sse2-amd64.S poly1305-avx2-amd64.S poly1305-armv7-neon.S \
-rijndael.c rijndael-internal.h rijndael-tables.h rijndael-aesni.c \
-  rijndael-padlock.c rijndael-amd64.S rijndael-arm.S \
-  rijndael-ssse3-amd64.c rijndael-ssse3-amd64-asm.S \
-  rijndael-armv8-ce.c rijndael-armv8-aarch32-ce.S rijndael-armv8-aarch64-ce.S \
-  rijndael-aarch64.S \
-rmd160.c \
-rsa.c \
-salsa20.c salsa20-amd64.S salsa20-armv7-neon.S \
-scrypt.c \
-seed.c \
-serpent.c serpent-sse2-amd64.S serpent-avx2-amd64.S serpent-armv7-neon.S \
-sha1.c sha1-ssse3-amd64.S sha1-avx-amd64.S sha1-avx-bmi2-amd64.S \
-  sha1-armv7-neon.S sha1-armv8-aarch32-ce.S sha1-armv8-aarch64-ce.S \
-sha256.c sha256-ssse3-amd64.S sha256-avx-amd64.S sha256-avx2-bmi2-amd64.S \
-  sha256-armv8-aarch32-ce.S sha256-armv8-aarch64-ce.S \
-sha512.c sha512-ssse3-amd64.S sha512-avx-amd64.S sha512-avx2-bmi2-amd64.S \
-  sha512-armv7-neon.S sha512-arm.S \
-keccak.c keccak_permute_32.h keccak_permute_64.h keccak-armv7-neon.S \
-stribog.c \
-tiger.c \
-whirlpool.c whirlpool-sse2-amd64.S \
-twofish.c twofish-amd64.S twofish-arm.S twofish-aarch64.S \
-  twofish-avx2-amd64.S \
-rfc2268.c \
-camellia.c camellia.h camellia-glue.c camellia-aesni-avx-amd64.S \
-  camellia-aesni-avx2-amd64.S camellia-arm.S camellia-aarch64.S \
-blake2.c
+       asm-common-aarch64.h \
+       asm-common-amd64.h \
+       asm-common-s390x.h \
+       asm-inline-s390x.h \
+       asm-poly1305-aarch64.h \
+       asm-poly1305-amd64.h \
+       asm-poly1305-s390x.h \
+       arcfour.c arcfour-amd64.S \
+       blowfish.c blowfish-amd64.S blowfish-arm.S \
+       cast5.c cast5-amd64.S cast5-arm.S \
+       chacha20.c chacha20-amd64-ssse3.S chacha20-amd64-avx2.S \
+       chacha20-armv7-neon.S chacha20-aarch64.S \
+       chacha20-ppc.c chacha20-s390x.S \
+       cipher-gcm-ppc.c cipher-gcm-intel-pclmul.c cipher-gcm-armv7-neon.S \
+       cipher-gcm-armv8-aarch32-ce.S cipher-gcm-armv8-aarch64-ce.S \
+       crc.c crc-intel-pclmul.c crc-armv8-ce.c \
+       crc-armv8-aarch64-ce.S \
+       crc-ppc.c \
+       des.c des-amd64.S \
+       dsa.c \
+       elgamal.c \
+       ecc.c ecc-curves.c ecc-misc.c ecc-common.h \
+       ecc-ecdh.c ecc-ecdsa.c ecc-eddsa.c ecc-gost.c ecc-sm2.c \
+       idea.c \
+       gost28147.c gost.h \
+       gostr3411-94.c \
+       md4.c \
+       md5.c \
+       poly1305-s390x.S \
+       rijndael.c rijndael-internal.h rijndael-tables.h   \
+       rijndael-aesni.c rijndael-padlock.c                \
+       rijndael-amd64.S rijndael-arm.S                    \
+       rijndael-ssse3-amd64.c rijndael-ssse3-amd64-asm.S  \
+       rijndael-vaes.c rijndael-vaes-avx2-amd64.S         \
+       rijndael-armv8-ce.c rijndael-armv8-aarch32-ce.S    \
+       rijndael-armv8-aarch64-ce.S rijndael-aarch64.S     \
+       rijndael-ppc.c rijndael-ppc9le.c                   \
+       rijndael-p10le.c rijndael-gcm-p10le.s             \
+       rijndael-ppc-common.h rijndael-ppc-functions.h     \
+       rijndael-s390x.c                                   \
+       rmd160.c \
+       rsa.c \
+       salsa20.c salsa20-amd64.S salsa20-armv7-neon.S \
+       scrypt.c \
+       seed.c \
+       serpent.c serpent-sse2-amd64.S \
+       sm4.c sm4-aesni-avx-amd64.S sm4-aesni-avx2-amd64.S \
+       serpent-avx2-amd64.S serpent-armv7-neon.S \
+       sha1.c sha1-ssse3-amd64.S sha1-avx-amd64.S sha1-avx-bmi2-amd64.S \
+       sha1-avx2-bmi2-amd64.S sha1-armv7-neon.S sha1-armv8-aarch32-ce.S \
+       sha1-armv8-aarch64-ce.S sha1-intel-shaext.c \
+       sha256.c sha256-ssse3-amd64.S sha256-avx-amd64.S \
+       sha256-avx2-bmi2-amd64.S \
+       sha256-armv8-aarch32-ce.S sha256-armv8-aarch64-ce.S \
+       sha256-intel-shaext.c sha256-ppc.c \
+       sha512.c sha512-ssse3-amd64.S sha512-avx-amd64.S \
+       sha512-avx2-bmi2-amd64.S \
+       sha512-armv7-neon.S sha512-arm.S \
+       sha512-ppc.c sha512-ssse3-i386.c \
+       sm3.c sm3-avx-bmi2-amd64.S sm3-aarch64.S \
+       keccak.c keccak_permute_32.h keccak_permute_64.h keccak-armv7-neon.S \
+       stribog.c \
+       tiger.c \
+       whirlpool.c whirlpool-sse2-amd64.S \
+       twofish.c twofish-amd64.S twofish-arm.S twofish-aarch64.S \
+       twofish-avx2-amd64.S \
+       rfc2268.c \
+       camellia.c camellia.h camellia-glue.c camellia-aesni-avx-amd64.S \
+       camellia-aesni-avx2-amd64.h camellia-vaes-avx2-amd64.S \
+       camellia-aesni-avx2-amd64.S camellia-arm.S camellia-aarch64.S \
+       blake2.c \
+       blake2b-amd64-avx2.S blake2s-amd64-avx.S
 
 gost28147.lo: gost-sb.h
 gost-sb.h: gost-s-box
        ./gost-s-box $@
 
 gost-s-box: gost-s-box.c
-       $(CC_FOR_BUILD) -o $@ $(srcdir)/gost-s-box.c
+       $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \
+           $(CPPFLAGS_FOR_BUILD) -o $@ $(srcdir)/gost-s-box.c
 
 
 if ENABLE_O_FLAG_MUNGING
-o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g'
+o_flag_munging = sed -e 's/-O\([2-9sg][2-9sg]*\)/-O1/' -e 's/-Ofast/-O1/g'
 else
 o_flag_munging = cat
 endif
 
 
 # We need to lower the optimization for this module.
-tiger.o: $(srcdir)/tiger.c
-       `echo $(COMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) `
+tiger.o: $(srcdir)/tiger.c Makefile
+       `echo $(COMPILE) -c $< | $(o_flag_munging) `
 
-tiger.lo: $(srcdir)/tiger.c
-       `echo $(LTCOMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) `
+tiger.lo: $(srcdir)/tiger.c Makefile
+       `echo $(LTCOMPILE) -c $< | $(o_flag_munging) `
+
+
+# We need to disable instrumentation for these modules as they use cc as
+# thin assembly front-end and do not tolerate in-between function calls
+# inserted by compiler as those functions may clobber the XMM registers.
+if ENABLE_INSTRUMENTATION_MUNGING
+instrumentation_munging = sed \
+       -e 's/-fsanitize[=,\-][=,a-z,A-Z,0-9,\,,\-]*//g' \
+       -e 's/-fprofile[=,\-][=,a-z,A-Z,0-9,\,,\-]*//g' \
+       -e 's/-fcoverage[=,\-][=,a-z,A-Z,0-9,\,,\-]*//g'
+else
+instrumentation_munging = cat
+endif
+
+rijndael-aesni.o: $(srcdir)/rijndael-aesni.c Makefile
+       `echo $(COMPILE) -c $< | $(instrumentation_munging) `
+
+rijndael-aesni.lo: $(srcdir)/rijndael-aesni.c Makefile
+       `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
+
+rijndael-ssse3-amd64.o: $(srcdir)/rijndael-ssse3-amd64.c Makefile
+       `echo $(COMPILE) -c $< | $(instrumentation_munging) `
+
+rijndael-ssse3-amd64.lo: $(srcdir)/rijndael-ssse3-amd64.c Makefile
+       `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
+
+cipher-gcm-intel-pclmul.o: $(srcdir)/cipher-gcm-intel-pclmul.c Makefile
+       `echo $(COMPILE) -c $< | $(instrumentation_munging) `
+
+cipher-gcm-intel-pclmul.lo: $(srcdir)/cipher-gcm-intel-pclmul.c Makefile
+       `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
+
+sha1-intel-shaext.o: $(srcdir)/sha1-intel-shaext.c Makefile
+       `echo $(COMPILE) -c $< | $(instrumentation_munging) `
+
+sha1-intel-shaext.lo: $(srcdir)/sha1-intel-shaext.c Makefile
+       `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
+
+sha256-intel-shaext.o: $(srcdir)/sha256-intel-shaext.c Makefile
+       `echo $(COMPILE) -c $< | $(instrumentation_munging) `
+
+sha256-intel-shaext.lo: $(srcdir)/sha256-intel-shaext.c Makefile
+       `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
+
+sha256-ssse3-i386.o: $(srcdir)/sha256-ssse3-i386.c Makefile
+       `echo $(COMPILE) -c $< | $(instrumentation_munging) `
+
+sha256-ssse3-i386.lo: $(srcdir)/sha256-ssse3-i386.c Makefile
+       `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
+
+crc-intel-pclmul.o: $(srcdir)/crc-intel-pclmul.c Makefile
+       `echo $(COMPILE) -c $< | $(instrumentation_munging) `
+
+crc-intel-pclmul.lo: $(srcdir)/crc-intel-pclmul.c Makefile
+       `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) `
+
+if ENABLE_PPC_VCRYPTO_EXTRA_CFLAGS
+ppc_vcrypto_cflags = -maltivec -mvsx -mcrypto
+else
+ppc_vcrypto_cflags =
+endif
+
+rijndael-ppc.o: $(srcdir)/rijndael-ppc.c Makefile
+       `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+rijndael-ppc.lo: $(srcdir)/rijndael-ppc.c Makefile
+       `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+rijndael-ppc9le.o: $(srcdir)/rijndael-ppc9le.c Makefile
+       `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+rijndael-ppc9le.lo: $(srcdir)/rijndael-ppc9le.c Makefile
+       `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+rijndael-p10le.o: $(srcdir)/rijndael-p10le.c Makefile
+       `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+rijndael-p10le.lo: $(srcdir)/rijndael-p10le.c Makefile
+       `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+sha256-ppc.o: $(srcdir)/sha256-ppc.c Makefile
+       `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+sha256-ppc.lo: $(srcdir)/sha256-ppc.c Makefile
+       `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+sha512-ppc.o: $(srcdir)/sha512-ppc.c Makefile
+       `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+sha512-ppc.lo: $(srcdir)/sha512-ppc.c Makefile
+       `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+chacha20-ppc.o: $(srcdir)/chacha20-ppc.c Makefile
+       `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+chacha20-ppc.lo: $(srcdir)/chacha20-ppc.c Makefile
+       `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+crc-ppc.o: $(srcdir)/crc-ppc.c Makefile
+       `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+crc-ppc.lo: $(srcdir)/crc-ppc.c Makefile
+       `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+cipher-gcm-ppc.o: $(srcdir)/cipher-gcm-ppc.c Makefile
+       `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
+
+cipher-gcm-ppc.lo: $(srcdir)/cipher-gcm-ppc.c Makefile
+       `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) `
diff --git a/cipher/Makefile.in b/cipher/Makefile.in
deleted file mode 100644 (file)
index 7c91bb9..0000000
+++ /dev/null
@@ -1,902 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Makefile for cipher modules
-# Copyright (C) 1998, 1999, 2000, 2001, 2002,
-#               2003, 2009 Free Software Foundation, Inc.
-#
-# 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 <http://www.gnu.org/licenses/>.
-
-# Process this file with automake to produce Makefile.in
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = cipher
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-       $(top_srcdir)/build-aux/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-LTLIBRARIES = $(noinst_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-am_libcipher_la_OBJECTS = cipher.lo cipher-cbc.lo cipher-cfb.lo \
-       cipher-ofb.lo cipher-ctr.lo cipher-aeswrap.lo cipher-ccm.lo \
-       cipher-cmac.lo cipher-gcm.lo cipher-gcm-intel-pclmul.lo \
-       cipher-gcm-armv8-aarch32-ce.lo cipher-gcm-armv8-aarch64-ce.lo \
-       cipher-poly1305.lo cipher-ocb.lo cipher-xts.lo \
-       cipher-selftest.lo pubkey.lo pubkey-util.lo md.lo mac.lo \
-       mac-hmac.lo mac-cmac.lo mac-gmac.lo mac-poly1305.lo \
-       poly1305.lo kdf.lo hmac-tests.lo primegen.lo hash-common.lo \
-       dsa-common.lo rsa-common.lo
-libcipher_la_OBJECTS = $(am_libcipher_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS)
-LTCPPASCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) \
-       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-       $(AM_CCASFLAGS) $(CCASFLAGS)
-AM_V_CPPAS = $(am__v_CPPAS_@AM_V@)
-am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@)
-am__v_CPPAS_0 = @echo "  CPPAS   " $@;
-am__v_CPPAS_1 = 
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-       $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(libcipher_la_SOURCES) $(EXTRA_libcipher_la_SOURCES)
-DIST_SOURCES = $(libcipher_la_SOURCES) $(EXTRA_libcipher_la_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-
-# Need to include ../src in addition to top_srcdir because gcrypt.h is
-# a built header.
-AM_CPPFLAGS = -I../src -I$(top_srcdir)/src
-AM_CFLAGS = $(GPG_ERROR_CFLAGS)
-AM_CCASFLAGS = $(NOEXECSTACK_FLAGS)
-EXTRA_DIST = gost-s-box.c
-CLEANFILES = gost-s-box
-DISTCLEANFILES = gost-sb.h
-noinst_LTLIBRARIES = libcipher.la
-GCRYPT_MODULES = @GCRYPT_CIPHERS@ @GCRYPT_PUBKEY_CIPHERS@ \
-                 @GCRYPT_DIGESTS@ @GCRYPT_KDFS@
-
-libcipher_la_DEPENDENCIES = $(GCRYPT_MODULES)
-libcipher_la_LIBADD = $(GCRYPT_MODULES)
-libcipher_la_SOURCES = \
-cipher.c cipher-internal.h \
-cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \
-cipher-ccm.c cipher-cmac.c cipher-gcm.c cipher-gcm-intel-pclmul.c \
-  cipher-gcm-armv8-aarch32-ce.S cipher-gcm-armv8-aarch64-ce.S \
-cipher-poly1305.c cipher-ocb.c cipher-xts.c \
-cipher-selftest.c cipher-selftest.h \
-pubkey.c pubkey-internal.h pubkey-util.c \
-md.c \
-mac.c mac-internal.h \
-mac-hmac.c mac-cmac.c mac-gmac.c mac-poly1305.c \
-poly1305.c poly1305-internal.h \
-kdf.c kdf-internal.h \
-hmac-tests.c \
-bithelp.h  \
-bufhelp.h  \
-primegen.c  \
-hash-common.c hash-common.h \
-dsa-common.c rsa-common.c \
-sha1.h
-
-EXTRA_libcipher_la_SOURCES = \
-arcfour.c arcfour-amd64.S \
-blowfish.c blowfish-amd64.S blowfish-arm.S \
-cast5.c cast5-amd64.S cast5-arm.S \
-chacha20.c chacha20-sse2-amd64.S chacha20-ssse3-amd64.S chacha20-avx2-amd64.S \
-  chacha20-armv7-neon.S \
-crc.c \
-  crc-intel-pclmul.c \
-des.c des-amd64.S \
-dsa.c \
-elgamal.c \
-ecc.c ecc-curves.c ecc-misc.c ecc-common.h \
-ecc-ecdsa.c ecc-eddsa.c ecc-gost.c \
-idea.c \
-gost28147.c gost.h \
-gostr3411-94.c \
-md4.c \
-md5.c \
-poly1305-sse2-amd64.S poly1305-avx2-amd64.S poly1305-armv7-neon.S \
-rijndael.c rijndael-internal.h rijndael-tables.h rijndael-aesni.c \
-  rijndael-padlock.c rijndael-amd64.S rijndael-arm.S \
-  rijndael-ssse3-amd64.c rijndael-ssse3-amd64-asm.S \
-  rijndael-armv8-ce.c rijndael-armv8-aarch32-ce.S rijndael-armv8-aarch64-ce.S \
-  rijndael-aarch64.S \
-rmd160.c \
-rsa.c \
-salsa20.c salsa20-amd64.S salsa20-armv7-neon.S \
-scrypt.c \
-seed.c \
-serpent.c serpent-sse2-amd64.S serpent-avx2-amd64.S serpent-armv7-neon.S \
-sha1.c sha1-ssse3-amd64.S sha1-avx-amd64.S sha1-avx-bmi2-amd64.S \
-  sha1-armv7-neon.S sha1-armv8-aarch32-ce.S sha1-armv8-aarch64-ce.S \
-sha256.c sha256-ssse3-amd64.S sha256-avx-amd64.S sha256-avx2-bmi2-amd64.S \
-  sha256-armv8-aarch32-ce.S sha256-armv8-aarch64-ce.S \
-sha512.c sha512-ssse3-amd64.S sha512-avx-amd64.S sha512-avx2-bmi2-amd64.S \
-  sha512-armv7-neon.S sha512-arm.S \
-keccak.c keccak_permute_32.h keccak_permute_64.h keccak-armv7-neon.S \
-stribog.c \
-tiger.c \
-whirlpool.c whirlpool-sse2-amd64.S \
-twofish.c twofish-amd64.S twofish-arm.S twofish-aarch64.S \
-  twofish-avx2-amd64.S \
-rfc2268.c \
-camellia.c camellia.h camellia-glue.c camellia-aesni-avx-amd64.S \
-  camellia-aesni-avx2-amd64.S camellia-arm.S camellia-aarch64.S \
-blake2.c
-
-@ENABLE_O_FLAG_MUNGING_FALSE@o_flag_munging = cat
-@ENABLE_O_FLAG_MUNGING_TRUE@o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g'
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-               && { if test -f $@; then exit 0; else break; fi; }; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cipher/Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu cipher/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-clean-noinstLTLIBRARIES:
-       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-       @list='$(noinst_LTLIBRARIES)'; \
-       locs=`for p in $$list; do echo $$p; done | \
-             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-             sort -u`; \
-       test -z "$$locs" || { \
-         echo rm -f $${locs}; \
-         rm -f $${locs}; \
-       }
-
-libcipher.la: $(libcipher_la_OBJECTS) $(libcipher_la_DEPENDENCIES) $(EXTRA_libcipher_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(LINK)  $(libcipher_la_OBJECTS) $(libcipher_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-       -rm -f *.$(OBJEXT)
-
-distclean-compile:
-       -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arcfour-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arcfour.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blake2.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blowfish-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blowfish-arm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blowfish.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/camellia-aarch64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/camellia-aesni-avx-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/camellia-aesni-avx2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/camellia-arm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/camellia-glue.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/camellia.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cast5-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cast5-arm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cast5.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chacha20-armv7-neon.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chacha20-avx2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chacha20-sse2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chacha20-ssse3-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chacha20.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-aeswrap.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-cbc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-ccm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-cfb.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-cmac.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-ctr.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-gcm-armv8-aarch32-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-gcm-armv8-aarch64-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-gcm-intel-pclmul.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-gcm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-ocb.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-ofb.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-poly1305.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-selftest.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher-xts.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cipher.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc-intel-pclmul.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/des-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/des.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsa-common.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsa.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc-curves.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc-ecdsa.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc-eddsa.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc-gost.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc-misc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elgamal.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gost28147.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gostr3411-94.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash-common.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac-tests.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idea.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdf.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keccak-armv7-neon.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keccak.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac-cmac.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac-gmac.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac-hmac.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac-poly1305.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mac.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md4.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poly1305-armv7-neon.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poly1305-avx2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poly1305-sse2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poly1305.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/primegen.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey-util.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rfc2268.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-aarch64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-aesni.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-arm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-armv8-aarch32-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-armv8-aarch64-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-armv8-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-padlock.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-ssse3-amd64-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael-ssse3-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rijndael.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rmd160.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsa-common.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsa.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/salsa20-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/salsa20-armv7-neon.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/salsa20.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scrypt.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/seed.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serpent-armv7-neon.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serpent-avx2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serpent-sse2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serpent.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1-armv7-neon.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1-armv8-aarch32-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1-armv8-aarch64-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1-avx-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1-avx-bmi2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1-ssse3-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256-armv8-aarch32-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256-armv8-aarch64-ce.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256-avx-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256-avx2-bmi2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256-ssse3-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha256.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha512-arm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha512-armv7-neon.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha512-avx-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha512-avx2-bmi2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha512-ssse3-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha512.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stribog.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tiger.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/twofish-aarch64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/twofish-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/twofish-arm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/twofish-avx2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/twofish.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whirlpool-sse2-amd64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/whirlpool.Plo@am__quote@
-
-.S.o:
-@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCCAS_FALSE@        $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ $<
-
-.S.obj:
-@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCCAS_FALSE@        $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.S.lo:
-@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    $(AM_V_CPPAS)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCCAS_FALSE@        $(AM_V_CPPAS@am__nodep@)$(LTCPPASCOMPILE) -c -o $@ $<
-
-.c.o:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-       $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       set x; \
-       here=`pwd`; \
-       $(am__define_uniq_tagged_files); \
-       shift; \
-       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-         test -n "$$unique" || unique=$$empty_fix; \
-         if test $$# -gt 0; then \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             "$$@" $$unique; \
-         else \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             $$unique; \
-         fi; \
-       fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       $(am__define_uniq_tagged_files); \
-       test -z "$(CTAGS_ARGS)$$unique" \
-         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$unique
-
-GTAGS:
-       here=`$(am__cd) $(top_builddir) && pwd` \
-         && $(am__cd) $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-       list='$(am__tagged_files)'; \
-       case "$(srcdir)" in \
-         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-         *) sdir=$(subdir)/$(srcdir) ;; \
-       esac; \
-       for i in $$list; do \
-         if test -f "$$i"; then \
-           echo "$(subdir)/$$i"; \
-         else \
-           echo "$$sdir/$$i"; \
-         fi; \
-       done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LTLIBRARIES)
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-       mostlyclean-am
-
-distclean: distclean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-       distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
-       clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
-       ctags-am distclean distclean-compile distclean-generic \
-       distclean-libtool distclean-tags distdir dvi dvi-am html \
-       html-am info info-am install install-am install-data \
-       install-data-am install-dvi install-dvi-am install-exec \
-       install-exec-am install-html install-html-am install-info \
-       install-info-am install-man install-pdf install-pdf-am \
-       install-ps install-ps-am install-strip installcheck \
-       installcheck-am installdirs maintainer-clean \
-       maintainer-clean-generic mostlyclean mostlyclean-compile \
-       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-       tags tags-am uninstall uninstall-am
-
-
-gost28147.lo: gost-sb.h
-gost-sb.h: gost-s-box
-       ./gost-s-box $@
-
-gost-s-box: gost-s-box.c
-       $(CC_FOR_BUILD) -o $@ $(srcdir)/gost-s-box.c
-
-# We need to lower the optimization for this module.
-tiger.o: $(srcdir)/tiger.c
-       `echo $(COMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) `
-
-tiger.lo: $(srcdir)/tiger.c
-       `echo $(LTCOMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) `
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
index 2e52ea0..2abd90a 100644 (file)
 #if defined(USE_ARCFOUR) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
 
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .text
 .align 16
 .globl _gcry_arcfour_amd64
 ELF(.type _gcry_arcfour_amd64,@function)
 _gcry_arcfour_amd64:
+       CFI_STARTPROC()
+       ENTER_SYSV_FUNC_PARAMS_0_4
        push    %rbp
+       CFI_PUSH(%rbp)
        push    %rbx
+       CFI_PUSH(%rbx)
        mov     %rdi,           %rbp    # key = ARG(key)
        mov     %rsi,           %rbx    # rbx = ARG(len)
        mov     %rdx,           %rsi    # in = ARG(in)
@@ -95,8 +95,12 @@ _gcry_arcfour_amd64:
        movb    %cl,            (4*256)(%rbp)   # key->y = y
        movb    %dl,            (4*256+4)(%rbp) # key->x = x
        pop     %rbx
+       CFI_POP(%rbx)
        pop     %rbp
-       ret
+       CFI_POP(%rbp)
+       EXIT_SYSV_FUNC
+       ret_spec_stop
+       CFI_ENDPROC()
 .L__gcry_arcfour_amd64_end:
 ELF(.size _gcry_arcfour_amd64,.L__gcry_arcfour_amd64_end-_gcry_arcfour_amd64)
 
index 44e8ef4..353de00 100644 (file)
@@ -30,6 +30,7 @@
 #include "types.h"
 #include "g10lib.h"
 #include "cipher.h"
+#include "cipher-internal.h"
 
 /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */
 #undef USE_AMD64_ASM
@@ -54,21 +55,7 @@ static void
 encrypt_stream (void *context,
                 byte *outbuf, const byte *inbuf, size_t length)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  const void *fn = _gcry_arcfour_amd64;
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  asm volatile ("callq *%0\n\t"
-                : "+a" (fn),
-                  "+D" (context),
-                  "+S" (length),
-                  "+d" (inbuf),
-                  "+c" (outbuf)
-                :
-                : "cc", "memory", "r8", "r9", "r10", "r11");
-#else
   _gcry_arcfour_amd64 (context, length, inbuf, outbuf );
-#endif
 }
 
 #else /*!USE_AMD64_ASM*/
@@ -184,10 +171,12 @@ do_arcfour_setkey (void *context, const byte *key, unsigned int keylen)
 }
 
 static gcry_err_code_t
-arcfour_setkey ( void *context, const byte *key, unsigned int keylen )
+arcfour_setkey ( void *context, const byte *key, unsigned int keylen,
+                 cipher_bulk_ops_t *bulk_ops )
 {
   ARCFOUR_context *ctx = (ARCFOUR_context *) context;
   gcry_err_code_t rc = do_arcfour_setkey (ctx, key, keylen );
+  (void)bulk_ops;
   return rc;
 }
 
@@ -207,11 +196,11 @@ selftest(void)
   static const byte ciphertext_1[] =
     { 0xF1, 0x38, 0x29, 0xC9, 0xDE };
 
-  arcfour_setkey( &ctx, key_1, sizeof(key_1));
+  arcfour_setkey( &ctx, key_1, sizeof(key_1), NULL);
   encrypt_stream( &ctx, scratch, plaintext_1, sizeof(plaintext_1));
   if ( memcmp (scratch, ciphertext_1, sizeof (ciphertext_1)))
     return "Arcfour encryption test 1 failed.";
-  arcfour_setkey( &ctx, key_1, sizeof(key_1));
+  arcfour_setkey( &ctx, key_1, sizeof(key_1), NULL);
   encrypt_stream(&ctx, scratch, scratch, sizeof(plaintext_1)); /* decrypt */
   if ( memcmp (scratch, plaintext_1, sizeof (plaintext_1)))
     return "Arcfour decryption test 1 failed.";
diff --git a/cipher/asm-common-aarch64.h b/cipher/asm-common-aarch64.h
new file mode 100644 (file)
index 0000000..451539e
--- /dev/null
@@ -0,0 +1,108 @@
+/* asm-common-aarch64.h  -  Common macros for AArch64 assembly
+ *
+ * Copyright (C) 2018 Martin Storsjö <martin@martin.st>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_ASM_COMMON_AARCH64_H
+#define GCRY_ASM_COMMON_AARCH64_H
+
+#include <config.h>
+
+#ifdef HAVE_GCC_ASM_ELF_DIRECTIVES
+# define ELF(...) __VA_ARGS__
+#else
+# define ELF(...) /*_*/
+#endif
+
+#ifdef __APPLE__
+#define GET_DATA_POINTER(reg, name) \
+       adrp    reg, name@GOTPAGE ; \
+       add     reg, reg, name@GOTPAGEOFF ;
+#elif defined(_WIN32)
+#define GET_DATA_POINTER(reg, name) \
+       adrp    reg, name ; \
+       add     reg, reg, #:lo12:name ;
+#else
+#define GET_DATA_POINTER(reg, name) \
+       adrp    reg, :got:name ; \
+       ldr     reg, [reg, #:got_lo12:name] ;
+#endif
+
+#ifdef HAVE_GCC_ASM_CFI_DIRECTIVES
+/* CFI directives to emit DWARF stack unwinding information. */
+# define CFI_STARTPROC()            .cfi_startproc
+# define CFI_ENDPROC()              .cfi_endproc
+# define CFI_REMEMBER_STATE()       .cfi_remember_state
+# define CFI_RESTORE_STATE()        .cfi_restore_state
+# define CFI_ADJUST_CFA_OFFSET(off) .cfi_adjust_cfa_offset off
+# define CFI_REL_OFFSET(reg,off)    .cfi_rel_offset reg, off
+# define CFI_DEF_CFA_REGISTER(reg)  .cfi_def_cfa_register reg
+# define CFI_REGISTER(ro,rn)        .cfi_register ro, rn
+# define CFI_RESTORE(reg)           .cfi_restore reg
+
+/* CFA expressions are used for pointing CFA and registers to
+ * SP relative offsets. */
+# define DW_REGNO_SP 31
+
+/* Fixed length encoding used for integers for now. */
+# define DW_SLEB128_7BIT(value) \
+       0x00|((value) & 0x7f)
+# define DW_SLEB128_28BIT(value) \
+       0x80|((value)&0x7f), \
+       0x80|(((value)>>7)&0x7f), \
+       0x80|(((value)>>14)&0x7f), \
+       0x00|(((value)>>21)&0x7f)
+
+# define CFI_CFA_ON_STACK(rsp_offs,cfa_depth) \
+       .cfi_escape \
+         0x0f, /* DW_CFA_def_cfa_expression */ \
+           DW_SLEB128_7BIT(11), /* length */ \
+         0x8f, /* DW_OP_breg31, rsp + constant */ \
+           DW_SLEB128_28BIT(rsp_offs), \
+         0x06, /* DW_OP_deref */ \
+         0x23, /* DW_OP_plus_constu */ \
+           DW_SLEB128_28BIT((cfa_depth)+8)
+
+# define CFI_REG_ON_STACK(regno,rsp_offs) \
+       .cfi_escape \
+         0x10, /* DW_CFA_expression */ \
+           DW_SLEB128_7BIT(regno), \
+           DW_SLEB128_7BIT(5), /* length */ \
+         0x8f, /* DW_OP_breg31, rsp + constant */ \
+           DW_SLEB128_28BIT(rsp_offs)
+
+#else
+# define CFI_STARTPROC()
+# define CFI_ENDPROC()
+# define CFI_REMEMBER_STATE()
+# define CFI_RESTORE_STATE()
+# define CFI_ADJUST_CFA_OFFSET(off)
+# define CFI_REL_OFFSET(reg,off)
+# define CFI_DEF_CFA_REGISTER(reg)
+# define CFI_REGISTER(ro,rn)
+# define CFI_RESTORE(reg)
+
+# define CFI_CFA_ON_STACK(rsp_offs,cfa_depth)
+# define CFI_REG_ON_STACK(reg,rsp_offs)
+#endif
+
+/* 'ret' instruction replacement for straight-line speculation mitigation */
+#define ret_spec_stop \
+       ret; dsb sy; isb;
+
+#endif /* GCRY_ASM_COMMON_AARCH64_H */
diff --git a/cipher/asm-common-amd64.h b/cipher/asm-common-amd64.h
new file mode 100644 (file)
index 0000000..97912b1
--- /dev/null
@@ -0,0 +1,193 @@
+/* asm-common-amd64.h  -  Common macros for AMD64 assembly
+ *
+ * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_ASM_COMMON_AMD64_H
+#define GCRY_ASM_COMMON_AMD64_H
+
+#include <config.h>
+
+#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
+# define ELF(...) __VA_ARGS__
+#else
+# define ELF(...) /*_*/
+#endif
+
+#ifdef __PIC__
+#  define rRIP (%rip)
+#else
+#  define rRIP
+#endif
+
+#ifdef __PIC__
+#  define RIP %rip
+#else
+#  define RIP
+#endif
+
+#ifdef __PIC__
+#  define ADD_RIP +rip
+#else
+#  define ADD_RIP
+#endif
+
+#if defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS) || !defined(__PIC__)
+#  define GET_EXTERN_POINTER(name, reg) movabsq $name, reg
+#else
+#  ifdef __code_model_large__
+#    define GET_EXTERN_POINTER(name, reg) \
+              pushq %r15; \
+              pushq %r14; \
+           1: leaq 1b(%rip), reg; \
+              movabsq $_GLOBAL_OFFSET_TABLE_-1b, %r14; \
+              movabsq $name@GOT, %r15; \
+              addq %r14, reg; \
+              popq %r14; \
+              movq (reg, %r15), reg; \
+              popq %r15;
+#  else
+#    define GET_EXTERN_POINTER(name, reg) movq name@GOTPCREL(%rip), reg
+#  endif
+#endif
+
+#ifdef HAVE_GCC_ASM_CFI_DIRECTIVES
+/* CFI directives to emit DWARF stack unwinding information. */
+# define CFI_STARTPROC()            .cfi_startproc
+# define CFI_ENDPROC()              .cfi_endproc
+# define CFI_REMEMBER_STATE()       .cfi_remember_state
+# define CFI_RESTORE_STATE()        .cfi_restore_state
+# define CFI_ADJUST_CFA_OFFSET(off) .cfi_adjust_cfa_offset off
+# define CFI_REL_OFFSET(reg,off)    .cfi_rel_offset reg, off
+# define CFI_DEF_CFA_REGISTER(reg)  .cfi_def_cfa_register reg
+# define CFI_REGISTER(ro,rn)        .cfi_register ro, rn
+# define CFI_RESTORE(reg)           .cfi_restore reg
+
+# define CFI_PUSH(reg) \
+       CFI_ADJUST_CFA_OFFSET(8); CFI_REL_OFFSET(reg, 0)
+# define CFI_POP(reg) \
+       CFI_ADJUST_CFA_OFFSET(-8); CFI_RESTORE(reg)
+# define CFI_POP_TMP_REG() \
+       CFI_ADJUST_CFA_OFFSET(-8);
+# define CFI_LEAVE() \
+       CFI_ADJUST_CFA_OFFSET(-8); CFI_DEF_CFA_REGISTER(%rsp)
+
+/* CFA expressions are used for pointing CFA and registers to
+ * %rsp relative offsets. */
+# define DW_REGNO_rax 0
+# define DW_REGNO_rdx 1
+# define DW_REGNO_rcx 2
+# define DW_REGNO_rbx 3
+# define DW_REGNO_rsi 4
+# define DW_REGNO_rdi 5
+# define DW_REGNO_rbp 6
+# define DW_REGNO_rsp 7
+# define DW_REGNO_r8  8
+# define DW_REGNO_r9  9
+# define DW_REGNO_r10 10
+# define DW_REGNO_r11 11
+# define DW_REGNO_r12 12
+# define DW_REGNO_r13 13
+# define DW_REGNO_r14 14
+# define DW_REGNO_r15 15
+
+# define DW_REGNO(reg) DW_REGNO_ ## reg
+
+/* Fixed length encoding used for integers for now. */
+# define DW_SLEB128_7BIT(value) \
+       0x00|((value) & 0x7f)
+# define DW_SLEB128_28BIT(value) \
+       0x80|((value)&0x7f), \
+       0x80|(((value)>>7)&0x7f), \
+       0x80|(((value)>>14)&0x7f), \
+       0x00|(((value)>>21)&0x7f)
+
+# define CFI_CFA_ON_STACK(rsp_offs,cfa_depth) \
+       .cfi_escape \
+         0x0f, /* DW_CFA_def_cfa_expression */ \
+           DW_SLEB128_7BIT(11), /* length */ \
+         0x77, /* DW_OP_breg7, rsp + constant */ \
+           DW_SLEB128_28BIT(rsp_offs), \
+         0x06, /* DW_OP_deref */ \
+         0x23, /* DW_OP_plus_constu */ \
+           DW_SLEB128_28BIT((cfa_depth)+8)
+
+# define CFI_REG_ON_STACK(reg,rsp_offs) \
+       .cfi_escape \
+         0x10, /* DW_CFA_expression */ \
+           DW_SLEB128_7BIT(DW_REGNO(reg)), \
+           DW_SLEB128_7BIT(5), /* length */ \
+         0x77, /* DW_OP_breg7, rsp + constant */ \
+           DW_SLEB128_28BIT(rsp_offs)
+
+#else
+# define CFI_STARTPROC()
+# define CFI_ENDPROC()
+# define CFI_REMEMBER_STATE()
+# define CFI_RESTORE_STATE()
+# define CFI_ADJUST_CFA_OFFSET(off)
+# define CFI_REL_OFFSET(reg,off)
+# define CFI_DEF_CFA_REGISTER(reg)
+# define CFI_REGISTER(ro,rn)
+# define CFI_RESTORE(reg)
+
+# define CFI_PUSH(reg)
+# define CFI_POP(reg)
+# define CFI_POP_TMP_REG()
+# define CFI_LEAVE()
+
+# define CFI_CFA_ON_STACK(rsp_offs,cfa_depth)
+# define CFI_REG_ON_STACK(reg,rsp_offs)
+#endif
+
+#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
+# define ENTER_SYSV_FUNC_PARAMS_0_4 \
+       pushq %rdi; \
+       CFI_PUSH(%rdi); \
+       pushq %rsi; \
+       CFI_PUSH(%rsi); \
+       movq %rcx, %rdi; \
+       movq %rdx, %rsi; \
+       movq %r8, %rdx; \
+       movq %r9, %rcx; \
+
+# define ENTER_SYSV_FUNC_PARAMS_5 \
+       ENTER_SYSV_FUNC_PARAMS_0_4; \
+       movq 0x38(%rsp), %r8;
+
+# define ENTER_SYSV_FUNC_PARAMS_6 \
+       ENTER_SYSV_FUNC_PARAMS_5; \
+       movq 0x40(%rsp), %r9;
+
+# define EXIT_SYSV_FUNC \
+       popq %rsi; \
+       CFI_POP(%rsi); \
+       popq %rdi; \
+       CFI_POP(%rdi);
+#else
+# define ENTER_SYSV_FUNC_PARAMS_0_4
+# define ENTER_SYSV_FUNC_PARAMS_5
+# define ENTER_SYSV_FUNC_PARAMS_6
+# define EXIT_SYSV_FUNC
+#endif
+
+/* 'ret' instruction replacement for straight-line speculation mitigation */
+#define ret_spec_stop \
+       ret; int3;
+
+#endif /* GCRY_ASM_COMMON_AMD64_H */
diff --git a/cipher/asm-common-s390x.h b/cipher/asm-common-s390x.h
new file mode 100644 (file)
index 0000000..b3a996c
--- /dev/null
@@ -0,0 +1,90 @@
+/* asm-common-s390x.h  -  Common macros for zSeries assembly
+ *
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_ASM_COMMON_S390X_H
+#define GCRY_ASM_COMMON_S390X_H
+
+#include <config.h>
+
+#ifdef HAVE_GCC_ASM_ELF_DIRECTIVES
+# define ELF(...) __VA_ARGS__
+#else
+# define ELF(...) /*_*/
+#endif
+
+#ifdef HAVE_GCC_ASM_CFI_DIRECTIVES
+/* CFI directives to emit DWARF stack unwinding information. */
+# define CFI_STARTPROC()            .cfi_startproc
+# define CFI_ENDPROC()              .cfi_endproc
+# define CFI_REMEMBER_STATE()       .cfi_remember_state
+# define CFI_RESTORE_STATE()        .cfi_restore_state
+# define CFI_ADJUST_CFA_OFFSET(off) .cfi_adjust_cfa_offset off
+# define CFI_REL_OFFSET(reg,off)    .cfi_rel_offset reg, off
+# define CFI_DEF_CFA_REGISTER(reg)  .cfi_def_cfa_register reg
+# define CFI_REGISTER(ro,rn)        .cfi_register ro, rn
+# define CFI_RESTORE(reg)           .cfi_restore reg
+
+/* CFA expressions are used for pointing CFA and registers to
+ * SP relative offsets. */
+# define DW_REGNO_SP 15
+
+/* Fixed length encoding used for integers for now. */
+# define DW_SLEB128_7BIT(value) \
+       0x00|((value) & 0x7f)
+# define DW_SLEB128_28BIT(value) \
+       0x80|((value)&0x7f), \
+       0x80|(((value)>>7)&0x7f), \
+       0x80|(((value)>>14)&0x7f), \
+       0x00|(((value)>>21)&0x7f)
+
+# define CFI_CFA_ON_STACK(rsp_offs,cfa_depth) \
+       .cfi_escape \
+         0x0f, /* DW_CFA_def_cfa_expression */ \
+           DW_SLEB128_7BIT(11), /* length */ \
+         0x7f, /* DW_OP_breg15, rsp + constant */ \
+           DW_SLEB128_28BIT(rsp_offs), \
+         0x06, /* DW_OP_deref */ \
+         0x23, /* DW_OP_plus_constu */ \
+           DW_SLEB128_28BIT((cfa_depth)+160)
+
+# define CFI_REG_ON_STACK(regno,rsp_offs) \
+       .cfi_escape \
+         0x10, /* DW_CFA_expression */ \
+           DW_SLEB128_7BIT(regno), \
+           DW_SLEB128_7BIT(5), /* length */ \
+         0x7f, /* DW_OP_breg15, rsp + constant */ \
+           DW_SLEB128_28BIT(rsp_offs)
+
+#else
+# define CFI_STARTPROC()
+# define CFI_ENDPROC()
+# define CFI_REMEMBER_STATE()
+# define CFI_RESTORE_STATE()
+# define CFI_ADJUST_CFA_OFFSET(off)
+# define CFI_REL_OFFSET(reg,off)
+# define CFI_DEF_CFA_REGISTER(reg)
+# define CFI_REGISTER(ro,rn)
+# define CFI_RESTORE(reg)
+
+# define CFI_CFA_ON_STACK(rsp_offs,cfa_depth)
+# define CFI_REG_ON_STACK(reg,rsp_offs)
+#endif
+
+#endif /* GCRY_ASM_COMMON_AMD64_H */
diff --git a/cipher/asm-inline-s390x.h b/cipher/asm-inline-s390x.h
new file mode 100644 (file)
index 0000000..001cb96
--- /dev/null
@@ -0,0 +1,205 @@
+/* asm-inline-s390x.h  -  Common macros for zSeries inline assembly
+ *
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_ASM_INLINE_S390X_H
+#define GCRY_ASM_INLINE_S390X_H
+
+#include <config.h>
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+
+typedef unsigned int u128_t __attribute__ ((mode (TI)));
+
+enum kmxx_functions_e
+{
+  KM_FUNCTION_AES_128 = 18,
+  KM_FUNCTION_AES_192 = 19,
+  KM_FUNCTION_AES_256 = 20,
+  KM_FUNCTION_XTS_AES_128 = 50,
+  KM_FUNCTION_XTS_AES_256 = 52,
+
+  KMID_FUNCTION_SHA1 = 1,
+  KMID_FUNCTION_SHA256 = 2,
+  KMID_FUNCTION_SHA512 = 3,
+  KMID_FUNCTION_SHA3_224 = 32,
+  KMID_FUNCTION_SHA3_256 = 33,
+  KMID_FUNCTION_SHA3_384 = 34,
+  KMID_FUNCTION_SHA3_512 = 35,
+  KMID_FUNCTION_SHAKE128 = 36,
+  KMID_FUNCTION_SHAKE256 = 37,
+  KMID_FUNCTION_GHASH = 65,
+
+  PCC_FUNCTION_NIST_P256 = 64,
+  PCC_FUNCTION_NIST_P384 = 65,
+  PCC_FUNCTION_NIST_P521 = 66,
+  PCC_FUNCTION_ED25519 = 72,
+  PCC_FUNCTION_ED448 = 73,
+  PCC_FUNCTION_X25519 = 80,
+  PCC_FUNCTION_X448 = 81
+};
+
+enum kmxx_function_flags_e
+{
+  KM_ENCRYPT  = 0 << 7,
+  KM_DECRYPT  = 1 << 7,
+
+  KMF_LCFB_16 = 16 << 24,
+
+  KMA_LPC     = 1 << 8,
+  KMA_LAAD    = 1 << 9,
+  KMA_HS      = 1 << 10,
+
+  KLMD_PADDING_STATE = 1 << 8,
+};
+
+static ALWAYS_INLINE u128_t km_function_to_mask(enum kmxx_functions_e func)
+{
+  return (u128_t)1 << (127 - func);
+}
+
+static inline u128_t kimd_query(void)
+{
+  static u128_t function_codes = 0;
+  static int initialized = 0;
+  register unsigned long reg0 asm("0") = 0;
+  register void *reg1 asm("1") = &function_codes;
+  u128_t r1;
+
+  if (initialized)
+    return function_codes;
+
+  asm volatile ("0: .insn rre,0xb93e << 16, 0, %[r1]\n\t"
+               "   brc 1,0b\n\t"
+               : [r1] "=a" (r1)
+               : [reg0] "r" (reg0), [reg1] "r" (reg1)
+               : "cc", "memory");
+
+  initialized = 1;
+  return function_codes;
+}
+
+static inline u128_t klmd_query(void)
+{
+  static u128_t function_codes = 0;
+  static int initialized = 0;
+  register unsigned long reg0 asm("0") = 0;
+  register void *reg1 asm("1") = &function_codes;
+  u128_t r1;
+
+  if (initialized)
+    return function_codes;
+
+  asm volatile ("0: .insn rre,0xb93f << 16, 0, %[r1]\n\t"
+               "   brc 1,0b\n\t"
+               : [r1] "=a" (r1)
+               : [reg0] "r" (reg0), [reg1] "r" (reg1)
+               : "cc", "memory");
+
+  initialized = 1;
+  return function_codes;
+}
+
+static inline u128_t pcc_query(void)
+{
+  static u128_t function_codes = 0;
+  static int initialized = 0;
+  register unsigned long reg0 asm("0") = 0;
+  register void *reg1 asm("1") = &function_codes;
+
+  if (initialized)
+    return function_codes;
+
+  asm volatile ("0: .insn rre,0xb92c << 16, 0, 0\n\t"
+               "   brc 1,0b\n\t"
+               :
+               : [reg0] "r" (reg0), [reg1] "r" (reg1)
+               : "cc", "memory");
+
+  initialized = 1;
+  return function_codes;
+}
+
+static ALWAYS_INLINE void
+kimd_execute(unsigned int func, void *param_block, const void *src,
+            size_t src_len)
+{
+  register unsigned long reg0 asm("0") = func;
+  register byte *reg1 asm("1") = param_block;
+  u128_t r1 = ((u128_t)(uintptr_t)src << 64) | (u64)src_len;
+
+  asm volatile ("0: .insn rre,0xb93e << 16, 0, %[r1]\n\t"
+               "   brc 1,0b\n\t"
+               : [r1] "+a" (r1)
+               : [func] "r" (reg0), [param_ptr] "r" (reg1)
+               : "cc", "memory");
+}
+
+static ALWAYS_INLINE void
+klmd_execute(unsigned int func, void *param_block, const void *src,
+            size_t src_len)
+{
+  register unsigned long reg0 asm("0") = func;
+  register byte *reg1 asm("1") = param_block;
+  u128_t r1 = ((u128_t)(uintptr_t)src << 64) | (u64)src_len;
+
+  asm volatile ("0: .insn rre,0xb93f << 16, 0, %[r1]\n\t"
+               "   brc 1,0b\n\t"
+               : [func] "+r" (reg0), [r1] "+a" (r1)
+               : [param_ptr] "r" (reg1)
+               : "cc", "memory");
+}
+
+static ALWAYS_INLINE void
+klmd_shake_execute(unsigned int func, void *param_block, void *dst,
+                  size_t dst_len, const void *src, size_t src_len)
+{
+  register unsigned long reg0 asm("0") = func;
+  register byte *reg1 asm("1") = param_block;
+  u128_t r1 = ((u128_t)(uintptr_t)dst << 64) | (u64)dst_len;
+  u128_t r2 = ((u128_t)(uintptr_t)src << 64) | (u64)src_len;
+
+  asm volatile ("0: .insn rre,0xb93f << 16, %[r1], %[r2]\n\t"
+               "   brc 1,0b\n\t"
+               : [func] "+r" (reg0), [r1] "+a" (r1), [r2] "+a" (r2)
+               : [param_ptr] "r" (reg1)
+               : "cc", "memory");
+}
+
+static ALWAYS_INLINE unsigned int
+pcc_scalar_multiply(unsigned int func, void *param_block)
+{
+  register unsigned long reg0 asm("0") = func;
+  register byte *reg1 asm("1") = param_block;
+  register unsigned long error = 0;
+
+  asm volatile ("0: .insn rre,0xb92c << 16, 0, 0\n\t"
+               "   brc 1,0b\n\t"
+               "   brc 7,1f\n\t"
+               "   j 2f\n\t"
+               "1: lhi %[error], 1\n\t"
+               "2:\n\t"
+               : [func] "+r" (reg0), [error] "+r" (error)
+               : [param_ptr] "r" (reg1)
+               : "cc", "memory");
+
+  return error;
+}
+
+#endif /* GCRY_ASM_INLINE_S390X_H */
diff --git a/cipher/asm-poly1305-aarch64.h b/cipher/asm-poly1305-aarch64.h
new file mode 100644 (file)
index 0000000..2f05aae
--- /dev/null
@@ -0,0 +1,245 @@
+/* asm-common-aarch64.h  -  Poly1305 macros for ARMv8/AArch64 assembly
+ *
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_ASM_POLY1305_AARCH64_H
+#define GCRY_ASM_POLY1305_AARCH64_H
+
+#include "asm-common-aarch64.h"
+
+#ifdef __AARCH64EL__
+  #define le_to_host(reg) /*_*/
+#else
+  #define le_to_host(reg) rev reg, reg;
+#endif
+
+/**********************************************************************
+  poly1305 for stitched chacha20-poly1305 Aarch64 implementations
+ **********************************************************************/
+
+#define POLY_RSTATE    x8
+#define POLY_RSRC      x9
+
+#define POLY_R_H0      x10
+#define POLY_R_H1      x11
+#define POLY_R_H2      x12
+#define POLY_R_H2d     w12
+#define POLY_R_R0      x13
+#define POLY_R_R1      x14
+#define POLY_R_R1_MUL5 x15
+#define POLY_R_X0_HI   x16
+#define POLY_R_X0_LO   x17
+#define POLY_R_X1_HI   x19
+#define POLY_R_X1_LO   x20
+#define POLY_R_ONE     x21
+#define POLY_R_ONEd    w21
+
+#define POLY_TMP0      x22
+#define POLY_TMP1      x23
+#define POLY_TMP2      x24
+#define POLY_TMP3      x25
+
+#define POLY_CHACHA_ROUND x26
+
+#define POLY_S_R0      (4 * 4 + 0 * 8)
+#define POLY_S_R1      (4 * 4 + 1 * 8)
+#define POLY_S_H0      (4 * 4 + 2 * 8 + 0 * 8)
+#define POLY_S_H1      (4 * 4 + 2 * 8 + 1 * 8)
+#define POLY_S_H2d     (4 * 4 + 2 * 8 + 2 * 8)
+
+#define POLY1305_PUSH_REGS() \
+       stp x19, x20, [sp, #-16]!; \
+       CFI_ADJUST_CFA_OFFSET(16); \
+       CFI_REG_ON_STACK(19, 0); \
+       CFI_REG_ON_STACK(20, 8); \
+       stp x21, x22, [sp, #-16]!; \
+       CFI_ADJUST_CFA_OFFSET(16); \
+       CFI_REG_ON_STACK(21, 0); \
+       CFI_REG_ON_STACK(22, 8); \
+       stp x23, x24, [sp, #-16]!; \
+       CFI_ADJUST_CFA_OFFSET(16); \
+       CFI_REG_ON_STACK(23, 0); \
+       CFI_REG_ON_STACK(24, 8); \
+       stp x25, x26, [sp, #-16]!; \
+       CFI_ADJUST_CFA_OFFSET(16); \
+       CFI_REG_ON_STACK(25, 0); \
+       CFI_REG_ON_STACK(26, 8);
+
+#define POLY1305_POP_REGS() \
+       ldp x25, x26, [sp], #16; \
+       CFI_ADJUST_CFA_OFFSET(-16); \
+       CFI_RESTORE(x25); \
+       CFI_RESTORE(x26); \
+       ldp x23, x24, [sp], #16; \
+       CFI_ADJUST_CFA_OFFSET(-16); \
+       CFI_RESTORE(x23); \
+       CFI_RESTORE(x24); \
+       ldp x21, x22, [sp], #16; \
+       CFI_ADJUST_CFA_OFFSET(-16); \
+       CFI_RESTORE(x21); \
+       CFI_RESTORE(x22); \
+       ldp x19, x20, [sp], #16; \
+       CFI_ADJUST_CFA_OFFSET(-16); \
+       CFI_RESTORE(x19); \
+       CFI_RESTORE(x20);
+
+#define POLY1305_LOAD_STATE() \
+       ldr POLY_R_R1, [POLY_RSTATE, #(POLY_S_R1)]; \
+       ldr POLY_R_H0, [POLY_RSTATE, #(POLY_S_H0)];  \
+       ldr POLY_R_H1, [POLY_RSTATE, #(POLY_S_H1)]; \
+       ldr POLY_R_H2d, [POLY_RSTATE, #(POLY_S_H2d)]; \
+       ldr POLY_R_R0, [POLY_RSTATE, #(POLY_S_R0)]; \
+       add POLY_R_R1_MUL5, POLY_R_R1, POLY_R_R1, lsr #2; \
+       mov POLY_R_ONE, #1;
+
+#define POLY1305_STORE_STATE() \
+       str POLY_R_H0, [POLY_RSTATE, #(POLY_S_H0)]; \
+       str POLY_R_H1, [POLY_RSTATE, #(POLY_S_H1)]; \
+       str POLY_R_H2d, [POLY_RSTATE, #(POLY_S_H2d)];
+
+#define POLY1305_BLOCK_PART1(src_offset) \
+       /* a = h + m */ \
+       ldr POLY_TMP0, [POLY_RSRC, #((src_offset) + 0 * 8)];
+#define POLY1305_BLOCK_PART2(src_offset) \
+       ldr POLY_TMP1, [POLY_RSRC, #((src_offset) + 1 * 8)];
+#define POLY1305_BLOCK_PART3() \
+       le_to_host(POLY_TMP0);
+#define POLY1305_BLOCK_PART4() \
+       le_to_host(POLY_TMP1);
+#define POLY1305_BLOCK_PART5() \
+       adds POLY_R_H0, POLY_R_H0, POLY_TMP0;
+#define POLY1305_BLOCK_PART6() \
+       adcs POLY_R_H1, POLY_R_H1, POLY_TMP1;
+#define POLY1305_BLOCK_PART7() \
+       adc POLY_R_H2d, POLY_R_H2d, POLY_R_ONEd;
+
+#define POLY1305_BLOCK_PART8() \
+       /* h = a * r (partial mod 2^130-5): */ \
+       mul POLY_R_X1_LO, POLY_R_H0, POLY_R_R1;   /* lo: h0 * r1 */
+#define POLY1305_BLOCK_PART9() \
+       mul POLY_TMP0, POLY_R_H1, POLY_R_R0;      /* lo: h1 * r0 */
+#define POLY1305_BLOCK_PART10() \
+       mul POLY_R_X0_LO, POLY_R_H0, POLY_R_R0;   /* lo: h0 * r0 */
+#define POLY1305_BLOCK_PART11() \
+       umulh POLY_R_X1_HI, POLY_R_H0, POLY_R_R1; /* hi: h0 * r1 */
+#define POLY1305_BLOCK_PART12() \
+       adds POLY_R_X1_LO, POLY_R_X1_LO, POLY_TMP0;
+#define POLY1305_BLOCK_PART13() \
+       umulh POLY_TMP1, POLY_R_H1, POLY_R_R0;    /* hi: h1 * r0 */
+#define POLY1305_BLOCK_PART14() \
+       mul POLY_TMP2, POLY_R_H1, POLY_R_R1_MUL5;   /* lo: h1 * r1 mod 2^130-5 */
+#define POLY1305_BLOCK_PART15() \
+       umulh POLY_R_X0_HI, POLY_R_H0, POLY_R_R0; /* hi: h0 * r0 */
+#define POLY1305_BLOCK_PART16() \
+       adc POLY_R_X1_HI, POLY_R_X1_HI, POLY_TMP1;
+#define POLY1305_BLOCK_PART17() \
+       umulh POLY_TMP3, POLY_R_H1, POLY_R_R1_MUL5; /* hi: h1 * r1 mod 2^130-5 */
+#define POLY1305_BLOCK_PART18() \
+       adds POLY_R_X0_LO, POLY_R_X0_LO, POLY_TMP2;
+#define POLY1305_BLOCK_PART19() \
+       mul POLY_R_H1, POLY_R_H2, POLY_R_R1_MUL5; /* h2 * r1 mod 2^130-5 */
+#define POLY1305_BLOCK_PART20() \
+       adc POLY_R_X0_HI, POLY_R_X0_HI, POLY_TMP3;
+#define POLY1305_BLOCK_PART21() \
+       mul POLY_R_H2, POLY_R_H2, POLY_R_R0;      /* h2 * r0 */
+#define POLY1305_BLOCK_PART22() \
+       adds POLY_R_H1, POLY_R_H1, POLY_R_X1_LO;
+#define POLY1305_BLOCK_PART23() \
+       adc POLY_R_H0, POLY_R_H2, POLY_R_X1_HI;
+
+#define POLY1305_BLOCK_PART24() \
+       /* carry propagation */ \
+       and POLY_R_H2, POLY_R_H0, #3;
+#define POLY1305_BLOCK_PART25() \
+       lsr POLY_R_H0, POLY_R_H0, #2;
+#define POLY1305_BLOCK_PART26() \
+       add POLY_R_H0, POLY_R_H0, POLY_R_H0, lsl #2;
+#define POLY1305_BLOCK_PART27() \
+       adds POLY_R_H0, POLY_R_H0, POLY_R_X0_LO;
+#define POLY1305_BLOCK_PART28() \
+       adcs POLY_R_H1, POLY_R_H1, POLY_R_X0_HI;
+#define POLY1305_BLOCK_PART29() \
+       adc POLY_R_H2d, POLY_R_H2d, wzr;
+
+//#define TESTING_POLY1305_ASM
+#ifdef TESTING_POLY1305_ASM
+/* for testing only. */
+.align 3
+.globl _gcry_poly1305_aarch64_blocks1
+ELF(.type _gcry_poly1305_aarch64_blocks1,%function;)
+_gcry_poly1305_aarch64_blocks1:
+       /* input:
+        *      x0: poly1305-state
+        *      x1: src
+        *      x2: nblks
+        */
+       CFI_STARTPROC()
+       POLY1305_PUSH_REGS();
+
+       mov POLY_RSTATE, x0;
+       mov POLY_RSRC, x1;
+
+       POLY1305_LOAD_STATE();
+
+.L_gcry_poly1305_aarch64_loop1:
+       POLY1305_BLOCK_PART1(0 * 16);
+       POLY1305_BLOCK_PART2(0 * 16);
+       add POLY_RSRC, POLY_RSRC, #16;
+       POLY1305_BLOCK_PART3();
+       POLY1305_BLOCK_PART4();
+       POLY1305_BLOCK_PART5();
+       POLY1305_BLOCK_PART6();
+       POLY1305_BLOCK_PART7();
+       POLY1305_BLOCK_PART8();
+       POLY1305_BLOCK_PART9();
+       POLY1305_BLOCK_PART10();
+       POLY1305_BLOCK_PART11();
+       POLY1305_BLOCK_PART12();
+       POLY1305_BLOCK_PART13();
+       POLY1305_BLOCK_PART14();
+       POLY1305_BLOCK_PART15();
+       POLY1305_BLOCK_PART16();
+       POLY1305_BLOCK_PART17();
+       POLY1305_BLOCK_PART18();
+       POLY1305_BLOCK_PART19();
+       POLY1305_BLOCK_PART20();
+       POLY1305_BLOCK_PART21();
+       POLY1305_BLOCK_PART22();
+       POLY1305_BLOCK_PART23();
+       POLY1305_BLOCK_PART24();
+       POLY1305_BLOCK_PART25();
+       POLY1305_BLOCK_PART26();
+       POLY1305_BLOCK_PART27();
+       POLY1305_BLOCK_PART28();
+       POLY1305_BLOCK_PART29();
+
+       subs x2, x2, #1;
+       b.ne .L_gcry_poly1305_aarch64_loop1;
+
+       POLY1305_STORE_STATE();
+
+       mov x0, #0;
+
+       POLY1305_POP_REGS();
+       ret_spec_stop;
+       CFI_ENDPROC()
+ELF(.size _gcry_poly1305_aarch64_blocks1, .-_gcry_poly1305_aarch64_blocks1;)
+#endif
+
+#endif /* GCRY_ASM_POLY1305_AARCH64_H */
diff --git a/cipher/asm-poly1305-amd64.h b/cipher/asm-poly1305-amd64.h
new file mode 100644 (file)
index 0000000..3f99ea3
--- /dev/null
@@ -0,0 +1,171 @@
+/* asm-common-amd64.h  -  Poly1305 macros for AMD64 assembly
+ *
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_ASM_POLY1305_AMD64_H
+#define GCRY_ASM_POLY1305_AMD64_H
+
+#include "asm-common-amd64.h"
+
+/**********************************************************************
+  poly1305 for stitched chacha20-poly1305 AMD64 implementations
+ **********************************************************************/
+
+#define POLY_RSTATE    %r8
+#define POLY_RSRC      %r9
+
+#define POLY_R_H0      %rbx
+#define POLY_R_H1      %rcx
+#define POLY_R_H2      %r10
+#define POLY_R_H2d     %r10d
+#define POLY_R_R0      %r11
+#define POLY_R_R1_MUL5 %r12
+#define POLY_R_X0_HI   %r13
+#define POLY_R_X0_LO   %r14
+#define POLY_R_X1_HI   %r15
+#define POLY_R_X1_LO   %rsi
+
+#define POLY_S_R0      (4 * 4 + 0 * 8)(POLY_RSTATE)
+#define POLY_S_R1      (4 * 4 + 1 * 8)(POLY_RSTATE)
+#define POLY_S_H0      (4 * 4 + 2 * 8 + 0 * 8)(POLY_RSTATE)
+#define POLY_S_H1      (4 * 4 + 2 * 8 + 1 * 8)(POLY_RSTATE)
+#define POLY_S_H2d     (4 * 4 + 2 * 8 + 2 * 8)(POLY_RSTATE)
+
+#define POLY1305_LOAD_STATE() \
+       movq POLY_S_H0, POLY_R_H0; \
+       movq POLY_S_H1, POLY_R_H1; \
+       movl POLY_S_H2d, POLY_R_H2d; \
+       movq POLY_S_R0, POLY_R_R0; \
+       movq POLY_S_R1, POLY_R_R1_MUL5; \
+       shrq $2, POLY_R_R1_MUL5; \
+       addq POLY_S_R1, POLY_R_R1_MUL5;
+
+#define POLY1305_STORE_STATE() \
+       movq POLY_R_H0, POLY_S_H0; \
+       movq POLY_R_H1, POLY_S_H1; \
+       movl POLY_R_H2d, POLY_S_H2d;
+
+/* a = h + m */
+#define POLY1305_BLOCK_PART1(src_offset) \
+       addq ((src_offset) + 0 * 8)(POLY_RSRC), POLY_R_H0; \
+       adcq ((src_offset) + 1 * 8)(POLY_RSRC), POLY_R_H1; \
+       adcl $1, POLY_R_H2d; \
+       \
+       /* h = a * r (partial mod 2^130-5): */ \
+       \
+       /* h0 * r1 */ \
+       movq POLY_R_H0, %rax; \
+       mulq POLY_S_R1; \
+       movq %rax, POLY_R_X1_LO; \
+       movq %rdx, POLY_R_X1_HI;
+
+#define POLY1305_BLOCK_PART2() \
+       \
+       /* h0 * r0 */ \
+       movq POLY_R_H0, %rax; \
+       mulq POLY_R_R0; \
+       movq %rax, POLY_R_X0_LO; \
+       movq %rdx, POLY_R_X0_HI;
+
+#define POLY1305_BLOCK_PART3() \
+       \
+       /* h1 * r0 */ \
+       movq POLY_R_H1, %rax; \
+       mulq POLY_R_R0; \
+       addq %rax, POLY_R_X1_LO; \
+       adcq %rdx, POLY_R_X1_HI; \
+       \
+       /* h1 * r1 mod 2^130-5 */ \
+       movq POLY_R_R1_MUL5, %rax; \
+       mulq POLY_R_H1;
+
+#define POLY1305_BLOCK_PART4() \
+       movq POLY_R_H2, POLY_R_H1; \
+       imulq POLY_R_R1_MUL5, POLY_R_H1; /* h2 * r1 mod 2^130-5 */ \
+       addq %rax, POLY_R_X0_LO; \
+       adcq %rdx, POLY_R_X0_HI; \
+       imulq POLY_R_R0, POLY_R_H2;      /* h2 * r0 */ \
+       addq POLY_R_X1_LO, POLY_R_H1; \
+       adcq POLY_R_X1_HI, POLY_R_H2;
+
+#define POLY1305_BLOCK_PART5() \
+       \
+       /* carry propagation */ \
+       movq POLY_R_H2, POLY_R_H0; \
+       andl $3, POLY_R_H2d; \
+       shrq $2, POLY_R_H0; \
+       leaq (POLY_R_H0, POLY_R_H0, 4), POLY_R_H0; \
+       addq POLY_R_X0_LO, POLY_R_H0; \
+       adcq POLY_R_X0_HI, POLY_R_H1; \
+       adcl $0, POLY_R_H2d;
+
+#ifdef TESTING_POLY1305_ASM
+/* for testing only, mixed C/asm poly1305.c is marginally faster (~2%). */
+.align 8
+.globl _gcry_poly1305_amd64_ssse3_blocks1
+ELF(.type _gcry_poly1305_amd64_ssse3_blocks1,@function;)
+
+_gcry_poly1305_amd64_ssse3_blocks1:
+       /* input:
+        *      %rdi: poly1305-state
+        *      %rsi: src
+        *      %rdx: nblks
+        */
+       pushq %rbp;
+       movq %rsp, %rbp;
+
+       subq $(10 * 8), %rsp;
+       movq %rbx, (1 * 8)(%rsp);
+       movq %r12, (2 * 8)(%rsp);
+       movq %r13, (3 * 8)(%rsp);
+       movq %r14, (4 * 8)(%rsp);
+       movq %r15, (5 * 8)(%rsp);
+
+       movq %rdx, (8 * 8)(%rsp); # NBLKS
+
+       movq %rdi, POLY_RSTATE;
+       movq %rsi, POLY_RSRC;
+
+       POLY1305_LOAD_STATE();
+
+.L_poly1:
+       POLY1305_BLOCK_PART1(0 * 16);
+       POLY1305_BLOCK_PART2();
+       POLY1305_BLOCK_PART3();
+       POLY1305_BLOCK_PART4();
+       POLY1305_BLOCK_PART5();
+
+       subq $1, (8 * 8)(%rsp); # NBLKS
+       leaq (16)(POLY_RSRC), POLY_RSRC;
+       jnz .L_poly1;
+
+       POLY1305_STORE_STATE();
+
+       movq (1 * 8)(%rsp), %rbx;
+       movq (2 * 8)(%rsp), %r12;
+       movq (3 * 8)(%rsp), %r13;
+       movq (4 * 8)(%rsp), %r14;
+       movq (5 * 8)(%rsp), %r15;
+
+       xorl %eax, %eax;
+       leave
+       ret;
+#endif
+
+#endif /* GCRY_ASM_POLY1305_AMD64_H */
diff --git a/cipher/asm-poly1305-s390x.h b/cipher/asm-poly1305-s390x.h
new file mode 100644 (file)
index 0000000..113ab94
--- /dev/null
@@ -0,0 +1,140 @@
+/* asm-common-amd64.h  -  Poly1305 macros for zSeries assembly
+ *
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_ASM_POLY1305_S390X_H
+#define GCRY_ASM_POLY1305_S390X_H
+
+#include "asm-common-s390x.h"
+
+/**********************************************************************
+  poly1305 for stitched chacha20-poly1305
+ **********************************************************************/
+
+#define POLY_RSTATE       %r1
+#define POLY_RSRC         %r14
+
+#define POLY_R_H0_TMP_HI  %r6  // even-
+#define POLY_R_H0         %r7  //      odd pair
+#define POLY_R_H1_TMP_HI  %r8  // even-
+#define POLY_R_H1         %r9  //      odd pair
+#define POLY_R_H2         %r10
+#define POLY_R_R0         %r11
+#define POLY_R_R1         %r12
+#define POLY_R_R1_MUL5    %r13
+#define POLY_R_X0_HI      %r2  // even-
+#define POLY_R_X0_LO      %r3  //      odd pair
+#define POLY_R_X1_HI      %r4  // even-
+#define POLY_R_X1_LO      %r5  //      odd pair
+
+#define POLY_S_R0      (4 * 4 + 0 * 8)(POLY_RSTATE)
+#define POLY_S_R1      (4 * 4 + 1 * 8)(POLY_RSTATE)
+#define POLY_S_H0      (4 * 4 + 2 * 8 + 0 * 8)(POLY_RSTATE)
+#define POLY_S_H1      (4 * 4 + 2 * 8 + 1 * 8)(POLY_RSTATE)
+#define POLY_S_H2d     (4 * 4 + 2 * 8 + 2 * 8)(POLY_RSTATE)
+
+#define INC_POLY1305_SRC(a) \
+       aghi POLY_RSRC, (a);
+
+#define POLY1305_LOAD_STATE() \
+       lg POLY_R_H0, POLY_S_H0; \
+       lg POLY_R_H1, POLY_S_H1; \
+       llgf POLY_R_H2, POLY_S_H2d; \
+       rllg POLY_R_H0, POLY_R_H0, 32; \
+       rllg POLY_R_H1, POLY_R_H1, 32; \
+       lg POLY_R_R0, POLY_S_R0; \
+       lg POLY_R_R1, POLY_S_R1; \
+       rllg POLY_R_R0, POLY_R_R0, 32; \
+       rllg POLY_R_R1, POLY_R_R1, 32; \
+       srlg POLY_R_R1_MUL5, POLY_R_R1, 2; \
+       algr POLY_R_R1_MUL5, POLY_R_R1;
+
+#define POLY1305_STORE_STATE() \
+       rllg POLY_R_H0, POLY_R_H0, 32; \
+       rllg POLY_R_H1, POLY_R_H1, 32; \
+       stg POLY_R_H0, POLY_S_H0; \
+       stg POLY_R_H1, POLY_S_H1; \
+       st POLY_R_H2, POLY_S_H2d;
+
+/* a = h + m */
+#define POLY1305_BLOCK_PART1_HB(src_offset, high_pad) \
+       lrvg POLY_R_X0_HI, ((src_offset) + 1 * 8)(POLY_RSRC); \
+       lrvg POLY_R_X0_LO, ((src_offset) + 0 * 8)(POLY_RSRC); \
+       lghi POLY_R_H1_TMP_HI, (high_pad);
+
+#define POLY1305_BLOCK_PART1(src_offset) \
+       POLY1305_BLOCK_PART1_HB(src_offset, 1);
+
+#define POLY1305_BLOCK_PART2() \
+       algr POLY_R_H0, POLY_R_X0_LO; \
+       alcgr POLY_R_H1, POLY_R_X0_HI; \
+       alcgr POLY_R_H2, POLY_R_H1_TMP_HI; \
+       lgr POLY_R_X1_LO, POLY_R_H0; \
+       lgr POLY_R_X0_LO, POLY_R_H0;
+
+#define POLY1305_BLOCK_PART3() \
+       /* h = a * r (partial mod 2^130-5): */ \
+       \
+       /* h0 * r1 */ \
+       mlgr POLY_R_X1_HI, POLY_R_R1; \
+       \
+       /* h1 * r0 */ \
+       lgr POLY_R_H0, POLY_R_H1; \
+       mlgr POLY_R_H0_TMP_HI, POLY_R_R0; \
+       \
+       /* h1 * r1 mod 2^130-5 */ \
+       mlgr POLY_R_H1_TMP_HI, POLY_R_R1_MUL5;
+
+#define POLY1305_BLOCK_PART4() \
+       \
+       /* h0 * r0 */ \
+       mlgr POLY_R_X0_HI, POLY_R_R0; \
+       \
+       algr POLY_R_X1_LO, POLY_R_H0; \
+       alcgr POLY_R_X1_HI, POLY_R_H0_TMP_HI; \
+       \
+       lgr POLY_R_H0_TMP_HI, POLY_R_H2; \
+       msgr POLY_R_H0_TMP_HI, POLY_R_R1_MUL5; /* h2 * r1 mod 2^130-5 */ \
+       msgr POLY_R_H2, POLY_R_R0;             /* h2 * r0 */
+
+#define POLY1305_BLOCK_PART5() \
+       \
+       algr POLY_R_X0_LO, POLY_R_H1; \
+       alcgr POLY_R_X0_HI, POLY_R_H1_TMP_HI;
+
+#define POLY1305_BLOCK_PART6() \
+       \
+       algrk POLY_R_H1, POLY_R_H0_TMP_HI, POLY_R_X1_LO; \
+       alcgr POLY_R_H2, POLY_R_X1_HI;
+
+#define POLY1305_BLOCK_PART7() \
+       \
+       /* carry propagation */ \
+       srlg POLY_R_H0, POLY_R_H2, 2; \
+       risbgn POLY_R_X1_LO, POLY_R_H2, 0, 0x80 | 61, 0; \
+       lghi POLY_R_H1_TMP_HI, 0; \
+       agr POLY_R_H0, POLY_R_X1_LO; \
+       risbgn POLY_R_H2, POLY_R_H2, 62, 0x80 | 63, 0;
+
+#define POLY1305_BLOCK_PART8() \
+       algr POLY_R_H0, POLY_R_X0_LO; \
+       alcgr POLY_R_H1, POLY_R_X0_HI; \
+       alcgr POLY_R_H2, POLY_R_H1_TMP_HI;
+
+#endif /* GCRY_ASM_POLY1305_AMD64_H */
index 26ef7c3..7793ce7 100644 (file)
@@ -83,7 +83,7 @@ static inline int
 _gcry_ctz (unsigned int x)
 {
 #if defined (HAVE_BUILTIN_CTZ)
-  return x? __builtin_ctz (x) : 8 * sizeof (x);
+  return x ? __builtin_ctz (x) : 8 * sizeof (x);
 #else
   /* See
    * http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightModLookup
@@ -106,9 +106,11 @@ _gcry_ctz (unsigned int x)
 static inline int
 _gcry_ctz64(u64 x)
 {
-#if defined (HAVE_BUILTIN_CTZ) && SIZEOF_UNSIGNED_INT >= 8
+#if defined (HAVE_BUILTIN_CTZL) && SIZEOF_UNSIGNED_LONG >= 8
+  return x ? __builtin_ctzl (x) : 8 * sizeof (x);
+#elif defined (HAVE_BUILTIN_CTZ) && SIZEOF_UNSIGNED_INT >= 8
 #warning hello
-  return x? __builtin_ctz (x) : 8 * sizeof (x);
+  return x ? __builtin_ctz (x) : 8 * sizeof (x);
 #else
   if ((x & 0xffffffff))
     return _gcry_ctz (x);
index 0e4cf9b..a5926b9 100644 (file)
 #include "cipher.h"
 #include "hash-common.h"
 
+/* USE_AVX indicates whether to compile with Intel AVX code. */
+#undef USE_AVX
+#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX) && \
+    (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+# define USE_AVX 1
+#endif
+
+/* USE_AVX2 indicates whether to compile with Intel AVX2 code. */
+#undef USE_AVX2
+#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX2) && \
+    (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+# define USE_AVX2 1
+#endif
+
+/* AMD64 assembly implementations use SystemV ABI, ABI conversion and additional
+ * stack to store XMM6-XMM15 needed on Win64. */
+#undef ASM_FUNC_ABI
+#undef ASM_EXTRA_STACK
+#if defined(USE_AVX2) && defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)
+# define ASM_FUNC_ABI __attribute__((sysv_abi))
+# define ASM_EXTRA_STACK (10 * 16)
+#else
+# define ASM_FUNC_ABI
+# define ASM_EXTRA_STACK 0
+#endif
+
 #define BLAKE2B_BLOCKBYTES 128
 #define BLAKE2B_OUTBYTES 64
 #define BLAKE2B_KEYBYTES 64
@@ -67,6 +95,9 @@ typedef struct BLAKE2B_CONTEXT_S
   byte buf[BLAKE2B_BLOCKBYTES];
   size_t buflen;
   size_t outlen;
+#ifdef USE_AVX2
+  unsigned int use_avx2:1;
+#endif
 } BLAKE2B_CONTEXT;
 
 typedef struct
@@ -98,6 +129,9 @@ typedef struct BLAKE2S_CONTEXT_S
   byte buf[BLAKE2S_BLOCKBYTES];
   size_t buflen;
   size_t outlen;
+#ifdef USE_AVX
+  unsigned int use_avx:1;
+#endif
 } BLAKE2S_CONTEXT;
 
 typedef unsigned int (*blake2_transform_t)(void *S, const void *inblk,
@@ -188,8 +222,9 @@ static inline u64 rotr64(u64 x, u64 n)
   return ((x >> (n & 63)) | (x << ((64 - n) & 63)));
 }
 
-static unsigned int blake2b_transform(void *vS, const void *inblks,
-                                     size_t nblks)
+static unsigned int blake2b_transform_generic(BLAKE2B_STATE *S,
+                                              const void *inblks,
+                                              size_t nblks)
 {
   static const byte blake2b_sigma[12][16] =
   {
@@ -206,7 +241,6 @@ static unsigned int blake2b_transform(void *vS, const void *inblks,
     {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 },
     { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }
   };
-  BLAKE2B_STATE *S = vS;
   const byte* in = inblks;
   u64 m[16];
   u64 v[16];
@@ -306,6 +340,33 @@ static unsigned int blake2b_transform(void *vS, const void *inblks,
   return sizeof(void *) * 4 + sizeof(u64) * 16 * 2;
 }
 
+#ifdef USE_AVX2
+unsigned int _gcry_blake2b_transform_amd64_avx2(BLAKE2B_STATE *S,
+                                                const void *inblks,
+                                                size_t nblks) ASM_FUNC_ABI;
+#endif
+
+static unsigned int blake2b_transform(void *ctx, const void *inblks,
+                                      size_t nblks)
+{
+  BLAKE2B_CONTEXT *c = ctx;
+  unsigned int nburn;
+
+  if (0)
+    {}
+#ifdef USE_AVX2
+  if (c->use_avx2)
+    nburn = _gcry_blake2b_transform_amd64_avx2(&c->state, inblks, nblks);
+#endif
+  else
+    nburn = blake2b_transform_generic(&c->state, inblks, nblks);
+
+  if (nburn)
+    nburn += ASM_EXTRA_STACK;
+
+  return nburn;
+}
+
 static void blake2b_final(void *ctx)
 {
   BLAKE2B_CONTEXT *c = ctx;
@@ -321,7 +382,7 @@ static void blake2b_final(void *ctx)
     memset (c->buf + c->buflen, 0, BLAKE2B_BLOCKBYTES - c->buflen); /* Padding */
   blake2b_set_lastblock (S);
   blake2b_increment_counter (S, (int)c->buflen - BLAKE2B_BLOCKBYTES);
-  burn = blake2b_transform (S, c->buf, 1);
+  burn = blake2b_transform (ctx, c->buf, 1);
 
   /* Output full hash to buffer */
   for (i = 0; i < 8; ++i)
@@ -397,16 +458,75 @@ static gcry_err_code_t blake2b_init_ctx(void *ctx, unsigned int flags,
                                        unsigned int dbits)
 {
   BLAKE2B_CONTEXT *c = ctx;
+  unsigned int features = _gcry_get_hw_features ();
 
+  (void)features;
   (void)flags;
 
   memset (c, 0, sizeof (*c));
 
+#ifdef USE_AVX2
+  c->use_avx2 = !!(features & HWF_INTEL_AVX2);
+#endif
+
   c->outlen = dbits / 8;
   c->buflen = 0;
   return blake2b_init(c, key, keylen);
 }
 
+/* Variable-length Hash Function H'.  */
+gcry_err_code_t
+blake2b_vl_hash (const void *in, size_t inlen, size_t outputlen, void *output)
+{
+  gcry_err_code_t ec;
+  BLAKE2B_CONTEXT ctx;
+  unsigned char buf[4];
+
+  ec = blake2b_init_ctx (&ctx, 0, NULL, 0,
+                         (outputlen < 64 ? outputlen: 64)*8);
+  if (ec)
+    return ec;
+
+  buf_put_le32 (buf, outputlen);
+  blake2b_write (&ctx, buf, 4);
+  blake2b_write (&ctx, in, inlen);
+  blake2b_final (&ctx);
+
+  if (outputlen <= 64)
+    memcpy (output, ctx.buf, outputlen);
+  else
+    {
+      int r = (outputlen-1)/32;
+      unsigned int remained = outputlen - 32*r;
+      int i;
+      unsigned char d[64];
+
+      i = 0;
+      while (1)
+        {
+          memcpy (d, ctx.buf, 64);
+          memcpy ((unsigned char *)output+i*32, d, 32);
+
+          if (++i >= r)
+            break;
+
+          ec = blake2b_init_ctx (&ctx, 0, NULL, 0, 64*8);
+          if (ec)
+            return ec;
+
+          blake2b_write (&ctx, d, 64);
+          blake2b_final (&ctx);
+        }
+
+      if (remained)
+        memcpy ((unsigned char *)output+r*32, d+32, remained);
+    }
+
+  wipememory (buf, sizeof (buf));
+  wipememory (&ctx, sizeof (ctx));
+  return 0;
+}
+
 static inline void blake2s_set_lastblock(BLAKE2S_STATE *S)
 {
   S->f[0] = 0xFFFFFFFFUL;
@@ -423,8 +543,9 @@ static inline void blake2s_increment_counter(BLAKE2S_STATE *S, const int inc)
   S->t[1] += (S->t[0] < (u32)inc) - (inc < 0);
 }
 
-static unsigned int blake2s_transform(void *vS, const void *inblks,
-                                     size_t nblks)
+static unsigned int blake2s_transform_generic(BLAKE2S_STATE *S,
+                                              const void *inblks,
+                                              size_t nblks)
 {
   static const byte blake2s_sigma[10][16] =
   {
@@ -439,7 +560,6 @@ static unsigned int blake2s_transform(void *vS, const void *inblks,
     {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 },
     { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 },
   };
-  BLAKE2S_STATE *S = vS;
   unsigned int burn = 0;
   const byte* in = inblks;
   u32 m[16];
@@ -538,6 +658,33 @@ static unsigned int blake2s_transform(void *vS, const void *inblks,
   return burn;
 }
 
+#ifdef USE_AVX
+unsigned int _gcry_blake2s_transform_amd64_avx(BLAKE2S_STATE *S,
+                                               const void *inblks,
+                                               size_t nblks) ASM_FUNC_ABI;
+#endif
+
+static unsigned int blake2s_transform(void *ctx, const void *inblks,
+                                      size_t nblks)
+{
+  BLAKE2S_CONTEXT *c = ctx;
+  unsigned int nburn;
+
+  if (0)
+    {}
+#ifdef USE_AVX
+  if (c->use_avx)
+    nburn = _gcry_blake2s_transform_amd64_avx(&c->state, inblks, nblks);
+#endif
+  else
+    nburn = blake2s_transform_generic(&c->state, inblks, nblks);
+
+  if (nburn)
+    nburn += ASM_EXTRA_STACK;
+
+  return nburn;
+}
+
 static void blake2s_final(void *ctx)
 {
   BLAKE2S_CONTEXT *c = ctx;
@@ -553,7 +700,7 @@ static void blake2s_final(void *ctx)
     memset (c->buf + c->buflen, 0, BLAKE2S_BLOCKBYTES - c->buflen); /* Padding */
   blake2s_set_lastblock (S);
   blake2s_increment_counter (S, (int)c->buflen - BLAKE2S_BLOCKBYTES);
-  burn = blake2s_transform (S, c->buf, 1);
+  burn = blake2s_transform (ctx, c->buf, 1);
 
   /* Output full hash to buffer */
   for (i = 0; i < 8; ++i)
@@ -629,11 +776,17 @@ static gcry_err_code_t blake2s_init_ctx(void *ctx, unsigned int flags,
                                        unsigned int dbits)
 {
   BLAKE2S_CONTEXT *c = ctx;
+  unsigned int features = _gcry_get_hw_features ();
 
+  (void)features;
   (void)flags;
 
   memset (c, 0, sizeof (*c));
 
+#ifdef USE_AVX
+  c->use_avx = !!(features & HWF_INTEL_AVX);
+#endif
+
   c->outlen = dbits / 8;
   c->buflen = 0;
   return blake2s_init(c, key, keylen);
@@ -845,19 +998,33 @@ gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags,
     int err = blake2##bs##_init_ctx (ctx, flags, NULL, 0, dbits); \
     gcry_assert (err == 0); \
   } \
-  static byte blake2##bs##_##dbits##_asn[] = { 0x30 }; \
-  static gcry_md_oid_spec_t oid_spec_blake2##bs##_##dbits[] = \
+  static void \
+  _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, \
+                          iov[0].len); \
+    blake2##bs##_final (&hd); \
+    memcpy (outbuf, blake2##bs##_read (&hd), dbits / 8); \
+  } \
+  static const byte blake2##bs##_##dbits##_asn[] = { 0x30 }; \
+  static const gcry_md_oid_spec_t oid_spec_blake2##bs##_##dbits[] = \
     { \
       { " 1.3.6.1.4.1.1722.12.2." oid_branch }, \
       { NULL } \
     }; \
-  gcry_md_spec_t _gcry_digest_spec_blake2##bs##_##dbits = \
+  const gcry_md_spec_t _gcry_digest_spec_blake2##bs##_##dbits = \
     { \
       GCRY_MD_BLAKE2##BS##_##dbits, {0, 0}, \
       "BLAKE2" #BS "_" #dbits, blake2##bs##_##dbits##_asn, \
       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_buffers, \
       sizeof (BLAKE2##BS##_CONTEXT), selftests_blake2##bs \
     };
 
diff --git a/cipher/blake2b-amd64-avx2.S b/cipher/blake2b-amd64-avx2.S
new file mode 100644 (file)
index 0000000..3601b65
--- /dev/null
@@ -0,0 +1,300 @@
+/* blake2b-amd64-avx2.S  -  AVX2 implementation of BLAKE2b
+ *
+ * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* The code is based on public-domain/CC0 BLAKE2 reference implementation
+ * by Samual Neves, at https://github.com/BLAKE2/BLAKE2/tree/master/sse
+ * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
+ */
+
+#ifdef __x86_64
+#include <config.h>
+#if defined(HAVE_GCC_INLINE_ASM_AVX2) && \
+   (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+
+#include "asm-common-amd64.h"
+
+.text
+
+/* register macros */
+#define RSTATE  %rdi
+#define RINBLKS %rsi
+#define RNBLKS  %rdx
+#define RIV     %rcx
+
+/* state structure */
+#define STATE_H 0
+#define STATE_T (STATE_H + 8 * 8)
+#define STATE_F (STATE_T + 2 * 8)
+
+/* vector registers */
+#define ROW1  %ymm0
+#define ROW2  %ymm1
+#define ROW3  %ymm2
+#define ROW4  %ymm3
+#define TMP1  %ymm4
+#define TMP1x %xmm4
+#define R16   %ymm5
+#define R24   %ymm6
+
+#define MA1   %ymm8
+#define MA2   %ymm9
+#define MA3   %ymm10
+#define MA4   %ymm11
+#define MA1x  %xmm8
+#define MA2x  %xmm9
+#define MA3x  %xmm10
+#define MA4x  %xmm11
+
+#define MB1   %ymm12
+#define MB2   %ymm13
+#define MB3   %ymm14
+#define MB4   %ymm15
+#define MB1x  %xmm12
+#define MB2x  %xmm13
+#define MB3x  %xmm14
+#define MB4x  %xmm15
+
+/**********************************************************************
+  blake2b/AVX2
+ **********************************************************************/
+
+#define GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                   s0, s1, s2, s3, s4, s5, s6, s7, s8, \
+                   s9, s10, s11, s12, s13, s14, s15) \
+        vmovq (s0)*8(RINBLKS), m1x; \
+        vmovq (s4)*8(RINBLKS), TMP1x; \
+        vpinsrq $1, (s2)*8(RINBLKS), m1x, m1x; \
+        vpinsrq $1, (s6)*8(RINBLKS), TMP1x, TMP1x; \
+        vinserti128 $1, TMP1x, m1, m1; \
+          vmovq (s1)*8(RINBLKS), m2x; \
+          vmovq (s5)*8(RINBLKS), TMP1x; \
+          vpinsrq $1, (s3)*8(RINBLKS), m2x, m2x; \
+          vpinsrq $1, (s7)*8(RINBLKS), TMP1x, TMP1x; \
+          vinserti128 $1, TMP1x, m2, m2; \
+            vmovq (s8)*8(RINBLKS), m3x; \
+            vmovq (s12)*8(RINBLKS), TMP1x; \
+            vpinsrq $1, (s10)*8(RINBLKS), m3x, m3x; \
+            vpinsrq $1, (s14)*8(RINBLKS), TMP1x, TMP1x; \
+            vinserti128 $1, TMP1x, m3, m3; \
+              vmovq (s9)*8(RINBLKS), m4x; \
+              vmovq (s13)*8(RINBLKS), TMP1x; \
+              vpinsrq $1, (s11)*8(RINBLKS), m4x, m4x; \
+              vpinsrq $1, (s15)*8(RINBLKS), TMP1x, TMP1x; \
+              vinserti128 $1, TMP1x, m4, m4;
+
+#define LOAD_MSG_0(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15)
+#define LOAD_MSG_1(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                   14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3)
+#define LOAD_MSG_2(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                   11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4)
+#define LOAD_MSG_3(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                    7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8)
+#define LOAD_MSG_4(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                    9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13)
+#define LOAD_MSG_5(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                    2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9)
+#define LOAD_MSG_6(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                   12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11)
+#define LOAD_MSG_7(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                   13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10)
+#define LOAD_MSG_8(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                    6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5)
+#define LOAD_MSG_9(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        GATHER_MSG(m1, m2, m3, m4, m1x, m2x, m3x, m4x, \
+                   10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0)
+#define LOAD_MSG_10(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        LOAD_MSG_0(m1, m2, m3, m4, m1x, m2x, m3x, m4x)
+#define LOAD_MSG_11(m1, m2, m3, m4, m1x, m2x, m3x, m4x) \
+        LOAD_MSG_1(m1, m2, m3, m4, m1x, m2x, m3x, m4x)
+
+#define LOAD_MSG(r, m1, m2, m3, m4) \
+        LOAD_MSG_##r(m1, m2, m3, m4, m1##x, m2##x, m3##x, m4##x)
+
+#define ROR_32(in, out) vpshufd $0xb1, in, out;
+
+#define ROR_24(in, out) vpshufb R24, in, out;
+
+#define ROR_16(in, out) vpshufb R16, in, out;
+
+#define ROR_63(in, out) \
+        vpsrlq $63, in, TMP1; \
+        vpaddq in, in, out; \
+        vpxor  TMP1, out, out;
+
+#define G(r1, r2, r3, r4, m, ROR_A, ROR_B) \
+        vpaddq m, r1, r1; \
+        vpaddq r2, r1, r1; \
+        vpxor r1, r4, r4; \
+        ROR_A(r4, r4); \
+        vpaddq r4, r3, r3; \
+        vpxor r3, r2, r2; \
+        ROR_B(r2, r2);
+
+#define G1(r1, r2, r3, r4, m) \
+        G(r1, r2, r3, r4, m, ROR_32, ROR_24);
+
+#define G2(r1, r2, r3, r4, m) \
+        G(r1, r2, r3, r4, m, ROR_16, ROR_63);
+
+#define MM_SHUFFLE(z,y,x,w) \
+        (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
+
+#define DIAGONALIZE(r1, r2, r3, r4) \
+        vpermq $MM_SHUFFLE(0,3,2,1), r2, r2; \
+        vpermq $MM_SHUFFLE(1,0,3,2), r3, r3; \
+        vpermq $MM_SHUFFLE(2,1,0,3), r4, r4;
+
+#define UNDIAGONALIZE(r1, r2, r3, r4) \
+        vpermq $MM_SHUFFLE(2,1,0,3), r2, r2; \
+        vpermq $MM_SHUFFLE(1,0,3,2), r3, r3; \
+        vpermq $MM_SHUFFLE(0,3,2,1), r4, r4;
+
+#define ROUND(r, m1, m2, m3, m4) \
+        G1(ROW1, ROW2, ROW3, ROW4, m1); \
+        G2(ROW1, ROW2, ROW3, ROW4, m2); \
+        DIAGONALIZE(ROW1, ROW2, ROW3, ROW4); \
+        G1(ROW1, ROW2, ROW3, ROW4, m3); \
+        G2(ROW1, ROW2, ROW3, ROW4, m4); \
+        UNDIAGONALIZE(ROW1, ROW2, ROW3, ROW4);
+
+blake2b_data:
+.align 32
+.Liv:
+        .quad 0x6a09e667f3bcc908, 0xbb67ae8584caa73b
+        .quad 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1
+        .quad 0x510e527fade682d1, 0x9b05688c2b3e6c1f
+        .quad 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
+.Lshuf_ror16:
+        .byte 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9
+.Lshuf_ror24:
+        .byte 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10
+
+.align 64
+.globl _gcry_blake2b_transform_amd64_avx2
+ELF(.type _gcry_blake2b_transform_amd64_avx2,@function;)
+
+_gcry_blake2b_transform_amd64_avx2:
+        /* input:
+         *     %rdi: state
+         *     %rsi: blks
+         *     %rdx: num_blks
+         */
+        CFI_STARTPROC();
+
+        vzeroupper;
+
+        addq $128, (STATE_T + 0)(RSTATE);
+        adcq $0, (STATE_T + 8)(RSTATE);
+
+        vbroadcasti128 .Lshuf_ror16 rRIP, R16;
+        vbroadcasti128 .Lshuf_ror24 rRIP, R24;
+
+        vmovdqa .Liv+(0 * 8) rRIP, ROW3;
+        vmovdqa .Liv+(4 * 8) rRIP, ROW4;
+
+        vmovdqu (STATE_H + 0 * 8)(RSTATE), ROW1;
+        vmovdqu (STATE_H + 4 * 8)(RSTATE), ROW2;
+
+        vpxor (STATE_T)(RSTATE), ROW4, ROW4;
+
+        LOAD_MSG(0, MA1, MA2, MA3, MA4);
+        LOAD_MSG(1, MB1, MB2, MB3, MB4);
+
+.Loop:
+        ROUND(0, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(2, MA1, MA2, MA3, MA4);
+        ROUND(1, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(3, MB1, MB2, MB3, MB4);
+        ROUND(2, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(4, MA1, MA2, MA3, MA4);
+        ROUND(3, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(5, MB1, MB2, MB3, MB4);
+        ROUND(4, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(6, MA1, MA2, MA3, MA4);
+        ROUND(5, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(7, MB1, MB2, MB3, MB4);
+        ROUND(6, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(8, MA1, MA2, MA3, MA4);
+        ROUND(7, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(9, MB1, MB2, MB3, MB4);
+        ROUND(8, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(10, MA1, MA2, MA3, MA4);
+        ROUND(9, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(11, MB1, MB2, MB3, MB4);
+        sub $1, RNBLKS;
+        jz .Loop_end;
+
+        lea 128(RINBLKS), RINBLKS;
+        addq $128, (STATE_T + 0)(RSTATE);
+        adcq $0, (STATE_T + 8)(RSTATE);
+
+        ROUND(10, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(0, MA1, MA2, MA3, MA4);
+        ROUND(11, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(1, MB1, MB2, MB3, MB4);
+
+        vpxor ROW3, ROW1, ROW1;
+        vpxor ROW4, ROW2, ROW2;
+
+        vmovdqa .Liv+(0 * 8) rRIP, ROW3;
+        vmovdqa .Liv+(4 * 8) rRIP, ROW4;
+
+        vpxor (STATE_H + 0 * 8)(RSTATE), ROW1, ROW1;
+        vpxor (STATE_H + 4 * 8)(RSTATE), ROW2, ROW2;
+
+        vmovdqu ROW1, (STATE_H + 0 * 8)(RSTATE);
+        vmovdqu ROW2, (STATE_H + 4 * 8)(RSTATE);
+
+        vpxor (STATE_T)(RSTATE), ROW4, ROW4;
+
+        jmp .Loop;
+
+.Loop_end:
+        ROUND(10, MA1, MA2, MA3, MA4);
+        ROUND(11, MB1, MB2, MB3, MB4);
+
+        vpxor ROW3, ROW1, ROW1;
+        vpxor ROW4, ROW2, ROW2;
+        vpxor (STATE_H + 0 * 8)(RSTATE), ROW1, ROW1;
+        vpxor (STATE_H + 4 * 8)(RSTATE), ROW2, ROW2;
+
+        vmovdqu ROW1, (STATE_H + 0 * 8)(RSTATE);
+        vmovdqu ROW2, (STATE_H + 4 * 8)(RSTATE);
+
+        xor %eax, %eax;
+        vzeroall;
+        ret_spec_stop;
+        CFI_ENDPROC();
+ELF(.size _gcry_blake2b_transform_amd64_avx2,
+    .-_gcry_blake2b_transform_amd64_avx2;)
+
+#endif /*defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)*/
+#endif /*__x86_64*/
diff --git a/cipher/blake2s-amd64-avx.S b/cipher/blake2s-amd64-avx.S
new file mode 100644 (file)
index 0000000..5094b4c
--- /dev/null
@@ -0,0 +1,278 @@
+/* blake2s-amd64-avx.S  -  AVX implementation of BLAKE2s
+ *
+ * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* The code is based on public-domain/CC0 BLAKE2 reference implementation
+ * by Samual Neves, at https://github.com/BLAKE2/BLAKE2/tree/master/sse
+ * Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
+ */
+
+#ifdef __x86_64
+#include <config.h>
+#if defined(HAVE_GCC_INLINE_ASM_AVX) && \
+   (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+
+#include "asm-common-amd64.h"
+
+.text
+
+/* register macros */
+#define RSTATE  %rdi
+#define RINBLKS %rsi
+#define RNBLKS  %rdx
+#define RIV     %rcx
+
+/* state structure */
+#define STATE_H 0
+#define STATE_T (STATE_H + 8 * 4)
+#define STATE_F (STATE_T + 2 * 4)
+
+/* vector registers */
+#define ROW1  %xmm0
+#define ROW2  %xmm1
+#define ROW3  %xmm2
+#define ROW4  %xmm3
+#define TMP1  %xmm4
+#define TMP1x %xmm4
+#define R16   %xmm5
+#define R8    %xmm6
+
+#define MA1   %xmm8
+#define MA2   %xmm9
+#define MA3   %xmm10
+#define MA4   %xmm11
+
+#define MB1   %xmm12
+#define MB2   %xmm13
+#define MB3   %xmm14
+#define MB4   %xmm15
+
+/**********************************************************************
+  blake2s/AVX
+ **********************************************************************/
+
+#define GATHER_MSG(m1, m2, m3, m4, \
+                   s0, s1, s2, s3, s4, s5, s6, s7, s8, \
+                   s9, s10, s11, s12, s13, s14, s15) \
+        vmovd (s0)*4(RINBLKS), m1; \
+          vmovd (s1)*4(RINBLKS), m2; \
+            vmovd (s8)*4(RINBLKS), m3; \
+              vmovd (s9)*4(RINBLKS), m4; \
+        vpinsrd $1, (s2)*4(RINBLKS), m1, m1; \
+          vpinsrd $1, (s3)*4(RINBLKS), m2, m2; \
+            vpinsrd $1, (s10)*4(RINBLKS), m3, m3; \
+              vpinsrd $1, (s11)*4(RINBLKS), m4, m4; \
+        vpinsrd $2, (s4)*4(RINBLKS), m1, m1; \
+          vpinsrd $2, (s5)*4(RINBLKS), m2, m2; \
+            vpinsrd $2, (s12)*4(RINBLKS), m3, m3; \
+              vpinsrd $2, (s13)*4(RINBLKS), m4, m4; \
+        vpinsrd $3, (s6)*4(RINBLKS), m1, m1; \
+          vpinsrd $3, (s7)*4(RINBLKS), m2, m2; \
+            vpinsrd $3, (s14)*4(RINBLKS), m3, m3; \
+              vpinsrd $3, (s15)*4(RINBLKS), m4, m4;
+
+#define LOAD_MSG_0(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15)
+#define LOAD_MSG_1(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                   14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3)
+#define LOAD_MSG_2(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                   11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4)
+#define LOAD_MSG_3(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                    7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8)
+#define LOAD_MSG_4(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                    9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13)
+#define LOAD_MSG_5(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                    2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9)
+#define LOAD_MSG_6(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                   12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11)
+#define LOAD_MSG_7(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                   13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10)
+#define LOAD_MSG_8(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                    6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5)
+#define LOAD_MSG_9(m1, m2, m3, m4) \
+        GATHER_MSG(m1, m2, m3, m4, \
+                   10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0)
+
+#define LOAD_MSG(r, m1, m2, m3, m4) LOAD_MSG_##r(m1, m2, m3, m4)
+
+#define ROR_16(in, out) vpshufb R16, in, out;
+
+#define ROR_8(in, out)  vpshufb R8, in, out;
+
+#define ROR_12(in, out) \
+        vpsrld $12, in, TMP1; \
+        vpslld $(32 - 12), in, out; \
+        vpxor TMP1, out, out;
+
+#define ROR_7(in, out) \
+        vpsrld $7, in, TMP1; \
+        vpslld $(32 - 7), in, out; \
+        vpxor TMP1, out, out;
+
+#define G(r1, r2, r3, r4, m, ROR_A, ROR_B) \
+        vpaddd m, r1, r1; \
+        vpaddd r2, r1, r1; \
+        vpxor r1, r4, r4; \
+        ROR_A(r4, r4); \
+        vpaddd r4, r3, r3; \
+        vpxor r3, r2, r2; \
+        ROR_B(r2, r2);
+
+#define G1(r1, r2, r3, r4, m) \
+        G(r1, r2, r3, r4, m, ROR_16, ROR_12);
+
+#define G2(r1, r2, r3, r4, m) \
+        G(r1, r2, r3, r4, m, ROR_8, ROR_7);
+
+#define MM_SHUFFLE(z,y,x,w) \
+        (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
+
+#define DIAGONALIZE(r1, r2, r3, r4) \
+        vpshufd $MM_SHUFFLE(0,3,2,1), r2, r2; \
+        vpshufd $MM_SHUFFLE(1,0,3,2), r3, r3; \
+        vpshufd $MM_SHUFFLE(2,1,0,3), r4, r4;
+
+#define UNDIAGONALIZE(r1, r2, r3, r4) \
+        vpshufd $MM_SHUFFLE(2,1,0,3), r2, r2; \
+        vpshufd $MM_SHUFFLE(1,0,3,2), r3, r3; \
+        vpshufd $MM_SHUFFLE(0,3,2,1), r4, r4;
+
+#define ROUND(r, m1, m2, m3, m4) \
+        G1(ROW1, ROW2, ROW3, ROW4, m1); \
+        G2(ROW1, ROW2, ROW3, ROW4, m2); \
+        DIAGONALIZE(ROW1, ROW2, ROW3, ROW4); \
+        G1(ROW1, ROW2, ROW3, ROW4, m3); \
+        G2(ROW1, ROW2, ROW3, ROW4, m4); \
+        UNDIAGONALIZE(ROW1, ROW2, ROW3, ROW4);
+
+blake2s_data:
+.align 16
+.Liv:
+        .long 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A
+        .long 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
+.Lshuf_ror16:
+        .byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13
+.Lshuf_ror8:
+        .byte 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12
+
+.align 64
+.globl _gcry_blake2s_transform_amd64_avx
+ELF(.type _gcry_blake2s_transform_amd64_avx,@function;)
+
+_gcry_blake2s_transform_amd64_avx:
+        /* input:
+         *     %rdi: state
+         *     %rsi: blks
+         *     %rdx: num_blks
+         */
+        CFI_STARTPROC();
+
+        vzeroupper;
+
+        addq $64, (STATE_T + 0)(RSTATE);
+
+        vmovdqa .Lshuf_ror16 rRIP, R16;
+        vmovdqa .Lshuf_ror8 rRIP, R8;
+
+        vmovdqa .Liv+(0 * 4) rRIP, ROW3;
+        vmovdqa .Liv+(4 * 4) rRIP, ROW4;
+
+        vmovdqu (STATE_H + 0 * 4)(RSTATE), ROW1;
+        vmovdqu (STATE_H + 4 * 4)(RSTATE), ROW2;
+
+        vpxor (STATE_T)(RSTATE), ROW4, ROW4;
+
+        LOAD_MSG(0, MA1, MA2, MA3, MA4);
+        LOAD_MSG(1, MB1, MB2, MB3, MB4);
+
+.Loop:
+        ROUND(0, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(2, MA1, MA2, MA3, MA4);
+        ROUND(1, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(3, MB1, MB2, MB3, MB4);
+        ROUND(2, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(4, MA1, MA2, MA3, MA4);
+        ROUND(3, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(5, MB1, MB2, MB3, MB4);
+        ROUND(4, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(6, MA1, MA2, MA3, MA4);
+        ROUND(5, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(7, MB1, MB2, MB3, MB4);
+        ROUND(6, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(8, MA1, MA2, MA3, MA4);
+        ROUND(7, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(9, MB1, MB2, MB3, MB4);
+        sub $1, RNBLKS;
+        jz .Loop_end;
+
+        lea 64(RINBLKS), RINBLKS;
+        addq $64, (STATE_T + 0)(RSTATE);
+
+        ROUND(8, MA1, MA2, MA3, MA4);
+                                      LOAD_MSG(0, MA1, MA2, MA3, MA4);
+        ROUND(9, MB1, MB2, MB3, MB4);
+                                      LOAD_MSG(1, MB1, MB2, MB3, MB4);
+
+        vpxor ROW3, ROW1, ROW1;
+        vpxor ROW4, ROW2, ROW2;
+
+        vmovdqa .Liv+(0 * 4) rRIP, ROW3;
+        vmovdqa .Liv+(4 * 4) rRIP, ROW4;
+
+        vpxor (STATE_H + 0 * 4)(RSTATE), ROW1, ROW1;
+        vpxor (STATE_H + 4 * 4)(RSTATE), ROW2, ROW2;
+
+        vmovdqu ROW1, (STATE_H + 0 * 4)(RSTATE);
+        vmovdqu ROW2, (STATE_H + 4 * 4)(RSTATE);
+
+        vpxor (STATE_T)(RSTATE), ROW4, ROW4;
+
+        jmp .Loop;
+
+.Loop_end:
+        ROUND(8, MA1, MA2, MA3, MA4);
+        ROUND(9, MB1, MB2, MB3, MB4);
+
+        vpxor ROW3, ROW1, ROW1;
+        vpxor ROW4, ROW2, ROW2;
+        vpxor (STATE_H + 0 * 4)(RSTATE), ROW1, ROW1;
+        vpxor (STATE_H + 4 * 4)(RSTATE), ROW2, ROW2;
+
+        vmovdqu ROW1, (STATE_H + 0 * 4)(RSTATE);
+        vmovdqu ROW2, (STATE_H + 4 * 4)(RSTATE);
+
+        xor %eax, %eax;
+        vzeroall;
+        ret_spec_stop;
+        CFI_ENDPROC();
+ELF(.size _gcry_blake2s_transform_amd64_avx,
+    .-_gcry_blake2s_transform_amd64_avx;)
+
+#endif /*defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)*/
+#endif /*__x86_64*/
index 21b63fc..2b4ffa1 100644 (file)
     (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
 
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -137,7 +133,9 @@ __blowfish_enc_blk1:
         * output:
         *      RX0: output plaintext block
         */
+       CFI_STARTPROC();
        movq %rbp, %r11;
+       CFI_REGISTER(%rbp, %r11);
 
        load_roundkey_enc(0);
        round_enc(2);
@@ -151,8 +149,10 @@ __blowfish_enc_blk1:
        add_roundkey_enc();
 
        movq %r11, %rbp;
+       CFI_RESTORE(%rbp)
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __blowfish_enc_blk1,.-__blowfish_enc_blk1;)
 
 .align 8
@@ -165,6 +165,9 @@ _gcry_blowfish_amd64_do_encrypt:
         *      %rsi: u32 *ret_xl
         *      %rdx: u32 *ret_xr
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        movl (%rdx), RX0d;
        shlq $32, RX0;
        movl (%rsi), RT3d;
@@ -178,7 +181,9 @@ _gcry_blowfish_amd64_do_encrypt:
        shrq $32, RX0;
        movl RX0d, (RX2);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_blowfish_amd64_do_encrypt,.-_gcry_blowfish_amd64_do_encrypt;)
 
 .align 8
@@ -191,6 +196,8 @@ _gcry_blowfish_amd64_encrypt_block:
         *      %rsi: dst
         *      %rdx: src
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
 
        movq %rsi, %r10;
 
@@ -202,7 +209,9 @@ _gcry_blowfish_amd64_encrypt_block:
        movq %r10, RIO;
        write_block();
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_blowfish_amd64_encrypt_block,.-_gcry_blowfish_amd64_encrypt_block;)
 
 .align 8
@@ -215,7 +224,11 @@ _gcry_blowfish_amd64_decrypt_block:
         *      %rsi: dst
         *      %rdx: src
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        movq %rbp, %r11;
+       CFI_REGISTER(%rbp, %r11);
 
        movq %rsi, %r10;
        movq %rdx, RIO;
@@ -237,8 +250,11 @@ _gcry_blowfish_amd64_decrypt_block:
        write_block();
 
        movq %r11, %rbp;
+       CFI_RESTORE(%rbp);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_blowfish_amd64_decrypt_block,.-_gcry_blowfish_amd64_decrypt_block;)
 
 /**********************************************************************
@@ -336,6 +352,7 @@ __blowfish_enc_blk4:
         * output:
         *      RX0,RX1,RX2,RX3: four output ciphertext blocks
         */
+       CFI_STARTPROC();
        preload_roundkey_enc(0);
 
        round_enc4(0);
@@ -350,7 +367,8 @@ __blowfish_enc_blk4:
 
        outbswap_block4();
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __blowfish_enc_blk4,.-__blowfish_enc_blk4;)
 
 .align 8
@@ -363,6 +381,7 @@ __blowfish_dec_blk4:
         * output:
         *      RX0,RX1,RX2,RX3: four output plaintext blocks
         */
+       CFI_STARTPROC();
        preload_roundkey_dec(17);
 
        inbswap_block4();
@@ -379,7 +398,8 @@ __blowfish_dec_blk4:
 
        outbswap_block4();
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __blowfish_dec_blk4,.-__blowfish_dec_blk4;)
 
 .align 8
@@ -392,10 +412,17 @@ _gcry_blowfish_amd64_ctr_enc:
         *      %rdx: src (4 blocks)
         *      %rcx: iv (big endian, 64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
 
        /* %r11-%r13 are not used by __blowfish_enc_blk4 */
        movq %rcx, %r13; /*iv*/
@@ -432,11 +459,17 @@ _gcry_blowfish_amd64_ctr_enc:
        movq RX3, 3 * 8(%r11);
 
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
+       CFI_POP(%rbp);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_blowfish_amd64_ctr_enc,.-_gcry_blowfish_amd64_ctr_enc;)
 
 .align 8
@@ -449,10 +482,17 @@ _gcry_blowfish_amd64_cbc_dec:
         *      %rdx: src (4 blocks)
         *      %rcx: iv (64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
 
        /* %r11-%r13 are not used by __blowfish_dec_blk4 */
        movq %rsi, %r11; /*dst*/
@@ -480,11 +520,17 @@ _gcry_blowfish_amd64_cbc_dec:
        movq RX3, 3 * 8(%r11);
 
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
+       CFI_POP(%rbp);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_blowfish_amd64_cbc_dec,.-_gcry_blowfish_amd64_cbc_dec;)
 
 .align 8
@@ -497,10 +543,17 @@ _gcry_blowfish_amd64_cfb_dec:
         *      %rdx: src (4 blocks)
         *      %rcx: iv (64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
 
        /* %r11-%r13 are not used by __blowfish_enc_blk4 */
        movq %rcx, %r13; /*iv*/
@@ -531,10 +584,17 @@ _gcry_blowfish_amd64_cfb_dec:
        movq RX3, 3 * 8(%r11);
 
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
-       ret;
+       CFI_POP(%rbp);
+
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_blowfish_amd64_cfb_dec,.-_gcry_blowfish_amd64_cfb_dec;)
 
 #endif /*defined(USE_BLOWFISH)*/
index a3fc26c..7b00130 100644 (file)
 #include "g10lib.h"
 #include "cipher.h"
 #include "bufhelp.h"
+#include "cipher-internal.h"
 #include "cipher-selftest.h"
 
 #define BLOWFISH_BLOCKSIZE 8
-#define BLOWFISH_ROUNDS 16
+#define BLOWFISH_KEY_MIN_BITS 8
+#define BLOWFISH_KEY_MAX_BITS 576
 
 
 /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */
 #undef USE_AMD64_ASM
 #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
-    (BLOWFISH_ROUNDS == 16)
+    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
 # define USE_AMD64_ASM 1
 #endif
 
 /* USE_ARM_ASM indicates whether to use ARM assembly code. */
 #undef USE_ARM_ASM
 #if defined(__ARMEL__)
-# if (BLOWFISH_ROUNDS == 16) && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS)
+# if defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS)
 #  define USE_ARM_ASM 1
 # endif
 #endif
@@ -64,10 +65,11 @@ typedef struct {
     u32 s1[256];
     u32 s2[256];
     u32 s3[256];
-    u32 p[BLOWFISH_ROUNDS+2];
+    u32 p[16+2];
 } BLOWFISH_context;
 
-static gcry_err_code_t bf_setkey (void *c, const byte *key, unsigned keylen);
+static gcry_err_code_t bf_setkey (void *c, const byte *key, unsigned keylen,
+                                  cipher_bulk_ops_t *bulk_ops);
 static unsigned int encrypt_block (void *bc, byte *outbuf, const byte *inbuf);
 static unsigned int decrypt_block (void *bc, byte *outbuf, const byte *inbuf);
 
@@ -253,7 +255,7 @@ static const u32 ks3[256] = {
     0x01C36AE4,0xD6EBE1F9,0x90D4F869,0xA65CDEA0,0x3F09252D,0xC208E69F,
     0xB74E6132,0xCE77E25B,0x578FDFE3,0x3AC372E6 };
 
-static const u32 ps[BLOWFISH_ROUNDS+2] = {
+static const u32 ps[16+2] = {
     0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,0xA4093822,0x299F31D0,
     0x082EFA98,0xEC4E6C89,0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C,
     0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917,0x9216D5D9,0x8979FB1B };
@@ -281,87 +283,43 @@ extern void _gcry_blowfish_amd64_cbc_dec(BLOWFISH_context *ctx, byte *out,
 extern void _gcry_blowfish_amd64_cfb_dec(BLOWFISH_context *ctx, byte *out,
                                         const byte *in, byte *iv);
 
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-static inline void
-call_sysv_fn (const void *fn, const void *arg1, const void *arg2,
-              const void *arg3, const void *arg4)
-{
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  asm volatile ("callq *%0\n\t"
-                : "+a" (fn),
-                  "+D" (arg1),
-                  "+S" (arg2),
-                  "+d" (arg3),
-                  "+c" (arg4)
-                :
-                : "cc", "memory", "r8", "r9", "r10", "r11");
-}
-#endif
-
 static void
 do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_blowfish_amd64_do_encrypt, bc, ret_xl, ret_xr, NULL);
-#else
   _gcry_blowfish_amd64_do_encrypt (bc, ret_xl, ret_xr);
-#endif
 }
 
 static void
 do_encrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_blowfish_amd64_encrypt_block, context, outbuf, inbuf,
-                NULL);
-#else
   _gcry_blowfish_amd64_encrypt_block (context, outbuf, inbuf);
-#endif
 }
 
 static void
 do_decrypt_block (BLOWFISH_context *context, byte *outbuf, const byte *inbuf)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_blowfish_amd64_decrypt_block, context, outbuf, inbuf,
-                NULL);
-#else
   _gcry_blowfish_amd64_decrypt_block (context, outbuf, inbuf);
-#endif
 }
 
 static inline void
 blowfish_amd64_ctr_enc(BLOWFISH_context *ctx, byte *out, const byte *in,
                        byte *ctr)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_blowfish_amd64_ctr_enc, ctx, out, in, ctr);
-#else
   _gcry_blowfish_amd64_ctr_enc(ctx, out, in, ctr);
-#endif
 }
 
 static inline void
 blowfish_amd64_cbc_dec(BLOWFISH_context *ctx, byte *out, const byte *in,
                        byte *iv)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_blowfish_amd64_cbc_dec, ctx, out, in, iv);
-#else
   _gcry_blowfish_amd64_cbc_dec(ctx, out, in, iv);
-#endif
 }
 
 static inline void
 blowfish_amd64_cfb_dec(BLOWFISH_context *ctx, byte *out, const byte *in,
                        byte *iv)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_blowfish_amd64_cfb_dec, ctx, out, in, iv);
-#else
   _gcry_blowfish_amd64_cfb_dec(ctx, out, in, iv);
-#endif
 }
 
 static unsigned int
@@ -438,42 +396,16 @@ decrypt_block (void *context, byte *outbuf, const byte *inbuf)
 
 #else /*USE_ARM_ASM*/
 
-#if BLOWFISH_ROUNDS != 16
-static inline u32
-function_F( BLOWFISH_context *bc, u32 x )
-{
-    u16 a, b, c, d;
-
-#ifdef WORDS_BIGENDIAN
-    a = ((byte*)&x)[0];
-    b = ((byte*)&x)[1];
-    c = ((byte*)&x)[2];
-    d = ((byte*)&x)[3];
-#else
-    a = ((byte*)&x)[3];
-    b = ((byte*)&x)[2];
-    c = ((byte*)&x)[1];
-    d = ((byte*)&x)[0];
-#endif
 
-    return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d];
-}
-#endif
-
-#ifdef WORDS_BIGENDIAN
-#define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]])       \
-                  ^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] )
-#else
-#define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]])       \
-                  ^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] )
-#endif
-#define R(l,r,i)  do { l ^= p[i]; r ^= F(l); } while(0)
+#define F(x) ((( s0[(x)>>24] + s1[((x)>>16)&0xff])      \
+                  ^ s2[((x)>>8)&0xff]) + s3[(x)&0xff] )
+#define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0)
+#define R3(l,r,i) do { R(l##0,r##0,i);R(l##1,r##1,i);R(l##2,r##2,i);} while(0)
 
 
 static void
 do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
 {
-#if BLOWFISH_ROUNDS == 16
   u32 xl, xr, *s0, *s1, *s2, *s3, *p;
 
   xl = *ret_xl;
@@ -484,16 +416,16 @@ do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
   s2 = bc->s2;
   s3 = bc->s3;
 
-  R( xl, xr,   0);
-  R( xr, xl,   1);
-  R( xl, xr,   2);
-  R( xr, xl,   3);
-  R( xl, xr,   4);
-  R( xr, xl,   5);
-  R( xl, xr,   6);
-  R( xr, xl,   7);
-  R( xl, xr,   8);
-  R( xr, xl,   9);
+  R( xl, xr,  0);
+  R( xr, xl,  1);
+  R( xl, xr,  2);
+  R( xr, xl,  3);
+  R( xl, xr,  4);
+  R( xr, xl,  5);
+  R( xl, xr,  6);
+  R( xr, xl,  7);
+  R( xl, xr,  8);
+  R( xr, xl,  9);
   R( xl, xr, 10);
   R( xr, xl, 11);
   R( xl, xr, 12);
@@ -501,45 +433,67 @@ do_encrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
   R( xl, xr, 14);
   R( xr, xl, 15);
 
-  xl ^= p[BLOWFISH_ROUNDS];
-  xr ^= p[BLOWFISH_ROUNDS+1];
+  xl ^= p[16];
+  xr ^= p[16+1];
 
   *ret_xl = xr;
   *ret_xr = xl;
+}
 
-#else
-  u32 xl, xr, temp, *p;
-  int i;
 
-  xl = *ret_xl;
-  xr = *ret_xr;
+static void
+do_encrypt_3 ( BLOWFISH_context *bc, byte *dst, const byte *src )
+{
+  u32 xl0, xr0, xl1, xr1, xl2, xr2, *s0, *s1, *s2, *s3, *p;
+
+  xl0 = buf_get_be32(src + 0);
+  xr0 = buf_get_be32(src + 4);
+  xl1 = buf_get_be32(src + 8);
+  xr1 = buf_get_be32(src + 12);
+  xl2 = buf_get_be32(src + 16);
+  xr2 = buf_get_be32(src + 20);
   p = bc->p;
+  s0 = bc->s0;
+  s1 = bc->s1;
+  s2 = bc->s2;
+  s3 = bc->s3;
 
-  for(i=0; i < BLOWFISH_ROUNDS; i++ )
-    {
-      xl ^= p[i];
-      xr ^= function_F(bc, xl);
-      temp = xl;
-      xl = xr;
-      xr = temp;
-    }
-  temp = xl;
-  xl = xr;
-  xr = temp;
-
-  xr ^= p[BLOWFISH_ROUNDS];
-  xl ^= p[BLOWFISH_ROUNDS+1];
-
-  *ret_xl = xl;
-  *ret_xr = xr;
-#endif
+  R3( xl, xr,  0);
+  R3( xr, xl,  1);
+  R3( xl, xr,  2);
+  R3( xr, xl,  3);
+  R3( xl, xr,  4);
+  R3( xr, xl,  5);
+  R3( xl, xr,  6);
+  R3( xr, xl,  7);
+  R3( xl, xr,  8);
+  R3( xr, xl,  9);
+  R3( xl, xr, 10);
+  R3( xr, xl, 11);
+  R3( xl, xr, 12);
+  R3( xr, xl, 13);
+  R3( xl, xr, 14);
+  R3( xr, xl, 15);
+
+  xl0 ^= p[16];
+  xr0 ^= p[16+1];
+  xl1 ^= p[16];
+  xr1 ^= p[16+1];
+  xl2 ^= p[16];
+  xr2 ^= p[16+1];
+
+  buf_put_be32(dst + 0, xr0);
+  buf_put_be32(dst + 4, xl0);
+  buf_put_be32(dst + 8, xr1);
+  buf_put_be32(dst + 12, xl1);
+  buf_put_be32(dst + 16, xr2);
+  buf_put_be32(dst + 20, xl2);
 }
 
 
 static void
 decrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
 {
-#if BLOWFISH_ROUNDS == 16
   u32 xl, xr, *s0, *s1, *s2, *s3, *p;
 
   xl = *ret_xl;
@@ -558,52 +512,75 @@ decrypt ( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
   R( xr, xl, 12);
   R( xl, xr, 11);
   R( xr, xl, 10);
-  R( xl, xr,   9);
-  R( xr, xl,   8);
-  R( xl, xr,   7);
-  R( xr, xl,   6);
-  R( xl, xr,   5);
-  R( xr, xl,   4);
-  R( xl, xr,   3);
-  R( xr, xl,   2);
+  R( xl, xr,  9);
+  R( xr, xl,  8);
+  R( xl, xr,  7);
+  R( xr, xl,  6);
+  R( xl, xr,  5);
+  R( xr, xl,  4);
+  R( xl, xr,  3);
+  R( xr, xl,  2);
 
   xl ^= p[1];
   xr ^= p[0];
 
   *ret_xl = xr;
   *ret_xr = xl;
+}
 
-#else
-  u32 xl, xr, temp, *p;
-  int i;
 
-  xl = *ret_xl;
-  xr = *ret_xr;
+static void
+do_decrypt_3 ( BLOWFISH_context *bc, byte *dst, const byte *src )
+{
+  u32 xl0, xr0, xl1, xr1, xl2, xr2, *s0, *s1, *s2, *s3, *p;
+
+  xl0 = buf_get_be32(src + 0);
+  xr0 = buf_get_be32(src + 4);
+  xl1 = buf_get_be32(src + 8);
+  xr1 = buf_get_be32(src + 12);
+  xl2 = buf_get_be32(src + 16);
+  xr2 = buf_get_be32(src + 20);
   p = bc->p;
+  s0 = bc->s0;
+  s1 = bc->s1;
+  s2 = bc->s2;
+  s3 = bc->s3;
 
-  for (i=BLOWFISH_ROUNDS+1; i > 1; i-- )
-    {
-      xl ^= p[i];
-      xr ^= function_F(bc, xl);
-      temp = xl;
-      xl = xr;
-      xr = temp;
-    }
-
-  temp = xl;
-  xl = xr;
-  xr = temp;
-
-  xr ^= p[1];
-  xl ^= p[0];
-
-  *ret_xl = xl;
-  *ret_xr = xr;
-#endif
+  R3( xl, xr, 17);
+  R3( xr, xl, 16);
+  R3( xl, xr, 15);
+  R3( xr, xl, 14);
+  R3( xl, xr, 13);
+  R3( xr, xl, 12);
+  R3( xl, xr, 11);
+  R3( xr, xl, 10);
+  R3( xl, xr,  9);
+  R3( xr, xl,  8);
+  R3( xl, xr,  7);
+  R3( xr, xl,  6);
+  R3( xl, xr,  5);
+  R3( xr, xl,  4);
+  R3( xl, xr,  3);
+  R3( xr, xl,  2);
+
+  xl0 ^= p[1];
+  xr0 ^= p[0];
+  xl1 ^= p[1];
+  xr1 ^= p[0];
+  xl2 ^= p[1];
+  xr2 ^= p[0];
+
+  buf_put_be32(dst + 0, xr0);
+  buf_put_be32(dst + 4, xl0);
+  buf_put_be32(dst + 8, xr1);
+  buf_put_be32(dst + 12, xl1);
+  buf_put_be32(dst + 16, xr2);
+  buf_put_be32(dst + 20, xl2);
 }
 
 #undef F
 #undef R
+#undef R3
 
 static void
 do_encrypt_block ( BLOWFISH_context *bc, byte *outbuf, const byte *inbuf )
@@ -652,16 +629,15 @@ decrypt_block (void *context, byte *outbuf, const byte *inbuf)
 /* Bulk encryption of complete blocks in CTR mode.  This function is only
    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
    of size BLOWFISH_BLOCKSIZE. */
-void
+static void
 _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
                       const void *inbuf_arg, size_t nblocks)
 {
   BLOWFISH_context *ctx = context;
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
-  unsigned char tmpbuf[BLOWFISH_BLOCKSIZE];
-  int burn_stack_depth = (64) + 2 * BLOWFISH_BLOCKSIZE;
-  int i;
+  unsigned char tmpbuf[BLOWFISH_BLOCKSIZE * 3];
+  int burn_stack_depth = (64) + 4 * BLOWFISH_BLOCKSIZE;
 
 #ifdef USE_AMD64_ASM
   {
@@ -679,7 +655,6 @@ _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
       }
 
     /* Use generic code to handle smaller chunks... */
-    /* TODO: use caching instead? */
   }
 #elif defined(USE_ARM_ASM)
   {
@@ -694,25 +669,38 @@ _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
       }
 
     /* Use generic code to handle smaller chunks... */
-    /* TODO: use caching instead? */
   }
 #endif
 
+#if !defined(USE_AMD64_ASM) && !defined(USE_ARM_ASM)
+  for ( ;nblocks >= 3; nblocks -= 3)
+    {
+      /* Prepare the counter blocks. */
+      cipher_block_cpy (tmpbuf + 0, ctr, BLOWFISH_BLOCKSIZE);
+      cipher_block_cpy (tmpbuf + 8, ctr, BLOWFISH_BLOCKSIZE);
+      cipher_block_cpy (tmpbuf + 16, ctr, BLOWFISH_BLOCKSIZE);
+      cipher_block_add (tmpbuf + 8, 1, BLOWFISH_BLOCKSIZE);
+      cipher_block_add (tmpbuf + 16, 2, BLOWFISH_BLOCKSIZE);
+      cipher_block_add (ctr, 3, BLOWFISH_BLOCKSIZE);
+      /* Encrypt the counter. */
+      do_encrypt_3(ctx, tmpbuf, tmpbuf);
+      /* XOR the input with the encrypted counter and store in output.  */
+      buf_xor(outbuf, tmpbuf, inbuf, BLOWFISH_BLOCKSIZE * 3);
+      outbuf += BLOWFISH_BLOCKSIZE * 3;
+      inbuf  += BLOWFISH_BLOCKSIZE * 3;
+    }
+#endif
+
   for ( ;nblocks; nblocks-- )
     {
       /* Encrypt the counter. */
       do_encrypt_block(ctx, tmpbuf, ctr);
       /* XOR the input with the encrypted counter and store in output.  */
-      buf_xor(outbuf, tmpbuf, inbuf, BLOWFISH_BLOCKSIZE);
+      cipher_block_xor(outbuf, tmpbuf, inbuf, BLOWFISH_BLOCKSIZE);
       outbuf += BLOWFISH_BLOCKSIZE;
       inbuf  += BLOWFISH_BLOCKSIZE;
       /* Increment the counter.  */
-      for (i = BLOWFISH_BLOCKSIZE; i > 0; i--)
-        {
-          ctr[i-1]++;
-          if (ctr[i-1])
-            break;
-        }
+      cipher_block_add (ctr, 1, BLOWFISH_BLOCKSIZE);
     }
 
   wipememory(tmpbuf, sizeof(tmpbuf));
@@ -722,15 +710,15 @@ _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
 
 /* Bulk decryption of complete blocks in CBC mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
                       const void *inbuf_arg, size_t nblocks)
 {
   BLOWFISH_context *ctx = context;
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
-  unsigned char savebuf[BLOWFISH_BLOCKSIZE];
-  int burn_stack_depth = (64) + 2 * BLOWFISH_BLOCKSIZE;
+  unsigned char savebuf[BLOWFISH_BLOCKSIZE * 3];
+  int burn_stack_depth = (64) + 4 * BLOWFISH_BLOCKSIZE;
 
 #ifdef USE_AMD64_ASM
   {
@@ -765,13 +753,29 @@ _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
   }
 #endif
 
+#if !defined(USE_AMD64_ASM) && !defined(USE_ARM_ASM)
+  for ( ;nblocks >= 3; nblocks -= 3)
+    {
+      /* INBUF is needed later and it may be identical to OUTBUF, so store
+         the intermediate result to SAVEBUF.  */
+      do_decrypt_3 (ctx, savebuf, inbuf);
+
+      cipher_block_xor_1 (savebuf + 0, iv, BLOWFISH_BLOCKSIZE);
+      cipher_block_xor_1 (savebuf + 8, inbuf, BLOWFISH_BLOCKSIZE * 2);
+      cipher_block_cpy (iv, inbuf + 16, BLOWFISH_BLOCKSIZE);
+      buf_cpy (outbuf, savebuf, BLOWFISH_BLOCKSIZE * 3);
+      inbuf += BLOWFISH_BLOCKSIZE * 3;
+      outbuf += BLOWFISH_BLOCKSIZE * 3;
+    }
+#endif
+
   for ( ;nblocks; nblocks-- )
     {
       /* INBUF is needed later and it may be identical to OUTBUF, so store
          the intermediate result to SAVEBUF.  */
       do_decrypt_block (ctx, savebuf, inbuf);
 
-      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOWFISH_BLOCKSIZE);
+      cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOWFISH_BLOCKSIZE);
       inbuf += BLOWFISH_BLOCKSIZE;
       outbuf += BLOWFISH_BLOCKSIZE;
     }
@@ -783,14 +787,15 @@ _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
 
 /* Bulk decryption of complete blocks in CFB mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_blowfish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
                       const void *inbuf_arg, size_t nblocks)
 {
   BLOWFISH_context *ctx = context;
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
-  int burn_stack_depth = (64) + 2 * BLOWFISH_BLOCKSIZE;
+  unsigned char tmpbuf[BLOWFISH_BLOCKSIZE * 3];
+  int burn_stack_depth = (64) + 4 * BLOWFISH_BLOCKSIZE;
 
 #ifdef USE_AMD64_ASM
   {
@@ -825,14 +830,28 @@ _gcry_blowfish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
   }
 #endif
 
+#if !defined(USE_AMD64_ASM) && !defined(USE_ARM_ASM)
+  for ( ;nblocks >= 3; nblocks -= 3 )
+    {
+      cipher_block_cpy (tmpbuf + 0, iv, BLOWFISH_BLOCKSIZE);
+      cipher_block_cpy (tmpbuf + 8, inbuf + 0, BLOWFISH_BLOCKSIZE * 2);
+      cipher_block_cpy (iv, inbuf + 16, BLOWFISH_BLOCKSIZE);
+      do_encrypt_3 (ctx, tmpbuf, tmpbuf);
+      buf_xor (outbuf, inbuf, tmpbuf, BLOWFISH_BLOCKSIZE * 3);
+      outbuf += BLOWFISH_BLOCKSIZE * 3;
+      inbuf  += BLOWFISH_BLOCKSIZE * 3;
+    }
+#endif
+
   for ( ;nblocks; nblocks-- )
     {
       do_encrypt_block(ctx, iv, iv);
-      buf_xor_n_copy(outbuf, iv, inbuf, BLOWFISH_BLOCKSIZE);
+      cipher_block_xor_n_copy(outbuf, iv, inbuf, BLOWFISH_BLOCKSIZE);
       outbuf += BLOWFISH_BLOCKSIZE;
       inbuf  += BLOWFISH_BLOCKSIZE;
     }
 
+  wipememory(tmpbuf, sizeof(tmpbuf));
   _gcry_burn_stack(burn_stack_depth);
 }
 
@@ -847,8 +866,7 @@ selftest_ctr (void)
   const int context_size = sizeof(BLOWFISH_context);
 
   return _gcry_selftest_helper_ctr("BLOWFISH", &bf_setkey,
-           &encrypt_block, &_gcry_blowfish_ctr_enc, nblocks, blocksize,
-          context_size);
+           &encrypt_block, nblocks, blocksize, context_size);
 }
 
 
@@ -862,8 +880,7 @@ selftest_cbc (void)
   const int context_size = sizeof(BLOWFISH_context);
 
   return _gcry_selftest_helper_cbc("BLOWFISH", &bf_setkey,
-           &encrypt_block, &_gcry_blowfish_cbc_dec, nblocks, blocksize,
-          context_size);
+           &encrypt_block, nblocks, blocksize, context_size);
 }
 
 
@@ -877,8 +894,7 @@ selftest_cfb (void)
   const int context_size = sizeof(BLOWFISH_context);
 
   return _gcry_selftest_helper_cfb("BLOWFISH", &bf_setkey,
-           &encrypt_block, &_gcry_blowfish_cfb_dec, nblocks, blocksize,
-          context_size);
+           &encrypt_block, nblocks, blocksize, context_size);
 }
 
 
@@ -886,6 +902,7 @@ static const char*
 selftest(void)
 {
   BLOWFISH_context c;
+  cipher_bulk_ops_t bulk_ops;
   byte plain[] = "BLOWFISH";
   byte buffer[8];
   static const byte plain3[] =
@@ -897,7 +914,8 @@ selftest(void)
   const char *r;
 
   bf_setkey( (void *) &c,
-             (const unsigned char*)"abcdefghijklmnopqrstuvwxyz", 26 );
+             (const unsigned char*)"abcdefghijklmnopqrstuvwxyz", 26,
+             &bulk_ops );
   encrypt_block( (void *) &c, buffer, plain );
   if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) )
     return "Blowfish selftest failed (1).";
@@ -905,7 +923,7 @@ selftest(void)
   if( memcmp( buffer, plain, 8 ) )
     return "Blowfish selftest failed (2).";
 
-  bf_setkey( (void *) &c, key3, 8 );
+  bf_setkey( (void *) &c, key3, 8, &bulk_ops );
   encrypt_block( (void *) &c, buffer, plain3 );
   if( memcmp( buffer, cipher3, 8 ) )
     return "Blowfish selftest failed (3).";
@@ -1001,9 +1019,13 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen)
   if( selftest_failed )
     return GPG_ERR_SELFTEST_FAILED;
 
+  if (keylen < BLOWFISH_KEY_MIN_BITS / 8 ||
+      keylen > BLOWFISH_KEY_MAX_BITS / 8)
+    return GPG_ERR_INV_KEYLEN;
+
   memset(hset, 0, sizeof(hset));
 
-  for(i=0; i < BLOWFISH_ROUNDS+2; i++ )
+  for(i=0; i < 16+2; i++ )
     c->p[i] = ps[i];
   for(i=0; i < 256; i++ )
     {
@@ -1013,7 +1035,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen)
       c->s3[i] = ks3[i];
     }
 
-  for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ )
+  for(i=j=0; i < 16+2; i++ )
     {
       data = ((u32)key[j] << 24) |
              ((u32)key[(j+1)%keylen] << 16) |
@@ -1024,7 +1046,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen)
     }
 
   datal = datar = 0;
-  for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 )
+  for(i=0; i < 16+2; i += 2 )
     {
       do_encrypt( c, &datal, &datar );
       c->p[i]   = datal;
@@ -1095,10 +1117,18 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen)
 
 
 static gcry_err_code_t
-bf_setkey (void *context, const byte *key, unsigned keylen)
+bf_setkey (void *context, const byte *key, unsigned keylen,
+           cipher_bulk_ops_t *bulk_ops)
 {
   BLOWFISH_context *c = (BLOWFISH_context *) context;
   gcry_err_code_t rc = do_bf_setkey (c, key, keylen);
+
+  /* Setup bulk encryption routines.  */
+  memset (bulk_ops, 0, sizeof(*bulk_ops));
+  bulk_ops->cfb_dec = _gcry_blowfish_cfb_dec;
+  bulk_ops->cbc_dec = _gcry_blowfish_cbc_dec;
+  bulk_ops->ctr_enc = _gcry_blowfish_ctr_enc;
+
   return rc;
 }
 
index 83d3f53..fa5b2e8 100644 (file)
 #endif
 
 
-#undef BUFHELP_FAST_UNALIGNED_ACCESS
-#if defined(BUFHELP_UNALIGNED_ACCESS) && \
-    (defined(__i386__) || defined(__x86_64__) || \
-     (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \
-     defined(__aarch64__))
-/* These architectures are able of unaligned memory accesses and can
-   handle those fast.
- */
-# define BUFHELP_FAST_UNALIGNED_ACCESS 1
-#endif
-
-
-#ifdef BUFHELP_FAST_UNALIGNED_ACCESS
-/* Define type with one-byte alignment on architectures with fast unaligned
-   memory accesses.
- */
-typedef struct bufhelp_int_s
-{
-  uintptr_t a;
-} __attribute__((packed, aligned(1), may_alias)) bufhelp_int_t;
-#else
-/* Define type with default alignment for other architectures (unaligned
-   accessed handled in per byte loops).
- */
-#ifdef HAVE_GCC_ATTRIBUTE_MAY_ALIAS
-typedef struct bufhelp_int_s
-{
-  uintptr_t a;
-} __attribute__((may_alias)) bufhelp_int_t;
-#else
-typedef struct bufhelp_int_s
-{
-  uintptr_t a;
-} bufhelp_int_t;
-#endif
-#endif
-
-
-/* Optimized function for small buffer copying */
-static inline void
-buf_cpy(void *_dst, const void *_src, size_t len)
-{
-#if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__))
-  /* For AMD64 and i386, memcpy is faster.  */
-  memcpy(_dst, _src, len);
-#else
-  byte *dst = _dst;
-  const byte *src = _src;
-  bufhelp_int_t *ldst;
-  const bufhelp_int_t *lsrc;
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
-
-  /* Skip fast processing if buffers are unaligned.  */
-  if (UNLIKELY(((uintptr_t)dst | (uintptr_t)src) & longmask))
-    goto do_bytes;
-#endif
-
-  ldst = (bufhelp_int_t *)(void *)dst;
-  lsrc = (const bufhelp_int_t *)(const void *)src;
-
-  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
-    (ldst++)->a = (lsrc++)->a;
-
-  dst = (byte *)ldst;
-  src = (const byte *)lsrc;
-
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-do_bytes:
-#endif
-  /* Handle tail.  */
-  for (; len; len--)
-    *dst++ = *src++;
-#endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/
-}
-
-
-/* Optimized function for buffer xoring */
-static inline void
-buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
-{
-  byte *dst = _dst;
-  const byte *src1 = _src1;
-  const byte *src2 = _src2;
-  bufhelp_int_t *ldst;
-  const bufhelp_int_t *lsrc1, *lsrc2;
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
-
-  /* Skip fast processing if buffers are unaligned.  */
-  if (UNLIKELY(((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask))
-    goto do_bytes;
-#endif
-
-  ldst = (bufhelp_int_t *)(void *)dst;
-  lsrc1 = (const bufhelp_int_t *)(const void *)src1;
-  lsrc2 = (const bufhelp_int_t *)(const void *)src2;
-
-  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
-    (ldst++)->a = (lsrc1++)->a ^ (lsrc2++)->a;
-
-  dst = (byte *)ldst;
-  src1 = (const byte *)lsrc1;
-  src2 = (const byte *)lsrc2;
-
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-do_bytes:
-#endif
-  /* Handle tail.  */
-  for (; len; len--)
-    *dst++ = *src1++ ^ *src2++;
-}
-
-
-/* Optimized function for in-place buffer xoring. */
-static inline void
-buf_xor_1(void *_dst, const void *_src, size_t len)
-{
-  byte *dst = _dst;
-  const byte *src = _src;
-  bufhelp_int_t *ldst;
-  const bufhelp_int_t *lsrc;
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
-
-  /* Skip fast processing if buffers are unaligned.  */
-  if (UNLIKELY(((uintptr_t)dst | (uintptr_t)src) & longmask))
-    goto do_bytes;
-#endif
-
-  ldst = (bufhelp_int_t *)(void *)dst;
-  lsrc = (const bufhelp_int_t *)(const void *)src;
-
-  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
-    (ldst++)->a ^= (lsrc++)->a;
-
-  dst = (byte *)ldst;
-  src = (const byte *)lsrc;
-
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-do_bytes:
-#endif
-  /* Handle tail.  */
-  for (; len; len--)
-    *dst++ ^= *src++;
-}
-
-
-/* Optimized function for buffer xoring with two destination buffers.  Used
-   mainly by CFB mode encryption.  */
-static inline void
-buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len)
-{
-  byte *dst1 = _dst1;
-  byte *dst2 = _dst2;
-  const byte *src = _src;
-  bufhelp_int_t *ldst1, *ldst2;
-  const bufhelp_int_t *lsrc;
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
-
-  /* Skip fast processing if buffers are unaligned.  */
-  if (UNLIKELY(((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask))
-    goto do_bytes;
-#endif
-
-  ldst1 = (bufhelp_int_t *)(void *)dst1;
-  ldst2 = (bufhelp_int_t *)(void *)dst2;
-  lsrc = (const bufhelp_int_t *)(const void *)src;
-
-  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
-    (ldst1++)->a = ((ldst2++)->a ^= (lsrc++)->a);
-
-  dst1 = (byte *)ldst1;
-  dst2 = (byte *)ldst2;
-  src = (const byte *)lsrc;
-
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-do_bytes:
-#endif
-  /* Handle tail.  */
-  for (; len; len--)
-    *dst1++ = (*dst2++ ^= *src++);
-}
-
-
-/* Optimized function for combined buffer xoring and copying.  Used by mainly
-   CBC mode decryption.  */
-static inline void
-buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy,
-                const void *_src_cpy, size_t len)
-{
-  byte *dst_xor = _dst_xor;
-  byte *srcdst_cpy = _srcdst_cpy;
-  const byte *src_xor = _src_xor;
-  const byte *src_cpy = _src_cpy;
-  byte temp;
-  bufhelp_int_t *ldst_xor, *lsrcdst_cpy;
-  const bufhelp_int_t *lsrc_cpy, *lsrc_xor;
-  uintptr_t ltemp;
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-  const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
-
-  /* Skip fast processing if buffers are unaligned.  */
-  if (UNLIKELY(((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor |
-       (uintptr_t)srcdst_cpy) & longmask))
-    goto do_bytes;
-#endif
-
-  ldst_xor = (bufhelp_int_t *)(void *)dst_xor;
-  lsrc_xor = (const bufhelp_int_t *)(void *)src_xor;
-  lsrcdst_cpy = (bufhelp_int_t *)(void *)srcdst_cpy;
-  lsrc_cpy = (const bufhelp_int_t *)(const void *)src_cpy;
-
-  for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
-    {
-      ltemp = (lsrc_cpy++)->a;
-      (ldst_xor++)->a = (lsrcdst_cpy)->a ^ (lsrc_xor++)->a;
-      (lsrcdst_cpy++)->a = ltemp;
-    }
-
-  dst_xor = (byte *)ldst_xor;
-  src_xor = (const byte *)lsrc_xor;
-  srcdst_cpy = (byte *)lsrcdst_cpy;
-  src_cpy = (const byte *)lsrc_cpy;
-
-#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
-do_bytes:
-#endif
-  /* Handle tail.  */
-  for (; len; len--)
-    {
-      temp = *src_cpy++;
-      *dst_xor++ = *srcdst_cpy ^ *src_xor++;
-      *srcdst_cpy++ = temp;
-    }
-}
-
-
-/* Optimized function for combined buffer xoring and copying.  Used by mainly
-   CFB mode decryption.  */
-static inline void
-buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len)
-{
-  buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len);
-}
-
-
-/* Constant-time compare of two buffers.  Returns 1 if buffers are equal,
-   and 0 if buffers differ.  */
-static inline int
-buf_eq_const(const void *_a, const void *_b, size_t len)
-{
-  const byte *a = _a;
-  const byte *b = _b;
-  int ab, ba;
-  size_t i;
-
-  /* Constant-time compare. */
-  for (i = 0, ab = 0, ba = 0; i < len; i++)
-    {
-      /* If a[i] != b[i], either ab or ba will be negative. */
-      ab |= a[i] - b[i];
-      ba |= b[i] - a[i];
-    }
-
-  /* 'ab | ba' is negative when buffers are not equal. */
-  return (ab | ba) >= 0;
-}
-
-
 #ifndef BUFHELP_UNALIGNED_ACCESS
 
 /* Functions for loading and storing unaligned u32 values of different
@@ -450,7 +179,207 @@ static inline void buf_put_le64(void *_buf, u64 val)
   out->a = le_bswap64(val);
 }
 
-
 #endif /*BUFHELP_UNALIGNED_ACCESS*/
 
+
+/* Host-endian get/put macros */
+#ifdef WORDS_BIGENDIAN
+# define buf_get_he32 buf_get_be32
+# define buf_put_he32 buf_put_be32
+# define buf_get_he64 buf_get_be64
+# define buf_put_he64 buf_put_be64
+#else
+# define buf_get_he32 buf_get_le32
+# define buf_put_he32 buf_put_le32
+# define buf_get_he64 buf_get_le64
+# define buf_put_he64 buf_put_le64
+#endif
+
+
+
+/* Optimized function for small buffer copying */
+static inline void
+buf_cpy(void *_dst, const void *_src, size_t len)
+{
+  byte *dst = _dst;
+  const byte *src = _src;
+
+#if __GNUC__ >= 4
+  if (!__builtin_constant_p (len))
+    {
+      if (UNLIKELY(len == 0))
+       return;
+      memcpy(_dst, _src, len);
+      return;
+    }
+#endif
+
+  while (len >= sizeof(u64))
+    {
+      buf_put_he64(dst, buf_get_he64(src));
+      dst += sizeof(u64);
+      src += sizeof(u64);
+      len -= sizeof(u64);
+    }
+
+  if (len >= sizeof(u32))
+    {
+      buf_put_he32(dst, buf_get_he32(src));
+      dst += sizeof(u32);
+      src += sizeof(u32);
+      len -= sizeof(u32);
+    }
+
+  /* Handle tail.  */
+  for (; len; len--)
+    *dst++ = *src++;
+}
+
+
+/* Optimized function for buffer xoring */
+static inline void
+buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
+{
+  byte *dst = _dst;
+  const byte *src1 = _src1;
+  const byte *src2 = _src2;
+
+  while (len >= sizeof(u64))
+    {
+      buf_put_he64(dst, buf_get_he64(src1) ^ buf_get_he64(src2));
+      dst += sizeof(u64);
+      src1 += sizeof(u64);
+      src2 += sizeof(u64);
+      len -= sizeof(u64);
+    }
+
+  if (len > sizeof(u32))
+    {
+      buf_put_he32(dst, buf_get_he32(src1) ^ buf_get_he32(src2));
+      dst += sizeof(u32);
+      src1 += sizeof(u32);
+      src2 += sizeof(u32);
+      len -= sizeof(u32);
+    }
+
+  /* Handle tail.  */
+  for (; len; len--)
+    *dst++ = *src1++ ^ *src2++;
+}
+
+
+/* Optimized function for buffer xoring with two destination buffers.  Used
+   mainly by CFB mode encryption.  */
+static inline void
+buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len)
+{
+  byte *dst1 = _dst1;
+  byte *dst2 = _dst2;
+  const byte *src = _src;
+
+  while (len >= sizeof(u64))
+    {
+      u64 temp = buf_get_he64(dst2) ^ buf_get_he64(src);
+      buf_put_he64(dst2, temp);
+      buf_put_he64(dst1, temp);
+      dst2 += sizeof(u64);
+      dst1 += sizeof(u64);
+      src += sizeof(u64);
+      len -= sizeof(u64);
+    }
+
+  if (len >= sizeof(u32))
+    {
+      u32 temp = buf_get_he32(dst2) ^ buf_get_he32(src);
+      buf_put_he32(dst2, temp);
+      buf_put_he32(dst1, temp);
+      dst2 += sizeof(u32);
+      dst1 += sizeof(u32);
+      src += sizeof(u32);
+      len -= sizeof(u32);
+    }
+
+  /* Handle tail.  */
+  for (; len; len--)
+    *dst1++ = (*dst2++ ^= *src++);
+}
+
+
+/* Optimized function for combined buffer xoring and copying.  Used by mainly
+   CBC mode decryption.  */
+static inline void
+buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy,
+                const void *_src_cpy, size_t len)
+{
+  byte *dst_xor = _dst_xor;
+  byte *srcdst_cpy = _srcdst_cpy;
+  const byte *src_xor = _src_xor;
+  const byte *src_cpy = _src_cpy;
+
+  while (len >= sizeof(u64))
+    {
+      u64 temp = buf_get_he64(src_cpy);
+      buf_put_he64(dst_xor, buf_get_he64(srcdst_cpy) ^ buf_get_he64(src_xor));
+      buf_put_he64(srcdst_cpy, temp);
+      dst_xor += sizeof(u64);
+      srcdst_cpy += sizeof(u64);
+      src_xor += sizeof(u64);
+      src_cpy += sizeof(u64);
+      len -= sizeof(u64);
+    }
+
+  if (len >= sizeof(u32))
+    {
+      u32 temp = buf_get_he32(src_cpy);
+      buf_put_he32(dst_xor, buf_get_he32(srcdst_cpy) ^ buf_get_he32(src_xor));
+      buf_put_he32(srcdst_cpy, temp);
+      dst_xor += sizeof(u32);
+      srcdst_cpy += sizeof(u32);
+      src_xor += sizeof(u32);
+      src_cpy += sizeof(u32);
+      len -= sizeof(u32);
+    }
+
+  /* Handle tail.  */
+  for (; len; len--)
+    {
+      byte temp = *src_cpy++;
+      *dst_xor++ = *srcdst_cpy ^ *src_xor++;
+      *srcdst_cpy++ = temp;
+    }
+}
+
+
+/* Optimized function for combined buffer xoring and copying.  Used by mainly
+   CFB mode decryption.  */
+static inline void
+buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len)
+{
+  buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len);
+}
+
+
+/* Constant-time compare of two buffers.  Returns 1 if buffers are equal,
+   and 0 if buffers differ.  */
+static inline int
+buf_eq_const(const void *_a, const void *_b, size_t len)
+{
+  const byte *a = _a;
+  const byte *b = _b;
+  int ab, ba;
+  size_t i;
+
+  /* Constant-time compare. */
+  for (i = 0, ab = 0, ba = 0; i < len; i++)
+    {
+      /* If a[i] != b[i], either ab or ba will be negative. */
+      ab |= a[i] - b[i];
+      ba |= b[i] - a[i];
+    }
+
+  /* 'ab | ba' is negative when buffers are not equal. */
+  return (ab | ba) >= 0;
+}
+
+
 #endif /*GCRYPT_BUFHELP_H*/
index 440f69f..30b568d 100644 (file)
@@ -19,7 +19,7 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "asm-common-aarch64.h"
 
 #if defined(__AARCH64EL__)
 #ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
@@ -33,7 +33,7 @@
 #define CTX x0
 #define RDST x1
 #define RSRC x2
-#define RKEYBITS x3
+#define RKEYBITS w3
 
 #define RTAB1 x4
 #define RTAB2 x5
 #define RT0 w15
 #define RT1 w16
 #define RT2 w17
-#define RT3 w18
+#define RT3 w19
 
 #define xRT0 x15
 #define xRT1 x16
 #define xRT2 x17
-#define xRT3 x18
+#define xRT3 x19
 
 #ifdef __AARCH64EL__
   #define host_to_be(reg, rtmp) \
        str_output_be(RDST, YL, YR, XL, XR, RT0, RT1);
 
 .globl _gcry_camellia_arm_encrypt_block
-.type   _gcry_camellia_arm_encrypt_block,@function;
+ELF(.type   _gcry_camellia_arm_encrypt_block,@function;)
 
 _gcry_camellia_arm_encrypt_block:
+       CFI_STARTPROC()
+       stp x19, x30, [sp, #-16]!
+       CFI_ADJUST_CFA_OFFSET(16)
+       CFI_REG_ON_STACK(19, 0)
+       CFI_REG_ON_STACK(30, 8)
+
        /* input:
         *      x0: keytable
         *      x1: dst
         *      x2: src
-        *      x3: keybitlen
+        *      w3: keybitlen
         */
 
        adr RTAB1,  _gcry_camellia_arm_tables;
@@ -227,7 +233,13 @@ _gcry_camellia_arm_encrypt_block:
 
        outunpack(24);
 
-       ret;
+       CFI_REMEMBER_STATE()
+       ldp x19, x30, [sp], #16
+       CFI_ADJUST_CFA_OFFSET(-16)
+       CFI_RESTORE(x19)
+       CFI_RESTORE(x30)
+       ret_spec_stop;
+       CFI_RESTORE_STATE()
 .ltorg
 
 .Lenc_256:
@@ -236,19 +248,30 @@ _gcry_camellia_arm_encrypt_block:
 
        outunpack(32);
 
-       ret;
+       ldp x19, x30, [sp], #16
+       CFI_ADJUST_CFA_OFFSET(-16)
+       CFI_RESTORE(x19)
+       CFI_RESTORE(x30)
+       ret_spec_stop;
+       CFI_ENDPROC()
 .ltorg
-.size _gcry_camellia_arm_encrypt_block,.-_gcry_camellia_arm_encrypt_block;
+ELF(.size _gcry_camellia_arm_encrypt_block,.-_gcry_camellia_arm_encrypt_block;)
 
 .globl _gcry_camellia_arm_decrypt_block
-.type   _gcry_camellia_arm_decrypt_block,@function;
+ELF(.type   _gcry_camellia_arm_decrypt_block,@function;)
 
 _gcry_camellia_arm_decrypt_block:
+       CFI_STARTPROC()
+       stp x19, x30, [sp, #-16]!
+       CFI_ADJUST_CFA_OFFSET(16)
+       CFI_REG_ON_STACK(19, 0)
+       CFI_REG_ON_STACK(30, 8)
+
        /* input:
         *      x0: keytable
         *      x1: dst
         *      x2: src
-        *      x3: keybitlen
+        *      w3: keybitlen
         */
 
        adr RTAB1,  _gcry_camellia_arm_tables;
@@ -271,7 +294,13 @@ _gcry_camellia_arm_decrypt_block:
 
        outunpack(0);
 
-       ret;
+       CFI_REMEMBER_STATE()
+       ldp x19, x30, [sp], #16
+       CFI_ADJUST_CFA_OFFSET(-16)
+       CFI_RESTORE(x19)
+       CFI_RESTORE(x30)
+       ret_spec_stop;
+       CFI_RESTORE_STATE()
 .ltorg
 
 .Ldec_256:
@@ -280,12 +309,12 @@ _gcry_camellia_arm_decrypt_block:
        dec_fls(24);
 
        b .Ldec_128;
+       CFI_ENDPROC()
 .ltorg
-.size _gcry_camellia_arm_decrypt_block,.-_gcry_camellia_arm_decrypt_block;
+ELF(.size _gcry_camellia_arm_decrypt_block,.-_gcry_camellia_arm_decrypt_block;)
 
 /* Encryption/Decryption tables */
-.globl _gcry_camellia_arm_tables
-.type  _gcry_camellia_arm_tables,@object;
+ELF(.type  _gcry_camellia_arm_tables,@object;)
 .balign 32
 _gcry_camellia_arm_tables:
 .Lcamellia_sp1110:
@@ -551,7 +580,7 @@ _gcry_camellia_arm_tables:
 .long 0xc7c7c700, 0x008f8f8f, 0xe300e3e3, 0xf4f400f4
 .long 0x80808000, 0x00010101, 0x40004040, 0xc7c700c7
 .long 0x9e9e9e00, 0x003d3d3d, 0x4f004f4f, 0x9e9e009e
-.size _gcry_camellia_arm_tables,.-_gcry_camellia_arm_tables;
+ELF(.size _gcry_camellia_arm_tables,.-_gcry_camellia_arm_tables;)
 
 #endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
 #endif /*__AARCH64EL__*/
index 8022934..5c304e5 100644 (file)
@@ -1,6 +1,6 @@
 /* camellia-avx-aesni-amd64.S  -  AES-NI/AVX implementation of Camellia cipher
  *
- * Copyright (C) 2013-2015 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2013-2015,2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifdef __x86_64
 #include <config.h>
+
+#ifdef __x86_64
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
     defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)
 
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 #define CAMELLIA_TABLE_BYTE_LEN 272
 
@@ -44,7 +35,6 @@
 
 /* register macros */
 #define CTX %rdi
-#define RIO %r8
 
 /**********************************************************************
   helper macros
        /* \
         * S-function with AES subbytes \
         */ \
-       vmovdqa .Linv_shift_row RIP, t4; \
-       vbroadcastss .L0f0f0f0f RIP, t7; \
-       vmovdqa .Lpre_tf_lo_s1 RIP, t0; \
-       vmovdqa .Lpre_tf_hi_s1 RIP, t1; \
+       vmovdqa .Linv_shift_row rRIP, t4; \
+       vbroadcastss .L0f0f0f0f rRIP, t7; \
+       vmovdqa .Lpre_tf_lo_s1 rRIP, t0; \
+       vmovdqa .Lpre_tf_hi_s1 rRIP, t1; \
        \
        /* AES inverse shift rows */ \
        vpshufb t4, x0, x0; \
@@ -91,8 +81,8 @@
        vpshufb t4, x6, x6; \
        \
        /* prefilter sboxes 1, 2 and 3 */ \
-       vmovdqa .Lpre_tf_lo_s4 RIP, t2; \
-       vmovdqa .Lpre_tf_hi_s4 RIP, t3; \
+       vmovdqa .Lpre_tf_lo_s4 rRIP, t2; \
+       vmovdqa .Lpre_tf_hi_s4 rRIP, t3; \
        filter_8bit(x0, t0, t1, t7, t6); \
        filter_8bit(x7, t0, t1, t7, t6); \
        filter_8bit(x1, t0, t1, t7, t6); \
        filter_8bit(x6, t2, t3, t7, t6); \
        \
        /* AES subbytes + AES shift rows */ \
-       vmovdqa .Lpost_tf_lo_s1 RIP, t0; \
-       vmovdqa .Lpost_tf_hi_s1 RIP, t1; \
+       vmovdqa .Lpost_tf_lo_s1 rRIP, t0; \
+       vmovdqa .Lpost_tf_hi_s1 rRIP, t1; \
        vaesenclast t4, x0, x0; \
        vaesenclast t4, x7, x7; \
        vaesenclast t4, x1, x1; \
        vaesenclast t4, x6, x6; \
        \
        /* postfilter sboxes 1 and 4 */ \
-       vmovdqa .Lpost_tf_lo_s3 RIP, t2; \
-       vmovdqa .Lpost_tf_hi_s3 RIP, t3; \
+       vmovdqa .Lpost_tf_lo_s3 rRIP, t2; \
+       vmovdqa .Lpost_tf_hi_s3 rRIP, t3; \
        filter_8bit(x0, t0, t1, t7, t6); \
        filter_8bit(x7, t0, t1, t7, t6); \
        filter_8bit(x3, t0, t1, t7, t6); \
        filter_8bit(x6, t0, t1, t7, t6); \
        \
        /* postfilter sbox 3 */ \
-       vmovdqa .Lpost_tf_lo_s2 RIP, t4; \
-       vmovdqa .Lpost_tf_hi_s2 RIP, t5; \
+       vmovdqa .Lpost_tf_lo_s2 rRIP, t4; \
+       vmovdqa .Lpost_tf_hi_s2 rRIP, t5; \
        filter_8bit(x2, t2, t3, t7, t6); \
        filter_8bit(x5, t2, t3, t7, t6); \
        \
        transpose_4x4(c0, c1, c2, c3, a0, a1); \
        transpose_4x4(d0, d1, d2, d3, a0, a1); \
        \
-       vmovdqu .Lshufb_16x16b RIP, a0; \
+       vmovdqu .Lshufb_16x16b rRIP, a0; \
        vmovdqu st1, a1; \
        vpshufb a0, a2, a2; \
        vpshufb a0, a3, a3; \
        vpunpcklwd t1, t3, e; \
        vpunpckhwd t1, t3, f; \
        \
-       vmovdqa .Ltranspose_8x8_shuf RIP, t3; \
+       vmovdqa .Ltranspose_8x8_shuf rRIP, t3; \
        \
        vpunpcklwd g, c, d; \
        vpunpckhwd g, c, c; \
 #define inpack16_pre(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
                     y6, y7, rio, key) \
        vmovq key, x0; \
-       vpshufb .Lpack_bswap RIP, x0, x0; \
+       vpshufb .Lpack_bswap rRIP, x0, x0; \
        \
        vpxor 0 * 16(rio), x0, y7; \
        vpxor 1 * 16(rio), x0, y6; \
        vmovdqu x0, stack_tmp0; \
        \
        vmovq key, x0; \
-       vpshufb .Lpack_bswap RIP, x0, x0; \
+       vpshufb .Lpack_bswap rRIP, x0, x0; \
        \
        vpxor x0, y7, y7; \
        vpxor x0, y6, y6; \
@@ -781,50 +771,42 @@ __camellia_enc_blk16:
        /* input:
         *      %rdi: ctx, CTX
         *      %rax: temporary storage, 256 bytes
+        *      %r8d: 24 for 16 byte key, 32 for larger
         *      %xmm0..%xmm15: 16 plaintext blocks
         * output:
         *      %xmm0..%xmm15: 16 encrypted blocks, order swapped:
         *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
         */
+       CFI_STARTPROC();
 
        leaq 8 * 16(%rax), %rcx;
 
+       leaq (-8 * 8)(CTX, %r8, 8), %r8;
+
        inpack16_post(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
                      %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
                      %xmm15, %rax, %rcx);
 
+.align 8
+.Lenc_loop:
        enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
                     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
                     %xmm15, %rax, %rcx, 0);
 
-       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-             %xmm15,
-             ((key_table + (8) * 8) + 0)(CTX),
-             ((key_table + (8) * 8) + 4)(CTX),
-             ((key_table + (8) * 8) + 8)(CTX),
-             ((key_table + (8) * 8) + 12)(CTX));
-
-       enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-                    %xmm15, %rax, %rcx, 8);
+       cmpq %r8, CTX;
+       je .Lenc_done;
+       leaq (8 * 8)(CTX), CTX;
 
        fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
              %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
              %xmm15,
-             ((key_table + (16) * 8) + 0)(CTX),
-             ((key_table + (16) * 8) + 4)(CTX),
-             ((key_table + (16) * 8) + 8)(CTX),
-             ((key_table + (16) * 8) + 12)(CTX));
-
-       enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-                    %xmm15, %rax, %rcx, 16);
-
-       movl $24, %r8d;
-       cmpl $128, key_bitlength(CTX);
-       jne .Lenc_max32;
+             ((key_table) + 0)(CTX),
+             ((key_table) + 4)(CTX),
+             ((key_table) + 8)(CTX),
+             ((key_table) + 12)(CTX));
+       jmp .Lenc_loop;
 
+.align 8
 .Lenc_done:
        /* load CD for output */
        vmovdqu 0 * 16(%rcx), %xmm8;
@@ -838,27 +820,10 @@ __camellia_enc_blk16:
 
        outunpack16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-                   %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax));
-
-       ret;
-
-.align 8
-.Lenc_max32:
-       movl $32, %r8d;
-
-       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-             %xmm15,
-             ((key_table + (24) * 8) + 0)(CTX),
-             ((key_table + (24) * 8) + 4)(CTX),
-             ((key_table + (24) * 8) + 8)(CTX),
-             ((key_table + (24) * 8) + 12)(CTX));
+                   %xmm15, ((key_table) + 8 * 8)(%r8), (%rax), 1 * 16(%rax));
 
-       enc_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-                    %xmm15, %rax, %rcx, 24);
-
-       jmp .Lenc_done;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __camellia_enc_blk16,.-__camellia_enc_blk16;)
 
 .align 8
@@ -874,6 +839,11 @@ __camellia_dec_blk16:
         *      %xmm0..%xmm15: 16 plaintext blocks, order swapped:
         *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
         */
+       CFI_STARTPROC();
+
+       movq %r8, %rcx;
+       movq CTX, %r8
+       leaq (-8 * 8)(CTX, %rcx, 8), CTX;
 
        leaq 8 * 16(%rax), %rcx;
 
@@ -881,38 +851,28 @@ __camellia_dec_blk16:
                      %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
                      %xmm15, %rax, %rcx);
 
-       cmpl $32, %r8d;
-       je .Ldec_max32;
-
-.Ldec_max24:
+.align 8
+.Ldec_loop:
        dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
                     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-                    %xmm15, %rax, %rcx, 16);
-
-       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-             %xmm15,
-             ((key_table + (16) * 8) + 8)(CTX),
-             ((key_table + (16) * 8) + 12)(CTX),
-             ((key_table + (16) * 8) + 0)(CTX),
-             ((key_table + (16) * 8) + 4)(CTX));
+                    %xmm15, %rax, %rcx, 0);
 
-       dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-                    %xmm15, %rax, %rcx, 8);
+       cmpq %r8, CTX;
+       je .Ldec_done;
 
        fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
              %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
              %xmm15,
-             ((key_table + (8) * 8) + 8)(CTX),
-             ((key_table + (8) * 8) + 12)(CTX),
-             ((key_table + (8) * 8) + 0)(CTX),
-             ((key_table + (8) * 8) + 4)(CTX));
+             ((key_table) + 8)(CTX),
+             ((key_table) + 12)(CTX),
+             ((key_table) + 0)(CTX),
+             ((key_table) + 4)(CTX));
 
-       dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-                    %xmm15, %rax, %rcx, 0);
+       leaq (-8 * 8)(CTX), CTX;
+       jmp .Ldec_loop;
 
+.align 8
+.Ldec_done:
        /* load CD for output */
        vmovdqu 0 * 16(%rcx), %xmm8;
        vmovdqu 1 * 16(%rcx), %xmm9;
@@ -927,23 +887,8 @@ __camellia_dec_blk16:
                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
                    %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax));
 
-       ret;
-
-.align 8
-.Ldec_max32:
-       dec_rounds16(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-                    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-                    %xmm15, %rax, %rcx, 24);
-
-       fls16(%rax, %xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
-             %rcx, %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
-             %xmm15,
-             ((key_table + (24) * 8) + 8)(CTX),
-             ((key_table + (24) * 8) + 12)(CTX),
-             ((key_table + (24) * 8) + 0)(CTX),
-             ((key_table + (24) * 8) + 4)(CTX));
-
-       jmp .Ldec_max24;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __camellia_dec_blk16,.-__camellia_dec_blk16;)
 
 #define inc_le128(x, minus_one, tmp) \
@@ -963,17 +908,25 @@ _gcry_camellia_aesni_avx_ctr_enc:
         *      %rdx: src (16 blocks)
         *      %rcx: iv (big endian, 128bit)
         */
+       CFI_STARTPROC();
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
 
        vzeroupper;
 
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %eax;
+       cmovel %eax, %r8d; /* max */
+
        subq $(16 * 16), %rsp;
        andq $~31, %rsp;
        movq %rsp, %rax;
 
-       vmovdqa .Lbswap128_mask RIP, %xmm14;
+       vmovdqa .Lbswap128_mask rRIP, %xmm14;
 
        /* load IV and byteswap */
        vmovdqu (%rcx), %xmm15;
@@ -1018,12 +971,12 @@ _gcry_camellia_aesni_avx_ctr_enc:
        vmovdqa %xmm0, %xmm13;
        vpshufb %xmm14, %xmm0, %xmm0;
        inc_le128(%xmm13, %xmm15, %xmm14);
-       vpshufb .Lbswap128_mask RIP, %xmm13, %xmm13; /* le => be */
+       vpshufb .Lbswap128_mask rRIP, %xmm13, %xmm13; /* le => be */
        vmovdqu %xmm13, (%rcx);
 
        /* inpack16_pre: */
        vmovq (key_table)(CTX), %xmm15;
-       vpshufb .Lpack_bswap RIP, %xmm15, %xmm15;
+       vpshufb .Lpack_bswap rRIP, %xmm15, %xmm15;
        vpxor %xmm0, %xmm15, %xmm0;
        vpxor %xmm1, %xmm15, %xmm1;
        vpxor %xmm2, %xmm15, %xmm2;
@@ -1067,7 +1020,9 @@ _gcry_camellia_aesni_avx_ctr_enc:
        vzeroall;
 
        leave;
-       ret;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_camellia_aesni_avx_ctr_enc,.-_gcry_camellia_aesni_avx_ctr_enc;)
 
 .align 8
@@ -1081,9 +1036,12 @@ _gcry_camellia_aesni_avx_cbc_dec:
         *      %rdx: src (16 blocks)
         *      %rcx: iv
         */
+       CFI_STARTPROC();
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
 
        vzeroupper;
 
@@ -1135,7 +1093,9 @@ _gcry_camellia_aesni_avx_cbc_dec:
        vzeroall;
 
        leave;
-       ret;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_camellia_aesni_avx_cbc_dec,.-_gcry_camellia_aesni_avx_cbc_dec;)
 
 .align 8
@@ -1149,19 +1109,27 @@ _gcry_camellia_aesni_avx_cfb_dec:
         *      %rdx: src (16 blocks)
         *      %rcx: iv
         */
+       CFI_STARTPROC();
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
 
        vzeroupper;
 
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %eax;
+       cmovel %eax, %r8d; /* max */
+
        subq $(16 * 16), %rsp;
        andq $~31, %rsp;
        movq %rsp, %rax;
 
        /* inpack16_pre: */
        vmovq (key_table)(CTX), %xmm0;
-       vpshufb .Lpack_bswap RIP, %xmm0, %xmm0;
+       vpshufb .Lpack_bswap rRIP, %xmm0, %xmm0;
        vpxor (%rcx), %xmm0, %xmm15;
        vmovdqu 15 * 16(%rdx), %xmm1;
        vmovdqu %xmm1, (%rcx); /* store new IV */
@@ -1207,7 +1175,9 @@ _gcry_camellia_aesni_avx_cfb_dec:
        vzeroall;
 
        leave;
-       ret;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_camellia_aesni_avx_cfb_dec,.-_gcry_camellia_aesni_avx_cfb_dec;)
 
 .align 8
@@ -1223,9 +1193,12 @@ _gcry_camellia_aesni_avx_ocb_enc:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
 
        vzeroupper;
 
@@ -1233,10 +1206,14 @@ _gcry_camellia_aesni_avx_ocb_enc:
        andq $~31, %rsp;
        movq %rsp, %rax;
 
-       movq %r10, (16 * 16 + 0 * 8)(%rax);
-       movq %r11, (16 * 16 + 1 * 8)(%rax);
-       movq %r12, (16 * 16 + 2 * 8)(%rax);
-       movq %r13, (16 * 16 + 3 * 8)(%rax);
+       movq %r10, (16 * 16 + 0 * 8)(%rsp);
+       movq %r11, (16 * 16 + 1 * 8)(%rsp);
+       movq %r12, (16 * 16 + 2 * 8)(%rsp);
+       movq %r13, (16 * 16 + 3 * 8)(%rsp);
+       CFI_REG_ON_STACK(r10, 16 * 16 + 0 * 8);
+       CFI_REG_ON_STACK(r11, 16 * 16 + 1 * 8);
+       CFI_REG_ON_STACK(r12, 16 * 16 + 2 * 8);
+       CFI_REG_ON_STACK(r13, 16 * 16 + 3 * 8);
 
        vmovdqu (%rcx), %xmm14;
        vmovdqu (%r8), %xmm15;
@@ -1290,9 +1267,14 @@ _gcry_camellia_aesni_avx_ocb_enc:
        vmovdqu %xmm14, (%rcx);
        vmovdqu %xmm15, (%r8);
 
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %r10d;
+       cmovel %r10d, %r8d; /* max */
+
        /* inpack16_pre: */
        vmovq (key_table)(CTX), %xmm15;
-       vpshufb .Lpack_bswap RIP, %xmm15, %xmm15;
+       vpshufb .Lpack_bswap rRIP, %xmm15, %xmm15;
        vpxor %xmm0, %xmm15, %xmm0;
        vpxor %xmm1, %xmm15, %xmm1;
        vpxor %xmm2, %xmm15, %xmm2;
@@ -1335,13 +1317,19 @@ _gcry_camellia_aesni_avx_ocb_enc:
 
        vzeroall;
 
-       movq (16 * 16 + 0 * 8)(%rax), %r10;
-       movq (16 * 16 + 1 * 8)(%rax), %r11;
-       movq (16 * 16 + 2 * 8)(%rax), %r12;
-       movq (16 * 16 + 3 * 8)(%rax), %r13;
+       movq (16 * 16 + 0 * 8)(%rsp), %r10;
+       movq (16 * 16 + 1 * 8)(%rsp), %r11;
+       movq (16 * 16 + 2 * 8)(%rsp), %r12;
+       movq (16 * 16 + 3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        leave;
-       ret;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_camellia_aesni_avx_ocb_enc,.-_gcry_camellia_aesni_avx_ocb_enc;)
 
 .align 8
@@ -1357,9 +1345,12 @@ _gcry_camellia_aesni_avx_ocb_dec:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
 
        vzeroupper;
 
@@ -1367,10 +1358,14 @@ _gcry_camellia_aesni_avx_ocb_dec:
        andq $~31, %rsp;
        movq %rsp, %rax;
 
-       movq %r10, (16 * 16 + 0 * 8)(%rax);
-       movq %r11, (16 * 16 + 1 * 8)(%rax);
-       movq %r12, (16 * 16 + 2 * 8)(%rax);
-       movq %r13, (16 * 16 + 3 * 8)(%rax);
+       movq %r10, (16 * 16 + 0 * 8)(%rsp);
+       movq %r11, (16 * 16 + 1 * 8)(%rsp);
+       movq %r12, (16 * 16 + 2 * 8)(%rsp);
+       movq %r13, (16 * 16 + 3 * 8)(%rsp);
+       CFI_REG_ON_STACK(r10, 16 * 16 + 0 * 8);
+       CFI_REG_ON_STACK(r11, 16 * 16 + 1 * 8);
+       CFI_REG_ON_STACK(r12, 16 * 16 + 2 * 8);
+       CFI_REG_ON_STACK(r13, 16 * 16 + 3 * 8);
 
        vmovdqu (%rcx), %xmm15;
 
@@ -1428,7 +1423,7 @@ _gcry_camellia_aesni_avx_ocb_dec:
 
        /* inpack16_pre: */
        vmovq (key_table)(CTX, %r8, 8), %xmm15;
-       vpshufb .Lpack_bswap RIP, %xmm15, %xmm15;
+       vpshufb .Lpack_bswap rRIP, %xmm15, %xmm15;
        vpxor %xmm0, %xmm15, %xmm0;
        vpxor %xmm1, %xmm15, %xmm1;
        vpxor %xmm2, %xmm15, %xmm2;
@@ -1493,13 +1488,19 @@ _gcry_camellia_aesni_avx_ocb_dec:
 
        vzeroall;
 
-       movq (16 * 16 + 0 * 8)(%rax), %r10;
-       movq (16 * 16 + 1 * 8)(%rax), %r11;
-       movq (16 * 16 + 2 * 8)(%rax), %r12;
-       movq (16 * 16 + 3 * 8)(%rax), %r13;
+       movq (16 * 16 + 0 * 8)(%rsp), %r10;
+       movq (16 * 16 + 1 * 8)(%rsp), %r11;
+       movq (16 * 16 + 2 * 8)(%rsp), %r12;
+       movq (16 * 16 + 3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        leave;
-       ret;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_camellia_aesni_avx_ocb_dec,.-_gcry_camellia_aesni_avx_ocb_dec;)
 
 .align 8
@@ -1514,9 +1515,12 @@ _gcry_camellia_aesni_avx_ocb_auth:
         *      %rcx: checksum
         *      %r8 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
 
        vzeroupper;
 
@@ -1524,10 +1528,14 @@ _gcry_camellia_aesni_avx_ocb_auth:
        andq $~31, %rsp;
        movq %rsp, %rax;
 
-       movq %r10, (16 * 16 + 0 * 8)(%rax);
-       movq %r11, (16 * 16 + 1 * 8)(%rax);
-       movq %r12, (16 * 16 + 2 * 8)(%rax);
-       movq %r13, (16 * 16 + 3 * 8)(%rax);
+       movq %r10, (16 * 16 + 0 * 8)(%rsp);
+       movq %r11, (16 * 16 + 1 * 8)(%rsp);
+       movq %r12, (16 * 16 + 2 * 8)(%rsp);
+       movq %r13, (16 * 16 + 3 * 8)(%rsp);
+       CFI_REG_ON_STACK(r10, 16 * 16 + 0 * 8);
+       CFI_REG_ON_STACK(r11, 16 * 16 + 1 * 8);
+       CFI_REG_ON_STACK(r12, 16 * 16 + 2 * 8);
+       CFI_REG_ON_STACK(r13, 16 * 16 + 3 * 8);
 
        vmovdqu (%rdx), %xmm15;
 
@@ -1574,13 +1582,18 @@ _gcry_camellia_aesni_avx_ocb_auth:
        OCB_INPUT(15, %r13, %xmm0);
 #undef OCB_INPUT
 
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %r10d;
+       cmovel %r10d, %r8d; /* max */
+
        vmovdqu %xmm15, (%rdx);
 
        movq %rcx, %r10;
 
        /* inpack16_pre: */
        vmovq (key_table)(CTX), %xmm15;
-       vpshufb .Lpack_bswap RIP, %xmm15, %xmm15;
+       vpshufb .Lpack_bswap rRIP, %xmm15, %xmm15;
        vpxor %xmm0, %xmm15, %xmm0;
        vpxor %xmm1, %xmm15, %xmm1;
        vpxor %xmm2, %xmm15, %xmm2;
@@ -1623,13 +1636,19 @@ _gcry_camellia_aesni_avx_ocb_auth:
 
        vzeroall;
 
-       movq (16 * 16 + 0 * 8)(%rax), %r10;
-       movq (16 * 16 + 1 * 8)(%rax), %r11;
-       movq (16 * 16 + 2 * 8)(%rax), %r12;
-       movq (16 * 16 + 3 * 8)(%rax), %r13;
+       movq (16 * 16 + 0 * 8)(%rsp), %r10;
+       movq (16 * 16 + 1 * 8)(%rsp), %r11;
+       movq (16 * 16 + 2 * 8)(%rsp), %r12;
+       movq (16 * 16 + 3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        leave;
-       ret;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_camellia_aesni_avx_ocb_auth,.-_gcry_camellia_aesni_avx_ocb_auth;)
 
 /*
@@ -1657,8 +1676,8 @@ ELF(.size _gcry_camellia_aesni_avx_ocb_auth,.-_gcry_camellia_aesni_avx_ocb_auth;
        vpand sbox4mask, t0, t0; \
        vpor t0, x, x; \
        \
-       vmovdqa .Lpost_tf_lo_s1 RIP, t0; \
-       vmovdqa .Lpost_tf_hi_s1 RIP, t1; \
+       vmovdqa .Lpost_tf_lo_s1 rRIP, t0; \
+       vmovdqa .Lpost_tf_hi_s1 rRIP, t1; \
        \
        /* prefilter sboxes */ \
        filter_8bit(x, pre_s1lo_mask, pre_s1hi_mask, _0f0f0f0fmask, t2); \
@@ -1672,18 +1691,18 @@ ELF(.size _gcry_camellia_aesni_avx_ocb_auth,.-_gcry_camellia_aesni_avx_ocb_auth;
        /* output rotation for sbox2 (<<< 1) */ \
        /* output rotation for sbox3 (>>> 1) */ \
        vpshufb inv_shift_row, x, t1; \
-       vpshufb .Lsp0044440444044404mask RIP, x, t4; \
-       vpshufb .Lsp1110111010011110mask RIP, x, x; \
+       vpshufb .Lsp0044440444044404mask rRIP, x, t4; \
+       vpshufb .Lsp1110111010011110mask rRIP, x, x; \
        vpaddb t1, t1, t2; \
        vpsrlw $7, t1, t0; \
        vpsllw $7, t1, t3; \
        vpor t0, t2, t0; \
        vpsrlw $1, t1, t1; \
-       vpshufb .Lsp0222022222000222mask RIP, t0, t0; \
+       vpshufb .Lsp0222022222000222mask rRIP, t0, t0; \
        vpor t1, t3, t1; \
        \
        vpxor x, t4, t4; \
-       vpshufb .Lsp3033303303303033mask RIP, t1, t1; \
+       vpshufb .Lsp3033303303303033mask rRIP, t1, t1; \
        vpxor t4, t0, t0; \
        vpxor t1, t0, t0; \
        vpsrldq $8, t0, x; \
@@ -1741,17 +1760,19 @@ __camellia_avx_setup128:
         *      %rdi: ctx, CTX; subkey storage at key_table(CTX)
         *      %xmm0: key
         */
+       CFI_STARTPROC();
+
 #define cmll_sub(n, ctx) (key_table+((n)*8))(ctx)
 #define KL128 %xmm0
 #define KA128 %xmm2
 
-       vpshufb .Lbswap128_mask RIP, KL128, KL128;
+       vpshufb .Lbswap128_mask rRIP, KL128, KL128;
 
-       vmovdqa .Linv_shift_row_and_unpcklbw RIP, %xmm11;
-       vmovq .Lsbox4_input_mask RIP, %xmm12;
-       vbroadcastss .L0f0f0f0f RIP, %xmm13;
-       vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14;
-       vmovdqa .Lpre_tf_hi_s1 RIP, %xmm15;
+       vmovdqa .Linv_shift_row_and_unpcklbw rRIP, %xmm11;
+       vmovq .Lsbox4_input_mask rRIP, %xmm12;
+       vbroadcastss .L0f0f0f0f rRIP, %xmm13;
+       vmovdqa .Lpre_tf_lo_s1 rRIP, %xmm14;
+       vmovdqa .Lpre_tf_hi_s1 rRIP, %xmm15;
 
        /*
         * Generate KA
@@ -1763,18 +1784,18 @@ __camellia_avx_setup128:
 
        camellia_f(%xmm2, %xmm4, %xmm1,
                   %xmm5, %xmm6, %xmm7, %xmm8,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma1 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma1 rRIP);
        vpxor %xmm4, %xmm3, %xmm3;
        camellia_f(%xmm3, %xmm2, %xmm1,
                   %xmm5, %xmm6, %xmm7, %xmm8,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma2 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma2 rRIP);
        camellia_f(%xmm2, %xmm3, %xmm1,
                   %xmm5, %xmm6, %xmm7, %xmm8,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma3 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma3 rRIP);
        vpxor %xmm4, %xmm3, %xmm3;
        camellia_f(%xmm3, %xmm4, %xmm1,
                   %xmm5, %xmm6, %xmm7, %xmm8,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma4 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma4 rRIP);
 
        vpslldq $8, %xmm3, %xmm3;
        vpxor %xmm4, %xmm2, %xmm2;
@@ -2075,7 +2096,8 @@ __camellia_avx_setup128:
 
        vzeroall;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __camellia_avx_setup128,.-__camellia_avx_setup128;)
 
 .align 8
@@ -2086,19 +2108,21 @@ __camellia_avx_setup256:
         *      %rdi: ctx, CTX; subkey storage at key_table(CTX)
         *      %xmm0 & %xmm1: key
         */
+       CFI_STARTPROC();
+
 #define KL128 %xmm0
 #define KR128 %xmm1
 #define KA128 %xmm2
 #define KB128 %xmm3
 
-       vpshufb .Lbswap128_mask RIP, KL128, KL128;
-       vpshufb .Lbswap128_mask RIP, KR128, KR128;
+       vpshufb .Lbswap128_mask rRIP, KL128, KL128;
+       vpshufb .Lbswap128_mask rRIP, KR128, KR128;
 
-       vmovdqa .Linv_shift_row_and_unpcklbw RIP, %xmm11;
-       vmovq .Lsbox4_input_mask RIP, %xmm12;
-       vbroadcastss .L0f0f0f0f RIP, %xmm13;
-       vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14;
-       vmovdqa .Lpre_tf_hi_s1 RIP, %xmm15;
+       vmovdqa .Linv_shift_row_and_unpcklbw rRIP, %xmm11;
+       vmovq .Lsbox4_input_mask rRIP, %xmm12;
+       vbroadcastss .L0f0f0f0f rRIP, %xmm13;
+       vmovdqa .Lpre_tf_lo_s1 rRIP, %xmm14;
+       vmovdqa .Lpre_tf_hi_s1 rRIP, %xmm15;
 
        /*
         * Generate KA
@@ -2111,20 +2135,20 @@ __camellia_avx_setup256:
 
        camellia_f(%xmm2, %xmm4, %xmm5,
                   %xmm7, %xmm8, %xmm9, %xmm10,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma1 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma1 rRIP);
        vpxor %xmm4, %xmm3, %xmm3;
        camellia_f(%xmm3, %xmm2, %xmm5,
                   %xmm7, %xmm8, %xmm9, %xmm10,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma2 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma2 rRIP);
        vpxor %xmm6, %xmm2, %xmm2;
        camellia_f(%xmm2, %xmm3, %xmm5,
                   %xmm7, %xmm8, %xmm9, %xmm10,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma3 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma3 rRIP);
        vpxor %xmm4, %xmm3, %xmm3;
        vpxor KR128, %xmm3, %xmm3;
        camellia_f(%xmm3, %xmm4, %xmm5,
                   %xmm7, %xmm8, %xmm9, %xmm10,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma4 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma4 rRIP);
 
        vpslldq $8, %xmm3, %xmm3;
        vpxor %xmm4, %xmm2, %xmm2;
@@ -2142,12 +2166,12 @@ __camellia_avx_setup256:
 
        camellia_f(%xmm4, %xmm5, %xmm6,
                   %xmm7, %xmm8, %xmm9, %xmm10,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma5 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma5 rRIP);
        vpxor %xmm5, %xmm3, %xmm3;
 
        camellia_f(%xmm3, %xmm5, %xmm6,
                   %xmm7, %xmm8, %xmm9, %xmm10,
-                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma6 RIP);
+                  %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma6 rRIP);
        vpslldq $8, %xmm3, %xmm3;
        vpxor %xmm5, %xmm4, %xmm4;
        vpsrldq $8, %xmm3, %xmm3;
@@ -2552,7 +2576,8 @@ __camellia_avx_setup256:
 
        vzeroall;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __camellia_avx_setup256,.-__camellia_avx_setup256;)
 
 .align 8
@@ -2565,6 +2590,7 @@ _gcry_camellia_aesni_avx_keygen:
         *      %rsi: key
         *      %rdx: keylen
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
@@ -2585,6 +2611,7 @@ _gcry_camellia_aesni_avx_keygen:
        vpor %xmm2, %xmm1, %xmm1;
 
        jmp __camellia_avx_setup256;
+       CFI_ENDPROC();
 ELF(.size _gcry_camellia_aesni_avx_keygen,.-_gcry_camellia_aesni_avx_keygen;)
 
 #endif /*defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)*/
index 897e4ae..5102d19 100644 (file)
@@ -1,6 +1,6 @@
-/* camellia-avx2-aesni-amd64.S  -  AES-NI/AVX2 implementation of Camellia cipher
+/* camellia-aesni-avx2-amd64.S  -  AES-NI/AVX2 implementation of Camellia cipher
  *
- * Copyright (C) 2013-2015 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifdef __x86_64
 #include <config.h>
+
+#ifdef __x86_64
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
     defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT)
 
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-#define CAMELLIA_TABLE_BYTE_LEN 272
-
-/* struct CAMELLIA_context: */
-#define key_table 0
-#define key_bitlength CAMELLIA_TABLE_BYTE_LEN
-
-/* register macros */
-#define CTX %rdi
-#define RIO %r8
-
-/**********************************************************************
-  helper macros
- **********************************************************************/
-#define filter_8bit(x, lo_t, hi_t, mask4bit, tmp0) \
-       vpand x, mask4bit, tmp0; \
-       vpandn x, mask4bit, x; \
-       vpsrld $4, x, x; \
-       \
-       vpshufb tmp0, lo_t, tmp0; \
-       vpshufb x, hi_t, x; \
-       vpxor tmp0, x, x;
-
-#define ymm0_x xmm0
-#define ymm1_x xmm1
-#define ymm2_x xmm2
-#define ymm3_x xmm3
-#define ymm4_x xmm4
-#define ymm5_x xmm5
-#define ymm6_x xmm6
-#define ymm7_x xmm7
-#define ymm8_x xmm8
-#define ymm9_x xmm9
-#define ymm10_x xmm10
-#define ymm11_x xmm11
-#define ymm12_x xmm12
-#define ymm13_x xmm13
-#define ymm14_x xmm14
-#define ymm15_x xmm15
-
-/**********************************************************************
-  32-way camellia
- **********************************************************************/
-
-/*
- * IN:
- *   x0..x7: byte-sliced AB state
- *   mem_cd: register pointer storing CD state
- *   key: index for key material
- * OUT:
- *   x0..x7: new byte-sliced CD state
- */
-#define roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, t0, t1, t2, t3, t4, t5, t6, \
-                 t7, mem_cd, key) \
-       /* \
-        * S-function with AES subbytes \
-        */ \
-       vbroadcasti128 .Linv_shift_row RIP, t4; \
-       vpbroadcastd .L0f0f0f0f RIP, t7; \
-       vbroadcasti128 .Lpre_tf_lo_s1 RIP, t5; \
-       vbroadcasti128 .Lpre_tf_hi_s1 RIP, t6; \
-       vbroadcasti128 .Lpre_tf_lo_s4 RIP, t2; \
-       vbroadcasti128 .Lpre_tf_hi_s4 RIP, t3; \
-       \
-       /* AES inverse shift rows */ \
-       vpshufb t4, x0, x0; \
-       vpshufb t4, x7, x7; \
-       vpshufb t4, x3, x3; \
-       vpshufb t4, x6, x6; \
-       vpshufb t4, x2, x2; \
-       vpshufb t4, x5, x5; \
-       vpshufb t4, x1, x1; \
-       vpshufb t4, x4, x4; \
-       \
-       /* prefilter sboxes 1, 2 and 3 */ \
-       /* prefilter sbox 4 */ \
-       filter_8bit(x0, t5, t6, t7, t4); \
-       filter_8bit(x7, t5, t6, t7, t4); \
-       vextracti128 $1, x0, t0##_x; \
-       vextracti128 $1, x7, t1##_x; \
-       filter_8bit(x3, t2, t3, t7, t4); \
-       filter_8bit(x6, t2, t3, t7, t4); \
-       vextracti128 $1, x3, t3##_x; \
-       vextracti128 $1, x6, t2##_x; \
-       filter_8bit(x2, t5, t6, t7, t4); \
-       filter_8bit(x5, t5, t6, t7, t4); \
-       filter_8bit(x1, t5, t6, t7, t4); \
-       filter_8bit(x4, t5, t6, t7, t4); \
-       \
-       vpxor t4##_x, t4##_x, t4##_x; \
-       \
-       /* AES subbytes + AES shift rows */ \
-       vextracti128 $1, x2, t6##_x; \
-       vextracti128 $1, x5, t5##_x; \
-       vaesenclast t4##_x, x0##_x, x0##_x; \
-       vaesenclast t4##_x, t0##_x, t0##_x; \
-       vaesenclast t4##_x, x7##_x, x7##_x; \
-       vaesenclast t4##_x, t1##_x, t1##_x; \
-       vaesenclast t4##_x, x3##_x, x3##_x; \
-       vaesenclast t4##_x, t3##_x, t3##_x; \
-       vaesenclast t4##_x, x6##_x, x6##_x; \
-       vaesenclast t4##_x, t2##_x, t2##_x; \
-       vinserti128 $1, t0##_x, x0, x0; \
-       vinserti128 $1, t1##_x, x7, x7; \
-       vinserti128 $1, t3##_x, x3, x3; \
-       vinserti128 $1, t2##_x, x6, x6; \
-       vextracti128 $1, x1, t3##_x; \
-       vextracti128 $1, x4, t2##_x; \
-       vbroadcasti128 .Lpost_tf_lo_s1 RIP, t0; \
-       vbroadcasti128 .Lpost_tf_hi_s1 RIP, t1; \
-       vaesenclast t4##_x, x2##_x, x2##_x; \
-       vaesenclast t4##_x, t6##_x, t6##_x; \
-       vaesenclast t4##_x, x5##_x, x5##_x; \
-       vaesenclast t4##_x, t5##_x, t5##_x; \
-       vaesenclast t4##_x, x1##_x, x1##_x; \
-       vaesenclast t4##_x, t3##_x, t3##_x; \
-       vaesenclast t4##_x, x4##_x, x4##_x; \
-       vaesenclast t4##_x, t2##_x, t2##_x; \
-       vinserti128 $1, t6##_x, x2, x2; \
-       vinserti128 $1, t5##_x, x5, x5; \
-       vinserti128 $1, t3##_x, x1, x1; \
-       vinserti128 $1, t2##_x, x4, x4; \
-       \
-       /* postfilter sboxes 1 and 4 */ \
-       vbroadcasti128 .Lpost_tf_lo_s3 RIP, t2; \
-       vbroadcasti128 .Lpost_tf_hi_s3 RIP, t3; \
-       filter_8bit(x0, t0, t1, t7, t4); \
-       filter_8bit(x7, t0, t1, t7, t4); \
-       filter_8bit(x3, t0, t1, t7, t6); \
-       filter_8bit(x6, t0, t1, t7, t6); \
-       \
-       /* postfilter sbox 3 */ \
-       vbroadcasti128 .Lpost_tf_lo_s2 RIP, t4; \
-       vbroadcasti128 .Lpost_tf_hi_s2 RIP, t5; \
-       filter_8bit(x2, t2, t3, t7, t6); \
-       filter_8bit(x5, t2, t3, t7, t6); \
-       \
-       vpbroadcastq key, t0; /* higher 64-bit duplicate ignored */ \
-       \
-       /* postfilter sbox 2 */ \
-       filter_8bit(x1, t4, t5, t7, t2); \
-       filter_8bit(x4, t4, t5, t7, t2); \
-       vpxor t7, t7, t7; \
-       \
-       vpsrldq $1, t0, t1; \
-       vpsrldq $2, t0, t2; \
-       vpshufb t7, t1, t1; \
-       vpsrldq $3, t0, t3; \
-       \
-       /* P-function */ \
-       vpxor x5, x0, x0; \
-       vpxor x6, x1, x1; \
-       vpxor x7, x2, x2; \
-       vpxor x4, x3, x3; \
-       \
-       vpshufb t7, t2, t2; \
-       vpsrldq $4, t0, t4; \
-       vpshufb t7, t3, t3; \
-       vpsrldq $5, t0, t5; \
-       vpshufb t7, t4, t4; \
-       \
-       vpxor x2, x4, x4; \
-       vpxor x3, x5, x5; \
-       vpxor x0, x6, x6; \
-       vpxor x1, x7, x7; \
-       \
-       vpsrldq $6, t0, t6; \
-       vpshufb t7, t5, t5; \
-       vpshufb t7, t6, t6; \
-       \
-       vpxor x7, x0, x0; \
-       vpxor x4, x1, x1; \
-       vpxor x5, x2, x2; \
-       vpxor x6, x3, x3; \
-       \
-       vpxor x3, x4, x4; \
-       vpxor x0, x5, x5; \
-       vpxor x1, x6, x6; \
-       vpxor x2, x7, x7; /* note: high and low parts swapped */ \
-       \
-       /* Add key material and result to CD (x becomes new CD) */ \
-       \
-       vpxor t6, x1, x1; \
-       vpxor 5 * 32(mem_cd), x1, x1; \
-       \
-       vpsrldq $7, t0, t6; \
-       vpshufb t7, t0, t0; \
-       vpshufb t7, t6, t7; \
-       \
-       vpxor t7, x0, x0; \
-       vpxor 4 * 32(mem_cd), x0, x0; \
-       \
-       vpxor t5, x2, x2; \
-       vpxor 6 * 32(mem_cd), x2, x2; \
-       \
-       vpxor t4, x3, x3; \
-       vpxor 7 * 32(mem_cd), x3, x3; \
-       \
-       vpxor t3, x4, x4; \
-       vpxor 0 * 32(mem_cd), x4, x4; \
-       \
-       vpxor t2, x5, x5; \
-       vpxor 1 * 32(mem_cd), x5, x5; \
-       \
-       vpxor t1, x6, x6; \
-       vpxor 2 * 32(mem_cd), x6, x6; \
-       \
-       vpxor t0, x7, x7; \
-       vpxor 3 * 32(mem_cd), x7, x7;
-
-/*
- * IN/OUT:
- *  x0..x7: byte-sliced AB state preloaded
- *  mem_ab: byte-sliced AB state in memory
- *  mem_cb: byte-sliced CD state in memory
- */
-#define two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, i, dir, store_ab) \
-       roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                 y6, y7, mem_cd, (key_table + (i) * 8)(CTX)); \
-       \
-       vmovdqu x0, 4 * 32(mem_cd); \
-       vmovdqu x1, 5 * 32(mem_cd); \
-       vmovdqu x2, 6 * 32(mem_cd); \
-       vmovdqu x3, 7 * 32(mem_cd); \
-       vmovdqu x4, 0 * 32(mem_cd); \
-       vmovdqu x5, 1 * 32(mem_cd); \
-       vmovdqu x6, 2 * 32(mem_cd); \
-       vmovdqu x7, 3 * 32(mem_cd); \
-       \
-       roundsm32(x4, x5, x6, x7, x0, x1, x2, x3, y0, y1, y2, y3, y4, y5, \
-                 y6, y7, mem_ab, (key_table + ((i) + (dir)) * 8)(CTX)); \
-       \
-       store_ab(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab);
-
-#define dummy_store(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) /* do nothing */
-
-#define store_ab_state(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) \
-       /* Store new AB state */ \
-       vmovdqu x4, 4 * 32(mem_ab); \
-       vmovdqu x5, 5 * 32(mem_ab); \
-       vmovdqu x6, 6 * 32(mem_ab); \
-       vmovdqu x7, 7 * 32(mem_ab); \
-       vmovdqu x0, 0 * 32(mem_ab); \
-       vmovdqu x1, 1 * 32(mem_ab); \
-       vmovdqu x2, 2 * 32(mem_ab); \
-       vmovdqu x3, 3 * 32(mem_ab);
-
-#define enc_rounds32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, i) \
-       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, (i) + 2, 1, store_ab_state); \
-       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, (i) + 4, 1, store_ab_state); \
-       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, (i) + 6, 1, dummy_store);
-
-#define dec_rounds32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, i) \
-       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, (i) + 7, -1, store_ab_state); \
-       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, (i) + 5, -1, store_ab_state); \
-       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd, (i) + 3, -1, dummy_store);
-
-/*
- * IN:
- *  v0..3: byte-sliced 32-bit integers
- * OUT:
- *  v0..3: (IN <<< 1)
- */
-#define rol32_1_32(v0, v1, v2, v3, t0, t1, t2, zero) \
-       vpcmpgtb v0, zero, t0; \
-       vpaddb v0, v0, v0; \
-       vpabsb t0, t0; \
-       \
-       vpcmpgtb v1, zero, t1; \
-       vpaddb v1, v1, v1; \
-       vpabsb t1, t1; \
-       \
-       vpcmpgtb v2, zero, t2; \
-       vpaddb v2, v2, v2; \
-       vpabsb t2, t2; \
-       \
-       vpor t0, v1, v1; \
-       \
-       vpcmpgtb v3, zero, t0; \
-       vpaddb v3, v3, v3; \
-       vpabsb t0, t0; \
-       \
-       vpor t1, v2, v2; \
-       vpor t2, v3, v3; \
-       vpor t0, v0, v0;
-
-/*
- * IN:
- *   r: byte-sliced AB state in memory
- *   l: byte-sliced CD state in memory
- * OUT:
- *   x0..x7: new byte-sliced CD state
- */
-#define fls32(l, l0, l1, l2, l3, l4, l5, l6, l7, r, t0, t1, t2, t3, tt0, \
-             tt1, tt2, tt3, kll, klr, krl, krr) \
-       /* \
-        * t0 = kll; \
-        * t0 &= ll; \
-        * lr ^= rol32(t0, 1); \
-        */ \
-       vpbroadcastd kll, t0; /* only lowest 32-bit used */ \
-       vpxor tt0, tt0, tt0; \
-       vpshufb tt0, t0, t3; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t2; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t1; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t0; \
-       \
-       vpand l0, t0, t0; \
-       vpand l1, t1, t1; \
-       vpand l2, t2, t2; \
-       vpand l3, t3, t3; \
-       \
-       rol32_1_32(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
-       \
-       vpxor l4, t0, l4; \
-       vpbroadcastd krr, t0; /* only lowest 32-bit used */ \
-       vmovdqu l4, 4 * 32(l); \
-       vpxor l5, t1, l5; \
-       vmovdqu l5, 5 * 32(l); \
-       vpxor l6, t2, l6; \
-       vmovdqu l6, 6 * 32(l); \
-       vpxor l7, t3, l7; \
-       vmovdqu l7, 7 * 32(l); \
-       \
-       /* \
-        * t2 = krr; \
-        * t2 |= rr; \
-        * rl ^= t2; \
-        */ \
-       \
-       vpshufb tt0, t0, t3; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t2; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t1; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t0; \
-       \
-       vpor 4 * 32(r), t0, t0; \
-       vpor 5 * 32(r), t1, t1; \
-       vpor 6 * 32(r), t2, t2; \
-       vpor 7 * 32(r), t3, t3; \
-       \
-       vpxor 0 * 32(r), t0, t0; \
-       vpxor 1 * 32(r), t1, t1; \
-       vpxor 2 * 32(r), t2, t2; \
-       vpxor 3 * 32(r), t3, t3; \
-       vmovdqu t0, 0 * 32(r); \
-       vpbroadcastd krl, t0; /* only lowest 32-bit used */ \
-       vmovdqu t1, 1 * 32(r); \
-       vmovdqu t2, 2 * 32(r); \
-       vmovdqu t3, 3 * 32(r); \
-       \
-       /* \
-        * t2 = krl; \
-        * t2 &= rl; \
-        * rr ^= rol32(t2, 1); \
-        */ \
-       vpshufb tt0, t0, t3; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t2; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t1; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t0; \
-       \
-       vpand 0 * 32(r), t0, t0; \
-       vpand 1 * 32(r), t1, t1; \
-       vpand 2 * 32(r), t2, t2; \
-       vpand 3 * 32(r), t3, t3; \
-       \
-       rol32_1_32(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
-       \
-       vpxor 4 * 32(r), t0, t0; \
-       vpxor 5 * 32(r), t1, t1; \
-       vpxor 6 * 32(r), t2, t2; \
-       vpxor 7 * 32(r), t3, t3; \
-       vmovdqu t0, 4 * 32(r); \
-       vpbroadcastd klr, t0; /* only lowest 32-bit used */ \
-       vmovdqu t1, 5 * 32(r); \
-       vmovdqu t2, 6 * 32(r); \
-       vmovdqu t3, 7 * 32(r); \
-       \
-       /* \
-        * t0 = klr; \
-        * t0 |= lr; \
-        * ll ^= t0; \
-        */ \
-       \
-       vpshufb tt0, t0, t3; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t2; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t1; \
-       vpsrldq $1, t0, t0; \
-       vpshufb tt0, t0, t0; \
-       \
-       vpor l4, t0, t0; \
-       vpor l5, t1, t1; \
-       vpor l6, t2, t2; \
-       vpor l7, t3, t3; \
-       \
-       vpxor l0, t0, l0; \
-       vmovdqu l0, 0 * 32(l); \
-       vpxor l1, t1, l1; \
-       vmovdqu l1, 1 * 32(l); \
-       vpxor l2, t2, l2; \
-       vmovdqu l2, 2 * 32(l); \
-       vpxor l3, t3, l3; \
-       vmovdqu l3, 3 * 32(l);
-
-#define transpose_4x4(x0, x1, x2, x3, t1, t2) \
-       vpunpckhdq x1, x0, t2; \
-       vpunpckldq x1, x0, x0; \
-       \
-       vpunpckldq x3, x2, t1; \
-       vpunpckhdq x3, x2, x2; \
-       \
-       vpunpckhqdq t1, x0, x1; \
-       vpunpcklqdq t1, x0, x0; \
-       \
-       vpunpckhqdq x2, t2, x3; \
-       vpunpcklqdq x2, t2, x2;
-
-#define byteslice_16x16b_fast(a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, d2, \
-                             a3, b3, c3, d3, st0, st1) \
-       vmovdqu d2, st0; \
-       vmovdqu d3, st1; \
-       transpose_4x4(a0, a1, a2, a3, d2, d3); \
-       transpose_4x4(b0, b1, b2, b3, d2, d3); \
-       vmovdqu st0, d2; \
-       vmovdqu st1, d3; \
-       \
-       vmovdqu a0, st0; \
-       vmovdqu a1, st1; \
-       transpose_4x4(c0, c1, c2, c3, a0, a1); \
-       transpose_4x4(d0, d1, d2, d3, a0, a1); \
-       \
-       vbroadcasti128 .Lshufb_16x16b RIP, a0; \
-       vmovdqu st1, a1; \
-       vpshufb a0, a2, a2; \
-       vpshufb a0, a3, a3; \
-       vpshufb a0, b0, b0; \
-       vpshufb a0, b1, b1; \
-       vpshufb a0, b2, b2; \
-       vpshufb a0, b3, b3; \
-       vpshufb a0, a1, a1; \
-       vpshufb a0, c0, c0; \
-       vpshufb a0, c1, c1; \
-       vpshufb a0, c2, c2; \
-       vpshufb a0, c3, c3; \
-       vpshufb a0, d0, d0; \
-       vpshufb a0, d1, d1; \
-       vpshufb a0, d2, d2; \
-       vpshufb a0, d3, d3; \
-       vmovdqu d3, st1; \
-       vmovdqu st0, d3; \
-       vpshufb a0, d3, a0; \
-       vmovdqu d2, st0; \
-       \
-       transpose_4x4(a0, b0, c0, d0, d2, d3); \
-       transpose_4x4(a1, b1, c1, d1, d2, d3); \
-       vmovdqu st0, d2; \
-       vmovdqu st1, d3; \
-       \
-       vmovdqu b0, st0; \
-       vmovdqu b1, st1; \
-       transpose_4x4(a2, b2, c2, d2, b0, b1); \
-       transpose_4x4(a3, b3, c3, d3, b0, b1); \
-       vmovdqu st0, b0; \
-       vmovdqu st1, b1; \
-       /* does not adjust output bytes inside vectors */
-
-/* load blocks to registers and apply pre-whitening */
-#define inpack32_pre(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                    y6, y7, rio, key) \
-       vpbroadcastq key, x0; \
-       vpshufb .Lpack_bswap RIP, x0, x0; \
-       \
-       vpxor 0 * 32(rio), x0, y7; \
-       vpxor 1 * 32(rio), x0, y6; \
-       vpxor 2 * 32(rio), x0, y5; \
-       vpxor 3 * 32(rio), x0, y4; \
-       vpxor 4 * 32(rio), x0, y3; \
-       vpxor 5 * 32(rio), x0, y2; \
-       vpxor 6 * 32(rio), x0, y1; \
-       vpxor 7 * 32(rio), x0, y0; \
-       vpxor 8 * 32(rio), x0, x7; \
-       vpxor 9 * 32(rio), x0, x6; \
-       vpxor 10 * 32(rio), x0, x5; \
-       vpxor 11 * 32(rio), x0, x4; \
-       vpxor 12 * 32(rio), x0, x3; \
-       vpxor 13 * 32(rio), x0, x2; \
-       vpxor 14 * 32(rio), x0, x1; \
-       vpxor 15 * 32(rio), x0, x0;
-
-/* byteslice pre-whitened blocks and store to temporary memory */
-#define inpack32_post(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                     y6, y7, mem_ab, mem_cd) \
-       byteslice_16x16b_fast(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, \
-                             y4, y5, y6, y7, (mem_ab), (mem_cd)); \
-       \
-       vmovdqu x0, 0 * 32(mem_ab); \
-       vmovdqu x1, 1 * 32(mem_ab); \
-       vmovdqu x2, 2 * 32(mem_ab); \
-       vmovdqu x3, 3 * 32(mem_ab); \
-       vmovdqu x4, 4 * 32(mem_ab); \
-       vmovdqu x5, 5 * 32(mem_ab); \
-       vmovdqu x6, 6 * 32(mem_ab); \
-       vmovdqu x7, 7 * 32(mem_ab); \
-       vmovdqu y0, 0 * 32(mem_cd); \
-       vmovdqu y1, 1 * 32(mem_cd); \
-       vmovdqu y2, 2 * 32(mem_cd); \
-       vmovdqu y3, 3 * 32(mem_cd); \
-       vmovdqu y4, 4 * 32(mem_cd); \
-       vmovdqu y5, 5 * 32(mem_cd); \
-       vmovdqu y6, 6 * 32(mem_cd); \
-       vmovdqu y7, 7 * 32(mem_cd);
-
-/* de-byteslice, apply post-whitening and store blocks */
-#define outunpack32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, \
-                   y5, y6, y7, key, stack_tmp0, stack_tmp1) \
-       byteslice_16x16b_fast(y0, y4, x0, x4, y1, y5, x1, x5, y2, y6, x2, x6, \
-                             y3, y7, x3, x7, stack_tmp0, stack_tmp1); \
-       \
-       vmovdqu x0, stack_tmp0; \
-       \
-       vpbroadcastq key, x0; \
-       vpshufb .Lpack_bswap RIP, x0, x0; \
-       \
-       vpxor x0, y7, y7; \
-       vpxor x0, y6, y6; \
-       vpxor x0, y5, y5; \
-       vpxor x0, y4, y4; \
-       vpxor x0, y3, y3; \
-       vpxor x0, y2, y2; \
-       vpxor x0, y1, y1; \
-       vpxor x0, y0, y0; \
-       vpxor x0, x7, x7; \
-       vpxor x0, x6, x6; \
-       vpxor x0, x5, x5; \
-       vpxor x0, x4, x4; \
-       vpxor x0, x3, x3; \
-       vpxor x0, x2, x2; \
-       vpxor x0, x1, x1; \
-       vpxor stack_tmp0, x0, x0;
-
-#define write_output(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
-                    y6, y7, rio) \
-       vmovdqu x0, 0 * 32(rio); \
-       vmovdqu x1, 1 * 32(rio); \
-       vmovdqu x2, 2 * 32(rio); \
-       vmovdqu x3, 3 * 32(rio); \
-       vmovdqu x4, 4 * 32(rio); \
-       vmovdqu x5, 5 * 32(rio); \
-       vmovdqu x6, 6 * 32(rio); \
-       vmovdqu x7, 7 * 32(rio); \
-       vmovdqu y0, 8 * 32(rio); \
-       vmovdqu y1, 9 * 32(rio); \
-       vmovdqu y2, 10 * 32(rio); \
-       vmovdqu y3, 11 * 32(rio); \
-       vmovdqu y4, 12 * 32(rio); \
-       vmovdqu y5, 13 * 32(rio); \
-       vmovdqu y6, 14 * 32(rio); \
-       vmovdqu y7, 15 * 32(rio);
-
-.text
-.align 32
-
-#define SHUFB_BYTES(idx) \
-       0 + (idx), 4 + (idx), 8 + (idx), 12 + (idx)
-
-.Lshufb_16x16b:
-       .byte SHUFB_BYTES(0), SHUFB_BYTES(1), SHUFB_BYTES(2), SHUFB_BYTES(3)
-       .byte SHUFB_BYTES(0), SHUFB_BYTES(1), SHUFB_BYTES(2), SHUFB_BYTES(3)
-
-.Lpack_bswap:
-       .long 0x00010203, 0x04050607, 0x80808080, 0x80808080
-       .long 0x00010203, 0x04050607, 0x80808080, 0x80808080
-
-/* For CTR-mode IV byteswap */
-.Lbswap128_mask:
-       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
-
-/*
- * pre-SubByte transform
- *
- * pre-lookup for sbox1, sbox2, sbox3:
- *   swap_bitendianness(
- *       isom_map_camellia_to_aes(
- *           camellia_f(
- *               swap_bitendianess(in)
- *           )
- *       )
- *   )
- *
- * (note: '⊕ 0xc5' inside camellia_f())
- */
-.Lpre_tf_lo_s1:
-       .byte 0x45, 0xe8, 0x40, 0xed, 0x2e, 0x83, 0x2b, 0x86
-       .byte 0x4b, 0xe6, 0x4e, 0xe3, 0x20, 0x8d, 0x25, 0x88
-.Lpre_tf_hi_s1:
-       .byte 0x00, 0x51, 0xf1, 0xa0, 0x8a, 0xdb, 0x7b, 0x2a
-       .byte 0x09, 0x58, 0xf8, 0xa9, 0x83, 0xd2, 0x72, 0x23
-
-/*
- * pre-SubByte transform
- *
- * pre-lookup for sbox4:
- *   swap_bitendianness(
- *       isom_map_camellia_to_aes(
- *           camellia_f(
- *               swap_bitendianess(in <<< 1)
- *           )
- *       )
- *   )
- *
- * (note: '⊕ 0xc5' inside camellia_f())
- */
-.Lpre_tf_lo_s4:
-       .byte 0x45, 0x40, 0x2e, 0x2b, 0x4b, 0x4e, 0x20, 0x25
-       .byte 0x14, 0x11, 0x7f, 0x7a, 0x1a, 0x1f, 0x71, 0x74
-.Lpre_tf_hi_s4:
-       .byte 0x00, 0xf1, 0x8a, 0x7b, 0x09, 0xf8, 0x83, 0x72
-       .byte 0xad, 0x5c, 0x27, 0xd6, 0xa4, 0x55, 0x2e, 0xdf
-
-/*
- * post-SubByte transform
- *
- * post-lookup for sbox1, sbox4:
- *  swap_bitendianness(
- *      camellia_h(
- *          isom_map_aes_to_camellia(
- *              swap_bitendianness(
- *                  aes_inverse_affine_transform(in)
- *              )
- *          )
- *      )
- *  )
- *
- * (note: '⊕ 0x6e' inside camellia_h())
- */
-.Lpost_tf_lo_s1:
-       .byte 0x3c, 0xcc, 0xcf, 0x3f, 0x32, 0xc2, 0xc1, 0x31
-       .byte 0xdc, 0x2c, 0x2f, 0xdf, 0xd2, 0x22, 0x21, 0xd1
-.Lpost_tf_hi_s1:
-       .byte 0x00, 0xf9, 0x86, 0x7f, 0xd7, 0x2e, 0x51, 0xa8
-       .byte 0xa4, 0x5d, 0x22, 0xdb, 0x73, 0x8a, 0xf5, 0x0c
-
-/*
- * post-SubByte transform
- *
- * post-lookup for sbox2:
- *  swap_bitendianness(
- *      camellia_h(
- *          isom_map_aes_to_camellia(
- *              swap_bitendianness(
- *                  aes_inverse_affine_transform(in)
- *              )
- *          )
- *      )
- *  ) <<< 1
- *
- * (note: '⊕ 0x6e' inside camellia_h())
- */
-.Lpost_tf_lo_s2:
-       .byte 0x78, 0x99, 0x9f, 0x7e, 0x64, 0x85, 0x83, 0x62
-       .byte 0xb9, 0x58, 0x5e, 0xbf, 0xa5, 0x44, 0x42, 0xa3
-.Lpost_tf_hi_s2:
-       .byte 0x00, 0xf3, 0x0d, 0xfe, 0xaf, 0x5c, 0xa2, 0x51
-       .byte 0x49, 0xba, 0x44, 0xb7, 0xe6, 0x15, 0xeb, 0x18
-
-/*
- * post-SubByte transform
- *
- * post-lookup for sbox3:
- *  swap_bitendianness(
- *      camellia_h(
- *          isom_map_aes_to_camellia(
- *              swap_bitendianness(
- *                  aes_inverse_affine_transform(in)
- *              )
- *          )
- *      )
- *  ) >>> 1
- *
- * (note: '⊕ 0x6e' inside camellia_h())
- */
-.Lpost_tf_lo_s3:
-       .byte 0x1e, 0x66, 0xe7, 0x9f, 0x19, 0x61, 0xe0, 0x98
-       .byte 0x6e, 0x16, 0x97, 0xef, 0x69, 0x11, 0x90, 0xe8
-.Lpost_tf_hi_s3:
-       .byte 0x00, 0xfc, 0x43, 0xbf, 0xeb, 0x17, 0xa8, 0x54
-       .byte 0x52, 0xae, 0x11, 0xed, 0xb9, 0x45, 0xfa, 0x06
-
-/* For isolating SubBytes from AESENCLAST, inverse shift row */
-.Linv_shift_row:
-       .byte 0x00, 0x0d, 0x0a, 0x07, 0x04, 0x01, 0x0e, 0x0b
-       .byte 0x08, 0x05, 0x02, 0x0f, 0x0c, 0x09, 0x06, 0x03
-
-.align 4
-/* 4-bit mask */
-.L0f0f0f0f:
-       .long 0x0f0f0f0f
-
-
-.align 8
-ELF(.type   __camellia_enc_blk32,@function;)
-
-__camellia_enc_blk32:
-       /* input:
-        *      %rdi: ctx, CTX
-        *      %rax: temporary storage, 512 bytes
-        *      %ymm0..%ymm15: 32 plaintext blocks
-        * output:
-        *      %ymm0..%ymm15: 32 encrypted blocks, order swapped:
-        *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
-        */
-
-       leaq 8 * 32(%rax), %rcx;
-
-       inpack32_post(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                     %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                     %ymm15, %rax, %rcx);
-
-       enc_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rax, %rcx, 0);
-
-       fls32(%rax, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-             %rcx, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-             %ymm15,
-             ((key_table + (8) * 8) + 0)(CTX),
-             ((key_table + (8) * 8) + 4)(CTX),
-             ((key_table + (8) * 8) + 8)(CTX),
-             ((key_table + (8) * 8) + 12)(CTX));
-
-       enc_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rax, %rcx, 8);
-
-       fls32(%rax, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-             %rcx, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-             %ymm15,
-             ((key_table + (16) * 8) + 0)(CTX),
-             ((key_table + (16) * 8) + 4)(CTX),
-             ((key_table + (16) * 8) + 8)(CTX),
-             ((key_table + (16) * 8) + 12)(CTX));
-
-       enc_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rax, %rcx, 16);
-
-       movl $24, %r8d;
-       cmpl $128, key_bitlength(CTX);
-       jne .Lenc_max32;
-
-.Lenc_done:
-       /* load CD for output */
-       vmovdqu 0 * 32(%rcx), %ymm8;
-       vmovdqu 1 * 32(%rcx), %ymm9;
-       vmovdqu 2 * 32(%rcx), %ymm10;
-       vmovdqu 3 * 32(%rcx), %ymm11;
-       vmovdqu 4 * 32(%rcx), %ymm12;
-       vmovdqu 5 * 32(%rcx), %ymm13;
-       vmovdqu 6 * 32(%rcx), %ymm14;
-       vmovdqu 7 * 32(%rcx), %ymm15;
-
-       outunpack32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                   %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                   %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax));
-
-       ret;
-
-.align 8
-.Lenc_max32:
-       movl $32, %r8d;
-
-       fls32(%rax, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-             %rcx, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-             %ymm15,
-             ((key_table + (24) * 8) + 0)(CTX),
-             ((key_table + (24) * 8) + 4)(CTX),
-             ((key_table + (24) * 8) + 8)(CTX),
-             ((key_table + (24) * 8) + 12)(CTX));
-
-       enc_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rax, %rcx, 24);
-
-       jmp .Lenc_done;
-ELF(.size __camellia_enc_blk32,.-__camellia_enc_blk32;)
-
-.align 8
-ELF(.type   __camellia_dec_blk32,@function;)
-
-__camellia_dec_blk32:
-       /* input:
-        *      %rdi: ctx, CTX
-        *      %rax: temporary storage, 512 bytes
-        *      %r8d: 24 for 16 byte key, 32 for larger
-        *      %ymm0..%ymm15: 16 encrypted blocks
-        * output:
-        *      %ymm0..%ymm15: 16 plaintext blocks, order swapped:
-        *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
-        */
-
-       leaq 8 * 32(%rax), %rcx;
-
-       inpack32_post(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                     %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                     %ymm15, %rax, %rcx);
-
-       cmpl $32, %r8d;
-       je .Ldec_max32;
-
-.Ldec_max24:
-       dec_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rax, %rcx, 16);
-
-       fls32(%rax, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-             %rcx, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-             %ymm15,
-             ((key_table + (16) * 8) + 8)(CTX),
-             ((key_table + (16) * 8) + 12)(CTX),
-             ((key_table + (16) * 8) + 0)(CTX),
-             ((key_table + (16) * 8) + 4)(CTX));
-
-       dec_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rax, %rcx, 8);
-
-       fls32(%rax, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-             %rcx, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-             %ymm15,
-             ((key_table + (8) * 8) + 8)(CTX),
-             ((key_table + (8) * 8) + 12)(CTX),
-             ((key_table + (8) * 8) + 0)(CTX),
-             ((key_table + (8) * 8) + 4)(CTX));
-
-       dec_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rax, %rcx, 0);
-
-       /* load CD for output */
-       vmovdqu 0 * 32(%rcx), %ymm8;
-       vmovdqu 1 * 32(%rcx), %ymm9;
-       vmovdqu 2 * 32(%rcx), %ymm10;
-       vmovdqu 3 * 32(%rcx), %ymm11;
-       vmovdqu 4 * 32(%rcx), %ymm12;
-       vmovdqu 5 * 32(%rcx), %ymm13;
-       vmovdqu 6 * 32(%rcx), %ymm14;
-       vmovdqu 7 * 32(%rcx), %ymm15;
-
-       outunpack32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                   %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                   %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax));
-
-       ret;
-
-.align 8
-.Ldec_max32:
-       dec_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rax, %rcx, 24);
-
-       fls32(%rax, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-             %rcx, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-             %ymm15,
-             ((key_table + (24) * 8) + 8)(CTX),
-             ((key_table + (24) * 8) + 12)(CTX),
-             ((key_table + (24) * 8) + 0)(CTX),
-             ((key_table + (24) * 8) + 4)(CTX));
-
-       jmp .Ldec_max24;
-ELF(.size __camellia_dec_blk32,.-__camellia_dec_blk32;)
-
-#define inc_le128(x, minus_one, tmp) \
-       vpcmpeqq minus_one, x, tmp; \
-       vpsubq minus_one, x, x; \
-       vpslldq $8, tmp, tmp; \
-       vpsubq tmp, x, x;
-
-.align 8
-.globl _gcry_camellia_aesni_avx2_ctr_enc
-ELF(.type   _gcry_camellia_aesni_avx2_ctr_enc,@function;)
-
-_gcry_camellia_aesni_avx2_ctr_enc:
-       /* input:
-        *      %rdi: ctx, CTX
-        *      %rsi: dst (32 blocks)
-        *      %rdx: src (32 blocks)
-        *      %rcx: iv (big endian, 128bit)
-        */
-
-       pushq %rbp;
-       movq %rsp, %rbp;
-
-       movq 8(%rcx), %r11;
-       bswapq %r11;
-
-       vzeroupper;
-
-       subq $(16 * 32), %rsp;
-       andq $~63, %rsp;
-       movq %rsp, %rax;
-
-       vpcmpeqd %ymm15, %ymm15, %ymm15;
-       vpsrldq $8, %ymm15, %ymm15; /* ab: -1:0 ; cd: -1:0 */
-
-       /* load IV and byteswap */
-       vmovdqu (%rcx), %xmm0;
-       vpshufb .Lbswap128_mask RIP, %xmm0, %xmm0;
-       vmovdqa %xmm0, %xmm1;
-       inc_le128(%xmm0, %xmm15, %xmm14);
-       vbroadcasti128 .Lbswap128_mask RIP, %ymm14;
-       vinserti128 $1, %xmm0, %ymm1, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm13;
-       vmovdqu %ymm13, 15 * 32(%rax);
-
-       /* check need for handling 64-bit overflow and carry */
-       cmpq $(0xffffffffffffffff - 32), %r11;
-       ja .Lload_ctr_carry;
-
-       /* construct IVs */
-       vpaddq %ymm15, %ymm15, %ymm15; /* ab: -2:0 ; cd: -2:0 */
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm13;
-       vmovdqu %ymm13, 14 * 32(%rax);
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm13;
-       vmovdqu %ymm13, 13 * 32(%rax);
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm12;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm11;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm10;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm9;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm8;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm7;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm6;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm5;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm4;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm3;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm2;
-       vpsubq %ymm15, %ymm0, %ymm0;
-       vpshufb %ymm14, %ymm0, %ymm1;
-       vpsubq %ymm15, %ymm0, %ymm0;  /* +30 ; +31 */
-       vpsubq %xmm15, %xmm0, %xmm13; /* +32 */
-       vpshufb %ymm14, %ymm0, %ymm0;
-       vpshufb %xmm14, %xmm13, %xmm13;
-       vmovdqu %xmm13, (%rcx);
-
-       jmp .Lload_ctr_done;
-
-.align 4
-.Lload_ctr_carry:
-       /* construct IVs */
-       inc_le128(%ymm0, %ymm15, %ymm13); /* ab: le1 ; cd: le2 */
-       inc_le128(%ymm0, %ymm15, %ymm13); /* ab: le2 ; cd: le3 */
-       vpshufb %ymm14, %ymm0, %ymm13;
-       vmovdqu %ymm13, 14 * 32(%rax);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm13;
-       vmovdqu %ymm13, 13 * 32(%rax);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm12;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm11;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm10;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm9;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm8;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm7;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm6;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm5;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm4;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm3;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm2;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vpshufb %ymm14, %ymm0, %ymm1;
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       inc_le128(%ymm0, %ymm15, %ymm13);
-       vextracti128 $1, %ymm0, %xmm13;
-       vpshufb %ymm14, %ymm0, %ymm0;
-       inc_le128(%xmm13, %xmm15, %xmm14);
-       vpshufb .Lbswap128_mask RIP, %xmm13, %xmm13;
-       vmovdqu %xmm13, (%rcx);
-
-.align 4
-.Lload_ctr_done:
-       /* inpack16_pre: */
-       vpbroadcastq (key_table)(CTX), %ymm15;
-       vpshufb .Lpack_bswap RIP, %ymm15, %ymm15;
-       vpxor %ymm0, %ymm15, %ymm0;
-       vpxor %ymm1, %ymm15, %ymm1;
-       vpxor %ymm2, %ymm15, %ymm2;
-       vpxor %ymm3, %ymm15, %ymm3;
-       vpxor %ymm4, %ymm15, %ymm4;
-       vpxor %ymm5, %ymm15, %ymm5;
-       vpxor %ymm6, %ymm15, %ymm6;
-       vpxor %ymm7, %ymm15, %ymm7;
-       vpxor %ymm8, %ymm15, %ymm8;
-       vpxor %ymm9, %ymm15, %ymm9;
-       vpxor %ymm10, %ymm15, %ymm10;
-       vpxor %ymm11, %ymm15, %ymm11;
-       vpxor %ymm12, %ymm15, %ymm12;
-       vpxor 13 * 32(%rax), %ymm15, %ymm13;
-       vpxor 14 * 32(%rax), %ymm15, %ymm14;
-       vpxor 15 * 32(%rax), %ymm15, %ymm15;
-
-       call __camellia_enc_blk32;
-
-       vpxor 0 * 32(%rdx), %ymm7, %ymm7;
-       vpxor 1 * 32(%rdx), %ymm6, %ymm6;
-       vpxor 2 * 32(%rdx), %ymm5, %ymm5;
-       vpxor 3 * 32(%rdx), %ymm4, %ymm4;
-       vpxor 4 * 32(%rdx), %ymm3, %ymm3;
-       vpxor 5 * 32(%rdx), %ymm2, %ymm2;
-       vpxor 6 * 32(%rdx), %ymm1, %ymm1;
-       vpxor 7 * 32(%rdx), %ymm0, %ymm0;
-       vpxor 8 * 32(%rdx), %ymm15, %ymm15;
-       vpxor 9 * 32(%rdx), %ymm14, %ymm14;
-       vpxor 10 * 32(%rdx), %ymm13, %ymm13;
-       vpxor 11 * 32(%rdx), %ymm12, %ymm12;
-       vpxor 12 * 32(%rdx), %ymm11, %ymm11;
-       vpxor 13 * 32(%rdx), %ymm10, %ymm10;
-       vpxor 14 * 32(%rdx), %ymm9, %ymm9;
-       vpxor 15 * 32(%rdx), %ymm8, %ymm8;
-       leaq 32 * 16(%rdx), %rdx;
-
-       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
-                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
-                    %ymm8, %rsi);
-
-       vzeroall;
-
-       leave;
-       ret;
-ELF(.size _gcry_camellia_aesni_avx2_ctr_enc,.-_gcry_camellia_aesni_avx2_ctr_enc;)
-
-.align 8
-.globl _gcry_camellia_aesni_avx2_cbc_dec
-ELF(.type   _gcry_camellia_aesni_avx2_cbc_dec,@function;)
-
-_gcry_camellia_aesni_avx2_cbc_dec:
-       /* input:
-        *      %rdi: ctx, CTX
-        *      %rsi: dst (32 blocks)
-        *      %rdx: src (32 blocks)
-        *      %rcx: iv
-        */
-
-       pushq %rbp;
-       movq %rsp, %rbp;
-
-       vzeroupper;
-
-       movq %rcx, %r9;
-
-       cmpl $128, key_bitlength(CTX);
-       movl $32, %r8d;
-       movl $24, %eax;
-       cmovel %eax, %r8d; /* max */
-
-       subq $(16 * 32), %rsp;
-       andq $~63, %rsp;
-       movq %rsp, %rax;
-
-       inpack32_pre(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
-                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
-                    %ymm15, %rdx, (key_table)(CTX, %r8, 8));
-
-       call __camellia_dec_blk32;
-
-       /* XOR output with IV */
-       vmovdqu %ymm8, (%rax);
-       vmovdqu (%r9), %xmm8;
-       vinserti128 $1, (%rdx), %ymm8, %ymm8;
-       vpxor %ymm8, %ymm7, %ymm7;
-       vmovdqu (%rax), %ymm8;
-       vpxor (0 * 32 + 16)(%rdx), %ymm6, %ymm6;
-       vpxor (1 * 32 + 16)(%rdx), %ymm5, %ymm5;
-       vpxor (2 * 32 + 16)(%rdx), %ymm4, %ymm4;
-       vpxor (3 * 32 + 16)(%rdx), %ymm3, %ymm3;
-       vpxor (4 * 32 + 16)(%rdx), %ymm2, %ymm2;
-       vpxor (5 * 32 + 16)(%rdx), %ymm1, %ymm1;
-       vpxor (6 * 32 + 16)(%rdx), %ymm0, %ymm0;
-       vpxor (7 * 32 + 16)(%rdx), %ymm15, %ymm15;
-       vpxor (8 * 32 + 16)(%rdx), %ymm14, %ymm14;
-       vpxor (9 * 32 + 16)(%rdx), %ymm13, %ymm13;
-       vpxor (10 * 32 + 16)(%rdx), %ymm12, %ymm12;
-       vpxor (11 * 32 + 16)(%rdx), %ymm11, %ymm11;
-       vpxor (12 * 32 + 16)(%rdx), %ymm10, %ymm10;
-       vpxor (13 * 32 + 16)(%rdx), %ymm9, %ymm9;
-       vpxor (14 * 32 + 16)(%rdx), %ymm8, %ymm8;
-       movq (15 * 32 + 16 + 0)(%rdx), %rax;
-       movq (15 * 32 + 16 + 8)(%rdx), %rcx;
-
-       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
-                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
-                    %ymm8, %rsi);
-
-       /* store new IV */
-       movq %rax, (0)(%r9);
-       movq %rcx, (8)(%r9);
-
-       vzeroall;
-
-       leave;
-       ret;
-ELF(.size _gcry_camellia_aesni_avx2_cbc_dec,.-_gcry_camellia_aesni_avx2_cbc_dec;)
-
-.align 8
-.globl _gcry_camellia_aesni_avx2_cfb_dec
-ELF(.type   _gcry_camellia_aesni_avx2_cfb_dec,@function;)
-
-_gcry_camellia_aesni_avx2_cfb_dec:
-       /* input:
-        *      %rdi: ctx, CTX
-        *      %rsi: dst (32 blocks)
-        *      %rdx: src (32 blocks)
-        *      %rcx: iv
-        */
-
-       pushq %rbp;
-       movq %rsp, %rbp;
-
-       vzeroupper;
-
-       subq $(16 * 32), %rsp;
-       andq $~63, %rsp;
-       movq %rsp, %rax;
-
-       /* inpack16_pre: */
-       vpbroadcastq (key_table)(CTX), %ymm0;
-       vpshufb .Lpack_bswap RIP, %ymm0, %ymm0;
-       vmovdqu (%rcx), %xmm15;
-       vinserti128 $1, (%rdx), %ymm15, %ymm15;
-       vpxor %ymm15, %ymm0, %ymm15;
-       vmovdqu (15 * 32 + 16)(%rdx), %xmm1;
-       vmovdqu %xmm1, (%rcx); /* store new IV */
-       vpxor (0 * 32 + 16)(%rdx), %ymm0, %ymm14;
-       vpxor (1 * 32 + 16)(%rdx), %ymm0, %ymm13;
-       vpxor (2 * 32 + 16)(%rdx), %ymm0, %ymm12;
-       vpxor (3 * 32 + 16)(%rdx), %ymm0, %ymm11;
-       vpxor (4 * 32 + 16)(%rdx), %ymm0, %ymm10;
-       vpxor (5 * 32 + 16)(%rdx), %ymm0, %ymm9;
-       vpxor (6 * 32 + 16)(%rdx), %ymm0, %ymm8;
-       vpxor (7 * 32 + 16)(%rdx), %ymm0, %ymm7;
-       vpxor (8 * 32 + 16)(%rdx), %ymm0, %ymm6;
-       vpxor (9 * 32 + 16)(%rdx), %ymm0, %ymm5;
-       vpxor (10 * 32 + 16)(%rdx), %ymm0, %ymm4;
-       vpxor (11 * 32 + 16)(%rdx), %ymm0, %ymm3;
-       vpxor (12 * 32 + 16)(%rdx), %ymm0, %ymm2;
-       vpxor (13 * 32 + 16)(%rdx), %ymm0, %ymm1;
-       vpxor (14 * 32 + 16)(%rdx), %ymm0, %ymm0;
-
-       call __camellia_enc_blk32;
-
-       vpxor 0 * 32(%rdx), %ymm7, %ymm7;
-       vpxor 1 * 32(%rdx), %ymm6, %ymm6;
-       vpxor 2 * 32(%rdx), %ymm5, %ymm5;
-       vpxor 3 * 32(%rdx), %ymm4, %ymm4;
-       vpxor 4 * 32(%rdx), %ymm3, %ymm3;
-       vpxor 5 * 32(%rdx), %ymm2, %ymm2;
-       vpxor 6 * 32(%rdx), %ymm1, %ymm1;
-       vpxor 7 * 32(%rdx), %ymm0, %ymm0;
-       vpxor 8 * 32(%rdx), %ymm15, %ymm15;
-       vpxor 9 * 32(%rdx), %ymm14, %ymm14;
-       vpxor 10 * 32(%rdx), %ymm13, %ymm13;
-       vpxor 11 * 32(%rdx), %ymm12, %ymm12;
-       vpxor 12 * 32(%rdx), %ymm11, %ymm11;
-       vpxor 13 * 32(%rdx), %ymm10, %ymm10;
-       vpxor 14 * 32(%rdx), %ymm9, %ymm9;
-       vpxor 15 * 32(%rdx), %ymm8, %ymm8;
-
-       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
-                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
-                    %ymm8, %rsi);
-
-       vzeroall;
-
-       leave;
-       ret;
-ELF(.size _gcry_camellia_aesni_avx2_cfb_dec,.-_gcry_camellia_aesni_avx2_cfb_dec;)
-
-.align 8
-.globl _gcry_camellia_aesni_avx2_ocb_enc
-ELF(.type   _gcry_camellia_aesni_avx2_ocb_enc,@function;)
-
-_gcry_camellia_aesni_avx2_ocb_enc:
-       /* input:
-        *      %rdi: ctx, CTX
-        *      %rsi: dst (32 blocks)
-        *      %rdx: src (32 blocks)
-        *      %rcx: offset
-        *      %r8 : checksum
-        *      %r9 : L pointers (void *L[32])
-        */
-
-       pushq %rbp;
-       movq %rsp, %rbp;
-
-       vzeroupper;
-
-       subq $(16 * 32 + 4 * 8), %rsp;
-       andq $~63, %rsp;
-       movq %rsp, %rax;
-
-       movq %r10, (16 * 32 + 0 * 8)(%rax);
-       movq %r11, (16 * 32 + 1 * 8)(%rax);
-       movq %r12, (16 * 32 + 2 * 8)(%rax);
-       movq %r13, (16 * 32 + 3 * 8)(%rax);
-
-       vmovdqu (%rcx), %xmm14;
-       vmovdqu (%r8), %xmm13;
-
-       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-       /* Checksum_i = Checksum_{i-1} xor P_i  */
-       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
-
-#define OCB_INPUT(n, l0reg, l1reg, yreg) \
-         vmovdqu (n * 32)(%rdx), yreg; \
-         vpxor (l0reg), %xmm14, %xmm15; \
-         vpxor (l1reg), %xmm15, %xmm14; \
-         vinserti128 $1, %xmm14, %ymm15, %ymm15; \
-         vpxor yreg, %ymm13, %ymm13; \
-         vpxor yreg, %ymm15, yreg; \
-         vmovdqu %ymm15, (n * 32)(%rsi);
-
-       movq (0 * 8)(%r9), %r10;
-       movq (1 * 8)(%r9), %r11;
-       movq (2 * 8)(%r9), %r12;
-       movq (3 * 8)(%r9), %r13;
-       OCB_INPUT(0, %r10, %r11, %ymm0);
-       vmovdqu %ymm0, (15 * 32)(%rax);
-       OCB_INPUT(1, %r12, %r13, %ymm0);
-       vmovdqu %ymm0, (14 * 32)(%rax);
-       movq (4 * 8)(%r9), %r10;
-       movq (5 * 8)(%r9), %r11;
-       movq (6 * 8)(%r9), %r12;
-       movq (7 * 8)(%r9), %r13;
-       OCB_INPUT(2, %r10, %r11, %ymm0);
-       vmovdqu %ymm0, (13 * 32)(%rax);
-       OCB_INPUT(3, %r12, %r13, %ymm12);
-       movq (8 * 8)(%r9), %r10;
-       movq (9 * 8)(%r9), %r11;
-       movq (10 * 8)(%r9), %r12;
-       movq (11 * 8)(%r9), %r13;
-       OCB_INPUT(4, %r10, %r11, %ymm11);
-       OCB_INPUT(5, %r12, %r13, %ymm10);
-       movq (12 * 8)(%r9), %r10;
-       movq (13 * 8)(%r9), %r11;
-       movq (14 * 8)(%r9), %r12;
-       movq (15 * 8)(%r9), %r13;
-       OCB_INPUT(6, %r10, %r11, %ymm9);
-       OCB_INPUT(7, %r12, %r13, %ymm8);
-       movq (16 * 8)(%r9), %r10;
-       movq (17 * 8)(%r9), %r11;
-       movq (18 * 8)(%r9), %r12;
-       movq (19 * 8)(%r9), %r13;
-       OCB_INPUT(8, %r10, %r11, %ymm7);
-       OCB_INPUT(9, %r12, %r13, %ymm6);
-       movq (20 * 8)(%r9), %r10;
-       movq (21 * 8)(%r9), %r11;
-       movq (22 * 8)(%r9), %r12;
-       movq (23 * 8)(%r9), %r13;
-       OCB_INPUT(10, %r10, %r11, %ymm5);
-       OCB_INPUT(11, %r12, %r13, %ymm4);
-       movq (24 * 8)(%r9), %r10;
-       movq (25 * 8)(%r9), %r11;
-       movq (26 * 8)(%r9), %r12;
-       movq (27 * 8)(%r9), %r13;
-       OCB_INPUT(12, %r10, %r11, %ymm3);
-       OCB_INPUT(13, %r12, %r13, %ymm2);
-       movq (28 * 8)(%r9), %r10;
-       movq (29 * 8)(%r9), %r11;
-       movq (30 * 8)(%r9), %r12;
-       movq (31 * 8)(%r9), %r13;
-       OCB_INPUT(14, %r10, %r11, %ymm1);
-       OCB_INPUT(15, %r12, %r13, %ymm0);
-#undef OCB_INPUT
-
-       vextracti128 $1, %ymm13, %xmm15;
-       vmovdqu %xmm14, (%rcx);
-       vpxor %xmm13, %xmm15, %xmm15;
-       vmovdqu %xmm15, (%r8);
-
-       /* inpack16_pre: */
-       vpbroadcastq (key_table)(CTX), %ymm15;
-       vpshufb .Lpack_bswap RIP, %ymm15, %ymm15;
-       vpxor %ymm0, %ymm15, %ymm0;
-       vpxor %ymm1, %ymm15, %ymm1;
-       vpxor %ymm2, %ymm15, %ymm2;
-       vpxor %ymm3, %ymm15, %ymm3;
-       vpxor %ymm4, %ymm15, %ymm4;
-       vpxor %ymm5, %ymm15, %ymm5;
-       vpxor %ymm6, %ymm15, %ymm6;
-       vpxor %ymm7, %ymm15, %ymm7;
-       vpxor %ymm8, %ymm15, %ymm8;
-       vpxor %ymm9, %ymm15, %ymm9;
-       vpxor %ymm10, %ymm15, %ymm10;
-       vpxor %ymm11, %ymm15, %ymm11;
-       vpxor %ymm12, %ymm15, %ymm12;
-       vpxor 13 * 32(%rax), %ymm15, %ymm13;
-       vpxor 14 * 32(%rax), %ymm15, %ymm14;
-       vpxor 15 * 32(%rax), %ymm15, %ymm15;
-
-       call __camellia_enc_blk32;
-
-       vpxor 0 * 32(%rsi), %ymm7, %ymm7;
-       vpxor 1 * 32(%rsi), %ymm6, %ymm6;
-       vpxor 2 * 32(%rsi), %ymm5, %ymm5;
-       vpxor 3 * 32(%rsi), %ymm4, %ymm4;
-       vpxor 4 * 32(%rsi), %ymm3, %ymm3;
-       vpxor 5 * 32(%rsi), %ymm2, %ymm2;
-       vpxor 6 * 32(%rsi), %ymm1, %ymm1;
-       vpxor 7 * 32(%rsi), %ymm0, %ymm0;
-       vpxor 8 * 32(%rsi), %ymm15, %ymm15;
-       vpxor 9 * 32(%rsi), %ymm14, %ymm14;
-       vpxor 10 * 32(%rsi), %ymm13, %ymm13;
-       vpxor 11 * 32(%rsi), %ymm12, %ymm12;
-       vpxor 12 * 32(%rsi), %ymm11, %ymm11;
-       vpxor 13 * 32(%rsi), %ymm10, %ymm10;
-       vpxor 14 * 32(%rsi), %ymm9, %ymm9;
-       vpxor 15 * 32(%rsi), %ymm8, %ymm8;
-
-       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
-                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
-                    %ymm8, %rsi);
-
-       vzeroall;
-
-       movq (16 * 32 + 0 * 8)(%rax), %r10;
-       movq (16 * 32 + 1 * 8)(%rax), %r11;
-       movq (16 * 32 + 2 * 8)(%rax), %r12;
-       movq (16 * 32 + 3 * 8)(%rax), %r13;
-
-       leave;
-       ret;
-ELF(.size _gcry_camellia_aesni_avx2_ocb_enc,.-_gcry_camellia_aesni_avx2_ocb_enc;)
-
-.align 8
-.globl _gcry_camellia_aesni_avx2_ocb_dec
-ELF(.type   _gcry_camellia_aesni_avx2_ocb_dec,@function;)
-
-_gcry_camellia_aesni_avx2_ocb_dec:
-       /* input:
-        *      %rdi: ctx, CTX
-        *      %rsi: dst (32 blocks)
-        *      %rdx: src (32 blocks)
-        *      %rcx: offset
-        *      %r8 : checksum
-        *      %r9 : L pointers (void *L[32])
-        */
-
-       pushq %rbp;
-       movq %rsp, %rbp;
-
-       vzeroupper;
-
-       subq $(16 * 32 + 4 * 8), %rsp;
-       andq $~63, %rsp;
-       movq %rsp, %rax;
-
-       movq %r10, (16 * 32 + 0 * 8)(%rax);
-       movq %r11, (16 * 32 + 1 * 8)(%rax);
-       movq %r12, (16 * 32 + 2 * 8)(%rax);
-       movq %r13, (16 * 32 + 3 * 8)(%rax);
-
-       vmovdqu (%rcx), %xmm14;
-
-       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
-
-#define OCB_INPUT(n, l0reg, l1reg, yreg) \
-         vmovdqu (n * 32)(%rdx), yreg; \
-         vpxor (l0reg), %xmm14, %xmm15; \
-         vpxor (l1reg), %xmm15, %xmm14; \
-         vinserti128 $1, %xmm14, %ymm15, %ymm15; \
-         vpxor yreg, %ymm15, yreg; \
-         vmovdqu %ymm15, (n * 32)(%rsi);
-
-       movq (0 * 8)(%r9), %r10;
-       movq (1 * 8)(%r9), %r11;
-       movq (2 * 8)(%r9), %r12;
-       movq (3 * 8)(%r9), %r13;
-       OCB_INPUT(0, %r10, %r11, %ymm0);
-       vmovdqu %ymm0, (15 * 32)(%rax);
-       OCB_INPUT(1, %r12, %r13, %ymm0);
-       vmovdqu %ymm0, (14 * 32)(%rax);
-       movq (4 * 8)(%r9), %r10;
-       movq (5 * 8)(%r9), %r11;
-       movq (6 * 8)(%r9), %r12;
-       movq (7 * 8)(%r9), %r13;
-       OCB_INPUT(2, %r10, %r11, %ymm13);
-       OCB_INPUT(3, %r12, %r13, %ymm12);
-       movq (8 * 8)(%r9), %r10;
-       movq (9 * 8)(%r9), %r11;
-       movq (10 * 8)(%r9), %r12;
-       movq (11 * 8)(%r9), %r13;
-       OCB_INPUT(4, %r10, %r11, %ymm11);
-       OCB_INPUT(5, %r12, %r13, %ymm10);
-       movq (12 * 8)(%r9), %r10;
-       movq (13 * 8)(%r9), %r11;
-       movq (14 * 8)(%r9), %r12;
-       movq (15 * 8)(%r9), %r13;
-       OCB_INPUT(6, %r10, %r11, %ymm9);
-       OCB_INPUT(7, %r12, %r13, %ymm8);
-       movq (16 * 8)(%r9), %r10;
-       movq (17 * 8)(%r9), %r11;
-       movq (18 * 8)(%r9), %r12;
-       movq (19 * 8)(%r9), %r13;
-       OCB_INPUT(8, %r10, %r11, %ymm7);
-       OCB_INPUT(9, %r12, %r13, %ymm6);
-       movq (20 * 8)(%r9), %r10;
-       movq (21 * 8)(%r9), %r11;
-       movq (22 * 8)(%r9), %r12;
-       movq (23 * 8)(%r9), %r13;
-       OCB_INPUT(10, %r10, %r11, %ymm5);
-       OCB_INPUT(11, %r12, %r13, %ymm4);
-       movq (24 * 8)(%r9), %r10;
-       movq (25 * 8)(%r9), %r11;
-       movq (26 * 8)(%r9), %r12;
-       movq (27 * 8)(%r9), %r13;
-       OCB_INPUT(12, %r10, %r11, %ymm3);
-       OCB_INPUT(13, %r12, %r13, %ymm2);
-       movq (28 * 8)(%r9), %r10;
-       movq (29 * 8)(%r9), %r11;
-       movq (30 * 8)(%r9), %r12;
-       movq (31 * 8)(%r9), %r13;
-       OCB_INPUT(14, %r10, %r11, %ymm1);
-       OCB_INPUT(15, %r12, %r13, %ymm0);
-#undef OCB_INPUT
-
-       vmovdqu %xmm14, (%rcx);
-
-       movq %r8, %r10;
-
-       cmpl $128, key_bitlength(CTX);
-       movl $32, %r8d;
-       movl $24, %r9d;
-       cmovel %r9d, %r8d; /* max */
-
-       /* inpack16_pre: */
-       vpbroadcastq (key_table)(CTX, %r8, 8), %ymm15;
-       vpshufb .Lpack_bswap RIP, %ymm15, %ymm15;
-       vpxor %ymm0, %ymm15, %ymm0;
-       vpxor %ymm1, %ymm15, %ymm1;
-       vpxor %ymm2, %ymm15, %ymm2;
-       vpxor %ymm3, %ymm15, %ymm3;
-       vpxor %ymm4, %ymm15, %ymm4;
-       vpxor %ymm5, %ymm15, %ymm5;
-       vpxor %ymm6, %ymm15, %ymm6;
-       vpxor %ymm7, %ymm15, %ymm7;
-       vpxor %ymm8, %ymm15, %ymm8;
-       vpxor %ymm9, %ymm15, %ymm9;
-       vpxor %ymm10, %ymm15, %ymm10;
-       vpxor %ymm11, %ymm15, %ymm11;
-       vpxor %ymm12, %ymm15, %ymm12;
-       vpxor %ymm13, %ymm15, %ymm13;
-       vpxor 14 * 32(%rax), %ymm15, %ymm14;
-       vpxor 15 * 32(%rax), %ymm15, %ymm15;
-
-       call __camellia_dec_blk32;
-
-       vpxor 0 * 32(%rsi), %ymm7, %ymm7;
-       vpxor 1 * 32(%rsi), %ymm6, %ymm6;
-       vpxor 2 * 32(%rsi), %ymm5, %ymm5;
-       vpxor 3 * 32(%rsi), %ymm4, %ymm4;
-       vpxor 4 * 32(%rsi), %ymm3, %ymm3;
-       vpxor 5 * 32(%rsi), %ymm2, %ymm2;
-       vpxor 6 * 32(%rsi), %ymm1, %ymm1;
-       vpxor 7 * 32(%rsi), %ymm0, %ymm0;
-       vmovdqu %ymm7, (7 * 32)(%rax);
-       vmovdqu %ymm6, (6 * 32)(%rax);
-       vpxor 8 * 32(%rsi), %ymm15, %ymm15;
-       vpxor 9 * 32(%rsi), %ymm14, %ymm14;
-       vpxor 10 * 32(%rsi), %ymm13, %ymm13;
-       vpxor 11 * 32(%rsi), %ymm12, %ymm12;
-       vpxor 12 * 32(%rsi), %ymm11, %ymm11;
-       vpxor 13 * 32(%rsi), %ymm10, %ymm10;
-       vpxor 14 * 32(%rsi), %ymm9, %ymm9;
-       vpxor 15 * 32(%rsi), %ymm8, %ymm8;
-
-       /* Checksum_i = Checksum_{i-1} xor P_i  */
-
-       vpxor %ymm5, %ymm7, %ymm7;
-       vpxor %ymm4, %ymm6, %ymm6;
-       vpxor %ymm3, %ymm7, %ymm7;
-       vpxor %ymm2, %ymm6, %ymm6;
-       vpxor %ymm1, %ymm7, %ymm7;
-       vpxor %ymm0, %ymm6, %ymm6;
-       vpxor %ymm15, %ymm7, %ymm7;
-       vpxor %ymm14, %ymm6, %ymm6;
-       vpxor %ymm13, %ymm7, %ymm7;
-       vpxor %ymm12, %ymm6, %ymm6;
-       vpxor %ymm11, %ymm7, %ymm7;
-       vpxor %ymm10, %ymm6, %ymm6;
-       vpxor %ymm9, %ymm7, %ymm7;
-       vpxor %ymm8, %ymm6, %ymm6;
-       vpxor %ymm7, %ymm6, %ymm7;
-
-       vextracti128 $1, %ymm7, %xmm6;
-       vpxor %xmm6, %xmm7, %xmm7;
-       vpxor (%r10), %xmm7, %xmm7;
-       vmovdqu %xmm7, (%r10);
-
-       vmovdqu 7 * 32(%rax), %ymm7;
-       vmovdqu 6 * 32(%rax), %ymm6;
-
-       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
-                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
-                    %ymm8, %rsi);
-
-       vzeroall;
-
-       movq (16 * 32 + 0 * 8)(%rax), %r10;
-       movq (16 * 32 + 1 * 8)(%rax), %r11;
-       movq (16 * 32 + 2 * 8)(%rax), %r12;
-       movq (16 * 32 + 3 * 8)(%rax), %r13;
-
-       leave;
-       ret;
-ELF(.size _gcry_camellia_aesni_avx2_ocb_dec,.-_gcry_camellia_aesni_avx2_ocb_dec;)
-
-.align 8
-.globl _gcry_camellia_aesni_avx2_ocb_auth
-ELF(.type   _gcry_camellia_aesni_avx2_ocb_auth,@function;)
-
-_gcry_camellia_aesni_avx2_ocb_auth:
-       /* input:
-        *      %rdi: ctx, CTX
-        *      %rsi: abuf (16 blocks)
-        *      %rdx: offset
-        *      %rcx: checksum
-        *      %r8 : L pointers (void *L[16])
-        */
-
-       pushq %rbp;
-       movq %rsp, %rbp;
-
-       vzeroupper;
-
-       subq $(16 * 32 + 4 * 8), %rsp;
-       andq $~63, %rsp;
-       movq %rsp, %rax;
-
-       movq %r10, (16 * 32 + 0 * 8)(%rax);
-       movq %r11, (16 * 32 + 1 * 8)(%rax);
-       movq %r12, (16 * 32 + 2 * 8)(%rax);
-       movq %r13, (16 * 32 + 3 * 8)(%rax);
-
-       vmovdqu (%rdx), %xmm14;
-
-       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-       /* Checksum_i = Checksum_{i-1} xor P_i  */
-       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
-
-#define OCB_INPUT(n, l0reg, l1reg, yreg) \
-         vmovdqu (n * 32)(%rsi), yreg; \
-         vpxor (l0reg), %xmm14, %xmm15; \
-         vpxor (l1reg), %xmm15, %xmm14; \
-         vinserti128 $1, %xmm14, %ymm15, %ymm15; \
-         vpxor yreg, %ymm15, yreg;
-
-       movq (0 * 8)(%r8), %r10;
-       movq (1 * 8)(%r8), %r11;
-       movq (2 * 8)(%r8), %r12;
-       movq (3 * 8)(%r8), %r13;
-       OCB_INPUT(0, %r10, %r11, %ymm0);
-       vmovdqu %ymm0, (15 * 32)(%rax);
-       OCB_INPUT(1, %r12, %r13, %ymm0);
-       vmovdqu %ymm0, (14 * 32)(%rax);
-       movq (4 * 8)(%r8), %r10;
-       movq (5 * 8)(%r8), %r11;
-       movq (6 * 8)(%r8), %r12;
-       movq (7 * 8)(%r8), %r13;
-       OCB_INPUT(2, %r10, %r11, %ymm13);
-       OCB_INPUT(3, %r12, %r13, %ymm12);
-       movq (8 * 8)(%r8), %r10;
-       movq (9 * 8)(%r8), %r11;
-       movq (10 * 8)(%r8), %r12;
-       movq (11 * 8)(%r8), %r13;
-       OCB_INPUT(4, %r10, %r11, %ymm11);
-       OCB_INPUT(5, %r12, %r13, %ymm10);
-       movq (12 * 8)(%r8), %r10;
-       movq (13 * 8)(%r8), %r11;
-       movq (14 * 8)(%r8), %r12;
-       movq (15 * 8)(%r8), %r13;
-       OCB_INPUT(6, %r10, %r11, %ymm9);
-       OCB_INPUT(7, %r12, %r13, %ymm8);
-       movq (16 * 8)(%r8), %r10;
-       movq (17 * 8)(%r8), %r11;
-       movq (18 * 8)(%r8), %r12;
-       movq (19 * 8)(%r8), %r13;
-       OCB_INPUT(8, %r10, %r11, %ymm7);
-       OCB_INPUT(9, %r12, %r13, %ymm6);
-       movq (20 * 8)(%r8), %r10;
-       movq (21 * 8)(%r8), %r11;
-       movq (22 * 8)(%r8), %r12;
-       movq (23 * 8)(%r8), %r13;
-       OCB_INPUT(10, %r10, %r11, %ymm5);
-       OCB_INPUT(11, %r12, %r13, %ymm4);
-       movq (24 * 8)(%r8), %r10;
-       movq (25 * 8)(%r8), %r11;
-       movq (26 * 8)(%r8), %r12;
-       movq (27 * 8)(%r8), %r13;
-       OCB_INPUT(12, %r10, %r11, %ymm3);
-       OCB_INPUT(13, %r12, %r13, %ymm2);
-       movq (28 * 8)(%r8), %r10;
-       movq (29 * 8)(%r8), %r11;
-       movq (30 * 8)(%r8), %r12;
-       movq (31 * 8)(%r8), %r13;
-       OCB_INPUT(14, %r10, %r11, %ymm1);
-       OCB_INPUT(15, %r12, %r13, %ymm0);
-#undef OCB_INPUT
-
-       vmovdqu %xmm14, (%rdx);
-
-       movq %rcx, %r10;
-
-       /* inpack16_pre: */
-       vpbroadcastq (key_table)(CTX), %ymm15;
-       vpshufb .Lpack_bswap RIP, %ymm15, %ymm15;
-       vpxor %ymm0, %ymm15, %ymm0;
-       vpxor %ymm1, %ymm15, %ymm1;
-       vpxor %ymm2, %ymm15, %ymm2;
-       vpxor %ymm3, %ymm15, %ymm3;
-       vpxor %ymm4, %ymm15, %ymm4;
-       vpxor %ymm5, %ymm15, %ymm5;
-       vpxor %ymm6, %ymm15, %ymm6;
-       vpxor %ymm7, %ymm15, %ymm7;
-       vpxor %ymm8, %ymm15, %ymm8;
-       vpxor %ymm9, %ymm15, %ymm9;
-       vpxor %ymm10, %ymm15, %ymm10;
-       vpxor %ymm11, %ymm15, %ymm11;
-       vpxor %ymm12, %ymm15, %ymm12;
-       vpxor %ymm13, %ymm15, %ymm13;
-       vpxor 14 * 32(%rax), %ymm15, %ymm14;
-       vpxor 15 * 32(%rax), %ymm15, %ymm15;
-
-       call __camellia_enc_blk32;
-
-       vpxor %ymm7, %ymm6, %ymm6;
-       vpxor %ymm5, %ymm4, %ymm4;
-       vpxor %ymm3, %ymm2, %ymm2;
-       vpxor %ymm1, %ymm0, %ymm0;
-       vpxor %ymm15, %ymm14, %ymm14;
-       vpxor %ymm13, %ymm12, %ymm12;
-       vpxor %ymm11, %ymm10, %ymm10;
-       vpxor %ymm9, %ymm8, %ymm8;
-
-       vpxor %ymm6, %ymm4, %ymm4;
-       vpxor %ymm2, %ymm0, %ymm0;
-       vpxor %ymm14, %ymm12, %ymm12;
-       vpxor %ymm10, %ymm8, %ymm8;
-
-       vpxor %ymm4, %ymm0, %ymm0;
-       vpxor %ymm12, %ymm8, %ymm8;
-
-       vpxor %ymm0, %ymm8, %ymm0;
-
-       vextracti128 $1, %ymm0, %xmm1;
-       vpxor (%r10), %xmm0, %xmm0;
-       vpxor %xmm0, %xmm1, %xmm0;
-       vmovdqu %xmm0, (%r10);
-
-       vzeroall;
-
-       movq (16 * 32 + 0 * 8)(%rax), %r10;
-       movq (16 * 32 + 1 * 8)(%rax), %r11;
-       movq (16 * 32 + 2 * 8)(%rax), %r12;
-       movq (16 * 32 + 3 * 8)(%rax), %r13;
+#undef CAMELLIA_VAES_BUILD
+#define FUNC_NAME(func) _gcry_camellia_aesni_avx2_ ## func
 
-       leave;
-       ret;
-ELF(.size _gcry_camellia_aesni_avx2_ocb_auth,.-_gcry_camellia_aesni_avx2_ocb_auth;)
+#include "camellia-aesni-avx2-amd64.h"
 
-#endif /*defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT)*/
-#endif /*__x86_64*/
+#endif /* defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT) */
+#endif /* __x86_64 */
diff --git a/cipher/camellia-aesni-avx2-amd64.h b/cipher/camellia-aesni-avx2-amd64.h
new file mode 100644 (file)
index 0000000..e93c40b
--- /dev/null
@@ -0,0 +1,1794 @@
+/* camellia-aesni-avx2-amd64.h - AES-NI/VAES/AVX2 implementation of Camellia
+ *
+ * Copyright (C) 2013-2015,2020-2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_CAMELLIA_AESNI_AVX2_AMD64_H
+#define GCRY_CAMELLIA_AESNI_AVX2_AMD64_H
+
+#include "asm-common-amd64.h"
+
+#define CAMELLIA_TABLE_BYTE_LEN 272
+
+/* struct CAMELLIA_context: */
+#define key_table 0
+#define key_bitlength CAMELLIA_TABLE_BYTE_LEN
+
+/* register macros */
+#define CTX %rdi
+#define RIO %r8
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+#define filter_8bit(x, lo_t, hi_t, mask4bit, tmp0) \
+       vpand x, mask4bit, tmp0; \
+       vpandn x, mask4bit, x; \
+       vpsrld $4, x, x; \
+       \
+       vpshufb tmp0, lo_t, tmp0; \
+       vpshufb x, hi_t, x; \
+       vpxor tmp0, x, x;
+
+#define ymm0_x xmm0
+#define ymm1_x xmm1
+#define ymm2_x xmm2
+#define ymm3_x xmm3
+#define ymm4_x xmm4
+#define ymm5_x xmm5
+#define ymm6_x xmm6
+#define ymm7_x xmm7
+#define ymm8_x xmm8
+#define ymm9_x xmm9
+#define ymm10_x xmm10
+#define ymm11_x xmm11
+#define ymm12_x xmm12
+#define ymm13_x xmm13
+#define ymm14_x xmm14
+#define ymm15_x xmm15
+
+#ifdef CAMELLIA_VAES_BUILD
+# define IF_AESNI(...)
+# define IF_VAES(...) __VA_ARGS__
+#else
+# define IF_AESNI(...) __VA_ARGS__
+# define IF_VAES(...)
+#endif
+
+/**********************************************************************
+  32-way camellia
+ **********************************************************************/
+
+/*
+ * IN:
+ *   x0..x7: byte-sliced AB state
+ *   mem_cd: register pointer storing CD state
+ *   key: index for key material
+ * OUT:
+ *   x0..x7: new byte-sliced CD state
+ */
+
+#define roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, t0, t1, t2, t3, t4, t5, \
+                 t6, t7, mem_cd, key) \
+       /* \
+        * S-function with AES subbytes \
+        */ \
+       vbroadcasti128 .Linv_shift_row rRIP, t4; \
+       vpbroadcastd .L0f0f0f0f rRIP, t7; \
+       vbroadcasti128 .Lpre_tf_lo_s1 rRIP, t5; \
+       vbroadcasti128 .Lpre_tf_hi_s1 rRIP, t6; \
+       vbroadcasti128 .Lpre_tf_lo_s4 rRIP, t2; \
+       vbroadcasti128 .Lpre_tf_hi_s4 rRIP, t3; \
+       \
+       /* AES inverse shift rows */ \
+       vpshufb t4, x0, x0; \
+       vpshufb t4, x7, x7; \
+       vpshufb t4, x3, x3; \
+       vpshufb t4, x6, x6; \
+       vpshufb t4, x2, x2; \
+       vpshufb t4, x5, x5; \
+       vpshufb t4, x1, x1; \
+       vpshufb t4, x4, x4; \
+       \
+       /* prefilter sboxes 1, 2 and 3 */ \
+       /* prefilter sbox 4 */ \
+       filter_8bit(x0, t5, t6, t7, t4); \
+       filter_8bit(x7, t5, t6, t7, t4); \
+       IF_AESNI(vextracti128 $1, x0, t0##_x); \
+       IF_AESNI(vextracti128 $1, x7, t1##_x); \
+       filter_8bit(x3, t2, t3, t7, t4); \
+       filter_8bit(x6, t2, t3, t7, t4); \
+       IF_AESNI(vextracti128 $1, x3, t3##_x); \
+       IF_AESNI(vextracti128 $1, x6, t2##_x); \
+       filter_8bit(x2, t5, t6, t7, t4); \
+       filter_8bit(x5, t5, t6, t7, t4); \
+       filter_8bit(x1, t5, t6, t7, t4); \
+       filter_8bit(x4, t5, t6, t7, t4); \
+       \
+       vpxor t4##_x, t4##_x, t4##_x; \
+       \
+       /* AES subbytes + AES shift rows */ \
+       IF_AESNI(vextracti128 $1, x2, t6##_x; \
+                vextracti128 $1, x5, t5##_x; \
+                vaesenclast t4##_x, x0##_x, x0##_x; \
+                vaesenclast t4##_x, t0##_x, t0##_x; \
+                vaesenclast t4##_x, x7##_x, x7##_x; \
+                vaesenclast t4##_x, t1##_x, t1##_x; \
+                vaesenclast t4##_x, x3##_x, x3##_x; \
+                vaesenclast t4##_x, t3##_x, t3##_x; \
+                vaesenclast t4##_x, x6##_x, x6##_x; \
+                vaesenclast t4##_x, t2##_x, t2##_x; \
+                vinserti128 $1, t0##_x, x0, x0; \
+                vinserti128 $1, t1##_x, x7, x7; \
+                vinserti128 $1, t3##_x, x3, x3; \
+                vinserti128 $1, t2##_x, x6, x6; \
+                vextracti128 $1, x1, t3##_x; \
+                vextracti128 $1, x4, t2##_x); \
+       vbroadcasti128 .Lpost_tf_lo_s1 rRIP, t0; \
+       vbroadcasti128 .Lpost_tf_hi_s1 rRIP, t1; \
+       IF_AESNI(vaesenclast t4##_x, x2##_x, x2##_x; \
+                vaesenclast t4##_x, t6##_x, t6##_x; \
+                vaesenclast t4##_x, x5##_x, x5##_x; \
+                vaesenclast t4##_x, t5##_x, t5##_x; \
+                vaesenclast t4##_x, x1##_x, x1##_x; \
+                vaesenclast t4##_x, t3##_x, t3##_x; \
+                vaesenclast t4##_x, x4##_x, x4##_x; \
+                vaesenclast t4##_x, t2##_x, t2##_x; \
+                vinserti128 $1, t6##_x, x2, x2; \
+                vinserti128 $1, t5##_x, x5, x5; \
+                vinserti128 $1, t3##_x, x1, x1; \
+                vinserti128 $1, t2##_x, x4, x4); \
+       IF_VAES(vaesenclast t4, x0, x0; \
+               vaesenclast t4, x7, x7; \
+               vaesenclast t4, x3, x3; \
+               vaesenclast t4, x6, x6; \
+               vaesenclast t4, x2, x2; \
+               vaesenclast t4, x5, x5; \
+               vaesenclast t4, x1, x1; \
+               vaesenclast t4, x4, x4); \
+       \
+       /* postfilter sboxes 1 and 4 */ \
+       vbroadcasti128 .Lpost_tf_lo_s3 rRIP, t2; \
+       vbroadcasti128 .Lpost_tf_hi_s3 rRIP, t3; \
+       filter_8bit(x0, t0, t1, t7, t4); \
+       filter_8bit(x7, t0, t1, t7, t4); \
+       filter_8bit(x3, t0, t1, t7, t6); \
+       filter_8bit(x6, t0, t1, t7, t6); \
+       \
+       /* postfilter sbox 3 */ \
+       vbroadcasti128 .Lpost_tf_lo_s2 rRIP, t4; \
+       vbroadcasti128 .Lpost_tf_hi_s2 rRIP, t5; \
+       filter_8bit(x2, t2, t3, t7, t6); \
+       filter_8bit(x5, t2, t3, t7, t6); \
+       \
+       vpbroadcastq key, t0; /* higher 64-bit duplicate ignored */ \
+       \
+       /* postfilter sbox 2 */ \
+       filter_8bit(x1, t4, t5, t7, t2); \
+       filter_8bit(x4, t4, t5, t7, t2); \
+       vpxor t7, t7, t7; \
+       \
+       vpsrldq $1, t0, t1; \
+       vpsrldq $2, t0, t2; \
+       vpshufb t7, t1, t1; \
+       vpsrldq $3, t0, t3; \
+       \
+       /* P-function */ \
+       vpxor x5, x0, x0; \
+       vpxor x6, x1, x1; \
+       vpxor x7, x2, x2; \
+       vpxor x4, x3, x3; \
+       \
+       vpshufb t7, t2, t2; \
+       vpsrldq $4, t0, t4; \
+       vpshufb t7, t3, t3; \
+       vpsrldq $5, t0, t5; \
+       vpshufb t7, t4, t4; \
+       \
+       vpxor x2, x4, x4; \
+       vpxor x3, x5, x5; \
+       vpxor x0, x6, x6; \
+       vpxor x1, x7, x7; \
+       \
+       vpsrldq $6, t0, t6; \
+       vpshufb t7, t5, t5; \
+       vpshufb t7, t6, t6; \
+       \
+       vpxor x7, x0, x0; \
+       vpxor x4, x1, x1; \
+       vpxor x5, x2, x2; \
+       vpxor x6, x3, x3; \
+       \
+       vpxor x3, x4, x4; \
+       vpxor x0, x5, x5; \
+       vpxor x1, x6, x6; \
+       vpxor x2, x7, x7; /* note: high and low parts swapped */ \
+       \
+       /* Add key material and result to CD (x becomes new CD) */ \
+       \
+       vpxor t6, x1, x1; \
+       vpxor 5 * 32(mem_cd), x1, x1; \
+       \
+       vpsrldq $7, t0, t6; \
+       vpshufb t7, t0, t0; \
+       vpshufb t7, t6, t7; \
+       \
+       vpxor t7, x0, x0; \
+       vpxor 4 * 32(mem_cd), x0, x0; \
+       \
+       vpxor t5, x2, x2; \
+       vpxor 6 * 32(mem_cd), x2, x2; \
+       \
+       vpxor t4, x3, x3; \
+       vpxor 7 * 32(mem_cd), x3, x3; \
+       \
+       vpxor t3, x4, x4; \
+       vpxor 0 * 32(mem_cd), x4, x4; \
+       \
+       vpxor t2, x5, x5; \
+       vpxor 1 * 32(mem_cd), x5, x5; \
+       \
+       vpxor t1, x6, x6; \
+       vpxor 2 * 32(mem_cd), x6, x6; \
+       \
+       vpxor t0, x7, x7; \
+       vpxor 3 * 32(mem_cd), x7, x7;
+
+/*
+ * IN/OUT:
+ *  x0..x7: byte-sliced AB state preloaded
+ *  mem_ab: byte-sliced AB state in memory
+ *  mem_cb: byte-sliced CD state in memory
+ */
+#define two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, i, dir, store_ab) \
+       roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                 y6, y7, mem_cd, (key_table + (i) * 8)(CTX)); \
+       \
+       vmovdqu x0, 4 * 32(mem_cd); \
+       vmovdqu x1, 5 * 32(mem_cd); \
+       vmovdqu x2, 6 * 32(mem_cd); \
+       vmovdqu x3, 7 * 32(mem_cd); \
+       vmovdqu x4, 0 * 32(mem_cd); \
+       vmovdqu x5, 1 * 32(mem_cd); \
+       vmovdqu x6, 2 * 32(mem_cd); \
+       vmovdqu x7, 3 * 32(mem_cd); \
+       \
+       roundsm32(x4, x5, x6, x7, x0, x1, x2, x3, y0, y1, y2, y3, y4, y5, \
+                 y6, y7, mem_ab, (key_table + ((i) + (dir)) * 8)(CTX)); \
+       \
+       store_ab(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab);
+
+#define dummy_store(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) /* do nothing */
+
+#define store_ab_state(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) \
+       /* Store new AB state */ \
+       vmovdqu x4, 4 * 32(mem_ab); \
+       vmovdqu x5, 5 * 32(mem_ab); \
+       vmovdqu x6, 6 * 32(mem_ab); \
+       vmovdqu x7, 7 * 32(mem_ab); \
+       vmovdqu x0, 0 * 32(mem_ab); \
+       vmovdqu x1, 1 * 32(mem_ab); \
+       vmovdqu x2, 2 * 32(mem_ab); \
+       vmovdqu x3, 3 * 32(mem_ab);
+
+#define enc_rounds32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, i) \
+       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 2, 1, store_ab_state); \
+       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 4, 1, store_ab_state); \
+       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 6, 1, dummy_store);
+
+#define dec_rounds32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, i) \
+       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 7, -1, store_ab_state); \
+       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 5, -1, store_ab_state); \
+       two_roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd, (i) + 3, -1, dummy_store);
+
+/*
+ * IN:
+ *  v0..3: byte-sliced 32-bit integers
+ * OUT:
+ *  v0..3: (IN <<< 1)
+ */
+#define rol32_1_32(v0, v1, v2, v3, t0, t1, t2, zero) \
+       vpcmpgtb v0, zero, t0; \
+       vpaddb v0, v0, v0; \
+       vpabsb t0, t0; \
+       \
+       vpcmpgtb v1, zero, t1; \
+       vpaddb v1, v1, v1; \
+       vpabsb t1, t1; \
+       \
+       vpcmpgtb v2, zero, t2; \
+       vpaddb v2, v2, v2; \
+       vpabsb t2, t2; \
+       \
+       vpor t0, v1, v1; \
+       \
+       vpcmpgtb v3, zero, t0; \
+       vpaddb v3, v3, v3; \
+       vpabsb t0, t0; \
+       \
+       vpor t1, v2, v2; \
+       vpor t2, v3, v3; \
+       vpor t0, v0, v0;
+
+/*
+ * IN:
+ *   r: byte-sliced AB state in memory
+ *   l: byte-sliced CD state in memory
+ * OUT:
+ *   x0..x7: new byte-sliced CD state
+ */
+#define fls32(l, l0, l1, l2, l3, l4, l5, l6, l7, r, t0, t1, t2, t3, tt0, \
+             tt1, tt2, tt3, kll, klr, krl, krr) \
+       /* \
+        * t0 = kll; \
+        * t0 &= ll; \
+        * lr ^= rol32(t0, 1); \
+        */ \
+       vpbroadcastd kll, t0; /* only lowest 32-bit used */ \
+       vpxor tt0, tt0, tt0; \
+       vpshufb tt0, t0, t3; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t2; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t1; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t0; \
+       \
+       vpand l0, t0, t0; \
+       vpand l1, t1, t1; \
+       vpand l2, t2, t2; \
+       vpand l3, t3, t3; \
+       \
+       rol32_1_32(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
+       \
+       vpxor l4, t0, l4; \
+       vpbroadcastd krr, t0; /* only lowest 32-bit used */ \
+       vmovdqu l4, 4 * 32(l); \
+       vpxor l5, t1, l5; \
+       vmovdqu l5, 5 * 32(l); \
+       vpxor l6, t2, l6; \
+       vmovdqu l6, 6 * 32(l); \
+       vpxor l7, t3, l7; \
+       vmovdqu l7, 7 * 32(l); \
+       \
+       /* \
+        * t2 = krr; \
+        * t2 |= rr; \
+        * rl ^= t2; \
+        */ \
+       \
+       vpshufb tt0, t0, t3; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t2; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t1; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t0; \
+       \
+       vpor 4 * 32(r), t0, t0; \
+       vpor 5 * 32(r), t1, t1; \
+       vpor 6 * 32(r), t2, t2; \
+       vpor 7 * 32(r), t3, t3; \
+       \
+       vpxor 0 * 32(r), t0, t0; \
+       vpxor 1 * 32(r), t1, t1; \
+       vpxor 2 * 32(r), t2, t2; \
+       vpxor 3 * 32(r), t3, t3; \
+       vmovdqu t0, 0 * 32(r); \
+       vpbroadcastd krl, t0; /* only lowest 32-bit used */ \
+       vmovdqu t1, 1 * 32(r); \
+       vmovdqu t2, 2 * 32(r); \
+       vmovdqu t3, 3 * 32(r); \
+       \
+       /* \
+        * t2 = krl; \
+        * t2 &= rl; \
+        * rr ^= rol32(t2, 1); \
+        */ \
+       vpshufb tt0, t0, t3; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t2; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t1; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t0; \
+       \
+       vpand 0 * 32(r), t0, t0; \
+       vpand 1 * 32(r), t1, t1; \
+       vpand 2 * 32(r), t2, t2; \
+       vpand 3 * 32(r), t3, t3; \
+       \
+       rol32_1_32(t3, t2, t1, t0, tt1, tt2, tt3, tt0); \
+       \
+       vpxor 4 * 32(r), t0, t0; \
+       vpxor 5 * 32(r), t1, t1; \
+       vpxor 6 * 32(r), t2, t2; \
+       vpxor 7 * 32(r), t3, t3; \
+       vmovdqu t0, 4 * 32(r); \
+       vpbroadcastd klr, t0; /* only lowest 32-bit used */ \
+       vmovdqu t1, 5 * 32(r); \
+       vmovdqu t2, 6 * 32(r); \
+       vmovdqu t3, 7 * 32(r); \
+       \
+       /* \
+        * t0 = klr; \
+        * t0 |= lr; \
+        * ll ^= t0; \
+        */ \
+       \
+       vpshufb tt0, t0, t3; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t2; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t1; \
+       vpsrldq $1, t0, t0; \
+       vpshufb tt0, t0, t0; \
+       \
+       vpor l4, t0, t0; \
+       vpor l5, t1, t1; \
+       vpor l6, t2, t2; \
+       vpor l7, t3, t3; \
+       \
+       vpxor l0, t0, l0; \
+       vmovdqu l0, 0 * 32(l); \
+       vpxor l1, t1, l1; \
+       vmovdqu l1, 1 * 32(l); \
+       vpxor l2, t2, l2; \
+       vmovdqu l2, 2 * 32(l); \
+       vpxor l3, t3, l3; \
+       vmovdqu l3, 3 * 32(l);
+
+#define transpose_4x4(x0, x1, x2, x3, t1, t2) \
+       vpunpckhdq x1, x0, t2; \
+       vpunpckldq x1, x0, x0; \
+       \
+       vpunpckldq x3, x2, t1; \
+       vpunpckhdq x3, x2, x2; \
+       \
+       vpunpckhqdq t1, x0, x1; \
+       vpunpcklqdq t1, x0, x0; \
+       \
+       vpunpckhqdq x2, t2, x3; \
+       vpunpcklqdq x2, t2, x2;
+
+#define byteslice_16x16b_fast(a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, d2, \
+                             a3, b3, c3, d3, st0, st1) \
+       vmovdqu d2, st0; \
+       vmovdqu d3, st1; \
+       transpose_4x4(a0, a1, a2, a3, d2, d3); \
+       transpose_4x4(b0, b1, b2, b3, d2, d3); \
+       vmovdqu st0, d2; \
+       vmovdqu st1, d3; \
+       \
+       vmovdqu a0, st0; \
+       vmovdqu a1, st1; \
+       transpose_4x4(c0, c1, c2, c3, a0, a1); \
+       transpose_4x4(d0, d1, d2, d3, a0, a1); \
+       \
+       vbroadcasti128 .Lshufb_16x16b rRIP, a0; \
+       vmovdqu st1, a1; \
+       vpshufb a0, a2, a2; \
+       vpshufb a0, a3, a3; \
+       vpshufb a0, b0, b0; \
+       vpshufb a0, b1, b1; \
+       vpshufb a0, b2, b2; \
+       vpshufb a0, b3, b3; \
+       vpshufb a0, a1, a1; \
+       vpshufb a0, c0, c0; \
+       vpshufb a0, c1, c1; \
+       vpshufb a0, c2, c2; \
+       vpshufb a0, c3, c3; \
+       vpshufb a0, d0, d0; \
+       vpshufb a0, d1, d1; \
+       vpshufb a0, d2, d2; \
+       vpshufb a0, d3, d3; \
+       vmovdqu d3, st1; \
+       vmovdqu st0, d3; \
+       vpshufb a0, d3, a0; \
+       vmovdqu d2, st0; \
+       \
+       transpose_4x4(a0, b0, c0, d0, d2, d3); \
+       transpose_4x4(a1, b1, c1, d1, d2, d3); \
+       vmovdqu st0, d2; \
+       vmovdqu st1, d3; \
+       \
+       vmovdqu b0, st0; \
+       vmovdqu b1, st1; \
+       transpose_4x4(a2, b2, c2, d2, b0, b1); \
+       transpose_4x4(a3, b3, c3, d3, b0, b1); \
+       vmovdqu st0, b0; \
+       vmovdqu st1, b1; \
+       /* does not adjust output bytes inside vectors */
+
+/* load blocks to registers and apply pre-whitening */
+#define inpack32_pre(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                    y6, y7, rio, key) \
+       vpbroadcastq key, x0; \
+       vpshufb .Lpack_bswap rRIP, x0, x0; \
+       \
+       vpxor 0 * 32(rio), x0, y7; \
+       vpxor 1 * 32(rio), x0, y6; \
+       vpxor 2 * 32(rio), x0, y5; \
+       vpxor 3 * 32(rio), x0, y4; \
+       vpxor 4 * 32(rio), x0, y3; \
+       vpxor 5 * 32(rio), x0, y2; \
+       vpxor 6 * 32(rio), x0, y1; \
+       vpxor 7 * 32(rio), x0, y0; \
+       vpxor 8 * 32(rio), x0, x7; \
+       vpxor 9 * 32(rio), x0, x6; \
+       vpxor 10 * 32(rio), x0, x5; \
+       vpxor 11 * 32(rio), x0, x4; \
+       vpxor 12 * 32(rio), x0, x3; \
+       vpxor 13 * 32(rio), x0, x2; \
+       vpxor 14 * 32(rio), x0, x1; \
+       vpxor 15 * 32(rio), x0, x0;
+
+/* byteslice pre-whitened blocks and store to temporary memory */
+#define inpack32_post(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                     y6, y7, mem_ab, mem_cd) \
+       byteslice_16x16b_fast(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, \
+                             y4, y5, y6, y7, (mem_ab), (mem_cd)); \
+       \
+       vmovdqu x0, 0 * 32(mem_ab); \
+       vmovdqu x1, 1 * 32(mem_ab); \
+       vmovdqu x2, 2 * 32(mem_ab); \
+       vmovdqu x3, 3 * 32(mem_ab); \
+       vmovdqu x4, 4 * 32(mem_ab); \
+       vmovdqu x5, 5 * 32(mem_ab); \
+       vmovdqu x6, 6 * 32(mem_ab); \
+       vmovdqu x7, 7 * 32(mem_ab); \
+       vmovdqu y0, 0 * 32(mem_cd); \
+       vmovdqu y1, 1 * 32(mem_cd); \
+       vmovdqu y2, 2 * 32(mem_cd); \
+       vmovdqu y3, 3 * 32(mem_cd); \
+       vmovdqu y4, 4 * 32(mem_cd); \
+       vmovdqu y5, 5 * 32(mem_cd); \
+       vmovdqu y6, 6 * 32(mem_cd); \
+       vmovdqu y7, 7 * 32(mem_cd);
+
+/* de-byteslice, apply post-whitening and store blocks */
+#define outunpack32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, \
+                   y5, y6, y7, key, stack_tmp0, stack_tmp1) \
+       byteslice_16x16b_fast(y0, y4, x0, x4, y1, y5, x1, x5, y2, y6, x2, x6, \
+                             y3, y7, x3, x7, stack_tmp0, stack_tmp1); \
+       \
+       vmovdqu x0, stack_tmp0; \
+       \
+       vpbroadcastq key, x0; \
+       vpshufb .Lpack_bswap rRIP, x0, x0; \
+       \
+       vpxor x0, y7, y7; \
+       vpxor x0, y6, y6; \
+       vpxor x0, y5, y5; \
+       vpxor x0, y4, y4; \
+       vpxor x0, y3, y3; \
+       vpxor x0, y2, y2; \
+       vpxor x0, y1, y1; \
+       vpxor x0, y0, y0; \
+       vpxor x0, x7, x7; \
+       vpxor x0, x6, x6; \
+       vpxor x0, x5, x5; \
+       vpxor x0, x4, x4; \
+       vpxor x0, x3, x3; \
+       vpxor x0, x2, x2; \
+       vpxor x0, x1, x1; \
+       vpxor stack_tmp0, x0, x0;
+
+#define write_output(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \
+                    y6, y7, rio) \
+       vmovdqu x0, 0 * 32(rio); \
+       vmovdqu x1, 1 * 32(rio); \
+       vmovdqu x2, 2 * 32(rio); \
+       vmovdqu x3, 3 * 32(rio); \
+       vmovdqu x4, 4 * 32(rio); \
+       vmovdqu x5, 5 * 32(rio); \
+       vmovdqu x6, 6 * 32(rio); \
+       vmovdqu x7, 7 * 32(rio); \
+       vmovdqu y0, 8 * 32(rio); \
+       vmovdqu y1, 9 * 32(rio); \
+       vmovdqu y2, 10 * 32(rio); \
+       vmovdqu y3, 11 * 32(rio); \
+       vmovdqu y4, 12 * 32(rio); \
+       vmovdqu y5, 13 * 32(rio); \
+       vmovdqu y6, 14 * 32(rio); \
+       vmovdqu y7, 15 * 32(rio);
+
+.text
+.align 32
+
+#define SHUFB_BYTES(idx) \
+       0 + (idx), 4 + (idx), 8 + (idx), 12 + (idx)
+
+.Lshufb_16x16b:
+       .byte SHUFB_BYTES(0), SHUFB_BYTES(1), SHUFB_BYTES(2), SHUFB_BYTES(3)
+       .byte SHUFB_BYTES(0), SHUFB_BYTES(1), SHUFB_BYTES(2), SHUFB_BYTES(3)
+
+.Lpack_bswap:
+       .long 0x00010203, 0x04050607, 0x80808080, 0x80808080
+       .long 0x00010203, 0x04050607, 0x80808080, 0x80808080
+
+/* For CTR-mode IV byteswap */
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
+/*
+ * pre-SubByte transform
+ *
+ * pre-lookup for sbox1, sbox2, sbox3:
+ *   swap_bitendianness(
+ *       isom_map_camellia_to_aes(
+ *           camellia_f(
+ *               swap_bitendianess(in)
+ *           )
+ *       )
+ *   )
+ *
+ * (note: '⊕ 0xc5' inside camellia_f())
+ */
+.Lpre_tf_lo_s1:
+       .byte 0x45, 0xe8, 0x40, 0xed, 0x2e, 0x83, 0x2b, 0x86
+       .byte 0x4b, 0xe6, 0x4e, 0xe3, 0x20, 0x8d, 0x25, 0x88
+.Lpre_tf_hi_s1:
+       .byte 0x00, 0x51, 0xf1, 0xa0, 0x8a, 0xdb, 0x7b, 0x2a
+       .byte 0x09, 0x58, 0xf8, 0xa9, 0x83, 0xd2, 0x72, 0x23
+
+/*
+ * pre-SubByte transform
+ *
+ * pre-lookup for sbox4:
+ *   swap_bitendianness(
+ *       isom_map_camellia_to_aes(
+ *           camellia_f(
+ *               swap_bitendianess(in <<< 1)
+ *           )
+ *       )
+ *   )
+ *
+ * (note: '⊕ 0xc5' inside camellia_f())
+ */
+.Lpre_tf_lo_s4:
+       .byte 0x45, 0x40, 0x2e, 0x2b, 0x4b, 0x4e, 0x20, 0x25
+       .byte 0x14, 0x11, 0x7f, 0x7a, 0x1a, 0x1f, 0x71, 0x74
+.Lpre_tf_hi_s4:
+       .byte 0x00, 0xf1, 0x8a, 0x7b, 0x09, 0xf8, 0x83, 0x72
+       .byte 0xad, 0x5c, 0x27, 0xd6, 0xa4, 0x55, 0x2e, 0xdf
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox1, sbox4:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  )
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s1:
+       .byte 0x3c, 0xcc, 0xcf, 0x3f, 0x32, 0xc2, 0xc1, 0x31
+       .byte 0xdc, 0x2c, 0x2f, 0xdf, 0xd2, 0x22, 0x21, 0xd1
+.Lpost_tf_hi_s1:
+       .byte 0x00, 0xf9, 0x86, 0x7f, 0xd7, 0x2e, 0x51, 0xa8
+       .byte 0xa4, 0x5d, 0x22, 0xdb, 0x73, 0x8a, 0xf5, 0x0c
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox2:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  ) <<< 1
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s2:
+       .byte 0x78, 0x99, 0x9f, 0x7e, 0x64, 0x85, 0x83, 0x62
+       .byte 0xb9, 0x58, 0x5e, 0xbf, 0xa5, 0x44, 0x42, 0xa3
+.Lpost_tf_hi_s2:
+       .byte 0x00, 0xf3, 0x0d, 0xfe, 0xaf, 0x5c, 0xa2, 0x51
+       .byte 0x49, 0xba, 0x44, 0xb7, 0xe6, 0x15, 0xeb, 0x18
+
+/*
+ * post-SubByte transform
+ *
+ * post-lookup for sbox3:
+ *  swap_bitendianness(
+ *      camellia_h(
+ *          isom_map_aes_to_camellia(
+ *              swap_bitendianness(
+ *                  aes_inverse_affine_transform(in)
+ *              )
+ *          )
+ *      )
+ *  ) >>> 1
+ *
+ * (note: '⊕ 0x6e' inside camellia_h())
+ */
+.Lpost_tf_lo_s3:
+       .byte 0x1e, 0x66, 0xe7, 0x9f, 0x19, 0x61, 0xe0, 0x98
+       .byte 0x6e, 0x16, 0x97, 0xef, 0x69, 0x11, 0x90, 0xe8
+.Lpost_tf_hi_s3:
+       .byte 0x00, 0xfc, 0x43, 0xbf, 0xeb, 0x17, 0xa8, 0x54
+       .byte 0x52, 0xae, 0x11, 0xed, 0xb9, 0x45, 0xfa, 0x06
+
+/* For isolating SubBytes from AESENCLAST, inverse shift row */
+.Linv_shift_row:
+       .byte 0x00, 0x0d, 0x0a, 0x07, 0x04, 0x01, 0x0e, 0x0b
+       .byte 0x08, 0x05, 0x02, 0x0f, 0x0c, 0x09, 0x06, 0x03
+
+.align 4
+/* 4-bit mask */
+.L0f0f0f0f:
+       .long 0x0f0f0f0f
+
+
+.align 8
+ELF(.type   __camellia_enc_blk32,@function;)
+
+__camellia_enc_blk32:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rax: temporary storage, 512 bytes
+        *      %r8d: 24 for 16 byte key, 32 for larger
+        *      %ymm0..%ymm15: 32 plaintext blocks
+        * output:
+        *      %ymm0..%ymm15: 32 encrypted blocks, order swapped:
+        *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
+        */
+       CFI_STARTPROC();
+
+       leaq 8 * 32(%rax), %rcx;
+
+       leaq (-8 * 8)(CTX, %r8, 8), %r8;
+
+       inpack32_post(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+                     %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+                     %ymm15, %rax, %rcx);
+
+.align 8
+.Lenc_loop:
+       enc_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+                    %ymm15, %rax, %rcx, 0);
+
+       cmpq %r8, CTX;
+       je .Lenc_done;
+       leaq (8 * 8)(CTX), CTX;
+
+       fls32(%rax, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+             %rcx, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+             %ymm15,
+             ((key_table) + 0)(CTX),
+             ((key_table) + 4)(CTX),
+             ((key_table) + 8)(CTX),
+             ((key_table) + 12)(CTX));
+       jmp .Lenc_loop;
+
+.align 8
+.Lenc_done:
+       /* load CD for output */
+       vmovdqu 0 * 32(%rcx), %ymm8;
+       vmovdqu 1 * 32(%rcx), %ymm9;
+       vmovdqu 2 * 32(%rcx), %ymm10;
+       vmovdqu 3 * 32(%rcx), %ymm11;
+       vmovdqu 4 * 32(%rcx), %ymm12;
+       vmovdqu 5 * 32(%rcx), %ymm13;
+       vmovdqu 6 * 32(%rcx), %ymm14;
+       vmovdqu 7 * 32(%rcx), %ymm15;
+
+       outunpack32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+                   %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+                   %ymm15, ((key_table) + 8 * 8)(%r8), (%rax), 1 * 32(%rax));
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size __camellia_enc_blk32,.-__camellia_enc_blk32;)
+
+.align 8
+ELF(.type   __camellia_dec_blk32,@function;)
+
+__camellia_dec_blk32:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rax: temporary storage, 512 bytes
+        *      %r8d: 24 for 16 byte key, 32 for larger
+        *      %ymm0..%ymm15: 16 encrypted blocks
+        * output:
+        *      %ymm0..%ymm15: 16 plaintext blocks, order swapped:
+        *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
+        */
+       CFI_STARTPROC();
+
+       movq %r8, %rcx;
+       movq CTX, %r8
+       leaq (-8 * 8)(CTX, %rcx, 8), CTX;
+
+       leaq 8 * 32(%rax), %rcx;
+
+       inpack32_post(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+                     %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+                     %ymm15, %rax, %rcx);
+
+.align 8
+.Ldec_loop:
+       dec_rounds32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+                    %ymm15, %rax, %rcx, 0);
+
+       cmpq %r8, CTX;
+       je .Ldec_done;
+
+       fls32(%rax, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+             %rcx, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+             %ymm15,
+             ((key_table) + 8)(CTX),
+             ((key_table) + 12)(CTX),
+             ((key_table) + 0)(CTX),
+             ((key_table) + 4)(CTX));
+
+       leaq (-8 * 8)(CTX), CTX;
+       jmp .Ldec_loop;
+
+.align 8
+.Ldec_done:
+       /* load CD for output */
+       vmovdqu 0 * 32(%rcx), %ymm8;
+       vmovdqu 1 * 32(%rcx), %ymm9;
+       vmovdqu 2 * 32(%rcx), %ymm10;
+       vmovdqu 3 * 32(%rcx), %ymm11;
+       vmovdqu 4 * 32(%rcx), %ymm12;
+       vmovdqu 5 * 32(%rcx), %ymm13;
+       vmovdqu 6 * 32(%rcx), %ymm14;
+       vmovdqu 7 * 32(%rcx), %ymm15;
+
+       outunpack32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+                   %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+                   %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax));
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size __camellia_dec_blk32,.-__camellia_dec_blk32;)
+
+#define inc_le128(x, minus_one, tmp) \
+       vpcmpeqq minus_one, x, tmp; \
+       vpsubq minus_one, x, x; \
+       vpslldq $8, tmp, tmp; \
+       vpsubq tmp, x, x;
+
+.align 8
+.globl FUNC_NAME(ctr_enc)
+ELF(.type   FUNC_NAME(ctr_enc),@function;)
+
+FUNC_NAME(ctr_enc):
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (32 blocks)
+        *      %rdx: src (32 blocks)
+        *      %rcx: iv (big endian, 128bit)
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       movq 8(%rcx), %r11;
+       bswapq %r11;
+
+       vzeroupper;
+
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %eax;
+       cmovel %eax, %r8d; /* max */
+
+       subq $(16 * 32), %rsp;
+       andq $~63, %rsp;
+       movq %rsp, %rax;
+
+       vpcmpeqd %ymm15, %ymm15, %ymm15;
+       vpsrldq $8, %ymm15, %ymm15; /* ab: -1:0 ; cd: -1:0 */
+
+       /* load IV and byteswap */
+       vmovdqu (%rcx), %xmm0;
+       vpshufb .Lbswap128_mask rRIP, %xmm0, %xmm0;
+       vmovdqa %xmm0, %xmm1;
+       inc_le128(%xmm0, %xmm15, %xmm14);
+       vbroadcasti128 .Lbswap128_mask rRIP, %ymm14;
+       vinserti128 $1, %xmm0, %ymm1, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm13;
+       vmovdqu %ymm13, 15 * 32(%rax);
+
+       /* check need for handling 64-bit overflow and carry */
+       cmpq $(0xffffffffffffffff - 32), %r11;
+       ja .Lload_ctr_carry;
+
+       /* construct IVs */
+       vpaddq %ymm15, %ymm15, %ymm15; /* ab: -2:0 ; cd: -2:0 */
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm13;
+       vmovdqu %ymm13, 14 * 32(%rax);
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm13;
+       vmovdqu %ymm13, 13 * 32(%rax);
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm12;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm11;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm10;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm9;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm8;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm7;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm6;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm5;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm4;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm3;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm2;
+       vpsubq %ymm15, %ymm0, %ymm0;
+       vpshufb %ymm14, %ymm0, %ymm1;
+       vpsubq %ymm15, %ymm0, %ymm0;  /* +30 ; +31 */
+       vpsubq %xmm15, %xmm0, %xmm13; /* +32 */
+       vpshufb %ymm14, %ymm0, %ymm0;
+       vpshufb %xmm14, %xmm13, %xmm13;
+       vmovdqu %xmm13, (%rcx);
+
+       jmp .Lload_ctr_done;
+
+.align 4
+.Lload_ctr_carry:
+       /* construct IVs */
+       inc_le128(%ymm0, %ymm15, %ymm13); /* ab: le1 ; cd: le2 */
+       inc_le128(%ymm0, %ymm15, %ymm13); /* ab: le2 ; cd: le3 */
+       vpshufb %ymm14, %ymm0, %ymm13;
+       vmovdqu %ymm13, 14 * 32(%rax);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm13;
+       vmovdqu %ymm13, 13 * 32(%rax);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm12;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm11;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm10;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm9;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm8;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm7;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm6;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm5;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm4;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm3;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm2;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vpshufb %ymm14, %ymm0, %ymm1;
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       inc_le128(%ymm0, %ymm15, %ymm13);
+       vextracti128 $1, %ymm0, %xmm13;
+       vpshufb %ymm14, %ymm0, %ymm0;
+       inc_le128(%xmm13, %xmm15, %xmm14);
+       vpshufb .Lbswap128_mask rRIP, %xmm13, %xmm13;
+       vmovdqu %xmm13, (%rcx);
+
+.align 4
+.Lload_ctr_done:
+       /* inpack16_pre: */
+       vpbroadcastq (key_table)(CTX), %ymm15;
+       vpshufb .Lpack_bswap rRIP, %ymm15, %ymm15;
+       vpxor %ymm0, %ymm15, %ymm0;
+       vpxor %ymm1, %ymm15, %ymm1;
+       vpxor %ymm2, %ymm15, %ymm2;
+       vpxor %ymm3, %ymm15, %ymm3;
+       vpxor %ymm4, %ymm15, %ymm4;
+       vpxor %ymm5, %ymm15, %ymm5;
+       vpxor %ymm6, %ymm15, %ymm6;
+       vpxor %ymm7, %ymm15, %ymm7;
+       vpxor %ymm8, %ymm15, %ymm8;
+       vpxor %ymm9, %ymm15, %ymm9;
+       vpxor %ymm10, %ymm15, %ymm10;
+       vpxor %ymm11, %ymm15, %ymm11;
+       vpxor %ymm12, %ymm15, %ymm12;
+       vpxor 13 * 32(%rax), %ymm15, %ymm13;
+       vpxor 14 * 32(%rax), %ymm15, %ymm14;
+       vpxor 15 * 32(%rax), %ymm15, %ymm15;
+
+       call __camellia_enc_blk32;
+
+       vpxor 0 * 32(%rdx), %ymm7, %ymm7;
+       vpxor 1 * 32(%rdx), %ymm6, %ymm6;
+       vpxor 2 * 32(%rdx), %ymm5, %ymm5;
+       vpxor 3 * 32(%rdx), %ymm4, %ymm4;
+       vpxor 4 * 32(%rdx), %ymm3, %ymm3;
+       vpxor 5 * 32(%rdx), %ymm2, %ymm2;
+       vpxor 6 * 32(%rdx), %ymm1, %ymm1;
+       vpxor 7 * 32(%rdx), %ymm0, %ymm0;
+       vpxor 8 * 32(%rdx), %ymm15, %ymm15;
+       vpxor 9 * 32(%rdx), %ymm14, %ymm14;
+       vpxor 10 * 32(%rdx), %ymm13, %ymm13;
+       vpxor 11 * 32(%rdx), %ymm12, %ymm12;
+       vpxor 12 * 32(%rdx), %ymm11, %ymm11;
+       vpxor 13 * 32(%rdx), %ymm10, %ymm10;
+       vpxor 14 * 32(%rdx), %ymm9, %ymm9;
+       vpxor 15 * 32(%rdx), %ymm8, %ymm8;
+       leaq 32 * 16(%rdx), %rdx;
+
+       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
+                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
+                    %ymm8, %rsi);
+
+       vzeroall;
+
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size FUNC_NAME(ctr_enc),.-FUNC_NAME(ctr_enc);)
+
+.align 8
+.globl FUNC_NAME(cbc_dec)
+ELF(.type   FUNC_NAME(cbc_dec),@function;)
+
+FUNC_NAME(cbc_dec):
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (32 blocks)
+        *      %rdx: src (32 blocks)
+        *      %rcx: iv
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       vzeroupper;
+
+       movq %rcx, %r9;
+
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %eax;
+       cmovel %eax, %r8d; /* max */
+
+       subq $(16 * 32), %rsp;
+       andq $~63, %rsp;
+       movq %rsp, %rax;
+
+       inpack32_pre(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7,
+                    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
+                    %ymm15, %rdx, (key_table)(CTX, %r8, 8));
+
+       call __camellia_dec_blk32;
+
+       /* XOR output with IV */
+       vmovdqu %ymm8, (%rax);
+       vmovdqu (%r9), %xmm8;
+       vinserti128 $1, (%rdx), %ymm8, %ymm8;
+       vpxor %ymm8, %ymm7, %ymm7;
+       vmovdqu (%rax), %ymm8;
+       vpxor (0 * 32 + 16)(%rdx), %ymm6, %ymm6;
+       vpxor (1 * 32 + 16)(%rdx), %ymm5, %ymm5;
+       vpxor (2 * 32 + 16)(%rdx), %ymm4, %ymm4;
+       vpxor (3 * 32 + 16)(%rdx), %ymm3, %ymm3;
+       vpxor (4 * 32 + 16)(%rdx), %ymm2, %ymm2;
+       vpxor (5 * 32 + 16)(%rdx), %ymm1, %ymm1;
+       vpxor (6 * 32 + 16)(%rdx), %ymm0, %ymm0;
+       vpxor (7 * 32 + 16)(%rdx), %ymm15, %ymm15;
+       vpxor (8 * 32 + 16)(%rdx), %ymm14, %ymm14;
+       vpxor (9 * 32 + 16)(%rdx), %ymm13, %ymm13;
+       vpxor (10 * 32 + 16)(%rdx), %ymm12, %ymm12;
+       vpxor (11 * 32 + 16)(%rdx), %ymm11, %ymm11;
+       vpxor (12 * 32 + 16)(%rdx), %ymm10, %ymm10;
+       vpxor (13 * 32 + 16)(%rdx), %ymm9, %ymm9;
+       vpxor (14 * 32 + 16)(%rdx), %ymm8, %ymm8;
+       movq (15 * 32 + 16 + 0)(%rdx), %rax;
+       movq (15 * 32 + 16 + 8)(%rdx), %rcx;
+
+       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
+                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
+                    %ymm8, %rsi);
+
+       /* store new IV */
+       movq %rax, (0)(%r9);
+       movq %rcx, (8)(%r9);
+
+       vzeroall;
+
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size FUNC_NAME(cbc_dec),.-FUNC_NAME(cbc_dec);)
+
+.align 8
+.globl FUNC_NAME(cfb_dec)
+ELF(.type   FUNC_NAME(cfb_dec),@function;)
+
+FUNC_NAME(cfb_dec):
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (32 blocks)
+        *      %rdx: src (32 blocks)
+        *      %rcx: iv
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       vzeroupper;
+
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %eax;
+       cmovel %eax, %r8d; /* max */
+
+       subq $(16 * 32), %rsp;
+       andq $~63, %rsp;
+       movq %rsp, %rax;
+
+       /* inpack16_pre: */
+       vpbroadcastq (key_table)(CTX), %ymm0;
+       vpshufb .Lpack_bswap rRIP, %ymm0, %ymm0;
+       vmovdqu (%rcx), %xmm15;
+       vinserti128 $1, (%rdx), %ymm15, %ymm15;
+       vpxor %ymm15, %ymm0, %ymm15;
+       vmovdqu (15 * 32 + 16)(%rdx), %xmm1;
+       vmovdqu %xmm1, (%rcx); /* store new IV */
+       vpxor (0 * 32 + 16)(%rdx), %ymm0, %ymm14;
+       vpxor (1 * 32 + 16)(%rdx), %ymm0, %ymm13;
+       vpxor (2 * 32 + 16)(%rdx), %ymm0, %ymm12;
+       vpxor (3 * 32 + 16)(%rdx), %ymm0, %ymm11;
+       vpxor (4 * 32 + 16)(%rdx), %ymm0, %ymm10;
+       vpxor (5 * 32 + 16)(%rdx), %ymm0, %ymm9;
+       vpxor (6 * 32 + 16)(%rdx), %ymm0, %ymm8;
+       vpxor (7 * 32 + 16)(%rdx), %ymm0, %ymm7;
+       vpxor (8 * 32 + 16)(%rdx), %ymm0, %ymm6;
+       vpxor (9 * 32 + 16)(%rdx), %ymm0, %ymm5;
+       vpxor (10 * 32 + 16)(%rdx), %ymm0, %ymm4;
+       vpxor (11 * 32 + 16)(%rdx), %ymm0, %ymm3;
+       vpxor (12 * 32 + 16)(%rdx), %ymm0, %ymm2;
+       vpxor (13 * 32 + 16)(%rdx), %ymm0, %ymm1;
+       vpxor (14 * 32 + 16)(%rdx), %ymm0, %ymm0;
+
+       call __camellia_enc_blk32;
+
+       vpxor 0 * 32(%rdx), %ymm7, %ymm7;
+       vpxor 1 * 32(%rdx), %ymm6, %ymm6;
+       vpxor 2 * 32(%rdx), %ymm5, %ymm5;
+       vpxor 3 * 32(%rdx), %ymm4, %ymm4;
+       vpxor 4 * 32(%rdx), %ymm3, %ymm3;
+       vpxor 5 * 32(%rdx), %ymm2, %ymm2;
+       vpxor 6 * 32(%rdx), %ymm1, %ymm1;
+       vpxor 7 * 32(%rdx), %ymm0, %ymm0;
+       vpxor 8 * 32(%rdx), %ymm15, %ymm15;
+       vpxor 9 * 32(%rdx), %ymm14, %ymm14;
+       vpxor 10 * 32(%rdx), %ymm13, %ymm13;
+       vpxor 11 * 32(%rdx), %ymm12, %ymm12;
+       vpxor 12 * 32(%rdx), %ymm11, %ymm11;
+       vpxor 13 * 32(%rdx), %ymm10, %ymm10;
+       vpxor 14 * 32(%rdx), %ymm9, %ymm9;
+       vpxor 15 * 32(%rdx), %ymm8, %ymm8;
+
+       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
+                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
+                    %ymm8, %rsi);
+
+       vzeroall;
+
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size FUNC_NAME(cfb_dec),.-FUNC_NAME(cfb_dec);)
+
+.align 8
+.globl FUNC_NAME(ocb_enc)
+ELF(.type   FUNC_NAME(ocb_enc),@function;)
+
+FUNC_NAME(ocb_enc):
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (32 blocks)
+        *      %rdx: src (32 blocks)
+        *      %rcx: offset
+        *      %r8 : checksum
+        *      %r9 : L pointers (void *L[32])
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       vzeroupper;
+
+       subq $(16 * 32 + 4 * 8), %rsp;
+       andq $~63, %rsp;
+       movq %rsp, %rax;
+
+       movq %r10, (16 * 32 + 0 * 8)(%rsp);
+       movq %r11, (16 * 32 + 1 * 8)(%rsp);
+       movq %r12, (16 * 32 + 2 * 8)(%rsp);
+       movq %r13, (16 * 32 + 3 * 8)(%rsp);
+       CFI_REG_ON_STACK(r10, 16 * 32 + 0 * 8);
+       CFI_REG_ON_STACK(r11, 16 * 32 + 1 * 8);
+       CFI_REG_ON_STACK(r12, 16 * 32 + 2 * 8);
+       CFI_REG_ON_STACK(r13, 16 * 32 + 3 * 8);
+
+       vmovdqu (%rcx), %xmm14;
+       vmovdqu (%r8), %xmm13;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* Checksum_i = Checksum_{i-1} xor P_i  */
+       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+
+#define OCB_INPUT(n, l0reg, l1reg, yreg) \
+         vmovdqu (n * 32)(%rdx), yreg; \
+         vpxor (l0reg), %xmm14, %xmm15; \
+         vpxor (l1reg), %xmm15, %xmm14; \
+         vinserti128 $1, %xmm14, %ymm15, %ymm15; \
+         vpxor yreg, %ymm13, %ymm13; \
+         vpxor yreg, %ymm15, yreg; \
+         vmovdqu %ymm15, (n * 32)(%rsi);
+
+       movq (0 * 8)(%r9), %r10;
+       movq (1 * 8)(%r9), %r11;
+       movq (2 * 8)(%r9), %r12;
+       movq (3 * 8)(%r9), %r13;
+       OCB_INPUT(0, %r10, %r11, %ymm0);
+       vmovdqu %ymm0, (15 * 32)(%rax);
+       OCB_INPUT(1, %r12, %r13, %ymm0);
+       vmovdqu %ymm0, (14 * 32)(%rax);
+       movq (4 * 8)(%r9), %r10;
+       movq (5 * 8)(%r9), %r11;
+       movq (6 * 8)(%r9), %r12;
+       movq (7 * 8)(%r9), %r13;
+       OCB_INPUT(2, %r10, %r11, %ymm0);
+       vmovdqu %ymm0, (13 * 32)(%rax);
+       OCB_INPUT(3, %r12, %r13, %ymm12);
+       movq (8 * 8)(%r9), %r10;
+       movq (9 * 8)(%r9), %r11;
+       movq (10 * 8)(%r9), %r12;
+       movq (11 * 8)(%r9), %r13;
+       OCB_INPUT(4, %r10, %r11, %ymm11);
+       OCB_INPUT(5, %r12, %r13, %ymm10);
+       movq (12 * 8)(%r9), %r10;
+       movq (13 * 8)(%r9), %r11;
+       movq (14 * 8)(%r9), %r12;
+       movq (15 * 8)(%r9), %r13;
+       OCB_INPUT(6, %r10, %r11, %ymm9);
+       OCB_INPUT(7, %r12, %r13, %ymm8);
+       movq (16 * 8)(%r9), %r10;
+       movq (17 * 8)(%r9), %r11;
+       movq (18 * 8)(%r9), %r12;
+       movq (19 * 8)(%r9), %r13;
+       OCB_INPUT(8, %r10, %r11, %ymm7);
+       OCB_INPUT(9, %r12, %r13, %ymm6);
+       movq (20 * 8)(%r9), %r10;
+       movq (21 * 8)(%r9), %r11;
+       movq (22 * 8)(%r9), %r12;
+       movq (23 * 8)(%r9), %r13;
+       OCB_INPUT(10, %r10, %r11, %ymm5);
+       OCB_INPUT(11, %r12, %r13, %ymm4);
+       movq (24 * 8)(%r9), %r10;
+       movq (25 * 8)(%r9), %r11;
+       movq (26 * 8)(%r9), %r12;
+       movq (27 * 8)(%r9), %r13;
+       OCB_INPUT(12, %r10, %r11, %ymm3);
+       OCB_INPUT(13, %r12, %r13, %ymm2);
+       movq (28 * 8)(%r9), %r10;
+       movq (29 * 8)(%r9), %r11;
+       movq (30 * 8)(%r9), %r12;
+       movq (31 * 8)(%r9), %r13;
+       OCB_INPUT(14, %r10, %r11, %ymm1);
+       OCB_INPUT(15, %r12, %r13, %ymm0);
+#undef OCB_INPUT
+
+       vextracti128 $1, %ymm13, %xmm15;
+       vmovdqu %xmm14, (%rcx);
+       vpxor %xmm13, %xmm15, %xmm15;
+       vmovdqu %xmm15, (%r8);
+
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %r10d;
+       cmovel %r10d, %r8d; /* max */
+
+       /* inpack16_pre: */
+       vpbroadcastq (key_table)(CTX), %ymm15;
+       vpshufb .Lpack_bswap rRIP, %ymm15, %ymm15;
+       vpxor %ymm0, %ymm15, %ymm0;
+       vpxor %ymm1, %ymm15, %ymm1;
+       vpxor %ymm2, %ymm15, %ymm2;
+       vpxor %ymm3, %ymm15, %ymm3;
+       vpxor %ymm4, %ymm15, %ymm4;
+       vpxor %ymm5, %ymm15, %ymm5;
+       vpxor %ymm6, %ymm15, %ymm6;
+       vpxor %ymm7, %ymm15, %ymm7;
+       vpxor %ymm8, %ymm15, %ymm8;
+       vpxor %ymm9, %ymm15, %ymm9;
+       vpxor %ymm10, %ymm15, %ymm10;
+       vpxor %ymm11, %ymm15, %ymm11;
+       vpxor %ymm12, %ymm15, %ymm12;
+       vpxor 13 * 32(%rax), %ymm15, %ymm13;
+       vpxor 14 * 32(%rax), %ymm15, %ymm14;
+       vpxor 15 * 32(%rax), %ymm15, %ymm15;
+
+       call __camellia_enc_blk32;
+
+       vpxor 0 * 32(%rsi), %ymm7, %ymm7;
+       vpxor 1 * 32(%rsi), %ymm6, %ymm6;
+       vpxor 2 * 32(%rsi), %ymm5, %ymm5;
+       vpxor 3 * 32(%rsi), %ymm4, %ymm4;
+       vpxor 4 * 32(%rsi), %ymm3, %ymm3;
+       vpxor 5 * 32(%rsi), %ymm2, %ymm2;
+       vpxor 6 * 32(%rsi), %ymm1, %ymm1;
+       vpxor 7 * 32(%rsi), %ymm0, %ymm0;
+       vpxor 8 * 32(%rsi), %ymm15, %ymm15;
+       vpxor 9 * 32(%rsi), %ymm14, %ymm14;
+       vpxor 10 * 32(%rsi), %ymm13, %ymm13;
+       vpxor 11 * 32(%rsi), %ymm12, %ymm12;
+       vpxor 12 * 32(%rsi), %ymm11, %ymm11;
+       vpxor 13 * 32(%rsi), %ymm10, %ymm10;
+       vpxor 14 * 32(%rsi), %ymm9, %ymm9;
+       vpxor 15 * 32(%rsi), %ymm8, %ymm8;
+
+       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
+                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
+                    %ymm8, %rsi);
+
+       vzeroall;
+
+       movq (16 * 32 + 0 * 8)(%rsp), %r10;
+       movq (16 * 32 + 1 * 8)(%rsp), %r11;
+       movq (16 * 32 + 2 * 8)(%rsp), %r12;
+       movq (16 * 32 + 3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size FUNC_NAME(ocb_enc),.-FUNC_NAME(ocb_enc);)
+
+.align 8
+.globl FUNC_NAME(ocb_dec)
+ELF(.type   FUNC_NAME(ocb_dec),@function;)
+
+FUNC_NAME(ocb_dec):
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (32 blocks)
+        *      %rdx: src (32 blocks)
+        *      %rcx: offset
+        *      %r8 : checksum
+        *      %r9 : L pointers (void *L[32])
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       vzeroupper;
+
+       subq $(16 * 32 + 4 * 8), %rsp;
+       andq $~63, %rsp;
+       movq %rsp, %rax;
+
+       movq %r10, (16 * 32 + 0 * 8)(%rsp);
+       movq %r11, (16 * 32 + 1 * 8)(%rsp);
+       movq %r12, (16 * 32 + 2 * 8)(%rsp);
+       movq %r13, (16 * 32 + 3 * 8)(%rsp);
+       CFI_REG_ON_STACK(r10, 16 * 32 + 0 * 8);
+       CFI_REG_ON_STACK(r11, 16 * 32 + 1 * 8);
+       CFI_REG_ON_STACK(r12, 16 * 32 + 2 * 8);
+       CFI_REG_ON_STACK(r13, 16 * 32 + 3 * 8);
+
+       vmovdqu (%rcx), %xmm14;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
+
+#define OCB_INPUT(n, l0reg, l1reg, yreg) \
+         vmovdqu (n * 32)(%rdx), yreg; \
+         vpxor (l0reg), %xmm14, %xmm15; \
+         vpxor (l1reg), %xmm15, %xmm14; \
+         vinserti128 $1, %xmm14, %ymm15, %ymm15; \
+         vpxor yreg, %ymm15, yreg; \
+         vmovdqu %ymm15, (n * 32)(%rsi);
+
+       movq (0 * 8)(%r9), %r10;
+       movq (1 * 8)(%r9), %r11;
+       movq (2 * 8)(%r9), %r12;
+       movq (3 * 8)(%r9), %r13;
+       OCB_INPUT(0, %r10, %r11, %ymm0);
+       vmovdqu %ymm0, (15 * 32)(%rax);
+       OCB_INPUT(1, %r12, %r13, %ymm0);
+       vmovdqu %ymm0, (14 * 32)(%rax);
+       movq (4 * 8)(%r9), %r10;
+       movq (5 * 8)(%r9), %r11;
+       movq (6 * 8)(%r9), %r12;
+       movq (7 * 8)(%r9), %r13;
+       OCB_INPUT(2, %r10, %r11, %ymm13);
+       OCB_INPUT(3, %r12, %r13, %ymm12);
+       movq (8 * 8)(%r9), %r10;
+       movq (9 * 8)(%r9), %r11;
+       movq (10 * 8)(%r9), %r12;
+       movq (11 * 8)(%r9), %r13;
+       OCB_INPUT(4, %r10, %r11, %ymm11);
+       OCB_INPUT(5, %r12, %r13, %ymm10);
+       movq (12 * 8)(%r9), %r10;
+       movq (13 * 8)(%r9), %r11;
+       movq (14 * 8)(%r9), %r12;
+       movq (15 * 8)(%r9), %r13;
+       OCB_INPUT(6, %r10, %r11, %ymm9);
+       OCB_INPUT(7, %r12, %r13, %ymm8);
+       movq (16 * 8)(%r9), %r10;
+       movq (17 * 8)(%r9), %r11;
+       movq (18 * 8)(%r9), %r12;
+       movq (19 * 8)(%r9), %r13;
+       OCB_INPUT(8, %r10, %r11, %ymm7);
+       OCB_INPUT(9, %r12, %r13, %ymm6);
+       movq (20 * 8)(%r9), %r10;
+       movq (21 * 8)(%r9), %r11;
+       movq (22 * 8)(%r9), %r12;
+       movq (23 * 8)(%r9), %r13;
+       OCB_INPUT(10, %r10, %r11, %ymm5);
+       OCB_INPUT(11, %r12, %r13, %ymm4);
+       movq (24 * 8)(%r9), %r10;
+       movq (25 * 8)(%r9), %r11;
+       movq (26 * 8)(%r9), %r12;
+       movq (27 * 8)(%r9), %r13;
+       OCB_INPUT(12, %r10, %r11, %ymm3);
+       OCB_INPUT(13, %r12, %r13, %ymm2);
+       movq (28 * 8)(%r9), %r10;
+       movq (29 * 8)(%r9), %r11;
+       movq (30 * 8)(%r9), %r12;
+       movq (31 * 8)(%r9), %r13;
+       OCB_INPUT(14, %r10, %r11, %ymm1);
+       OCB_INPUT(15, %r12, %r13, %ymm0);
+#undef OCB_INPUT
+
+       vmovdqu %xmm14, (%rcx);
+
+       movq %r8, %r10;
+
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %r9d;
+       cmovel %r9d, %r8d; /* max */
+
+       /* inpack16_pre: */
+       vpbroadcastq (key_table)(CTX, %r8, 8), %ymm15;
+       vpshufb .Lpack_bswap rRIP, %ymm15, %ymm15;
+       vpxor %ymm0, %ymm15, %ymm0;
+       vpxor %ymm1, %ymm15, %ymm1;
+       vpxor %ymm2, %ymm15, %ymm2;
+       vpxor %ymm3, %ymm15, %ymm3;
+       vpxor %ymm4, %ymm15, %ymm4;
+       vpxor %ymm5, %ymm15, %ymm5;
+       vpxor %ymm6, %ymm15, %ymm6;
+       vpxor %ymm7, %ymm15, %ymm7;
+       vpxor %ymm8, %ymm15, %ymm8;
+       vpxor %ymm9, %ymm15, %ymm9;
+       vpxor %ymm10, %ymm15, %ymm10;
+       vpxor %ymm11, %ymm15, %ymm11;
+       vpxor %ymm12, %ymm15, %ymm12;
+       vpxor %ymm13, %ymm15, %ymm13;
+       vpxor 14 * 32(%rax), %ymm15, %ymm14;
+       vpxor 15 * 32(%rax), %ymm15, %ymm15;
+
+       call __camellia_dec_blk32;
+
+       vpxor 0 * 32(%rsi), %ymm7, %ymm7;
+       vpxor 1 * 32(%rsi), %ymm6, %ymm6;
+       vpxor 2 * 32(%rsi), %ymm5, %ymm5;
+       vpxor 3 * 32(%rsi), %ymm4, %ymm4;
+       vpxor 4 * 32(%rsi), %ymm3, %ymm3;
+       vpxor 5 * 32(%rsi), %ymm2, %ymm2;
+       vpxor 6 * 32(%rsi), %ymm1, %ymm1;
+       vpxor 7 * 32(%rsi), %ymm0, %ymm0;
+       vmovdqu %ymm7, (7 * 32)(%rax);
+       vmovdqu %ymm6, (6 * 32)(%rax);
+       vpxor 8 * 32(%rsi), %ymm15, %ymm15;
+       vpxor 9 * 32(%rsi), %ymm14, %ymm14;
+       vpxor 10 * 32(%rsi), %ymm13, %ymm13;
+       vpxor 11 * 32(%rsi), %ymm12, %ymm12;
+       vpxor 12 * 32(%rsi), %ymm11, %ymm11;
+       vpxor 13 * 32(%rsi), %ymm10, %ymm10;
+       vpxor 14 * 32(%rsi), %ymm9, %ymm9;
+       vpxor 15 * 32(%rsi), %ymm8, %ymm8;
+
+       /* Checksum_i = Checksum_{i-1} xor P_i  */
+
+       vpxor %ymm5, %ymm7, %ymm7;
+       vpxor %ymm4, %ymm6, %ymm6;
+       vpxor %ymm3, %ymm7, %ymm7;
+       vpxor %ymm2, %ymm6, %ymm6;
+       vpxor %ymm1, %ymm7, %ymm7;
+       vpxor %ymm0, %ymm6, %ymm6;
+       vpxor %ymm15, %ymm7, %ymm7;
+       vpxor %ymm14, %ymm6, %ymm6;
+       vpxor %ymm13, %ymm7, %ymm7;
+       vpxor %ymm12, %ymm6, %ymm6;
+       vpxor %ymm11, %ymm7, %ymm7;
+       vpxor %ymm10, %ymm6, %ymm6;
+       vpxor %ymm9, %ymm7, %ymm7;
+       vpxor %ymm8, %ymm6, %ymm6;
+       vpxor %ymm7, %ymm6, %ymm7;
+
+       vextracti128 $1, %ymm7, %xmm6;
+       vpxor %xmm6, %xmm7, %xmm7;
+       vpxor (%r10), %xmm7, %xmm7;
+       vmovdqu %xmm7, (%r10);
+
+       vmovdqu 7 * 32(%rax), %ymm7;
+       vmovdqu 6 * 32(%rax), %ymm6;
+
+       write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0,
+                    %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9,
+                    %ymm8, %rsi);
+
+       vzeroall;
+
+       movq (16 * 32 + 0 * 8)(%rsp), %r10;
+       movq (16 * 32 + 1 * 8)(%rsp), %r11;
+       movq (16 * 32 + 2 * 8)(%rsp), %r12;
+       movq (16 * 32 + 3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size FUNC_NAME(ocb_dec),.-FUNC_NAME(ocb_dec);)
+
+.align 8
+.globl FUNC_NAME(ocb_auth)
+ELF(.type   FUNC_NAME(ocb_auth),@function;)
+
+FUNC_NAME(ocb_auth):
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: abuf (16 blocks)
+        *      %rdx: offset
+        *      %rcx: checksum
+        *      %r8 : L pointers (void *L[16])
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       vzeroupper;
+
+       subq $(16 * 32 + 4 * 8), %rsp;
+       andq $~63, %rsp;
+       movq %rsp, %rax;
+
+       movq %r10, (16 * 32 + 0 * 8)(%rsp);
+       movq %r11, (16 * 32 + 1 * 8)(%rsp);
+       movq %r12, (16 * 32 + 2 * 8)(%rsp);
+       movq %r13, (16 * 32 + 3 * 8)(%rsp);
+       CFI_REG_ON_STACK(r10, 16 * 32 + 0 * 8);
+       CFI_REG_ON_STACK(r11, 16 * 32 + 1 * 8);
+       CFI_REG_ON_STACK(r12, 16 * 32 + 2 * 8);
+       CFI_REG_ON_STACK(r13, 16 * 32 + 3 * 8);
+
+       vmovdqu (%rdx), %xmm14;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* Checksum_i = Checksum_{i-1} xor P_i  */
+       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+
+#define OCB_INPUT(n, l0reg, l1reg, yreg) \
+         vmovdqu (n * 32)(%rsi), yreg; \
+         vpxor (l0reg), %xmm14, %xmm15; \
+         vpxor (l1reg), %xmm15, %xmm14; \
+         vinserti128 $1, %xmm14, %ymm15, %ymm15; \
+         vpxor yreg, %ymm15, yreg;
+
+       movq (0 * 8)(%r8), %r10;
+       movq (1 * 8)(%r8), %r11;
+       movq (2 * 8)(%r8), %r12;
+       movq (3 * 8)(%r8), %r13;
+       OCB_INPUT(0, %r10, %r11, %ymm0);
+       vmovdqu %ymm0, (15 * 32)(%rax);
+       OCB_INPUT(1, %r12, %r13, %ymm0);
+       vmovdqu %ymm0, (14 * 32)(%rax);
+       movq (4 * 8)(%r8), %r10;
+       movq (5 * 8)(%r8), %r11;
+       movq (6 * 8)(%r8), %r12;
+       movq (7 * 8)(%r8), %r13;
+       OCB_INPUT(2, %r10, %r11, %ymm13);
+       OCB_INPUT(3, %r12, %r13, %ymm12);
+       movq (8 * 8)(%r8), %r10;
+       movq (9 * 8)(%r8), %r11;
+       movq (10 * 8)(%r8), %r12;
+       movq (11 * 8)(%r8), %r13;
+       OCB_INPUT(4, %r10, %r11, %ymm11);
+       OCB_INPUT(5, %r12, %r13, %ymm10);
+       movq (12 * 8)(%r8), %r10;
+       movq (13 * 8)(%r8), %r11;
+       movq (14 * 8)(%r8), %r12;
+       movq (15 * 8)(%r8), %r13;
+       OCB_INPUT(6, %r10, %r11, %ymm9);
+       OCB_INPUT(7, %r12, %r13, %ymm8);
+       movq (16 * 8)(%r8), %r10;
+       movq (17 * 8)(%r8), %r11;
+       movq (18 * 8)(%r8), %r12;
+       movq (19 * 8)(%r8), %r13;
+       OCB_INPUT(8, %r10, %r11, %ymm7);
+       OCB_INPUT(9, %r12, %r13, %ymm6);
+       movq (20 * 8)(%r8), %r10;
+       movq (21 * 8)(%r8), %r11;
+       movq (22 * 8)(%r8), %r12;
+       movq (23 * 8)(%r8), %r13;
+       OCB_INPUT(10, %r10, %r11, %ymm5);
+       OCB_INPUT(11, %r12, %r13, %ymm4);
+       movq (24 * 8)(%r8), %r10;
+       movq (25 * 8)(%r8), %r11;
+       movq (26 * 8)(%r8), %r12;
+       movq (27 * 8)(%r8), %r13;
+       OCB_INPUT(12, %r10, %r11, %ymm3);
+       OCB_INPUT(13, %r12, %r13, %ymm2);
+       movq (28 * 8)(%r8), %r10;
+       movq (29 * 8)(%r8), %r11;
+       movq (30 * 8)(%r8), %r12;
+       movq (31 * 8)(%r8), %r13;
+       OCB_INPUT(14, %r10, %r11, %ymm1);
+       OCB_INPUT(15, %r12, %r13, %ymm0);
+#undef OCB_INPUT
+
+       vmovdqu %xmm14, (%rdx);
+
+       cmpl $128, key_bitlength(CTX);
+       movl $32, %r8d;
+       movl $24, %r10d;
+       cmovel %r10d, %r8d; /* max */
+
+       movq %rcx, %r10;
+
+       /* inpack16_pre: */
+       vpbroadcastq (key_table)(CTX), %ymm15;
+       vpshufb .Lpack_bswap rRIP, %ymm15, %ymm15;
+       vpxor %ymm0, %ymm15, %ymm0;
+       vpxor %ymm1, %ymm15, %ymm1;
+       vpxor %ymm2, %ymm15, %ymm2;
+       vpxor %ymm3, %ymm15, %ymm3;
+       vpxor %ymm4, %ymm15, %ymm4;
+       vpxor %ymm5, %ymm15, %ymm5;
+       vpxor %ymm6, %ymm15, %ymm6;
+       vpxor %ymm7, %ymm15, %ymm7;
+       vpxor %ymm8, %ymm15, %ymm8;
+       vpxor %ymm9, %ymm15, %ymm9;
+       vpxor %ymm10, %ymm15, %ymm10;
+       vpxor %ymm11, %ymm15, %ymm11;
+       vpxor %ymm12, %ymm15, %ymm12;
+       vpxor %ymm13, %ymm15, %ymm13;
+       vpxor 14 * 32(%rax), %ymm15, %ymm14;
+       vpxor 15 * 32(%rax), %ymm15, %ymm15;
+
+       call __camellia_enc_blk32;
+
+       vpxor %ymm7, %ymm6, %ymm6;
+       vpxor %ymm5, %ymm4, %ymm4;
+       vpxor %ymm3, %ymm2, %ymm2;
+       vpxor %ymm1, %ymm0, %ymm0;
+       vpxor %ymm15, %ymm14, %ymm14;
+       vpxor %ymm13, %ymm12, %ymm12;
+       vpxor %ymm11, %ymm10, %ymm10;
+       vpxor %ymm9, %ymm8, %ymm8;
+
+       vpxor %ymm6, %ymm4, %ymm4;
+       vpxor %ymm2, %ymm0, %ymm0;
+       vpxor %ymm14, %ymm12, %ymm12;
+       vpxor %ymm10, %ymm8, %ymm8;
+
+       vpxor %ymm4, %ymm0, %ymm0;
+       vpxor %ymm12, %ymm8, %ymm8;
+
+       vpxor %ymm0, %ymm8, %ymm0;
+
+       vextracti128 $1, %ymm0, %xmm1;
+       vpxor (%r10), %xmm0, %xmm0;
+       vpxor %xmm0, %xmm1, %xmm0;
+       vmovdqu %xmm0, (%r10);
+
+       vzeroall;
+
+       movq (16 * 32 + 0 * 8)(%rsp), %r10;
+       movq (16 * 32 + 1 * 8)(%rsp), %r11;
+       movq (16 * 32 + 2 * 8)(%rsp), %r12;
+       movq (16 * 32 + 3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size FUNC_NAME(ocb_auth),.-FUNC_NAME(ocb_auth);)
+
+#endif /* GCRY_CAMELLIA_AESNI_AVX2_AMD64_H */
index 7687094..72c02d7 100644 (file)
 # endif
 #endif
 
+/* USE_VAES_AVX2 inidicates whether to compile with Intel VAES/AVX2 code. */
+#undef USE_VAES_AVX2
+#if defined(USE_AESNI_AVX2) && defined(HAVE_GCC_INLINE_ASM_VAES_VPCLMUL)
+# define USE_VAES_AVX2 1
+#endif
+
 typedef struct
 {
   KEY_TABLE_TYPE keytable;
@@ -100,6 +106,7 @@ typedef struct
 #endif /*USE_AESNI_AVX*/
 #ifdef USE_AESNI_AVX2
   unsigned int use_aesni_avx2:1;/* AES-NI/AVX2 implementation shall be used.  */
+  unsigned int use_vaes_avx2:1; /* VAES/AVX2 implementation shall be used.  */
 #endif /*USE_AESNI_AVX2*/
 } CAMELLIA_context;
 
@@ -201,15 +208,71 @@ extern void _gcry_camellia_aesni_avx2_ocb_auth(CAMELLIA_context *ctx,
                                               const u64 Ls[32]) ASM_FUNC_ABI;
 #endif
 
+#ifdef USE_VAES_AVX2
+/* Assembler implementations of Camellia using VAES and AVX2.  Process data
+   in 32 block same time.
+ */
+extern void _gcry_camellia_vaes_avx2_ctr_enc(CAMELLIA_context *ctx,
+                                            unsigned char *out,
+                                            const unsigned char *in,
+                                            unsigned char *ctr) ASM_FUNC_ABI;
+
+extern void _gcry_camellia_vaes_avx2_cbc_dec(CAMELLIA_context *ctx,
+                                            unsigned char *out,
+                                            const unsigned char *in,
+                                            unsigned char *iv) ASM_FUNC_ABI;
+
+extern void _gcry_camellia_vaes_avx2_cfb_dec(CAMELLIA_context *ctx,
+                                            unsigned char *out,
+                                            const unsigned char *in,
+                                            unsigned char *iv) ASM_FUNC_ABI;
+
+extern void _gcry_camellia_vaes_avx2_ocb_enc(CAMELLIA_context *ctx,
+                                            unsigned char *out,
+                                            const unsigned char *in,
+                                            unsigned char *offset,
+                                            unsigned char *checksum,
+                                            const u64 Ls[32]) ASM_FUNC_ABI;
+
+extern void _gcry_camellia_vaes_avx2_ocb_dec(CAMELLIA_context *ctx,
+                                            unsigned char *out,
+                                            const unsigned char *in,
+                                            unsigned char *offset,
+                                            unsigned char *checksum,
+                                            const u64 Ls[32]) ASM_FUNC_ABI;
+
+extern void _gcry_camellia_vaes_avx2_ocb_auth(CAMELLIA_context *ctx,
+                                             const unsigned char *abuf,
+                                             unsigned char *offset,
+                                             unsigned char *checksum,
+                                             const u64 Ls[32]) ASM_FUNC_ABI;
+#endif
+
 static const char *selftest(void);
 
+static void _gcry_camellia_ctr_enc (void *context, unsigned char *ctr,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+static void _gcry_camellia_cbc_dec (void *context, unsigned char *iv,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+static void _gcry_camellia_cfb_dec (void *context, unsigned char *iv,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+static size_t _gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                       const void *inbuf_arg, size_t nblocks,
+                                       int encrypt);
+static size_t _gcry_camellia_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
+                                      size_t nblocks);
+
 static gcry_err_code_t
-camellia_setkey(void *c, const byte *key, unsigned keylen)
+camellia_setkey(void *c, const byte *key, unsigned keylen,
+                cipher_bulk_ops_t *bulk_ops)
 {
   CAMELLIA_context *ctx=c;
   static int initialized=0;
   static const char *selftest_failed=NULL;
-#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2)
+#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) || defined(USE_VAES_AVX2)
   unsigned int hwf = _gcry_get_hw_features ();
 #endif
 
@@ -232,10 +295,22 @@ camellia_setkey(void *c, const byte *key, unsigned keylen)
 #endif
 #ifdef USE_AESNI_AVX2
   ctx->use_aesni_avx2 = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX2);
+  ctx->use_vaes_avx2 = 0;
+#endif
+#ifdef USE_VAES_AVX2
+  ctx->use_vaes_avx2 = (hwf & HWF_INTEL_VAES_VPCLMUL) && (hwf & HWF_INTEL_AVX2);
 #endif
 
   ctx->keybitlength=keylen*8;
 
+  /* Setup bulk encryption routines.  */
+  memset (bulk_ops, 0, sizeof(*bulk_ops));
+  bulk_ops->cbc_dec = _gcry_camellia_cbc_dec;
+  bulk_ops->cfb_dec = _gcry_camellia_cfb_dec;
+  bulk_ops->ctr_enc = _gcry_camellia_ctr_enc;
+  bulk_ops->ocb_crypt = _gcry_camellia_ocb_crypt;
+  bulk_ops->ocb_auth  = _gcry_camellia_ocb_auth;
+
   if (0)
     { }
 #ifdef USE_AESNI_AVX
@@ -350,7 +425,7 @@ camellia_decrypt(void *c, byte *outbuf, const byte *inbuf)
 /* Bulk encryption of complete blocks in CTR mode.  This function is only
    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
    of size CAMELLIA_BLOCK_SIZE. */
-void
+static void
 _gcry_camellia_ctr_enc(void *context, unsigned char *ctr,
                        void *outbuf_arg, const void *inbuf_arg,
                        size_t nblocks)
@@ -360,17 +435,24 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr,
   const unsigned char *inbuf = inbuf_arg;
   unsigned char tmpbuf[CAMELLIA_BLOCK_SIZE];
   int burn_stack_depth = CAMELLIA_encrypt_stack_burn_size;
-  int i;
 
 #ifdef USE_AESNI_AVX2
   if (ctx->use_aesni_avx2)
     {
       int did_use_aesni_avx2 = 0;
+#ifdef USE_VAES_AVX2
+      int use_vaes = ctx->use_vaes_avx2;
+#endif
 
       /* Process data in 32 block chunks. */
       while (nblocks >= 32)
         {
-          _gcry_camellia_aesni_avx2_ctr_enc(ctx, outbuf, inbuf, ctr);
+#ifdef USE_VAES_AVX2
+          if (use_vaes)
+            _gcry_camellia_vaes_avx2_ctr_enc(ctx, outbuf, inbuf, ctr);
+          else
+#endif
+            _gcry_camellia_aesni_avx2_ctr_enc(ctx, outbuf, inbuf, ctr);
 
           nblocks -= 32;
           outbuf += 32 * CAMELLIA_BLOCK_SIZE;
@@ -427,16 +509,11 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr,
       /* Encrypt the counter. */
       Camellia_EncryptBlock(ctx->keybitlength, ctr, ctx->keytable, tmpbuf);
       /* XOR the input with the encrypted counter and store in output.  */
-      buf_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE);
+      cipher_block_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE);
       outbuf += CAMELLIA_BLOCK_SIZE;
       inbuf  += CAMELLIA_BLOCK_SIZE;
       /* Increment the counter.  */
-      for (i = CAMELLIA_BLOCK_SIZE; i > 0; i--)
-        {
-          ctr[i-1]++;
-          if (ctr[i-1])
-            break;
-        }
+      cipher_block_add(ctr, 1, CAMELLIA_BLOCK_SIZE);
     }
 
   wipememory(tmpbuf, sizeof(tmpbuf));
@@ -445,7 +522,7 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr,
 
 /* Bulk decryption of complete blocks in CBC mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_camellia_cbc_dec(void *context, unsigned char *iv,
                        void *outbuf_arg, const void *inbuf_arg,
                        size_t nblocks)
@@ -460,11 +537,19 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv,
   if (ctx->use_aesni_avx2)
     {
       int did_use_aesni_avx2 = 0;
+#ifdef USE_VAES_AVX2
+      int use_vaes = ctx->use_vaes_avx2;
+#endif
 
       /* Process data in 32 block chunks. */
       while (nblocks >= 32)
         {
-          _gcry_camellia_aesni_avx2_cbc_dec(ctx, outbuf, inbuf, iv);
+#ifdef USE_VAES_AVX2
+          if (use_vaes)
+            _gcry_camellia_vaes_avx2_cbc_dec(ctx, outbuf, inbuf, iv);
+          else
+#endif
+            _gcry_camellia_aesni_avx2_cbc_dec(ctx, outbuf, inbuf, iv);
 
           nblocks -= 32;
           outbuf += 32 * CAMELLIA_BLOCK_SIZE;
@@ -520,7 +605,8 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv,
          the intermediate result to SAVEBUF.  */
       Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, savebuf);
 
-      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAMELLIA_BLOCK_SIZE);
+      cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf,
+                                CAMELLIA_BLOCK_SIZE);
       inbuf += CAMELLIA_BLOCK_SIZE;
       outbuf += CAMELLIA_BLOCK_SIZE;
     }
@@ -531,7 +617,7 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv,
 
 /* Bulk decryption of complete blocks in CFB mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_camellia_cfb_dec(void *context, unsigned char *iv,
                        void *outbuf_arg, const void *inbuf_arg,
                        size_t nblocks)
@@ -545,11 +631,19 @@ _gcry_camellia_cfb_dec(void *context, unsigned char *iv,
   if (ctx->use_aesni_avx2)
     {
       int did_use_aesni_avx2 = 0;
+#ifdef USE_VAES_AVX2
+      int use_vaes = ctx->use_vaes_avx2;
+#endif
 
       /* Process data in 32 block chunks. */
       while (nblocks >= 32)
         {
-          _gcry_camellia_aesni_avx2_cfb_dec(ctx, outbuf, inbuf, iv);
+#ifdef USE_VAES_AVX2
+          if (use_vaes)
+            _gcry_camellia_vaes_avx2_cfb_dec(ctx, outbuf, inbuf, iv);
+          else
+#endif
+            _gcry_camellia_aesni_avx2_cfb_dec(ctx, outbuf, inbuf, iv);
 
           nblocks -= 32;
           outbuf += 32 * CAMELLIA_BLOCK_SIZE;
@@ -602,7 +696,7 @@ _gcry_camellia_cfb_dec(void *context, unsigned char *iv,
   for ( ;nblocks; nblocks-- )
     {
       Camellia_EncryptBlock(ctx->keybitlength, iv, ctx->keytable, iv);
-      buf_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE);
+      cipher_block_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE);
       outbuf += CAMELLIA_BLOCK_SIZE;
       inbuf  += CAMELLIA_BLOCK_SIZE;
     }
@@ -611,7 +705,7 @@ _gcry_camellia_cfb_dec(void *context, unsigned char *iv,
 }
 
 /* Bulk encryption/decryption of complete blocks in OCB mode. */
-size_t
+static size_t
 _gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
                          const void *inbuf_arg, size_t nblocks, int encrypt)
 {
@@ -635,6 +729,10 @@ _gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
   if (ctx->use_aesni_avx2)
     {
       int did_use_aesni_avx2 = 0;
+#ifdef USE_VAES_AVX2
+      int encrypt_use_vaes = encrypt && ctx->use_vaes_avx2;
+      int decrypt_use_vaes = !encrypt && ctx->use_vaes_avx2;
+#endif
       u64 Ls[32];
       unsigned int n = 32 - (blkn % 32);
       u64 *l;
@@ -666,7 +764,16 @@ _gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
              blkn += 32;
              *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 32);
 
-             if (encrypt)
+             if (0) {}
+#ifdef USE_VAES_AVX2
+             else if (encrypt_use_vaes)
+               _gcry_camellia_vaes_avx2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
+                                                 c->u_ctr.ctr, Ls);
+             else if (decrypt_use_vaes)
+               _gcry_camellia_vaes_avx2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
+                                                 c->u_ctr.ctr, Ls);
+#endif
+             else if (encrypt)
                _gcry_camellia_aesni_avx2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
                                                  c->u_ctr.ctr, Ls);
              else
@@ -764,7 +871,7 @@ _gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
 }
 
 /* Bulk authentication of complete blocks in OCB mode. */
-size_t
+static size_t
 _gcry_camellia_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
                         size_t nblocks)
 {
@@ -784,6 +891,9 @@ _gcry_camellia_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
   if (ctx->use_aesni_avx2)
     {
       int did_use_aesni_avx2 = 0;
+#ifdef USE_VAES_AVX2
+      int use_vaes = ctx->use_vaes_avx2;
+#endif
       u64 Ls[32];
       unsigned int n = 32 - (blkn % 32);
       u64 *l;
@@ -815,9 +925,16 @@ _gcry_camellia_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
              blkn += 32;
              *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 32);
 
-             _gcry_camellia_aesni_avx2_ocb_auth(ctx, abuf,
-                                                c->u_mode.ocb.aad_offset,
-                                                c->u_mode.ocb.aad_sum, Ls);
+#ifdef USE_VAES_AVX2
+              if (use_vaes)
+                _gcry_camellia_vaes_avx2_ocb_auth(ctx, abuf,
+                                                  c->u_mode.ocb.aad_offset,
+                                                  c->u_mode.ocb.aad_sum, Ls);
+              else
+#endif
+                _gcry_camellia_aesni_avx2_ocb_auth(ctx, abuf,
+                                                   c->u_mode.ocb.aad_offset,
+                                                   c->u_mode.ocb.aad_sum, Ls);
 
              nblocks -= 32;
              abuf += 32 * CAMELLIA_BLOCK_SIZE;
@@ -914,8 +1031,7 @@ selftest_ctr_128 (void)
   const int context_size = sizeof(CAMELLIA_context);
 
   return _gcry_selftest_helper_ctr("CAMELLIA", &camellia_setkey,
-           &camellia_encrypt, &_gcry_camellia_ctr_enc, nblocks, blocksize,
-          context_size);
+           &camellia_encrypt, nblocks, blocksize, context_size);
 }
 
 /* Run the self-tests for CAMELLIA-CBC-128, tests bulk CBC decryption.
@@ -928,8 +1044,7 @@ selftest_cbc_128 (void)
   const int context_size = sizeof(CAMELLIA_context);
 
   return _gcry_selftest_helper_cbc("CAMELLIA", &camellia_setkey,
-           &camellia_encrypt, &_gcry_camellia_cbc_dec, nblocks, blocksize,
-          context_size);
+           &camellia_encrypt, nblocks, blocksize, context_size);
 }
 
 /* Run the self-tests for CAMELLIA-CFB-128, tests bulk CFB decryption.
@@ -942,8 +1057,7 @@ selftest_cfb_128 (void)
   const int context_size = sizeof(CAMELLIA_context);
 
   return _gcry_selftest_helper_cfb("CAMELLIA", &camellia_setkey,
-           &camellia_encrypt, &_gcry_camellia_cfb_dec, nblocks, blocksize,
-          context_size);
+           &camellia_encrypt, nblocks, blocksize, context_size);
 }
 
 static const char *
@@ -951,6 +1065,7 @@ selftest(void)
 {
   CAMELLIA_context ctx;
   byte scratch[16];
+  cipher_bulk_ops_t bulk_ops;
   const char *r;
 
   /* These test vectors are from RFC-3713 */
@@ -991,7 +1106,7 @@ selftest(void)
       0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09
     };
 
-  camellia_setkey(&ctx,key_128,sizeof(key_128));
+  camellia_setkey(&ctx,key_128,sizeof(key_128),&bulk_ops);
   camellia_encrypt(&ctx,scratch,plaintext);
   if(memcmp(scratch,ciphertext_128,sizeof(ciphertext_128))!=0)
     return "CAMELLIA-128 test encryption failed.";
@@ -999,7 +1114,7 @@ selftest(void)
   if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
     return "CAMELLIA-128 test decryption failed.";
 
-  camellia_setkey(&ctx,key_192,sizeof(key_192));
+  camellia_setkey(&ctx,key_192,sizeof(key_192),&bulk_ops);
   camellia_encrypt(&ctx,scratch,plaintext);
   if(memcmp(scratch,ciphertext_192,sizeof(ciphertext_192))!=0)
     return "CAMELLIA-192 test encryption failed.";
@@ -1007,7 +1122,7 @@ selftest(void)
   if(memcmp(scratch,plaintext,sizeof(plaintext))!=0)
     return "CAMELLIA-192 test decryption failed.";
 
-  camellia_setkey(&ctx,key_256,sizeof(key_256));
+  camellia_setkey(&ctx,key_256,sizeof(key_256),&bulk_ops);
   camellia_encrypt(&ctx,scratch,plaintext);
   if(memcmp(scratch,ciphertext_256,sizeof(ciphertext_256))!=0)
     return "CAMELLIA-256 test encryption failed.";
@@ -1031,7 +1146,7 @@ selftest(void)
    <http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications_oid.html>,
    retrieved May 1, 2007. */
 
-static gcry_cipher_oid_spec_t camellia128_oids[] =
+static const gcry_cipher_oid_spec_t camellia128_oids[] =
   {
     {"1.2.392.200011.61.1.1.1.2", GCRY_CIPHER_MODE_CBC},
     {"0.3.4401.5.3.1.9.1", GCRY_CIPHER_MODE_ECB},
@@ -1040,7 +1155,7 @@ static gcry_cipher_oid_spec_t camellia128_oids[] =
     { NULL }
   };
 
-static gcry_cipher_oid_spec_t camellia192_oids[] =
+static const gcry_cipher_oid_spec_t camellia192_oids[] =
   {
     {"1.2.392.200011.61.1.1.1.3", GCRY_CIPHER_MODE_CBC},
     {"0.3.4401.5.3.1.9.21", GCRY_CIPHER_MODE_ECB},
@@ -1049,7 +1164,7 @@ static gcry_cipher_oid_spec_t camellia192_oids[] =
     { NULL }
   };
 
-static gcry_cipher_oid_spec_t camellia256_oids[] =
+static const gcry_cipher_oid_spec_t camellia256_oids[] =
   {
     {"1.2.392.200011.61.1.1.1.4", GCRY_CIPHER_MODE_CBC},
     {"0.3.4401.5.3.1.9.41", GCRY_CIPHER_MODE_ECB},
diff --git a/cipher/camellia-vaes-avx2-amd64.S b/cipher/camellia-vaes-avx2-amd64.S
new file mode 100644 (file)
index 0000000..e6e0c78
--- /dev/null
@@ -0,0 +1,35 @@
+/* camellia-vaes-avx2-amd64.S  -  VAES/AVX2 implementation of Camellia cipher
+ *
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#ifdef __x86_64
+#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
+    defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT) && \
+    defined(HAVE_GCC_INLINE_ASM_VAES_VPCLMUL)
+
+#define CAMELLIA_VAES_BUILD 1
+#define FUNC_NAME(func) _gcry_camellia_vaes_avx2_ ## func
+
+#include "camellia-aesni-avx2-amd64.h"
+
+#endif /* defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT) */
+#endif /* __x86_64 */
index c04015a..a804654 100644 (file)
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_CAST5)
 
-#if defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS) || !defined(__PIC__)
-#  define GET_EXTERN_POINTER(name, reg) movabsq $name, reg
-#else
-#  ifdef __code_model_large__
-#    define GET_EXTERN_POINTER(name, reg) \
-              pushq %r15; \
-              pushq %r14; \
-           1: leaq 1b(%rip), reg; \
-              movabsq $_GLOBAL_OFFSET_TABLE_-1b, %r14; \
-              movabsq $name@GOT, %r15; \
-              addq %r14, reg; \
-              popq %r14; \
-              movq (reg, %r15), reg; \
-              popq %r15;
-#  else
-#    define GET_EXTERN_POINTER(name, reg) movq name@GOTPCREL(%rip), reg
-#  endif
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -206,8 +183,13 @@ _gcry_cast5_amd64_encrypt_block:
         *      %rsi: dst
         *      %rdx: src
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
 
        movq %rsi, %r10;
 
@@ -232,8 +214,13 @@ _gcry_cast5_amd64_encrypt_block:
        write_block();
 
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
-       ret;
+       CFI_POP(%rbp);
+
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_cast5_amd64_encrypt_block,.-_gcry_cast5_amd64_encrypt_block;)
 
 .align 8
@@ -246,8 +233,13 @@ _gcry_cast5_amd64_decrypt_block:
         *      %rsi: dst
         *      %rdx: src
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
 
        movq %rsi, %r10;
 
@@ -272,8 +264,13 @@ _gcry_cast5_amd64_decrypt_block:
        write_block();
 
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
-       ret;
+       CFI_POP(%rbp);
+
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_cast5_amd64_decrypt_block,.-_gcry_cast5_amd64_decrypt_block;)
 
 /**********************************************************************
@@ -386,6 +383,7 @@ __cast5_enc_blk4:
         * output:
         *      RLR0,RLR1,RLR2,RLR3: four output ciphertext blocks
         */
+       CFI_STARTPROC();
        GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
 
        get_round_km(0, RKM0d);
@@ -401,7 +399,8 @@ __cast5_enc_blk4:
        round_enc_last4(14, F4_3, F4_1);
 
        outbswap_block4(RLR0, RLR1, RLR2, RLR3);
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __cast5_enc_blk4,.-__cast5_enc_blk4;)
 
 .align 8
@@ -414,6 +413,7 @@ __cast5_dec_blk4:
         * output:
         *      RLR0,RLR1,RLR2,RLR3: four output plaintext blocks
         */
+       CFI_STARTPROC();
        GET_EXTERN_POINTER(_gcry_cast5_s1to4, RTAB);
 
        inbswap_block4(RLR0, RLR1, RLR2, RLR3);
@@ -431,7 +431,8 @@ __cast5_dec_blk4:
        round_dec_last4(1, F4_2, F4_1);
 
        outbswap_block4(RLR0, RLR1, RLR2, RLR3);
-       ret;
+       CFI_ENDPROC();
+       ret_spec_stop;
 ELF(.size __cast5_dec_blk4,.-__cast5_dec_blk4;)
 
 .align 8
@@ -440,19 +441,28 @@ ELF(.type   _gcry_cast5_amd64_ctr_enc,@function;)
 _gcry_cast5_amd64_ctr_enc:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst (8 blocks)
-        *      %rdx: src (8 blocks)
+        *      %rsi: dst (4 blocks)
+        *      %rdx: src (4 blocks)
         *      %rcx: iv (big endian, 64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
        pushq %r14;
+       CFI_PUSH(%r14);
 
        pushq %rsi;
+       CFI_PUSH(%rsi);
        pushq %rdx;
+       CFI_PUSH(%rdx);
 
        /* load IV and byteswap */
        movq (%rcx), RX0;
@@ -472,7 +482,9 @@ _gcry_cast5_amd64_ctr_enc:
        call __cast5_enc_blk4;
 
        popq %r14; /*src*/
+       CFI_POP_TMP_REG();
        popq %r13; /*dst*/
+       CFI_POP_TMP_REG();
 
        /* XOR key-stream with plaintext */
        xorq 0 * 8(%r14), RLR0;
@@ -485,11 +497,19 @@ _gcry_cast5_amd64_ctr_enc:
        movq RLR3, 3 * 8(%r13);
 
        popq %r14;
+       CFI_POP(%r14);
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
-       ret
+       CFI_POP(%rbp);
+
+       EXIT_SYSV_FUNC
+       ret_spec_stop
+       CFI_ENDPROC();
 ELF(.size _gcry_cast5_amd64_ctr_enc,.-_gcry_cast5_amd64_ctr_enc;)
 
 .align 8
@@ -498,20 +518,30 @@ ELF(.type   _gcry_cast5_amd64_cbc_dec,@function;)
 _gcry_cast5_amd64_cbc_dec:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst (8 blocks)
-        *      %rdx: src (8 blocks)
+        *      %rsi: dst (4 blocks)
+        *      %rdx: src (4 blocks)
         *      %rcx: iv (64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
        pushq %r14;
+       CFI_PUSH(%r14);
 
        pushq %rcx;
+       CFI_PUSH(%rcx);
        pushq %rsi;
+       CFI_PUSH(%rsi);
        pushq %rdx;
+       CFI_PUSH(%rdx);
 
        /* load input */
        movq 0 * 8(%rdx), RLR0;
@@ -522,8 +552,11 @@ _gcry_cast5_amd64_cbc_dec:
        call __cast5_dec_blk4;
 
        popq RX0; /*src*/
+       CFI_POP_TMP_REG();
        popq RX1; /*dst*/
+       CFI_POP_TMP_REG();
        popq RX2; /*iv*/
+       CFI_POP_TMP_REG();
 
        movq 3 * 8(RX0), %r14;
        xorq      (RX2), RLR0;
@@ -538,12 +571,19 @@ _gcry_cast5_amd64_cbc_dec:
        movq RLR3, 3 * 8(RX1);
 
        popq %r14;
+       CFI_POP(%r14);
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
-       ret;
+       CFI_POP(%rbp);
 
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_cast5_amd64_cbc_dec,.-_gcry_cast5_amd64_cbc_dec;)
 
 .align 8
@@ -552,19 +592,28 @@ ELF(.type   _gcry_cast5_amd64_cfb_dec,@function;)
 _gcry_cast5_amd64_cfb_dec:
        /* input:
         *      %rdi: ctx, CTX
-        *      %rsi: dst (8 blocks)
-        *      %rdx: src (8 blocks)
+        *      %rsi: dst (4 blocks)
+        *      %rdx: src (4 blocks)
         *      %rcx: iv (64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
        pushq %r14;
+       CFI_PUSH(%r14);
 
        pushq %rsi;
+       CFI_PUSH(%rsi);
        pushq %rdx;
+       CFI_PUSH(%rdx);
 
        /* Load input */
        movq (%rcx), RLR0;
@@ -581,7 +630,9 @@ _gcry_cast5_amd64_cfb_dec:
        call __cast5_enc_blk4;
 
        popq %rdx; /*src*/
+       CFI_POP_TMP_REG();
        popq %rcx; /*dst*/
+       CFI_POP_TMP_REG();
 
        xorq 0 * 8(%rdx), RLR0;
        xorq 1 * 8(%rdx), RLR1;
@@ -593,12 +644,19 @@ _gcry_cast5_amd64_cfb_dec:
        movq RLR3, 3 * 8(%rcx);
 
        popq %r14;
+       CFI_POP(%r14);
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
-       ret;
+       CFI_POP(%rbp);
 
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_cast5_amd64_cfb_dec,.-_gcry_cast5_amd64_cfb_dec;)
 
 #endif /*defined(USE_CAST5)*/
index 94dcee7..837ea0f 100644 (file)
@@ -44,6 +44,7 @@
 #include "cipher.h"
 #include "bithelp.h"
 #include "bufhelp.h"
+#include "cipher-internal.h"
 #include "cipher-selftest.h"
 
 /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */
@@ -72,7 +73,8 @@ typedef struct {
 #endif
 } CAST5_context;
 
-static gcry_err_code_t cast_setkey (void *c, const byte *key, unsigned keylen);
+static gcry_err_code_t cast_setkey (void *c, const byte *key, unsigned keylen,
+                                    cipher_bulk_ops_t *bulk_ops);
 static unsigned int encrypt_block (void *c, byte *outbuf, const byte *inbuf);
 static unsigned int decrypt_block (void *c, byte *outbuf, const byte *inbuf);
 
@@ -373,72 +375,34 @@ extern void _gcry_cast5_amd64_cbc_dec(CAST5_context *ctx, byte *out,
 extern void _gcry_cast5_amd64_cfb_dec(CAST5_context *ctx, byte *out,
                                      const byte *in, byte *iv);
 
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-static inline void
-call_sysv_fn (const void *fn, const void *arg1, const void *arg2,
-              const void *arg3, const void *arg4)
-{
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  asm volatile ("callq *%0\n\t"
-                : "+a" (fn),
-                  "+D" (arg1),
-                  "+S" (arg2),
-                  "+d" (arg3),
-                  "+c" (arg4)
-                :
-                : "cc", "memory", "r8", "r9", "r10", "r11");
-}
-#endif
-
 static void
 do_encrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_cast5_amd64_encrypt_block, context, outbuf, inbuf, NULL);
-#else
   _gcry_cast5_amd64_encrypt_block (context, outbuf, inbuf);
-#endif
 }
 
 static void
 do_decrypt_block (CAST5_context *context, byte *outbuf, const byte *inbuf)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_cast5_amd64_decrypt_block, context, outbuf, inbuf, NULL);
-#else
   _gcry_cast5_amd64_decrypt_block (context, outbuf, inbuf);
-#endif
 }
 
 static void
 cast5_amd64_ctr_enc(CAST5_context *ctx, byte *out, const byte *in, byte *ctr)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_cast5_amd64_ctr_enc, ctx, out, in, ctr);
-#else
   _gcry_cast5_amd64_ctr_enc (ctx, out, in, ctr);
-#endif
 }
 
 static void
 cast5_amd64_cbc_dec(CAST5_context *ctx, byte *out, const byte *in, byte *iv)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_cast5_amd64_cbc_dec, ctx, out, in, iv);
-#else
   _gcry_cast5_amd64_cbc_dec (ctx, out, in, iv);
-#endif
 }
 
 static void
 cast5_amd64_cfb_dec(CAST5_context *ctx, byte *out, const byte *in, byte *iv)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_cast5_amd64_cfb_dec, ctx, out, in, iv);
-#else
   _gcry_cast5_amd64_cfb_dec (ctx, out, in, iv);
-#endif
 }
 
 static unsigned int
@@ -519,10 +483,10 @@ do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf )
     u32 l, r, t;
     u32 I;   /* used by the Fx macros */
     u32 *Km;
-    byte *Kr;
+    u32 Kr;
 
     Km = c->Km;
-    Kr = c->Kr;
+    Kr = buf_get_le32(c->Kr + 0);
 
     /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and
      * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.)
@@ -538,22 +502,22 @@ do_encrypt_block( CAST5_context *c, byte *outbuf, const byte *inbuf )
      * Rounds 3, 6, 9, 12, and 15 use f function Type 3.
      */
 
-    t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
-    t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
-    t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
-    t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
-    t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
-    t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
-    t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
-    t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
-    t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
-    t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
-    t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
-    t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
-    t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
-    t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
-    t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
-    t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
+    t = l; l = r; r = t ^ F1(r, Km[ 0], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F2(r, Km[ 1], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F3(r, Km[ 2], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F1(r, Km[ 3], Kr & 31); Kr = buf_get_le32(c->Kr + 4);
+    t = l; l = r; r = t ^ F2(r, Km[ 4], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F3(r, Km[ 5], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F1(r, Km[ 6], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F2(r, Km[ 7], Kr & 31); Kr = buf_get_le32(c->Kr + 8);
+    t = l; l = r; r = t ^ F3(r, Km[ 8], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F1(r, Km[ 9], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F2(r, Km[10], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F3(r, Km[11], Kr & 31); Kr = buf_get_le32(c->Kr + 12);
+    t = l; l = r; r = t ^ F1(r, Km[12], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F2(r, Km[13], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F3(r, Km[14], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F1(r, Km[15], Kr & 31);
 
     /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and
      * concatenate to form the ciphertext.) */
@@ -571,35 +535,126 @@ encrypt_block (void *context , byte *outbuf, const byte *inbuf)
 
 
 static void
+do_encrypt_block_3( CAST5_context *c, byte *outbuf, const byte *inbuf )
+{
+    u32 l0, r0, t0, l1, r1, t1, l2, r2, t2;
+    u32 I;   /* used by the Fx macros */
+    u32 *Km;
+    u32 Kr;
+
+    Km = c->Km;
+    Kr = buf_get_le32(c->Kr + 0);
+
+    l0 = buf_get_be32(inbuf + 0);
+    r0 = buf_get_be32(inbuf + 4);
+    l1 = buf_get_be32(inbuf + 8);
+    r1 = buf_get_be32(inbuf + 12);
+    l2 = buf_get_be32(inbuf + 16);
+    r2 = buf_get_be32(inbuf + 20);
+
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[ 0], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[ 0], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[ 0], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[ 1], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[ 1], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[ 1], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[ 2], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[ 2], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[ 2], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[ 3], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[ 3], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[ 3], Kr & 31);
+    Kr = buf_get_le32(c->Kr + 4);
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[ 4], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[ 4], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[ 4], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[ 5], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[ 5], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[ 5], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[ 6], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[ 6], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[ 6], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[ 7], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[ 7], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[ 7], Kr & 31);
+    Kr = buf_get_le32(c->Kr + 8);
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[ 8], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[ 8], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[ 8], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[ 9], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[ 9], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[ 9], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[10], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[10], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[10], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[11], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[11], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[11], Kr & 31);
+    Kr = buf_get_le32(c->Kr + 12);
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[12], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[12], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[12], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[13], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[13], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[13], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[14], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[14], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[14], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[15], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[15], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[15], Kr & 31);
+
+    buf_put_be32(outbuf + 0, r0);
+    buf_put_be32(outbuf + 4, l0);
+    buf_put_be32(outbuf + 8, r1);
+    buf_put_be32(outbuf + 12, l1);
+    buf_put_be32(outbuf + 16, r2);
+    buf_put_be32(outbuf + 20, l2);
+}
+
+
+static void
 do_decrypt_block (CAST5_context *c, byte *outbuf, const byte *inbuf )
 {
     u32 l, r, t;
     u32 I;
     u32 *Km;
-    byte *Kr;
+    u32 Kr;
 
     Km = c->Km;
-    Kr = c->Kr;
+    Kr = buf_get_be32(c->Kr + 12);
 
     l = buf_get_be32(inbuf + 0);
     r = buf_get_be32(inbuf + 4);
 
-    t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
-    t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
-    t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
-    t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
-    t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
-    t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
-    t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
-    t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
-    t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
-    t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
-    t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
-    t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
-    t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
-    t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
-    t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
-    t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
+    t = l; l = r; r = t ^ F1(r, Km[15], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F3(r, Km[14], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F2(r, Km[13], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F1(r, Km[12], Kr & 31); Kr = buf_get_be32(c->Kr + 8);
+    t = l; l = r; r = t ^ F3(r, Km[11], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F2(r, Km[10], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F1(r, Km[ 9], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F3(r, Km[ 8], Kr & 31); Kr = buf_get_be32(c->Kr + 4);
+    t = l; l = r; r = t ^ F2(r, Km[ 7], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F1(r, Km[ 6], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F3(r, Km[ 5], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F2(r, Km[ 4], Kr & 31); Kr = buf_get_be32(c->Kr + 0);
+    t = l; l = r; r = t ^ F1(r, Km[ 3], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F3(r, Km[ 2], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F2(r, Km[ 1], Kr & 31); Kr >>= 8;
+    t = l; l = r; r = t ^ F1(r, Km[ 0], Kr & 31);
 
     buf_put_be32(outbuf + 0, r);
     buf_put_be32(outbuf + 4, l);
@@ -613,23 +668,112 @@ decrypt_block (void *context, byte *outbuf, const byte *inbuf)
   return /*burn_stack*/ (20+4*sizeof(void*));
 }
 
+
+static void
+do_decrypt_block_3 (CAST5_context *c, byte *outbuf, const byte *inbuf )
+{
+    u32 l0, r0, t0, l1, r1, t1, l2, r2, t2;
+    u32 I;
+    u32 *Km;
+    u32 Kr;
+
+    Km = c->Km;
+    Kr = buf_get_be32(c->Kr + 12);
+
+    l0 = buf_get_be32(inbuf + 0);
+    r0 = buf_get_be32(inbuf + 4);
+    l1 = buf_get_be32(inbuf + 8);
+    r1 = buf_get_be32(inbuf + 12);
+    l2 = buf_get_be32(inbuf + 16);
+    r2 = buf_get_be32(inbuf + 20);
+
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[15], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[15], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[15], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[14], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[14], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[14], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[13], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[13], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[13], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[12], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[12], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[12], Kr & 31);
+    Kr = buf_get_be32(c->Kr + 8);
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[11], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[11], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[11], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[10], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[10], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[10], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[ 9], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[ 9], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[ 9], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[ 8], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[ 8], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[ 8], Kr & 31);
+    Kr = buf_get_be32(c->Kr + 4);
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[ 7], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[ 7], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[ 7], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[ 6], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[ 6], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[ 6], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[ 5], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[ 5], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[ 5], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[ 4], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[ 4], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[ 4], Kr & 31);
+    Kr = buf_get_be32(c->Kr + 0);
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[ 3], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[ 3], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[ 3], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F3(r0, Km[ 2], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F3(r1, Km[ 2], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F3(r2, Km[ 2], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F2(r0, Km[ 1], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F2(r1, Km[ 1], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F2(r2, Km[ 1], Kr & 31);
+    Kr >>= 8;
+    t0 = l0; l0 = r0; r0 = t0 ^ F1(r0, Km[ 0], Kr & 31);
+           t1 = l1; l1 = r1; r1 = t1 ^ F1(r1, Km[ 0], Kr & 31);
+                   t2 = l2; l2 = r2; r2 = t2 ^ F1(r2, Km[ 0], Kr & 31);
+
+    buf_put_be32(outbuf + 0, r0);
+    buf_put_be32(outbuf + 4, l0);
+    buf_put_be32(outbuf + 8, r1);
+    buf_put_be32(outbuf + 12, l1);
+    buf_put_be32(outbuf + 16, r2);
+    buf_put_be32(outbuf + 20, l2);
+}
+
 #endif /*!USE_ARM_ASM*/
 
 
 /* Bulk encryption of complete blocks in CTR mode.  This function is only
    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
    of size CAST5_BLOCKSIZE. */
-void
+static void
 _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
                    const void *inbuf_arg, size_t nblocks)
 {
   CAST5_context *ctx = context;
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
-  unsigned char tmpbuf[CAST5_BLOCKSIZE];
-  int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE;
-
-  int i;
+  unsigned char tmpbuf[CAST5_BLOCKSIZE * 3];
+  int burn_stack_depth = (20 + 4 * sizeof(void*)) + 4 * CAST5_BLOCKSIZE;
 
 #ifdef USE_AMD64_ASM
   {
@@ -647,7 +791,6 @@ _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
       }
 
     /* Use generic code to handle smaller chunks... */
-    /* TODO: use caching instead? */
   }
 #elif defined(USE_ARM_ASM)
   {
@@ -662,25 +805,38 @@ _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
       }
 
     /* Use generic code to handle smaller chunks... */
-    /* TODO: use caching instead? */
   }
 #endif
 
+#if !defined(USE_AMD64_ASM) && !defined(USE_ARM_ASM)
+  for ( ;nblocks >= 3; nblocks -= 3)
+    {
+      /* Prepare the counter blocks. */
+      cipher_block_cpy (tmpbuf + 0, ctr, CAST5_BLOCKSIZE);
+      cipher_block_cpy (tmpbuf + 8, ctr, CAST5_BLOCKSIZE);
+      cipher_block_cpy (tmpbuf + 16, ctr, CAST5_BLOCKSIZE);
+      cipher_block_add (tmpbuf + 8, 1, CAST5_BLOCKSIZE);
+      cipher_block_add (tmpbuf + 16, 2, CAST5_BLOCKSIZE);
+      cipher_block_add (ctr, 3, CAST5_BLOCKSIZE);
+      /* Encrypt the counter. */
+      do_encrypt_block_3(ctx, tmpbuf, tmpbuf);
+      /* XOR the input with the encrypted counter and store in output.  */
+      buf_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE * 3);
+      outbuf += CAST5_BLOCKSIZE * 3;
+      inbuf  += CAST5_BLOCKSIZE * 3;
+    }
+#endif
+
   for ( ;nblocks; nblocks-- )
     {
       /* Encrypt the counter. */
       do_encrypt_block(ctx, tmpbuf, ctr);
       /* XOR the input with the encrypted counter and store in output.  */
-      buf_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE);
+      cipher_block_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE);
       outbuf += CAST5_BLOCKSIZE;
       inbuf  += CAST5_BLOCKSIZE;
       /* Increment the counter.  */
-      for (i = CAST5_BLOCKSIZE; i > 0; i--)
-        {
-          ctr[i-1]++;
-          if (ctr[i-1])
-            break;
-        }
+      cipher_block_add (ctr, 1, CAST5_BLOCKSIZE);
     }
 
   wipememory(tmpbuf, sizeof(tmpbuf));
@@ -690,15 +846,15 @@ _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
 
 /* Bulk decryption of complete blocks in CBC mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
                    const void *inbuf_arg, size_t nblocks)
 {
   CAST5_context *ctx = context;
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
-  unsigned char savebuf[CAST5_BLOCKSIZE];
-  int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE;
+  unsigned char savebuf[CAST5_BLOCKSIZE * 3];
+  int burn_stack_depth = (20 + 4 * sizeof(void*)) + 4 * CAST5_BLOCKSIZE;
 
 #ifdef USE_AMD64_ASM
   {
@@ -733,13 +889,29 @@ _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
   }
 #endif
 
+#if !defined(USE_AMD64_ASM) && !defined(USE_ARM_ASM)
+  for ( ;nblocks >= 3; nblocks -= 3)
+    {
+      /* INBUF is needed later and it may be identical to OUTBUF, so store
+         the intermediate result to SAVEBUF.  */
+      do_decrypt_block_3 (ctx, savebuf, inbuf);
+
+      cipher_block_xor_1 (savebuf + 0, iv, CAST5_BLOCKSIZE);
+      cipher_block_xor_1 (savebuf + 8, inbuf, CAST5_BLOCKSIZE * 2);
+      cipher_block_cpy (iv, inbuf + 16, CAST5_BLOCKSIZE);
+      buf_cpy (outbuf, savebuf, CAST5_BLOCKSIZE * 3);
+      inbuf += CAST5_BLOCKSIZE * 3;
+      outbuf += CAST5_BLOCKSIZE * 3;
+    }
+#endif
+
   for ( ;nblocks; nblocks-- )
     {
       /* INBUF is needed later and it may be identical to OUTBUF, so store
          the intermediate result to SAVEBUF.  */
       do_decrypt_block (ctx, savebuf, inbuf);
 
-      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAST5_BLOCKSIZE);
+      cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAST5_BLOCKSIZE);
       inbuf += CAST5_BLOCKSIZE;
       outbuf += CAST5_BLOCKSIZE;
     }
@@ -750,14 +922,15 @@ _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
 
 /* Bulk decryption of complete blocks in CFB mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_cast5_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
                    const void *inbuf_arg, size_t nblocks)
 {
   CAST5_context *ctx = context;
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
-  int burn_stack_depth = (20 + 4 * sizeof(void*)) + 2 * CAST5_BLOCKSIZE;
+  unsigned char tmpbuf[CAST5_BLOCKSIZE * 3];
+  int burn_stack_depth = (20 + 4 * sizeof(void*)) + 4 * CAST5_BLOCKSIZE;
 
 #ifdef USE_AMD64_ASM
   {
@@ -792,14 +965,28 @@ _gcry_cast5_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
   }
 #endif
 
+#if !defined(USE_AMD64_ASM) && !defined(USE_ARM_ASM)
+  for ( ;nblocks >= 3; nblocks -= 3 )
+    {
+      cipher_block_cpy (tmpbuf + 0, iv, CAST5_BLOCKSIZE);
+      cipher_block_cpy (tmpbuf + 8, inbuf + 0, CAST5_BLOCKSIZE * 2);
+      cipher_block_cpy (iv, inbuf + 16, CAST5_BLOCKSIZE);
+      do_encrypt_block_3 (ctx, tmpbuf, tmpbuf);
+      buf_xor (outbuf, inbuf, tmpbuf, CAST5_BLOCKSIZE * 3);
+      outbuf += CAST5_BLOCKSIZE * 3;
+      inbuf  += CAST5_BLOCKSIZE * 3;
+    }
+#endif
+
   for ( ;nblocks; nblocks-- )
     {
       do_encrypt_block(ctx, iv, iv);
-      buf_xor_n_copy(outbuf, iv, inbuf, CAST5_BLOCKSIZE);
+      cipher_block_xor_n_copy(outbuf, iv, inbuf, CAST5_BLOCKSIZE);
       outbuf += CAST5_BLOCKSIZE;
       inbuf  += CAST5_BLOCKSIZE;
     }
 
+  wipememory(tmpbuf, sizeof(tmpbuf));
   _gcry_burn_stack(burn_stack_depth);
 }
 
@@ -814,8 +1001,7 @@ selftest_ctr (void)
   const int context_size = sizeof(CAST5_context);
 
   return _gcry_selftest_helper_ctr("CAST5", &cast_setkey,
-           &encrypt_block, &_gcry_cast5_ctr_enc, nblocks, blocksize,
-          context_size);
+           &encrypt_block, nblocks, blocksize, context_size);
 }
 
 
@@ -829,8 +1015,7 @@ selftest_cbc (void)
   const int context_size = sizeof(CAST5_context);
 
   return _gcry_selftest_helper_cbc("CAST5", &cast_setkey,
-           &encrypt_block, &_gcry_cast5_cbc_dec, nblocks, blocksize,
-          context_size);
+           &encrypt_block, nblocks, blocksize, context_size);
 }
 
 
@@ -844,8 +1029,7 @@ selftest_cfb (void)
   const int context_size = sizeof(CAST5_context);
 
   return _gcry_selftest_helper_cfb("CAST5", &cast_setkey,
-           &encrypt_block, &_gcry_cast5_cfb_dec, nblocks, blocksize,
-          context_size);
+           &encrypt_block, nblocks, blocksize, context_size);
 }
 
 
@@ -853,6 +1037,7 @@ static const char*
 selftest(void)
 {
     CAST5_context c;
+    cipher_bulk_ops_t bulk_ops;
     static const byte key[16] =
                     { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
                      0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A  };
@@ -863,7 +1048,7 @@ selftest(void)
     byte buffer[8];
     const char *r;
 
-    cast_setkey( &c, key, 16 );
+    cast_setkey( &c, key, 16, &bulk_ops );
     encrypt_block( &c, buffer, plain );
     if( memcmp( buffer, cipher, 8 ) )
        return "1";
@@ -884,10 +1069,10 @@ selftest(void)
                        0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E };
 
        for(i=0; i < 1000000; i++ ) {
-           cast_setkey( &c, b0, 16 );
+           cast_setkey( &c, b0, 16, &bulk_ops );
            encrypt_block( &c, a0, a0 );
            encrypt_block( &c, a0+8, a0+8 );
-           cast_setkey( &c, a0, 16 );
+           cast_setkey( &c, a0, 16, &bulk_ops );
            encrypt_block( &c, b0, b0 );
            encrypt_block( &c, b0+8, b0+8 );
        }
@@ -1029,10 +1214,18 @@ do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen )
 }
 
 static gcry_err_code_t
-cast_setkey (void *context, const byte *key, unsigned keylen )
+cast_setkey (void *context, const byte *key, unsigned keylen,
+             cipher_bulk_ops_t *bulk_ops)
 {
   CAST5_context *c = (CAST5_context *) context;
   gcry_err_code_t rc = do_cast_setkey (c, key, keylen);
+
+  /* Setup bulk encryption routines.  */
+  memset (bulk_ops, 0, sizeof(*bulk_ops));
+  bulk_ops->cfb_dec = _gcry_cast5_cfb_dec;
+  bulk_ops->cbc_dec = _gcry_cast5_cbc_dec;
+  bulk_ops->ctr_enc = _gcry_cast5_ctr_enc;
+
   return rc;
 }
 
diff --git a/cipher/chacha20-aarch64.S b/cipher/chacha20-aarch64.S
new file mode 100644 (file)
index 0000000..2a980b9
--- /dev/null
@@ -0,0 +1,648 @@
+/* chacha20-aarch64.S - ARMv8/AArch64 accelerated chacha20 blocks function
+ *
+ * Copyright (C) 2017-2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Based on D. J. Bernstein reference implementation at
+ * http://cr.yp.to/chacha.html:
+ *
+ * chacha-regs.c version 20080118
+ * D. J. Bernstein
+ * Public domain.
+ */
+
+#include "asm-common-aarch64.h"
+
+#if defined(__AARCH64EL__) && \
+    defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_AARCH64_NEON) && \
+    defined(USE_CHACHA20)
+
+.cpu generic+simd
+
+.text
+
+#include "asm-poly1305-aarch64.h"
+
+/* register macros */
+#define INPUT     x0
+#define DST       x1
+#define SRC       x2
+#define NBLKS     x3
+#define ROUND     x4
+#define INPUT_CTR x5
+#define INPUT_POS x6
+#define CTR       x7
+
+/* vector registers */
+#define X0 v16
+#define X1 v17
+#define X2 v18
+#define X3 v19
+#define X4 v20
+#define X5 v21
+#define X6 v22
+#define X7 v23
+#define X8 v24
+#define X9 v25
+#define X10 v26
+#define X11 v27
+#define X12 v28
+#define X13 v29
+#define X14 v30
+#define X15 v31
+
+#define VCTR    v0
+#define VTMP0   v1
+#define VTMP1   v2
+#define VTMP2   v3
+#define VTMP3   v4
+#define X12_TMP v5
+#define X13_TMP v6
+#define ROT8    v7
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+
+#define _(...) __VA_ARGS__
+
+#define vpunpckldq(s1, s2, dst) \
+       zip1 dst.4s, s2.4s, s1.4s;
+
+#define vpunpckhdq(s1, s2, dst) \
+       zip2 dst.4s, s2.4s, s1.4s;
+
+#define vpunpcklqdq(s1, s2, dst) \
+       zip1 dst.2d, s2.2d, s1.2d;
+
+#define vpunpckhqdq(s1, s2, dst) \
+       zip2 dst.2d, s2.2d, s1.2d;
+
+/* 4x4 32-bit integer matrix transpose */
+#define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \
+       vpunpckhdq(x1, x0, t2); \
+       vpunpckldq(x1, x0, x0); \
+       \
+       vpunpckldq(x3, x2, t1); \
+       vpunpckhdq(x3, x2, x2); \
+       \
+       vpunpckhqdq(t1, x0, x1); \
+       vpunpcklqdq(t1, x0, x0); \
+       \
+       vpunpckhqdq(x2, t2, x3); \
+       vpunpcklqdq(x2, t2, x2);
+
+#define clear(x) \
+       movi x.16b, #0;
+
+/**********************************************************************
+  4-way chacha20
+ **********************************************************************/
+
+#define XOR(d,s1,s2) \
+       eor d.16b, s2.16b, s1.16b;
+
+#define PLUS(ds,s) \
+       add ds.4s, ds.4s, s.4s;
+
+#define ROTATE4(dst1,dst2,dst3,dst4,c,src1,src2,src3,src4,iop1,iop2,iop3) \
+       shl dst1.4s, src1.4s, #(c);             \
+       shl dst2.4s, src2.4s, #(c);             \
+       iop1;                                   \
+       shl dst3.4s, src3.4s, #(c);             \
+       shl dst4.4s, src4.4s, #(c);             \
+       iop2;                                   \
+       sri dst1.4s, src1.4s, #(32 - (c));      \
+       sri dst2.4s, src2.4s, #(32 - (c));      \
+       iop3;                                   \
+       sri dst3.4s, src3.4s, #(32 - (c));      \
+       sri dst4.4s, src4.4s, #(32 - (c));
+
+#define ROTATE4_8(dst1,dst2,dst3,dst4,src1,src2,src3,src4,iop1,iop2,iop3) \
+       tbl dst1.16b, {src1.16b}, ROT8.16b;     \
+       iop1;                                   \
+       tbl dst2.16b, {src2.16b}, ROT8.16b;     \
+       iop2;                                   \
+       tbl dst3.16b, {src3.16b}, ROT8.16b;     \
+       iop3;                                   \
+       tbl dst4.16b, {src4.16b}, ROT8.16b;
+
+#define ROTATE4_16(dst1,dst2,dst3,dst4,src1,src2,src3,src4,iop1) \
+       rev32 dst1.8h, src1.8h;                 \
+       rev32 dst2.8h, src2.8h;                 \
+       iop1;                                   \
+       rev32 dst3.8h, src3.8h;                 \
+       rev32 dst4.8h, src4.8h;
+
+#define QUARTERROUND4(a1,b1,c1,d1,a2,b2,c2,d2,a3,b3,c3,d3,a4,b4,c4,d4,ign,tmp1,tmp2,tmp3,tmp4,\
+                     iop1,iop2,iop3,iop4,iop5,iop6,iop7,iop8,iop9,iop10,iop11,iop12,iop13,iop14,\
+                     iop15,iop16,iop17,iop18,iop19,iop20,iop21,iop22,iop23,iop24,iop25,iop26,\
+                     iop27,iop28,iop29) \
+       PLUS(a1,b1); PLUS(a2,b2); iop1;                                         \
+       PLUS(a3,b3); PLUS(a4,b4); iop2;                                         \
+           XOR(tmp1,d1,a1); XOR(tmp2,d2,a2); iop3;                             \
+           XOR(tmp3,d3,a3); XOR(tmp4,d4,a4); iop4;                             \
+               ROTATE4_16(d1, d2, d3, d4, tmp1, tmp2, tmp3, tmp4, _(iop5));    \
+               iop6;                                                           \
+       PLUS(c1,d1); PLUS(c2,d2); iop7;                                         \
+       PLUS(c3,d3); PLUS(c4,d4); iop8;                                         \
+           XOR(tmp1,b1,c1); XOR(tmp2,b2,c2); iop9;                             \
+           XOR(tmp3,b3,c3); XOR(tmp4,b4,c4); iop10;                            \
+               ROTATE4(b1, b2, b3, b4, 12, tmp1, tmp2, tmp3, tmp4,             \
+                       _(iop11), _(iop12), _(iop13)); iop14;                   \
+       PLUS(a1,b1); PLUS(a2,b2); iop15;                                        \
+       PLUS(a3,b3); PLUS(a4,b4); iop16;                                        \
+           XOR(tmp1,d1,a1); XOR(tmp2,d2,a2); iop17;                            \
+           XOR(tmp3,d3,a3); XOR(tmp4,d4,a4); iop18;                            \
+               ROTATE4_8(d1, d2, d3, d4, tmp1, tmp2, tmp3, tmp4,               \
+                         _(iop19), _(iop20), _(iop21)); iop22;                 \
+       PLUS(c1,d1); PLUS(c2,d2); iop23;                                        \
+       PLUS(c3,d3); PLUS(c4,d4); iop24;                                        \
+           XOR(tmp1,b1,c1); XOR(tmp2,b2,c2); iop25;                            \
+           XOR(tmp3,b3,c3); XOR(tmp4,b4,c4); iop26;                            \
+               ROTATE4(b1, b2, b3, b4, 7, tmp1, tmp2, tmp3, tmp4,              \
+                       _(iop27), _(iop28), _(iop29));
+
+.align 4
+.globl _gcry_chacha20_aarch64_blocks4_data_inc_counter
+_gcry_chacha20_aarch64_blocks4_data_inc_counter:
+       .long 0,1,2,3
+
+.align 4
+.globl _gcry_chacha20_aarch64_blocks4_data_rot8
+_gcry_chacha20_aarch64_blocks4_data_rot8:
+       .byte 3,0,1,2
+       .byte 7,4,5,6
+       .byte 11,8,9,10
+       .byte 15,12,13,14
+
+.align 3
+.globl _gcry_chacha20_aarch64_blocks4
+ELF(.type _gcry_chacha20_aarch64_blocks4,%function;)
+
+_gcry_chacha20_aarch64_blocks4:
+       /* input:
+        *      x0: input
+        *      x1: dst
+        *      x2: src
+        *      x3: nblks (multiple of 4)
+        */
+       CFI_STARTPROC()
+
+       GET_DATA_POINTER(CTR, _gcry_chacha20_aarch64_blocks4_data_rot8);
+       add INPUT_CTR, INPUT, #(12*4);
+       ld1 {ROT8.16b}, [CTR];
+       GET_DATA_POINTER(CTR, _gcry_chacha20_aarch64_blocks4_data_inc_counter);
+       mov INPUT_POS, INPUT;
+       ld1 {VCTR.16b}, [CTR];
+
+.Loop4:
+       /* Construct counter vectors X12 and X13 */
+
+       ld1 {X15.16b}, [INPUT_CTR];
+       mov ROUND, #20;
+       ld1 {VTMP1.16b-VTMP3.16b}, [INPUT_POS];
+
+       dup X12.4s, X15.s[0];
+       dup X13.4s, X15.s[1];
+       ldr CTR, [INPUT_CTR];
+       add X12.4s, X12.4s, VCTR.4s;
+       dup X0.4s, VTMP1.s[0];
+       dup X1.4s, VTMP1.s[1];
+       dup X2.4s, VTMP1.s[2];
+       dup X3.4s, VTMP1.s[3];
+       dup X14.4s, X15.s[2];
+       cmhi VTMP0.4s, VCTR.4s, X12.4s;
+       dup X15.4s, X15.s[3];
+       add CTR, CTR, #4; /* Update counter */
+       dup X4.4s, VTMP2.s[0];
+       dup X5.4s, VTMP2.s[1];
+       dup X6.4s, VTMP2.s[2];
+       dup X7.4s, VTMP2.s[3];
+       sub X13.4s, X13.4s, VTMP0.4s;
+       dup X8.4s, VTMP3.s[0];
+       dup X9.4s, VTMP3.s[1];
+       dup X10.4s, VTMP3.s[2];
+       dup X11.4s, VTMP3.s[3];
+       mov X12_TMP.16b, X12.16b;
+       mov X13_TMP.16b, X13.16b;
+       str CTR, [INPUT_CTR];
+
+.Lround2:
+       subs ROUND, ROUND, #2
+       QUARTERROUND4(X0, X4,  X8, X12,   X1, X5,  X9, X13,
+                     X2, X6, X10, X14,   X3, X7, X11, X15,
+                     tmp:=,VTMP0,VTMP1,VTMP2,VTMP3,
+                     ,,,,,,,,,,,,,,,,,,,,,,,,,,,,)
+       QUARTERROUND4(X0, X5, X10, X15,   X1, X6, X11, X12,
+                     X2, X7,  X8, X13,   X3, X4,  X9, X14,
+                     tmp:=,VTMP0,VTMP1,VTMP2,VTMP3,
+                     ,,,,,,,,,,,,,,,,,,,,,,,,,,,,)
+       b.ne .Lround2;
+
+       ld1 {VTMP0.16b, VTMP1.16b}, [INPUT_POS], #32;
+
+       PLUS(X12, X12_TMP);        /* INPUT + 12 * 4 + counter */
+       PLUS(X13, X13_TMP);        /* INPUT + 13 * 4 + counter */
+
+       dup VTMP2.4s, VTMP0.s[0]; /* INPUT + 0 * 4 */
+       dup VTMP3.4s, VTMP0.s[1]; /* INPUT + 1 * 4 */
+       dup X12_TMP.4s, VTMP0.s[2]; /* INPUT + 2 * 4 */
+       dup X13_TMP.4s, VTMP0.s[3]; /* INPUT + 3 * 4 */
+       PLUS(X0, VTMP2);
+       PLUS(X1, VTMP3);
+       PLUS(X2, X12_TMP);
+       PLUS(X3, X13_TMP);
+
+       dup VTMP2.4s, VTMP1.s[0]; /* INPUT + 4 * 4 */
+       dup VTMP3.4s, VTMP1.s[1]; /* INPUT + 5 * 4 */
+       dup X12_TMP.4s, VTMP1.s[2]; /* INPUT + 6 * 4 */
+       dup X13_TMP.4s, VTMP1.s[3]; /* INPUT + 7 * 4 */
+       ld1 {VTMP0.16b, VTMP1.16b}, [INPUT_POS];
+       mov INPUT_POS, INPUT;
+       PLUS(X4, VTMP2);
+       PLUS(X5, VTMP3);
+       PLUS(X6, X12_TMP);
+       PLUS(X7, X13_TMP);
+
+       dup VTMP2.4s, VTMP0.s[0]; /* INPUT + 8 * 4 */
+       dup VTMP3.4s, VTMP0.s[1]; /* INPUT + 9 * 4 */
+       dup X12_TMP.4s, VTMP0.s[2]; /* INPUT + 10 * 4 */
+       dup X13_TMP.4s, VTMP0.s[3]; /* INPUT + 11 * 4 */
+       dup VTMP0.4s, VTMP1.s[2]; /* INPUT + 14 * 4 */
+       dup VTMP1.4s, VTMP1.s[3]; /* INPUT + 15 * 4 */
+       PLUS(X8, VTMP2);
+       PLUS(X9, VTMP3);
+       PLUS(X10, X12_TMP);
+       PLUS(X11, X13_TMP);
+       PLUS(X14, VTMP0);
+       PLUS(X15, VTMP1);
+
+       transpose_4x4(X0, X1, X2, X3, VTMP0, VTMP1, VTMP2);
+       transpose_4x4(X4, X5, X6, X7, VTMP0, VTMP1, VTMP2);
+       transpose_4x4(X8, X9, X10, X11, VTMP0, VTMP1, VTMP2);
+       transpose_4x4(X12, X13, X14, X15, VTMP0, VTMP1, VTMP2);
+
+       subs NBLKS, NBLKS, #4;
+
+       ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
+       ld1 {X12_TMP.16b-X13_TMP.16b}, [SRC], #32;
+       eor VTMP0.16b, X0.16b, VTMP0.16b;
+       eor VTMP1.16b, X4.16b, VTMP1.16b;
+       eor VTMP2.16b, X8.16b, VTMP2.16b;
+       eor VTMP3.16b, X12.16b, VTMP3.16b;
+       eor X12_TMP.16b, X1.16b, X12_TMP.16b;
+       eor X13_TMP.16b, X5.16b, X13_TMP.16b;
+       st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
+       ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
+       st1 {X12_TMP.16b-X13_TMP.16b}, [DST], #32;
+       ld1 {X12_TMP.16b-X13_TMP.16b}, [SRC], #32;
+       eor VTMP0.16b, X9.16b, VTMP0.16b;
+       eor VTMP1.16b, X13.16b, VTMP1.16b;
+       eor VTMP2.16b, X2.16b, VTMP2.16b;
+       eor VTMP3.16b, X6.16b, VTMP3.16b;
+       eor X12_TMP.16b, X10.16b, X12_TMP.16b;
+       eor X13_TMP.16b, X14.16b, X13_TMP.16b;
+       st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
+       ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
+       st1 {X12_TMP.16b-X13_TMP.16b}, [DST], #32;
+       eor VTMP0.16b, X3.16b, VTMP0.16b;
+       eor VTMP1.16b, X7.16b, VTMP1.16b;
+       eor VTMP2.16b, X11.16b, VTMP2.16b;
+       eor VTMP3.16b, X15.16b, VTMP3.16b;
+       st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
+
+       b.ne .Loop4;
+
+       /* clear the used vector registers and stack */
+       clear(VTMP0);
+       clear(VTMP1);
+       clear(VTMP2);
+       clear(VTMP3);
+       clear(X12_TMP);
+       clear(X13_TMP);
+       clear(X0);
+       clear(X1);
+       clear(X2);
+       clear(X3);
+       clear(X4);
+       clear(X5);
+       clear(X6);
+       clear(X7);
+       clear(X8);
+       clear(X9);
+       clear(X10);
+       clear(X11);
+       clear(X12);
+       clear(X13);
+       clear(X14);
+       clear(X15);
+
+       eor x0, x0, x0
+       ret_spec_stop
+       CFI_ENDPROC()
+ELF(.size _gcry_chacha20_aarch64_blocks4, .-_gcry_chacha20_aarch64_blocks4;)
+
+/**********************************************************************
+  4-way stitched chacha20-poly1305
+ **********************************************************************/
+
+.align 3
+.globl _gcry_chacha20_poly1305_aarch64_blocks4
+ELF(.type _gcry_chacha20_poly1305_aarch64_blocks4,%function;)
+
+_gcry_chacha20_poly1305_aarch64_blocks4:
+       /* input:
+        *      x0: input
+        *      x1: dst
+        *      x2: src
+        *      x3: nblks (multiple of 4)
+        *      x4: poly1305-state
+        *      x5: poly1305-src
+        */
+       CFI_STARTPROC()
+       POLY1305_PUSH_REGS()
+
+       mov POLY_RSTATE, x4;
+       mov POLY_RSRC, x5;
+
+       GET_DATA_POINTER(CTR, _gcry_chacha20_aarch64_blocks4_data_rot8);
+       add INPUT_CTR, INPUT, #(12*4);
+       ld1 {ROT8.16b}, [CTR];
+       GET_DATA_POINTER(CTR, _gcry_chacha20_aarch64_blocks4_data_inc_counter);
+       mov INPUT_POS, INPUT;
+       ld1 {VCTR.16b}, [CTR];
+
+       POLY1305_LOAD_STATE()
+
+.Loop_poly4:
+       /* Construct counter vectors X12 and X13 */
+
+       ld1 {X15.16b}, [INPUT_CTR];
+       ld1 {VTMP1.16b-VTMP3.16b}, [INPUT_POS];
+
+       dup X12.4s, X15.s[0];
+       dup X13.4s, X15.s[1];
+       ldr CTR, [INPUT_CTR];
+       add X12.4s, X12.4s, VCTR.4s;
+       dup X0.4s, VTMP1.s[0];
+       dup X1.4s, VTMP1.s[1];
+       dup X2.4s, VTMP1.s[2];
+       dup X3.4s, VTMP1.s[3];
+       dup X14.4s, X15.s[2];
+       cmhi VTMP0.4s, VCTR.4s, X12.4s;
+       dup X15.4s, X15.s[3];
+       add CTR, CTR, #4; /* Update counter */
+       dup X4.4s, VTMP2.s[0];
+       dup X5.4s, VTMP2.s[1];
+       dup X6.4s, VTMP2.s[2];
+       dup X7.4s, VTMP2.s[3];
+       sub X13.4s, X13.4s, VTMP0.4s;
+       dup X8.4s, VTMP3.s[0];
+       dup X9.4s, VTMP3.s[1];
+       dup X10.4s, VTMP3.s[2];
+       dup X11.4s, VTMP3.s[3];
+       mov X12_TMP.16b, X12.16b;
+       mov X13_TMP.16b, X13.16b;
+       str CTR, [INPUT_CTR];
+
+       mov ROUND, #20
+.Lround4_with_poly1305_outer:
+       mov POLY_CHACHA_ROUND, #6;
+.Lround4_with_poly1305_inner1:
+                     POLY1305_BLOCK_PART1(0 * 16)
+       QUARTERROUND4(X0, X4,  X8, X12,   X1, X5,  X9, X13,
+                     X2, X6, X10, X14,   X3, X7, X11, X15,
+                     tmp:=,VTMP0,VTMP1,VTMP2,VTMP3,
+                     POLY1305_BLOCK_PART2(0 * 16),
+                     POLY1305_BLOCK_PART3(),
+                     POLY1305_BLOCK_PART4(),
+                     POLY1305_BLOCK_PART5(),
+                     POLY1305_BLOCK_PART6(),
+                     POLY1305_BLOCK_PART7(),
+                     POLY1305_BLOCK_PART8(),
+                     POLY1305_BLOCK_PART9(),
+                     POLY1305_BLOCK_PART10(),
+                     POLY1305_BLOCK_PART11(),
+                     POLY1305_BLOCK_PART12(),
+                     POLY1305_BLOCK_PART13(),
+                     POLY1305_BLOCK_PART14(),
+                     POLY1305_BLOCK_PART15(),
+                     POLY1305_BLOCK_PART16(),
+                     POLY1305_BLOCK_PART17(),
+                     POLY1305_BLOCK_PART18(),
+                     POLY1305_BLOCK_PART19(),
+                     POLY1305_BLOCK_PART20(),
+                     POLY1305_BLOCK_PART21(),
+                     POLY1305_BLOCK_PART22(),
+                     POLY1305_BLOCK_PART23(),
+                     POLY1305_BLOCK_PART24(),
+                     POLY1305_BLOCK_PART25(),
+                     POLY1305_BLOCK_PART26(),
+                     POLY1305_BLOCK_PART27(),
+                     POLY1305_BLOCK_PART28(),
+                     POLY1305_BLOCK_PART29(),
+                     POLY1305_BLOCK_PART1(1 * 16))
+                     POLY1305_BLOCK_PART2(1 * 16)
+       QUARTERROUND4(X0, X5, X10, X15,   X1, X6, X11, X12,
+                     X2, X7,  X8, X13,   X3, X4,  X9, X14,
+                     tmp:=,VTMP0,VTMP1,VTMP2,VTMP3,
+                     _(add POLY_RSRC, POLY_RSRC, #(2*16)),
+                     POLY1305_BLOCK_PART3(),
+                     POLY1305_BLOCK_PART4(),
+                     POLY1305_BLOCK_PART5(),
+                     POLY1305_BLOCK_PART6(),
+                     POLY1305_BLOCK_PART7(),
+                     POLY1305_BLOCK_PART8(),
+                     POLY1305_BLOCK_PART9(),
+                     POLY1305_BLOCK_PART10(),
+                     POLY1305_BLOCK_PART11(),
+                     POLY1305_BLOCK_PART12(),
+                     POLY1305_BLOCK_PART13(),
+                     POLY1305_BLOCK_PART14(),
+                     POLY1305_BLOCK_PART15(),
+                     POLY1305_BLOCK_PART16(),
+                     POLY1305_BLOCK_PART17(),
+                     POLY1305_BLOCK_PART18(),
+                     POLY1305_BLOCK_PART19(),
+                     POLY1305_BLOCK_PART20(),
+                     POLY1305_BLOCK_PART21(),
+                     POLY1305_BLOCK_PART22(),
+                     POLY1305_BLOCK_PART23(),
+                     POLY1305_BLOCK_PART24(),
+                     POLY1305_BLOCK_PART25(),
+                     POLY1305_BLOCK_PART26(),
+                     POLY1305_BLOCK_PART27(),
+                     POLY1305_BLOCK_PART28(),
+                     POLY1305_BLOCK_PART29(),
+                     _(subs POLY_CHACHA_ROUND, POLY_CHACHA_ROUND, #2));
+       b.ne .Lround4_with_poly1305_inner1;
+
+       mov POLY_CHACHA_ROUND, #4;
+.Lround4_with_poly1305_inner2:
+                     POLY1305_BLOCK_PART1(0 * 16)
+       QUARTERROUND4(X0, X4,  X8, X12,   X1, X5,  X9, X13,
+                     X2, X6, X10, X14,   X3, X7, X11, X15,
+                     tmp:=,VTMP0,VTMP1,VTMP2,VTMP3,,
+                     POLY1305_BLOCK_PART2(0 * 16),,
+                     _(add POLY_RSRC, POLY_RSRC, #(1*16)),,
+                     POLY1305_BLOCK_PART3(),,
+                     POLY1305_BLOCK_PART4(),,
+                     POLY1305_BLOCK_PART5(),,
+                     POLY1305_BLOCK_PART6(),,
+                     POLY1305_BLOCK_PART7(),,
+                     POLY1305_BLOCK_PART8(),,
+                     POLY1305_BLOCK_PART9(),,
+                     POLY1305_BLOCK_PART10(),,
+                     POLY1305_BLOCK_PART11(),,
+                     POLY1305_BLOCK_PART12(),,
+                     POLY1305_BLOCK_PART13(),,
+                     POLY1305_BLOCK_PART14(),)
+                     POLY1305_BLOCK_PART15()
+       QUARTERROUND4(X0, X5, X10, X15,   X1, X6, X11, X12,
+                     X2, X7,  X8, X13,   X3, X4,  X9, X14,
+                     tmp:=,VTMP0,VTMP1,VTMP2,VTMP3,
+                     POLY1305_BLOCK_PART16(),,
+                     POLY1305_BLOCK_PART17(),,
+                     POLY1305_BLOCK_PART18(),,
+                     POLY1305_BLOCK_PART19(),,
+                     POLY1305_BLOCK_PART20(),,
+                     POLY1305_BLOCK_PART21(),,
+                     POLY1305_BLOCK_PART22(),,
+                     POLY1305_BLOCK_PART23(),,
+                     POLY1305_BLOCK_PART24(),,
+                     POLY1305_BLOCK_PART25(),,
+                     POLY1305_BLOCK_PART26(),,
+                     POLY1305_BLOCK_PART27(),,
+                     POLY1305_BLOCK_PART28(),,
+                     POLY1305_BLOCK_PART29(),
+                     _(subs POLY_CHACHA_ROUND, POLY_CHACHA_ROUND, #2),)
+       b.ne .Lround4_with_poly1305_inner2;
+
+       subs ROUND, ROUND, #10
+       b.ne .Lround4_with_poly1305_outer;
+
+       ld1 {VTMP0.16b, VTMP1.16b}, [INPUT_POS], #32;
+
+       PLUS(X12, X12_TMP);        /* INPUT + 12 * 4 + counter */
+       PLUS(X13, X13_TMP);        /* INPUT + 13 * 4 + counter */
+
+       dup VTMP2.4s, VTMP0.s[0]; /* INPUT + 0 * 4 */
+       dup VTMP3.4s, VTMP0.s[1]; /* INPUT + 1 * 4 */
+       dup X12_TMP.4s, VTMP0.s[2]; /* INPUT + 2 * 4 */
+       dup X13_TMP.4s, VTMP0.s[3]; /* INPUT + 3 * 4 */
+       PLUS(X0, VTMP2);
+       PLUS(X1, VTMP3);
+       PLUS(X2, X12_TMP);
+       PLUS(X3, X13_TMP);
+
+       dup VTMP2.4s, VTMP1.s[0]; /* INPUT + 4 * 4 */
+       dup VTMP3.4s, VTMP1.s[1]; /* INPUT + 5 * 4 */
+       dup X12_TMP.4s, VTMP1.s[2]; /* INPUT + 6 * 4 */
+       dup X13_TMP.4s, VTMP1.s[3]; /* INPUT + 7 * 4 */
+       ld1 {VTMP0.16b, VTMP1.16b}, [INPUT_POS];
+       mov INPUT_POS, INPUT;
+       PLUS(X4, VTMP2);
+       PLUS(X5, VTMP3);
+       PLUS(X6, X12_TMP);
+       PLUS(X7, X13_TMP);
+
+       dup VTMP2.4s, VTMP0.s[0]; /* INPUT + 8 * 4 */
+       dup VTMP3.4s, VTMP0.s[1]; /* INPUT + 9 * 4 */
+       dup X12_TMP.4s, VTMP0.s[2]; /* INPUT + 10 * 4 */
+       dup X13_TMP.4s, VTMP0.s[3]; /* INPUT + 11 * 4 */
+       dup VTMP0.4s, VTMP1.s[2]; /* INPUT + 14 * 4 */
+       dup VTMP1.4s, VTMP1.s[3]; /* INPUT + 15 * 4 */
+       PLUS(X8, VTMP2);
+       PLUS(X9, VTMP3);
+       PLUS(X10, X12_TMP);
+       PLUS(X11, X13_TMP);
+       PLUS(X14, VTMP0);
+       PLUS(X15, VTMP1);
+
+       transpose_4x4(X0, X1, X2, X3, VTMP0, VTMP1, VTMP2);
+       transpose_4x4(X4, X5, X6, X7, VTMP0, VTMP1, VTMP2);
+       transpose_4x4(X8, X9, X10, X11, VTMP0, VTMP1, VTMP2);
+       transpose_4x4(X12, X13, X14, X15, VTMP0, VTMP1, VTMP2);
+
+       subs NBLKS, NBLKS, #4;
+
+       ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
+       ld1 {X12_TMP.16b-X13_TMP.16b}, [SRC], #32;
+       eor VTMP0.16b, X0.16b, VTMP0.16b;
+       eor VTMP1.16b, X4.16b, VTMP1.16b;
+       eor VTMP2.16b, X8.16b, VTMP2.16b;
+       eor VTMP3.16b, X12.16b, VTMP3.16b;
+       eor X12_TMP.16b, X1.16b, X12_TMP.16b;
+       eor X13_TMP.16b, X5.16b, X13_TMP.16b;
+       st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
+       ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
+       st1 {X12_TMP.16b-X13_TMP.16b}, [DST], #32;
+       ld1 {X12_TMP.16b-X13_TMP.16b}, [SRC], #32;
+       eor VTMP0.16b, X9.16b, VTMP0.16b;
+       eor VTMP1.16b, X13.16b, VTMP1.16b;
+       eor VTMP2.16b, X2.16b, VTMP2.16b;
+       eor VTMP3.16b, X6.16b, VTMP3.16b;
+       eor X12_TMP.16b, X10.16b, X12_TMP.16b;
+       eor X13_TMP.16b, X14.16b, X13_TMP.16b;
+       st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
+       ld1 {VTMP0.16b-VTMP3.16b}, [SRC], #64;
+       st1 {X12_TMP.16b-X13_TMP.16b}, [DST], #32;
+       eor VTMP0.16b, X3.16b, VTMP0.16b;
+       eor VTMP1.16b, X7.16b, VTMP1.16b;
+       eor VTMP2.16b, X11.16b, VTMP2.16b;
+       eor VTMP3.16b, X15.16b, VTMP3.16b;
+       st1 {VTMP0.16b-VTMP3.16b}, [DST], #64;
+
+       b.ne .Loop_poly4;
+
+       POLY1305_STORE_STATE()
+
+       /* clear the used vector registers and stack */
+       clear(VTMP0);
+       clear(VTMP1);
+       clear(VTMP2);
+       clear(VTMP3);
+       clear(X12_TMP);
+       clear(X13_TMP);
+       clear(X0);
+       clear(X1);
+       clear(X2);
+       clear(X3);
+       clear(X4);
+       clear(X5);
+       clear(X6);
+       clear(X7);
+       clear(X8);
+       clear(X9);
+       clear(X10);
+       clear(X11);
+       clear(X12);
+       clear(X13);
+       clear(X14);
+       clear(X15);
+
+       eor x0, x0, x0
+       POLY1305_POP_REGS()
+       ret_spec_stop
+       CFI_ENDPROC()
+ELF(.size _gcry_chacha20_poly1305_aarch64_blocks4, .-_gcry_chacha20_poly1305_aarch64_blocks4;)
+
+#endif
diff --git a/cipher/chacha20-amd64-avx2.S b/cipher/chacha20-amd64-avx2.S
new file mode 100644 (file)
index 0000000..9f2a036
--- /dev/null
@@ -0,0 +1,601 @@
+/* chacha20-amd64-avx2.S  -  AVX2 implementation of ChaCha20 cipher
+ *
+ * Copyright (C) 2017-2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Based on D. J. Bernstein reference implementation at
+ * http://cr.yp.to/chacha.html:
+ *
+ * chacha-regs.c version 20080118
+ * D. J. Bernstein
+ * Public domain.
+ */
+
+#ifdef __x86_64
+#include <config.h>
+#if defined(HAVE_GCC_INLINE_ASM_AVX2) && \
+   (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+
+.text
+
+#include "asm-common-amd64.h"
+#include "asm-poly1305-amd64.h"
+
+/* register macros */
+#define INPUT %rdi
+#define DST   %rsi
+#define SRC   %rdx
+#define NBLKS %rcx
+#define ROUND %eax
+
+/* stack structure */
+#define STACK_VEC_X12 (32)
+#define STACK_VEC_X13 (32 + STACK_VEC_X12)
+#define STACK_TMP     (32 + STACK_VEC_X13)
+#define STACK_TMP1    (32 + STACK_TMP)
+
+#define STACK_MAX     (32 + STACK_TMP1)
+
+/* vector registers */
+#define X0 %ymm0
+#define X1 %ymm1
+#define X2 %ymm2
+#define X3 %ymm3
+#define X4 %ymm4
+#define X5 %ymm5
+#define X6 %ymm6
+#define X7 %ymm7
+#define X8 %ymm8
+#define X9 %ymm9
+#define X10 %ymm10
+#define X11 %ymm11
+#define X12 %ymm12
+#define X13 %ymm13
+#define X14 %ymm14
+#define X15 %ymm15
+
+#define X0h %xmm0
+#define X1h %xmm1
+#define X2h %xmm2
+#define X3h %xmm3
+#define X4h %xmm4
+#define X5h %xmm5
+#define X6h %xmm6
+#define X7h %xmm7
+#define X8h %xmm8
+#define X9h %xmm9
+#define X10h %xmm10
+#define X11h %xmm11
+#define X12h %xmm12
+#define X13h %xmm13
+#define X14h %xmm14
+#define X15h %xmm15
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+
+/* 4x4 32-bit integer matrix transpose */
+#define transpose_4x4(x0,x1,x2,x3,t1,t2) \
+       vpunpckhdq x1, x0, t2; \
+       vpunpckldq x1, x0, x0; \
+       \
+       vpunpckldq x3, x2, t1; \
+       vpunpckhdq x3, x2, x2; \
+       \
+       vpunpckhqdq t1, x0, x1; \
+       vpunpcklqdq t1, x0, x0; \
+       \
+       vpunpckhqdq x2, t2, x3; \
+       vpunpcklqdq x2, t2, x2;
+
+/* 2x2 128-bit matrix transpose */
+#define transpose_16byte_2x2(x0,x1,t1) \
+       vmovdqa    x0, t1; \
+       vperm2i128 $0x20, x1, x0, x0; \
+       vperm2i128 $0x31, x1, t1, x1;
+
+/* xor register with unaligned src and save to unaligned dst */
+#define xor_src_dst(dst, src, offset, xreg) \
+       vpxor offset(src), xreg, xreg; \
+       vmovdqu xreg, offset(dst);
+
+/**********************************************************************
+  8-way chacha20
+ **********************************************************************/
+
+#define ROTATE2(v1,v2,c,tmp)   \
+       vpsrld $(32 - (c)), v1, tmp;    \
+       vpslld $(c), v1, v1;            \
+       vpaddb tmp, v1, v1;             \
+       vpsrld $(32 - (c)), v2, tmp;    \
+       vpslld $(c), v2, v2;            \
+       vpaddb tmp, v2, v2;
+
+#define ROTATE_SHUF_2(v1,v2,shuf)      \
+       vpshufb shuf, v1, v1;           \
+       vpshufb shuf, v2, v2;
+
+#define XOR(ds,s) \
+       vpxor s, ds, ds;
+
+#define PLUS(ds,s) \
+       vpaddd s, ds, ds;
+
+#define QUARTERROUND2(a1,b1,c1,d1,a2,b2,c2,d2,ign,tmp1,\
+                     interleave_op1,interleave_op2,\
+                     interleave_op3,interleave_op4)            \
+       vbroadcasti128 .Lshuf_rol16 rRIP, tmp1;                 \
+               interleave_op1;                                 \
+       PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
+           ROTATE_SHUF_2(d1, d2, tmp1);                        \
+               interleave_op2;                                 \
+       PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
+           ROTATE2(b1, b2, 12, tmp1);                          \
+       vbroadcasti128 .Lshuf_rol8 rRIP, tmp1;                  \
+               interleave_op3;                                 \
+       PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
+           ROTATE_SHUF_2(d1, d2, tmp1);                        \
+               interleave_op4;                                 \
+       PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
+           ROTATE2(b1, b2,  7, tmp1);
+
+.align 32
+chacha20_data:
+.Lshuf_rol16:
+       .byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13
+.Lshuf_rol8:
+       .byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14
+.Linc_counter:
+       .byte 0,1,2,3,4,5,6,7
+.Lunsigned_cmp:
+       .long 0x80000000
+
+.align 8
+.globl _gcry_chacha20_amd64_avx2_blocks8
+ELF(.type _gcry_chacha20_amd64_avx2_blocks8,@function;)
+
+_gcry_chacha20_amd64_avx2_blocks8:
+       /* input:
+        *      %rdi: input
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: nblks (multiple of 8)
+        */
+       CFI_STARTPROC();
+
+       vzeroupper;
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       subq $STACK_MAX, %rsp;
+       andq $~31, %rsp;
+
+.Loop8:
+       mov $20, ROUND;
+
+       /* Construct counter vectors X12 and X13 */
+       vpmovzxbd .Linc_counter rRIP, X0;
+       vpbroadcastd .Lunsigned_cmp rRIP, X2;
+       vpbroadcastd (12 * 4)(INPUT), X12;
+       vpbroadcastd (13 * 4)(INPUT), X13;
+       vpaddd X0, X12, X12;
+       vpxor X2, X0, X0;
+       vpxor X2, X12, X1;
+       vpcmpgtd X1, X0, X0;
+       vpsubd X0, X13, X13;
+       vmovdqa X12, (STACK_VEC_X12)(%rsp);
+       vmovdqa X13, (STACK_VEC_X13)(%rsp);
+
+       /* Load vectors */
+       vpbroadcastd (0 * 4)(INPUT), X0;
+       vpbroadcastd (1 * 4)(INPUT), X1;
+       vpbroadcastd (2 * 4)(INPUT), X2;
+       vpbroadcastd (3 * 4)(INPUT), X3;
+       vpbroadcastd (4 * 4)(INPUT), X4;
+       vpbroadcastd (5 * 4)(INPUT), X5;
+       vpbroadcastd (6 * 4)(INPUT), X6;
+       vpbroadcastd (7 * 4)(INPUT), X7;
+       vpbroadcastd (8 * 4)(INPUT), X8;
+       vpbroadcastd (9 * 4)(INPUT), X9;
+       vpbroadcastd (10 * 4)(INPUT), X10;
+       vpbroadcastd (11 * 4)(INPUT), X11;
+       vpbroadcastd (14 * 4)(INPUT), X14;
+       vpbroadcastd (15 * 4)(INPUT), X15;
+       vmovdqa X15, (STACK_TMP)(%rsp);
+
+.Lround2:
+       QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,,,,)
+       vmovdqa (STACK_TMP)(%rsp), X15;
+       vmovdqa X8, (STACK_TMP)(%rsp);
+       QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,,,,)
+       QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,,,,)
+       vmovdqa (STACK_TMP)(%rsp), X8;
+       vmovdqa X15, (STACK_TMP)(%rsp);
+       QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,,,,)
+       sub $2, ROUND;
+       jnz .Lround2;
+
+       vmovdqa X8, (STACK_TMP1)(%rsp);
+
+       /* tmp := X15 */
+       vpbroadcastd (0 * 4)(INPUT), X15;
+       PLUS(X0, X15);
+       vpbroadcastd (1 * 4)(INPUT), X15;
+       PLUS(X1, X15);
+       vpbroadcastd (2 * 4)(INPUT), X15;
+       PLUS(X2, X15);
+       vpbroadcastd (3 * 4)(INPUT), X15;
+       PLUS(X3, X15);
+       vpbroadcastd (4 * 4)(INPUT), X15;
+       PLUS(X4, X15);
+       vpbroadcastd (5 * 4)(INPUT), X15;
+       PLUS(X5, X15);
+       vpbroadcastd (6 * 4)(INPUT), X15;
+       PLUS(X6, X15);
+       vpbroadcastd (7 * 4)(INPUT), X15;
+       PLUS(X7, X15);
+       transpose_4x4(X0, X1, X2, X3, X8, X15);
+       transpose_4x4(X4, X5, X6, X7, X8, X15);
+       vmovdqa (STACK_TMP1)(%rsp), X8;
+       transpose_16byte_2x2(X0, X4, X15);
+       transpose_16byte_2x2(X1, X5, X15);
+       transpose_16byte_2x2(X2, X6, X15);
+       transpose_16byte_2x2(X3, X7, X15);
+       vmovdqa (STACK_TMP)(%rsp), X15;
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1);
+       vpbroadcastd (8 * 4)(INPUT), X0;
+       PLUS(X8, X0);
+       vpbroadcastd (9 * 4)(INPUT), X0;
+       PLUS(X9, X0);
+       vpbroadcastd (10 * 4)(INPUT), X0;
+       PLUS(X10, X0);
+       vpbroadcastd (11 * 4)(INPUT), X0;
+       PLUS(X11, X0);
+       vmovdqa (STACK_VEC_X12)(%rsp), X0;
+       PLUS(X12, X0);
+       vmovdqa (STACK_VEC_X13)(%rsp), X0;
+       PLUS(X13, X0);
+       vpbroadcastd (14 * 4)(INPUT), X0;
+       PLUS(X14, X0);
+       vpbroadcastd (15 * 4)(INPUT), X0;
+       PLUS(X15, X0);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3);
+
+       /* Update counter */
+       addq $8, (12 * 4)(INPUT);
+
+       transpose_4x4(X8, X9, X10, X11, X0, X1);
+       transpose_4x4(X12, X13, X14, X15, X0, X1);
+       xor_src_dst(DST, SRC, (64 * 4 + 16 * 0), X4);
+       xor_src_dst(DST, SRC, (64 * 5 + 16 * 0), X5);
+       transpose_16byte_2x2(X8, X12, X0);
+       transpose_16byte_2x2(X9, X13, X0);
+       transpose_16byte_2x2(X10, X14, X0);
+       transpose_16byte_2x2(X11, X15, X0);
+       xor_src_dst(DST, SRC, (64 * 6 + 16 * 0), X6);
+       xor_src_dst(DST, SRC, (64 * 7 + 16 * 0), X7);
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11);
+       xor_src_dst(DST, SRC, (64 * 4 + 16 * 2), X12);
+       xor_src_dst(DST, SRC, (64 * 5 + 16 * 2), X13);
+       xor_src_dst(DST, SRC, (64 * 6 + 16 * 2), X14);
+       xor_src_dst(DST, SRC, (64 * 7 + 16 * 2), X15);
+
+       sub $8, NBLKS;
+       lea (8 * 64)(DST), DST;
+       lea (8 * 64)(SRC), SRC;
+       jnz .Loop8;
+
+       /* clear the used vector registers and stack */
+       vpxor X0, X0, X0;
+       vmovdqa X0, (STACK_VEC_X12)(%rsp);
+       vmovdqa X0, (STACK_VEC_X13)(%rsp);
+       vmovdqa X0, (STACK_TMP)(%rsp);
+       vmovdqa X0, (STACK_TMP1)(%rsp);
+       vzeroall;
+
+       /* eax zeroed by round loop. */
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_amd64_avx2_blocks8,
+         .-_gcry_chacha20_amd64_avx2_blocks8;)
+
+/**********************************************************************
+  8-way stitched chacha20-poly1305
+ **********************************************************************/
+
+#define _ /*_*/
+
+.align 8
+.globl _gcry_chacha20_poly1305_amd64_avx2_blocks8
+ELF(.type _gcry_chacha20_poly1305_amd64_avx2_blocks8,@function;)
+
+_gcry_chacha20_poly1305_amd64_avx2_blocks8:
+       /* input:
+        *      %rdi: input
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: nblks (multiple of 8)
+        *      %r9: poly1305-state
+        *      %r8: poly1305-src
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       vzeroupper;
+
+       subq $(9 * 8) + STACK_MAX + 32, %rsp;
+       andq $~31, %rsp;
+
+       movq %rbx, (STACK_MAX + 0 * 8)(%rsp);
+       movq %r12, (STACK_MAX + 1 * 8)(%rsp);
+       movq %r13, (STACK_MAX + 2 * 8)(%rsp);
+       movq %r14, (STACK_MAX + 3 * 8)(%rsp);
+       movq %r15, (STACK_MAX + 4 * 8)(%rsp);
+       CFI_REG_ON_STACK(rbx, STACK_MAX + 0 * 8);
+       CFI_REG_ON_STACK(r12, STACK_MAX + 1 * 8);
+       CFI_REG_ON_STACK(r13, STACK_MAX + 2 * 8);
+       CFI_REG_ON_STACK(r14, STACK_MAX + 3 * 8);
+       CFI_REG_ON_STACK(r15, STACK_MAX + 4 * 8);
+
+       movq %rdx, (STACK_MAX + 5 * 8)(%rsp); # SRC
+       movq %rsi, (STACK_MAX + 6 * 8)(%rsp); # DST
+       movq %rcx, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
+
+       /* Load state */
+       POLY1305_LOAD_STATE();
+
+.Loop_poly8:
+
+       /* Construct counter vectors X12 and X13 */
+       vpmovzxbd .Linc_counter rRIP, X0;
+       vpbroadcastd .Lunsigned_cmp rRIP, X2;
+       vpbroadcastd (12 * 4)(INPUT), X12;
+       vpbroadcastd (13 * 4)(INPUT), X13;
+       vpaddd X0, X12, X12;
+       vpxor X2, X0, X0;
+       vpxor X2, X12, X1;
+       vpcmpgtd X1, X0, X0;
+       vpsubd X0, X13, X13;
+       vmovdqa X12, (STACK_VEC_X12)(%rsp);
+       vmovdqa X13, (STACK_VEC_X13)(%rsp);
+
+       /* Load vectors */
+       vpbroadcastd (0 * 4)(INPUT), X0;
+       vpbroadcastd (1 * 4)(INPUT), X1;
+       vpbroadcastd (2 * 4)(INPUT), X2;
+       vpbroadcastd (3 * 4)(INPUT), X3;
+       vpbroadcastd (4 * 4)(INPUT), X4;
+       vpbroadcastd (5 * 4)(INPUT), X5;
+       vpbroadcastd (6 * 4)(INPUT), X6;
+       vpbroadcastd (7 * 4)(INPUT), X7;
+       vpbroadcastd (8 * 4)(INPUT), X8;
+       vpbroadcastd (9 * 4)(INPUT), X9;
+       vpbroadcastd (10 * 4)(INPUT), X10;
+       vpbroadcastd (11 * 4)(INPUT), X11;
+       vpbroadcastd (14 * 4)(INPUT), X14;
+       vpbroadcastd (15 * 4)(INPUT), X15;
+       vmovdqa X15, (STACK_TMP)(%rsp);
+
+       /* Process eight ChaCha20 blocks and 32 Poly1305 blocks. */
+
+       movl $20, (STACK_MAX + 8 * 8 + 4)(%rsp);
+.Lround8_with_poly1305_outer:
+       movl $6, (STACK_MAX + 8 * 8)(%rsp);
+.Lround8_with_poly1305_inner1:
+       /* rounds 0-5 & 10-15 */
+                     POLY1305_BLOCK_PART1(0 * 16)
+       QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
+                     POLY1305_BLOCK_PART2(),
+                     POLY1305_BLOCK_PART3(),
+                     POLY1305_BLOCK_PART4(),
+                     POLY1305_BLOCK_PART5())
+       vmovdqa (STACK_TMP)(%rsp), X15;
+       vmovdqa X8, (STACK_TMP)(%rsp);
+                     POLY1305_BLOCK_PART1(1 * 16)
+       QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
+                     POLY1305_BLOCK_PART2(),
+                     POLY1305_BLOCK_PART3(),
+                     POLY1305_BLOCK_PART4(),
+                     POLY1305_BLOCK_PART5())
+                     POLY1305_BLOCK_PART1(2 * 16)
+       QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
+                     POLY1305_BLOCK_PART2(),
+                     POLY1305_BLOCK_PART3(),
+                     POLY1305_BLOCK_PART4(),
+                     POLY1305_BLOCK_PART5())
+       vmovdqa (STACK_TMP)(%rsp), X8;
+       vmovdqa X15, (STACK_TMP)(%rsp);
+                     POLY1305_BLOCK_PART1(3 * 16)
+                     lea (4 * 16)(POLY_RSRC), POLY_RSRC;
+       QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
+                     POLY1305_BLOCK_PART2(),
+                     POLY1305_BLOCK_PART3(),
+                     POLY1305_BLOCK_PART4(),
+                     POLY1305_BLOCK_PART5())
+
+       subl $2, (STACK_MAX + 8 * 8)(%rsp);
+       jnz .Lround8_with_poly1305_inner1;
+
+       movl $4, (STACK_MAX + 8 * 8)(%rsp);
+.Lround8_with_poly1305_inner2:
+       /* rounds 6-9 & 16-19 */
+                     POLY1305_BLOCK_PART1(0 * 16)
+       QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X15,
+                     POLY1305_BLOCK_PART2(),
+                     _,
+                     POLY1305_BLOCK_PART3(),
+                     _)
+       vmovdqa (STACK_TMP)(%rsp), X15;
+       vmovdqa X8, (STACK_TMP)(%rsp);
+       QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,
+                     _,
+                     POLY1305_BLOCK_PART4(),
+                     _,
+                     POLY1305_BLOCK_PART5())
+                     POLY1305_BLOCK_PART1(1 * 16);
+                     lea (2 * 16)(POLY_RSRC), POLY_RSRC;
+       QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,
+                     _,
+                     POLY1305_BLOCK_PART2(),
+                     _,
+                     POLY1305_BLOCK_PART3())
+       vmovdqa (STACK_TMP)(%rsp), X8;
+       vmovdqa X15, (STACK_TMP)(%rsp);
+       QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X15,
+                     POLY1305_BLOCK_PART4(),
+                     _,
+                     POLY1305_BLOCK_PART5(),
+                     _)
+
+       subl $2, (STACK_MAX + 8 * 8)(%rsp);
+       jnz .Lround8_with_poly1305_inner2;
+
+       subl $10, (STACK_MAX + 8 * 8 + 4)(%rsp);
+       jnz .Lround8_with_poly1305_outer;
+
+       movq (STACK_MAX + 5 * 8)(%rsp), SRC;
+       movq (STACK_MAX + 6 * 8)(%rsp), DST;
+
+       vmovdqa X8, (STACK_TMP1)(%rsp);
+
+       /* tmp := X15 */
+       vpbroadcastd (0 * 4)(INPUT), X15;
+       PLUS(X0, X15);
+       vpbroadcastd (1 * 4)(INPUT), X15;
+       PLUS(X1, X15);
+       vpbroadcastd (2 * 4)(INPUT), X15;
+       PLUS(X2, X15);
+       vpbroadcastd (3 * 4)(INPUT), X15;
+       PLUS(X3, X15);
+       vpbroadcastd (4 * 4)(INPUT), X15;
+       PLUS(X4, X15);
+       vpbroadcastd (5 * 4)(INPUT), X15;
+       PLUS(X5, X15);
+       vpbroadcastd (6 * 4)(INPUT), X15;
+       PLUS(X6, X15);
+       vpbroadcastd (7 * 4)(INPUT), X15;
+       PLUS(X7, X15);
+       transpose_4x4(X0, X1, X2, X3, X8, X15);
+       transpose_4x4(X4, X5, X6, X7, X8, X15);
+       vmovdqa (STACK_TMP1)(%rsp), X8;
+       transpose_16byte_2x2(X0, X4, X15);
+       transpose_16byte_2x2(X1, X5, X15);
+       transpose_16byte_2x2(X2, X6, X15);
+       transpose_16byte_2x2(X3, X7, X15);
+       vmovdqa (STACK_TMP)(%rsp), X15;
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1);
+       vpbroadcastd (8 * 4)(INPUT), X0;
+       PLUS(X8, X0);
+       vpbroadcastd (9 * 4)(INPUT), X0;
+       PLUS(X9, X0);
+       vpbroadcastd (10 * 4)(INPUT), X0;
+       PLUS(X10, X0);
+       vpbroadcastd (11 * 4)(INPUT), X0;
+       PLUS(X11, X0);
+       vmovdqa (STACK_VEC_X12)(%rsp), X0;
+       PLUS(X12, X0);
+       vmovdqa (STACK_VEC_X13)(%rsp), X0;
+       PLUS(X13, X0);
+       vpbroadcastd (14 * 4)(INPUT), X0;
+       PLUS(X14, X0);
+       vpbroadcastd (15 * 4)(INPUT), X0;
+       PLUS(X15, X0);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3);
+
+       /* Update counter */
+       addq $8, (12 * 4)(INPUT);
+
+       transpose_4x4(X8, X9, X10, X11, X0, X1);
+       transpose_4x4(X12, X13, X14, X15, X0, X1);
+       xor_src_dst(DST, SRC, (64 * 4 + 16 * 0), X4);
+       xor_src_dst(DST, SRC, (64 * 5 + 16 * 0), X5);
+       transpose_16byte_2x2(X8, X12, X0);
+       transpose_16byte_2x2(X9, X13, X0);
+       transpose_16byte_2x2(X10, X14, X0);
+       transpose_16byte_2x2(X11, X15, X0);
+       xor_src_dst(DST, SRC, (64 * 6 + 16 * 0), X6);
+       xor_src_dst(DST, SRC, (64 * 7 + 16 * 0), X7);
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11);
+       xor_src_dst(DST, SRC, (64 * 4 + 16 * 2), X12);
+       xor_src_dst(DST, SRC, (64 * 5 + 16 * 2), X13);
+       xor_src_dst(DST, SRC, (64 * 6 + 16 * 2), X14);
+       xor_src_dst(DST, SRC, (64 * 7 + 16 * 2), X15);
+
+       subq $8, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
+
+       lea (8 * 64)(DST), DST;
+       lea (8 * 64)(SRC), SRC;
+       movq SRC, (STACK_MAX + 5 * 8)(%rsp);
+       movq DST, (STACK_MAX + 6 * 8)(%rsp);
+
+       jnz .Loop_poly8;
+
+       /* Store state */
+       POLY1305_STORE_STATE();
+
+       /* clear the used vector registers and stack */
+       vpxor X0, X0, X0;
+       vmovdqa X0, (STACK_VEC_X12)(%rsp);
+       vmovdqa X0, (STACK_VEC_X13)(%rsp);
+       vmovdqa X0, (STACK_TMP)(%rsp);
+       vmovdqa X0, (STACK_TMP1)(%rsp);
+       vzeroall;
+
+       movq (STACK_MAX + 0 * 8)(%rsp), %rbx;
+       movq (STACK_MAX + 1 * 8)(%rsp), %r12;
+       movq (STACK_MAX + 2 * 8)(%rsp), %r13;
+       movq (STACK_MAX + 3 * 8)(%rsp), %r14;
+       movq (STACK_MAX + 4 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
+
+       xorl %eax, %eax;
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_poly1305_amd64_avx2_blocks8,
+         .-_gcry_chacha20_poly1305_amd64_avx2_blocks8;)
+
+#endif /*defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)*/
+#endif /*__x86_64*/
diff --git a/cipher/chacha20-amd64-ssse3.S b/cipher/chacha20-amd64-ssse3.S
new file mode 100644 (file)
index 0000000..6c73797
--- /dev/null
@@ -0,0 +1,1012 @@
+/* chacha20-amd64-ssse3.S  -  SSSE3 implementation of ChaCha20 cipher
+ *
+ * Copyright (C) 2017-2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Based on D. J. Bernstein reference implementation at
+ * http://cr.yp.to/chacha.html:
+ *
+ * chacha-regs.c version 20080118
+ * D. J. Bernstein
+ * Public domain.
+ */
+
+#ifdef __x86_64
+#include <config.h>
+#if defined(HAVE_GCC_INLINE_ASM_SSSE3) && \
+   (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+
+.text
+
+#include "asm-common-amd64.h"
+#include "asm-poly1305-amd64.h"
+
+/* register macros */
+#define INPUT %rdi
+#define DST   %rsi
+#define SRC   %rdx
+#define NBLKS %rcx
+#define ROUND %eax
+
+/* stack structure */
+#define STACK_VEC_X12 (16)
+#define STACK_VEC_X13 (16 + STACK_VEC_X12)
+#define STACK_TMP     (16 + STACK_VEC_X13)
+#define STACK_TMP1    (16 + STACK_TMP)
+#define STACK_TMP2    (16 + STACK_TMP1)
+
+#define STACK_MAX     (16 + STACK_TMP2)
+
+/* vector registers */
+#define X0 %xmm0
+#define X1 %xmm1
+#define X2 %xmm2
+#define X3 %xmm3
+#define X4 %xmm4
+#define X5 %xmm5
+#define X6 %xmm6
+#define X7 %xmm7
+#define X8 %xmm8
+#define X9 %xmm9
+#define X10 %xmm10
+#define X11 %xmm11
+#define X12 %xmm12
+#define X13 %xmm13
+#define X14 %xmm14
+#define X15 %xmm15
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+
+/* 4x4 32-bit integer matrix transpose */
+#define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \
+       movdqa    x0, t2; \
+       punpckhdq x1, t2; \
+       punpckldq x1, x0; \
+       \
+       movdqa    x2, t1; \
+       punpckldq x3, t1; \
+       punpckhdq x3, x2; \
+       \
+       movdqa     x0, x1; \
+       punpckhqdq t1, x1; \
+       punpcklqdq t1, x0; \
+       \
+       movdqa     t2, x3; \
+       punpckhqdq x2, x3; \
+       punpcklqdq x2, t2; \
+       movdqa     t2, x2;
+
+/* fill xmm register with 32-bit value from memory */
+#define pbroadcastd(mem32, xreg) \
+       movd mem32, xreg; \
+       pshufd $0, xreg, xreg;
+
+/* xor with unaligned memory operand */
+#define pxor_u(umem128, xreg, t) \
+       movdqu umem128, t; \
+       pxor t, xreg;
+
+/* xor register with unaligned src and save to unaligned dst */
+#define xor_src_dst(dst, src, offset, xreg, t) \
+       pxor_u(offset(src), xreg, t); \
+       movdqu xreg, offset(dst);
+
+#define clear(x) pxor x,x;
+
+/**********************************************************************
+  4-way chacha20
+ **********************************************************************/
+
+#define ROTATE2(v1,v2,c,tmp1,tmp2)     \
+       movdqa v1, tmp1;                \
+       movdqa v2, tmp2;                \
+       psrld $(32 - (c)), v1;          \
+       pslld $(c), tmp1;               \
+       paddb tmp1, v1;                 \
+       psrld $(32 - (c)), v2;          \
+       pslld $(c), tmp2;               \
+       paddb tmp2, v2;
+
+#define ROTATE_SHUF_2(v1,v2,shuf)      \
+       pshufb shuf, v1;                \
+       pshufb shuf, v2;
+
+#define XOR(ds,s) \
+       pxor s, ds;
+
+#define PLUS(ds,s) \
+       paddd s, ds;
+
+#define QUARTERROUND2(a1,b1,c1,d1,a2,b2,c2,d2,ign,tmp1,tmp2,\
+                     interleave_op1,interleave_op2)            \
+       movdqa .Lshuf_rol16 rRIP, tmp1;                         \
+               interleave_op1;                                 \
+       PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
+           ROTATE_SHUF_2(d1, d2, tmp1);                        \
+       PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
+           ROTATE2(b1, b2, 12, tmp1, tmp2);                    \
+       movdqa .Lshuf_rol8 rRIP, tmp1;                          \
+               interleave_op2;                                 \
+       PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
+           ROTATE_SHUF_2(d1, d2, tmp1);                        \
+       PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
+           ROTATE2(b1, b2,  7, tmp1, tmp2);
+
+chacha20_data:
+.align 16
+.Lshuf_rol16:
+       .byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13
+.Lshuf_rol8:
+       .byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14
+.Lcounter1:
+       .long 1,0,0,0
+.Linc_counter:
+       .long 0,1,2,3
+.Lunsigned_cmp:
+       .long 0x80000000,0x80000000,0x80000000,0x80000000
+
+.align 8
+.globl _gcry_chacha20_amd64_ssse3_blocks4
+ELF(.type _gcry_chacha20_amd64_ssse3_blocks4,@function;)
+
+_gcry_chacha20_amd64_ssse3_blocks4:
+       /* input:
+        *      %rdi: input
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: nblks (multiple of 4)
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       subq $STACK_MAX, %rsp;
+       andq $~15, %rsp;
+
+.Loop4:
+       mov $20, ROUND;
+
+       /* Construct counter vectors X12 and X13 */
+       movdqa .Linc_counter rRIP, X0;
+       movdqa .Lunsigned_cmp rRIP, X2;
+       pbroadcastd((12 * 4)(INPUT), X12);
+       pbroadcastd((13 * 4)(INPUT), X13);
+       paddd X0, X12;
+       movdqa X12, X1;
+       pxor X2, X0;
+       pxor X2, X1;
+       pcmpgtd X1, X0;
+       psubd X0, X13;
+       movdqa X12, (STACK_VEC_X12)(%rsp);
+       movdqa X13, (STACK_VEC_X13)(%rsp);
+
+       /* Load vectors */
+       pbroadcastd((0 * 4)(INPUT), X0);
+       pbroadcastd((1 * 4)(INPUT), X1);
+       pbroadcastd((2 * 4)(INPUT), X2);
+       pbroadcastd((3 * 4)(INPUT), X3);
+       pbroadcastd((4 * 4)(INPUT), X4);
+       pbroadcastd((5 * 4)(INPUT), X5);
+       pbroadcastd((6 * 4)(INPUT), X6);
+       pbroadcastd((7 * 4)(INPUT), X7);
+       pbroadcastd((8 * 4)(INPUT), X8);
+       pbroadcastd((9 * 4)(INPUT), X9);
+       pbroadcastd((10 * 4)(INPUT), X10);
+       pbroadcastd((11 * 4)(INPUT), X11);
+       pbroadcastd((14 * 4)(INPUT), X14);
+       pbroadcastd((15 * 4)(INPUT), X15);
+       movdqa X11, (STACK_TMP)(%rsp);
+       movdqa X15, (STACK_TMP1)(%rsp);
+
+.Lround2_4:
+       QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,,)
+       movdqa (STACK_TMP)(%rsp), X11;
+       movdqa (STACK_TMP1)(%rsp), X15;
+       movdqa X8, (STACK_TMP)(%rsp);
+       movdqa X9, (STACK_TMP1)(%rsp);
+       QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,,)
+       QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,,)
+       movdqa (STACK_TMP)(%rsp), X8;
+       movdqa (STACK_TMP1)(%rsp), X9;
+       movdqa X11, (STACK_TMP)(%rsp);
+       movdqa X15, (STACK_TMP1)(%rsp);
+       QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,,)
+       sub $2, ROUND;
+       jnz .Lround2_4;
+
+       /* tmp := X15 */
+       movdqa (STACK_TMP)(%rsp), X11;
+       pbroadcastd((0 * 4)(INPUT), X15);
+       PLUS(X0, X15);
+       pbroadcastd((1 * 4)(INPUT), X15);
+       PLUS(X1, X15);
+       pbroadcastd((2 * 4)(INPUT), X15);
+       PLUS(X2, X15);
+       pbroadcastd((3 * 4)(INPUT), X15);
+       PLUS(X3, X15);
+       pbroadcastd((4 * 4)(INPUT), X15);
+       PLUS(X4, X15);
+       pbroadcastd((5 * 4)(INPUT), X15);
+       PLUS(X5, X15);
+       pbroadcastd((6 * 4)(INPUT), X15);
+       PLUS(X6, X15);
+       pbroadcastd((7 * 4)(INPUT), X15);
+       PLUS(X7, X15);
+       pbroadcastd((8 * 4)(INPUT), X15);
+       PLUS(X8, X15);
+       pbroadcastd((9 * 4)(INPUT), X15);
+       PLUS(X9, X15);
+       pbroadcastd((10 * 4)(INPUT), X15);
+       PLUS(X10, X15);
+       pbroadcastd((11 * 4)(INPUT), X15);
+       PLUS(X11, X15);
+       movdqa (STACK_VEC_X12)(%rsp), X15;
+       PLUS(X12, X15);
+       movdqa (STACK_VEC_X13)(%rsp), X15;
+       PLUS(X13, X15);
+       movdqa X13, (STACK_TMP)(%rsp);
+       pbroadcastd((14 * 4)(INPUT), X15);
+       PLUS(X14, X15);
+       movdqa (STACK_TMP1)(%rsp), X15;
+       movdqa X14, (STACK_TMP1)(%rsp);
+       pbroadcastd((15 * 4)(INPUT), X13);
+       PLUS(X15, X13);
+       movdqa X15, (STACK_TMP2)(%rsp);
+
+       /* Update counter */
+       addq $4, (12 * 4)(INPUT);
+
+       transpose_4x4(X0, X1, X2, X3, X13, X14, X15);
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0, X15);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1, X15);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2, X15);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3, X15);
+       transpose_4x4(X4, X5, X6, X7, X0, X1, X2);
+       movdqa (STACK_TMP)(%rsp), X13;
+       movdqa (STACK_TMP1)(%rsp), X14;
+       movdqa (STACK_TMP2)(%rsp), X15;
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 1), X4, X0);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 1), X5, X0);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 1), X6, X0);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 1), X7, X0);
+       transpose_4x4(X8, X9, X10, X11, X0, X1, X2);
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8, X0);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9, X0);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10, X0);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11, X0);
+       transpose_4x4(X12, X13, X14, X15, X0, X1, X2);
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 3), X12, X0);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 3), X13, X0);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 3), X14, X0);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 3), X15, X0);
+
+       sub $4, NBLKS;
+       lea (4 * 64)(DST), DST;
+       lea (4 * 64)(SRC), SRC;
+       jnz .Loop4;
+
+       /* clear the used vector registers and stack */
+       clear(X0);
+       movdqa X0, (STACK_VEC_X12)(%rsp);
+       movdqa X0, (STACK_VEC_X13)(%rsp);
+       movdqa X0, (STACK_TMP)(%rsp);
+       movdqa X0, (STACK_TMP1)(%rsp);
+       movdqa X0, (STACK_TMP2)(%rsp);
+       clear(X1);
+       clear(X2);
+       clear(X3);
+       clear(X4);
+       clear(X5);
+       clear(X6);
+       clear(X7);
+       clear(X8);
+       clear(X9);
+       clear(X10);
+       clear(X11);
+       clear(X12);
+       clear(X13);
+       clear(X14);
+       clear(X15);
+
+       /* eax zeroed by round loop. */
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_amd64_ssse3_blocks4,
+         .-_gcry_chacha20_amd64_ssse3_blocks4;)
+
+/**********************************************************************
+  2-way && 1-way chacha20
+ **********************************************************************/
+
+#define ROTATE_SHUF(v1,shuf)           \
+       pshufb shuf, v1;
+
+#define ROTATE(v1,c,tmp1)              \
+       movdqa v1, tmp1;                \
+       psrld $(32 - (c)), v1;          \
+       pslld $(c), tmp1;               \
+       paddb tmp1, v1;
+
+#define WORD_SHUF(v1,shuf)             \
+       pshufd $shuf, v1, v1;
+
+#define QUARTERROUND4(x0,x1,x2,x3,shuf_rol8,shuf_rol16,tmp1,shuf_x1,\
+                     shuf_x2,shuf_x3) \
+       PLUS(x0, x1); XOR(x3, x0); ROTATE_SHUF(x3, shuf_rol16); \
+       PLUS(x2, x3); XOR(x1, x2); ROTATE(x1, 12, tmp1); \
+       PLUS(x0, x1); XOR(x3, x0); ROTATE_SHUF(x3, shuf_rol8); \
+       PLUS(x2, x3); \
+         WORD_SHUF(x3, shuf_x3); \
+                     XOR(x1, x2); \
+         WORD_SHUF(x2, shuf_x2); \
+                                  ROTATE(x1, 7, tmp1); \
+         WORD_SHUF(x1, shuf_x1);
+
+.align 8
+.globl _gcry_chacha20_amd64_ssse3_blocks1
+ELF(.type _gcry_chacha20_amd64_ssse3_blocks1,@function;)
+
+_gcry_chacha20_amd64_ssse3_blocks1:
+       /* input:
+        *      %rdi: input
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: nblks
+        */
+       CFI_STARTPROC();
+
+       /* Load constants */
+       movdqa .Lcounter1 rRIP, X4;
+       movdqa .Lshuf_rol8 rRIP, X5;
+       movdqa .Lshuf_rol16 rRIP, X6;
+
+       /* Load state */
+       movdqu (0 * 4)(INPUT), X10;
+       movdqu (4 * 4)(INPUT), X11;
+       movdqu (8 * 4)(INPUT), X12;
+       movdqu (12 * 4)(INPUT), X13;
+
+       cmp $2, NBLKS;
+       jb .Loop1;
+
+       mov $20, ROUND;
+
+       movdqa X10, X0;
+       movdqa X11, X1;
+       movdqa X12, X2;
+       movdqa X13, X3;
+
+       movdqa X10, X8;
+       movdqa X11, X9;
+       movdqa X12, X14;
+       movdqa X13, X15;
+       paddq X4, X15;
+
+.Lround2_2:
+       QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
+       QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
+       QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
+       QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
+       sub $2, ROUND;
+       jnz .Lround2_2;
+
+       PLUS(X0, X10);
+       PLUS(X1, X11);
+       PLUS(X2, X12);
+       PLUS(X3, X13);
+
+       /* Update counter */
+       paddq X4, X13;
+
+       PLUS(X8, X10);
+       PLUS(X9, X11);
+       PLUS(X14, X12);
+       PLUS(X15, X13);
+
+       /* Update counter */
+       paddq X4, X13;
+
+       xor_src_dst(DST, SRC, 0 * 4, X0, X7);
+       xor_src_dst(DST, SRC, 4 * 4, X1, X7);
+       xor_src_dst(DST, SRC, 8 * 4, X2, X7);
+       xor_src_dst(DST, SRC, 12 * 4, X3, X7);
+       xor_src_dst(DST, SRC, 16 * 4, X8, X7);
+       xor_src_dst(DST, SRC, 20 * 4, X9, X7);
+       xor_src_dst(DST, SRC, 24 * 4, X14, X7);
+       xor_src_dst(DST, SRC, 28 * 4, X15, X7);
+
+       lea (2 * 64)(DST), DST;
+       lea (2 * 64)(SRC), SRC;
+
+       clear(X8);
+       clear(X9);
+       clear(X14);
+       clear(X15);
+
+       sub $2, NBLKS;
+       jz .Ldone1;
+
+.Loop1:
+       mov $20, ROUND;
+
+       movdqa X10, X0;
+       movdqa X11, X1;
+       movdqa X12, X2;
+       movdqa X13, X3;
+
+.Lround2_1:
+       QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
+       QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
+       sub $2, ROUND;
+       jnz .Lround2_1;
+
+       PLUS(X0, X10);
+       PLUS(X1, X11);
+       PLUS(X2, X12);
+       PLUS(X3, X13);
+
+       /* Update counter */
+       paddq X4, X13;
+
+       xor_src_dst(DST, SRC, 0 * 4, X0, X7);
+       xor_src_dst(DST, SRC, 4 * 4, X1, X7);
+       xor_src_dst(DST, SRC, 8 * 4, X2, X7);
+       xor_src_dst(DST, SRC, 12 * 4, X3, X7);
+
+       lea (64)(DST), DST;
+       lea (64)(SRC), SRC;
+
+       sub $1, NBLKS;
+       jnz .Loop1;
+
+.Ldone1:
+       /* Store counter */
+       movdqu X13, (12 * 4)(INPUT);
+
+       /* clear the used vector registers */
+       clear(X0);
+       clear(X1);
+       clear(X2);
+       clear(X3);
+       clear(X4);
+       clear(X5);
+       clear(X6);
+       clear(X7);
+       clear(X10);
+       clear(X11);
+       clear(X12);
+       clear(X13);
+
+       /* eax zeroed by round loop. */
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_amd64_ssse3_blocks1,
+         .-_gcry_chacha20_amd64_ssse3_blocks1;)
+
+/**********************************************************************
+  4-way stitched chacha20-poly1305
+ **********************************************************************/
+
+#define _ /*_*/
+
+.align 8
+.globl _gcry_chacha20_poly1305_amd64_ssse3_blocks4
+ELF(.type _gcry_chacha20_poly1305_amd64_ssse3_blocks4,@function;)
+
+_gcry_chacha20_poly1305_amd64_ssse3_blocks4:
+       /* input:
+        *      %rdi: input
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: nblks (multiple of 4)
+        *      %r9: poly1305-state
+        *      %r8: poly1305-src
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       subq $(9 * 8) + STACK_MAX + 16, %rsp;
+       andq $~15, %rsp;
+
+       movq %rbx, (STACK_MAX + 0 * 8)(%rsp);
+       movq %r12, (STACK_MAX + 1 * 8)(%rsp);
+       movq %r13, (STACK_MAX + 2 * 8)(%rsp);
+       movq %r14, (STACK_MAX + 3 * 8)(%rsp);
+       movq %r15, (STACK_MAX + 4 * 8)(%rsp);
+       CFI_REG_ON_STACK(rbx, STACK_MAX + 0 * 8);
+       CFI_REG_ON_STACK(r12, STACK_MAX + 1 * 8);
+       CFI_REG_ON_STACK(r13, STACK_MAX + 2 * 8);
+       CFI_REG_ON_STACK(r14, STACK_MAX + 3 * 8);
+       CFI_REG_ON_STACK(r15, STACK_MAX + 4 * 8);
+
+       movq %rdx, (STACK_MAX + 5 * 8)(%rsp); # SRC
+       movq %rsi, (STACK_MAX + 6 * 8)(%rsp); # DST
+       movq %rcx, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
+
+       /* Load state */
+       POLY1305_LOAD_STATE();
+
+.Loop_poly4:
+
+       /* Construct counter vectors X12 and X13 */
+       movdqa .Linc_counter rRIP, X0;
+       movdqa .Lunsigned_cmp rRIP, X2;
+       pbroadcastd((12 * 4)(INPUT), X12);
+       pbroadcastd((13 * 4)(INPUT), X13);
+       paddd X0, X12;
+       movdqa X12, X1;
+       pxor X2, X0;
+       pxor X2, X1;
+       pcmpgtd X1, X0;
+       psubd X0, X13;
+       movdqa X12, (STACK_VEC_X12)(%rsp);
+       movdqa X13, (STACK_VEC_X13)(%rsp);
+
+       /* Load vectors */
+       pbroadcastd((0 * 4)(INPUT), X0);
+       pbroadcastd((1 * 4)(INPUT), X1);
+       pbroadcastd((2 * 4)(INPUT), X2);
+       pbroadcastd((3 * 4)(INPUT), X3);
+       pbroadcastd((4 * 4)(INPUT), X4);
+       pbroadcastd((5 * 4)(INPUT), X5);
+       pbroadcastd((6 * 4)(INPUT), X6);
+       pbroadcastd((7 * 4)(INPUT), X7);
+       pbroadcastd((8 * 4)(INPUT), X8);
+       pbroadcastd((9 * 4)(INPUT), X9);
+       pbroadcastd((10 * 4)(INPUT), X10);
+       pbroadcastd((11 * 4)(INPUT), X11);
+       pbroadcastd((14 * 4)(INPUT), X14);
+       pbroadcastd((15 * 4)(INPUT), X15);
+       movdqa X11, (STACK_TMP)(%rsp);
+       movdqa X15, (STACK_TMP1)(%rsp);
+
+       /* Process four ChaCha20 blocks and sixteen Poly1305 blocks. */
+
+       movl $20, (STACK_MAX + 8 * 8 + 4)(%rsp);
+.Lround4_with_poly1305_outer:
+       movl $6, (STACK_MAX + 8 * 8)(%rsp);
+.Lround4_with_poly1305_inner1:
+       /* rounds 0-5 & 10-15 */
+                     POLY1305_BLOCK_PART1(0 * 16)
+       QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
+                     POLY1305_BLOCK_PART2(),
+                     POLY1305_BLOCK_PART3())
+       movdqa (STACK_TMP)(%rsp), X11;
+       movdqa (STACK_TMP1)(%rsp), X15;
+       movdqa X8, (STACK_TMP)(%rsp);
+       movdqa X9, (STACK_TMP1)(%rsp);
+       QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
+                     POLY1305_BLOCK_PART4(),
+                     POLY1305_BLOCK_PART5())
+                     POLY1305_BLOCK_PART1(1 * 16)
+                     lea (2 * 16)(POLY_RSRC), POLY_RSRC;
+       QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
+                     POLY1305_BLOCK_PART2(),
+                     POLY1305_BLOCK_PART3())
+       movdqa (STACK_TMP)(%rsp), X8;
+       movdqa (STACK_TMP1)(%rsp), X9;
+       movdqa X11, (STACK_TMP)(%rsp);
+       movdqa X15, (STACK_TMP1)(%rsp);
+       QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
+                     POLY1305_BLOCK_PART4(),
+                     POLY1305_BLOCK_PART5())
+
+       subl $2, (STACK_MAX + 8 * 8)(%rsp);
+       jnz .Lround4_with_poly1305_inner1;
+
+       movl $4, (STACK_MAX + 8 * 8)(%rsp);
+.Lround4_with_poly1305_inner2:
+       /* rounds 6-9 & 16-19 */
+                     POLY1305_BLOCK_PART1(0 * 16)
+                     lea (1 * 16)(POLY_RSRC), POLY_RSRC;
+       QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15,
+                     POLY1305_BLOCK_PART2(),
+                     _)
+       movdqa (STACK_TMP)(%rsp), X11;
+       movdqa (STACK_TMP1)(%rsp), X15;
+       movdqa X8, (STACK_TMP)(%rsp);
+       movdqa X9, (STACK_TMP1)(%rsp);
+       QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9,
+                     POLY1305_BLOCK_PART3(),
+                     _)
+       QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9,
+                     POLY1305_BLOCK_PART4(),
+                     _)
+       movdqa (STACK_TMP)(%rsp), X8;
+       movdqa (STACK_TMP1)(%rsp), X9;
+       movdqa X11, (STACK_TMP)(%rsp);
+       movdqa X15, (STACK_TMP1)(%rsp);
+       QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15,
+                     POLY1305_BLOCK_PART5(),
+                     _)
+
+       subl $2, (STACK_MAX + 8 * 8)(%rsp);
+       jnz .Lround4_with_poly1305_inner2;
+
+       subl $10, (STACK_MAX + 8 * 8 + 4)(%rsp);
+       jnz .Lround4_with_poly1305_outer;
+
+       /* tmp := X15 */
+       movdqa (STACK_TMP)(%rsp), X11;
+       pbroadcastd((0 * 4)(INPUT), X15);
+       PLUS(X0, X15);
+       pbroadcastd((1 * 4)(INPUT), X15);
+       PLUS(X1, X15);
+       pbroadcastd((2 * 4)(INPUT), X15);
+       PLUS(X2, X15);
+       pbroadcastd((3 * 4)(INPUT), X15);
+       PLUS(X3, X15);
+       pbroadcastd((4 * 4)(INPUT), X15);
+       PLUS(X4, X15);
+       pbroadcastd((5 * 4)(INPUT), X15);
+       PLUS(X5, X15);
+       pbroadcastd((6 * 4)(INPUT), X15);
+       PLUS(X6, X15);
+       pbroadcastd((7 * 4)(INPUT), X15);
+       PLUS(X7, X15);
+       pbroadcastd((8 * 4)(INPUT), X15);
+       PLUS(X8, X15);
+       pbroadcastd((9 * 4)(INPUT), X15);
+       PLUS(X9, X15);
+       pbroadcastd((10 * 4)(INPUT), X15);
+       PLUS(X10, X15);
+       pbroadcastd((11 * 4)(INPUT), X15);
+       PLUS(X11, X15);
+       movdqa (STACK_VEC_X12)(%rsp), X15;
+       PLUS(X12, X15);
+       movdqa (STACK_VEC_X13)(%rsp), X15;
+       PLUS(X13, X15);
+       movdqa X13, (STACK_TMP)(%rsp);
+       pbroadcastd((14 * 4)(INPUT), X15);
+       PLUS(X14, X15);
+       movdqa (STACK_TMP1)(%rsp), X15;
+       movdqa X14, (STACK_TMP1)(%rsp);
+       pbroadcastd((15 * 4)(INPUT), X13);
+       PLUS(X15, X13);
+       movdqa X15, (STACK_TMP2)(%rsp);
+
+       /* Update counter */
+       addq $4, (12 * 4)(INPUT);
+
+       movq (STACK_MAX + 5 * 8)(%rsp), SRC;
+       movq (STACK_MAX + 6 * 8)(%rsp), DST;
+
+       transpose_4x4(X0, X1, X2, X3, X13, X14, X15);
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 0), X0, X15);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 0), X1, X15);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 0), X2, X15);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 0), X3, X15);
+       transpose_4x4(X4, X5, X6, X7, X0, X1, X2);
+       movdqa (STACK_TMP)(%rsp), X13;
+       movdqa (STACK_TMP1)(%rsp), X14;
+       movdqa (STACK_TMP2)(%rsp), X15;
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 1), X4, X0);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 1), X5, X0);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 1), X6, X0);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 1), X7, X0);
+       transpose_4x4(X8, X9, X10, X11, X0, X1, X2);
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 2), X8, X0);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 2), X9, X0);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 2), X10, X0);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 2), X11, X0);
+       transpose_4x4(X12, X13, X14, X15, X0, X1, X2);
+       xor_src_dst(DST, SRC, (64 * 0 + 16 * 3), X12, X0);
+       xor_src_dst(DST, SRC, (64 * 1 + 16 * 3), X13, X0);
+       xor_src_dst(DST, SRC, (64 * 2 + 16 * 3), X14, X0);
+       xor_src_dst(DST, SRC, (64 * 3 + 16 * 3), X15, X0);
+
+       subq $4, (STACK_MAX + 7 * 8)(%rsp); # NBLKS
+
+       lea (4 * 64)(DST), DST;
+       lea (4 * 64)(SRC), SRC;
+       movq SRC, (STACK_MAX + 5 * 8)(%rsp);
+       movq DST, (STACK_MAX + 6 * 8)(%rsp);
+
+       jnz .Loop_poly4;
+
+       /* Store state */
+       POLY1305_STORE_STATE();
+
+       /* clear the used vector registers and stack */
+       clear(X0);
+       movdqa X0, (STACK_VEC_X12)(%rsp);
+       movdqa X0, (STACK_VEC_X13)(%rsp);
+       movdqa X0, (STACK_TMP)(%rsp);
+       movdqa X0, (STACK_TMP1)(%rsp);
+       movdqa X0, (STACK_TMP2)(%rsp);
+       clear(X1);
+       clear(X2);
+       clear(X3);
+       clear(X4);
+       clear(X5);
+       clear(X6);
+       clear(X7);
+       clear(X8);
+       clear(X9);
+       clear(X10);
+       clear(X11);
+       clear(X12);
+       clear(X13);
+       clear(X14);
+       clear(X15);
+
+       movq (STACK_MAX + 0 * 8)(%rsp), %rbx;
+       movq (STACK_MAX + 1 * 8)(%rsp), %r12;
+       movq (STACK_MAX + 2 * 8)(%rsp), %r13;
+       movq (STACK_MAX + 3 * 8)(%rsp), %r14;
+       movq (STACK_MAX + 4 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
+
+       xorl %eax, %eax;
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_poly1305_amd64_ssse3_blocks4,
+         .-_gcry_chacha20_poly1305_amd64_ssse3_blocks4;)
+
+/**********************************************************************
+  2-way && 1-way stitched chacha20-poly1305
+ **********************************************************************/
+
+.align 8
+.globl _gcry_chacha20_poly1305_amd64_ssse3_blocks1
+ELF(.type _gcry_chacha20_poly1305_amd64_ssse3_blocks1,@function;)
+
+_gcry_chacha20_poly1305_amd64_ssse3_blocks1:
+       /* input:
+        *      %rdi: chacha20-state
+        *      %rsi: dst
+        *      %rdx: src
+        *      %rcx: nblks
+        *      %r9: poly1305-state
+        *      %r8: poly1305-src
+        */
+       CFI_STARTPROC();
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       subq $(9 * 8), %rsp;
+       movq %rbx, (0 * 8)(%rsp);
+       movq %r12, (1 * 8)(%rsp);
+       movq %r13, (2 * 8)(%rsp);
+       movq %r14, (3 * 8)(%rsp);
+       movq %r15, (4 * 8)(%rsp);
+       CFI_REG_ON_STACK(rbx, 0 * 8);
+       CFI_REG_ON_STACK(r12, 1 * 8);
+       CFI_REG_ON_STACK(r13, 2 * 8);
+       CFI_REG_ON_STACK(r14, 3 * 8);
+       CFI_REG_ON_STACK(r15, 4 * 8);
+
+       movq %rdx, (5 * 8)(%rsp); # SRC
+       movq %rsi, (6 * 8)(%rsp); # DST
+       movq %rcx, (7 * 8)(%rsp); # NBLKS
+
+       /* Load constants */
+       movdqa .Lcounter1 rRIP, X4;
+       movdqa .Lshuf_rol8 rRIP, X5;
+       movdqa .Lshuf_rol16 rRIP, X6;
+
+       /* Load state */
+       movdqu (0 * 4)(INPUT), X10;
+       movdqu (4 * 4)(INPUT), X11;
+       movdqu (8 * 4)(INPUT), X12;
+       movdqu (12 * 4)(INPUT), X13;
+
+       POLY1305_LOAD_STATE();
+
+       cmpq $2, (7 * 8)(%rsp); #NBLKS
+       jb .Loop_poly1;
+
+       movdqa X10, X0;
+       movdqa X11, X1;
+       movdqa X12, X2;
+       movdqa X13, X3;
+
+       movdqa X10, X8;
+       movdqa X11, X9;
+       movdqa X12, X14;
+       movdqa X13, X15;
+       paddq X4, X15;
+
+       /* Process two ChaCha20 blocks and eight Poly1305 blocks. */
+
+       movl $20, (8 * 8 + 4)(%rsp);
+.Lround2_with_poly1305_outer:
+       movl $8, (8 * 8)(%rsp);
+.Lround2_with_poly1305_inner:
+       POLY1305_BLOCK_PART1(0 * 16);
+         QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
+       lea (1 * 16)(POLY_RSRC), POLY_RSRC;
+       POLY1305_BLOCK_PART2();
+         QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
+       POLY1305_BLOCK_PART3();
+         QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
+       POLY1305_BLOCK_PART4();
+         QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
+       POLY1305_BLOCK_PART5();
+
+       subl $2, (8 * 8)(%rsp);
+       jnz .Lround2_with_poly1305_inner;
+
+         QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x39, 0x4e, 0x93);
+         QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x39, 0x4e, 0x93);
+         QUARTERROUND4(X0, X1, X2,  X3,  X5, X6, X7, 0x93, 0x4e, 0x39);
+         QUARTERROUND4(X8, X9, X14, X15, X5, X6, X7, 0x93, 0x4e, 0x39);
+
+       subl $10, (8 * 8 + 4)(%rsp);
+       jnz .Lround2_with_poly1305_outer;
+
+       movq (5 * 8)(%rsp), SRC;
+       movq (6 * 8)(%rsp), DST;
+
+       PLUS(X0, X10);
+       PLUS(X1, X11);
+       PLUS(X2, X12);
+       PLUS(X3, X13);
+
+       /* Update counter */
+       paddq X4, X13;
+
+       PLUS(X8, X10);
+       PLUS(X9, X11);
+       PLUS(X14, X12);
+       PLUS(X15, X13);
+
+       /* Update counter */
+       paddq X4, X13;
+
+       xor_src_dst(DST, SRC, 0 * 4, X0, X7);
+       xor_src_dst(DST, SRC, 4 * 4, X1, X7);
+       xor_src_dst(DST, SRC, 8 * 4, X2, X7);
+       xor_src_dst(DST, SRC, 12 * 4, X3, X7);
+       xor_src_dst(DST, SRC, 16 * 4, X8, X7);
+       xor_src_dst(DST, SRC, 20 * 4, X9, X7);
+       xor_src_dst(DST, SRC, 24 * 4, X14, X7);
+       xor_src_dst(DST, SRC, 28 * 4, X15, X7);
+
+       clear(X8);
+       clear(X9);
+       clear(X14);
+       clear(X15);
+
+       subq $2, (7 * 8)(%rsp); # NBLKS
+       lea (2 * 64)(SRC), SRC;
+       lea (2 * 64)(DST), DST;
+       movq SRC, (5 * 8)(%rsp);
+       movq DST, (6 * 8)(%rsp);
+       jz .Ldone_poly1;
+
+.Loop_poly1:
+       movdqa X10, X0;
+       movdqa X11, X1;
+       movdqa X12, X2;
+       movdqa X13, X3;
+
+       /* Process one ChaCha20 block and four Poly1305 blocks. */
+
+       movl $20, (8 * 8 + 4)(%rsp);
+.Lround1_with_poly1305_outer:
+       movl $8, (8 * 8)(%rsp);
+.Lround1_with_poly1305_inner:
+       POLY1305_BLOCK_PART1(0 * 16);
+         QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
+       POLY1305_BLOCK_PART2();
+         QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
+       lea (1 * 16)(POLY_RSRC), POLY_RSRC;
+
+       POLY1305_BLOCK_PART3();
+         QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
+       POLY1305_BLOCK_PART4();
+         QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
+       POLY1305_BLOCK_PART5();
+
+       subl $4, (8 * 8)(%rsp);
+       jnz .Lround1_with_poly1305_inner;
+
+         QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x39, 0x4e, 0x93);
+         QUARTERROUND4(X0, X1, X2, X3, X5, X6, X7, 0x93, 0x4e, 0x39);
+
+       subl $10, (8 * 8 + 4)(%rsp);
+       jnz .Lround1_with_poly1305_outer;
+
+       movq (5 * 8)(%rsp), SRC;
+       movq (6 * 8)(%rsp), DST;
+
+       PLUS(X0, X10);
+       PLUS(X1, X11);
+       PLUS(X2, X12);
+       PLUS(X3, X13);
+
+       /* Update counter */
+       paddq X4, X13;
+
+       xor_src_dst(DST, SRC, 0 * 4, X0, X7);
+       xor_src_dst(DST, SRC, 4 * 4, X1, X7);
+       xor_src_dst(DST, SRC, 8 * 4, X2, X7);
+       xor_src_dst(DST, SRC, 12 * 4, X3, X7);
+
+       subq $1, (7 * 8)(%rsp); # NBLKS
+       lea (64)(SRC), SRC;
+       lea (64)(DST), DST;
+       movq SRC, (5 * 8)(%rsp);
+       movq DST, (6 * 8)(%rsp);
+
+       jnz .Loop_poly1;
+
+.Ldone_poly1:
+       /* Store state */
+       POLY1305_STORE_STATE();
+
+       movdqu X13, (12 * 4)(INPUT);
+
+       /* clear the used vector registers */
+       clear(X0);
+       clear(X1);
+       clear(X2);
+       clear(X3);
+       clear(X4);
+       clear(X5);
+       clear(X6);
+       clear(X7);
+       clear(X10);
+       clear(X11);
+       clear(X12);
+       clear(X13);
+
+       movq (0 * 8)(%rsp), %rbx;
+       movq (1 * 8)(%rsp), %r12;
+       movq (2 * 8)(%rsp), %r13;
+       movq (3 * 8)(%rsp), %r14;
+       movq (4 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
+
+       xorl %eax, %eax;
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_poly1305_amd64_ssse3_blocks1,
+         .-_gcry_chacha20_poly1305_amd64_ssse3_blocks1;)
+
+#endif /*defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS)*/
+#endif /*__x86_64*/
index c1971fc..a862be4 100644 (file)
@@ -1,6 +1,6 @@
-/* chacha20-armv7-neon.S - ARM/NEON accelerated chacha20 blocks function
+/* chacha20-armv7-neon.S  -  ARMv7 NEON implementation of ChaCha20 cipher
  *
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2017,2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
  */
 
 /*
- * Based on public domain implementation by Andrew Moon at
- *  https://github.com/floodyberry/chacha-opt
+ * Based on D. J. Bernstein reference implementation at
+ * http://cr.yp.to/chacha.html:
+ *
+ * chacha-regs.c version 20080118
+ * D. J. Bernstein
+ * Public domain.
  */
 
 #include <config.h>
 
 #if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \
     defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
-    defined(HAVE_GCC_INLINE_ASM_NEON) && defined(USE_CHACHA20)
+    defined(HAVE_GCC_INLINE_ASM_NEON)
 
 .syntax unified
 .fpu neon
 .arm
 
-#define UNALIGNED_STMIA8(ptr, l0, l1, l2, l3, l4, l5, l6, l7) \
-        tst ptr, #3; \
-        beq 1f; \
-        vpush {d0-d3}; \
-        vmov s0, l0; \
-        vmov s1, l1; \
-        vmov s2, l2; \
-        vmov s3, l3; \
-        vmov s4, l4; \
-        vmov s5, l5; \
-        vmov s6, l6; \
-        vmov s7, l7; \
-        vst1.32 {d0-d3}, [ptr]; \
-        add ptr, #32; \
-        vpop {d0-d3}; \
-        b 2f; \
-     1: stmia ptr!, {l0-l7}; \
-     2: ;
-
-#define UNALIGNED_LDMIA4(ptr, l0, l1, l2, l3) \
-        tst ptr, #3; \
-        beq 1f; \
-        vpush {d0-d1}; \
-        vld1.32 {d0-d1}, [ptr]; \
-        add ptr, #16; \
-        vmov l0, s0; \
-        vmov l1, s1; \
-        vmov l2, s2; \
-        vmov l3, s3; \
-        vpop {d0-d1}; \
-        b 2f; \
-     1: ldmia ptr!, {l0-l3}; \
-     2: ;
-
 .text
 
-.globl _gcry_chacha20_armv7_neon_blocks
-.type  _gcry_chacha20_armv7_neon_blocks,%function;
-_gcry_chacha20_armv7_neon_blocks:
-.Lchacha_blocks_neon_local:
-       tst r3, r3
-       beq .Lchacha_blocks_neon_nobytes
-       vstmdb sp!, {q4,q5,q6,q7}
-       stmfd sp!, {r4-r12, r14}
-       mov r8, sp
-       sub sp, sp, #196
-       and sp, sp, #0xffffffe0
-       str r0, [sp, #60]
-       str r1, [sp, #48]
-       str r2, [sp, #40]
-       str r3, [sp, #52]
-       str r8, [sp, #192]
-       add r1, sp, #64
-       ldmia r0!, {r4-r11}
-       stmia r1!, {r4-r11}
-       ldmia r0!, {r4-r11}
-       stmia r1!, {r4-r11}
-       mov r4, #20
-       str r4, [sp, #44]
-       cmp r3, #256
-       blo .Lchacha_blocks_neon_mainloop2
-.Lchacha_blocks_neon_mainloop1:
-       ldr r0, [sp, #44]
-       str r0, [sp, #0]
-       add r1, sp, #(64)
-       mov r2, #1
-       veor q12, q12
-       vld1.32 {q0,q1}, [r1,:128]!
-       vld1.32 {q2,q3}, [r1,:128]
-       vmov.32 d24[0], r2
-       vadd.u64 q3, q3, q12
-       vmov q4, q0
-       vmov q5, q1
-       vmov q6, q2
-       vadd.u64 q7, q3, q12
-       vmov q8, q0
-       vmov q9, q1
-       vmov q10, q2
-       vadd.u64 q11, q7, q12
-       add r0, sp, #64
-       ldm r0, {r0-r12}
-       ldr r14, [sp, #(64 +60)]
-       str r6, [sp, #8]
-       str r11, [sp, #12]
-       str r14, [sp, #28]
-       ldr r11, [sp, #(64 +52)]
-       ldr r14, [sp, #(64 +56)]
-.Lchacha_blocks_neon_rounds1:
-       ldr r6, [sp, #0]
-       vadd.i32 q0, q0, q1
-       add r0, r0, r4
-       vadd.i32 q4, q4, q5
-       add r1, r1, r5
-       vadd.i32 q8, q8, q9
-       eor r12, r12, r0
-       veor q12, q3, q0
-       eor r11, r11, r1
-       veor q13, q7, q4
-       ror r12, r12, #16
-       veor q14, q11, q8
-       ror r11, r11, #16
-       vrev32.16 q3, q12
-       subs r6, r6, #2
-       vrev32.16 q7, q13
-       add r8, r8, r12
-       vrev32.16 q11, q14
-       add r9, r9, r11
-       vadd.i32 q2, q2, q3
-       eor r4, r4, r8
-       vadd.i32 q6, q6, q7
-       eor r5, r5, r9
-       vadd.i32 q10, q10, q11
-       str r6, [sp, #0]
-       veor q12, q1, q2
-       ror r4, r4, #20
-       veor q13, q5, q6
-       ror r5, r5, #20
-       veor q14, q9, q10
-       add r0, r0, r4
-       vshl.i32 q1, q12, #12
-       add r1, r1, r5
-       vshl.i32 q5, q13, #12
-       ldr r6, [sp, #8]
-       vshl.i32 q9, q14, #12
-       eor r12, r12, r0
-       vsri.u32 q1, q12, #20
-       eor r11, r11, r1
-       vsri.u32 q5, q13, #20
-       ror r12, r12, #24
-       vsri.u32 q9, q14, #20
-       ror r11, r11, #24
-       vadd.i32 q0, q0, q1
-       add r8, r8, r12
-       vadd.i32 q4, q4, q5
-       add r9, r9, r11
-       vadd.i32 q8, q8, q9
-       eor r4, r4, r8
-       veor q12, q3, q0
-       eor r5, r5, r9
-       veor q13, q7, q4
-       str r11, [sp, #20]
-       veor q14, q11, q8
-       ror r4, r4, #25
-       vshl.i32 q3, q12, #8
-       ror r5, r5, #25
-       vshl.i32 q7, q13, #8
-       str r4, [sp, #4]
-       vshl.i32 q11, q14, #8
-       ldr r4, [sp, #28]
-       vsri.u32 q3, q12, #24
-       add r2, r2, r6
-       vsri.u32 q7, q13, #24
-       add r3, r3, r7
-       vsri.u32 q11, q14, #24
-       ldr r11, [sp, #12]
-       vadd.i32 q2, q2, q3
-       eor r14, r14, r2
-       vadd.i32 q6, q6, q7
-       eor r4, r4, r3
-       vadd.i32 q10, q10, q11
-       ror r14, r14, #16
-       veor q12, q1, q2
-       ror r4, r4, #16
-       veor q13, q5, q6
-       add r10, r10, r14
-       veor q14, q9, q10
-       add r11, r11, r4
-       vshl.i32 q1, q12, #7
-       eor r6, r6, r10
-       vshl.i32 q5, q13, #7
-       eor r7, r7, r11
-       vshl.i32 q9, q14, #7
-       ror r6, r6, #20
-       vsri.u32 q1, q12, #25
-       ror r7, r7, #20
-       vsri.u32 q5, q13, #25
-       add r2, r2, r6
-       vsri.u32 q9, q14, #25
-       add r3, r3, r7
-       vext.32 q3, q3, q3, #3
-       eor r14, r14, r2
-       vext.32 q7, q7, q7, #3
-       eor r4, r4, r3
-       vext.32 q11, q11, q11, #3
-       ror r14, r14, #24
-       vext.32 q1, q1, q1, #1
-       ror r4, r4, #24
-       vext.32 q5, q5, q5, #1
-       add r10, r10, r14
-       vext.32 q9, q9, q9, #1
-       add r11, r11, r4
-       vext.32 q2, q2, q2, #2
-       eor r6, r6, r10
-       vext.32 q6, q6, q6, #2
-       eor r7, r7, r11
-       vext.32 q10, q10, q10, #2
-       ror r6, r6, #25
-       vadd.i32 q0, q0, q1
-       ror r7, r7, #25
-       vadd.i32 q4, q4, q5
-       add r0, r0, r5
-       vadd.i32 q8, q8, q9
-       add r1, r1, r6
-       veor q12, q3, q0
-       eor r4, r4, r0
-       veor q13, q7, q4
-       eor r12, r12, r1
-       veor q14, q11, q8
-       ror r4, r4, #16
-       vrev32.16 q3, q12
-       ror r12, r12, #16
-       vrev32.16 q7, q13
-       add r10, r10, r4
-       vrev32.16 q11, q14
-       add r11, r11, r12
-       vadd.i32 q2, q2, q3
-       eor r5, r5, r10
-       vadd.i32 q6, q6, q7
-       eor r6, r6, r11
-       vadd.i32 q10, q10, q11
-       ror r5, r5, #20
-       veor q12, q1, q2
-       ror r6, r6, #20
-       veor q13, q5, q6
-       add r0, r0, r5
-       veor q14, q9, q10
-       add r1, r1, r6
-       vshl.i32 q1, q12, #12
-       eor r4, r4, r0
-       vshl.i32 q5, q13, #12
-       eor r12, r12, r1
-       vshl.i32 q9, q14, #12
-       ror r4, r4, #24
-       vsri.u32 q1, q12, #20
-       ror r12, r12, #24
-       vsri.u32 q5, q13, #20
-       add r10, r10, r4
-       vsri.u32 q9, q14, #20
-       add r11, r11, r12
-       vadd.i32 q0, q0, q1
-       eor r5, r5, r10
-       vadd.i32 q4, q4, q5
-       eor r6, r6, r11
-       vadd.i32 q8, q8, q9
-       str r11, [sp, #12]
-       veor q12, q3, q0
-       ror r5, r5, #25
-       veor q13, q7, q4
-       ror r6, r6, #25
-       veor q14, q11, q8
-       str r4, [sp, #28]
-       vshl.i32 q3, q12, #8
-       ldr r4, [sp, #4]
-       vshl.i32 q7, q13, #8
-       add r2, r2, r7
-       vshl.i32 q11, q14, #8
-       add r3, r3, r4
-       vsri.u32 q3, q12, #24
-       ldr r11, [sp, #20]
-       vsri.u32 q7, q13, #24
-       eor r11, r11, r2
-       vsri.u32 q11, q14, #24
-       eor r14, r14, r3
-       vadd.i32 q2, q2, q3
-       ror r11, r11, #16
-       vadd.i32 q6, q6, q7
-       ror r14, r14, #16
-       vadd.i32 q10, q10, q11
-       add r8, r8, r11
-       veor q12, q1, q2
-       add r9, r9, r14
-       veor q13, q5, q6
-       eor r7, r7, r8
-       veor q14, q9, q10
-       eor r4, r4, r9
-       vshl.i32 q1, q12, #7
-       ror r7, r7, #20
-       vshl.i32 q5, q13, #7
-       ror r4, r4, #20
-       vshl.i32 q9, q14, #7
-       str r6, [sp, #8]
-       vsri.u32 q1, q12, #25
-       add r2, r2, r7
-       vsri.u32 q5, q13, #25
-       add r3, r3, r4
-       vsri.u32 q9, q14, #25
-       eor r11, r11, r2
-       vext.32 q3, q3, q3, #1
-       eor r14, r14, r3
-       vext.32 q7, q7, q7, #1
-       ror r11, r11, #24
-       vext.32 q11, q11, q11, #1
-       ror r14, r14, #24
-       vext.32 q1, q1, q1, #3
-       add r8, r8, r11
-       vext.32 q5, q5, q5, #3
-       add r9, r9, r14
-       vext.32 q9, q9, q9, #3
-       eor r7, r7, r8
-       vext.32 q2, q2, q2, #2
-       eor r4, r4, r9
-       vext.32 q6, q6, q6, #2
-       ror r7, r7, #25
-       vext.32 q10, q10, q10, #2
-       ror r4, r4, #25
-       bne .Lchacha_blocks_neon_rounds1
-       str r8, [sp, #0]
-       str r9, [sp, #4]
-       str r10, [sp, #8]
-       str r12, [sp, #16]
-       str r11, [sp, #20]
-       str r14, [sp, #24]
-       add r9, sp, #64
-       vld1.32 {q12,q13}, [r9,:128]!
-       ldr r12, [sp, #48]
-       vld1.32 {q14,q15}, [r9,:128]
-       ldr r14, [sp, #40]
-       vadd.i32 q0, q0, q12
-       ldr r8, [sp, #(64 +0)]
-       vadd.i32 q4, q4, q12
-       ldr r9, [sp, #(64 +4)]
-       vadd.i32 q8, q8, q12
-       ldr r10, [sp, #(64 +8)]
-       vadd.i32 q1, q1, q13
-       ldr r11, [sp, #(64 +12)]
-       vadd.i32 q5, q5, q13
-       add r0, r0, r8
-       vadd.i32 q9, q9, q13
-       add r1, r1, r9
-       vadd.i32 q2, q2, q14
-       add r2, r2, r10
-       vadd.i32 q6, q6, q14
-       ldr r8, [sp, #(64 +16)]
-       vadd.i32 q10, q10, q14
-       add r3, r3, r11
-       veor q14, q14, q14
-       ldr r9, [sp, #(64 +20)]
-       mov r11, #1
-       add r4, r4, r8
-       vmov.32 d28[0], r11
-       ldr r10, [sp, #(64 +24)]
-       vadd.u64 q12, q14, q15
-       add r5, r5, r9
-       vadd.u64 q13, q14, q12
-       ldr r11, [sp, #(64 +28)]
-       vadd.u64 q14, q14, q13
-       add r6, r6, r10
-       vadd.i32 q3, q3, q12
-       tst r12, r12
-       vadd.i32 q7, q7, q13
-       add r7, r7, r11
-       vadd.i32 q11, q11, q14
-       beq .Lchacha_blocks_neon_nomessage11
-       UNALIGNED_LDMIA4(r12, r8, r9, r10, r11)
-       tst r12, r12
-       eor r0, r0, r8
-       eor r1, r1, r9
-       eor r2, r2, r10
-       ldr r8, [r12, #0]
-       eor r3, r3, r11
-       ldr r9, [r12, #4]
-       eor r4, r4, r8
-       ldr r10, [r12, #8]
-       eor r5, r5, r9
-       ldr r11, [r12, #12]
-       eor r6, r6, r10
-       add r12, r12, #16
-       eor r7, r7, r11
-.Lchacha_blocks_neon_nomessage11:
-       UNALIGNED_STMIA8(r14, r0, r1, r2, r3, r4, r5, r6, r7)
-       tst r12, r12
-       ldm sp, {r0-r7}
-       ldr r8, [sp, #(64 +32)]
-       ldr r9, [sp, #(64 +36)]
-       ldr r10, [sp, #(64 +40)]
-       ldr r11, [sp, #(64 +44)]
-       add r0, r0, r8
-       add r1, r1, r9
-       add r2, r2, r10
-       ldr r8, [sp, #(64 +48)]
-       add r3, r3, r11
-       ldr r9, [sp, #(64 +52)]
-       add r4, r4, r8
-       ldr r10, [sp, #(64 +56)]
-       add r5, r5, r9
-       ldr r11, [sp, #(64 +60)]
-       add r6, r6, r10
-       adds r8, r8, #4
-       add r7, r7, r11
-       adc r9, r9, #0
-       str r8, [sp, #(64 +48)]
-       tst r12, r12
-       str r9, [sp, #(64 +52)]
-       beq .Lchacha_blocks_neon_nomessage12
-       UNALIGNED_LDMIA4(r12, r8, r9, r10, r11)
-       tst r12, r12
-       eor r0, r0, r8
-       eor r1, r1, r9
-       eor r2, r2, r10
-       ldr r8, [r12, #0]
-       eor r3, r3, r11
-       ldr r9, [r12, #4]
-       eor r4, r4, r8
-       ldr r10, [r12, #8]
-       eor r5, r5, r9
-       ldr r11, [r12, #12]
-       eor r6, r6, r10
-       add r12, r12, #16
-       eor r7, r7, r11
-.Lchacha_blocks_neon_nomessage12:
-       UNALIGNED_STMIA8(r14, r0, r1, r2, r3, r4, r5, r6, r7)
-       tst r12, r12
-       beq .Lchacha_blocks_neon_nomessage13
-       vld1.32 {q12,q13}, [r12]!
-       vld1.32 {q14,q15}, [r12]!
-       veor q0, q0, q12
-       veor q1, q1, q13
-       veor q2, q2, q14
-       veor q3, q3, q15
-.Lchacha_blocks_neon_nomessage13:
-       vst1.32 {q0,q1}, [r14]!
-       vst1.32 {q2,q3}, [r14]!
-       beq .Lchacha_blocks_neon_nomessage14
-       vld1.32 {q12,q13}, [r12]!
-       vld1.32 {q14,q15}, [r12]!
-       veor q4, q4, q12
-       veor q5, q5, q13
-       veor q6, q6, q14
-       veor q7, q7, q15
-.Lchacha_blocks_neon_nomessage14:
-       vst1.32 {q4,q5}, [r14]!
-       vst1.32 {q6,q7}, [r14]!
-       beq .Lchacha_blocks_neon_nomessage15
-       vld1.32 {q12,q13}, [r12]!
-       vld1.32 {q14,q15}, [r12]!
-       veor q8, q8, q12
-       veor q9, q9, q13
-       veor q10, q10, q14
-       veor q11, q11, q15
-.Lchacha_blocks_neon_nomessage15:
-       vst1.32 {q8,q9}, [r14]!
-       vst1.32 {q10,q11}, [r14]!
-       str r12, [sp, #48]
-       str r14, [sp, #40]
-       ldr r3, [sp, #52]
-       sub r3, r3, #256
-       cmp r3, #256
-       str r3, [sp, #52]
-       bhs .Lchacha_blocks_neon_mainloop1
-       tst r3, r3
-       beq .Lchacha_blocks_neon_done
-.Lchacha_blocks_neon_mainloop2:
-       ldr r3, [sp, #52]
-       ldr r1, [sp, #48]
-       cmp r3, #64
-       bhs .Lchacha_blocks_neon_noswap1
-       add r4, sp, #128
-       mov r5, r4
-       tst r1, r1
-       beq .Lchacha_blocks_neon_nocopy1
-.Lchacha_blocks_neon_copyinput1:
-       subs r3, r3, #1
-       ldrb r0, [r1], #1
-       strb r0, [r4], #1
-       bne .Lchacha_blocks_neon_copyinput1
-       str r5, [sp, #48]
-.Lchacha_blocks_neon_nocopy1:
-       ldr r4, [sp, #40]
-       str r5, [sp, #40]
-       str r4, [sp, #56]
-.Lchacha_blocks_neon_noswap1:
-       ldr r0, [sp, #44]
-       str r0, [sp, #0]
-       add r0, sp, #64
-       ldm r0, {r0-r12}
-       ldr r14, [sp, #(64 +60)]
-       str r6, [sp, #8]
-       str r11, [sp, #12]
-       str r14, [sp, #28]
-       ldr r11, [sp, #(64 +52)]
-       ldr r14, [sp, #(64 +56)]
-.Lchacha_blocks_neon_rounds2:
-       ldr r6, [sp, #0]
-       add r0, r0, r4
-       add r1, r1, r5
-       eor r12, r12, r0
-       eor r11, r11, r1
-       ror r12, r12, #16
-       ror r11, r11, #16
-       subs r6, r6, #2
-       add r8, r8, r12
-       add r9, r9, r11
-       eor r4, r4, r8
-       eor r5, r5, r9
-       str r6, [sp, #0]
-       ror r4, r4, #20
-       ror r5, r5, #20
-       add r0, r0, r4
-       add r1, r1, r5
-       ldr r6, [sp, #8]
-       eor r12, r12, r0
-       eor r11, r11, r1
-       ror r12, r12, #24
-       ror r11, r11, #24
-       add r8, r8, r12
-       add r9, r9, r11
-       eor r4, r4, r8
-       eor r5, r5, r9
-       str r11, [sp, #20]
-       ror r4, r4, #25
-       ror r5, r5, #25
-       str r4, [sp, #4]
-       ldr r4, [sp, #28]
-       add r2, r2, r6
-       add r3, r3, r7
-       ldr r11, [sp, #12]
-       eor r14, r14, r2
-       eor r4, r4, r3
-       ror r14, r14, #16
-       ror r4, r4, #16
-       add r10, r10, r14
-       add r11, r11, r4
-       eor r6, r6, r10
-       eor r7, r7, r11
-       ror r6, r6, #20
-       ror r7, r7, #20
-       add r2, r2, r6
-       add r3, r3, r7
-       eor r14, r14, r2
-       eor r4, r4, r3
-       ror r14, r14, #24
-       ror r4, r4, #24
-       add r10, r10, r14
-       add r11, r11, r4
-       eor r6, r6, r10
-       eor r7, r7, r11
-       ror r6, r6, #25
-       ror r7, r7, #25
-       add r0, r0, r5
-       add r1, r1, r6
-       eor r4, r4, r0
-       eor r12, r12, r1
-       ror r4, r4, #16
-       ror r12, r12, #16
-       add r10, r10, r4
-       add r11, r11, r12
-       eor r5, r5, r10
-       eor r6, r6, r11
-       ror r5, r5, #20
-       ror r6, r6, #20
-       add r0, r0, r5
-       add r1, r1, r6
-       eor r4, r4, r0
-       eor r12, r12, r1
-       ror r4, r4, #24
-       ror r12, r12, #24
-       add r10, r10, r4
-       add r11, r11, r12
-       eor r5, r5, r10
-       eor r6, r6, r11
-       str r11, [sp, #12]
-       ror r5, r5, #25
-       ror r6, r6, #25
-       str r4, [sp, #28]
-       ldr r4, [sp, #4]
-       add r2, r2, r7
-       add r3, r3, r4
-       ldr r11, [sp, #20]
-       eor r11, r11, r2
-       eor r14, r14, r3
-       ror r11, r11, #16
-       ror r14, r14, #16
-       add r8, r8, r11
-       add r9, r9, r14
-       eor r7, r7, r8
-       eor r4, r4, r9
-       ror r7, r7, #20
-       ror r4, r4, #20
-       str r6, [sp, #8]
-       add r2, r2, r7
-       add r3, r3, r4
-       eor r11, r11, r2
-       eor r14, r14, r3
-       ror r11, r11, #24
-       ror r14, r14, #24
-       add r8, r8, r11
-       add r9, r9, r14
-       eor r7, r7, r8
-       eor r4, r4, r9
-       ror r7, r7, #25
-       ror r4, r4, #25
-       bne .Lchacha_blocks_neon_rounds2
-       str r8, [sp, #0]
-       str r9, [sp, #4]
-       str r10, [sp, #8]
-       str r12, [sp, #16]
-       str r11, [sp, #20]
-       str r14, [sp, #24]
-       ldr r12, [sp, #48]
-       ldr r14, [sp, #40]
-       ldr r8, [sp, #(64 +0)]
-       ldr r9, [sp, #(64 +4)]
-       ldr r10, [sp, #(64 +8)]
-       ldr r11, [sp, #(64 +12)]
-       add r0, r0, r8
-       add r1, r1, r9
-       add r2, r2, r10
-       ldr r8, [sp, #(64 +16)]
-       add r3, r3, r11
-       ldr r9, [sp, #(64 +20)]
-       add r4, r4, r8
-       ldr r10, [sp, #(64 +24)]
-       add r5, r5, r9
-       ldr r11, [sp, #(64 +28)]
-       add r6, r6, r10
-       tst r12, r12
-       add r7, r7, r11
-       beq .Lchacha_blocks_neon_nomessage21
-       UNALIGNED_LDMIA4(r12, r8, r9, r10, r11)
-       tst r12, r12
-       eor r0, r0, r8
-       eor r1, r1, r9
-       eor r2, r2, r10
-       ldr r8, [r12, #0]
-       eor r3, r3, r11
-       ldr r9, [r12, #4]
-       eor r4, r4, r8
-       ldr r10, [r12, #8]
-       eor r5, r5, r9
-       ldr r11, [r12, #12]
-       eor r6, r6, r10
-       add r12, r12, #16
-       eor r7, r7, r11
-.Lchacha_blocks_neon_nomessage21:
-       UNALIGNED_STMIA8(r14, r0, r1, r2, r3, r4, r5, r6, r7)
-       ldm sp, {r0-r7}
-       ldr r8, [sp, #(64 +32)]
-       ldr r9, [sp, #(64 +36)]
-       ldr r10, [sp, #(64 +40)]
-       ldr r11, [sp, #(64 +44)]
-       add r0, r0, r8
-       add r1, r1, r9
-       add r2, r2, r10
-       ldr r8, [sp, #(64 +48)]
-       add r3, r3, r11
-       ldr r9, [sp, #(64 +52)]
-       add r4, r4, r8
-       ldr r10, [sp, #(64 +56)]
-       add r5, r5, r9
-       ldr r11, [sp, #(64 +60)]
-       add r6, r6, r10
-       adds r8, r8, #1
-       add r7, r7, r11
-       adc r9, r9, #0
-       str r8, [sp, #(64 +48)]
-       tst r12, r12
-       str r9, [sp, #(64 +52)]
-       beq .Lchacha_blocks_neon_nomessage22
-       UNALIGNED_LDMIA4(r12, r8, r9, r10, r11)
-       tst r12, r12
-       eor r0, r0, r8
-       eor r1, r1, r9
-       eor r2, r2, r10
-       ldr r8, [r12, #0]
-       eor r3, r3, r11
-       ldr r9, [r12, #4]
-       eor r4, r4, r8
-       ldr r10, [r12, #8]
-       eor r5, r5, r9
-       ldr r11, [r12, #12]
-       eor r6, r6, r10
-       add r12, r12, #16
-       eor r7, r7, r11
-.Lchacha_blocks_neon_nomessage22:
-       UNALIGNED_STMIA8(r14, r0, r1, r2, r3, r4, r5, r6, r7)
-       str r12, [sp, #48]
-       str r14, [sp, #40]
-       ldr r3, [sp, #52]
-       cmp r3, #64
-       sub r4, r3, #64
-       str r4, [sp, #52]
-       bhi .Lchacha_blocks_neon_mainloop2
-       cmp r3, #64
-       beq .Lchacha_blocks_neon_nocopy2
-       ldr r1, [sp, #56]
-       sub r14, r14, #64
-.Lchacha_blocks_neon_copyinput2:
-       subs r3, r3, #1
-       ldrb r0, [r14], #1
-       strb r0, [r1], #1
-       bne .Lchacha_blocks_neon_copyinput2
-.Lchacha_blocks_neon_nocopy2:
-.Lchacha_blocks_neon_done:
-       ldr r7, [sp, #60]
-       ldr r8, [sp, #(64 +48)]
-       ldr r9, [sp, #(64 +52)]
-       str r8, [r7, #(48 + 0)]
-       str r9, [r7, #(48 + 4)]
+#ifdef __PIC__
+#  define GET_DATA_POINTER(reg, name, rtmp) \
+               ldr reg, 1f; \
+               ldr rtmp, 2f; \
+               b 3f; \
+       1:      .word _GLOBAL_OFFSET_TABLE_-(3f+8); \
+       2:      .word name(GOT); \
+       3:      add reg, pc, reg; \
+               ldr reg, [reg, rtmp];
+#else
+#  define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name
+#endif
+
+/* register macros */
+#define INPUT r0
+#define DST   r1
+#define SRC   r2
+#define NBLKS r3
+#define ROUND r4
+
+/* stack structure */
+#define STACK_VEC_X12 (16)
+#define STACK_VEC_X13 (STACK_VEC_X12 + 16)
+#define STACK_TMP     (STACK_VEC_X13 + 16)
+#define STACK_TMP1    (16 + STACK_TMP)
+#define STACK_TMP2    (16 + STACK_TMP1)
+
+#define STACK_MAX     (16 + STACK_TMP2)
+
+/* vector registers */
+#define X0 q0
+#define X1 q1
+#define X2 q2
+#define X3 q3
+#define X4 q4
+#define X5 q5
+#define X6 q6
+#define X7 q7
+#define X8 q8
+#define X9 q9
+#define X10 q10
+#define X11 q11
+#define X12 q12
+#define X13 q13
+#define X14 q14
+#define X15 q15
+
+#define X0l d0
+#define X1l d2
+#define X2l d4
+#define X3l d6
+#define X4l d8
+#define X5l d10
+#define X6l d12
+#define X7l d14
+#define X8l d16
+#define X9l d18
+#define X10l d20
+#define X11l d22
+#define X12l d24
+#define X13l d26
+#define X14l d28
+#define X15l d30
+
+#define X0h d1
+#define X1h d3
+#define X2h d5
+#define X3h d7
+#define X4h d9
+#define X5h d11
+#define X6h d13
+#define X7h d15
+#define X8h d17
+#define X9h d19
+#define X10h d21
+#define X11h d23
+#define X12h d25
+#define X13h d27
+#define X14h d29
+#define X15h d31
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+
+/* 4x4 32-bit integer matrix transpose */
+#define transpose_4x4_part1(_q0, _q1, _q2, _q3)        \
+       vtrn.32 _q0, _q1;                       \
+       vtrn.32 _q2, _q3;
+#define transpose_4x4_part2(_q0, _q1, _q2, _q3)        \
+       vswp _q0##h, _q2##l;                    \
+       vswp _q1##h, _q3##l;
+
+#define clear(x) vmov.i8 x, #0;
+
+/**********************************************************************
+  4-way chacha20
+ **********************************************************************/
+
+#define ROTATE2(dst1,dst2,c,src1,src2)         \
+       vshl.u32 dst1, src1, #(c);              \
+       vshl.u32 dst2, src2, #(c);              \
+       vsri.u32 dst1, src1, #(32 - (c));       \
+       vsri.u32 dst2, src2, #(32 - (c));
+
+#define ROTATE2_16(dst1,dst2,src1,src2)                \
+       vrev32.16 dst1, src1;                   \
+       vrev32.16 dst2, src2;
+
+#define XOR(d,s1,s2) \
+       veor d, s2, s1;
+
+#define PLUS(ds,s) \
+       vadd.u32 ds, ds, s;
+
+#define QUARTERROUND2(a1,b1,c1,d1,a2,b2,c2,d2,ign,tmp1,tmp2)           \
+       PLUS(a1,b1); PLUS(a2,b2); XOR(tmp1,d1,a1); XOR(tmp2,d2,a2);     \
+           ROTATE2_16(d1, d2, tmp1, tmp2);                             \
+       PLUS(c1,d1); PLUS(c2,d2); XOR(tmp1,b1,c1); XOR(tmp2,b2,c2);     \
+           ROTATE2(b1, b2, 12, tmp1, tmp2);                            \
+       PLUS(a1,b1); PLUS(a2,b2); XOR(tmp1,d1,a1); XOR(tmp2,d2,a2);     \
+           ROTATE2(d1, d2,  8, tmp1, tmp2);                            \
+       PLUS(c1,d1); PLUS(c2,d2); XOR(tmp1,b1,c1); XOR(tmp2,b2,c2);     \
+           ROTATE2(b1, b2,  7, tmp1, tmp2);
+
+chacha20_data:
+.align 4
+.Linc_counter:
+       .long 0,1,2,3
+
+.align 3
+.globl _gcry_chacha20_armv7_neon_blocks4
+.type _gcry_chacha20_armv7_neon_blocks4,%function;
+
+_gcry_chacha20_armv7_neon_blocks4:
+       /* input:
+        *      r0: input
+        *      r1: dst
+        *      r2: src
+        *      r3: nblks (multiple of 4)
+        */
+
+       vpush {q4-q7};
+       push {r4-r12,lr};
+
        mov r12, sp
-       stmia r12!, {r0-r7}
-       add r12, r12, #48
-       stmia r12!, {r0-r7}
-       sub r0, sp, #8
-       ldr sp, [sp, #192]
-       ldmfd sp!, {r4-r12, r14}
-       vldm sp!, {q4-q7}
-       sub r0, sp, r0
-       bx lr
-.Lchacha_blocks_neon_nobytes:
-       mov r0, #0;
+
+       mov r6, sp;
+       sub r6, r6, #(STACK_MAX);
+       and r6, r6, #(~15);
+       mov sp, r6;
+       GET_DATA_POINTER(r9, .Linc_counter, lr);
+       add lr, INPUT, #(12*4);
+       add r8, sp, #STACK_VEC_X12;
+
+.Loop4:
+       mov ROUND, #20;
+
+       /* Construct counter vectors X12 and X13 */
+
+       vld1.8 {X15}, [lr];
+       mov lr, INPUT;
+       vld1.8 {X8}, [r9];
+       vdup.32 X12, X15l[0];
+       vdup.32 X13, X15l[1];
+       vld1.8 {X3}, [lr]!;
+       vadd.u32 X12, X12, X8;
+       vdup.32 X0, X3l[0];
+       vdup.32 X1, X3l[1];
+       vdup.32 X2, X3h[0];
+       vcgt.u32 X8, X8, X12;
+       vdup.32 X3, X3h[1];
+       vdup.32 X14, X15h[0];
+       vdup.32 X15, X15h[1];
+       vsub.u32 X13, X13, X8;
+       vld1.8 {X7}, [lr]!;
+       vld1.8 {X11}, [lr];
+       vst1.8 {X12, X13}, [r8];
+       vdup.32 X4, X7l[0];
+       vdup.32 X5, X7l[1];
+       vdup.32 X6, X7h[0];
+       vdup.32 X7, X7h[1];
+       vdup.32 X8, X11l[0];
+       vdup.32 X9, X11l[1];
+       vdup.32 X10, X11h[0];
+       vdup.32 X11, X11h[1];
+
+       add r7, sp, #STACK_TMP2;
+       add r6, sp, #STACK_TMP1;
+       add r5, sp, #STACK_TMP;
+       vst1.8 {X15}, [r6];
+       vst1.8 {X11}, [r5];
+
+       mov lr, INPUT;
+.Lround2:
+       subs ROUND, ROUND, #2
+       QUARTERROUND2(X0, X4,  X8, X12,   X1, X5,  X9, X13, tmp:=,X11,X15)
+       vld1.8 {X11}, [r5];
+       vld1.8 {X15}, [r6];
+       vst1.8 {X8}, [r5];
+       vst1.8 {X9}, [r6];
+       QUARTERROUND2(X2, X6, X10, X14,   X3, X7, X11, X15, tmp:=,X8,X9)
+       QUARTERROUND2(X0, X5, X10, X15,   X1, X6, X11, X12, tmp:=,X8,X9)
+       vld1.8 {X8}, [r5];
+       vld1.8 {X9}, [r6];
+       vst1.8 {X11}, [r5];
+       vst1.8 {X15}, [r6];
+       QUARTERROUND2(X2, X7,  X8, X13,   X3, X4,  X9, X14, tmp:=,X11,X15)
+       bne .Lround2;
+
+       vld1.8 {X11}, [lr]!;
+       vst1.8 {X14}, [r7];
+
+       vdup.32 X14, X11l[0]; /* INPUT + 0 * 4 */
+       vdup.32 X15, X11l[1]; /* INPUT + 1 * 4 */
+       PLUS(X0, X14);
+       PLUS(X1, X15);
+       vdup.32 X14, X11h[0]; /* INPUT + 2 * 4 */
+       vdup.32 X15, X11h[1]; /* INPUT + 3 * 4 */
+       PLUS(X2, X14);
+       PLUS(X3, X15);
+
+       vld1.8 {X11}, [r5];
+       vld1.8 {X15}, [r6];
+       vst1.8 {X0}, [r5];
+       vld1.8 {X0}, [lr]!;
+       vst1.8 {X1}, [r6];
+
+       vdup.32 X14, X0l[0]; /* INPUT + 4 * 4 */
+       vdup.32  X1, X0l[1]; /* INPUT + 5 * 4 */
+       PLUS(X4, X14);
+       PLUS(X5, X1);
+       vdup.32 X14, X0h[0]; /* INPUT + 6 * 4 */
+       vdup.32  X1, X0h[1]; /* INPUT + 7 * 4 */
+       PLUS(X6, X14);
+       PLUS(X7, X1);
+
+       vld1.8 {X0}, [lr]!;
+
+       vdup.32 X14, X0l[0]; /* INPUT + 8 * 4 */
+       vdup.32  X1, X0l[1]; /* INPUT + 9 * 4 */
+       PLUS(X8, X14);
+       PLUS(X9, X1);
+       vdup.32 X14, X0h[0]; /* INPUT + 10 * 4 */
+       vdup.32  X1, X0h[1]; /* INPUT + 11 * 4 */
+       PLUS(X10, X14);
+       PLUS(X11, X1);
+
+       vld1.8 {X0}, [lr];
+       add lr, INPUT, #(12*4)
+       vld1.8 {X14}, [r7];
+
+       vdup.32 X1, X0h[0]; /* INPUT + 10 * 4 */
+       ldm lr, {r10, r11}; /* Update counter */
+       vdup.32 X0, X0h[1]; /* INPUT + 11 * 4 */
+       PLUS(X14, X1);
+       PLUS(X15, X0);
+       adds r10, r10, #4;  /* Update counter */
+       vld1.8 {X0, X1}, [r8];
+
+       PLUS(X12, X0);
+       vld1.8 {X0}, [r5];
+       PLUS(X13, X1);
+       adc r11, r11, #0;   /* Update counter */
+
+       vld1.8 {X1}, [r6];
+       stm lr, {r10, r11}; /* Update counter */
+       transpose_4x4_part1(X0, X1, X2, X3);
+       transpose_4x4_part1(X4, X5, X6, X7);
+       transpose_4x4_part1(X8, X9, X10, X11);
+       transpose_4x4_part1(X12, X13, X14, X15);
+       transpose_4x4_part2(X0, X1, X2, X3);
+       transpose_4x4_part2(X4, X5, X6, X7);
+       transpose_4x4_part2(X8, X9, X10, X11);
+       transpose_4x4_part2(X12, X13, X14, X15);
+
+       subs NBLKS, NBLKS, #4;
+
+       vst1.8 {X10}, [r5];
+       add lr, INPUT, #(12*4)
+       vst1.8 {X11}, [r6];
+       vld1.8 {X10, X11}, [SRC]!;
+       veor X10, X0, X10;
+       vld1.8 {X0}, [SRC]!;
+       veor X11, X4, X11;
+       vld1.8 {X4}, [SRC]!;
+       vst1.8 {X10, X11}, [DST]!;
+       vld1.8 {X10, X11}, [SRC]!;
+       veor X0, X8, X0;
+       veor X4, X12, X4;
+       veor X10, X1, X10;
+       veor X11, X5, X11;
+       vst1.8 {X0}, [DST]!;
+       vld1.8 {X0, X1}, [SRC]!;
+       vst1.8 {X4}, [DST]!;
+       vld1.8 {X4, X5}, [SRC]!;
+       vst1.8 {X10, X11}, [DST]!;
+       vld1.8 {X10}, [r5];
+       vld1.8 {X11}, [r6];
+       veor X0, X9, X0;
+       vld1.8 {X8, X9}, [SRC]!;
+       veor X1, X13, X1;
+       vld1.8 {X12, X13}, [SRC]!;
+       veor X4, X2, X4;
+       veor X5, X6, X5;
+       vst1.8 {X0, X1}, [DST]!;
+       vld1.8 {X0, X1}, [SRC]!;
+       vst1.8 {X4, X5}, [DST]!;
+       veor X8, X10, X8;
+       veor X9, X14, X9;
+       veor X12, X3, X12;
+       veor X13, X7, X13;
+       veor X0, X11, X0;
+       veor X1, X15, X1;
+       vst1.8 {X8, X9}, [DST]!;
+       vst1.8 {X12, X13}, [DST]!;
+       vst1.8 {X0, X1}, [DST]!;
+
+       bne .Loop4;
+
+       /* clear the used vector registers and stack */
+       clear(X0);
+       vst1.8 {X0}, [r5];
+       vst1.8 {X0}, [r6];
+       vst1.8 {X0}, [r7];
+       vst1.8 {X0}, [r8]!;
+       vst1.8 {X0}, [r8];
+
+       mov sp, r12
+       clear(X1);
+       clear(X2);
+       clear(X3);
+       clear(X4);
+       clear(X5);
+       clear(X6);
+       clear(X7);
+       clear(X8);
+       clear(X9);
+       clear(X10);
+       clear(X11);
+       clear(X12);
+       clear(X13);
+       clear(X14);
+       clear(X15);
+
+       pop {r4-r12,lr}
+       vpop {q4-q7}
+       eor r0, r0, r0
        bx lr
-.ltorg
-.size _gcry_chacha20_armv7_neon_blocks,.-_gcry_chacha20_armv7_neon_blocks;
+.size _gcry_chacha20_armv7_neon_blocks4, .-_gcry_chacha20_armv7_neon_blocks4;
 
 #endif
diff --git a/cipher/chacha20-avx2-amd64.S b/cipher/chacha20-avx2-amd64.S
deleted file mode 100644 (file)
index 8c085ba..0000000
+++ /dev/null
@@ -1,956 +0,0 @@
-/* chacha20-avx2-amd64.S  -  AMD64/AVX2 implementation of ChaCha20
- *
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Based on public domain implementation by Andrew Moon at
- *  https://github.com/floodyberry/chacha-opt
- */
-
-#ifdef __x86_64__
-#include <config.h>
-
-#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
-    defined(ENABLE_AVX2_SUPPORT) && USE_CHACHA20
-
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-.text
-
-.align 8
-.globl _gcry_chacha20_amd64_avx2_blocks
-ELF(.type  _gcry_chacha20_amd64_avx2_blocks,@function;)
-_gcry_chacha20_amd64_avx2_blocks:
-.Lchacha_blocks_avx2_local:
-       vzeroupper
-       pushq %rbx
-       pushq %rbp
-       pushq %r12
-       pushq %r13
-       pushq %r14
-       movq %rsp, %rbp
-       andq $~63, %rsp
-       subq $512, %rsp
-       leaq .LC RIP, %rax
-       vmovdqu 0(%rax), %xmm6
-       vmovdqu 16(%rax), %xmm7
-       vmovdqu 0(%rdi), %xmm8
-       vmovdqu 16(%rdi), %xmm9
-       vmovdqu 32(%rdi), %xmm10
-       vmovdqu 48(%rdi), %xmm11
-       movl $20, %eax
-       movq $1, %r9
-       vmovdqa %xmm8, 0(%rsp)
-       vmovdqa %xmm9, 16(%rsp)
-       vmovdqa %xmm10, 32(%rsp)
-       vmovdqa %xmm11, 48(%rsp)
-       movq %rax, 64(%rsp)
-       vmovdqa %xmm6, 448(%rsp)
-       vmovdqa %xmm6, 464(%rsp)
-       vmovdqa %xmm7, 480(%rsp)
-       vmovdqa %xmm7, 496(%rsp)
-       cmpq $512, %rcx
-       jae .Lchacha_blocks_avx2_atleast512
-       cmp $256, %rcx
-       jae .Lchacha_blocks_avx2_atleast256
-       jmp .Lchacha_blocks_avx2_below256
-       .p2align 6,,63
-.Lchacha_blocks_avx2_atleast512:
-       movq 48(%rsp), %rax
-       leaq 1(%rax), %r8
-       leaq 2(%rax), %r9
-       leaq 3(%rax), %r10
-       leaq 4(%rax), %rbx
-       leaq 5(%rax), %r11
-       leaq 6(%rax), %r12
-       leaq 7(%rax), %r13
-       leaq 8(%rax), %r14
-       movl %eax, 128(%rsp)
-       movl %r8d, 4+128(%rsp)
-       movl %r9d, 8+128(%rsp)
-       movl %r10d, 12+128(%rsp)
-       movl %ebx, 16+128(%rsp)
-       movl %r11d, 20+128(%rsp)
-       movl %r12d, 24+128(%rsp)
-       movl %r13d, 28+128(%rsp)
-       shrq $32, %rax
-       shrq $32, %r8
-       shrq $32, %r9
-       shrq $32, %r10
-       shrq $32, %rbx
-       shrq $32, %r11
-       shrq $32, %r12
-       shrq $32, %r13
-       movl %eax, 160(%rsp)
-       movl %r8d, 4+160(%rsp)
-       movl %r9d, 8+160(%rsp)
-       movl %r10d, 12+160(%rsp)
-       movl %ebx, 16+160(%rsp)
-       movl %r11d, 20+160(%rsp)
-       movl %r12d, 24+160(%rsp)
-       movl %r13d, 28+160(%rsp)
-       movq %r14, 48(%rsp)
-       movq 64(%rsp), %rax
-       vpbroadcastd 0(%rsp), %ymm0
-       vpbroadcastd 4+0(%rsp), %ymm1
-       vpbroadcastd 8+0(%rsp), %ymm2
-       vpbroadcastd 12+0(%rsp), %ymm3
-       vpbroadcastd 16(%rsp), %ymm4
-       vpbroadcastd 4+16(%rsp), %ymm5
-       vpbroadcastd 8+16(%rsp), %ymm6
-       vpbroadcastd 12+16(%rsp), %ymm7
-       vpbroadcastd 32(%rsp), %ymm8
-       vpbroadcastd 4+32(%rsp), %ymm9
-       vpbroadcastd 8+32(%rsp), %ymm10
-       vpbroadcastd 12+32(%rsp), %ymm11
-       vpbroadcastd 8+48(%rsp), %ymm14
-       vpbroadcastd 12+48(%rsp), %ymm15
-       vmovdqa 128(%rsp), %ymm12
-       vmovdqa 160(%rsp), %ymm13
-.Lchacha_blocks_avx2_mainloop1:
-       vpaddd %ymm0, %ymm4, %ymm0
-       vpaddd %ymm1, %ymm5, %ymm1
-       vpxor %ymm12, %ymm0, %ymm12
-       vpxor %ymm13, %ymm1, %ymm13
-       vpaddd %ymm2, %ymm6, %ymm2
-       vpaddd %ymm3, %ymm7, %ymm3
-       vpxor %ymm14, %ymm2, %ymm14
-       vpxor %ymm15, %ymm3, %ymm15
-       vpshufb 448(%rsp), %ymm12, %ymm12
-       vpshufb 448(%rsp), %ymm13, %ymm13
-       vpaddd %ymm8, %ymm12, %ymm8
-       vpaddd %ymm9, %ymm13, %ymm9
-       vpshufb 448(%rsp), %ymm14, %ymm14
-       vpshufb 448(%rsp), %ymm15, %ymm15
-       vpaddd %ymm10, %ymm14, %ymm10
-       vpaddd %ymm11, %ymm15, %ymm11
-       vmovdqa %ymm12, 96(%rsp)
-       vpxor %ymm4, %ymm8, %ymm4
-       vpxor %ymm5, %ymm9, %ymm5
-       vpslld $ 12, %ymm4, %ymm12
-       vpsrld $20, %ymm4, %ymm4
-       vpxor %ymm4, %ymm12, %ymm4
-       vpslld $ 12, %ymm5, %ymm12
-       vpsrld $20, %ymm5, %ymm5
-       vpxor %ymm5, %ymm12, %ymm5
-       vpxor %ymm6, %ymm10, %ymm6
-       vpxor %ymm7, %ymm11, %ymm7
-       vpslld $ 12, %ymm6, %ymm12
-       vpsrld $20, %ymm6, %ymm6
-       vpxor %ymm6, %ymm12, %ymm6
-       vpslld $ 12, %ymm7, %ymm12
-       vpsrld $20, %ymm7, %ymm7
-       vpxor %ymm7, %ymm12, %ymm7
-       vpaddd %ymm0, %ymm4, %ymm0
-       vpaddd %ymm1, %ymm5, %ymm1
-       vpxor 96(%rsp), %ymm0, %ymm12
-       vpxor %ymm13, %ymm1, %ymm13
-       vpaddd %ymm2, %ymm6, %ymm2
-       vpaddd %ymm3, %ymm7, %ymm3
-       vpxor %ymm14, %ymm2, %ymm14
-       vpxor %ymm15, %ymm3, %ymm15
-       vpshufb 480(%rsp), %ymm12, %ymm12
-       vpshufb 480(%rsp), %ymm13, %ymm13
-       vpaddd %ymm8, %ymm12, %ymm8
-       vpaddd %ymm9, %ymm13, %ymm9
-       vpshufb 480(%rsp), %ymm14, %ymm14
-       vpshufb 480(%rsp), %ymm15, %ymm15
-       vpaddd %ymm10, %ymm14, %ymm10
-       vpaddd %ymm11, %ymm15, %ymm11
-       vmovdqa %ymm12, 96(%rsp)
-       vpxor %ymm4, %ymm8, %ymm4
-       vpxor %ymm5, %ymm9, %ymm5
-       vpslld $ 7, %ymm4, %ymm12
-       vpsrld $25, %ymm4, %ymm4
-       vpxor %ymm4, %ymm12, %ymm4
-       vpslld $ 7, %ymm5, %ymm12
-       vpsrld $25, %ymm5, %ymm5
-       vpxor %ymm5, %ymm12, %ymm5
-       vpxor %ymm6, %ymm10, %ymm6
-       vpxor %ymm7, %ymm11, %ymm7
-       vpslld $ 7, %ymm6, %ymm12
-       vpsrld $25, %ymm6, %ymm6
-       vpxor %ymm6, %ymm12, %ymm6
-       vpslld $ 7, %ymm7, %ymm12
-       vpsrld $25, %ymm7, %ymm7
-       vpxor %ymm7, %ymm12, %ymm7
-       vpaddd %ymm0, %ymm5, %ymm0
-       vpaddd %ymm1, %ymm6, %ymm1
-       vpxor %ymm15, %ymm0, %ymm15
-       vpxor 96(%rsp), %ymm1, %ymm12
-       vpaddd %ymm2, %ymm7, %ymm2
-       vpaddd %ymm3, %ymm4, %ymm3
-       vpxor %ymm13, %ymm2, %ymm13
-       vpxor %ymm14, %ymm3, %ymm14
-       vpshufb 448(%rsp), %ymm15, %ymm15
-       vpshufb 448(%rsp), %ymm12, %ymm12
-       vpaddd %ymm10, %ymm15, %ymm10
-       vpaddd %ymm11, %ymm12, %ymm11
-       vpshufb 448(%rsp), %ymm13, %ymm13
-       vpshufb 448(%rsp), %ymm14, %ymm14
-       vpaddd %ymm8, %ymm13, %ymm8
-       vpaddd %ymm9, %ymm14, %ymm9
-       vmovdqa %ymm15, 96(%rsp)
-       vpxor %ymm5, %ymm10, %ymm5
-       vpxor %ymm6, %ymm11, %ymm6
-       vpslld $ 12, %ymm5, %ymm15
-       vpsrld $20, %ymm5, %ymm5
-       vpxor %ymm5, %ymm15, %ymm5
-       vpslld $ 12, %ymm6, %ymm15
-       vpsrld $20, %ymm6, %ymm6
-       vpxor %ymm6, %ymm15, %ymm6
-       vpxor %ymm7, %ymm8, %ymm7
-       vpxor %ymm4, %ymm9, %ymm4
-       vpslld $ 12, %ymm7, %ymm15
-       vpsrld $20, %ymm7, %ymm7
-       vpxor %ymm7, %ymm15, %ymm7
-       vpslld $ 12, %ymm4, %ymm15
-       vpsrld $20, %ymm4, %ymm4
-       vpxor %ymm4, %ymm15, %ymm4
-       vpaddd %ymm0, %ymm5, %ymm0
-       vpaddd %ymm1, %ymm6, %ymm1
-       vpxor 96(%rsp), %ymm0, %ymm15
-       vpxor %ymm12, %ymm1, %ymm12
-       vpaddd %ymm2, %ymm7, %ymm2
-       vpaddd %ymm3, %ymm4, %ymm3
-       vpxor %ymm13, %ymm2, %ymm13
-       vpxor %ymm14, %ymm3, %ymm14
-       vpshufb 480(%rsp), %ymm15, %ymm15
-       vpshufb 480(%rsp), %ymm12, %ymm12
-       vpaddd %ymm10, %ymm15, %ymm10
-       vpaddd %ymm11, %ymm12, %ymm11
-       vpshufb 480(%rsp), %ymm13, %ymm13
-       vpshufb 480(%rsp), %ymm14, %ymm14
-       vpaddd %ymm8, %ymm13, %ymm8
-       vpaddd %ymm9, %ymm14, %ymm9
-       vmovdqa %ymm15, 96(%rsp)
-       vpxor %ymm5, %ymm10, %ymm5
-       vpxor %ymm6, %ymm11, %ymm6
-       vpslld $ 7, %ymm5, %ymm15
-       vpsrld $25, %ymm5, %ymm5
-       vpxor %ymm5, %ymm15, %ymm5
-       vpslld $ 7, %ymm6, %ymm15
-       vpsrld $25, %ymm6, %ymm6
-       vpxor %ymm6, %ymm15, %ymm6
-       vpxor %ymm7, %ymm8, %ymm7
-       vpxor %ymm4, %ymm9, %ymm4
-       vpslld $ 7, %ymm7, %ymm15
-       vpsrld $25, %ymm7, %ymm7
-       vpxor %ymm7, %ymm15, %ymm7
-       vpslld $ 7, %ymm4, %ymm15
-       vpsrld $25, %ymm4, %ymm4
-       vpxor %ymm4, %ymm15, %ymm4
-       vmovdqa 96(%rsp), %ymm15
-       subq $2, %rax
-       jnz .Lchacha_blocks_avx2_mainloop1
-       vmovdqa %ymm8, 192(%rsp)
-       vmovdqa %ymm9, 224(%rsp)
-       vmovdqa %ymm10, 256(%rsp)
-       vmovdqa %ymm11, 288(%rsp)
-       vmovdqa %ymm12, 320(%rsp)
-       vmovdqa %ymm13, 352(%rsp)
-       vmovdqa %ymm14, 384(%rsp)
-       vmovdqa %ymm15, 416(%rsp)
-       vpbroadcastd 0(%rsp), %ymm8
-       vpbroadcastd 4+0(%rsp), %ymm9
-       vpbroadcastd 8+0(%rsp), %ymm10
-       vpbroadcastd 12+0(%rsp), %ymm11
-       vpbroadcastd 16(%rsp), %ymm12
-       vpbroadcastd 4+16(%rsp), %ymm13
-       vpbroadcastd 8+16(%rsp), %ymm14
-       vpbroadcastd 12+16(%rsp), %ymm15
-       vpaddd %ymm8, %ymm0, %ymm0
-       vpaddd %ymm9, %ymm1, %ymm1
-       vpaddd %ymm10, %ymm2, %ymm2
-       vpaddd %ymm11, %ymm3, %ymm3
-       vpaddd %ymm12, %ymm4, %ymm4
-       vpaddd %ymm13, %ymm5, %ymm5
-       vpaddd %ymm14, %ymm6, %ymm6
-       vpaddd %ymm15, %ymm7, %ymm7
-       vpunpckldq %ymm1, %ymm0, %ymm8
-       vpunpckldq %ymm3, %ymm2, %ymm9
-       vpunpckhdq %ymm1, %ymm0, %ymm12
-       vpunpckhdq %ymm3, %ymm2, %ymm13
-       vpunpckldq %ymm5, %ymm4, %ymm10
-       vpunpckldq %ymm7, %ymm6, %ymm11
-       vpunpckhdq %ymm5, %ymm4, %ymm14
-       vpunpckhdq %ymm7, %ymm6, %ymm15
-       vpunpcklqdq %ymm9, %ymm8, %ymm0
-       vpunpcklqdq %ymm11, %ymm10, %ymm1
-       vpunpckhqdq %ymm9, %ymm8, %ymm2
-       vpunpckhqdq %ymm11, %ymm10, %ymm3
-       vpunpcklqdq %ymm13, %ymm12, %ymm4
-       vpunpcklqdq %ymm15, %ymm14, %ymm5
-       vpunpckhqdq %ymm13, %ymm12, %ymm6
-       vpunpckhqdq %ymm15, %ymm14, %ymm7
-       vperm2i128 $0x20, %ymm1, %ymm0, %ymm8
-       vperm2i128 $0x20, %ymm3, %ymm2, %ymm9
-       vperm2i128 $0x31, %ymm1, %ymm0, %ymm12
-       vperm2i128 $0x31, %ymm3, %ymm2, %ymm13
-       vperm2i128 $0x20, %ymm5, %ymm4, %ymm10
-       vperm2i128 $0x20, %ymm7, %ymm6, %ymm11
-       vperm2i128 $0x31, %ymm5, %ymm4, %ymm14
-       vperm2i128 $0x31, %ymm7, %ymm6, %ymm15
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_avx2_noinput1
-       vpxor 0(%rsi), %ymm8, %ymm8
-       vpxor 64(%rsi), %ymm9, %ymm9
-       vpxor 128(%rsi), %ymm10, %ymm10
-       vpxor 192(%rsi), %ymm11, %ymm11
-       vpxor 256(%rsi), %ymm12, %ymm12
-       vpxor 320(%rsi), %ymm13, %ymm13
-       vpxor 384(%rsi), %ymm14, %ymm14
-       vpxor 448(%rsi), %ymm15, %ymm15
-       vmovdqu %ymm8, 0(%rdx)
-       vmovdqu %ymm9, 64(%rdx)
-       vmovdqu %ymm10, 128(%rdx)
-       vmovdqu %ymm11, 192(%rdx)
-       vmovdqu %ymm12, 256(%rdx)
-       vmovdqu %ymm13, 320(%rdx)
-       vmovdqu %ymm14, 384(%rdx)
-       vmovdqu %ymm15, 448(%rdx)
-       vmovdqa 192(%rsp), %ymm0
-       vmovdqa 224(%rsp), %ymm1
-       vmovdqa 256(%rsp), %ymm2
-       vmovdqa 288(%rsp), %ymm3
-       vmovdqa 320(%rsp), %ymm4
-       vmovdqa 352(%rsp), %ymm5
-       vmovdqa 384(%rsp), %ymm6
-       vmovdqa 416(%rsp), %ymm7
-       vpbroadcastd 32(%rsp), %ymm8
-       vpbroadcastd 4+32(%rsp), %ymm9
-       vpbroadcastd 8+32(%rsp), %ymm10
-       vpbroadcastd 12+32(%rsp), %ymm11
-       vmovdqa 128(%rsp), %ymm12
-       vmovdqa 160(%rsp), %ymm13
-       vpbroadcastd 8+48(%rsp), %ymm14
-       vpbroadcastd 12+48(%rsp), %ymm15
-       vpaddd %ymm8, %ymm0, %ymm0
-       vpaddd %ymm9, %ymm1, %ymm1
-       vpaddd %ymm10, %ymm2, %ymm2
-       vpaddd %ymm11, %ymm3, %ymm3
-       vpaddd %ymm12, %ymm4, %ymm4
-       vpaddd %ymm13, %ymm5, %ymm5
-       vpaddd %ymm14, %ymm6, %ymm6
-       vpaddd %ymm15, %ymm7, %ymm7
-       vpunpckldq %ymm1, %ymm0, %ymm8
-       vpunpckldq %ymm3, %ymm2, %ymm9
-       vpunpckhdq %ymm1, %ymm0, %ymm12
-       vpunpckhdq %ymm3, %ymm2, %ymm13
-       vpunpckldq %ymm5, %ymm4, %ymm10
-       vpunpckldq %ymm7, %ymm6, %ymm11
-       vpunpckhdq %ymm5, %ymm4, %ymm14
-       vpunpckhdq %ymm7, %ymm6, %ymm15
-       vpunpcklqdq %ymm9, %ymm8, %ymm0
-       vpunpcklqdq %ymm11, %ymm10, %ymm1
-       vpunpckhqdq %ymm9, %ymm8, %ymm2
-       vpunpckhqdq %ymm11, %ymm10, %ymm3
-       vpunpcklqdq %ymm13, %ymm12, %ymm4
-       vpunpcklqdq %ymm15, %ymm14, %ymm5
-       vpunpckhqdq %ymm13, %ymm12, %ymm6
-       vpunpckhqdq %ymm15, %ymm14, %ymm7
-       vperm2i128 $0x20, %ymm1, %ymm0, %ymm8
-       vperm2i128 $0x20, %ymm3, %ymm2, %ymm9
-       vperm2i128 $0x31, %ymm1, %ymm0, %ymm12
-       vperm2i128 $0x31, %ymm3, %ymm2, %ymm13
-       vperm2i128 $0x20, %ymm5, %ymm4, %ymm10
-       vperm2i128 $0x20, %ymm7, %ymm6, %ymm11
-       vperm2i128 $0x31, %ymm5, %ymm4, %ymm14
-       vperm2i128 $0x31, %ymm7, %ymm6, %ymm15
-       vpxor 32(%rsi), %ymm8, %ymm8
-       vpxor 96(%rsi), %ymm9, %ymm9
-       vpxor 160(%rsi), %ymm10, %ymm10
-       vpxor 224(%rsi), %ymm11, %ymm11
-       vpxor 288(%rsi), %ymm12, %ymm12
-       vpxor 352(%rsi), %ymm13, %ymm13
-       vpxor 416(%rsi), %ymm14, %ymm14
-       vpxor 480(%rsi), %ymm15, %ymm15
-       vmovdqu %ymm8, 32(%rdx)
-       vmovdqu %ymm9, 96(%rdx)
-       vmovdqu %ymm10, 160(%rdx)
-       vmovdqu %ymm11, 224(%rdx)
-       vmovdqu %ymm12, 288(%rdx)
-       vmovdqu %ymm13, 352(%rdx)
-       vmovdqu %ymm14, 416(%rdx)
-       vmovdqu %ymm15, 480(%rdx)
-       addq $512, %rsi
-       jmp .Lchacha_blocks_avx2_mainloop1_cont
-.Lchacha_blocks_avx2_noinput1:
-       vmovdqu %ymm8, 0(%rdx)
-       vmovdqu %ymm9, 64(%rdx)
-       vmovdqu %ymm10, 128(%rdx)
-       vmovdqu %ymm11, 192(%rdx)
-       vmovdqu %ymm12, 256(%rdx)
-       vmovdqu %ymm13, 320(%rdx)
-       vmovdqu %ymm14, 384(%rdx)
-       vmovdqu %ymm15, 448(%rdx)
-       vmovdqa 192(%rsp), %ymm0
-       vmovdqa 224(%rsp), %ymm1
-       vmovdqa 256(%rsp), %ymm2
-       vmovdqa 288(%rsp), %ymm3
-       vmovdqa 320(%rsp), %ymm4
-       vmovdqa 352(%rsp), %ymm5
-       vmovdqa 384(%rsp), %ymm6
-       vmovdqa 416(%rsp), %ymm7
-       vpbroadcastd 32(%rsp), %ymm8
-       vpbroadcastd 4+32(%rsp), %ymm9
-       vpbroadcastd 8+32(%rsp), %ymm10
-       vpbroadcastd 12+32(%rsp), %ymm11
-       vmovdqa 128(%rsp), %ymm12
-       vmovdqa 160(%rsp), %ymm13
-       vpbroadcastd 8+48(%rsp), %ymm14
-       vpbroadcastd 12+48(%rsp), %ymm15
-       vpaddd %ymm8, %ymm0, %ymm0
-       vpaddd %ymm9, %ymm1, %ymm1
-       vpaddd %ymm10, %ymm2, %ymm2
-       vpaddd %ymm11, %ymm3, %ymm3
-       vpaddd %ymm12, %ymm4, %ymm4
-       vpaddd %ymm13, %ymm5, %ymm5
-       vpaddd %ymm14, %ymm6, %ymm6
-       vpaddd %ymm15, %ymm7, %ymm7
-       vpunpckldq %ymm1, %ymm0, %ymm8
-       vpunpckldq %ymm3, %ymm2, %ymm9
-       vpunpckhdq %ymm1, %ymm0, %ymm12
-       vpunpckhdq %ymm3, %ymm2, %ymm13
-       vpunpckldq %ymm5, %ymm4, %ymm10
-       vpunpckldq %ymm7, %ymm6, %ymm11
-       vpunpckhdq %ymm5, %ymm4, %ymm14
-       vpunpckhdq %ymm7, %ymm6, %ymm15
-       vpunpcklqdq %ymm9, %ymm8, %ymm0
-       vpunpcklqdq %ymm11, %ymm10, %ymm1
-       vpunpckhqdq %ymm9, %ymm8, %ymm2
-       vpunpckhqdq %ymm11, %ymm10, %ymm3
-       vpunpcklqdq %ymm13, %ymm12, %ymm4
-       vpunpcklqdq %ymm15, %ymm14, %ymm5
-       vpunpckhqdq %ymm13, %ymm12, %ymm6
-       vpunpckhqdq %ymm15, %ymm14, %ymm7
-       vperm2i128 $0x20, %ymm1, %ymm0, %ymm8
-       vperm2i128 $0x20, %ymm3, %ymm2, %ymm9
-       vperm2i128 $0x31, %ymm1, %ymm0, %ymm12
-       vperm2i128 $0x31, %ymm3, %ymm2, %ymm13
-       vperm2i128 $0x20, %ymm5, %ymm4, %ymm10
-       vperm2i128 $0x20, %ymm7, %ymm6, %ymm11
-       vperm2i128 $0x31, %ymm5, %ymm4, %ymm14
-       vperm2i128 $0x31, %ymm7, %ymm6, %ymm15
-       vmovdqu %ymm8, 32(%rdx)
-       vmovdqu %ymm9, 96(%rdx)
-       vmovdqu %ymm10, 160(%rdx)
-       vmovdqu %ymm11, 224(%rdx)
-       vmovdqu %ymm12, 288(%rdx)
-       vmovdqu %ymm13, 352(%rdx)
-       vmovdqu %ymm14, 416(%rdx)
-       vmovdqu %ymm15, 480(%rdx)
-.Lchacha_blocks_avx2_mainloop1_cont:
-       addq $512, %rdx
-       subq $512, %rcx
-       cmp $512, %rcx
-       jae .Lchacha_blocks_avx2_atleast512
-       cmp $256, %rcx
-       jb .Lchacha_blocks_avx2_below256_fixup
-.Lchacha_blocks_avx2_atleast256:
-       movq 48(%rsp), %rax
-       leaq 1(%rax), %r8
-       leaq 2(%rax), %r9
-       leaq 3(%rax), %r10
-       leaq 4(%rax), %rbx
-       movl %eax, 128(%rsp)
-       movl %r8d, 4+128(%rsp)
-       movl %r9d, 8+128(%rsp)
-       movl %r10d, 12+128(%rsp)
-       shrq $32, %rax
-       shrq $32, %r8
-       shrq $32, %r9
-       shrq $32, %r10
-       movl %eax, 160(%rsp)
-       movl %r8d, 4+160(%rsp)
-       movl %r9d, 8+160(%rsp)
-       movl %r10d, 12+160(%rsp)
-       movq %rbx, 48(%rsp)
-       movq 64(%rsp), %rax
-       vpbroadcastd 0(%rsp), %xmm0
-       vpbroadcastd 4+0(%rsp), %xmm1
-       vpbroadcastd 8+0(%rsp), %xmm2
-       vpbroadcastd 12+0(%rsp), %xmm3
-       vpbroadcastd 16(%rsp), %xmm4
-       vpbroadcastd 4+16(%rsp), %xmm5
-       vpbroadcastd 8+16(%rsp), %xmm6
-       vpbroadcastd 12+16(%rsp), %xmm7
-       vpbroadcastd 32(%rsp), %xmm8
-       vpbroadcastd 4+32(%rsp), %xmm9
-       vpbroadcastd 8+32(%rsp), %xmm10
-       vpbroadcastd 12+32(%rsp), %xmm11
-       vmovdqa 128(%rsp), %xmm12
-       vmovdqa 160(%rsp), %xmm13
-       vpbroadcastd 8+48(%rsp), %xmm14
-       vpbroadcastd 12+48(%rsp), %xmm15
-.Lchacha_blocks_avx2_mainloop2:
-       vpaddd %xmm0, %xmm4, %xmm0
-       vpaddd %xmm1, %xmm5, %xmm1
-       vpxor %xmm12, %xmm0, %xmm12
-       vpxor %xmm13, %xmm1, %xmm13
-       vpaddd %xmm2, %xmm6, %xmm2
-       vpaddd %xmm3, %xmm7, %xmm3
-       vpxor %xmm14, %xmm2, %xmm14
-       vpxor %xmm15, %xmm3, %xmm15
-       vpshufb 448(%rsp), %xmm12, %xmm12
-       vpshufb 448(%rsp), %xmm13, %xmm13
-       vpaddd %xmm8, %xmm12, %xmm8
-       vpaddd %xmm9, %xmm13, %xmm9
-       vpshufb 448(%rsp), %xmm14, %xmm14
-       vpshufb 448(%rsp), %xmm15, %xmm15
-       vpaddd %xmm10, %xmm14, %xmm10
-       vpaddd %xmm11, %xmm15, %xmm11
-       vmovdqa %xmm12, 96(%rsp)
-       vpxor %xmm4, %xmm8, %xmm4
-       vpxor %xmm5, %xmm9, %xmm5
-       vpslld $ 12, %xmm4, %xmm12
-       vpsrld $20, %xmm4, %xmm4
-       vpxor %xmm4, %xmm12, %xmm4
-       vpslld $ 12, %xmm5, %xmm12
-       vpsrld $20, %xmm5, %xmm5
-       vpxor %xmm5, %xmm12, %xmm5
-       vpxor %xmm6, %xmm10, %xmm6
-       vpxor %xmm7, %xmm11, %xmm7
-       vpslld $ 12, %xmm6, %xmm12
-       vpsrld $20, %xmm6, %xmm6
-       vpxor %xmm6, %xmm12, %xmm6
-       vpslld $ 12, %xmm7, %xmm12
-       vpsrld $20, %xmm7, %xmm7
-       vpxor %xmm7, %xmm12, %xmm7
-       vpaddd %xmm0, %xmm4, %xmm0
-       vpaddd %xmm1, %xmm5, %xmm1
-       vpxor 96(%rsp), %xmm0, %xmm12
-       vpxor %xmm13, %xmm1, %xmm13
-       vpaddd %xmm2, %xmm6, %xmm2
-       vpaddd %xmm3, %xmm7, %xmm3
-       vpxor %xmm14, %xmm2, %xmm14
-       vpxor %xmm15, %xmm3, %xmm15
-       vpshufb 480(%rsp), %xmm12, %xmm12
-       vpshufb 480(%rsp), %xmm13, %xmm13
-       vpaddd %xmm8, %xmm12, %xmm8
-       vpaddd %xmm9, %xmm13, %xmm9
-       vpshufb 480(%rsp), %xmm14, %xmm14
-       vpshufb 480(%rsp), %xmm15, %xmm15
-       vpaddd %xmm10, %xmm14, %xmm10
-       vpaddd %xmm11, %xmm15, %xmm11
-       vmovdqa %xmm12, 96(%rsp)
-       vpxor %xmm4, %xmm8, %xmm4
-       vpxor %xmm5, %xmm9, %xmm5
-       vpslld $ 7, %xmm4, %xmm12
-       vpsrld $25, %xmm4, %xmm4
-       vpxor %xmm4, %xmm12, %xmm4
-       vpslld $ 7, %xmm5, %xmm12
-       vpsrld $25, %xmm5, %xmm5
-       vpxor %xmm5, %xmm12, %xmm5
-       vpxor %xmm6, %xmm10, %xmm6
-       vpxor %xmm7, %xmm11, %xmm7
-       vpslld $ 7, %xmm6, %xmm12
-       vpsrld $25, %xmm6, %xmm6
-       vpxor %xmm6, %xmm12, %xmm6
-       vpslld $ 7, %xmm7, %xmm12
-       vpsrld $25, %xmm7, %xmm7
-       vpxor %xmm7, %xmm12, %xmm7
-       vpaddd %xmm0, %xmm5, %xmm0
-       vpaddd %xmm1, %xmm6, %xmm1
-       vpxor %xmm15, %xmm0, %xmm15
-       vpxor 96(%rsp), %xmm1, %xmm12
-       vpaddd %xmm2, %xmm7, %xmm2
-       vpaddd %xmm3, %xmm4, %xmm3
-       vpxor %xmm13, %xmm2, %xmm13
-       vpxor %xmm14, %xmm3, %xmm14
-       vpshufb 448(%rsp), %xmm15, %xmm15
-       vpshufb 448(%rsp), %xmm12, %xmm12
-       vpaddd %xmm10, %xmm15, %xmm10
-       vpaddd %xmm11, %xmm12, %xmm11
-       vpshufb 448(%rsp), %xmm13, %xmm13
-       vpshufb 448(%rsp), %xmm14, %xmm14
-       vpaddd %xmm8, %xmm13, %xmm8
-       vpaddd %xmm9, %xmm14, %xmm9
-       vmovdqa %xmm15, 96(%rsp)
-       vpxor %xmm5, %xmm10, %xmm5
-       vpxor %xmm6, %xmm11, %xmm6
-       vpslld $ 12, %xmm5, %xmm15
-       vpsrld $20, %xmm5, %xmm5
-       vpxor %xmm5, %xmm15, %xmm5
-       vpslld $ 12, %xmm6, %xmm15
-       vpsrld $20, %xmm6, %xmm6
-       vpxor %xmm6, %xmm15, %xmm6
-       vpxor %xmm7, %xmm8, %xmm7
-       vpxor %xmm4, %xmm9, %xmm4
-       vpslld $ 12, %xmm7, %xmm15
-       vpsrld $20, %xmm7, %xmm7
-       vpxor %xmm7, %xmm15, %xmm7
-       vpslld $ 12, %xmm4, %xmm15
-       vpsrld $20, %xmm4, %xmm4
-       vpxor %xmm4, %xmm15, %xmm4
-       vpaddd %xmm0, %xmm5, %xmm0
-       vpaddd %xmm1, %xmm6, %xmm1
-       vpxor 96(%rsp), %xmm0, %xmm15
-       vpxor %xmm12, %xmm1, %xmm12
-       vpaddd %xmm2, %xmm7, %xmm2
-       vpaddd %xmm3, %xmm4, %xmm3
-       vpxor %xmm13, %xmm2, %xmm13
-       vpxor %xmm14, %xmm3, %xmm14
-       vpshufb 480(%rsp), %xmm15, %xmm15
-       vpshufb 480(%rsp), %xmm12, %xmm12
-       vpaddd %xmm10, %xmm15, %xmm10
-       vpaddd %xmm11, %xmm12, %xmm11
-       vpshufb 480(%rsp), %xmm13, %xmm13
-       vpshufb 480(%rsp), %xmm14, %xmm14
-       vpaddd %xmm8, %xmm13, %xmm8
-       vpaddd %xmm9, %xmm14, %xmm9
-       vmovdqa %xmm15, 96(%rsp)
-       vpxor %xmm5, %xmm10, %xmm5
-       vpxor %xmm6, %xmm11, %xmm6
-       vpslld $ 7, %xmm5, %xmm15
-       vpsrld $25, %xmm5, %xmm5
-       vpxor %xmm5, %xmm15, %xmm5
-       vpslld $ 7, %xmm6, %xmm15
-       vpsrld $25, %xmm6, %xmm6
-       vpxor %xmm6, %xmm15, %xmm6
-       vpxor %xmm7, %xmm8, %xmm7
-       vpxor %xmm4, %xmm9, %xmm4
-       vpslld $ 7, %xmm7, %xmm15
-       vpsrld $25, %xmm7, %xmm7
-       vpxor %xmm7, %xmm15, %xmm7
-       vpslld $ 7, %xmm4, %xmm15
-       vpsrld $25, %xmm4, %xmm4
-       vpxor %xmm4, %xmm15, %xmm4
-       vmovdqa 96(%rsp), %xmm15
-       subq $2, %rax
-       jnz .Lchacha_blocks_avx2_mainloop2
-       vmovdqa %xmm8, 192(%rsp)
-       vmovdqa %xmm9, 208(%rsp)
-       vmovdqa %xmm10, 224(%rsp)
-       vmovdqa %xmm11, 240(%rsp)
-       vmovdqa %xmm12, 256(%rsp)
-       vmovdqa %xmm13, 272(%rsp)
-       vmovdqa %xmm14, 288(%rsp)
-       vmovdqa %xmm15, 304(%rsp)
-       vpbroadcastd 0(%rsp), %xmm8
-       vpbroadcastd 4+0(%rsp), %xmm9
-       vpbroadcastd 8+0(%rsp), %xmm10
-       vpbroadcastd 12+0(%rsp), %xmm11
-       vpbroadcastd 16(%rsp), %xmm12
-       vpbroadcastd 4+16(%rsp), %xmm13
-       vpbroadcastd 8+16(%rsp), %xmm14
-       vpbroadcastd 12+16(%rsp), %xmm15
-       vpaddd %xmm8, %xmm0, %xmm0
-       vpaddd %xmm9, %xmm1, %xmm1
-       vpaddd %xmm10, %xmm2, %xmm2
-       vpaddd %xmm11, %xmm3, %xmm3
-       vpaddd %xmm12, %xmm4, %xmm4
-       vpaddd %xmm13, %xmm5, %xmm5
-       vpaddd %xmm14, %xmm6, %xmm6
-       vpaddd %xmm15, %xmm7, %xmm7
-       vpunpckldq %xmm1, %xmm0, %xmm8
-       vpunpckldq %xmm3, %xmm2, %xmm9
-       vpunpckhdq %xmm1, %xmm0, %xmm12
-       vpunpckhdq %xmm3, %xmm2, %xmm13
-       vpunpckldq %xmm5, %xmm4, %xmm10
-       vpunpckldq %xmm7, %xmm6, %xmm11
-       vpunpckhdq %xmm5, %xmm4, %xmm14
-       vpunpckhdq %xmm7, %xmm6, %xmm15
-       vpunpcklqdq %xmm9, %xmm8, %xmm0
-       vpunpcklqdq %xmm11, %xmm10, %xmm1
-       vpunpckhqdq %xmm9, %xmm8, %xmm2
-       vpunpckhqdq %xmm11, %xmm10, %xmm3
-       vpunpcklqdq %xmm13, %xmm12, %xmm4
-       vpunpcklqdq %xmm15, %xmm14, %xmm5
-       vpunpckhqdq %xmm13, %xmm12, %xmm6
-       vpunpckhqdq %xmm15, %xmm14, %xmm7
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_avx2_noinput2
-       vpxor 0(%rsi), %xmm0, %xmm0
-       vpxor 16(%rsi), %xmm1, %xmm1
-       vpxor 64(%rsi), %xmm2, %xmm2
-       vpxor 80(%rsi), %xmm3, %xmm3
-       vpxor 128(%rsi), %xmm4, %xmm4
-       vpxor 144(%rsi), %xmm5, %xmm5
-       vpxor 192(%rsi), %xmm6, %xmm6
-       vpxor 208(%rsi), %xmm7, %xmm7
-       vmovdqu %xmm0, 0(%rdx)
-       vmovdqu %xmm1, 16(%rdx)
-       vmovdqu %xmm2, 64(%rdx)
-       vmovdqu %xmm3, 80(%rdx)
-       vmovdqu %xmm4, 128(%rdx)
-       vmovdqu %xmm5, 144(%rdx)
-       vmovdqu %xmm6, 192(%rdx)
-       vmovdqu %xmm7, 208(%rdx)
-       vmovdqa 192(%rsp), %xmm0
-       vmovdqa 208(%rsp), %xmm1
-       vmovdqa 224(%rsp), %xmm2
-       vmovdqa 240(%rsp), %xmm3
-       vmovdqa 256(%rsp), %xmm4
-       vmovdqa 272(%rsp), %xmm5
-       vmovdqa 288(%rsp), %xmm6
-       vmovdqa 304(%rsp), %xmm7
-       vpbroadcastd 32(%rsp), %xmm8
-       vpbroadcastd 4+32(%rsp), %xmm9
-       vpbroadcastd 8+32(%rsp), %xmm10
-       vpbroadcastd 12+32(%rsp), %xmm11
-       vmovdqa 128(%rsp), %xmm12
-       vmovdqa 160(%rsp), %xmm13
-       vpbroadcastd 8+48(%rsp), %xmm14
-       vpbroadcastd 12+48(%rsp), %xmm15
-       vpaddd %xmm8, %xmm0, %xmm0
-       vpaddd %xmm9, %xmm1, %xmm1
-       vpaddd %xmm10, %xmm2, %xmm2
-       vpaddd %xmm11, %xmm3, %xmm3
-       vpaddd %xmm12, %xmm4, %xmm4
-       vpaddd %xmm13, %xmm5, %xmm5
-       vpaddd %xmm14, %xmm6, %xmm6
-       vpaddd %xmm15, %xmm7, %xmm7
-       vpunpckldq %xmm1, %xmm0, %xmm8
-       vpunpckldq %xmm3, %xmm2, %xmm9
-       vpunpckhdq %xmm1, %xmm0, %xmm12
-       vpunpckhdq %xmm3, %xmm2, %xmm13
-       vpunpckldq %xmm5, %xmm4, %xmm10
-       vpunpckldq %xmm7, %xmm6, %xmm11
-       vpunpckhdq %xmm5, %xmm4, %xmm14
-       vpunpckhdq %xmm7, %xmm6, %xmm15
-       vpunpcklqdq %xmm9, %xmm8, %xmm0
-       vpunpcklqdq %xmm11, %xmm10, %xmm1
-       vpunpckhqdq %xmm9, %xmm8, %xmm2
-       vpunpckhqdq %xmm11, %xmm10, %xmm3
-       vpunpcklqdq %xmm13, %xmm12, %xmm4
-       vpunpcklqdq %xmm15, %xmm14, %xmm5
-       vpunpckhqdq %xmm13, %xmm12, %xmm6
-       vpunpckhqdq %xmm15, %xmm14, %xmm7
-       vpxor 32(%rsi), %xmm0, %xmm0
-       vpxor 48(%rsi), %xmm1, %xmm1
-       vpxor 96(%rsi), %xmm2, %xmm2
-       vpxor 112(%rsi), %xmm3, %xmm3
-       vpxor 160(%rsi), %xmm4, %xmm4
-       vpxor 176(%rsi), %xmm5, %xmm5
-       vpxor 224(%rsi), %xmm6, %xmm6
-       vpxor 240(%rsi), %xmm7, %xmm7
-       vmovdqu %xmm0, 32(%rdx)
-       vmovdqu %xmm1, 48(%rdx)
-       vmovdqu %xmm2, 96(%rdx)
-       vmovdqu %xmm3, 112(%rdx)
-       vmovdqu %xmm4, 160(%rdx)
-       vmovdqu %xmm5, 176(%rdx)
-       vmovdqu %xmm6, 224(%rdx)
-       vmovdqu %xmm7, 240(%rdx)
-       addq $256, %rsi
-       jmp .Lchacha_blocks_avx2_mainloop2_cont
-.Lchacha_blocks_avx2_noinput2:
-       vmovdqu %xmm0, 0(%rdx)
-       vmovdqu %xmm1, 16(%rdx)
-       vmovdqu %xmm2, 64(%rdx)
-       vmovdqu %xmm3, 80(%rdx)
-       vmovdqu %xmm4, 128(%rdx)
-       vmovdqu %xmm5, 144(%rdx)
-       vmovdqu %xmm6, 192(%rdx)
-       vmovdqu %xmm7, 208(%rdx)
-       vmovdqa 192(%rsp), %xmm0
-       vmovdqa 208(%rsp), %xmm1
-       vmovdqa 224(%rsp), %xmm2
-       vmovdqa 240(%rsp), %xmm3
-       vmovdqa 256(%rsp), %xmm4
-       vmovdqa 272(%rsp), %xmm5
-       vmovdqa 288(%rsp), %xmm6
-       vmovdqa 304(%rsp), %xmm7
-       vpbroadcastd 32(%rsp), %xmm8
-       vpbroadcastd 4+32(%rsp), %xmm9
-       vpbroadcastd 8+32(%rsp), %xmm10
-       vpbroadcastd 12+32(%rsp), %xmm11
-       vmovdqa 128(%rsp), %xmm12
-       vmovdqa 160(%rsp), %xmm13
-       vpbroadcastd 8+48(%rsp), %xmm14
-       vpbroadcastd 12+48(%rsp), %xmm15
-       vpaddd %xmm8, %xmm0, %xmm0
-       vpaddd %xmm9, %xmm1, %xmm1
-       vpaddd %xmm10, %xmm2, %xmm2
-       vpaddd %xmm11, %xmm3, %xmm3
-       vpaddd %xmm12, %xmm4, %xmm4
-       vpaddd %xmm13, %xmm5, %xmm5
-       vpaddd %xmm14, %xmm6, %xmm6
-       vpaddd %xmm15, %xmm7, %xmm7
-       vpunpckldq %xmm1, %xmm0, %xmm8
-       vpunpckldq %xmm3, %xmm2, %xmm9
-       vpunpckhdq %xmm1, %xmm0, %xmm12
-       vpunpckhdq %xmm3, %xmm2, %xmm13
-       vpunpckldq %xmm5, %xmm4, %xmm10
-       vpunpckldq %xmm7, %xmm6, %xmm11
-       vpunpckhdq %xmm5, %xmm4, %xmm14
-       vpunpckhdq %xmm7, %xmm6, %xmm15
-       vpunpcklqdq %xmm9, %xmm8, %xmm0
-       vpunpcklqdq %xmm11, %xmm10, %xmm1
-       vpunpckhqdq %xmm9, %xmm8, %xmm2
-       vpunpckhqdq %xmm11, %xmm10, %xmm3
-       vpunpcklqdq %xmm13, %xmm12, %xmm4
-       vpunpcklqdq %xmm15, %xmm14, %xmm5
-       vpunpckhqdq %xmm13, %xmm12, %xmm6
-       vpunpckhqdq %xmm15, %xmm14, %xmm7
-       vmovdqu %xmm0, 32(%rdx)
-       vmovdqu %xmm1, 48(%rdx)
-       vmovdqu %xmm2, 96(%rdx)
-       vmovdqu %xmm3, 112(%rdx)
-       vmovdqu %xmm4, 160(%rdx)
-       vmovdqu %xmm5, 176(%rdx)
-       vmovdqu %xmm6, 224(%rdx)
-       vmovdqu %xmm7, 240(%rdx)
-.Lchacha_blocks_avx2_mainloop2_cont:
-       addq $256, %rdx
-       subq $256, %rcx
-       cmp $256, %rcx
-       jae .Lchacha_blocks_avx2_atleast256
-.Lchacha_blocks_avx2_below256_fixup:
-       vmovdqa 448(%rsp), %xmm6
-       vmovdqa 480(%rsp), %xmm7
-       vmovdqa 0(%rsp), %xmm8
-       vmovdqa 16(%rsp), %xmm9
-       vmovdqa 32(%rsp), %xmm10
-       vmovdqa 48(%rsp), %xmm11
-       movq $1, %r9
-.Lchacha_blocks_avx2_below256:
-       vmovq %r9, %xmm5
-       andq %rcx, %rcx
-       jz .Lchacha_blocks_avx2_done
-       cmpq $64, %rcx
-       jae .Lchacha_blocks_avx2_above63
-       movq %rdx, %r9
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_avx2_noinput3
-       movq %rcx, %r10
-       movq %rsp, %rdx
-       addq %r10, %rsi
-       addq %r10, %rdx
-       negq %r10
-.Lchacha_blocks_avx2_copyinput:
-       movb (%rsi, %r10), %al
-       movb %al, (%rdx, %r10)
-       incq %r10
-       jnz .Lchacha_blocks_avx2_copyinput
-       movq %rsp, %rsi
-.Lchacha_blocks_avx2_noinput3:
-       movq %rsp, %rdx
-.Lchacha_blocks_avx2_above63:
-       vmovdqa %xmm8, %xmm0
-       vmovdqa %xmm9, %xmm1
-       vmovdqa %xmm10, %xmm2
-       vmovdqa %xmm11, %xmm3
-       movq 64(%rsp), %rax
-.Lchacha_blocks_avx2_mainloop3:
-       vpaddd %xmm0, %xmm1, %xmm0
-       vpxor %xmm3, %xmm0, %xmm3
-       vpshufb %xmm6, %xmm3, %xmm3
-       vpaddd %xmm2, %xmm3, %xmm2
-       vpxor %xmm1, %xmm2, %xmm1
-       vpslld $12, %xmm1, %xmm4
-       vpsrld $20, %xmm1, %xmm1
-       vpxor %xmm1, %xmm4, %xmm1
-       vpaddd %xmm0, %xmm1, %xmm0
-       vpxor %xmm3, %xmm0, %xmm3
-       vpshufb %xmm7, %xmm3, %xmm3
-       vpshufd $0x93, %xmm0, %xmm0
-       vpaddd %xmm2, %xmm3, %xmm2
-       vpshufd $0x4e, %xmm3, %xmm3
-       vpxor %xmm1, %xmm2, %xmm1
-       vpshufd $0x39, %xmm2, %xmm2
-       vpslld $7, %xmm1, %xmm4
-       vpsrld $25, %xmm1, %xmm1
-       vpxor %xmm1, %xmm4, %xmm1
-       vpaddd %xmm0, %xmm1, %xmm0
-       vpxor %xmm3, %xmm0, %xmm3
-       vpshufb %xmm6, %xmm3, %xmm3
-       vpaddd %xmm2, %xmm3, %xmm2
-       vpxor %xmm1, %xmm2, %xmm1
-       vpslld $12, %xmm1, %xmm4
-       vpsrld $20, %xmm1, %xmm1
-       vpxor %xmm1, %xmm4, %xmm1
-       vpaddd %xmm0, %xmm1, %xmm0
-       vpxor %xmm3, %xmm0, %xmm3
-       vpshufb %xmm7, %xmm3, %xmm3
-       vpshufd $0x39, %xmm0, %xmm0
-       vpaddd %xmm2, %xmm3, %xmm2
-       vpshufd $0x4e, %xmm3, %xmm3
-       vpxor %xmm1, %xmm2, %xmm1
-       vpshufd $0x93, %xmm2, %xmm2
-       vpslld $7, %xmm1, %xmm4
-       vpsrld $25, %xmm1, %xmm1
-       vpxor %xmm1, %xmm4, %xmm1
-       subq $2, %rax
-       jnz .Lchacha_blocks_avx2_mainloop3
-       vpaddd %xmm0, %xmm8, %xmm0
-       vpaddd %xmm1, %xmm9, %xmm1
-       vpaddd %xmm2, %xmm10, %xmm2
-       vpaddd %xmm3, %xmm11, %xmm3
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_avx2_noinput4
-       vpxor 0(%rsi), %xmm0, %xmm0
-       vpxor 16(%rsi), %xmm1, %xmm1
-       vpxor 32(%rsi), %xmm2, %xmm2
-       vpxor 48(%rsi), %xmm3, %xmm3
-       addq $64, %rsi
-.Lchacha_blocks_avx2_noinput4:
-       vmovdqu %xmm0, 0(%rdx)
-       vmovdqu %xmm1, 16(%rdx)
-       vmovdqu %xmm2, 32(%rdx)
-       vmovdqu %xmm3, 48(%rdx)
-       vpaddq %xmm11, %xmm5, %xmm11
-       cmpq $64, %rcx
-       jbe .Lchacha_blocks_avx2_mainloop3_finishup
-       addq $64, %rdx
-       subq $64, %rcx
-       jmp .Lchacha_blocks_avx2_below256
-.Lchacha_blocks_avx2_mainloop3_finishup:
-       cmpq $64, %rcx
-       je .Lchacha_blocks_avx2_done
-       addq %rcx, %r9
-       addq %rcx, %rdx
-       negq %rcx
-.Lchacha_blocks_avx2_copyoutput:
-       movb (%rdx, %rcx), %al
-       movb %al, (%r9, %rcx)
-       incq %rcx
-       jnz .Lchacha_blocks_avx2_copyoutput
-.Lchacha_blocks_avx2_done:
-       vmovdqu %xmm11, 48(%rdi)
-       movq %rbp, %rsp
-       popq %r14
-       popq %r13
-       popq %r12
-       popq %rbp
-       popq %rbx
-       vzeroall
-       movl $(63 + 512), %eax
-       ret
-ELF(.size _gcry_chacha20_amd64_avx2_blocks,.-_gcry_chacha20_amd64_avx2_blocks;)
-
-.align 16
-.LC:
-.byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13       /* pshufb rotate by 16 */
-.byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14       /* pshufb rotate by 8 */
-
-#endif /*defined(USE_CHACHA20)*/
-#endif /*__x86_64*/
diff --git a/cipher/chacha20-ppc.c b/cipher/chacha20-ppc.c
new file mode 100644 (file)
index 0000000..4a21b83
--- /dev/null
@@ -0,0 +1,646 @@
+/* chacha20-ppc.c - PowerPC vector implementation of ChaCha20
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#if defined(ENABLE_PPC_CRYPTO_SUPPORT) && \
+    defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+    defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) && \
+    defined(USE_CHACHA20) && \
+    __GNUC__ >= 4
+
+#include <altivec.h>
+#include "bufhelp.h"
+#include "poly1305-internal.h"
+
+#include "mpi-internal.h"
+#include "longlong.h"
+
+
+typedef vector unsigned char vector16x_u8;
+typedef vector unsigned int vector4x_u32;
+typedef vector unsigned long long vector2x_u64;
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR          NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE   ASM_FUNC_ATTR ALWAYS_INLINE
+#define ASM_FUNC_ATTR_NOINLINE ASM_FUNC_ATTR NO_INLINE
+
+
+#ifdef WORDS_BIGENDIAN
+static const vector16x_u8 le_bswap_const =
+  { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 };
+#endif
+
+
+static ASM_FUNC_ATTR_INLINE vector4x_u32
+vec_rol_elems(vector4x_u32 v, unsigned int idx)
+{
+#ifndef WORDS_BIGENDIAN
+  return vec_sld (v, v, (16 - (4 * idx)) & 15);
+#else
+  return vec_sld (v, v, (4 * idx) & 15);
+#endif
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector4x_u32
+vec_load_le(unsigned long offset, const unsigned char *ptr)
+{
+  vector4x_u32 vec;
+  vec = vec_vsx_ld (offset, (const u32 *)ptr);
+#ifdef WORDS_BIGENDIAN
+  vec = (vector4x_u32)vec_perm((vector16x_u8)vec, (vector16x_u8)vec,
+                              le_bswap_const);
+#endif
+  return vec;
+}
+
+
+static ASM_FUNC_ATTR_INLINE void
+vec_store_le(vector4x_u32 vec, unsigned long offset, unsigned char *ptr)
+{
+#ifdef WORDS_BIGENDIAN
+  vec = (vector4x_u32)vec_perm((vector16x_u8)vec, (vector16x_u8)vec,
+                              le_bswap_const);
+#endif
+  vec_vsx_st (vec, offset, (u32 *)ptr);
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector4x_u32
+vec_add_ctr_u64(vector4x_u32 v, vector4x_u32 a)
+{
+#ifdef WORDS_BIGENDIAN
+  static const vector16x_u8 swap32 =
+    { 4, 5, 6, 7, 0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11 };
+  vector2x_u64 vec, add, sum;
+
+  vec = (vector2x_u64)vec_perm((vector16x_u8)v, (vector16x_u8)v, swap32);
+  add = (vector2x_u64)vec_perm((vector16x_u8)a, (vector16x_u8)a, swap32);
+  sum = vec + add;
+  return (vector4x_u32)vec_perm((vector16x_u8)sum, (vector16x_u8)sum, swap32);
+#else
+  return (vector4x_u32)((vector2x_u64)(v) + (vector2x_u64)(a));
+#endif
+}
+
+
+/**********************************************************************
+  2-way && 1-way chacha20
+ **********************************************************************/
+
+#define ROTATE(v1,rolv)                        \
+       __asm__ ("vrlw %0,%1,%2\n\t" : "=v" (v1) : "v" (v1), "v" (rolv))
+
+#define WORD_ROL(v1,c)                 \
+       ((v1) = vec_rol_elems((v1), (c)))
+
+#define XOR(ds,s) \
+       ((ds) ^= (s))
+
+#define PLUS(ds,s) \
+       ((ds) += (s))
+
+#define QUARTERROUND4(x0,x1,x2,x3,rol_x1,rol_x2,rol_x3) \
+       PLUS(x0, x1); XOR(x3, x0); ROTATE(x3, rotate_16); \
+       PLUS(x2, x3); XOR(x1, x2); ROTATE(x1, rotate_12); \
+       PLUS(x0, x1); XOR(x3, x0); ROTATE(x3, rotate_8); \
+       PLUS(x2, x3); \
+         WORD_ROL(x3, rol_x3); \
+                     XOR(x1, x2); \
+         WORD_ROL(x2, rol_x2); \
+                                  ROTATE(x1, rotate_7); \
+         WORD_ROL(x1, rol_x1);
+
+#define ADD_U64(v,a) \
+       (v = vec_add_ctr_u64(v, a))
+
+unsigned int ASM_FUNC_ATTR
+_gcry_chacha20_ppc8_blocks1(u32 *state, byte *dst, const byte *src,
+                           size_t nblks)
+{
+  vector4x_u32 counter_1 = { 1, 0, 0, 0 };
+  vector4x_u32 rotate_16 = { 16, 16, 16, 16 };
+  vector4x_u32 rotate_12 = { 12, 12, 12, 12 };
+  vector4x_u32 rotate_8 = { 8, 8, 8, 8 };
+  vector4x_u32 rotate_7 = { 7, 7, 7, 7 };
+  vector4x_u32 state0, state1, state2, state3;
+  vector4x_u32 v0, v1, v2, v3;
+  vector4x_u32 v4, v5, v6, v7;
+  int i;
+
+  /* force preload of constants to vector registers */
+  __asm__ ("": "+v" (counter_1) :: "memory");
+  __asm__ ("": "+v" (rotate_16) :: "memory");
+  __asm__ ("": "+v" (rotate_12) :: "memory");
+  __asm__ ("": "+v" (rotate_8) :: "memory");
+  __asm__ ("": "+v" (rotate_7) :: "memory");
+
+  state0 = vec_vsx_ld(0 * 16, state);
+  state1 = vec_vsx_ld(1 * 16, state);
+  state2 = vec_vsx_ld(2 * 16, state);
+  state3 = vec_vsx_ld(3 * 16, state);
+
+  while (nblks >= 2)
+    {
+      v0 = state0;
+      v1 = state1;
+      v2 = state2;
+      v3 = state3;
+
+      v4 = state0;
+      v5 = state1;
+      v6 = state2;
+      v7 = state3;
+      ADD_U64(v7, counter_1);
+
+      for (i = 20; i > 0; i -= 2)
+       {
+         QUARTERROUND4(v0, v1, v2, v3, 1, 2, 3);
+         QUARTERROUND4(v4, v5, v6, v7, 1, 2, 3);
+         QUARTERROUND4(v0, v1, v2, v3, 3, 2, 1);
+         QUARTERROUND4(v4, v5, v6, v7, 3, 2, 1);
+       }
+
+      v0 += state0;
+      v1 += state1;
+      v2 += state2;
+      v3 += state3;
+      ADD_U64(state3, counter_1); /* update counter */
+      v4 += state0;
+      v5 += state1;
+      v6 += state2;
+      v7 += state3;
+      ADD_U64(state3, counter_1); /* update counter */
+
+      v0 ^= vec_load_le(0 * 16, src);
+      v1 ^= vec_load_le(1 * 16, src);
+      v2 ^= vec_load_le(2 * 16, src);
+      v3 ^= vec_load_le(3 * 16, src);
+      vec_store_le(v0, 0 * 16, dst);
+      vec_store_le(v1, 1 * 16, dst);
+      vec_store_le(v2, 2 * 16, dst);
+      vec_store_le(v3, 3 * 16, dst);
+      src += 64;
+      dst += 64;
+      v4 ^= vec_load_le(0 * 16, src);
+      v5 ^= vec_load_le(1 * 16, src);
+      v6 ^= vec_load_le(2 * 16, src);
+      v7 ^= vec_load_le(3 * 16, src);
+      vec_store_le(v4, 0 * 16, dst);
+      vec_store_le(v5, 1 * 16, dst);
+      vec_store_le(v6, 2 * 16, dst);
+      vec_store_le(v7, 3 * 16, dst);
+      src += 64;
+      dst += 64;
+
+      nblks -= 2;
+    }
+
+  while (nblks)
+    {
+      v0 = state0;
+      v1 = state1;
+      v2 = state2;
+      v3 = state3;
+
+      for (i = 20; i > 0; i -= 2)
+       {
+         QUARTERROUND4(v0, v1, v2, v3, 1, 2, 3);
+         QUARTERROUND4(v0, v1, v2, v3, 3, 2, 1);
+       }
+
+      v0 += state0;
+      v1 += state1;
+      v2 += state2;
+      v3 += state3;
+      ADD_U64(state3, counter_1); /* update counter */
+
+      v0 ^= vec_load_le(0 * 16, src);
+      v1 ^= vec_load_le(1 * 16, src);
+      v2 ^= vec_load_le(2 * 16, src);
+      v3 ^= vec_load_le(3 * 16, src);
+      vec_store_le(v0, 0 * 16, dst);
+      vec_store_le(v1, 1 * 16, dst);
+      vec_store_le(v2, 2 * 16, dst);
+      vec_store_le(v3, 3 * 16, dst);
+      src += 64;
+      dst += 64;
+
+      nblks--;
+    }
+
+  vec_vsx_st(state3, 3 * 16, state); /* store counter */
+
+  return 0;
+}
+
+
+/**********************************************************************
+  4-way chacha20
+ **********************************************************************/
+
+/* 4x4 32-bit integer matrix transpose */
+#define transpose_4x4(x0, x1, x2, x3) ({ \
+       vector4x_u32 t1 = vec_mergeh(x0, x2); \
+       vector4x_u32 t2 = vec_mergel(x0, x2); \
+       vector4x_u32 t3 = vec_mergeh(x1, x3); \
+       x3 = vec_mergel(x1, x3); \
+       x0 = vec_mergeh(t1, t3); \
+       x1 = vec_mergel(t1, t3); \
+       x2 = vec_mergeh(t2, x3); \
+       x3 = vec_mergel(t2, x3); \
+      })
+
+#define QUARTERROUND2(a1,b1,c1,d1,a2,b2,c2,d2)                 \
+       PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
+           ROTATE(d1, rotate_16); ROTATE(d2, rotate_16);       \
+       PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
+           ROTATE(b1, rotate_12); ROTATE(b2, rotate_12);       \
+       PLUS(a1,b1); PLUS(a2,b2); XOR(d1,a1); XOR(d2,a2);       \
+           ROTATE(d1, rotate_8); ROTATE(d2, rotate_8);         \
+       PLUS(c1,d1); PLUS(c2,d2); XOR(b1,c1); XOR(b2,c2);       \
+           ROTATE(b1, rotate_7); ROTATE(b2, rotate_7);
+
+unsigned int ASM_FUNC_ATTR
+_gcry_chacha20_ppc8_blocks4(u32 *state, byte *dst, const byte *src,
+                           size_t nblks)
+{
+  vector4x_u32 counters_0123 = { 0, 1, 2, 3 };
+  vector4x_u32 counter_4 = { 4, 0, 0, 0 };
+  vector4x_u32 rotate_16 = { 16, 16, 16, 16 };
+  vector4x_u32 rotate_12 = { 12, 12, 12, 12 };
+  vector4x_u32 rotate_8 = { 8, 8, 8, 8 };
+  vector4x_u32 rotate_7 = { 7, 7, 7, 7 };
+  vector4x_u32 state0, state1, state2, state3;
+  vector4x_u32 v0, v1, v2, v3, v4, v5, v6, v7;
+  vector4x_u32 v8, v9, v10, v11, v12, v13, v14, v15;
+  vector4x_u32 tmp;
+  int i;
+
+  /* force preload of constants to vector registers */
+  __asm__ ("": "+v" (counters_0123) :: "memory");
+  __asm__ ("": "+v" (counter_4) :: "memory");
+  __asm__ ("": "+v" (rotate_16) :: "memory");
+  __asm__ ("": "+v" (rotate_12) :: "memory");
+  __asm__ ("": "+v" (rotate_8) :: "memory");
+  __asm__ ("": "+v" (rotate_7) :: "memory");
+
+  state0 = vec_vsx_ld(0 * 16, state);
+  state1 = vec_vsx_ld(1 * 16, state);
+  state2 = vec_vsx_ld(2 * 16, state);
+  state3 = vec_vsx_ld(3 * 16, state);
+
+  do
+    {
+      v0 = vec_splat(state0, 0);
+      v1 = vec_splat(state0, 1);
+      v2 = vec_splat(state0, 2);
+      v3 = vec_splat(state0, 3);
+      v4 = vec_splat(state1, 0);
+      v5 = vec_splat(state1, 1);
+      v6 = vec_splat(state1, 2);
+      v7 = vec_splat(state1, 3);
+      v8 = vec_splat(state2, 0);
+      v9 = vec_splat(state2, 1);
+      v10 = vec_splat(state2, 2);
+      v11 = vec_splat(state2, 3);
+      v12 = vec_splat(state3, 0);
+      v13 = vec_splat(state3, 1);
+      v14 = vec_splat(state3, 2);
+      v15 = vec_splat(state3, 3);
+
+      v12 += counters_0123;
+      v13 -= vec_cmplt(v12, counters_0123);
+
+      for (i = 20; i > 0; i -= 2)
+       {
+         QUARTERROUND2(v0, v4,  v8, v12,   v1, v5,  v9, v13)
+         QUARTERROUND2(v2, v6, v10, v14,   v3, v7, v11, v15)
+         QUARTERROUND2(v0, v5, v10, v15,   v1, v6, v11, v12)
+         QUARTERROUND2(v2, v7,  v8, v13,   v3, v4,  v9, v14)
+       }
+
+      v0 += vec_splat(state0, 0);
+      v1 += vec_splat(state0, 1);
+      v2 += vec_splat(state0, 2);
+      v3 += vec_splat(state0, 3);
+      v4 += vec_splat(state1, 0);
+      v5 += vec_splat(state1, 1);
+      v6 += vec_splat(state1, 2);
+      v7 += vec_splat(state1, 3);
+      v8 += vec_splat(state2, 0);
+      v9 += vec_splat(state2, 1);
+      v10 += vec_splat(state2, 2);
+      v11 += vec_splat(state2, 3);
+      tmp = vec_splat(state3, 0);
+      tmp += counters_0123;
+      v12 += tmp;
+      v13 += vec_splat(state3, 1) - vec_cmplt(tmp, counters_0123);
+      v14 += vec_splat(state3, 2);
+      v15 += vec_splat(state3, 3);
+      ADD_U64(state3, counter_4); /* update counter */
+
+      transpose_4x4(v0, v1, v2, v3);
+      transpose_4x4(v4, v5, v6, v7);
+      transpose_4x4(v8, v9, v10, v11);
+      transpose_4x4(v12, v13, v14, v15);
+
+      v0 ^= vec_load_le((64 * 0 + 16 * 0), src);
+      v1 ^= vec_load_le((64 * 1 + 16 * 0), src);
+      v2 ^= vec_load_le((64 * 2 + 16 * 0), src);
+      v3 ^= vec_load_le((64 * 3 + 16 * 0), src);
+
+      v4 ^= vec_load_le((64 * 0 + 16 * 1), src);
+      v5 ^= vec_load_le((64 * 1 + 16 * 1), src);
+      v6 ^= vec_load_le((64 * 2 + 16 * 1), src);
+      v7 ^= vec_load_le((64 * 3 + 16 * 1), src);
+
+      v8 ^= vec_load_le((64 * 0 + 16 * 2), src);
+      v9 ^= vec_load_le((64 * 1 + 16 * 2), src);
+      v10 ^= vec_load_le((64 * 2 + 16 * 2), src);
+      v11 ^= vec_load_le((64 * 3 + 16 * 2), src);
+
+      v12 ^= vec_load_le((64 * 0 + 16 * 3), src);
+      v13 ^= vec_load_le((64 * 1 + 16 * 3), src);
+      v14 ^= vec_load_le((64 * 2 + 16 * 3), src);
+      v15 ^= vec_load_le((64 * 3 + 16 * 3), src);
+
+      vec_store_le(v0, (64 * 0 + 16 * 0), dst);
+      vec_store_le(v1, (64 * 1 + 16 * 0), dst);
+      vec_store_le(v2, (64 * 2 + 16 * 0), dst);
+      vec_store_le(v3, (64 * 3 + 16 * 0), dst);
+
+      vec_store_le(v4, (64 * 0 + 16 * 1), dst);
+      vec_store_le(v5, (64 * 1 + 16 * 1), dst);
+      vec_store_le(v6, (64 * 2 + 16 * 1), dst);
+      vec_store_le(v7, (64 * 3 + 16 * 1), dst);
+
+      vec_store_le(v8, (64 * 0 + 16 * 2), dst);
+      vec_store_le(v9, (64 * 1 + 16 * 2), dst);
+      vec_store_le(v10, (64 * 2 + 16 * 2), dst);
+      vec_store_le(v11, (64 * 3 + 16 * 2), dst);
+
+      vec_store_le(v12, (64 * 0 + 16 * 3), dst);
+      vec_store_le(v13, (64 * 1 + 16 * 3), dst);
+      vec_store_le(v14, (64 * 2 + 16 * 3), dst);
+      vec_store_le(v15, (64 * 3 + 16 * 3), dst);
+
+      src += 4*64;
+      dst += 4*64;
+
+      nblks -= 4;
+    }
+  while (nblks);
+
+  vec_vsx_st(state3, 3 * 16, state); /* store counter */
+
+  return 0;
+}
+
+
+#if SIZEOF_UNSIGNED_LONG == 8
+
+/**********************************************************************
+  4-way stitched chacha20-poly1305
+ **********************************************************************/
+
+#define ADD_1305_64(A2, A1, A0, B2, B1, B0) \
+      __asm__ ("addc %0, %3, %0\n" \
+              "adde %1, %4, %1\n" \
+              "adde %2, %5, %2\n" \
+              : "+r" (A0), "+r" (A1), "+r" (A2) \
+              : "r" (B0), "r" (B1), "r" (B2) \
+              : "cc" )
+
+#define MUL_MOD_1305_64_PART1(H2, H1, H0, R1, R0, R1_MULT5) do { \
+    /* x = a * r (partial mod 2^130-5) */ \
+    umul_ppmm(x0_hi, x0_lo, H0, R0);  /* h0 * r0 */ \
+    umul_ppmm(x1_hi, x1_lo, H0, R1);  /* h0 * r1 */ \
+    \
+    umul_ppmm(t0_hi, t0_lo, H1, R1_MULT5); /* h1 * r1 mod 2^130-5 */ \
+  } while (0)
+
+#define MUL_MOD_1305_64_PART2(H2, H1, H0, R1, R0, R1_MULT5) do { \
+    add_ssaaaa(x0_hi, x0_lo, x0_hi, x0_lo, t0_hi, t0_lo); \
+    umul_ppmm(t1_hi, t1_lo, H1, R0);       /* h1 * r0 */ \
+    add_ssaaaa(x1_hi, x1_lo, x1_hi, x1_lo, t1_hi, t1_lo); \
+    \
+    t1_lo = H2 * R1_MULT5; /* h2 * r1 mod 2^130-5 */ \
+    t1_hi = H2 * R0;       /* h2 * r0 */ \
+    add_ssaaaa(H0, H1, x1_hi, x1_lo, t1_hi, t1_lo); \
+    \
+    /* carry propagation */ \
+    H2 = H0 & 3; \
+    H0 = (H0 >> 2) * 5; /* msb mod 2^130-5 */ \
+    ADD_1305_64(H2, H1, H0, (u64)0, x0_hi, x0_lo); \
+  } while (0)
+
+#define POLY1305_BLOCK_PART1(in_pos) do { \
+    m0 = buf_get_le64(poly1305_src + (in_pos) + 0); \
+    m1 = buf_get_le64(poly1305_src + (in_pos) + 8); \
+    /* a = h + m */ \
+    ADD_1305_64(h2, h1, h0, m2, m1, m0); \
+    /* h = a * r (partial mod 2^130-5) */ \
+    MUL_MOD_1305_64_PART1(h2, h1, h0, r1, r0, r1_mult5); \
+  } while (0)
+
+#define POLY1305_BLOCK_PART2(in_pos) do { \
+    MUL_MOD_1305_64_PART2(h2, h1, h0, r1, r0, r1_mult5); \
+  } while (0)
+
+unsigned int ASM_FUNC_ATTR
+_gcry_chacha20_poly1305_ppc8_blocks4(u32 *state, byte *dst, const byte *src,
+                                    size_t nblks, POLY1305_STATE *st,
+                                    const byte *poly1305_src)
+{
+  vector4x_u32 counters_0123 = { 0, 1, 2, 3 };
+  vector4x_u32 counter_4 = { 4, 0, 0, 0 };
+  vector4x_u32 rotate_16 = { 16, 16, 16, 16 };
+  vector4x_u32 rotate_12 = { 12, 12, 12, 12 };
+  vector4x_u32 rotate_8 = { 8, 8, 8, 8 };
+  vector4x_u32 rotate_7 = { 7, 7, 7, 7 };
+  vector4x_u32 state0, state1, state2, state3;
+  vector4x_u32 v0, v1, v2, v3, v4, v5, v6, v7;
+  vector4x_u32 v8, v9, v10, v11, v12, v13, v14, v15;
+  vector4x_u32 tmp;
+  u64 r0, r1, r1_mult5;
+  u64 h0, h1, h2;
+  u64 m0, m1, m2;
+  u64 x0_lo, x0_hi, x1_lo, x1_hi;
+  u64 t0_lo, t0_hi, t1_lo, t1_hi;
+  unsigned int i, o;
+
+  /* load poly1305 state */
+  m2 = 1;
+  h0 = st->h[0] + ((u64)st->h[1] << 32);
+  h1 = st->h[2] + ((u64)st->h[3] << 32);
+  h2 = st->h[4];
+  r0 = st->r[0] + ((u64)st->r[1] << 32);
+  r1 = st->r[2] + ((u64)st->r[3] << 32);
+  r1_mult5 = (r1 >> 2) + r1;
+
+  /* force preload of constants to vector registers */
+  __asm__ ("": "+v" (counters_0123) :: "memory");
+  __asm__ ("": "+v" (counter_4) :: "memory");
+  __asm__ ("": "+v" (rotate_16) :: "memory");
+  __asm__ ("": "+v" (rotate_12) :: "memory");
+  __asm__ ("": "+v" (rotate_8) :: "memory");
+  __asm__ ("": "+v" (rotate_7) :: "memory");
+
+  state0 = vec_vsx_ld(0 * 16, state);
+  state1 = vec_vsx_ld(1 * 16, state);
+  state2 = vec_vsx_ld(2 * 16, state);
+  state3 = vec_vsx_ld(3 * 16, state);
+
+  do
+    {
+      v0 = vec_splat(state0, 0);
+      v1 = vec_splat(state0, 1);
+      v2 = vec_splat(state0, 2);
+      v3 = vec_splat(state0, 3);
+      v4 = vec_splat(state1, 0);
+      v5 = vec_splat(state1, 1);
+      v6 = vec_splat(state1, 2);
+      v7 = vec_splat(state1, 3);
+      v8 = vec_splat(state2, 0);
+      v9 = vec_splat(state2, 1);
+      v10 = vec_splat(state2, 2);
+      v11 = vec_splat(state2, 3);
+      v12 = vec_splat(state3, 0);
+      v13 = vec_splat(state3, 1);
+      v14 = vec_splat(state3, 2);
+      v15 = vec_splat(state3, 3);
+
+      v12 += counters_0123;
+      v13 -= vec_cmplt(v12, counters_0123);
+
+      for (o = 20; o; o -= 10)
+       {
+         for (i = 8; i; i -= 2)
+           {
+             POLY1305_BLOCK_PART1(0 * 16);
+             QUARTERROUND2(v0, v4,  v8, v12,   v1, v5,  v9, v13)
+             POLY1305_BLOCK_PART2();
+             QUARTERROUND2(v2, v6, v10, v14,   v3, v7, v11, v15)
+             POLY1305_BLOCK_PART1(1 * 16);
+             poly1305_src += 2 * 16;
+             QUARTERROUND2(v0, v5, v10, v15,   v1, v6, v11, v12)
+             POLY1305_BLOCK_PART2();
+             QUARTERROUND2(v2, v7,  v8, v13,   v3, v4,  v9, v14)
+           }
+
+         QUARTERROUND2(v0, v4,  v8, v12,   v1, v5,  v9, v13)
+         QUARTERROUND2(v2, v6, v10, v14,   v3, v7, v11, v15)
+         QUARTERROUND2(v0, v5, v10, v15,   v1, v6, v11, v12)
+         QUARTERROUND2(v2, v7,  v8, v13,   v3, v4,  v9, v14)
+       }
+
+      v0 += vec_splat(state0, 0);
+      v1 += vec_splat(state0, 1);
+      v2 += vec_splat(state0, 2);
+      v3 += vec_splat(state0, 3);
+      v4 += vec_splat(state1, 0);
+      v5 += vec_splat(state1, 1);
+      v6 += vec_splat(state1, 2);
+      v7 += vec_splat(state1, 3);
+      v8 += vec_splat(state2, 0);
+      v9 += vec_splat(state2, 1);
+      v10 += vec_splat(state2, 2);
+      v11 += vec_splat(state2, 3);
+      tmp = vec_splat(state3, 0);
+      tmp += counters_0123;
+      v12 += tmp;
+      v13 += vec_splat(state3, 1) - vec_cmplt(tmp, counters_0123);
+      v14 += vec_splat(state3, 2);
+      v15 += vec_splat(state3, 3);
+      ADD_U64(state3, counter_4); /* update counter */
+
+      transpose_4x4(v0, v1, v2, v3);
+      transpose_4x4(v4, v5, v6, v7);
+      transpose_4x4(v8, v9, v10, v11);
+      transpose_4x4(v12, v13, v14, v15);
+
+      v0 ^= vec_load_le((64 * 0 + 16 * 0), src);
+      v1 ^= vec_load_le((64 * 1 + 16 * 0), src);
+      v2 ^= vec_load_le((64 * 2 + 16 * 0), src);
+      v3 ^= vec_load_le((64 * 3 + 16 * 0), src);
+
+      v4 ^= vec_load_le((64 * 0 + 16 * 1), src);
+      v5 ^= vec_load_le((64 * 1 + 16 * 1), src);
+      v6 ^= vec_load_le((64 * 2 + 16 * 1), src);
+      v7 ^= vec_load_le((64 * 3 + 16 * 1), src);
+
+      v8 ^= vec_load_le((64 * 0 + 16 * 2), src);
+      v9 ^= vec_load_le((64 * 1 + 16 * 2), src);
+      v10 ^= vec_load_le((64 * 2 + 16 * 2), src);
+      v11 ^= vec_load_le((64 * 3 + 16 * 2), src);
+
+      v12 ^= vec_load_le((64 * 0 + 16 * 3), src);
+      v13 ^= vec_load_le((64 * 1 + 16 * 3), src);
+      v14 ^= vec_load_le((64 * 2 + 16 * 3), src);
+      v15 ^= vec_load_le((64 * 3 + 16 * 3), src);
+
+      vec_store_le(v0, (64 * 0 + 16 * 0), dst);
+      vec_store_le(v1, (64 * 1 + 16 * 0), dst);
+      vec_store_le(v2, (64 * 2 + 16 * 0), dst);
+      vec_store_le(v3, (64 * 3 + 16 * 0), dst);
+
+      vec_store_le(v4, (64 * 0 + 16 * 1), dst);
+      vec_store_le(v5, (64 * 1 + 16 * 1), dst);
+      vec_store_le(v6, (64 * 2 + 16 * 1), dst);
+      vec_store_le(v7, (64 * 3 + 16 * 1), dst);
+
+      vec_store_le(v8, (64 * 0 + 16 * 2), dst);
+      vec_store_le(v9, (64 * 1 + 16 * 2), dst);
+      vec_store_le(v10, (64 * 2 + 16 * 2), dst);
+      vec_store_le(v11, (64 * 3 + 16 * 2), dst);
+
+      vec_store_le(v12, (64 * 0 + 16 * 3), dst);
+      vec_store_le(v13, (64 * 1 + 16 * 3), dst);
+      vec_store_le(v14, (64 * 2 + 16 * 3), dst);
+      vec_store_le(v15, (64 * 3 + 16 * 3), dst);
+
+      src += 4*64;
+      dst += 4*64;
+
+      nblks -= 4;
+    }
+  while (nblks);
+
+  vec_vsx_st(state3, 3 * 16, state); /* store counter */
+
+  /* store poly1305 state */
+  st->h[0] = h0;
+  st->h[1] = h0 >> 32;
+  st->h[2] = h1;
+  st->h[3] = h1 >> 32;
+  st->h[4] = h2;
+
+  return 0;
+}
+
+#endif /* SIZEOF_UNSIGNED_LONG == 8 */
+
+#endif /* ENABLE_PPC_CRYPTO_SUPPORT */
diff --git a/cipher/chacha20-s390x.S b/cipher/chacha20-s390x.S
new file mode 100644 (file)
index 0000000..9b1d59c
--- /dev/null
@@ -0,0 +1,1561 @@
+/* chacha20-s390x.S  -  zSeries implementation of ChaCha20 cipher
+ *
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#if defined (__s390x__) && __GNUC__ >= 4 && __ARCH__ >= 9
+#include <config.h>
+#if defined(HAVE_GCC_INLINE_ASM_S390X_VX)
+
+#include "asm-common-s390x.h"
+#include "asm-poly1305-s390x.h"
+
+.machine "z13+vx"
+.text
+
+.balign 16
+.Lconsts:
+.Lwordswap:
+       .byte 12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3
+.Lbswap128:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+.Lbswap32:
+       .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+.Lone:
+       .long 0, 0, 0, 1
+.Ladd_counter_0123:
+       .long 0, 1, 2, 3
+.Ladd_counter_4567:
+       .long 4, 5, 6, 7
+
+/* register macros */
+#define INPUT %r2
+#define DST   %r3
+#define SRC   %r4
+#define NBLKS %r0
+#define ROUND %r1
+
+/* stack structure */
+
+#define STACK_FRAME_STD    (8 * 16 + 8 * 4)
+#define STACK_FRAME_F8_F15 (8 * 8)
+#define STACK_FRAME_Y0_Y15 (16 * 16)
+#define STACK_FRAME_CTR    (4 * 16)
+#define STACK_FRAME_PARAMS (6 * 8)
+
+#define STACK_MAX   (STACK_FRAME_STD + STACK_FRAME_F8_F15 + \
+                    STACK_FRAME_Y0_Y15 + STACK_FRAME_CTR + \
+                    STACK_FRAME_PARAMS)
+
+#define STACK_F8     (STACK_MAX - STACK_FRAME_F8_F15)
+#define STACK_F9     (STACK_F8 + 8)
+#define STACK_F10    (STACK_F9 + 8)
+#define STACK_F11    (STACK_F10 + 8)
+#define STACK_F12    (STACK_F11 + 8)
+#define STACK_F13    (STACK_F12 + 8)
+#define STACK_F14    (STACK_F13 + 8)
+#define STACK_F15    (STACK_F14 + 8)
+#define STACK_Y0_Y15 (STACK_F8 - STACK_FRAME_Y0_Y15)
+#define STACK_CTR    (STACK_Y0_Y15 - STACK_FRAME_CTR)
+#define STACK_INPUT  (STACK_CTR - STACK_FRAME_PARAMS)
+#define STACK_DST    (STACK_INPUT + 8)
+#define STACK_SRC    (STACK_DST + 8)
+#define STACK_NBLKS  (STACK_SRC + 8)
+#define STACK_POCTX  (STACK_NBLKS + 8)
+#define STACK_POSRC  (STACK_POCTX + 8)
+
+#define STACK_G0_H3  STACK_Y0_Y15
+
+/* vector registers */
+#define A0 %v0
+#define A1 %v1
+#define A2 %v2
+#define A3 %v3
+
+#define B0 %v4
+#define B1 %v5
+#define B2 %v6
+#define B3 %v7
+
+#define C0 %v8
+#define C1 %v9
+#define C2 %v10
+#define C3 %v11
+
+#define D0 %v12
+#define D1 %v13
+#define D2 %v14
+#define D3 %v15
+
+#define E0 %v16
+#define E1 %v17
+#define E2 %v18
+#define E3 %v19
+
+#define F0 %v20
+#define F1 %v21
+#define F2 %v22
+#define F3 %v23
+
+#define G0 %v24
+#define G1 %v25
+#define G2 %v26
+#define G3 %v27
+
+#define H0 %v28
+#define H1 %v29
+#define H2 %v30
+#define H3 %v31
+
+#define IO0 E0
+#define IO1 E1
+#define IO2 E2
+#define IO3 E3
+#define IO4 F0
+#define IO5 F1
+#define IO6 F2
+#define IO7 F3
+
+#define S0 G0
+#define S1 G1
+#define S2 G2
+#define S3 G3
+
+#define TMP0 H0
+#define TMP1 H1
+#define TMP2 H2
+#define TMP3 H3
+
+#define X0 A0
+#define X1 A1
+#define X2 A2
+#define X3 A3
+#define X4 B0
+#define X5 B1
+#define X6 B2
+#define X7 B3
+#define X8 C0
+#define X9 C1
+#define X10 C2
+#define X11 C3
+#define X12 D0
+#define X13 D1
+#define X14 D2
+#define X15 D3
+
+#define Y0 E0
+#define Y1 E1
+#define Y2 E2
+#define Y3 E3
+#define Y4 F0
+#define Y5 F1
+#define Y6 F2
+#define Y7 F3
+#define Y8 G0
+#define Y9 G1
+#define Y10 G2
+#define Y11 G3
+#define Y12 H0
+#define Y13 H1
+#define Y14 H2
+#define Y15 H3
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+
+#define _ /*_*/
+
+#define CLEAR(x,...) vzero x;
+
+#define START_STACK(last_r) \
+       lgr %r0, %r15; \
+       lghi %r1, ~15; \
+       stmg %r6, last_r, 6 * 8(%r15); \
+       aghi %r0, -STACK_MAX; \
+       ngr %r0, %r1; \
+       lgr %r1, %r15; \
+       CFI_DEF_CFA_REGISTER(1); \
+       lgr %r15, %r0; \
+       stg %r1, 0(%r15); \
+       CFI_CFA_ON_STACK(0, 0); \
+       std %f8, STACK_F8(%r15); \
+       std %f9, STACK_F9(%r15); \
+       std %f10, STACK_F10(%r15); \
+       std %f11, STACK_F11(%r15); \
+       std %f12, STACK_F12(%r15); \
+       std %f13, STACK_F13(%r15); \
+       std %f14, STACK_F14(%r15); \
+       std %f15, STACK_F15(%r15);
+
+#define END_STACK(last_r) \
+       lg %r1, 0(%r15); \
+       ld %f8, STACK_F8(%r15); \
+       ld %f9, STACK_F9(%r15); \
+       ld %f10, STACK_F10(%r15); \
+       ld %f11, STACK_F11(%r15); \
+       ld %f12, STACK_F12(%r15); \
+       ld %f13, STACK_F13(%r15); \
+       ld %f14, STACK_F14(%r15); \
+       ld %f15, STACK_F15(%r15); \
+       lmg %r6, last_r, 6 * 8(%r1); \
+       lgr %r15, %r1; \
+       CFI_DEF_CFA_REGISTER(DW_REGNO_SP);
+
+#define PLUS(dst,src) \
+       vaf dst, dst, src;
+
+#define XOR(dst,src) \
+       vx dst, dst, src;
+
+#define ROTATE(v1,c) \
+       verllf v1, v1, (c)(0);
+
+#define WORD_ROTATE(v1,s) \
+       vsldb v1, v1, v1, ((s) * 4);
+
+#define DST_1(OPER, I, J) \
+       OPER(A##I, J);
+
+#define DST_2(OPER, I, J) \
+       OPER(A##I, J); OPER(B##I, J);
+
+#define DST_4(OPER, I, J) \
+       OPER(A##I, J); OPER(B##I, J); OPER(C##I, J); OPER(D##I, J);
+
+#define DST_8(OPER, I, J) \
+       OPER(A##I, J); OPER(B##I, J); OPER(C##I, J); OPER(D##I, J); \
+       OPER(E##I, J); OPER(F##I, J); OPER(G##I, J); OPER(H##I, J);
+
+#define DST_SRC_1(OPER, I, J) \
+       OPER(A##I, A##J);
+
+#define DST_SRC_2(OPER, I, J) \
+       OPER(A##I, A##J); OPER(B##I, B##J);
+
+#define DST_SRC_4(OPER, I, J) \
+       OPER(A##I, A##J); OPER(B##I, B##J); OPER(C##I, C##J); \
+       OPER(D##I, D##J);
+
+#define DST_SRC_8(OPER, I, J) \
+       OPER(A##I, A##J); OPER(B##I, B##J); OPER(C##I, C##J); \
+       OPER(D##I, D##J); OPER(E##I, E##J); OPER(F##I, F##J); \
+       OPER(G##I, G##J); OPER(H##I, H##J);
+
+/**********************************************************************
+  round macros
+ **********************************************************************/
+
+#define QUARTERROUND4_POLY(wrot_1,wrot_2,wrot_3,op1,op2) \
+       op1; DST_SRC_1(PLUS, 0, 1); DST_SRC_1(XOR, 3, 0); DST_1(ROTATE, 3, 16); \
+       DST_SRC_1(PLUS, 2, 3); DST_SRC_1(XOR, 1, 2); DST_1(ROTATE, 1, 12); \
+       DST_SRC_1(PLUS, 0, 1); DST_SRC_1(XOR, 3, 0); DST_1(ROTATE, 3, 8); \
+       op2; DST_SRC_1(PLUS, 2, 3); DST_SRC_1(XOR, 1, 2); DST_1(ROTATE, 1, 7); \
+       DST_1(WORD_ROTATE, 3, wrot_3); \
+       DST_1(WORD_ROTATE, 2, wrot_2); \
+       DST_1(WORD_ROTATE, 1, wrot_1);
+
+#define QUARTERROUND4(wrot_1,wrot_2,wrot_3) \
+       QUARTERROUND4_POLY(wrot_1,wrot_2,wrot_3,,)
+
+#define QUARTERROUND4_2_POLY(wrot_1,wrot_2,wrot_3,op1,op2,op3,op4) \
+       op1; DST_SRC_2(PLUS, 0, 1); DST_SRC_2(XOR, 3, 0); DST_2(ROTATE, 3, 16); \
+       DST_SRC_2(PLUS, 2, 3); op2; DST_SRC_2(XOR, 1, 2); DST_2(ROTATE, 1, 12); \
+       DST_SRC_2(PLUS, 0, 1); DST_SRC_2(XOR, 3, 0); op3; DST_2(ROTATE, 3, 8); \
+       DST_SRC_2(PLUS, 2, 3); DST_SRC_2(XOR, 1, 2); DST_2(ROTATE, 1, 7); op4; \
+       DST_2(WORD_ROTATE, 3, wrot_3); \
+       DST_2(WORD_ROTATE, 2, wrot_2); \
+       DST_2(WORD_ROTATE, 1, wrot_1);
+
+#define QUARTERROUND4_2(wrot_1,wrot_2,wrot_3) \
+       QUARTERROUND4_2_POLY(wrot_1,wrot_2,wrot_3,,,,)
+
+#define QUARTERROUND4_4_POLY(wrot_1,wrot_2,wrot_3,op1,op2,op3,op4,op5,op6) \
+       DST_SRC_4(PLUS, 0, 1); DST_SRC_4(XOR, 3, 0); op1; DST_4(ROTATE, 3, 16); \
+       DST_SRC_4(PLUS, 2, 3); op2; DST_SRC_4(XOR, 1, 2); DST_4(ROTATE, 1, 12); \
+       op3; DST_SRC_4(PLUS, 0, 1); DST_SRC_4(XOR, 3, 0); op4; DST_4(ROTATE, 3, 8); \
+       DST_SRC_4(PLUS, 2, 3); op5; DST_SRC_4(XOR, 1, 2); DST_4(ROTATE, 1, 7); \
+       op6; \
+       DST_4(WORD_ROTATE, 3, wrot_3); \
+       DST_4(WORD_ROTATE, 2, wrot_2); \
+       DST_4(WORD_ROTATE, 1, wrot_1);
+
+#define QUARTERROUND4_4(wrot_1,wrot_2,wrot_3) \
+       QUARTERROUND4_4_POLY(wrot_1,wrot_2,wrot_3,,,,,,)
+
+/**********************************************************************
+  4-way && 2-way && 1-way chacha20 ("horizontal")
+ **********************************************************************/
+
+.balign 8
+.globl _gcry_chacha20_s390x_vx_blocks4_2_1
+ELF(.type _gcry_chacha20_s390x_vx_blocks4_2_1,@function;)
+
+_gcry_chacha20_s390x_vx_blocks4_2_1:
+       /* input:
+        *      %r2: input
+        *      %r3: dst
+        *      %r4: src
+        *      %r5: nblks
+        */
+       CFI_STARTPROC();
+
+       START_STACK(%r7);
+       lgr NBLKS, %r5;
+
+       /* Load constants. */
+       larl %r7, .Lconsts;
+       vl TMP0, (.Lwordswap - .Lconsts)(%r7);
+       vl TMP1, (.Lone - .Lconsts)(%r7);
+       vl TMP2, (.Lbswap128 - .Lconsts)(%r7);
+
+       /* Load state. */
+       vlm S0, S3, 0(INPUT);
+       vperm S0, S0, S0, TMP0;
+       vperm S1, S1, S1, TMP0;
+       vperm S2, S2, S2, TMP0;
+       vperm S3, S3, S3, TMP0;
+
+       clgijl NBLKS, 4, .Lloop2;
+
+.balign 4
+.Lloop4:
+       /* Process four chacha20 blocks. */
+       vlr TMP3, S3;
+       lghi ROUND, (20 / 2);
+       vlr A0, S0;
+       vlr A1, S1;
+       vlr A2, S2;
+       vlr A3, TMP3;
+       vag TMP3, TMP3, TMP1;
+       vlr B0, S0;
+       vlr B1, S1;
+       vlr B2, S2;
+       vlr B3, TMP3;
+       vag TMP3, TMP3, TMP1;
+       vlr C0, S0;
+       vlr C1, S1;
+       vlr C2, S2;
+       vlr C3, TMP3;
+       vlr D0, S0;
+       vlr D1, S1;
+       vlr D2, S2;
+       vag D3, TMP3, TMP1;
+
+       slgfi NBLKS, 4;
+
+.balign 4
+.Lround2_4:
+       QUARTERROUND4_4(3, 2, 1);
+       QUARTERROUND4_4(1, 2, 3);
+       brctg ROUND, .Lround2_4;
+
+       vlm IO0, IO7, 0(SRC);
+
+       PLUS(A0, S0);
+       PLUS(A1, S1);
+       PLUS(A2, S2);
+       PLUS(A3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       PLUS(B0, S0);
+       PLUS(B1, S1);
+       PLUS(B2, S2);
+       PLUS(B3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       vperm A0, A0, A0, TMP2;
+       vperm A1, A1, A1, TMP2;
+       vperm A2, A2, A2, TMP2;
+       vperm A3, A3, A3, TMP2;
+       vperm B0, B0, B0, TMP2;
+       vperm B1, B1, B1, TMP2;
+       vperm B2, B2, B2, TMP2;
+       vperm B3, B3, B3, TMP2;
+       PLUS(C0, S0);
+       PLUS(C1, S1);
+       PLUS(C2, S2);
+       PLUS(C3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       PLUS(D0, S0);
+       PLUS(D1, S1);
+       PLUS(D2, S2);
+       PLUS(D3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       vperm C0, C0, C0, TMP2;
+       vperm C1, C1, C1, TMP2;
+       vperm C2, C2, C2, TMP2;
+       vperm C3, C3, C3, TMP2;
+       vperm D0, D0, D0, TMP2;
+       vperm D1, D1, D1, TMP2;
+       vperm D2, D2, D2, TMP2;
+       vperm D3, D3, D3, TMP2;
+
+       XOR(IO0, A0);
+       XOR(IO1, A1);
+       XOR(IO2, A2);
+       XOR(IO3, A3);
+       XOR(IO4, B0);
+       XOR(IO5, B1);
+       XOR(IO6, B2);
+       XOR(IO7, B3);
+       vlm A0, B3, 128(SRC);
+       vstm IO0, IO7, 0(DST);
+       XOR(A0, C0);
+       XOR(A1, C1);
+       XOR(A2, C2);
+       XOR(A3, C3);
+       XOR(B0, D0);
+       XOR(B1, D1);
+       XOR(B2, D2);
+       XOR(B3, D3);
+       vstm A0, B3, 128(DST);
+
+       aghi SRC, 256;
+       aghi DST, 256;
+
+       clgijhe NBLKS, 4, .Lloop4;
+
+       CLEAR(C0);
+       CLEAR(C1);
+       CLEAR(C2);
+       CLEAR(C3);
+       CLEAR(D0);
+       CLEAR(D1);
+       CLEAR(D2);
+       CLEAR(D3);
+
+.balign 4
+.Lloop2:
+       clgijl NBLKS, 2, .Lloop1;
+
+       /* Process two chacha20 blocks. */
+       lghi ROUND, (20 / 2);
+       vlr A0, S0;
+       vlr A1, S1;
+       vlr A2, S2;
+       vlr A3, S3;
+       vlr B0, S0;
+       vlr B1, S1;
+       vlr B2, S2;
+       vag B3, S3, TMP1;
+
+       slgfi NBLKS, 2;
+
+.balign 4
+.Lround2_2:
+       QUARTERROUND4_2(3, 2, 1);
+       QUARTERROUND4_2(1, 2, 3);
+       brctg ROUND, .Lround2_2;
+
+       vlm IO0, IO7, 0(SRC);
+
+       PLUS(A0, S0);
+       PLUS(A1, S1);
+       PLUS(A2, S2);
+       PLUS(A3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       PLUS(B0, S0);
+       PLUS(B1, S1);
+       PLUS(B2, S2);
+       PLUS(B3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       vperm A0, A0, A0, TMP2;
+       vperm A1, A1, A1, TMP2;
+       vperm A2, A2, A2, TMP2;
+       vperm A3, A3, A3, TMP2;
+       vperm B0, B0, B0, TMP2;
+       vperm B1, B1, B1, TMP2;
+       vperm B2, B2, B2, TMP2;
+       vperm B3, B3, B3, TMP2;
+
+       XOR(IO0, A0);
+       XOR(IO1, A1);
+       XOR(IO2, A2);
+       XOR(IO3, A3);
+       XOR(IO4, B0);
+       XOR(IO5, B1);
+       XOR(IO6, B2);
+       XOR(IO7, B3);
+       vstm IO0, IO7, 0(DST);
+
+       aghi SRC, 128;
+       aghi DST, 128;
+
+       clgijhe NBLKS, 2, .Lloop2;
+
+       CLEAR(B0);
+       CLEAR(B1);
+       CLEAR(B2);
+       CLEAR(B3);
+
+.balign 4
+.Lloop1:
+       clgijl NBLKS, 1, .Ldone;
+
+       /* Process one chacha20 block.*/
+       lghi ROUND, (20 / 2);
+       vlr A0, S0;
+       vlr A1, S1;
+       vlr A2, S2;
+       vlr A3, S3;
+
+       slgfi NBLKS, 1;
+
+.balign 4
+.Lround2_1:
+       QUARTERROUND4(3, 2, 1);
+       QUARTERROUND4(1, 2, 3);
+       brct ROUND, .Lround2_1;
+
+       vlm IO0, IO3, 0(SRC);
+
+       PLUS(A0, S0);
+       PLUS(A1, S1);
+       PLUS(A2, S2);
+       PLUS(A3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+
+       vperm A0, A0, A0, TMP2;
+       vperm A1, A1, A1, TMP2;
+       vperm A2, A2, A2, TMP2;
+       vperm A3, A3, A3, TMP2;
+       XOR(IO0, A0);
+       XOR(IO1, A1);
+       XOR(IO2, A2);
+       XOR(IO3, A3);
+       vstm IO0, IO3, 0(DST);
+
+       aghi SRC, 64;
+       aghi DST, 64;
+
+       clgijhe NBLKS, 1, .Lloop1;
+
+.balign 4
+.Ldone:
+       /* Store counter. */
+       vperm S3, S3, S3, TMP0;
+       vst S3, (48)(INPUT);
+
+       /* Clear the used vector registers. */
+       CLEAR(A0);
+       CLEAR(A1);
+       CLEAR(A2);
+       CLEAR(A3);
+       CLEAR(IO0);
+       CLEAR(IO1);
+       CLEAR(IO2);
+       CLEAR(IO3);
+       CLEAR(IO4);
+       CLEAR(IO5);
+       CLEAR(IO6);
+       CLEAR(IO7);
+       CLEAR(TMP0);
+       CLEAR(TMP1);
+       CLEAR(TMP2);
+
+       END_STACK(%r7);
+       xgr %r2, %r2;
+       br %r14;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_s390x_vx_blocks4_2_1,
+    .-_gcry_chacha20_s390x_vx_blocks4_2_1;)
+
+/**********************************************************************
+  4-way && 2-way && 1-way stitched chacha20-poly1305 ("horizontal")
+ **********************************************************************/
+
+.balign 8
+.globl _gcry_chacha20_poly1305_s390x_vx_blocks4_2_1
+ELF(.type _gcry_chacha20_poly1305_s390x_vx_blocks4_2_1,@function;)
+
+_gcry_chacha20_poly1305_s390x_vx_blocks4_2_1:
+       /* input:
+        *       %r2: input
+        *       %r3: dst
+        *       %r4: src
+        *       %r5: nblks
+        *       %r6: poly1305 state
+        * 160(%r15): poly1305 src
+        */
+       CFI_STARTPROC();
+
+       START_STACK(%r14);
+       lgr NBLKS, %r5;
+
+       /* Load constants. */
+       larl %r8, .Lconsts;
+       vl TMP0, (.Lwordswap - .Lconsts)(%r8);
+       vl TMP1, (.Lone - .Lconsts)(%r8);
+       vl TMP2, (.Lbswap128 - .Lconsts)(%r8);
+
+       /* Load state. */
+       vlm S0, S3, 0(INPUT);
+       vperm S0, S0, S0, TMP0;
+       vperm S1, S1, S1, TMP0;
+       vperm S2, S2, S2, TMP0;
+       vperm S3, S3, S3, TMP0;
+
+       /* Store parameters to stack. */
+       stmg %r2, %r6, STACK_INPUT(%r15);
+
+       lgr POLY_RSTATE, %r6;
+       lgr NBLKS, %r5;
+
+       lg POLY_RSRC, 0(%r15);
+       lg POLY_RSRC, 160(POLY_RSRC);
+       stg POLY_RSRC, STACK_POSRC(%r15);
+
+       /* Load poly1305 state */
+       POLY1305_LOAD_STATE();
+
+       clgijl NBLKS, 4, .Lloop2_poly;
+
+.balign 4
+.Lloop4_poly:
+       /* Process four chacha20 blocks and 16 poly1305 blocks. */
+       vlr TMP3, S3;
+       lghi ROUND, (20 / 4);
+       vlr A0, S0;
+       vlr A1, S1;
+       vlr A2, S2;
+       vlr A3, TMP3;
+       vag TMP3, TMP3, TMP1;
+       vlr B0, S0;
+       vlr B1, S1;
+       vlr B2, S2;
+       vlr B3, TMP3;
+       vag TMP3, TMP3, TMP1;
+       vlr C0, S0;
+       vlr C1, S1;
+       vlr C2, S2;
+       vlr C3, TMP3;
+       vlr D0, S0;
+       vlr D1, S1;
+       vlr D2, S2;
+       vag D3, TMP3, TMP1;
+
+       slgfi NBLKS, 4;
+
+.balign 4
+.Lround4_4_poly:
+       /* Total 15 poly1305 blocks processed by this loop. */
+       QUARTERROUND4_4_POLY(3, 2, 1,
+                            POLY1305_BLOCK_PART1(0 * 16),
+                            POLY1305_BLOCK_PART2(),
+                            POLY1305_BLOCK_PART3(),
+                            POLY1305_BLOCK_PART4(),
+                            POLY1305_BLOCK_PART5(),
+                            POLY1305_BLOCK_PART6());
+       QUARTERROUND4_4_POLY(1, 2, 3,
+                            POLY1305_BLOCK_PART7(),
+                            POLY1305_BLOCK_PART8(),
+                            POLY1305_BLOCK_PART1(1 * 16),
+                            POLY1305_BLOCK_PART2(),
+                            POLY1305_BLOCK_PART3(),
+                            POLY1305_BLOCK_PART4());
+       QUARTERROUND4_4_POLY(3, 2, 1,
+                            POLY1305_BLOCK_PART5(),
+                            POLY1305_BLOCK_PART6(),
+                            POLY1305_BLOCK_PART7(),
+                            POLY1305_BLOCK_PART8(),
+                            POLY1305_BLOCK_PART1(2 * 16);
+                             INC_POLY1305_SRC(3 * 16),
+                            POLY1305_BLOCK_PART2());
+       QUARTERROUND4_4_POLY(1, 2, 3,
+                            POLY1305_BLOCK_PART3(),
+                            POLY1305_BLOCK_PART4(),
+                            POLY1305_BLOCK_PART5(),
+                            POLY1305_BLOCK_PART6(),
+                            POLY1305_BLOCK_PART7(),
+                            POLY1305_BLOCK_PART8());
+       brctg ROUND, .Lround4_4_poly;
+
+       POLY1305_BLOCK_PART1(0 * 16);
+       INC_POLY1305_SRC(1 * 16);
+       stg POLY_RSRC, STACK_POSRC(%r15);
+
+       lg %r14, STACK_SRC(%r15);
+       vlm IO0, IO7, 0(%r14);
+
+       PLUS(A0, S0);
+       PLUS(A1, S1);
+       PLUS(A2, S2);
+       PLUS(A3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       POLY1305_BLOCK_PART2();
+       PLUS(B0, S0);
+       PLUS(B1, S1);
+       PLUS(B2, S2);
+       PLUS(B3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       POLY1305_BLOCK_PART3();
+       vperm A0, A0, A0, TMP2;
+       vperm A1, A1, A1, TMP2;
+       vperm A2, A2, A2, TMP2;
+       vperm A3, A3, A3, TMP2;
+       vperm B0, B0, B0, TMP2;
+       vperm B1, B1, B1, TMP2;
+       vperm B2, B2, B2, TMP2;
+       vperm B3, B3, B3, TMP2;
+       POLY1305_BLOCK_PART4();
+       PLUS(C0, S0);
+       PLUS(C1, S1);
+       PLUS(C2, S2);
+       PLUS(C3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       PLUS(D0, S0);
+       PLUS(D1, S1);
+       PLUS(D2, S2);
+       PLUS(D3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       POLY1305_BLOCK_PART5();
+       vperm C0, C0, C0, TMP2;
+       vperm C1, C1, C1, TMP2;
+       vperm C2, C2, C2, TMP2;
+       vperm C3, C3, C3, TMP2;
+       vperm D0, D0, D0, TMP2;
+       vperm D1, D1, D1, TMP2;
+       vperm D2, D2, D2, TMP2;
+       vperm D3, D3, D3, TMP2;
+
+       POLY1305_BLOCK_PART6();
+       XOR(IO0, A0);
+       XOR(IO1, A1);
+       XOR(IO2, A2);
+       XOR(IO3, A3);
+       XOR(IO4, B0);
+       XOR(IO5, B1);
+       XOR(IO6, B2);
+       XOR(IO7, B3);
+       vlm A0, B3, 128(%r14);
+       aghi %r14, 256;
+       stg %r14, STACK_SRC(%r15);
+
+       lg %r14, STACK_DST(%r15);
+       POLY1305_BLOCK_PART7();
+       vstm IO0, IO7, 0(%r14);
+       XOR(A0, C0);
+       XOR(A1, C1);
+       XOR(A2, C2);
+       XOR(A3, C3);
+       XOR(B0, D0);
+       XOR(B1, D1);
+       XOR(B2, D2);
+       XOR(B3, D3);
+       POLY1305_BLOCK_PART8();
+       vstm A0, B3, 128(%r14);
+       aghi %r14, 256;
+       stg %r14, STACK_DST(%r15);
+
+       lg POLY_RSRC, STACK_POSRC(%r15);
+
+       clgijhe NBLKS, 4, .Lloop4_poly;
+
+       CLEAR(C0);
+       CLEAR(C1);
+       CLEAR(C2);
+       CLEAR(C3);
+       CLEAR(D0);
+       CLEAR(D1);
+       CLEAR(D2);
+       CLEAR(D3);
+
+.balign 4
+.Lloop2_poly:
+       clgijl NBLKS, 2, .Lloop1_poly;
+
+       /* Process two chacha20 and eight poly1305 blocks. */
+       lghi ROUND, ((20 - 4) / 2);
+       vlr A0, S0;
+       vlr A1, S1;
+       vlr A2, S2;
+       vlr A3, S3;
+       vlr B0, S0;
+       vlr B1, S1;
+       vlr B2, S2;
+       vag B3, S3, TMP1;
+
+       slgfi NBLKS, 2;
+
+.balign 4
+.Lround4_2_poly:
+       /* Total eight poly1305 blocks processed by this loop. */
+       QUARTERROUND4_2_POLY(3, 2, 1,
+                            POLY1305_BLOCK_PART1(0 * 16),
+                            POLY1305_BLOCK_PART2(),
+                            POLY1305_BLOCK_PART3(),
+                            POLY1305_BLOCK_PART4());
+                            INC_POLY1305_SRC(1 * 16);
+       QUARTERROUND4_2_POLY(1, 2, 3,
+                            POLY1305_BLOCK_PART5(),
+                            POLY1305_BLOCK_PART6(),
+                            POLY1305_BLOCK_PART7(),
+                            POLY1305_BLOCK_PART8());
+       brctg ROUND, .Lround4_2_poly;
+
+       stg POLY_RSRC, STACK_POSRC(%r15);
+       lg %r14, STACK_SRC(%r15);
+
+       QUARTERROUND4_2(3, 2, 1);
+       QUARTERROUND4_2(1, 2, 3);
+       QUARTERROUND4_2(3, 2, 1);
+       QUARTERROUND4_2(1, 2, 3);
+
+       vlm IO0, IO7, 0(%r14);
+       aghi %r14, 128;
+       stg %r14, STACK_SRC(%r15);
+
+       PLUS(A0, S0);
+       PLUS(A1, S1);
+       PLUS(A2, S2);
+       PLUS(A3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       PLUS(B0, S0);
+       PLUS(B1, S1);
+       PLUS(B2, S2);
+       PLUS(B3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+       vperm A0, A0, A0, TMP2;
+       vperm A1, A1, A1, TMP2;
+       vperm A2, A2, A2, TMP2;
+       vperm A3, A3, A3, TMP2;
+       vperm B0, B0, B0, TMP2;
+       vperm B1, B1, B1, TMP2;
+       vperm B2, B2, B2, TMP2;
+       vperm B3, B3, B3, TMP2;
+
+       lg %r14, STACK_DST(%r15);
+       XOR(IO0, A0);
+       XOR(IO1, A1);
+       XOR(IO2, A2);
+       XOR(IO3, A3);
+       XOR(IO4, B0);
+       XOR(IO5, B1);
+       XOR(IO6, B2);
+       XOR(IO7, B3);
+       vstm IO0, IO7, 0(%r14);
+       aghi %r14, 128;
+       stg %r14, STACK_DST(%r15);
+
+       lg POLY_RSRC, STACK_POSRC(%r15);
+
+       clgijhe NBLKS, 2, .Lloop2_poly;
+
+       CLEAR(B0);
+       CLEAR(B1);
+       CLEAR(B2);
+       CLEAR(B3);
+
+.balign 4
+.Lloop1_poly:
+       clgijl NBLKS, 1, .Ldone_poly;
+
+       /* Process one chacha20 block and four poly1305 blocks.*/
+       lghi ROUND, ((20 - 4) / 4);
+       vlr A0, S0;
+       vlr A1, S1;
+       vlr A2, S2;
+       vlr A3, S3;
+
+       slgfi NBLKS, 1;
+
+.balign 4
+.Lround4_1_poly:
+       /* Total four poly1305 blocks processed by this loop. */
+       QUARTERROUND4_POLY(3, 2, 1,
+                          POLY1305_BLOCK_PART1(0 * 16),
+                          POLY1305_BLOCK_PART2());
+                          INC_POLY1305_SRC(1 * 16);
+       QUARTERROUND4_POLY(1, 2, 3,
+                          POLY1305_BLOCK_PART3(),
+                          POLY1305_BLOCK_PART4());
+       QUARTERROUND4_POLY(3, 2, 1,
+                          POLY1305_BLOCK_PART5(),
+                          POLY1305_BLOCK_PART6());
+       QUARTERROUND4_POLY(1, 2, 3,
+                          POLY1305_BLOCK_PART7(),
+                          POLY1305_BLOCK_PART8());
+       brct ROUND, .Lround4_1_poly;
+
+       stg POLY_RSRC, STACK_POSRC(%r15);
+       lg %r14, STACK_SRC(%r15);
+
+       QUARTERROUND4(3, 2, 1);
+       QUARTERROUND4(1, 2, 3);
+       QUARTERROUND4(3, 2, 1);
+       QUARTERROUND4(1, 2, 3);
+
+       vlm IO0, IO3, 0(%r14);
+       aghi %r14, 64;
+       stg %r14, STACK_SRC(%r15);
+
+       PLUS(A0, S0);
+       PLUS(A1, S1);
+       PLUS(A2, S2);
+       PLUS(A3, S3);
+       vag S3, S3, TMP1; /* Update counter. */
+
+       lg %r14, STACK_DST(%r15);
+       vperm A0, A0, A0, TMP2;
+       vperm A1, A1, A1, TMP2;
+       vperm A2, A2, A2, TMP2;
+       vperm A3, A3, A3, TMP2;
+       XOR(IO0, A0);
+       XOR(IO1, A1);
+       XOR(IO2, A2);
+       XOR(IO3, A3);
+       vstm IO0, IO3, 0(%r14);
+       aghi %r14, 64;
+       stg %r14, STACK_DST(%r15);
+
+       lg POLY_RSRC, STACK_POSRC(%r15);
+
+       clgijhe NBLKS, 1, .Lloop1_poly;
+
+.balign 4
+.Ldone_poly:
+       /* Store poly1305 state */
+       lg POLY_RSTATE, STACK_POCTX(%r15);
+       POLY1305_STORE_STATE();
+
+       /* Store counter. */
+       lg INPUT, STACK_INPUT(%r15);
+       vperm S3, S3, S3, TMP0;
+       vst S3, (48)(INPUT);
+
+       /* Clear the used vector registers. */
+       CLEAR(A0);
+       CLEAR(A1);
+       CLEAR(A2);
+       CLEAR(A3);
+       CLEAR(IO0);
+       CLEAR(IO1);
+       CLEAR(IO2);
+       CLEAR(IO3);
+       CLEAR(IO4);
+       CLEAR(IO5);
+       CLEAR(IO6);
+       CLEAR(IO7);
+       CLEAR(TMP0);
+       CLEAR(TMP1);
+       CLEAR(TMP2);
+
+       END_STACK(%r14);
+       xgr %r2, %r2;
+       br %r14;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_poly1305_s390x_vx_blocks4_2_1,
+    .-_gcry_chacha20_poly1305_s390x_vx_blocks4_2_1;)
+
+/**********************************************************************
+  8-way chacha20 ("vertical")
+ **********************************************************************/
+
+#define QUARTERROUND4_V8_POLY(x0,x1,x2,x3,x4,x5,x6,x7,\
+                             x8,x9,x10,x11,x12,x13,x14,x15,\
+                             y0,y1,y2,y3,y4,y5,y6,y7,\
+                             y8,y9,y10,y11,y12,y13,y14,y15,\
+                             op1,op2,op3,op4,op5,op6,op7,op8,\
+                             op9,op10,op11,op12) \
+       op1;                                                    \
+       PLUS(x0, x1); PLUS(x4, x5);                             \
+       PLUS(x8, x9); PLUS(x12, x13);                           \
+       PLUS(y0, y1); PLUS(y4, y5);                             \
+       PLUS(y8, y9); PLUS(y12, y13);                           \
+           op2;                                                \
+           XOR(x3, x0);  XOR(x7, x4);                          \
+           XOR(x11, x8); XOR(x15, x12);                        \
+           XOR(y3, y0);  XOR(y7, y4);                          \
+           XOR(y11, y8); XOR(y15, y12);                        \
+               op3;                                            \
+               ROTATE(x3, 16); ROTATE(x7, 16);                 \
+               ROTATE(x11, 16); ROTATE(x15, 16);               \
+               ROTATE(y3, 16); ROTATE(y7, 16);                 \
+               ROTATE(y11, 16); ROTATE(y15, 16);               \
+       op4;                                                    \
+       PLUS(x2, x3); PLUS(x6, x7);                             \
+       PLUS(x10, x11); PLUS(x14, x15);                         \
+       PLUS(y2, y3); PLUS(y6, y7);                             \
+       PLUS(y10, y11); PLUS(y14, y15);                         \
+           op5;                                                \
+           XOR(x1, x2); XOR(x5, x6);                           \
+           XOR(x9, x10); XOR(x13, x14);                        \
+           XOR(y1, y2); XOR(y5, y6);                           \
+           XOR(y9, y10); XOR(y13, y14);                        \
+               op6;                                            \
+               ROTATE(x1,12); ROTATE(x5,12);                   \
+               ROTATE(x9,12); ROTATE(x13,12);                  \
+               ROTATE(y1,12); ROTATE(y5,12);                   \
+               ROTATE(y9,12); ROTATE(y13,12);                  \
+       op7;                                                    \
+       PLUS(x0, x1); PLUS(x4, x5);                             \
+       PLUS(x8, x9); PLUS(x12, x13);                           \
+       PLUS(y0, y1); PLUS(y4, y5);                             \
+       PLUS(y8, y9); PLUS(y12, y13);                           \
+           op8;                                                \
+           XOR(x3, x0); XOR(x7, x4);                           \
+           XOR(x11, x8); XOR(x15, x12);                        \
+           XOR(y3, y0); XOR(y7, y4);                           \
+           XOR(y11, y8); XOR(y15, y12);                        \
+               op9;                                            \
+               ROTATE(x3,8); ROTATE(x7,8);                     \
+               ROTATE(x11,8); ROTATE(x15,8);                   \
+               ROTATE(y3,8); ROTATE(y7,8);                     \
+               ROTATE(y11,8); ROTATE(y15,8);                   \
+       op10;                                                   \
+       PLUS(x2, x3); PLUS(x6, x7);                             \
+       PLUS(x10, x11); PLUS(x14, x15);                         \
+       PLUS(y2, y3); PLUS(y6, y7);                             \
+       PLUS(y10, y11); PLUS(y14, y15);                         \
+           op11;                                               \
+           XOR(x1, x2); XOR(x5, x6);                           \
+           XOR(x9, x10); XOR(x13, x14);                        \
+           XOR(y1, y2); XOR(y5, y6);                           \
+           XOR(y9, y10); XOR(y13, y14);                        \
+               op12;                                           \
+               ROTATE(x1,7); ROTATE(x5,7);                     \
+               ROTATE(x9,7); ROTATE(x13,7);                    \
+               ROTATE(y1,7); ROTATE(y5,7);                     \
+               ROTATE(y9,7); ROTATE(y13,7);
+
+#define QUARTERROUND4_V8(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,\
+                        y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12,y13,y14,y15) \
+       QUARTERROUND4_V8_POLY(x0,x1,x2,x3,x4,x5,x6,x7,\
+                             x8,x9,x10,x11,x12,x13,x14,x15,\
+                             y0,y1,y2,y3,y4,y5,y6,y7,\
+                             y8,y9,y10,y11,y12,y13,y14,y15,\
+                             ,,,,,,,,,,,)
+
+#define TRANSPOSE_4X4_2(v0,v1,v2,v3,va,vb,vc,vd,tmp0,tmp1,tmp2,tmpa,tmpb,tmpc) \
+         vmrhf tmp0, v0, v1;                                   \
+         vmrhf tmp1, v2, v3;                                   \
+         vmrlf tmp2, v0, v1;                                   \
+         vmrlf   v3, v2, v3;                                   \
+         vmrhf tmpa, va, vb;                                   \
+         vmrhf tmpb, vc, vd;                                   \
+         vmrlf tmpc, va, vb;                                   \
+         vmrlf   vd, vc, vd;                                   \
+         vpdi v0, tmp0, tmp1, 0;                               \
+         vpdi v1, tmp0, tmp1, 5;                               \
+         vpdi v2, tmp2,   v3, 0;                               \
+         vpdi v3, tmp2,   v3, 5;                               \
+         vpdi va, tmpa, tmpb, 0;                               \
+         vpdi vb, tmpa, tmpb, 5;                               \
+         vpdi vc, tmpc,   vd, 0;                               \
+         vpdi vd, tmpc,   vd, 5;
+
+.balign 8
+.globl _gcry_chacha20_s390x_vx_blocks8
+ELF(.type _gcry_chacha20_s390x_vx_blocks8,@function;)
+
+_gcry_chacha20_s390x_vx_blocks8:
+       /* input:
+        *      %r2: input
+        *      %r3: dst
+        *      %r4: src
+        *      %r5: nblks (multiple of 8)
+        */
+       CFI_STARTPROC();
+
+       START_STACK(%r8);
+       lgr NBLKS, %r5;
+
+       larl %r7, .Lconsts;
+
+       /* Load counter. */
+       lg %r8, (12 * 4)(INPUT);
+       rllg %r8, %r8, 32;
+
+.balign 4
+       /* Process eight chacha20 blocks per loop. */
+.Lloop8:
+       vlm Y0, Y3, 0(INPUT);
+
+       slgfi NBLKS, 8;
+       lghi ROUND, (20 / 2);
+
+       /* Construct counter vectors X12/X13 & Y12/Y13. */
+       vl X4, (.Ladd_counter_0123 - .Lconsts)(%r7);
+       vl Y4, (.Ladd_counter_4567 - .Lconsts)(%r7);
+       vrepf Y12, Y3, 0;
+       vrepf Y13, Y3, 1;
+       vaccf X5, Y12, X4;
+       vaccf Y5, Y12, Y4;
+       vaf X12, Y12, X4;
+       vaf Y12, Y12, Y4;
+       vaf X13, Y13, X5;
+       vaf Y13, Y13, Y5;
+
+       vrepf X0, Y0, 0;
+       vrepf X1, Y0, 1;
+       vrepf X2, Y0, 2;
+       vrepf X3, Y0, 3;
+       vrepf X4, Y1, 0;
+       vrepf X5, Y1, 1;
+       vrepf X6, Y1, 2;
+       vrepf X7, Y1, 3;
+       vrepf X8, Y2, 0;
+       vrepf X9, Y2, 1;
+       vrepf X10, Y2, 2;
+       vrepf X11, Y2, 3;
+       vrepf X14, Y3, 2;
+       vrepf X15, Y3, 3;
+
+       /* Store counters for blocks 0-7. */
+       vstm X12, X13, (STACK_CTR + 0 * 16)(%r15);
+       vstm Y12, Y13, (STACK_CTR + 2 * 16)(%r15);
+
+       vlr Y0, X0;
+       vlr Y1, X1;
+       vlr Y2, X2;
+       vlr Y3, X3;
+       vlr Y4, X4;
+       vlr Y5, X5;
+       vlr Y6, X6;
+       vlr Y7, X7;
+       vlr Y8, X8;
+       vlr Y9, X9;
+       vlr Y10, X10;
+       vlr Y11, X11;
+       vlr Y14, X14;
+       vlr Y15, X15;
+
+       /* Update and store counter. */
+       agfi %r8, 8;
+       rllg %r5, %r8, 32;
+       stg %r5, (12 * 4)(INPUT);
+
+.balign 4
+.Lround2_8:
+       QUARTERROUND4_V8(X0, X4,  X8, X12,   X1, X5,  X9, X13,
+                        X2, X6, X10, X14,   X3, X7, X11, X15,
+                        Y0, Y4,  Y8, Y12,   Y1, Y5,  Y9, Y13,
+                        Y2, Y6, Y10, Y14,   Y3, Y7, Y11, Y15);
+       QUARTERROUND4_V8(X0, X5, X10, X15,   X1, X6, X11, X12,
+                        X2, X7,  X8, X13,   X3, X4,  X9, X14,
+                        Y0, Y5, Y10, Y15,   Y1, Y6, Y11, Y12,
+                        Y2, Y7,  Y8, Y13,   Y3, Y4,  Y9, Y14);
+       brctg ROUND, .Lround2_8;
+
+       /* Store blocks 4-7. */
+       vstm Y0, Y15, STACK_Y0_Y15(%r15);
+
+       /* Load counters for blocks 0-3. */
+       vlm Y0, Y1, (STACK_CTR + 0 * 16)(%r15);
+
+       lghi ROUND, 1;
+       j .Lfirst_output_4blks_8;
+
+.balign 4
+.Lsecond_output_4blks_8:
+       /* Load blocks 4-7. */
+       vlm X0, X15, STACK_Y0_Y15(%r15);
+
+       /* Load counters for blocks 4-7. */
+       vlm Y0, Y1, (STACK_CTR + 2 * 16)(%r15);
+
+       lghi ROUND, 0;
+
+.balign 4
+       /* Output four chacha20 blocks per loop. */
+.Lfirst_output_4blks_8:
+       vlm Y12, Y15, 0(INPUT);
+       PLUS(X12, Y0);
+       PLUS(X13, Y1);
+       vrepf Y0, Y12, 0;
+       vrepf Y1, Y12, 1;
+       vrepf Y2, Y12, 2;
+       vrepf Y3, Y12, 3;
+       vrepf Y4, Y13, 0;
+       vrepf Y5, Y13, 1;
+       vrepf Y6, Y13, 2;
+       vrepf Y7, Y13, 3;
+       vrepf Y8, Y14, 0;
+       vrepf Y9, Y14, 1;
+       vrepf Y10, Y14, 2;
+       vrepf Y11, Y14, 3;
+       vrepf Y14, Y15, 2;
+       vrepf Y15, Y15, 3;
+       PLUS(X0, Y0);
+       PLUS(X1, Y1);
+       PLUS(X2, Y2);
+       PLUS(X3, Y3);
+       PLUS(X4, Y4);
+       PLUS(X5, Y5);
+       PLUS(X6, Y6);
+       PLUS(X7, Y7);
+       PLUS(X8, Y8);
+       PLUS(X9, Y9);
+       PLUS(X10, Y10);
+       PLUS(X11, Y11);
+       PLUS(X14, Y14);
+       PLUS(X15, Y15);
+
+       vl Y15, (.Lbswap32 - .Lconsts)(%r7);
+       TRANSPOSE_4X4_2(X0, X1, X2, X3, X4, X5, X6, X7,
+                       Y9, Y10, Y11, Y12, Y13, Y14);
+       TRANSPOSE_4X4_2(X8, X9, X10, X11, X12, X13, X14, X15,
+                       Y9, Y10, Y11, Y12, Y13, Y14);
+
+       vlm Y0, Y14, 0(SRC);
+       vperm X0, X0, X0, Y15;
+       vperm X1, X1, X1, Y15;
+       vperm X2, X2, X2, Y15;
+       vperm X3, X3, X3, Y15;
+       vperm X4, X4, X4, Y15;
+       vperm X5, X5, X5, Y15;
+       vperm X6, X6, X6, Y15;
+       vperm X7, X7, X7, Y15;
+       vperm X8, X8, X8, Y15;
+       vperm X9, X9, X9, Y15;
+       vperm X10, X10, X10, Y15;
+       vperm X11, X11, X11, Y15;
+       vperm X12, X12, X12, Y15;
+       vperm X13, X13, X13, Y15;
+       vperm X14, X14, X14, Y15;
+       vperm X15, X15, X15, Y15;
+       vl Y15, (15 * 16)(SRC);
+
+       XOR(Y0, X0);
+       XOR(Y1, X4);
+       XOR(Y2, X8);
+       XOR(Y3, X12);
+       XOR(Y4, X1);
+       XOR(Y5, X5);
+       XOR(Y6, X9);
+       XOR(Y7, X13);
+       XOR(Y8, X2);
+       XOR(Y9, X6);
+       XOR(Y10, X10);
+       XOR(Y11, X14);
+       XOR(Y12, X3);
+       XOR(Y13, X7);
+       XOR(Y14, X11);
+       XOR(Y15, X15);
+       vstm Y0, Y15, 0(DST);
+
+       aghi SRC, 256;
+       aghi DST, 256;
+
+       clgije ROUND, 1, .Lsecond_output_4blks_8;
+
+       clgijhe NBLKS, 8, .Lloop8;
+
+       /* Clear the used vector registers. */
+       DST_8(CLEAR, 0, _);
+       DST_8(CLEAR, 1, _);
+       DST_8(CLEAR, 2, _);
+       DST_8(CLEAR, 3, _);
+
+       /* Clear sensitive data in stack. */
+       vlm Y0, Y15, STACK_Y0_Y15(%r15);
+       vlm Y0, Y3, STACK_CTR(%r15);
+
+       END_STACK(%r8);
+       xgr %r2, %r2;
+       br %r14;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_s390x_vx_blocks8,
+    .-_gcry_chacha20_s390x_vx_blocks8;)
+
+/**********************************************************************
+  8-way stitched chacha20-poly1305 ("vertical")
+ **********************************************************************/
+
+.balign 8
+.globl _gcry_chacha20_poly1305_s390x_vx_blocks8
+ELF(.type _gcry_chacha20_poly1305_s390x_vx_blocks8,@function;)
+
+_gcry_chacha20_poly1305_s390x_vx_blocks8:
+       /* input:
+        *       %r2: input
+        *       %r3: dst
+        *       %r4: src
+        *       %r5: nblks (multiple of 8)
+        *       %r6: poly1305 state
+        * 160(%r15): poly1305 src
+        */
+       CFI_STARTPROC();
+
+       START_STACK(%r14);
+
+       /* Store parameters to stack. */
+       stmg %r2, %r6, STACK_INPUT(%r15);
+
+       lgr POLY_RSTATE, %r6;
+       lgr NBLKS, %r5;
+
+       lg POLY_RSRC, 0(%r15);
+       lg POLY_RSRC, 160(POLY_RSRC);
+       stg POLY_RSRC, STACK_POSRC(%r15);
+
+       /* Load poly1305 state */
+       POLY1305_LOAD_STATE();
+
+.balign 4
+       /* Process eight chacha20 blocks and 32 poly1305 blocks per loop. */
+.Lloop8_poly:
+       lg INPUT, STACK_INPUT(%r15);
+       larl %r8, .Lconsts;
+
+       vlm Y0, Y3, 0(INPUT);
+
+       slgfi NBLKS, 8;
+       lghi ROUND, (20 / 2);
+
+       /* Construct counter vectors X12/X13 & Y12/Y13. */
+       vl X4, (.Ladd_counter_0123 - .Lconsts)(%r8);
+       vl Y4, (.Ladd_counter_4567 - .Lconsts)(%r8);
+       lg %r8, (12 * 4)(INPUT); /* Update counter. */
+       vrepf Y12, Y3, 0;
+       vrepf Y13, Y3, 1;
+       vaccf X5, Y12, X4;
+       vaccf Y5, Y12, Y4;
+       vaf X12, Y12, X4;
+       vaf Y12, Y12, Y4;
+       vaf X13, Y13, X5;
+       vaf Y13, Y13, Y5;
+       rllg %r8, %r8, 32;
+
+       vrepf X0, Y0, 0;
+       vrepf X1, Y0, 1;
+       vrepf X2, Y0, 2;
+       vrepf X3, Y0, 3;
+       vrepf X4, Y1, 0;
+       vrepf X5, Y1, 1;
+       vrepf X6, Y1, 2;
+       vrepf X7, Y1, 3;
+       vrepf X8, Y2, 0;
+       vrepf X9, Y2, 1;
+       vrepf X10, Y2, 2;
+       vrepf X11, Y2, 3;
+       vrepf X14, Y3, 2;
+       vrepf X15, Y3, 3;
+       agfi %r8, 8;
+
+       /* Store counters for blocks 0-7. */
+       vstm X12, X13, (STACK_CTR + 0 * 16)(%r15);
+       vstm Y12, Y13, (STACK_CTR + 2 * 16)(%r15);
+       rllg %r8, %r8, 32;
+
+       vlr Y0, X0;
+       vlr Y1, X1;
+       vlr Y2, X2;
+       vlr Y3, X3;
+       vlr Y4, X4;
+       vlr Y5, X5;
+       vlr Y6, X6;
+       vlr Y7, X7;
+       vlr Y8, X8;
+       vlr Y9, X9;
+       vlr Y10, X10;
+       vlr Y11, X11;
+       vlr Y14, X14;
+       vlr Y15, X15;
+       stg %r8, (12 * 4)(INPUT);
+
+.balign 4
+.Lround2_8_poly:
+       /* Total 30 poly1305 blocks processed by this loop. */
+       QUARTERROUND4_V8_POLY(X0, X4,  X8, X12,   X1, X5,  X9, X13,
+                             X2, X6, X10, X14,   X3, X7, X11, X15,
+                             Y0, Y4,  Y8, Y12,   Y1, Y5,  Y9, Y13,
+                             Y2, Y6, Y10, Y14,   Y3, Y7, Y11, Y15,
+                             POLY1305_BLOCK_PART1(0 * 16),
+                             POLY1305_BLOCK_PART2(),
+                             POLY1305_BLOCK_PART3(),
+                             POLY1305_BLOCK_PART4(),
+                             POLY1305_BLOCK_PART5(),
+                             POLY1305_BLOCK_PART6(),
+                             POLY1305_BLOCK_PART7(),
+                             POLY1305_BLOCK_PART8(),
+                             POLY1305_BLOCK_PART1(1 * 16),
+                             POLY1305_BLOCK_PART2(),
+                             POLY1305_BLOCK_PART3(),
+                             POLY1305_BLOCK_PART4());
+       QUARTERROUND4_V8_POLY(X0, X5, X10, X15,   X1, X6, X11, X12,
+                             X2, X7,  X8, X13,   X3, X4,  X9, X14,
+                             Y0, Y5, Y10, Y15,   Y1, Y6, Y11, Y12,
+                             Y2, Y7,  Y8, Y13,   Y3, Y4,  Y9, Y14,
+                             POLY1305_BLOCK_PART5(),
+                             POLY1305_BLOCK_PART6(),
+                             POLY1305_BLOCK_PART7(),
+                             POLY1305_BLOCK_PART8(),
+                             POLY1305_BLOCK_PART1(2 * 16);
+                               INC_POLY1305_SRC(3 * 16),
+                             POLY1305_BLOCK_PART2(),
+                             POLY1305_BLOCK_PART3(),
+                             POLY1305_BLOCK_PART4(),
+                             POLY1305_BLOCK_PART5(),
+                             POLY1305_BLOCK_PART6(),
+                             POLY1305_BLOCK_PART7(),
+                             POLY1305_BLOCK_PART8());
+       brctg ROUND, .Lround2_8_poly;
+
+       POLY1305_BLOCK_PART1(0 * 16);
+
+       /* Store blocks 4-7. */
+       vstm Y0, Y15, STACK_Y0_Y15(%r15);
+
+       /* Load counters for blocks 0-3. */
+       vlm Y0, Y1, (STACK_CTR + 0 * 16)(%r15);
+
+       stg POLY_RSRC, STACK_POSRC(%r15); /* %r14 used for INPUT/SRC/DST pointer. */
+
+       lghi ROUND, 1;
+       j .Lfirst_output_4blks_8_poly;
+
+.balign 4
+.Lsecond_output_4blks_8_poly:
+
+       POLY1305_BLOCK_PART1(1 * 16);
+
+       /* Load blocks 4-7. */
+       vlm X0, X15, STACK_Y0_Y15(%r15);
+
+       /* Load counters for blocks 4-7. */
+       vlm Y0, Y1, (STACK_CTR + 2 * 16)(%r15);
+
+       INC_POLY1305_SRC(2 * 16);
+       stg POLY_RSRC, STACK_POSRC(%r15); /* %r14 used for INPUT/SRC/DST pointer. */
+
+       lghi ROUND, 0;
+
+.balign 4
+       /* Output four chacha20 blocks and one poly1305 block per loop. */
+.Lfirst_output_4blks_8_poly:
+       lg %r14, STACK_INPUT(%r15);
+       vlm Y12, Y15, 0(%r14);
+       POLY1305_BLOCK_PART2();
+       PLUS(X12, Y0);
+       PLUS(X13, Y1);
+       vrepf Y0, Y12, 0;
+       vrepf Y1, Y12, 1;
+       vrepf Y2, Y12, 2;
+       vrepf Y3, Y12, 3;
+       vrepf Y4, Y13, 0;
+       vrepf Y5, Y13, 1;
+       vrepf Y6, Y13, 2;
+       vrepf Y7, Y13, 3;
+       vrepf Y8, Y14, 0;
+       vrepf Y9, Y14, 1;
+       vrepf Y10, Y14, 2;
+       vrepf Y11, Y14, 3;
+       vrepf Y14, Y15, 2;
+       vrepf Y15, Y15, 3;
+       POLY1305_BLOCK_PART3();
+       PLUS(X0, Y0);
+       PLUS(X1, Y1);
+       PLUS(X2, Y2);
+       PLUS(X3, Y3);
+       PLUS(X4, Y4);
+       PLUS(X5, Y5);
+       PLUS(X6, Y6);
+       PLUS(X7, Y7);
+       PLUS(X8, Y8);
+       PLUS(X9, Y9);
+       PLUS(X10, Y10);
+       PLUS(X11, Y11);
+       PLUS(X14, Y14);
+       PLUS(X15, Y15);
+       POLY1305_BLOCK_PART4();
+
+       larl %r14, .Lconsts;
+       vl Y15, (.Lbswap32 - .Lconsts)(%r14);
+       TRANSPOSE_4X4_2(X0, X1, X2, X3, X4, X5, X6, X7,
+                       Y9, Y10, Y11, Y12, Y13, Y14);
+       lg %r14, STACK_SRC(%r15);
+       POLY1305_BLOCK_PART5();
+       TRANSPOSE_4X4_2(X8, X9, X10, X11, X12, X13, X14, X15,
+                       Y9, Y10, Y11, Y12, Y13, Y14);
+
+       vlm Y0, Y14, 0(%r14);
+       POLY1305_BLOCK_PART6();
+       vperm X0, X0, X0, Y15;
+       vperm X1, X1, X1, Y15;
+       vperm X2, X2, X2, Y15;
+       vperm X3, X3, X3, Y15;
+       vperm X4, X4, X4, Y15;
+       vperm X5, X5, X5, Y15;
+       vperm X6, X6, X6, Y15;
+       vperm X7, X7, X7, Y15;
+       vperm X8, X8, X8, Y15;
+       vperm X9, X9, X9, Y15;
+       vperm X10, X10, X10, Y15;
+       vperm X11, X11, X11, Y15;
+       vperm X12, X12, X12, Y15;
+       vperm X13, X13, X13, Y15;
+       vperm X14, X14, X14, Y15;
+       vperm X15, X15, X15, Y15;
+       vl Y15, (15 * 16)(%r14);
+       POLY1305_BLOCK_PART7();
+
+       aghi %r14, 256;
+       stg %r14, STACK_SRC(%r15);
+       lg %r14, STACK_DST(%r15);
+
+       XOR(Y0, X0);
+       XOR(Y1, X4);
+       XOR(Y2, X8);
+       XOR(Y3, X12);
+       XOR(Y4, X1);
+       XOR(Y5, X5);
+       XOR(Y6, X9);
+       XOR(Y7, X13);
+       XOR(Y8, X2);
+       XOR(Y9, X6);
+       XOR(Y10, X10);
+       XOR(Y11, X14);
+       XOR(Y12, X3);
+       XOR(Y13, X7);
+       XOR(Y14, X11);
+       XOR(Y15, X15);
+       POLY1305_BLOCK_PART8();
+       vstm Y0, Y15, 0(%r14);
+
+       aghi %r14, 256;
+       stg %r14, STACK_DST(%r15);
+
+       lg POLY_RSRC, STACK_POSRC(%r15);
+
+       clgije ROUND, 1, .Lsecond_output_4blks_8_poly;
+
+       clgijhe NBLKS, 8, .Lloop8_poly;
+
+       /* Store poly1305 state */
+       lg POLY_RSTATE, STACK_POCTX(%r15);
+       POLY1305_STORE_STATE();
+
+       /* Clear the used vector registers */
+       DST_8(CLEAR, 0, _);
+       DST_8(CLEAR, 1, _);
+       DST_8(CLEAR, 2, _);
+       DST_8(CLEAR, 3, _);
+
+       /* Clear sensitive data in stack. */
+       vlm Y0, Y15, STACK_Y0_Y15(%r15);
+       vlm Y0, Y3, STACK_CTR(%r15);
+
+       END_STACK(%r14);
+       xgr %r2, %r2;
+       br %r14;
+       CFI_ENDPROC();
+ELF(.size _gcry_chacha20_poly1305_s390x_vx_blocks8,
+    .-_gcry_chacha20_poly1305_s390x_vx_blocks8;)
+
+#endif /*HAVE_GCC_INLINE_ASM_S390X_VX*/
+#endif /*__s390x__*/
diff --git a/cipher/chacha20-sse2-amd64.S b/cipher/chacha20-sse2-amd64.S
deleted file mode 100644 (file)
index 2b9842c..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-/* chacha20-sse2-amd64.S  -  AMD64/SSE2 implementation of ChaCha20
- *
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Based on public domain implementation by Andrew Moon at
- *  https://github.com/floodyberry/chacha-opt
- */
-
-#ifdef __x86_64__
-#include <config.h>
-
-#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && USE_CHACHA20
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-.text
-
-.align 8
-.globl _gcry_chacha20_amd64_sse2_blocks
-ELF(.type  _gcry_chacha20_amd64_sse2_blocks,@function;)
-_gcry_chacha20_amd64_sse2_blocks:
-.Lchacha_blocks_sse2_local:
-       pushq %rbx
-       pushq %rbp
-       movq %rsp, %rbp
-       andq $~63, %rsp
-       subq $512, %rsp
-       movdqu (%rdi), %xmm8
-       movdqu 16(%rdi), %xmm9
-       movdqu 32(%rdi), %xmm10
-       movdqu 48(%rdi), %xmm11
-       movq $20, %rax
-       movq $1, %r9
-       movdqa %xmm8, 0(%rsp)
-       movdqa %xmm9, 16(%rsp)
-       movdqa %xmm10, 32(%rsp)
-       movdqa %xmm11, 48(%rsp)
-       movq %rax, 64(%rsp)
-       cmpq $256, %rcx
-       jb .Lchacha_blocks_sse2_below256
-       pshufd $0x00, %xmm8, %xmm0
-       pshufd $0x55, %xmm8, %xmm1
-       pshufd $0xaa, %xmm8, %xmm2
-       pshufd $0xff, %xmm8, %xmm3
-       movdqa %xmm0, 128(%rsp)
-       movdqa %xmm1, 144(%rsp)
-       movdqa %xmm2, 160(%rsp)
-       movdqa %xmm3, 176(%rsp)
-       pshufd $0x00, %xmm9, %xmm0
-       pshufd $0x55, %xmm9, %xmm1
-       pshufd $0xaa, %xmm9, %xmm2
-       pshufd $0xff, %xmm9, %xmm3
-       movdqa %xmm0, 192(%rsp)
-       movdqa %xmm1, 208(%rsp)
-       movdqa %xmm2, 224(%rsp)
-       movdqa %xmm3, 240(%rsp)
-       pshufd $0x00, %xmm10, %xmm0
-       pshufd $0x55, %xmm10, %xmm1
-       pshufd $0xaa, %xmm10, %xmm2
-       pshufd $0xff, %xmm10, %xmm3
-       movdqa %xmm0, 256(%rsp)
-       movdqa %xmm1, 272(%rsp)
-       movdqa %xmm2, 288(%rsp)
-       movdqa %xmm3, 304(%rsp)
-       pshufd $0xaa, %xmm11, %xmm0
-       pshufd $0xff, %xmm11, %xmm1
-       movdqa %xmm0, 352(%rsp)
-       movdqa %xmm1, 368(%rsp)
-       jmp .Lchacha_blocks_sse2_atleast256
-.p2align 6,,63
-.Lchacha_blocks_sse2_atleast256:
-       movq 48(%rsp), %rax
-       leaq 1(%rax), %r8
-       leaq 2(%rax), %r9
-       leaq 3(%rax), %r10
-       leaq 4(%rax), %rbx
-       movl %eax, 320(%rsp)
-       movl %r8d, 4+320(%rsp)
-       movl %r9d, 8+320(%rsp)
-       movl %r10d, 12+320(%rsp)
-       shrq $32, %rax
-       shrq $32, %r8
-       shrq $32, %r9
-       shrq $32, %r10
-       movl %eax, 336(%rsp)
-       movl %r8d, 4+336(%rsp)
-       movl %r9d, 8+336(%rsp)
-       movl %r10d, 12+336(%rsp)
-       movq %rbx, 48(%rsp)
-       movq 64(%rsp), %rax
-       movdqa 128(%rsp), %xmm0
-       movdqa 144(%rsp), %xmm1
-       movdqa 160(%rsp), %xmm2
-       movdqa 176(%rsp), %xmm3
-       movdqa 192(%rsp), %xmm4
-       movdqa 208(%rsp), %xmm5
-       movdqa 224(%rsp), %xmm6
-       movdqa 240(%rsp), %xmm7
-       movdqa 256(%rsp), %xmm8
-       movdqa 272(%rsp), %xmm9
-       movdqa 288(%rsp), %xmm10
-       movdqa 304(%rsp), %xmm11
-       movdqa 320(%rsp), %xmm12
-       movdqa 336(%rsp), %xmm13
-       movdqa 352(%rsp), %xmm14
-       movdqa 368(%rsp), %xmm15
-.Lchacha_blocks_sse2_mainloop1:
-       paddd %xmm4, %xmm0
-       paddd %xmm5, %xmm1
-       pxor %xmm0, %xmm12
-       pxor %xmm1, %xmm13
-       paddd %xmm6, %xmm2
-       paddd %xmm7, %xmm3
-       movdqa %xmm6, 96(%rsp)
-       pxor %xmm2, %xmm14
-       pxor %xmm3, %xmm15
-       pshuflw $0xb1,%xmm12,%xmm12
-       pshufhw $0xb1,%xmm12,%xmm12
-       pshuflw $0xb1,%xmm13,%xmm13
-       pshufhw $0xb1,%xmm13,%xmm13
-       pshuflw $0xb1,%xmm14,%xmm14
-       pshufhw $0xb1,%xmm14,%xmm14
-       pshuflw $0xb1,%xmm15,%xmm15
-       pshufhw $0xb1,%xmm15,%xmm15
-       paddd %xmm12, %xmm8
-       paddd %xmm13, %xmm9
-       paddd %xmm14, %xmm10
-       paddd %xmm15, %xmm11
-       movdqa %xmm12, 112(%rsp)
-       pxor %xmm8, %xmm4
-       pxor %xmm9, %xmm5
-       movdqa 96(%rsp), %xmm6
-       movdqa %xmm4, %xmm12
-       pslld $ 12, %xmm4
-       psrld $20, %xmm12
-       pxor %xmm12, %xmm4
-       movdqa %xmm5, %xmm12
-       pslld $ 12, %xmm5
-       psrld $20, %xmm12
-       pxor %xmm12, %xmm5
-       pxor %xmm10, %xmm6
-       pxor %xmm11, %xmm7
-       movdqa %xmm6, %xmm12
-       pslld $ 12, %xmm6
-       psrld $20, %xmm12
-       pxor %xmm12, %xmm6
-       movdqa %xmm7, %xmm12
-       pslld $ 12, %xmm7
-       psrld $20, %xmm12
-       pxor %xmm12, %xmm7
-       movdqa 112(%rsp), %xmm12
-       paddd %xmm4, %xmm0
-       paddd %xmm5, %xmm1
-       pxor %xmm0, %xmm12
-       pxor %xmm1, %xmm13
-       paddd %xmm6, %xmm2
-       paddd %xmm7, %xmm3
-       movdqa %xmm6, 96(%rsp)
-       pxor %xmm2, %xmm14
-       pxor %xmm3, %xmm15
-       movdqa %xmm12, %xmm6
-       pslld $ 8, %xmm12
-       psrld $24, %xmm6
-       pxor %xmm6, %xmm12
-       movdqa %xmm13, %xmm6
-       pslld $ 8, %xmm13
-       psrld $24, %xmm6
-       pxor %xmm6, %xmm13
-       paddd %xmm12, %xmm8
-       paddd %xmm13, %xmm9
-       movdqa %xmm14, %xmm6
-       pslld $ 8, %xmm14
-       psrld $24, %xmm6
-       pxor %xmm6, %xmm14
-       movdqa %xmm15, %xmm6
-       pslld $ 8, %xmm15
-       psrld $24, %xmm6
-       pxor %xmm6, %xmm15
-       paddd %xmm14, %xmm10
-       paddd %xmm15, %xmm11
-       movdqa %xmm12, 112(%rsp)
-       pxor %xmm8, %xmm4
-       pxor %xmm9, %xmm5
-       movdqa 96(%rsp), %xmm6
-       movdqa %xmm4, %xmm12
-       pslld $ 7, %xmm4
-       psrld $25, %xmm12
-       pxor %xmm12, %xmm4
-       movdqa %xmm5, %xmm12
-       pslld $ 7, %xmm5
-       psrld $25, %xmm12
-       pxor %xmm12, %xmm5
-       pxor %xmm10, %xmm6
-       pxor %xmm11, %xmm7
-       movdqa %xmm6, %xmm12
-       pslld $ 7, %xmm6
-       psrld $25, %xmm12
-       pxor %xmm12, %xmm6
-       movdqa %xmm7, %xmm12
-       pslld $ 7, %xmm7
-       psrld $25, %xmm12
-       pxor %xmm12, %xmm7
-       movdqa 112(%rsp), %xmm12
-       paddd %xmm5, %xmm0
-       paddd %xmm6, %xmm1
-       pxor %xmm0, %xmm15
-       pxor %xmm1, %xmm12
-       paddd %xmm7, %xmm2
-       paddd %xmm4, %xmm3
-       movdqa %xmm7, 96(%rsp)
-       pxor %xmm2, %xmm13
-       pxor %xmm3, %xmm14
-       pshuflw $0xb1,%xmm15,%xmm15
-       pshufhw $0xb1,%xmm15,%xmm15
-       pshuflw $0xb1,%xmm12,%xmm12
-       pshufhw $0xb1,%xmm12,%xmm12
-       pshuflw $0xb1,%xmm13,%xmm13
-       pshufhw $0xb1,%xmm13,%xmm13
-       pshuflw $0xb1,%xmm14,%xmm14
-       pshufhw $0xb1,%xmm14,%xmm14
-       paddd %xmm15, %xmm10
-       paddd %xmm12, %xmm11
-       paddd %xmm13, %xmm8
-       paddd %xmm14, %xmm9
-       movdqa %xmm15, 112(%rsp)
-       pxor %xmm10, %xmm5
-       pxor %xmm11, %xmm6
-       movdqa 96(%rsp), %xmm7
-       movdqa %xmm5, %xmm15
-       pslld $ 12, %xmm5
-       psrld $20, %xmm15
-       pxor %xmm15, %xmm5
-       movdqa %xmm6, %xmm15
-       pslld $ 12, %xmm6
-       psrld $20, %xmm15
-       pxor %xmm15, %xmm6
-       pxor %xmm8, %xmm7
-       pxor %xmm9, %xmm4
-       movdqa %xmm7, %xmm15
-       pslld $ 12, %xmm7
-       psrld $20, %xmm15
-       pxor %xmm15, %xmm7
-       movdqa %xmm4, %xmm15
-       pslld $ 12, %xmm4
-       psrld $20, %xmm15
-       pxor %xmm15, %xmm4
-       movdqa 112(%rsp), %xmm15
-       paddd %xmm5, %xmm0
-       paddd %xmm6, %xmm1
-       pxor %xmm0, %xmm15
-       pxor %xmm1, %xmm12
-       paddd %xmm7, %xmm2
-       paddd %xmm4, %xmm3
-       movdqa %xmm7, 96(%rsp)
-       pxor %xmm2, %xmm13
-       pxor %xmm3, %xmm14
-       movdqa %xmm15, %xmm7
-       pslld $ 8, %xmm15
-       psrld $24, %xmm7
-       pxor %xmm7, %xmm15
-       movdqa %xmm12, %xmm7
-       pslld $ 8, %xmm12
-       psrld $24, %xmm7
-       pxor %xmm7, %xmm12
-       paddd %xmm15, %xmm10
-       paddd %xmm12, %xmm11
-       movdqa %xmm13, %xmm7
-       pslld $ 8, %xmm13
-       psrld $24, %xmm7
-       pxor %xmm7, %xmm13
-       movdqa %xmm14, %xmm7
-       pslld $ 8, %xmm14
-       psrld $24, %xmm7
-       pxor %xmm7, %xmm14
-       paddd %xmm13, %xmm8
-       paddd %xmm14, %xmm9
-       movdqa %xmm15, 112(%rsp)
-       pxor %xmm10, %xmm5
-       pxor %xmm11, %xmm6
-       movdqa 96(%rsp), %xmm7
-       movdqa %xmm5, %xmm15
-       pslld $ 7, %xmm5
-       psrld $25, %xmm15
-       pxor %xmm15, %xmm5
-       movdqa %xmm6, %xmm15
-       pslld $ 7, %xmm6
-       psrld $25, %xmm15
-       pxor %xmm15, %xmm6
-       pxor %xmm8, %xmm7
-       pxor %xmm9, %xmm4
-       movdqa %xmm7, %xmm15
-       pslld $ 7, %xmm7
-       psrld $25, %xmm15
-       pxor %xmm15, %xmm7
-       movdqa %xmm4, %xmm15
-       pslld $ 7, %xmm4
-       psrld $25, %xmm15
-       pxor %xmm15, %xmm4
-       movdqa 112(%rsp), %xmm15
-       subq $2, %rax
-       jnz .Lchacha_blocks_sse2_mainloop1
-       paddd 128(%rsp), %xmm0
-       paddd 144(%rsp), %xmm1
-       paddd 160(%rsp), %xmm2
-       paddd 176(%rsp), %xmm3
-       paddd 192(%rsp), %xmm4
-       paddd 208(%rsp), %xmm5
-       paddd 224(%rsp), %xmm6
-       paddd 240(%rsp), %xmm7
-       paddd 256(%rsp), %xmm8
-       paddd 272(%rsp), %xmm9
-       paddd 288(%rsp), %xmm10
-       paddd 304(%rsp), %xmm11
-       paddd 320(%rsp), %xmm12
-       paddd 336(%rsp), %xmm13
-       paddd 352(%rsp), %xmm14
-       paddd 368(%rsp), %xmm15
-       movdqa %xmm8, 384(%rsp)
-       movdqa %xmm9, 400(%rsp)
-       movdqa %xmm10, 416(%rsp)
-       movdqa %xmm11, 432(%rsp)
-       movdqa %xmm12, 448(%rsp)
-       movdqa %xmm13, 464(%rsp)
-       movdqa %xmm14, 480(%rsp)
-       movdqa %xmm15, 496(%rsp)
-       movdqa %xmm0, %xmm8
-       movdqa %xmm2, %xmm9
-       movdqa %xmm4, %xmm10
-       movdqa %xmm6, %xmm11
-       punpckhdq %xmm1, %xmm0
-       punpckhdq %xmm3, %xmm2
-       punpckhdq %xmm5, %xmm4
-       punpckhdq %xmm7, %xmm6
-       punpckldq %xmm1, %xmm8
-       punpckldq %xmm3, %xmm9
-       punpckldq %xmm5, %xmm10
-       punpckldq %xmm7, %xmm11
-       movdqa %xmm0, %xmm1
-       movdqa %xmm4, %xmm3
-       movdqa %xmm8, %xmm5
-       movdqa %xmm10, %xmm7
-       punpckhqdq %xmm2, %xmm0
-       punpckhqdq %xmm6, %xmm4
-       punpckhqdq %xmm9, %xmm8
-       punpckhqdq %xmm11, %xmm10
-       punpcklqdq %xmm2, %xmm1
-       punpcklqdq %xmm6, %xmm3
-       punpcklqdq %xmm9, %xmm5
-       punpcklqdq %xmm11, %xmm7
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_sse2_noinput1
-       movdqu 0(%rsi), %xmm2
-       movdqu 16(%rsi), %xmm6
-       movdqu 64(%rsi), %xmm9
-       movdqu 80(%rsi), %xmm11
-       movdqu 128(%rsi), %xmm12
-       movdqu 144(%rsi), %xmm13
-       movdqu 192(%rsi), %xmm14
-       movdqu 208(%rsi), %xmm15
-       pxor %xmm2, %xmm5
-       pxor %xmm6, %xmm7
-       pxor %xmm9, %xmm8
-       pxor %xmm11, %xmm10
-       pxor %xmm12, %xmm1
-       pxor %xmm13, %xmm3
-       pxor %xmm14, %xmm0
-       pxor %xmm15, %xmm4
-       movdqu %xmm5, 0(%rdx)
-       movdqu %xmm7, 16(%rdx)
-       movdqu %xmm8, 64(%rdx)
-       movdqu %xmm10, 80(%rdx)
-       movdqu %xmm1, 128(%rdx)
-       movdqu %xmm3, 144(%rdx)
-       movdqu %xmm0, 192(%rdx)
-       movdqu %xmm4, 208(%rdx)
-       movdqa 384(%rsp), %xmm0
-       movdqa 400(%rsp), %xmm1
-       movdqa 416(%rsp), %xmm2
-       movdqa 432(%rsp), %xmm3
-       movdqa 448(%rsp), %xmm4
-       movdqa 464(%rsp), %xmm5
-       movdqa 480(%rsp), %xmm6
-       movdqa 496(%rsp), %xmm7
-       movdqa %xmm0, %xmm8
-       movdqa %xmm2, %xmm9
-       movdqa %xmm4, %xmm10
-       movdqa %xmm6, %xmm11
-       punpckldq %xmm1, %xmm8
-       punpckldq %xmm3, %xmm9
-       punpckhdq %xmm1, %xmm0
-       punpckhdq %xmm3, %xmm2
-       punpckldq %xmm5, %xmm10
-       punpckldq %xmm7, %xmm11
-       punpckhdq %xmm5, %xmm4
-       punpckhdq %xmm7, %xmm6
-       movdqa %xmm8, %xmm1
-       movdqa %xmm0, %xmm3
-       movdqa %xmm10, %xmm5
-       movdqa %xmm4, %xmm7
-       punpcklqdq %xmm9, %xmm1
-       punpcklqdq %xmm11, %xmm5
-       punpckhqdq %xmm9, %xmm8
-       punpckhqdq %xmm11, %xmm10
-       punpcklqdq %xmm2, %xmm3
-       punpcklqdq %xmm6, %xmm7
-       punpckhqdq %xmm2, %xmm0
-       punpckhqdq %xmm6, %xmm4
-       movdqu 32(%rsi), %xmm2
-       movdqu 48(%rsi), %xmm6
-       movdqu 96(%rsi), %xmm9
-       movdqu 112(%rsi), %xmm11
-       movdqu 160(%rsi), %xmm12
-       movdqu 176(%rsi), %xmm13
-       movdqu 224(%rsi), %xmm14
-       movdqu 240(%rsi), %xmm15
-       pxor %xmm2, %xmm1
-       pxor %xmm6, %xmm5
-       pxor %xmm9, %xmm8
-       pxor %xmm11, %xmm10
-       pxor %xmm12, %xmm3
-       pxor %xmm13, %xmm7
-       pxor %xmm14, %xmm0
-       pxor %xmm15, %xmm4
-       movdqu %xmm1, 32(%rdx)
-       movdqu %xmm5, 48(%rdx)
-       movdqu %xmm8, 96(%rdx)
-       movdqu %xmm10, 112(%rdx)
-       movdqu %xmm3, 160(%rdx)
-       movdqu %xmm7, 176(%rdx)
-       movdqu %xmm0, 224(%rdx)
-       movdqu %xmm4, 240(%rdx)
-       addq $256, %rsi
-       jmp .Lchacha_blocks_sse2_mainloop_cont
-.Lchacha_blocks_sse2_noinput1:
-       movdqu %xmm5, 0(%rdx)
-       movdqu %xmm7, 16(%rdx)
-       movdqu %xmm8, 64(%rdx)
-       movdqu %xmm10, 80(%rdx)
-       movdqu %xmm1, 128(%rdx)
-       movdqu %xmm3, 144(%rdx)
-       movdqu %xmm0, 192(%rdx)
-       movdqu %xmm4, 208(%rdx)
-       movdqa 384(%rsp), %xmm0
-       movdqa 400(%rsp), %xmm1
-       movdqa 416(%rsp), %xmm2
-       movdqa 432(%rsp), %xmm3
-       movdqa 448(%rsp), %xmm4
-       movdqa 464(%rsp), %xmm5
-       movdqa 480(%rsp), %xmm6
-       movdqa 496(%rsp), %xmm7
-       movdqa %xmm0, %xmm8
-       movdqa %xmm2, %xmm9
-       movdqa %xmm4, %xmm10
-       movdqa %xmm6, %xmm11
-       punpckldq %xmm1, %xmm8
-       punpckldq %xmm3, %xmm9
-       punpckhdq %xmm1, %xmm0
-       punpckhdq %xmm3, %xmm2
-       punpckldq %xmm5, %xmm10
-       punpckldq %xmm7, %xmm11
-       punpckhdq %xmm5, %xmm4
-       punpckhdq %xmm7, %xmm6
-       movdqa %xmm8, %xmm1
-       movdqa %xmm0, %xmm3
-       movdqa %xmm10, %xmm5
-       movdqa %xmm4, %xmm7
-       punpcklqdq %xmm9, %xmm1
-       punpcklqdq %xmm11, %xmm5
-       punpckhqdq %xmm9, %xmm8
-       punpckhqdq %xmm11, %xmm10
-       punpcklqdq %xmm2, %xmm3
-       punpcklqdq %xmm6, %xmm7
-       punpckhqdq %xmm2, %xmm0
-       punpckhqdq %xmm6, %xmm4
-       movdqu %xmm1, 32(%rdx)
-       movdqu %xmm5, 48(%rdx)
-       movdqu %xmm8, 96(%rdx)
-       movdqu %xmm10, 112(%rdx)
-       movdqu %xmm3, 160(%rdx)
-       movdqu %xmm7, 176(%rdx)
-       movdqu %xmm0, 224(%rdx)
-       movdqu %xmm4, 240(%rdx)
-.Lchacha_blocks_sse2_mainloop_cont:
-       addq $256, %rdx
-       subq $256, %rcx
-       cmp $256, %rcx
-       jae .Lchacha_blocks_sse2_atleast256
-       movdqa 0(%rsp), %xmm8
-       movdqa 16(%rsp), %xmm9
-       movdqa 32(%rsp), %xmm10
-       movdqa 48(%rsp), %xmm11
-       movq $1, %r9
-.Lchacha_blocks_sse2_below256:
-       movq %r9, %xmm5
-       andq %rcx, %rcx
-       jz .Lchacha_blocks_sse2_done
-       cmpq $64, %rcx
-       jae .Lchacha_blocks_sse2_above63
-       movq %rdx, %r9
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_sse2_noinput2
-       movq %rcx, %r10
-       movq %rsp, %rdx
-       addq %r10, %rsi
-       addq %r10, %rdx
-       negq %r10
-.Lchacha_blocks_sse2_copyinput:
-       movb (%rsi, %r10), %al
-       movb %al, (%rdx, %r10)
-       incq %r10
-       jnz .Lchacha_blocks_sse2_copyinput
-       movq %rsp, %rsi
-.Lchacha_blocks_sse2_noinput2:
-       movq %rsp, %rdx
-.Lchacha_blocks_sse2_above63:
-       movdqa %xmm8, %xmm0
-       movdqa %xmm9, %xmm1
-       movdqa %xmm10, %xmm2
-       movdqa %xmm11, %xmm3
-       movq 64(%rsp), %rax
-.Lchacha_blocks_sse2_mainloop2:
-       paddd %xmm1, %xmm0
-       pxor %xmm0, %xmm3
-       pshuflw $0xb1,%xmm3,%xmm3
-       pshufhw $0xb1,%xmm3,%xmm3
-       paddd %xmm3, %xmm2
-       pxor %xmm2, %xmm1
-       movdqa %xmm1,%xmm4
-       pslld $12, %xmm1
-       psrld $20, %xmm4
-       pxor %xmm4, %xmm1
-       paddd %xmm1, %xmm0
-       pxor %xmm0, %xmm3
-       movdqa %xmm3,%xmm4
-       pslld $8, %xmm3
-       psrld $24, %xmm4
-       pshufd $0x93,%xmm0,%xmm0
-       pxor %xmm4, %xmm3
-       paddd %xmm3, %xmm2
-       pshufd $0x4e,%xmm3,%xmm3
-       pxor %xmm2, %xmm1
-       pshufd $0x39,%xmm2,%xmm2
-       movdqa %xmm1,%xmm4
-       pslld $7, %xmm1
-       psrld $25, %xmm4
-       pxor %xmm4, %xmm1
-       subq $2, %rax
-       paddd %xmm1, %xmm0
-       pxor %xmm0, %xmm3
-       pshuflw $0xb1,%xmm3,%xmm3
-       pshufhw $0xb1,%xmm3,%xmm3
-       paddd %xmm3, %xmm2
-       pxor %xmm2, %xmm1
-       movdqa %xmm1,%xmm4
-       pslld $12, %xmm1
-       psrld $20, %xmm4
-       pxor %xmm4, %xmm1
-       paddd %xmm1, %xmm0
-       pxor %xmm0, %xmm3
-       movdqa %xmm3,%xmm4
-       pslld $8, %xmm3
-       psrld $24, %xmm4
-       pshufd $0x39,%xmm0,%xmm0
-       pxor %xmm4, %xmm3
-       paddd %xmm3, %xmm2
-       pshufd $0x4e,%xmm3,%xmm3
-       pxor %xmm2, %xmm1
-       pshufd $0x93,%xmm2,%xmm2
-       movdqa %xmm1,%xmm4
-       pslld $7, %xmm1
-       psrld $25, %xmm4
-       pxor %xmm4, %xmm1
-       jnz .Lchacha_blocks_sse2_mainloop2
-       paddd %xmm8, %xmm0
-       paddd %xmm9, %xmm1
-       paddd %xmm10, %xmm2
-       paddd %xmm11, %xmm3
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_sse2_noinput3
-       movdqu 0(%rsi), %xmm12
-       movdqu 16(%rsi), %xmm13
-       movdqu 32(%rsi), %xmm14
-       movdqu 48(%rsi), %xmm15
-       pxor %xmm12, %xmm0
-       pxor %xmm13, %xmm1
-       pxor %xmm14, %xmm2
-       pxor %xmm15, %xmm3
-       addq $64, %rsi
-.Lchacha_blocks_sse2_noinput3:
-       movdqu %xmm0, 0(%rdx)
-       movdqu %xmm1, 16(%rdx)
-       movdqu %xmm2, 32(%rdx)
-       movdqu %xmm3, 48(%rdx)
-       paddq %xmm5, %xmm11
-       cmpq $64, %rcx
-       jbe .Lchacha_blocks_sse2_mainloop2_finishup
-       addq $64, %rdx
-       subq $64, %rcx
-       jmp .Lchacha_blocks_sse2_below256
-.Lchacha_blocks_sse2_mainloop2_finishup:
-       cmpq $64, %rcx
-       je .Lchacha_blocks_sse2_done
-       addq %rcx, %r9
-       addq %rcx, %rdx
-       negq %rcx
-.Lchacha_blocks_sse2_copyoutput:
-       movb (%rdx, %rcx), %al
-       movb %al, (%r9, %rcx)
-       incq %rcx
-       jnz .Lchacha_blocks_sse2_copyoutput
-.Lchacha_blocks_sse2_done:
-       movdqu %xmm11, 48(%rdi)
-       movq %rbp, %rsp
-       pxor %xmm15, %xmm15
-       pxor %xmm7, %xmm7
-       pxor %xmm14, %xmm14
-       pxor %xmm6, %xmm6
-       pxor %xmm13, %xmm13
-       pxor %xmm5, %xmm5
-       pxor %xmm12, %xmm12
-       pxor %xmm4, %xmm4
-       popq %rbp
-       popq %rbx
-       movl $(63 + 512 + 16), %eax
-       pxor %xmm11, %xmm11
-       pxor %xmm3, %xmm3
-       pxor %xmm10, %xmm10
-       pxor %xmm2, %xmm2
-       pxor %xmm9, %xmm9
-       pxor %xmm1, %xmm1
-       pxor %xmm8, %xmm8
-       pxor %xmm0, %xmm0
-       ret
-ELF(.size _gcry_chacha20_amd64_sse2_blocks,.-_gcry_chacha20_amd64_sse2_blocks;)
-
-#endif /*defined(USE_CHACHA20)*/
-#endif /*__x86_64*/
diff --git a/cipher/chacha20-ssse3-amd64.S b/cipher/chacha20-ssse3-amd64.S
deleted file mode 100644 (file)
index c04010e..0000000
+++ /dev/null
@@ -1,632 +0,0 @@
-/* chacha20-ssse3-amd64.S  -  AMD64/SSSE3 implementation of ChaCha20
- *
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Based on public domain implementation by Andrew Moon at
- *  https://github.com/floodyberry/chacha-opt
- */
-
-#ifdef __x86_64__
-#include <config.h>
-
-#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
-    defined(HAVE_GCC_INLINE_ASM_SSSE3) && USE_CHACHA20
-
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-.text
-
-.align 8
-.globl _gcry_chacha20_amd64_ssse3_blocks
-ELF(.type  _gcry_chacha20_amd64_ssse3_blocks,@function;)
-_gcry_chacha20_amd64_ssse3_blocks:
-.Lchacha_blocks_ssse3_local:
-       pushq %rbx
-       pushq %rbp
-       movq %rsp, %rbp
-       andq $~63, %rsp
-       subq $512, %rsp
-       leaq .LC RIP, %rax
-       movdqa 0(%rax), %xmm6
-       movdqa 16(%rax), %xmm7
-       movdqu 0(%rdi), %xmm8
-       movdqu 16(%rdi), %xmm9
-       movdqu 32(%rdi), %xmm10
-       movdqu 48(%rdi), %xmm11
-       movl $20, %eax
-       movq $1, %r9
-       movdqa %xmm8, 0(%rsp)
-       movdqa %xmm9, 16(%rsp)
-       movdqa %xmm10, 32(%rsp)
-       movdqa %xmm11, 48(%rsp)
-       movdqa %xmm6, 80(%rsp)
-       movdqa %xmm7, 96(%rsp)
-       movq %rax, 64(%rsp)
-       cmpq $256, %rcx
-       jb .Lchacha_blocks_ssse3_below256
-       pshufd $0x00, %xmm8, %xmm0
-       pshufd $0x55, %xmm8, %xmm1
-       pshufd $0xaa, %xmm8, %xmm2
-       pshufd $0xff, %xmm8, %xmm3
-       movdqa %xmm0, 128(%rsp)
-       movdqa %xmm1, 144(%rsp)
-       movdqa %xmm2, 160(%rsp)
-       movdqa %xmm3, 176(%rsp)
-       pshufd $0x00, %xmm9, %xmm0
-       pshufd $0x55, %xmm9, %xmm1
-       pshufd $0xaa, %xmm9, %xmm2
-       pshufd $0xff, %xmm9, %xmm3
-       movdqa %xmm0, 192(%rsp)
-       movdqa %xmm1, 208(%rsp)
-       movdqa %xmm2, 224(%rsp)
-       movdqa %xmm3, 240(%rsp)
-       pshufd $0x00, %xmm10, %xmm0
-       pshufd $0x55, %xmm10, %xmm1
-       pshufd $0xaa, %xmm10, %xmm2
-       pshufd $0xff, %xmm10, %xmm3
-       movdqa %xmm0, 256(%rsp)
-       movdqa %xmm1, 272(%rsp)
-       movdqa %xmm2, 288(%rsp)
-       movdqa %xmm3, 304(%rsp)
-       pshufd $0xaa, %xmm11, %xmm0
-       pshufd $0xff, %xmm11, %xmm1
-       movdqa %xmm0, 352(%rsp)
-       movdqa %xmm1, 368(%rsp)
-       jmp .Lchacha_blocks_ssse3_atleast256
-.p2align 6,,63
-       # align to 4 mod 64
-       nop;nop;nop;nop;
-.Lchacha_blocks_ssse3_atleast256:
-       movq 48(%rsp), %rax
-       leaq 1(%rax), %r8
-       leaq 2(%rax), %r9
-       leaq 3(%rax), %r10
-       leaq 4(%rax), %rbx
-       movl %eax, 320(%rsp)
-       movl %r8d, 4+320(%rsp)
-       movl %r9d, 8+320(%rsp)
-       movl %r10d, 12+320(%rsp)
-       shrq $32, %rax
-       shrq $32, %r8
-       shrq $32, %r9
-       shrq $32, %r10
-       movl %eax, 336(%rsp)
-       movl %r8d, 4+336(%rsp)
-       movl %r9d, 8+336(%rsp)
-       movl %r10d, 12+336(%rsp)
-       movq %rbx, 48(%rsp)
-       movq 64(%rsp), %rax
-       movdqa 128(%rsp), %xmm0
-       movdqa 144(%rsp), %xmm1
-       movdqa 160(%rsp), %xmm2
-       movdqa 176(%rsp), %xmm3
-       movdqa 192(%rsp), %xmm4
-       movdqa 208(%rsp), %xmm5
-       movdqa 224(%rsp), %xmm6
-       movdqa 240(%rsp), %xmm7
-       movdqa 256(%rsp), %xmm8
-       movdqa 272(%rsp), %xmm9
-       movdqa 288(%rsp), %xmm10
-       movdqa 304(%rsp), %xmm11
-       movdqa 320(%rsp), %xmm12
-       movdqa 336(%rsp), %xmm13
-       movdqa 352(%rsp), %xmm14
-       movdqa 368(%rsp), %xmm15
-.Lchacha_blocks_ssse3_mainloop1:
-       paddd %xmm4, %xmm0
-       paddd %xmm5, %xmm1
-       pxor %xmm0, %xmm12
-       pxor %xmm1, %xmm13
-       paddd %xmm6, %xmm2
-       paddd %xmm7, %xmm3
-       pxor %xmm2, %xmm14
-       pxor %xmm3, %xmm15
-       pshufb 80(%rsp), %xmm12
-       pshufb 80(%rsp), %xmm13
-       paddd %xmm12, %xmm8
-       paddd %xmm13, %xmm9
-       pshufb 80(%rsp), %xmm14
-       pshufb 80(%rsp), %xmm15
-       paddd %xmm14, %xmm10
-       paddd %xmm15, %xmm11
-       movdqa %xmm12, 112(%rsp)
-       pxor %xmm8, %xmm4
-       pxor %xmm9, %xmm5
-       movdqa %xmm4, %xmm12
-       pslld $ 12, %xmm4
-       psrld $20, %xmm12
-       pxor %xmm12, %xmm4
-       movdqa %xmm5, %xmm12
-       pslld $ 12, %xmm5
-       psrld $20, %xmm12
-       pxor %xmm12, %xmm5
-       pxor %xmm10, %xmm6
-       pxor %xmm11, %xmm7
-       movdqa %xmm6, %xmm12
-       pslld $ 12, %xmm6
-       psrld $20, %xmm12
-       pxor %xmm12, %xmm6
-       movdqa %xmm7, %xmm12
-       pslld $ 12, %xmm7
-       psrld $20, %xmm12
-       pxor %xmm12, %xmm7
-       movdqa 112(%rsp), %xmm12
-       paddd %xmm4, %xmm0
-       paddd %xmm5, %xmm1
-       pxor %xmm0, %xmm12
-       pxor %xmm1, %xmm13
-       paddd %xmm6, %xmm2
-       paddd %xmm7, %xmm3
-       pxor %xmm2, %xmm14
-       pxor %xmm3, %xmm15
-       pshufb 96(%rsp), %xmm12
-       pshufb 96(%rsp), %xmm13
-       paddd %xmm12, %xmm8
-       paddd %xmm13, %xmm9
-       pshufb 96(%rsp), %xmm14
-       pshufb 96(%rsp), %xmm15
-       paddd %xmm14, %xmm10
-       paddd %xmm15, %xmm11
-       movdqa %xmm12, 112(%rsp)
-       pxor %xmm8, %xmm4
-       pxor %xmm9, %xmm5
-       movdqa %xmm4, %xmm12
-       pslld $ 7, %xmm4
-       psrld $25, %xmm12
-       pxor %xmm12, %xmm4
-       movdqa %xmm5, %xmm12
-       pslld $ 7, %xmm5
-       psrld $25, %xmm12
-       pxor %xmm12, %xmm5
-       pxor %xmm10, %xmm6
-       pxor %xmm11, %xmm7
-       movdqa %xmm6, %xmm12
-       pslld $ 7, %xmm6
-       psrld $25, %xmm12
-       pxor %xmm12, %xmm6
-       movdqa %xmm7, %xmm12
-       pslld $ 7, %xmm7
-       psrld $25, %xmm12
-       pxor %xmm12, %xmm7
-       movdqa 112(%rsp), %xmm12
-       paddd %xmm5, %xmm0
-       paddd %xmm6, %xmm1
-       pxor %xmm0, %xmm15
-       pxor %xmm1, %xmm12
-       paddd %xmm7, %xmm2
-       paddd %xmm4, %xmm3
-       pxor %xmm2, %xmm13
-       pxor %xmm3, %xmm14
-       pshufb 80(%rsp), %xmm15
-       pshufb 80(%rsp), %xmm12
-       paddd %xmm15, %xmm10
-       paddd %xmm12, %xmm11
-       pshufb 80(%rsp), %xmm13
-       pshufb 80(%rsp), %xmm14
-       paddd %xmm13, %xmm8
-       paddd %xmm14, %xmm9
-       movdqa %xmm15, 112(%rsp)
-       pxor %xmm10, %xmm5
-       pxor %xmm11, %xmm6
-       movdqa %xmm5, %xmm15
-       pslld $ 12, %xmm5
-       psrld $20, %xmm15
-       pxor %xmm15, %xmm5
-       movdqa %xmm6, %xmm15
-       pslld $ 12, %xmm6
-       psrld $20, %xmm15
-       pxor %xmm15, %xmm6
-       pxor %xmm8, %xmm7
-       pxor %xmm9, %xmm4
-       movdqa %xmm7, %xmm15
-       pslld $ 12, %xmm7
-       psrld $20, %xmm15
-       pxor %xmm15, %xmm7
-       movdqa %xmm4, %xmm15
-       pslld $ 12, %xmm4
-       psrld $20, %xmm15
-       pxor %xmm15, %xmm4
-       movdqa 112(%rsp), %xmm15
-       paddd %xmm5, %xmm0
-       paddd %xmm6, %xmm1
-       pxor %xmm0, %xmm15
-       pxor %xmm1, %xmm12
-       paddd %xmm7, %xmm2
-       paddd %xmm4, %xmm3
-       pxor %xmm2, %xmm13
-       pxor %xmm3, %xmm14
-       pshufb 96(%rsp), %xmm15
-       pshufb 96(%rsp), %xmm12
-       paddd %xmm15, %xmm10
-       paddd %xmm12, %xmm11
-       pshufb 96(%rsp), %xmm13
-       pshufb 96(%rsp), %xmm14
-       paddd %xmm13, %xmm8
-       paddd %xmm14, %xmm9
-       movdqa %xmm15, 112(%rsp)
-       pxor %xmm10, %xmm5
-       pxor %xmm11, %xmm6
-       movdqa %xmm5, %xmm15
-       pslld $ 7, %xmm5
-       psrld $25, %xmm15
-       pxor %xmm15, %xmm5
-       movdqa %xmm6, %xmm15
-       pslld $ 7, %xmm6
-       psrld $25, %xmm15
-       pxor %xmm15, %xmm6
-       pxor %xmm8, %xmm7
-       pxor %xmm9, %xmm4
-       movdqa %xmm7, %xmm15
-       pslld $ 7, %xmm7
-       psrld $25, %xmm15
-       pxor %xmm15, %xmm7
-       movdqa %xmm4, %xmm15
-       pslld $ 7, %xmm4
-       psrld $25, %xmm15
-       pxor %xmm15, %xmm4
-       subq $2, %rax
-       movdqa 112(%rsp), %xmm15
-       jnz .Lchacha_blocks_ssse3_mainloop1
-       paddd 128(%rsp), %xmm0
-       paddd 144(%rsp), %xmm1
-       paddd 160(%rsp), %xmm2
-       paddd 176(%rsp), %xmm3
-       paddd 192(%rsp), %xmm4
-       paddd 208(%rsp), %xmm5
-       paddd 224(%rsp), %xmm6
-       paddd 240(%rsp), %xmm7
-       paddd 256(%rsp), %xmm8
-       paddd 272(%rsp), %xmm9
-       paddd 288(%rsp), %xmm10
-       paddd 304(%rsp), %xmm11
-       paddd 320(%rsp), %xmm12
-       paddd 336(%rsp), %xmm13
-       paddd 352(%rsp), %xmm14
-       paddd 368(%rsp), %xmm15
-       movdqa %xmm8, 384(%rsp)
-       movdqa %xmm9, 400(%rsp)
-       movdqa %xmm10, 416(%rsp)
-       movdqa %xmm11, 432(%rsp)
-       movdqa %xmm12, 448(%rsp)
-       movdqa %xmm13, 464(%rsp)
-       movdqa %xmm14, 480(%rsp)
-       movdqa %xmm15, 496(%rsp)
-       movdqa %xmm0, %xmm8
-       movdqa %xmm2, %xmm9
-       movdqa %xmm4, %xmm10
-       movdqa %xmm6, %xmm11
-       punpckhdq %xmm1, %xmm0
-       punpckhdq %xmm3, %xmm2
-       punpckhdq %xmm5, %xmm4
-       punpckhdq %xmm7, %xmm6
-       punpckldq %xmm1, %xmm8
-       punpckldq %xmm3, %xmm9
-       punpckldq %xmm5, %xmm10
-       punpckldq %xmm7, %xmm11
-       movdqa %xmm0, %xmm1
-       movdqa %xmm4, %xmm3
-       movdqa %xmm8, %xmm5
-       movdqa %xmm10, %xmm7
-       punpckhqdq %xmm2, %xmm0
-       punpckhqdq %xmm6, %xmm4
-       punpckhqdq %xmm9, %xmm8
-       punpckhqdq %xmm11, %xmm10
-       punpcklqdq %xmm2, %xmm1
-       punpcklqdq %xmm6, %xmm3
-       punpcklqdq %xmm9, %xmm5
-       punpcklqdq %xmm11, %xmm7
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_ssse3_noinput1
-       movdqu 0(%rsi), %xmm2
-       movdqu 16(%rsi), %xmm6
-       movdqu 64(%rsi), %xmm9
-       movdqu 80(%rsi), %xmm11
-       movdqu 128(%rsi), %xmm12
-       movdqu 144(%rsi), %xmm13
-       movdqu 192(%rsi), %xmm14
-       movdqu 208(%rsi), %xmm15
-       pxor %xmm2, %xmm5
-       pxor %xmm6, %xmm7
-       pxor %xmm9, %xmm8
-       pxor %xmm11, %xmm10
-       pxor %xmm12, %xmm1
-       pxor %xmm13, %xmm3
-       pxor %xmm14, %xmm0
-       pxor %xmm15, %xmm4
-       movdqu %xmm5, 0(%rdx)
-       movdqu %xmm7, 16(%rdx)
-       movdqu %xmm8, 64(%rdx)
-       movdqu %xmm10, 80(%rdx)
-       movdqu %xmm1, 128(%rdx)
-       movdqu %xmm3, 144(%rdx)
-       movdqu %xmm0, 192(%rdx)
-       movdqu %xmm4, 208(%rdx)
-       movdqa 384(%rsp), %xmm0
-       movdqa 400(%rsp), %xmm1
-       movdqa 416(%rsp), %xmm2
-       movdqa 432(%rsp), %xmm3
-       movdqa 448(%rsp), %xmm4
-       movdqa 464(%rsp), %xmm5
-       movdqa 480(%rsp), %xmm6
-       movdqa 496(%rsp), %xmm7
-       movdqa %xmm0, %xmm8
-       movdqa %xmm2, %xmm9
-       movdqa %xmm4, %xmm10
-       movdqa %xmm6, %xmm11
-       punpckldq %xmm1, %xmm8
-       punpckldq %xmm3, %xmm9
-       punpckhdq %xmm1, %xmm0
-       punpckhdq %xmm3, %xmm2
-       punpckldq %xmm5, %xmm10
-       punpckldq %xmm7, %xmm11
-       punpckhdq %xmm5, %xmm4
-       punpckhdq %xmm7, %xmm6
-       movdqa %xmm8, %xmm1
-       movdqa %xmm0, %xmm3
-       movdqa %xmm10, %xmm5
-       movdqa %xmm4, %xmm7
-       punpcklqdq %xmm9, %xmm1
-       punpcklqdq %xmm11, %xmm5
-       punpckhqdq %xmm9, %xmm8
-       punpckhqdq %xmm11, %xmm10
-       punpcklqdq %xmm2, %xmm3
-       punpcklqdq %xmm6, %xmm7
-       punpckhqdq %xmm2, %xmm0
-       punpckhqdq %xmm6, %xmm4
-       movdqu 32(%rsi), %xmm2
-       movdqu 48(%rsi), %xmm6
-       movdqu 96(%rsi), %xmm9
-       movdqu 112(%rsi), %xmm11
-       movdqu 160(%rsi), %xmm12
-       movdqu 176(%rsi), %xmm13
-       movdqu 224(%rsi), %xmm14
-       movdqu 240(%rsi), %xmm15
-       pxor %xmm2, %xmm1
-       pxor %xmm6, %xmm5
-       pxor %xmm9, %xmm8
-       pxor %xmm11, %xmm10
-       pxor %xmm12, %xmm3
-       pxor %xmm13, %xmm7
-       pxor %xmm14, %xmm0
-       pxor %xmm15, %xmm4
-       movdqu %xmm1, 32(%rdx)
-       movdqu %xmm5, 48(%rdx)
-       movdqu %xmm8, 96(%rdx)
-       movdqu %xmm10, 112(%rdx)
-       movdqu %xmm3, 160(%rdx)
-       movdqu %xmm7, 176(%rdx)
-       movdqu %xmm0, 224(%rdx)
-       movdqu %xmm4, 240(%rdx)
-       addq $256, %rsi
-       jmp .Lchacha_blocks_ssse3_mainloop_cont
-.Lchacha_blocks_ssse3_noinput1:
-       movdqu %xmm5, 0(%rdx)
-       movdqu %xmm7, 16(%rdx)
-       movdqu %xmm8, 64(%rdx)
-       movdqu %xmm10, 80(%rdx)
-       movdqu %xmm1, 128(%rdx)
-       movdqu %xmm3, 144(%rdx)
-       movdqu %xmm0, 192(%rdx)
-       movdqu %xmm4, 208(%rdx)
-       movdqa 384(%rsp), %xmm0
-       movdqa 400(%rsp), %xmm1
-       movdqa 416(%rsp), %xmm2
-       movdqa 432(%rsp), %xmm3
-       movdqa 448(%rsp), %xmm4
-       movdqa 464(%rsp), %xmm5
-       movdqa 480(%rsp), %xmm6
-       movdqa 496(%rsp), %xmm7
-       movdqa %xmm0, %xmm8
-       movdqa %xmm2, %xmm9
-       movdqa %xmm4, %xmm10
-       movdqa %xmm6, %xmm11
-       punpckldq %xmm1, %xmm8
-       punpckldq %xmm3, %xmm9
-       punpckhdq %xmm1, %xmm0
-       punpckhdq %xmm3, %xmm2
-       punpckldq %xmm5, %xmm10
-       punpckldq %xmm7, %xmm11
-       punpckhdq %xmm5, %xmm4
-       punpckhdq %xmm7, %xmm6
-       movdqa %xmm8, %xmm1
-       movdqa %xmm0, %xmm3
-       movdqa %xmm10, %xmm5
-       movdqa %xmm4, %xmm7
-       punpcklqdq %xmm9, %xmm1
-       punpcklqdq %xmm11, %xmm5
-       punpckhqdq %xmm9, %xmm8
-       punpckhqdq %xmm11, %xmm10
-       punpcklqdq %xmm2, %xmm3
-       punpcklqdq %xmm6, %xmm7
-       punpckhqdq %xmm2, %xmm0
-       punpckhqdq %xmm6, %xmm4
-       movdqu %xmm1, 32(%rdx)
-       movdqu %xmm5, 48(%rdx)
-       movdqu %xmm8, 96(%rdx)
-       movdqu %xmm10, 112(%rdx)
-       movdqu %xmm3, 160(%rdx)
-       movdqu %xmm7, 176(%rdx)
-       movdqu %xmm0, 224(%rdx)
-       movdqu %xmm4, 240(%rdx)
-.Lchacha_blocks_ssse3_mainloop_cont:
-       addq $256, %rdx
-       subq $256, %rcx
-       cmp $256, %rcx
-       jae .Lchacha_blocks_ssse3_atleast256
-       movdqa 80(%rsp), %xmm6
-       movdqa 96(%rsp), %xmm7
-       movdqa 0(%rsp), %xmm8
-       movdqa 16(%rsp), %xmm9
-       movdqa 32(%rsp), %xmm10
-       movdqa 48(%rsp), %xmm11
-       movq $1, %r9
-.Lchacha_blocks_ssse3_below256:
-       movq %r9, %xmm5
-       andq %rcx, %rcx
-       jz .Lchacha_blocks_ssse3_done
-       cmpq $64, %rcx
-       jae .Lchacha_blocks_ssse3_above63
-       movq %rdx, %r9
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_ssse3_noinput2
-       movq %rcx, %r10
-       movq %rsp, %rdx
-       addq %r10, %rsi
-       addq %r10, %rdx
-       negq %r10
-.Lchacha_blocks_ssse3_copyinput:
-       movb (%rsi, %r10), %al
-       movb %al, (%rdx, %r10)
-       incq %r10
-       jnz .Lchacha_blocks_ssse3_copyinput
-       movq %rsp, %rsi
-.Lchacha_blocks_ssse3_noinput2:
-       movq %rsp, %rdx
-.Lchacha_blocks_ssse3_above63:
-       movdqa %xmm8, %xmm0
-       movdqa %xmm9, %xmm1
-       movdqa %xmm10, %xmm2
-       movdqa %xmm11, %xmm3
-       movq 64(%rsp), %rax
-.Lchacha_blocks_ssse3_mainloop2:
-       paddd %xmm1, %xmm0
-       pxor %xmm0, %xmm3
-       pshufb %xmm6, %xmm3
-       paddd %xmm3, %xmm2
-       pxor %xmm2, %xmm1
-       movdqa %xmm1, %xmm4
-       pslld $12, %xmm4
-       psrld $20, %xmm1
-       pxor %xmm4, %xmm1
-       paddd %xmm1, %xmm0
-       pxor %xmm0, %xmm3
-       pshufb %xmm7, %xmm3
-       pshufd $0x93, %xmm0, %xmm0
-       paddd %xmm3, %xmm2
-       pshufd $0x4e, %xmm3, %xmm3
-       pxor %xmm2, %xmm1
-       pshufd $0x39, %xmm2, %xmm2
-       movdqa %xmm1, %xmm4
-       pslld $7, %xmm4
-       psrld $25, %xmm1
-       pxor %xmm4, %xmm1
-       paddd %xmm1, %xmm0
-       pxor %xmm0, %xmm3
-       pshufb %xmm6, %xmm3
-       paddd %xmm3, %xmm2
-       pxor %xmm2, %xmm1
-       movdqa %xmm1, %xmm4
-       pslld $12, %xmm4
-       psrld $20, %xmm1
-       pxor %xmm4, %xmm1
-       paddd %xmm1, %xmm0
-       pxor %xmm0, %xmm3
-       pshufb %xmm7, %xmm3
-       pshufd $0x39, %xmm0, %xmm0
-       paddd %xmm3, %xmm2
-       pshufd $0x4e, %xmm3, %xmm3
-       pxor %xmm2, %xmm1
-       pshufd $0x93, %xmm2, %xmm2
-       movdqa %xmm1, %xmm4
-       pslld $7, %xmm4
-       psrld $25, %xmm1
-       pxor %xmm4, %xmm1
-       subq $2, %rax
-       jnz .Lchacha_blocks_ssse3_mainloop2
-       paddd %xmm8, %xmm0
-       paddd %xmm9, %xmm1
-       paddd %xmm10, %xmm2
-       paddd %xmm11, %xmm3
-       andq %rsi, %rsi
-       jz .Lchacha_blocks_ssse3_noinput3
-       movdqu 0(%rsi), %xmm12
-       movdqu 16(%rsi), %xmm13
-       movdqu 32(%rsi), %xmm14
-       movdqu 48(%rsi), %xmm15
-       pxor %xmm12, %xmm0
-       pxor %xmm13, %xmm1
-       pxor %xmm14, %xmm2
-       pxor %xmm15, %xmm3
-       addq $64, %rsi
-.Lchacha_blocks_ssse3_noinput3:
-       movdqu %xmm0, 0(%rdx)
-       movdqu %xmm1, 16(%rdx)
-       movdqu %xmm2, 32(%rdx)
-       movdqu %xmm3, 48(%rdx)
-       paddq %xmm5, %xmm11
-       cmpq $64, %rcx
-       jbe .Lchacha_blocks_ssse3_mainloop2_finishup
-       addq $64, %rdx
-       subq $64, %rcx
-       jmp .Lchacha_blocks_ssse3_below256
-.Lchacha_blocks_ssse3_mainloop2_finishup:
-       cmpq $64, %rcx
-       je .Lchacha_blocks_ssse3_done
-       addq %rcx, %r9
-       addq %rcx, %rdx
-       negq %rcx
-.Lchacha_blocks_ssse3_copyoutput:
-       movb (%rdx, %rcx), %al
-       movb %al, (%r9, %rcx)
-       incq %rcx
-       jnz .Lchacha_blocks_ssse3_copyoutput
-.Lchacha_blocks_ssse3_done:
-       movdqu %xmm11, 48(%rdi)
-       movq %rbp, %rsp
-       pxor %xmm15, %xmm15
-       pxor %xmm7, %xmm7
-       pxor %xmm14, %xmm14
-       pxor %xmm6, %xmm6
-       pxor %xmm13, %xmm13
-       pxor %xmm5, %xmm5
-       pxor %xmm12, %xmm12
-       pxor %xmm4, %xmm4
-       popq %rbp
-       popq %rbx
-       movl $(63 + 512 + 16), %eax
-       pxor %xmm11, %xmm11
-       pxor %xmm3, %xmm3
-       pxor %xmm10, %xmm10
-       pxor %xmm2, %xmm2
-       pxor %xmm9, %xmm9
-       pxor %xmm1, %xmm1
-       pxor %xmm8, %xmm8
-       pxor %xmm0, %xmm0
-       ret
-ELF(.size _gcry_chacha20_amd64_ssse3_blocks,.-_gcry_chacha20_amd64_ssse3_blocks;)
-
-.align 16;
-.LC:
-.byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13       /* pshufb rotate by 16 */
-.byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14       /* pshufb rotate by 8 */
-
-#endif /*defined(USE_CHACHA20)*/
-#endif /*__x86_64*/
index 613fa82..497594a 100644 (file)
@@ -1,5 +1,5 @@
 /* chacha20.c  -  Bernstein's ChaCha20 cipher
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2014,2017-2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
  *   http://cr.yp.to/chacha.html
  */
 
-/* The code is based on salsa20.c and public-domain ChaCha implementations:
- *  chacha-ref.c version 20080118
- *  D. J. Bernstein
- *  Public domain.
- * and
- *  Andrew Moon
- *  https://github.com/floodyberry/chacha-opt
+/*
+ * Based on D. J. Bernstein reference implementation at
+ * http://cr.yp.to/chacha.html:
+ *
+ * chacha-regs.c version 20080118
+ * D. J. Bernstein
+ * Public domain.
  */
 
-
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,6 +36,7 @@
 #include "types.h"
 #include "g10lib.h"
 #include "cipher.h"
+#include "cipher-internal.h"
 #include "bufhelp.h"
 
 
 #define CHACHA20_MIN_IV_SIZE   8        /* Bytes.  */
 #define CHACHA20_MAX_IV_SIZE  12        /* Bytes.  */
 #define CHACHA20_CTR_SIZE     16        /* Bytes.  */
-#define CHACHA20_INPUT_LENGTH (CHACHA20_BLOCK_SIZE / 4)
 
-/* USE_SSE2 indicates whether to compile with Intel SSE2 code. */
-#undef USE_SSE2
-#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
-# define USE_SSE2 1
-#endif
 
 /* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */
 #undef USE_SSSE3
-#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
-    defined(HAVE_GCC_INLINE_ASM_SSSE3)
+#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \
+   (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
 # define USE_SSSE3 1
 #endif
 
 /* USE_AVX2 indicates whether to compile with Intel AVX2 code. */
 #undef USE_AVX2
-#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
-    defined(ENABLE_AVX2_SUPPORT)
+#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX2) && \
+    (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
 # define USE_AVX2 1
 #endif
 
-/* USE_NEON indicates whether to enable ARM NEON assembly code. */
-#undef USE_NEON
+/* USE_ARMV7_NEON indicates whether to enable ARMv7 NEON assembly code. */
+#undef USE_ARMV7_NEON
 #ifdef ENABLE_NEON_SUPPORT
 # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \
      && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \
      && defined(HAVE_GCC_INLINE_ASM_NEON)
-#  define USE_NEON 1
+#  define USE_ARMV7_NEON 1
 # endif
-#endif /*ENABLE_NEON_SUPPORT*/
+#endif
 
+/* USE_AARCH64_SIMD indicates whether to enable ARMv8 SIMD assembly
+ * code. */
+#undef USE_AARCH64_SIMD
+#ifdef ENABLE_NEON_SUPPORT
+# if defined(__AARCH64EL__) \
+       && defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) \
+       && defined(HAVE_GCC_INLINE_ASM_AARCH64_NEON)
+#  define USE_AARCH64_SIMD 1
+# endif
+#endif
 
-struct CHACHA20_context_s;
+/* USE_PPC_VEC indicates whether to enable PowerPC vector
+ * accelerated code. */
+#undef USE_PPC_VEC
+#ifdef ENABLE_PPC_CRYPTO_SUPPORT
+# if defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+     defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC)
+#  if __GNUC__ >= 4
+#   define USE_PPC_VEC 1
+#  endif
+# endif
+#endif
 
+/* USE_S390X_VX indicates whether to enable zSeries code. */
+#undef USE_S390X_VX
+#if defined (__s390x__) && __GNUC__ >= 4 && __ARCH__ >= 9
+# if defined(HAVE_GCC_INLINE_ASM_S390X_VX)
+#  define USE_S390X_VX 1
+# endif /* USE_S390X_VX */
+#endif
 
 /* Assembly implementations use SystemV ABI, ABI conversion and additional
  * stack to store XMM6-XMM15 needed on Win64. */
 #undef ASM_FUNC_ABI
 #undef ASM_EXTRA_STACK
-#if (defined(USE_SSE2) || defined(USE_SSSE3) || defined(USE_AVX2)) && \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)
+#if defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)
 # define ASM_FUNC_ABI __attribute__((sysv_abi))
-# define ASM_EXTRA_STACK (10 * 16)
 #else
 # define ASM_FUNC_ABI
-# define ASM_EXTRA_STACK 0
 #endif
 
 
-typedef unsigned int (* chacha20_blocks_t)(u32 *state, const byte *src,
-                                           byte *dst,
-                                           size_t bytes) ASM_FUNC_ABI;
-
 typedef struct CHACHA20_context_s
 {
-  u32 input[CHACHA20_INPUT_LENGTH];
-  u32 pad[CHACHA20_INPUT_LENGTH];
-  chacha20_blocks_t blocks;
+  u32 input[16];
+  unsigned char pad[CHACHA20_BLOCK_SIZE];
   unsigned int unused; /* bytes in the pad.  */
+  unsigned int use_ssse3:1;
+  unsigned int use_avx2:1;
+  unsigned int use_neon:1;
+  unsigned int use_ppc:1;
+  unsigned int use_s390x:1;
 } CHACHA20_context_t;
 
 
-#ifdef USE_SSE2
+#ifdef USE_SSSE3
 
-unsigned int _gcry_chacha20_amd64_sse2_blocks(u32 *state, const byte *in,
-                                              byte *out,
-                                              size_t bytes) ASM_FUNC_ABI;
+unsigned int _gcry_chacha20_amd64_ssse3_blocks4(u32 *state, byte *dst,
+                                               const byte *src,
+                                               size_t nblks) ASM_FUNC_ABI;
 
-#endif /* USE_SSE2 */
+unsigned int _gcry_chacha20_amd64_ssse3_blocks1(u32 *state, byte *dst,
+                                               const byte *src,
+                                               size_t nblks) ASM_FUNC_ABI;
 
-#ifdef USE_SSSE3
+unsigned int _gcry_chacha20_poly1305_amd64_ssse3_blocks4(
+               u32 *state, byte *dst, const byte *src, size_t nblks,
+               void *poly1305_state, const byte *poly1305_src) ASM_FUNC_ABI;
 
-unsigned int _gcry_chacha20_amd64_ssse3_blocks(u32 *state, const byte *in,
-                                               byte *out,
-                                               size_t bytes) ASM_FUNC_ABI;
+unsigned int _gcry_chacha20_poly1305_amd64_ssse3_blocks1(
+               u32 *state, byte *dst, const byte *src, size_t nblks,
+               void *poly1305_state, const byte *poly1305_src) ASM_FUNC_ABI;
 
 #endif /* USE_SSSE3 */
 
 #ifdef USE_AVX2
 
-unsigned int _gcry_chacha20_amd64_avx2_blocks(u32 *state, const byte *in,
-                                              byte *out,
-                                              size_t bytes) ASM_FUNC_ABI;
+unsigned int _gcry_chacha20_amd64_avx2_blocks8(u32 *state, byte *dst,
+                                              const byte *src,
+                                              size_t nblks) ASM_FUNC_ABI;
+
+unsigned int _gcry_chacha20_poly1305_amd64_avx2_blocks8(
+               u32 *state, byte *dst, const byte *src, size_t nblks,
+               void *poly1305_state, const byte *poly1305_src) ASM_FUNC_ABI;
 
 #endif /* USE_AVX2 */
 
-#ifdef USE_NEON
+#ifdef USE_PPC_VEC
+
+unsigned int _gcry_chacha20_ppc8_blocks4(u32 *state, byte *dst,
+                                        const byte *src,
+                                        size_t nblks);
+
+unsigned int _gcry_chacha20_ppc8_blocks1(u32 *state, byte *dst,
+                                        const byte *src,
+                                        size_t nblks);
+
+#undef USE_PPC_VEC_POLY1305
+#if SIZEOF_UNSIGNED_LONG == 8
+#define USE_PPC_VEC_POLY1305 1
+unsigned int _gcry_chacha20_poly1305_ppc8_blocks4(
+               u32 *state, byte *dst, const byte *src, size_t nblks,
+               POLY1305_STATE *st, const byte *poly1305_src);
+#endif /* SIZEOF_UNSIGNED_LONG == 8 */
+
+#endif /* USE_PPC_VEC */
+
+#ifdef USE_S390X_VX
 
-unsigned int _gcry_chacha20_armv7_neon_blocks(u32 *state, const byte *in,
-                                              byte *out,
-                                              size_t bytes) ASM_FUNC_ABI;
+unsigned int _gcry_chacha20_s390x_vx_blocks8(u32 *state, byte *dst,
+                                            const byte *src, size_t nblks);
 
-#endif /* USE_NEON */
+unsigned int _gcry_chacha20_s390x_vx_blocks4_2_1(u32 *state, byte *dst,
+                                                const byte *src, size_t nblks);
+
+#undef USE_S390X_VX_POLY1305
+#if SIZEOF_UNSIGNED_LONG == 8
+#define USE_S390X_VX_POLY1305 1
+unsigned int _gcry_chacha20_poly1305_s390x_vx_blocks8(
+               u32 *state, byte *dst, const byte *src, size_t nblks,
+               POLY1305_STATE *st, const byte *poly1305_src);
+
+unsigned int _gcry_chacha20_poly1305_s390x_vx_blocks4_2_1(
+               u32 *state, byte *dst, const byte *src, size_t nblks,
+               POLY1305_STATE *st, const byte *poly1305_src);
+#endif /* SIZEOF_UNSIGNED_LONG == 8 */
+
+#endif /* USE_S390X_VX */
+
+#ifdef USE_ARMV7_NEON
+
+unsigned int _gcry_chacha20_armv7_neon_blocks4(u32 *state, byte *dst,
+                                              const byte *src,
+                                              size_t nblks);
+
+#endif /* USE_ARMV7_NEON */
+
+#ifdef USE_AARCH64_SIMD
+
+unsigned int _gcry_chacha20_aarch64_blocks4(u32 *state, byte *dst,
+                                           const byte *src, size_t nblks);
+
+unsigned int _gcry_chacha20_poly1305_aarch64_blocks4(
+               u32 *state, byte *dst, const byte *src, size_t nblks,
+               void *poly1305_state, const byte *poly1305_src);
+
+#endif /* USE_AARCH64_SIMD */
 
 
-static void chacha20_setiv (void *context, const byte * iv, size_t ivlen);
 static const char *selftest (void);
 \f
 
+#define ROTATE(v,c)    (rol(v,c))
+#define XOR(v,w)       ((v) ^ (w))
+#define PLUS(v,w)      ((u32)((v) + (w)))
+#define PLUSONE(v)     (PLUS((v),1))
 
-#define QROUND(a,b,c,d)         \
-  do {                          \
-    a += b; d = rol(d ^ a, 16); \
-    c += d; b = rol(b ^ c, 12); \
-    a += b; d = rol(d ^ a, 8);  \
-    c += d; b = rol(b ^ c, 7);  \
-  } while (0)
+#define QUARTERROUND(a,b,c,d) \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
 
-#define QOUT(ai, bi, ci, di) \
-  DO_OUT(ai); DO_OUT(bi); DO_OUT(ci); DO_OUT(di)
+#define BUF_XOR_LE32(dst, src, offset, x) \
+  buf_put_le32((dst) + (offset), buf_get_le32((src) + (offset)) ^ (x))
 
-
-#ifndef USE_SSE2
-ASM_FUNC_ABI static unsigned int
-chacha20_blocks (u32 *state, const byte *src, byte *dst, size_t bytes)
+static unsigned int
+do_chacha20_blocks (u32 *input, byte *dst, const byte *src, size_t nblks)
 {
-  u32 pad[CHACHA20_INPUT_LENGTH];
-  u32 inp[CHACHA20_INPUT_LENGTH];
+  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
   unsigned int i;
 
-  /* Note: 'bytes' must be multiple of 64 and not zero. */
-
-  inp[0] = state[0];
-  inp[1] = state[1];
-  inp[2] = state[2];
-  inp[3] = state[3];
-  inp[4] = state[4];
-  inp[5] = state[5];
-  inp[6] = state[6];
-  inp[7] = state[7];
-  inp[8] = state[8];
-  inp[9] = state[9];
-  inp[10] = state[10];
-  inp[11] = state[11];
-  inp[12] = state[12];
-  inp[13] = state[13];
-  inp[14] = state[14];
-  inp[15] = state[15];
-
-  do
-    {
-      /* First round. */
-      pad[0] = inp[0];
-      pad[4] = inp[4];
-      pad[8] = inp[8];
-      pad[12] = inp[12];
-      QROUND (pad[0], pad[4], pad[8], pad[12]);
-      pad[1] = inp[1];
-      pad[5] = inp[5];
-      pad[9] = inp[9];
-      pad[13] = inp[13];
-      QROUND (pad[1], pad[5], pad[9], pad[13]);
-      pad[2] = inp[2];
-      pad[6] = inp[6];
-      pad[10] = inp[10];
-      pad[14] = inp[14];
-      QROUND (pad[2], pad[6], pad[10], pad[14]);
-      pad[3] = inp[3];
-      pad[7] = inp[7];
-      pad[11] = inp[11];
-      pad[15] = inp[15];
-      QROUND (pad[3], pad[7], pad[11], pad[15]);
-
-      QROUND (pad[0], pad[5], pad[10], pad[15]);
-      QROUND (pad[1], pad[6], pad[11], pad[12]);
-      QROUND (pad[2], pad[7], pad[8], pad[13]);
-      QROUND (pad[3], pad[4], pad[9], pad[14]);
-
-      for (i = 2; i < 20 - 2; i += 2)
-      {
-        QROUND (pad[0], pad[4], pad[8], pad[12]);
-        QROUND (pad[1], pad[5], pad[9], pad[13]);
-        QROUND (pad[2], pad[6], pad[10], pad[14]);
-        QROUND (pad[3], pad[7], pad[11], pad[15]);
-
-        QROUND (pad[0], pad[5], pad[10], pad[15]);
-        QROUND (pad[1], pad[6], pad[11], pad[12]);
-        QROUND (pad[2], pad[7], pad[8], pad[13]);
-        QROUND (pad[3], pad[4], pad[9], pad[14]);
-      }
-
-      QROUND (pad[0], pad[4], pad[8], pad[12]);
-      QROUND (pad[1], pad[5], pad[9], pad[13]);
-      QROUND (pad[2], pad[6], pad[10], pad[14]);
-      QROUND (pad[3], pad[7], pad[11], pad[15]);
-
-      if (src)
-        {
-#define DO_OUT(idx) buf_put_le32(dst + (idx) * 4, \
-                                 (pad[idx] + inp[idx]) ^ \
-                                  buf_get_le32(src + (idx) * 4))
-          /* Last round. */
-          QROUND (pad[0], pad[5], pad[10], pad[15]);
-          QOUT(0, 5, 10, 15);
-          QROUND (pad[1], pad[6], pad[11], pad[12]);
-          QOUT(1, 6, 11, 12);
-          QROUND (pad[2], pad[7], pad[8], pad[13]);
-          QOUT(2, 7, 8, 13);
-          QROUND (pad[3], pad[4], pad[9], pad[14]);
-          QOUT(3, 4, 9, 14);
-#undef DO_OUT
-        }
-      else
-        {
-#define DO_OUT(idx) buf_put_le32(dst + (idx) * 4, pad[idx] + inp[idx])
-          /* Last round. */
-          QROUND (pad[0], pad[5], pad[10], pad[15]);
-          QOUT(0, 5, 10, 15);
-          QROUND (pad[1], pad[6], pad[11], pad[12]);
-          QOUT(1, 6, 11, 12);
-          QROUND (pad[2], pad[7], pad[8], pad[13]);
-          QOUT(2, 7, 8, 13);
-          QROUND (pad[3], pad[4], pad[9], pad[14]);
-          QOUT(3, 4, 9, 14);
-#undef DO_OUT
-        }
-
-      /* Update counter. */
-      inp[13] += (!++inp[12]);
-
-      bytes -= CHACHA20_BLOCK_SIZE;
+  while (nblks)
+    {
+      x0 = input[0];
+      x1 = input[1];
+      x2 = input[2];
+      x3 = input[3];
+      x4 = input[4];
+      x5 = input[5];
+      x6 = input[6];
+      x7 = input[7];
+      x8 = input[8];
+      x9 = input[9];
+      x10 = input[10];
+      x11 = input[11];
+      x12 = input[12];
+      x13 = input[13];
+      x14 = input[14];
+      x15 = input[15];
+
+      for (i = 20; i > 0; i -= 2)
+       {
+         QUARTERROUND(x0, x4,  x8, x12)
+         QUARTERROUND(x1, x5,  x9, x13)
+         QUARTERROUND(x2, x6, x10, x14)
+         QUARTERROUND(x3, x7, x11, x15)
+         QUARTERROUND(x0, x5, x10, x15)
+         QUARTERROUND(x1, x6, x11, x12)
+         QUARTERROUND(x2, x7,  x8, x13)
+         QUARTERROUND(x3, x4,  x9, x14)
+       }
+
+      x0 = PLUS(x0, input[0]);
+      x1 = PLUS(x1, input[1]);
+      x2 = PLUS(x2, input[2]);
+      x3 = PLUS(x3, input[3]);
+      x4 = PLUS(x4, input[4]);
+      x5 = PLUS(x5, input[5]);
+      x6 = PLUS(x6, input[6]);
+      x7 = PLUS(x7, input[7]);
+      x8 = PLUS(x8, input[8]);
+      x9 = PLUS(x9, input[9]);
+      x10 = PLUS(x10, input[10]);
+      x11 = PLUS(x11, input[11]);
+      x12 = PLUS(x12, input[12]);
+      x13 = PLUS(x13, input[13]);
+      x14 = PLUS(x14, input[14]);
+      x15 = PLUS(x15, input[15]);
+
+      input[12] = PLUSONE(input[12]);
+      input[13] = PLUS(input[13], !input[12]);
+
+      BUF_XOR_LE32(dst, src, 0, x0);
+      BUF_XOR_LE32(dst, src, 4, x1);
+      BUF_XOR_LE32(dst, src, 8, x2);
+      BUF_XOR_LE32(dst, src, 12, x3);
+      BUF_XOR_LE32(dst, src, 16, x4);
+      BUF_XOR_LE32(dst, src, 20, x5);
+      BUF_XOR_LE32(dst, src, 24, x6);
+      BUF_XOR_LE32(dst, src, 28, x7);
+      BUF_XOR_LE32(dst, src, 32, x8);
+      BUF_XOR_LE32(dst, src, 36, x9);
+      BUF_XOR_LE32(dst, src, 40, x10);
+      BUF_XOR_LE32(dst, src, 44, x11);
+      BUF_XOR_LE32(dst, src, 48, x12);
+      BUF_XOR_LE32(dst, src, 52, x13);
+      BUF_XOR_LE32(dst, src, 56, x14);
+      BUF_XOR_LE32(dst, src, 60, x15);
+
+      src += CHACHA20_BLOCK_SIZE;
       dst += CHACHA20_BLOCK_SIZE;
-      src += (src) ? CHACHA20_BLOCK_SIZE : 0;
+      nblks--;
     }
-  while (bytes >= CHACHA20_BLOCK_SIZE);
-
-  state[12] = inp[12];
-  state[13] = inp[13];
 
   /* burn_stack */
-  return (2 * CHACHA20_INPUT_LENGTH * sizeof(u32) + 6 * sizeof(void *));
+  return (17 * sizeof(u32) + 6 * sizeof(void *));
 }
-#endif /*!USE_SSE2*/
-
-#undef QROUND
-#undef QOUT
 
 
 static unsigned int
-chacha20_core(u32 *dst, struct CHACHA20_context_s *ctx)
+chacha20_blocks (CHACHA20_context_t *ctx, byte *dst, const byte *src,
+                size_t nblks)
 {
-  return ctx->blocks(ctx->input, NULL, (byte *)dst, CHACHA20_BLOCK_SIZE)
-         + ASM_EXTRA_STACK;
+#ifdef USE_SSSE3
+  if (ctx->use_ssse3)
+    {
+      return _gcry_chacha20_amd64_ssse3_blocks1(ctx->input, dst, src, nblks);
+    }
+#endif
+
+#ifdef USE_PPC_VEC
+  if (ctx->use_ppc)
+    {
+      return _gcry_chacha20_ppc8_blocks1(ctx->input, dst, src, nblks);
+    }
+#endif
+
+#ifdef USE_S390X_VX
+  if (ctx->use_s390x)
+    {
+      return _gcry_chacha20_s390x_vx_blocks4_2_1(ctx->input, dst, src, nblks);
+    }
+#endif
+
+  return do_chacha20_blocks (ctx->input, dst, src, nblks);
 }
 
 
 static void
-chacha20_keysetup (CHACHA20_context_t * ctx, const byte * key,
+chacha20_keysetup (CHACHA20_context_t *ctx, const byte *key,
                    unsigned int keylen)
 {
-  /* These constants are the little endian encoding of the string
-     "expand 32-byte k".  For the 128 bit variant, the "32" in that
-     string will be fixed up to "16".  */
-  ctx->input[0] = 0x61707865;        /* "apxe"  */
-  ctx->input[1] = 0x3320646e;        /* "3 dn"  */
-  ctx->input[2] = 0x79622d32;        /* "yb-2"  */
-  ctx->input[3] = 0x6b206574;        /* "k et"  */
-
-  ctx->input[4] = buf_get_le32 (key + 0);
-  ctx->input[5] = buf_get_le32 (key + 4);
-  ctx->input[6] = buf_get_le32 (key + 8);
-  ctx->input[7] = buf_get_le32 (key + 12);
-
+  static const char sigma[16] = "expand 32-byte k";
+  static const char tau[16] = "expand 16-byte k";
+  const char *constants;
+
+  ctx->input[4] = buf_get_le32(key + 0);
+  ctx->input[5] = buf_get_le32(key + 4);
+  ctx->input[6] = buf_get_le32(key + 8);
+  ctx->input[7] = buf_get_le32(key + 12);
   if (keylen == CHACHA20_MAX_KEY_SIZE) /* 256 bits */
     {
-      ctx->input[8] = buf_get_le32 (key + 16);
-      ctx->input[9] = buf_get_le32 (key + 20);
-      ctx->input[10] = buf_get_le32 (key + 24);
-      ctx->input[11] = buf_get_le32 (key + 28);
+      key += 16;
+      constants = sigma;
     }
   else /* 128 bits */
     {
-      ctx->input[8] = ctx->input[4];
-      ctx->input[9] = ctx->input[5];
-      ctx->input[10] = ctx->input[6];
-      ctx->input[11] = ctx->input[7];
-
-      ctx->input[1] -= 0x02000000;        /* Change to "1 dn".  */
-      ctx->input[2] += 0x00000004;        /* Change to "yb-6".  */
+      constants = tau;
     }
+  ctx->input[8] = buf_get_le32(key + 0);
+  ctx->input[9] = buf_get_le32(key + 4);
+  ctx->input[10] = buf_get_le32(key + 8);
+  ctx->input[11] = buf_get_le32(key + 12);
+  ctx->input[0] = buf_get_le32(constants + 0);
+  ctx->input[1] = buf_get_le32(constants + 4);
+  ctx->input[2] = buf_get_le32(constants + 8);
+  ctx->input[3] = buf_get_le32(constants + 12);
 }
 
 
 static void
-chacha20_ivsetup (CHACHA20_context_t * ctx, const byte * iv, size_t ivlen)
+chacha20_ivsetup (CHACHA20_context_t * ctx, const byte *iv, size_t ivlen)
 {
   if (ivlen == CHACHA20_CTR_SIZE)
     {
@@ -367,9 +419,30 @@ chacha20_ivsetup (CHACHA20_context_t * ctx, const byte * iv, size_t ivlen)
 }
 
 
+static void
+chacha20_setiv (void *context, const byte *iv, size_t ivlen)
+{
+  CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
+
+  /* draft-nir-cfrg-chacha20-poly1305-02 defines 96-bit and 64-bit nonce. */
+  if (iv && ivlen != CHACHA20_MAX_IV_SIZE && ivlen != CHACHA20_MIN_IV_SIZE
+      && ivlen != CHACHA20_CTR_SIZE)
+    log_info ("WARNING: chacha20_setiv: bad ivlen=%u\n", (u32) ivlen);
+
+  if (iv && (ivlen == CHACHA20_MAX_IV_SIZE || ivlen == CHACHA20_MIN_IV_SIZE
+             || ivlen == CHACHA20_CTR_SIZE))
+    chacha20_ivsetup (ctx, iv, ivlen);
+  else
+    chacha20_ivsetup (ctx, NULL, 0);
+
+  /* Reset the unused pad bytes counter.  */
+  ctx->unused = 0;
+}
+
+
 static gcry_err_code_t
-chacha20_do_setkey (CHACHA20_context_t * ctx,
-                    const byte * key, unsigned int keylen)
+chacha20_do_setkey (CHACHA20_context_t *ctx,
+                    const byte *key, unsigned int keylen)
 {
   static int initialized;
   static const char *selftest_failed;
@@ -388,23 +461,23 @@ chacha20_do_setkey (CHACHA20_context_t * ctx,
   if (keylen != CHACHA20_MAX_KEY_SIZE && keylen != CHACHA20_MIN_KEY_SIZE)
     return GPG_ERR_INV_KEYLEN;
 
-#ifdef USE_SSE2
-  ctx->blocks = _gcry_chacha20_amd64_sse2_blocks;
-#else
-  ctx->blocks = chacha20_blocks;
-#endif
-
 #ifdef USE_SSSE3
-  if (features & HWF_INTEL_SSSE3)
-    ctx->blocks = _gcry_chacha20_amd64_ssse3_blocks;
+  ctx->use_ssse3 = (features & HWF_INTEL_SSSE3) != 0;
 #endif
 #ifdef USE_AVX2
-  if (features & HWF_INTEL_AVX2)
-    ctx->blocks = _gcry_chacha20_amd64_avx2_blocks;
+  ctx->use_avx2 = (features & HWF_INTEL_AVX2) != 0;
+#endif
+#ifdef USE_ARMV7_NEON
+  ctx->use_neon = (features & HWF_ARM_NEON) != 0;
+#endif
+#ifdef USE_AARCH64_SIMD
+  ctx->use_neon = (features & HWF_ARM_NEON) != 0;
+#endif
+#ifdef USE_PPC_VEC
+  ctx->use_ppc = (features & HWF_PPC_ARCH_2_07) != 0;
 #endif
-#ifdef USE_NEON
-  if (features & HWF_ARM_NEON)
-    ctx->blocks = _gcry_chacha20_armv7_neon_blocks;
+#ifdef USE_S390X_VX
+  ctx->use_s390x = (features & HWF_S390X_VX) != 0;
 #endif
 
   (void)features;
@@ -419,47 +492,146 @@ chacha20_do_setkey (CHACHA20_context_t * ctx,
 
 
 static gcry_err_code_t
-chacha20_setkey (void *context, const byte * key, unsigned int keylen)
+chacha20_setkey (void *context, const byte *key, unsigned int keylen,
+                 cipher_bulk_ops_t *bulk_ops)
 {
   CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
   gcry_err_code_t rc = chacha20_do_setkey (ctx, key, keylen);
+  (void)bulk_ops;
   _gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *));
   return rc;
 }
 
 
-static void
-chacha20_setiv (void *context, const byte * iv, size_t ivlen)
+static unsigned int
+do_chacha20_encrypt_stream_tail (CHACHA20_context_t *ctx, byte *outbuf,
+                                const byte *inbuf, size_t length)
 {
-  CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
+  static const unsigned char zero_pad[CHACHA20_BLOCK_SIZE] = { 0, };
+  unsigned int nburn, burn = 0;
 
-  /* draft-nir-cfrg-chacha20-poly1305-02 defines 96-bit and 64-bit nonce. */
-  if (iv && ivlen != CHACHA20_MAX_IV_SIZE && ivlen != CHACHA20_MIN_IV_SIZE
-      && ivlen != CHACHA20_CTR_SIZE)
-    log_info ("WARNING: chacha20_setiv: bad ivlen=%u\n", (u32) ivlen);
+#ifdef USE_AVX2
+  if (ctx->use_avx2 && length >= CHACHA20_BLOCK_SIZE * 8)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 8;
+      nburn = _gcry_chacha20_amd64_avx2_blocks8(ctx->input, outbuf, inbuf,
+                                               nblocks);
+      burn = nburn > burn ? nburn : burn;
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
 
-  if (iv && (ivlen == CHACHA20_MAX_IV_SIZE || ivlen == CHACHA20_MIN_IV_SIZE
-             || ivlen == CHACHA20_CTR_SIZE))
-    chacha20_ivsetup (ctx, iv, ivlen);
-  else
-    chacha20_ivsetup (ctx, NULL, 0);
+#ifdef USE_SSSE3
+  if (ctx->use_ssse3 && length >= CHACHA20_BLOCK_SIZE * 4)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 4;
+      nburn = _gcry_chacha20_amd64_ssse3_blocks4(ctx->input, outbuf, inbuf,
+                                                nblocks);
+      burn = nburn > burn ? nburn : burn;
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
 
-  /* Reset the unused pad bytes counter.  */
-  ctx->unused = 0;
+#ifdef USE_ARMV7_NEON
+  if (ctx->use_neon && length >= CHACHA20_BLOCK_SIZE * 4)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 4;
+      nburn = _gcry_chacha20_armv7_neon_blocks4(ctx->input, outbuf, inbuf,
+                                               nblocks);
+      burn = nburn > burn ? nburn : burn;
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+
+#ifdef USE_AARCH64_SIMD
+  if (ctx->use_neon && length >= CHACHA20_BLOCK_SIZE * 4)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 4;
+      nburn = _gcry_chacha20_aarch64_blocks4(ctx->input, outbuf, inbuf,
+                                            nblocks);
+      burn = nburn > burn ? nburn : burn;
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+
+#ifdef USE_PPC_VEC
+  if (ctx->use_ppc && length >= CHACHA20_BLOCK_SIZE * 4)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 4;
+      nburn = _gcry_chacha20_ppc8_blocks4(ctx->input, outbuf, inbuf, nblocks);
+      burn = nburn > burn ? nburn : burn;
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+
+#ifdef USE_S390X_VX
+  if (ctx->use_s390x && length >= CHACHA20_BLOCK_SIZE * 8)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 8;
+      nburn = _gcry_chacha20_s390x_vx_blocks8(ctx->input, outbuf, inbuf,
+                                             nblocks);
+      burn = nburn > burn ? nburn : burn;
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+
+  if (length >= CHACHA20_BLOCK_SIZE)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nburn = chacha20_blocks(ctx, outbuf, inbuf, nblocks);
+      burn = nburn > burn ? nburn : burn;
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+
+  if (length > 0)
+    {
+      nburn = chacha20_blocks(ctx, ctx->pad, zero_pad, 1);
+      burn = nburn > burn ? nburn : burn;
+
+      buf_xor (outbuf, inbuf, ctx->pad, length);
+      ctx->unused = CHACHA20_BLOCK_SIZE - length;
+    }
+
+  if (burn)
+    burn += 5 * sizeof(void *);
+
+  return burn;
 }
-\f
 
 
-/* Note: This function requires LENGTH > 0.  */
 static void
-chacha20_do_encrypt_stream (CHACHA20_context_t * ctx,
-                            byte * outbuf, const byte * inbuf, size_t length)
+chacha20_encrypt_stream (void *context, byte *outbuf, const byte *inbuf,
+                         size_t length)
 {
+  CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
   unsigned int nburn, burn = 0;
 
+  if (!length)
+    return;
+
   if (ctx->unused)
     {
-      unsigned char *p = (void *) ctx->pad;
+      unsigned char *p = ctx->pad;
       size_t n;
 
       gcry_assert (ctx->unused < CHACHA20_BLOCK_SIZE);
@@ -467,47 +639,544 @@ chacha20_do_encrypt_stream (CHACHA20_context_t * ctx,
       n = ctx->unused;
       if (n > length)
         n = length;
+
       buf_xor (outbuf, inbuf, p + CHACHA20_BLOCK_SIZE - ctx->unused, n);
       length -= n;
       outbuf += n;
       inbuf += n;
       ctx->unused -= n;
+
       if (!length)
         return;
       gcry_assert (!ctx->unused);
     }
 
-  if (length >= CHACHA20_BLOCK_SIZE)
+  nburn = do_chacha20_encrypt_stream_tail (ctx, outbuf, inbuf, length);
+  burn = nburn > burn ? nburn : burn;
+
+  if (burn)
+    _gcry_burn_stack (burn);
+}
+
+
+gcry_err_code_t
+_gcry_chacha20_poly1305_encrypt(gcry_cipher_hd_t c, byte *outbuf,
+                               const byte *inbuf, size_t length)
+{
+  CHACHA20_context_t *ctx = (void *) &c->context.c;
+  unsigned int nburn, burn = 0;
+  byte *authptr = NULL;
+
+  if (!length)
+    return 0;
+
+  if (ctx->unused)
     {
-      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
-      size_t bytes = nblocks * CHACHA20_BLOCK_SIZE;
-      burn = ctx->blocks(ctx->input, inbuf, outbuf, bytes);
-      length -= bytes;
-      outbuf += bytes;
-      inbuf  += bytes;
+      unsigned char *p = ctx->pad;
+      size_t n;
+
+      gcry_assert (ctx->unused < CHACHA20_BLOCK_SIZE);
+
+      n = ctx->unused;
+      if (n > length)
+        n = length;
+
+      buf_xor (outbuf, inbuf, p + CHACHA20_BLOCK_SIZE - ctx->unused, n);
+      nburn = _gcry_poly1305_update_burn (&c->u_mode.poly1305.ctx, outbuf, n);
+      burn = nburn > burn ? nburn : burn;
+      length -= n;
+      outbuf += n;
+      inbuf += n;
+      ctx->unused -= n;
+
+      if (!length)
+       {
+         if (burn)
+           _gcry_burn_stack (burn);
+
+         return 0;
+       }
+      gcry_assert (!ctx->unused);
     }
 
-  if (length > 0)
+  gcry_assert (c->u_mode.poly1305.ctx.leftover == 0);
+
+  if (0)
+    { }
+#ifdef USE_AVX2
+  else if (ctx->use_avx2 && length >= CHACHA20_BLOCK_SIZE * 8)
     {
-      nburn = chacha20_core (ctx->pad, ctx);
+      nburn = _gcry_chacha20_amd64_avx2_blocks8(ctx->input, outbuf, inbuf, 8);
       burn = nburn > burn ? nburn : burn;
 
-      buf_xor (outbuf, inbuf, ctx->pad, length);
-      ctx->unused = CHACHA20_BLOCK_SIZE - length;
+      authptr = outbuf;
+      length -= 8 * CHACHA20_BLOCK_SIZE;
+      outbuf += 8 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 8 * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+#ifdef USE_SSSE3
+  else if (ctx->use_ssse3 && length >= CHACHA20_BLOCK_SIZE * 4)
+    {
+      nburn = _gcry_chacha20_amd64_ssse3_blocks4(ctx->input, outbuf, inbuf, 4);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 4 * CHACHA20_BLOCK_SIZE;
+      outbuf += 4 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 4 * CHACHA20_BLOCK_SIZE;
+    }
+  else if (ctx->use_ssse3 && length >= CHACHA20_BLOCK_SIZE * 2)
+    {
+      nburn = _gcry_chacha20_amd64_ssse3_blocks1(ctx->input, outbuf, inbuf, 2);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 2 * CHACHA20_BLOCK_SIZE;
+      outbuf += 2 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 2 * CHACHA20_BLOCK_SIZE;
+    }
+  else if (ctx->use_ssse3 && length >= CHACHA20_BLOCK_SIZE)
+    {
+      nburn = _gcry_chacha20_amd64_ssse3_blocks1(ctx->input, outbuf, inbuf, 1);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 1 * CHACHA20_BLOCK_SIZE;
+      outbuf += 1 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 1 * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+#ifdef USE_AARCH64_SIMD
+  else if (ctx->use_neon && length >= CHACHA20_BLOCK_SIZE * 4)
+    {
+      nburn = _gcry_chacha20_aarch64_blocks4(ctx->input, outbuf, inbuf, 4);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 4 * CHACHA20_BLOCK_SIZE;
+      outbuf += 4 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 4 * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+#ifdef USE_PPC_VEC_POLY1305
+  else if (ctx->use_ppc && length >= CHACHA20_BLOCK_SIZE * 4)
+    {
+      nburn = _gcry_chacha20_ppc8_blocks4(ctx->input, outbuf, inbuf, 4);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 4 * CHACHA20_BLOCK_SIZE;
+      outbuf += 4 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 4 * CHACHA20_BLOCK_SIZE;
     }
+#endif
+#ifdef USE_S390X_VX_POLY1305
+  else if (ctx->use_s390x && length >= 2 * CHACHA20_BLOCK_SIZE * 8)
+    {
+      nburn = _gcry_chacha20_s390x_vx_blocks8(ctx->input, outbuf, inbuf, 8);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 8 * CHACHA20_BLOCK_SIZE;
+      outbuf += 8 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 8 * CHACHA20_BLOCK_SIZE;
+    }
+  else if (ctx->use_s390x && length >= CHACHA20_BLOCK_SIZE * 4)
+    {
+      nburn = _gcry_chacha20_s390x_vx_blocks4_2_1(ctx->input, outbuf, inbuf, 4);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 4 * CHACHA20_BLOCK_SIZE;
+      outbuf += 4 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 4 * CHACHA20_BLOCK_SIZE;
+    }
+  else if (ctx->use_s390x && length >= CHACHA20_BLOCK_SIZE * 2)
+    {
+      nburn = _gcry_chacha20_s390x_vx_blocks4_2_1(ctx->input, outbuf, inbuf, 2);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 2 * CHACHA20_BLOCK_SIZE;
+      outbuf += 2 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 2 * CHACHA20_BLOCK_SIZE;
+    }
+  else if (ctx->use_s390x && length >= CHACHA20_BLOCK_SIZE)
+    {
+      nburn = _gcry_chacha20_s390x_vx_blocks4_2_1(ctx->input, outbuf, inbuf, 1);
+      burn = nburn > burn ? nburn : burn;
+
+      authptr = outbuf;
+      length -= 1 * CHACHA20_BLOCK_SIZE;
+      outbuf += 1 * CHACHA20_BLOCK_SIZE;
+      inbuf  += 1 * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+
+  if (authptr)
+    {
+      size_t authoffset = outbuf - authptr;
+
+#ifdef USE_AVX2
+      if (ctx->use_avx2 &&
+         length >= 8 * CHACHA20_BLOCK_SIZE &&
+         authoffset >= 8 * CHACHA20_BLOCK_SIZE)
+       {
+         size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+         nblocks -= nblocks % 8;
+
+         nburn = _gcry_chacha20_poly1305_amd64_avx2_blocks8(
+                     ctx->input, outbuf, inbuf, nblocks,
+                     &c->u_mode.poly1305.ctx.state, authptr);
+         burn = nburn > burn ? nburn : burn;
+
+         length  -= nblocks * CHACHA20_BLOCK_SIZE;
+         outbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+         inbuf   += nblocks * CHACHA20_BLOCK_SIZE;
+         authptr += nblocks * CHACHA20_BLOCK_SIZE;
+       }
+#endif
+
+#ifdef USE_SSSE3
+      if (ctx->use_ssse3)
+       {
+         if (length >= 4 * CHACHA20_BLOCK_SIZE &&
+             authoffset >= 4 * CHACHA20_BLOCK_SIZE)
+           {
+             size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+             nblocks -= nblocks % 4;
+
+             nburn = _gcry_chacha20_poly1305_amd64_ssse3_blocks4(
+                         ctx->input, outbuf, inbuf, nblocks,
+                         &c->u_mode.poly1305.ctx.state, authptr);
+             burn = nburn > burn ? nburn : burn;
+
+             length  -= nblocks * CHACHA20_BLOCK_SIZE;
+             outbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+             inbuf   += nblocks * CHACHA20_BLOCK_SIZE;
+             authptr += nblocks * CHACHA20_BLOCK_SIZE;
+           }
+
+         if (length >= CHACHA20_BLOCK_SIZE &&
+             authoffset >= CHACHA20_BLOCK_SIZE)
+           {
+             size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+
+             nburn = _gcry_chacha20_poly1305_amd64_ssse3_blocks1(
+                         ctx->input, outbuf, inbuf, nblocks,
+                         &c->u_mode.poly1305.ctx.state, authptr);
+             burn = nburn > burn ? nburn : burn;
+
+             length  -= nblocks * CHACHA20_BLOCK_SIZE;
+             outbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+             inbuf   += nblocks * CHACHA20_BLOCK_SIZE;
+             authptr += nblocks * CHACHA20_BLOCK_SIZE;
+           }
+       }
+#endif
+
+#ifdef USE_AARCH64_SIMD
+      if (ctx->use_neon &&
+         length >= 4 * CHACHA20_BLOCK_SIZE &&
+         authoffset >= 4 * CHACHA20_BLOCK_SIZE)
+       {
+         size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+         nblocks -= nblocks % 4;
+
+         nburn = _gcry_chacha20_poly1305_aarch64_blocks4(
+                     ctx->input, outbuf, inbuf, nblocks,
+                     &c->u_mode.poly1305.ctx.state, authptr);
+         burn = nburn > burn ? nburn : burn;
+
+         length  -= nblocks * CHACHA20_BLOCK_SIZE;
+         outbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+         inbuf   += nblocks * CHACHA20_BLOCK_SIZE;
+         authptr += nblocks * CHACHA20_BLOCK_SIZE;
+       }
+#endif
+
+#ifdef USE_PPC_VEC_POLY1305
+      if (ctx->use_ppc &&
+         length >= 4 * CHACHA20_BLOCK_SIZE &&
+         authoffset >= 4 * CHACHA20_BLOCK_SIZE)
+       {
+         size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+         nblocks -= nblocks % 4;
+
+         nburn = _gcry_chacha20_poly1305_ppc8_blocks4(
+                     ctx->input, outbuf, inbuf, nblocks,
+                     &c->u_mode.poly1305.ctx.state, authptr);
+         burn = nburn > burn ? nburn : burn;
+
+         length  -= nblocks * CHACHA20_BLOCK_SIZE;
+         outbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+         inbuf   += nblocks * CHACHA20_BLOCK_SIZE;
+         authptr += nblocks * CHACHA20_BLOCK_SIZE;
+       }
+#endif
+
+#ifdef USE_S390X_VX_POLY1305
+      if (ctx->use_s390x)
+       {
+         if (length >= 8 * CHACHA20_BLOCK_SIZE &&
+             authoffset >= 8 * CHACHA20_BLOCK_SIZE)
+           {
+             size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+             nblocks -= nblocks % 8;
+
+             burn = _gcry_chacha20_poly1305_s390x_vx_blocks8(
+                         ctx->input, outbuf, inbuf, nblocks,
+                         &c->u_mode.poly1305.ctx.state, authptr);
+             burn = nburn > burn ? nburn : burn;
+
+             length  -= nblocks * CHACHA20_BLOCK_SIZE;
+             outbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+             inbuf   += nblocks * CHACHA20_BLOCK_SIZE;
+             authptr += nblocks * CHACHA20_BLOCK_SIZE;
+           }
+
+         if (length >= CHACHA20_BLOCK_SIZE &&
+             authoffset >= CHACHA20_BLOCK_SIZE)
+           {
+             size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+
+             burn = _gcry_chacha20_poly1305_s390x_vx_blocks4_2_1(
+                         ctx->input, outbuf, inbuf, nblocks,
+                         &c->u_mode.poly1305.ctx.state, authptr);
+             burn = nburn > burn ? nburn : burn;
+
+             length  -= nblocks * CHACHA20_BLOCK_SIZE;
+             outbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+             inbuf   += nblocks * CHACHA20_BLOCK_SIZE;
+             authptr += nblocks * CHACHA20_BLOCK_SIZE;
+           }
+       }
+#endif
+
+      if (authoffset > 0)
+       {
+         _gcry_poly1305_update (&c->u_mode.poly1305.ctx, authptr, authoffset);
+         authptr += authoffset;
+         authoffset = 0;
+       }
+
+      gcry_assert(authptr == outbuf);
+    }
+
+  while (length)
+    {
+      size_t currlen = length;
+
+      /* Since checksumming is done after encryption, process input in 24KiB
+       * chunks to keep data loaded in L1 cache for checksumming. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
 
-  _gcry_burn_stack (burn);
+      nburn = do_chacha20_encrypt_stream_tail (ctx, outbuf, inbuf, currlen);
+      burn = nburn > burn ? nburn : burn;
+
+      nburn = _gcry_poly1305_update_burn (&c->u_mode.poly1305.ctx, outbuf,
+                                         currlen);
+      burn = nburn > burn ? nburn : burn;
+
+      outbuf += currlen;
+      inbuf += currlen;
+      length -= currlen;
+    }
+
+  if (burn)
+    _gcry_burn_stack (burn);
+
+  return 0;
 }
 
 
-static void
-chacha20_encrypt_stream (void *context, byte * outbuf, const byte * inbuf,
-                         size_t length)
+gcry_err_code_t
+_gcry_chacha20_poly1305_decrypt(gcry_cipher_hd_t c, byte *outbuf,
+                               const byte *inbuf, size_t length)
 {
-  CHACHA20_context_t *ctx = (CHACHA20_context_t *) context;
+  CHACHA20_context_t *ctx = (void *) &c->context.c;
+  unsigned int nburn, burn = 0;
+
+  if (!length)
+    return 0;
+
+  if (ctx->unused)
+    {
+      unsigned char *p = ctx->pad;
+      size_t n;
+
+      gcry_assert (ctx->unused < CHACHA20_BLOCK_SIZE);
 
-  if (length)
-    chacha20_do_encrypt_stream (ctx, outbuf, inbuf, length);
+      n = ctx->unused;
+      if (n > length)
+        n = length;
+
+      nburn = _gcry_poly1305_update_burn (&c->u_mode.poly1305.ctx, inbuf, n);
+      burn = nburn > burn ? nburn : burn;
+      buf_xor (outbuf, inbuf, p + CHACHA20_BLOCK_SIZE - ctx->unused, n);
+      length -= n;
+      outbuf += n;
+      inbuf += n;
+      ctx->unused -= n;
+
+      if (!length)
+       {
+         if (burn)
+           _gcry_burn_stack (burn);
+
+         return 0;
+       }
+      gcry_assert (!ctx->unused);
+    }
+
+  gcry_assert (c->u_mode.poly1305.ctx.leftover == 0);
+
+#ifdef USE_AVX2
+  if (ctx->use_avx2 && length >= 8 * CHACHA20_BLOCK_SIZE)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 8;
+
+      nburn = _gcry_chacha20_poly1305_amd64_avx2_blocks8(
+                       ctx->input, outbuf, inbuf, nblocks,
+                       &c->u_mode.poly1305.ctx.state, inbuf);
+      burn = nburn > burn ? nburn : burn;
+
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+
+#ifdef USE_SSSE3
+  if (ctx->use_ssse3)
+    {
+      if (length >= 4 * CHACHA20_BLOCK_SIZE)
+       {
+         size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+         nblocks -= nblocks % 4;
+
+         nburn = _gcry_chacha20_poly1305_amd64_ssse3_blocks4(
+                           ctx->input, outbuf, inbuf, nblocks,
+                           &c->u_mode.poly1305.ctx.state, inbuf);
+         burn = nburn > burn ? nburn : burn;
+
+         length -= nblocks * CHACHA20_BLOCK_SIZE;
+         outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+         inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+       }
+
+      if (length >= CHACHA20_BLOCK_SIZE)
+       {
+         size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+
+         nburn = _gcry_chacha20_poly1305_amd64_ssse3_blocks1(
+                           ctx->input, outbuf, inbuf, nblocks,
+                           &c->u_mode.poly1305.ctx.state, inbuf);
+         burn = nburn > burn ? nburn : burn;
+
+         length -= nblocks * CHACHA20_BLOCK_SIZE;
+         outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+         inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+       }
+    }
+#endif
+
+#ifdef USE_AARCH64_SIMD
+  if (ctx->use_neon && length >= 4 * CHACHA20_BLOCK_SIZE)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 4;
+
+      nburn = _gcry_chacha20_poly1305_aarch64_blocks4(
+                       ctx->input, outbuf, inbuf, nblocks,
+                       &c->u_mode.poly1305.ctx.state, inbuf);
+      burn = nburn > burn ? nburn : burn;
+
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+
+#ifdef USE_PPC_VEC_POLY1305
+  if (ctx->use_ppc && length >= 4 * CHACHA20_BLOCK_SIZE)
+    {
+      size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+      nblocks -= nblocks % 4;
+
+      nburn = _gcry_chacha20_poly1305_ppc8_blocks4(
+                       ctx->input, outbuf, inbuf, nblocks,
+                       &c->u_mode.poly1305.ctx.state, inbuf);
+      burn = nburn > burn ? nburn : burn;
+
+      length -= nblocks * CHACHA20_BLOCK_SIZE;
+      outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+      inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+    }
+#endif
+
+#ifdef USE_S390X_VX_POLY1305
+  if (ctx->use_s390x)
+    {
+      if (length >= 8 * CHACHA20_BLOCK_SIZE)
+       {
+         size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+         nblocks -= nblocks % 8;
+
+         nburn = _gcry_chacha20_poly1305_s390x_vx_blocks8(
+                           ctx->input, outbuf, inbuf, nblocks,
+                           &c->u_mode.poly1305.ctx.state, inbuf);
+         burn = nburn > burn ? nburn : burn;
+
+         length -= nblocks * CHACHA20_BLOCK_SIZE;
+         outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+         inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+       }
+
+      if (length >= CHACHA20_BLOCK_SIZE)
+       {
+         size_t nblocks = length / CHACHA20_BLOCK_SIZE;
+
+         nburn = _gcry_chacha20_poly1305_s390x_vx_blocks4_2_1(
+                           ctx->input, outbuf, inbuf, nblocks,
+                           &c->u_mode.poly1305.ctx.state, inbuf);
+         burn = nburn > burn ? nburn : burn;
+
+         length -= nblocks * CHACHA20_BLOCK_SIZE;
+         outbuf += nblocks * CHACHA20_BLOCK_SIZE;
+         inbuf  += nblocks * CHACHA20_BLOCK_SIZE;
+       }
+    }
+#endif
+
+  while (length)
+    {
+      size_t currlen = length;
+
+      /* Since checksumming is done before decryption, process input in 24KiB
+       * chunks to keep data loaded in L1 cache for decryption. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
+
+      nburn = _gcry_poly1305_update_burn (&c->u_mode.poly1305.ctx, inbuf,
+                                         currlen);
+      burn = nburn > burn ? nburn : burn;
+
+      nburn = do_chacha20_encrypt_stream_tail (ctx, outbuf, inbuf, currlen);
+      burn = nburn > burn ? nburn : burn;
+
+      outbuf += currlen;
+      inbuf += currlen;
+      length -= currlen;
+    }
+
+  if (burn)
+    _gcry_burn_stack (burn);
+
+  return 0;
 }
 
 
@@ -569,7 +1238,7 @@ selftest (void)
   /* 16-byte alignment required for amd64 implementation. */
   ctx = (CHACHA20_context_t *)((uintptr_t)(ctxbuf + 15) & ~(uintptr_t)15);
 
-  chacha20_setkey (ctx, key_1, sizeof key_1);
+  chacha20_setkey (ctx, key_1, sizeof key_1, NULL);
   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
   scratch[sizeof (scratch) - 1] = 0;
   chacha20_encrypt_stream (ctx, scratch, plaintext_1, sizeof plaintext_1);
@@ -577,7 +1246,7 @@ selftest (void)
     return "ChaCha20 encryption test 1 failed.";
   if (scratch[sizeof (scratch) - 1])
     return "ChaCha20 wrote too much.";
-  chacha20_setkey (ctx, key_1, sizeof (key_1));
+  chacha20_setkey (ctx, key_1, sizeof (key_1), NULL);
   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
   chacha20_encrypt_stream (ctx, scratch, scratch, sizeof plaintext_1);
   if (memcmp (scratch, plaintext_1, sizeof plaintext_1))
@@ -585,12 +1254,12 @@ selftest (void)
 
   for (i = 0; i < sizeof buf; i++)
     buf[i] = i;
-  chacha20_setkey (ctx, key_1, sizeof key_1);
+  chacha20_setkey (ctx, key_1, sizeof key_1, NULL);
   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
   /*encrypt */
   chacha20_encrypt_stream (ctx, buf, buf, sizeof buf);
   /*decrypt */
-  chacha20_setkey (ctx, key_1, sizeof key_1);
+  chacha20_setkey (ctx, key_1, sizeof key_1, NULL);
   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
   chacha20_encrypt_stream (ctx, buf, buf, 1);
   chacha20_encrypt_stream (ctx, buf + 1, buf + 1, (sizeof buf) - 1 - 1);
@@ -600,13 +1269,13 @@ selftest (void)
     if (buf[i] != (byte) i)
       return "ChaCha20 encryption test 2 failed.";
 
-  chacha20_setkey (ctx, key_1, sizeof key_1);
+  chacha20_setkey (ctx, key_1, sizeof key_1, NULL);
   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
   /* encrypt */
   for (i = 0; i < sizeof buf; i++)
     chacha20_encrypt_stream (ctx, &buf[i], &buf[i], 1);
   /* decrypt */
-  chacha20_setkey (ctx, key_1, sizeof key_1);
+  chacha20_setkey (ctx, key_1, sizeof key_1, NULL);
   chacha20_setiv (ctx, nonce_1, sizeof nonce_1);
   chacha20_encrypt_stream (ctx, buf, buf, sizeof buf);
   for (i = 0; i < sizeof buf; i++)
index a8d0e03..76c64fb 100644 (file)
 #include "bufhelp.h"
 #include "./cipher-internal.h"
 
-
-/* Perform the AES-Wrap algorithm as specified by RFC3394.  We
-   implement this as a mode usable with any cipher algorithm of
-   blocksize 128.  */
-gcry_err_code_t
-_gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
-                              byte *outbuf, size_t outbuflen,
-                              const byte *inbuf, size_t inbuflen )
+/* Perform the wrap algorithm W as specified by NIST SP 800-38F.
+   Cipher block size must be 128-bit.  */
+static gcry_err_code_t
+wrap (gcry_cipher_hd_t c, byte *outbuf, size_t inbuflen)
 {
   int j, x;
   size_t n, i;
@@ -50,18 +46,14 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
   if (c->spec->blocksize != 16)
     return GPG_ERR_INV_LENGTH;
 
-  /* The output buffer must be able to hold the input data plus one
-     additional block.  */
-  if (outbuflen < inbuflen + 8)
-    return GPG_ERR_BUFFER_TOO_SHORT;
   /* Input data must be multiple of 64 bits.  */
   if (inbuflen % 8)
     return GPG_ERR_INV_ARG;
 
   n = inbuflen / 8;
 
-  /* We need at least two 64 bit blocks.  */
-  if (n < 2)
+  /* We need at least three 64 bit blocks.  */
+  if (n < 3)
     return GPG_ERR_INV_ARG;
 
   burn = 0;
@@ -70,36 +62,23 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
   a = outbuf;  /* We store A directly in OUTBUF.  */
   b = c->u_ctr.ctr;  /* B is also used to concatenate stuff.  */
 
-  /* Copy the inbuf to the outbuf. */
-  memmove (r+8, inbuf, inbuflen);
-
-  /* If an IV has been set we use that IV as the Alternative Initial
-     Value; if it has not been set we use the standard value.  */
-  if (c->marks.iv)
-    memcpy (a, c->u_iv.iv, 8);
-  else
-    memset (a, 0xa6, 8);
-
   memset (t, 0, sizeof t); /* t := 0.  */
 
   for (j = 0; j <= 5; j++)
     {
-      for (i = 1; i <= n; i++)
+      for (i = 1; i < n; i++)
         {
-          /* B := AES_k( A | R[i] ) */
+          /* B := CIPH_k( A | R[i] ) */
           memcpy (b, a, 8);
           memcpy (b+8, r+i*8, 8);
           nburn = c->spec->encrypt (&c->context.c, b, b);
           burn = nburn > burn ? nburn : burn;
           /* t := t + 1  */
-         for (x = 7; x >= 0; x--)
-           {
-             t[x]++;
-             if (t[x])
-               break;
-           }
+          for (x = 7; x >= 0; x--)
+            if (++t[x])
+              break;
           /* A := MSB_64(B) ^ t */
-         buf_xor(a, b, t, 8);
+          cipher_block_xor (a, b, t, 8);
           /* R[i] := LSB_64(B) */
           memcpy (r+i*8, b+8, 8);
         }
@@ -111,14 +90,106 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
   return 0;
 }
 
-/* Perform the AES-Unwrap algorithm as specified by RFC3394.  We
+
+/* Perform the Key Wrap algorithm as specified by RFC3394.  We
    implement this as a mode usable with any cipher algorithm of
    blocksize 128.  */
 gcry_err_code_t
-_gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c,
+_gcry_cipher_keywrap_encrypt (gcry_cipher_hd_t c,
                               byte *outbuf, size_t outbuflen,
                               const byte *inbuf, size_t inbuflen)
 {
+  gcry_err_code_t err;
+  unsigned char *r = outbuf;
+
+  /* We require a cipher with a 128 bit block length.  */
+  if (c->spec->blocksize != 16)
+    return GPG_ERR_INV_LENGTH;
+
+  /* The output buffer must be able to hold the input data plus one
+     additional block.  */
+  if (outbuflen < inbuflen + 8)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+  /* Input data must be multiple of 64 bits.  */
+  if (inbuflen % 8)
+    return GPG_ERR_INV_ARG;
+
+  /* We need at least two 64 bit blocks.  */
+  if ((inbuflen / 8) < 2)
+    return GPG_ERR_INV_ARG;
+
+  /* Copy the inbuf to the outbuf. */
+  memmove (r+8, inbuf, inbuflen);
+
+  /* If an IV has been set we use that IV as the Alternative Initial
+     Value; if it has not been set we use the standard value.  */
+  if (c->marks.iv)
+    memcpy (r, c->u_iv.iv, 8);
+  else
+    memset (r, 0xa6, 8);
+
+  err = wrap (c, r, inbuflen + 8);
+
+  return err;
+}
+
+
+static const unsigned char icv2[] = { 0xA6, 0x59, 0x59, 0xA6 };
+
+/* Perform the Key Wrap algorithm as specified by RFC5649.  */
+gcry_err_code_t
+_gcry_cipher_keywrap_encrypt_padding (gcry_cipher_hd_t c,
+                                      byte *outbuf, size_t outbuflen,
+                                      const byte *inbuf, size_t inbuflen)
+{
+  gcry_err_code_t err;
+  unsigned char *r = outbuf;
+  unsigned int padlen;
+
+  /* We require a cipher with a 128 bit block length.  */
+  if (c->spec->blocksize != 16)
+    return GPG_ERR_INV_LENGTH;
+
+  /* The output buffer must be able to hold the input data plus one
+     additional block and padding.  */
+  if (outbuflen < ((inbuflen + 7)/8)*8 + 8)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+
+  if (inbuflen % 8)
+    padlen = 8 - (inbuflen % 8);
+  else
+    padlen = 0;
+
+  memcpy (r, icv2, 4);
+  r[4] = ((inbuflen >> 24) & 0xff);
+  r[5] = ((inbuflen >> 16) & 0xff);
+  r[6] = ((inbuflen >> 8) & 0xff);
+  r[7] = (inbuflen & 0xff);
+  memcpy (r+8, inbuf, inbuflen);
+  if (padlen)
+    memset (r+8+inbuflen, 0, padlen);
+
+  if (inbuflen <= 8)
+    {
+      unsigned int burn;
+
+      burn = c->spec->encrypt (&c->context.c, r, r);
+      if (burn > 0)
+        _gcry_burn_stack (burn + 4 * sizeof(void *));
+      err = 0;
+    }
+  else
+    err = wrap (c, r, ((inbuflen + 7)/8)*8 + 8);
+
+  return err;
+}
+
+
+/* Perform the unwrap algorithm W^-1 as specified by NIST SP 800-38F.
+   Cipher block size must be 128-bit.  */
+static gcry_err_code_t
+unwrap (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, size_t inbuflen)
+{
   int j, x;
   size_t n, i;
   unsigned char *r, *a, *b;
@@ -132,11 +203,6 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c,
   if (c->spec->blocksize != 16)
     return GPG_ERR_INV_LENGTH;
 
-  /* The output buffer must be able to hold the input data minus one
-     additional block.  Fixme: The caller has more restrictive checks
-     - we may want to fix them for this mode.  */
-  if (outbuflen + 8  < inbuflen)
-    return GPG_ERR_BUFFER_TOO_SHORT;
   /* Input data must be multiple of 64 bits.  */
   if (inbuflen % 8)
     return GPG_ERR_INV_ARG;
@@ -169,41 +235,146 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c,
     {
       for (i = n; i >= 1; i--)
         {
-          /* B := AES_k^1( (A ^ t)| R[i] ) */
-         buf_xor(b, a, t, 8);
+          /* B := CIPH_k^-1( (A ^ t)| R[i] ) */
+          cipher_block_xor (b, a, t, 8);
           memcpy (b+8, r+(i-1)*8, 8);
           nburn = c->spec->decrypt (&c->context.c, b, b);
           burn = nburn > burn ? nburn : burn;
           /* t := t - 1  */
-         for (x = 7; x >= 0; x--)
-           {
-             t[x]--;
-             if (t[x] != 0xff)
-               break;
-           }
+          for (x = 7; x >= 0; x--)
+            if (--t[x] != 0xff)
+              break;
           /* A := MSB_64(B) */
           memcpy (a, b, 8);
           /* R[i] := LSB_64(B) */
           memcpy (r+(i-1)*8, b+8, 8);
         }
    }
+  wipememory (b, 16);  /* Clear scratch area.  */
 
-  /* If an IV has been set we compare against this Alternative Initial
-     Value; if it has not been set we compare against the standard IV.  */
-  if (c->marks.iv)
-    j = memcmp (a, c->u_iv.iv, 8);
-  else
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
+  return 0;
+}
+
+
+/* Perform the Key Unwrap algorithm as specified by RFC3394 and
+   RFC5649.  */
+gcry_err_code_t
+_gcry_cipher_keywrap_decrypt_auto (gcry_cipher_hd_t c,
+                                   byte *outbuf, size_t outbuflen,
+                                   const byte *inbuf, size_t inbuflen)
+{
+  gcry_err_code_t err;
+
+  /* We require a cipher with a 128 bit block length.  */
+  if (c->spec->blocksize != 16)
+    return GPG_ERR_INV_LENGTH;
+
+  /* The output buffer must be able to hold the input data minus one
+     additional block.  Fixme: The caller has more restrictive checks
+     - we may want to fix them for this mode.  */
+  if (outbuflen + 8 < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+  /* Input data must be multiple of 64 bits.  */
+  if (inbuflen % 8)
+    return GPG_ERR_INV_ARG;
+
+  if (inbuflen == 16)
     {
-      for (j=0, x=0; x < 8; x++)
-        if (a[x] != 0xa6)
-          {
-            j=1;
-            break;
-          }
+      unsigned int burn;
+      unsigned char t[16];
+
+      if (!(c->flags & GCRY_CIPHER_EXTENDED))
+        return GPG_ERR_BUFFER_TOO_SHORT;
+
+      burn = c->spec->decrypt (&c->context.c, t, inbuf);
+      if (burn > 0)
+        _gcry_burn_stack (burn + 4 * sizeof(void *));
+
+      if (memcmp (t, icv2, 4))
+        err = GPG_ERR_CHECKSUM;
+      else
+        {
+          unsigned int plen = (t[4]<<24) | (t[5]<<16) | (t[6]<<8) | t[7];
+
+          err = 0;
+          if (plen > 8)
+            err = GPG_ERR_CHECKSUM;
+          else if (plen)
+            {
+              int i;
+
+              for (i = 0; i < 16 - (8+plen); i++)
+                if (t[8+plen+i])
+                  {
+                    err = GPG_ERR_CHECKSUM;
+                    break;
+                  }
+              if (!err)
+                {
+                  memcpy (outbuf, t+8, 8);
+                  memcpy (c->u_mode.wrap.plen, t+4, 4);
+                }
+            }
+        }
     }
+  else
+    {
+      /* We need at least three 64 bit blocks.  */
+      if ((inbuflen / 8) < 3)
+        return GPG_ERR_INV_ARG;
 
-  if (burn > 0)
-    _gcry_burn_stack (burn + 4 * sizeof(void *));
+      err = unwrap (c, outbuf, inbuf, inbuflen);
+      if (!err)
+        {
+          unsigned char *a;
+
+          a = c->lastiv;  /* We use c->LASTIV as buffer for A.  */
+
+          /* If an IV has been set we compare against this Alternative Initial
+             Value; if it has not been set we compare against the standard IV.  */
+          if (c->marks.iv && !memcmp (a, c->u_iv.iv, 8))
+            memset (c->u_mode.wrap.plen, 0, 4);
+          else if (!memcmp (a, icv2, 4)) /* It's a packet wrapped by KWP.  */
+            {
+              unsigned int plen = (a[4]<<24) | (a[5]<<16) | (a[6]<<8) | a[7];
+              int padlen = inbuflen - 8 - plen;
+
+              if (!(c->flags & GCRY_CIPHER_EXTENDED))
+                err = GPG_ERR_CHECKSUM;
+              else if (padlen < 0 || padlen > 7)
+                err = GPG_ERR_CHECKSUM;
+              else if (padlen)
+                {
+                  int i;
+
+                  for (i = 0; i < padlen; i++)
+                    if (outbuf[plen+i])
+                      {
+                        err = GPG_ERR_CHECKSUM;
+                        break;
+                      }
+                }
+              if (!err)
+                memcpy (c->u_mode.wrap.plen, a+4, 4);
+            }
+          else                  /* It's a packet wrapped by KW.  */
+            {
+              int i;
+
+              for (i = 0; i < 8; i++)
+                if (a[i] != 0xa6)
+                  {
+                    err = GPG_ERR_CHECKSUM;
+                    break;
+                  }
+              if (!err)
+                memset (c->u_mode.wrap.plen, 0, 4);
+            }
+        }
+    }
 
-  return j? GPG_ERR_CHECKSUM : 0;
+  return err;
 }
index 95c49b2..d4df1e7 100644 (file)
 
 
 
-gcry_err_code_t
-_gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
-                          unsigned char *outbuf, size_t outbuflen,
-                          const unsigned char *inbuf, size_t inbuflen)
+static inline unsigned int
+cbc_encrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf,
+                  const unsigned char *inbuf, size_t nblocks, size_t blocksize,
+                  int is_cbc_cmac)
 {
-  size_t n;
-  unsigned char *ivp;
-  int i;
-  size_t blocksize = c->spec->blocksize;
-  gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
-  size_t nblocks = inbuflen / blocksize;
-  unsigned int burn, nburn;
-
-  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
-   * length, to allow better optimization of this function.  */
-  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return GPG_ERR_INV_LENGTH;
-
-  if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen))
-    return GPG_ERR_BUFFER_TOO_SHORT;
 
-  if ((inbuflen % blocksize)
-      && !(inbuflen > blocksize
-           && (c->flags & GCRY_CIPHER_CBC_CTS)))
-    return GPG_ERR_INV_LENGTH;
+  unsigned int burn, nburn;
+  size_t n;
 
   burn = 0;
 
-  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
-    {
-      if ((inbuflen % blocksize) == 0)
-       nblocks--;
-    }
-
   if (c->bulk.cbc_enc)
     {
       c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks,
-                       (c->flags & GCRY_CIPHER_CBC_MAC));
-      inbuf  += nblocks * blocksize;
-      if (!(c->flags & GCRY_CIPHER_CBC_MAC))
-        outbuf += nblocks * blocksize;
+                       is_cbc_cmac);
     }
   else
     {
+      gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
+      unsigned char *ivp;
+
       ivp = c->u_iv.iv;
 
       for (n=0; n < nblocks; n++ )
         {
-          buf_xor (outbuf, inbuf, ivp, blocksize);
+          cipher_block_xor (outbuf, inbuf, ivp, blocksize);
           nburn = enc_fn ( &c->context.c, outbuf, outbuf );
           burn = nburn > burn ? nburn : burn;
           ivp = outbuf;
-          inbuf  += blocksize;
-          if (!(c->flags & GCRY_CIPHER_CBC_MAC))
+          inbuf += blocksize;
+          if (!is_cbc_cmac)
             outbuf += blocksize;
         }
 
       if (ivp != c->u_iv.iv)
-        buf_cpy (c->u_iv.iv, ivp, blocksize );
+        cipher_block_cpy (c->u_iv.iv, ivp, blocksize);
+    }
+
+  return burn;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
+                          unsigned char *outbuf, size_t outbuflen,
+                          const unsigned char *inbuf, size_t inbuflen)
+{
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
+  size_t blocksize_mask = blocksize - 1;
+  size_t nblocks = inbuflen >> blocksize_shift;
+  int is_cbc_cmac = !!(c->flags & GCRY_CIPHER_CBC_MAC);
+  unsigned int burn;
+
+  if (outbuflen < (is_cbc_cmac ? blocksize : inbuflen))
+    return GPG_ERR_BUFFER_TOO_SHORT;
+
+  if (inbuflen & blocksize_mask)
+    return GPG_ERR_INV_LENGTH;
+
+  burn = cbc_encrypt_inner(c, outbuf, inbuf, nblocks, blocksize, is_cbc_cmac);
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_cbc_cts_encrypt (gcry_cipher_hd_t c,
+                              unsigned char *outbuf, size_t outbuflen,
+                              const unsigned char *inbuf, size_t inbuflen)
+{
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
+  size_t blocksize_mask = blocksize - 1;
+  gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
+  size_t nblocks = inbuflen >> blocksize_shift;
+  unsigned int burn, nburn;
+  unsigned char *ivp;
+  int i;
+
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+
+  if ((inbuflen & blocksize_mask) && !(inbuflen > blocksize))
+    return GPG_ERR_INV_LENGTH;
+
+  burn = 0;
+
+  if (inbuflen > blocksize)
+    {
+      if ((inbuflen & blocksize_mask) == 0)
+       nblocks--;
     }
 
-  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
+  burn = cbc_encrypt_inner(c, outbuf, inbuf, nblocks, blocksize, 0);
+  inbuf += nblocks << blocksize_shift;
+  outbuf += nblocks << blocksize_shift;
+
+  if (inbuflen > blocksize)
     {
       /* We have to be careful here, since outbuf might be equal to
          inbuf.  */
       size_t restbytes;
       unsigned char b;
 
-      if ((inbuflen % blocksize) == 0)
+      if ((inbuflen & blocksize_mask) == 0)
         restbytes = blocksize;
       else
-        restbytes = inbuflen % blocksize;
+        restbytes = inbuflen & blocksize_mask;
 
       outbuf -= blocksize;
       for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++)
@@ -116,7 +156,7 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
 
       nburn = enc_fn (&c->context.c, outbuf, outbuf);
       burn = nburn > burn ? nburn : burn;
-      buf_cpy (c->u_iv.iv, outbuf, blocksize);
+      cipher_block_cpy (c->u_iv.iv, outbuf, blocksize);
     }
 
   if (burn > 0)
@@ -126,72 +166,110 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
 }
 
 
-gcry_err_code_t
-_gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
-                          unsigned char *outbuf, size_t outbuflen,
-                          const unsigned char *inbuf, size_t inbuflen)
+static inline unsigned int
+cbc_decrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf,
+                  const unsigned char *inbuf, size_t nblocks, size_t blocksize)
 {
-  size_t n;
-  int i;
-  size_t blocksize = c->spec->blocksize;
-  gcry_cipher_decrypt_t dec_fn = c->spec->decrypt;
-  size_t nblocks = inbuflen / blocksize;
   unsigned int burn, nburn;
-
-  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
-   * length, to allow better optimization of this function.  */
-  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return GPG_ERR_INV_LENGTH;
-
-  if (outbuflen < inbuflen)
-    return GPG_ERR_BUFFER_TOO_SHORT;
-
-  if ((inbuflen % blocksize)
-      && !(inbuflen > blocksize
-           && (c->flags & GCRY_CIPHER_CBC_CTS)))
-    return GPG_ERR_INV_LENGTH;
+  size_t n;
 
   burn = 0;
 
-  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
-    {
-      nblocks--;
-      if ((inbuflen % blocksize) == 0)
-       nblocks--;
-      buf_cpy (c->lastiv, c->u_iv.iv, blocksize);
-    }
-
   if (c->bulk.cbc_dec)
     {
       c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
-      inbuf  += nblocks * blocksize;
-      outbuf += nblocks * blocksize;
     }
   else
     {
-      for (n=0; n < nblocks; n++ )
+      gcry_cipher_decrypt_t dec_fn = c->spec->decrypt;
+
+      for (n = 0; n < nblocks; n++)
         {
           /* Because outbuf and inbuf might be the same, we must not overwrite
              the original ciphertext block.  We use LASTIV as intermediate
              storage here because it is not used otherwise.  */
           nburn = dec_fn ( &c->context.c, c->lastiv, inbuf );
           burn = nburn > burn ? nburn : burn;
-          buf_xor_n_copy_2(outbuf, c->lastiv, c->u_iv.iv, inbuf, blocksize);
+          cipher_block_xor_n_copy_2 (outbuf, c->lastiv, c->u_iv.iv, inbuf,
+                                     blocksize);
           inbuf  += blocksize;
           outbuf += blocksize;
         }
     }
 
-  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
+  return burn;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
+                          unsigned char *outbuf, size_t outbuflen,
+                          const unsigned char *inbuf, size_t inbuflen)
+{
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
+  size_t blocksize_mask = blocksize - 1;
+  size_t nblocks = inbuflen >> blocksize_shift;
+  unsigned int burn;
+
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+
+  if (inbuflen & blocksize_mask)
+    return GPG_ERR_INV_LENGTH;
+
+  burn = cbc_decrypt_inner(c, outbuf, inbuf, nblocks, blocksize);
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_cbc_cts_decrypt (gcry_cipher_hd_t c,
+                              unsigned char *outbuf, size_t outbuflen,
+                              const unsigned char *inbuf, size_t inbuflen)
+{
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
+  size_t blocksize_mask = blocksize - 1;
+  gcry_cipher_decrypt_t dec_fn = c->spec->decrypt;
+  size_t nblocks = inbuflen >> blocksize_shift;
+  unsigned int burn, nburn;
+  int i;
+
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+
+  if ((inbuflen & blocksize_mask) && !(inbuflen > blocksize))
+    return GPG_ERR_INV_LENGTH;
+
+  burn = 0;
+
+  if (inbuflen > blocksize)
+    {
+      nblocks--;
+      if ((inbuflen & blocksize_mask) == 0)
+       nblocks--;
+      cipher_block_cpy (c->lastiv, c->u_iv.iv, blocksize);
+    }
+
+  burn = cbc_decrypt_inner(c, outbuf, inbuf, nblocks, blocksize);
+  inbuf  += nblocks << blocksize_shift;
+  outbuf += nblocks << blocksize_shift;
+
+  if (inbuflen > blocksize)
     {
       size_t restbytes;
 
-      if ((inbuflen % blocksize) == 0)
+      if ((inbuflen & blocksize_mask) == 0)
         restbytes = blocksize;
       else
-        restbytes = inbuflen % blocksize;
+        restbytes = inbuflen & blocksize_mask;
 
-      buf_cpy (c->lastiv, c->u_iv.iv, blocksize );         /* Save Cn-2. */
+      cipher_block_cpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */
       buf_cpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
 
       nburn = dec_fn ( &c->context.c, outbuf, inbuf );
@@ -203,7 +281,7 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
         c->u_iv.iv[i] = outbuf[i];
       nburn = dec_fn (&c->context.c, outbuf, c->u_iv.iv);
       burn = nburn > burn ? nburn : burn;
-      buf_xor(outbuf, outbuf, c->lastiv, blocksize);
+      cipher_block_xor(outbuf, outbuf, c->lastiv, blocksize);
       /* c->lastiv is now really lastlastiv, does this matter? */
     }
 
index d7f14d8..dcb268d 100644 (file)
@@ -44,6 +44,7 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen,
   unsigned int burn = 0;
   unsigned int unused = c->u_mode.ccm.mac_unused;
   size_t nblocks;
+  size_t n;
 
   if (inlen == 0 && (unused == 0 || !do_padding))
     return 0;
@@ -52,22 +53,31 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen,
     {
       if (inlen + unused < blocksize || unused > 0)
         {
-          for (; inlen && unused < blocksize; inlen--)
-            c->u_mode.ccm.macbuf[unused++] = *inbuf++;
+         n = (inlen > blocksize - unused) ? blocksize - unused : inlen;
+
+         buf_cpy (&c->u_mode.ccm.macbuf[unused], inbuf, n);
+         unused += n;
+         inlen -= n;
+         inbuf += n;
         }
       if (!inlen)
         {
           if (!do_padding)
             break;
 
-          while (unused < blocksize)
-            c->u_mode.ccm.macbuf[unused++] = 0;
+         n = blocksize - unused;
+         if (n > 0)
+           {
+             memset (&c->u_mode.ccm.macbuf[unused], 0, n);
+             unused = blocksize;
+           }
         }
 
       if (unused > 0)
         {
           /* Process one block from macbuf.  */
-          buf_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf, blocksize);
+          cipher_block_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf,
+                           blocksize);
           set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ));
 
           unused = 0;
@@ -86,7 +96,7 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen,
         {
           while (inlen >= blocksize)
             {
-              buf_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize);
+              cipher_block_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize);
 
               set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ));
 
@@ -272,7 +282,7 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
       burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding.  */
 
       /* Add S_0 */
-      buf_xor (c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.s0, 16);
+      cipher_block_xor (c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.s0, 16);
 
       wipememory (c->u_ctr.ctr, 16);
       wipememory (c->u_mode.ccm.s0, 16);
@@ -318,7 +328,9 @@ _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
                           size_t outbuflen, const unsigned char *inbuf,
                           size_t inbuflen)
 {
-  unsigned int burn;
+  gcry_err_code_t err = 0;
+  unsigned int burn = 0;
+  unsigned int nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -328,12 +340,32 @@ _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
   if (inbuflen > c->u_mode.ccm.encryptlen)
     return GPG_ERR_INV_LENGTH;
 
-  c->u_mode.ccm.encryptlen -= inbuflen;
-  burn = do_cbc_mac (c, inbuf, inbuflen, 0);
+  while (inbuflen)
+    {
+      size_t currlen = inbuflen;
+
+      /* Since checksumming is done before encryption, process input in 24KiB
+       * chunks to keep data loaded in L1 cache for encryption. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
+
+      c->u_mode.ccm.encryptlen -= currlen;
+      nburn = do_cbc_mac (c, inbuf, currlen, 0);
+      burn = nburn > burn ? nburn : burn;
+
+      err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, currlen);
+      if (err)
+       break;
+
+      outbuf += currlen;
+      inbuf += currlen;
+      outbuflen -= currlen;
+      inbuflen -= currlen;
+    }
+
   if (burn)
     _gcry_burn_stack (burn + sizeof(void *) * 5);
-
-  return _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+  return err;
 }
 
 
@@ -342,8 +374,9 @@ _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
                           size_t outbuflen, const unsigned char *inbuf,
                           size_t inbuflen)
 {
-  gcry_err_code_t err;
-  unsigned int burn;
+  gcry_err_code_t err = 0;
+  unsigned int burn = 0;
+  unsigned int nburn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
@@ -353,14 +386,30 @@ _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
   if (inbuflen > c->u_mode.ccm.encryptlen)
     return GPG_ERR_INV_LENGTH;
 
-  err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-  if (err)
-    return err;
+  while (inbuflen)
+    {
+      size_t currlen = inbuflen;
+
+      /* Since checksumming is done after decryption, process input in 24KiB
+       * chunks to keep data loaded in L1 cache for checksumming. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
+
+      err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, currlen);
+      if (err)
+       break;
+
+      c->u_mode.ccm.encryptlen -= currlen;
+      nburn = do_cbc_mac (c, outbuf, currlen, 0);
+      burn = nburn > burn ? nburn : burn;
+
+      outbuf += currlen;
+      inbuf += currlen;
+      outbuflen -= currlen;
+      inbuflen -= currlen;
+    }
 
-  c->u_mode.ccm.encryptlen -= inbuflen;
-  burn = do_cbc_mac (c, outbuf, inbuflen, 0);
   if (burn)
     _gcry_burn_stack (burn + sizeof(void *) * 5);
-
   return err;
 }
index c888e70..012c6c1 100644 (file)
@@ -37,15 +37,11 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
 {
   unsigned char *ivp;
   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
-  size_t blocksize = c->spec->blocksize;
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
   size_t blocksize_x_2 = blocksize + blocksize;
   unsigned int burn, nburn;
 
-  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
-   * length, to allow better optimization of this function.  */
-  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return GPG_ERR_INV_LENGTH;
-
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
@@ -77,11 +73,11 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
      also allows to use a bulk encryption function if available.  */
   if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc)
     {
-      size_t nblocks = inbuflen / blocksize;
+      size_t nblocks = inbuflen >> blocksize_shift;
       c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
-      outbuf += nblocks * blocksize;
-      inbuf  += nblocks * blocksize;
-      inbuflen -= nblocks * blocksize;
+      outbuf += nblocks << blocksize_shift;
+      inbuf  += nblocks << blocksize_shift;
+      inbuflen -= nblocks << blocksize_shift;
     }
   else
     {
@@ -91,7 +87,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
           nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
           burn = nburn > burn ? nburn : burn;
           /* XOR the input with the IV and store input into IV.  */
-          buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
+          cipher_block_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
           outbuf += blocksize;
           inbuf += blocksize;
           inbuflen -= blocksize;
@@ -101,11 +97,11 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
   if ( inbuflen >= blocksize )
     {
       /* Save the current IV and then encrypt the IV. */
-      buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
+      cipher_block_cpy( c->lastiv, c->u_iv.iv, blocksize );
       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
       burn = nburn > burn ? nburn : burn;
       /* XOR the input with the IV and store input into IV */
-      buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
+      cipher_block_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
       outbuf += blocksize;
       inbuf += blocksize;
       inbuflen -= blocksize;
@@ -113,7 +109,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
   if ( inbuflen )
     {
       /* Save the current IV and then encrypt the IV. */
-      buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
+      cipher_block_cpy( c->lastiv, c->u_iv.iv, blocksize );
       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
       burn = nburn > burn ? nburn : burn;
       c->unused = blocksize;
@@ -139,15 +135,11 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
 {
   unsigned char *ivp;
   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
-  size_t blocksize = c->spec->blocksize;
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
   size_t blocksize_x_2 = blocksize + blocksize;
   unsigned int burn, nburn;
 
-  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
-   * length, to allow better optimization of this function.  */
-  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return GPG_ERR_INV_LENGTH;
-
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
@@ -179,11 +171,11 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
      also allows to use a bulk encryption function if available.  */
   if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec)
     {
-      size_t nblocks = inbuflen / blocksize;
+      size_t nblocks = inbuflen >> blocksize_shift;
       c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
-      outbuf += nblocks * blocksize;
-      inbuf  += nblocks * blocksize;
-      inbuflen -= nblocks * blocksize;
+      outbuf += nblocks << blocksize_shift;
+      inbuf  += nblocks << blocksize_shift;
+      inbuflen -= nblocks << blocksize_shift;
     }
   else
     {
@@ -193,7 +185,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
           nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
           burn = nburn > burn ? nburn : burn;
           /* XOR the input with the IV and store input into IV. */
-          buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
+          cipher_block_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
           outbuf += blocksize;
           inbuf += blocksize;
           inbuflen -= blocksize;
@@ -203,11 +195,11 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
   if (inbuflen >= blocksize )
     {
       /* Save the current IV and then encrypt the IV. */
-      buf_cpy ( c->lastiv, c->u_iv.iv, blocksize);
+      cipher_block_cpy ( c->lastiv, c->u_iv.iv, blocksize);
       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
       burn = nburn > burn ? nburn : burn;
       /* XOR the input with the IV and store input into IV */
-      buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
+      cipher_block_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
       outbuf += blocksize;
       inbuf += blocksize;
       inbuflen -= blocksize;
@@ -216,7 +208,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
   if (inbuflen)
     {
       /* Save the current IV and then encrypt the IV. */
-      buf_cpy ( c->lastiv, c->u_iv.iv, blocksize );
+      cipher_block_cpy ( c->lastiv, c->u_iv.iv, blocksize );
       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
       burn = nburn > burn ? nburn : burn;
       c->unused = blocksize;
index da3ef75..4efd1e1 100644 (file)
@@ -1,5 +1,5 @@
 /* cmac.c - CMAC, Cipher-based MAC.
- * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2013,2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
   (burn) = (burn) > __nburn ? (burn) : __nburn; } while (0)
 
 
-static void
-cmac_write (gcry_cipher_hd_t c, const byte * inbuf, size_t inlen)
+gcry_err_code_t
+_gcry_cmac_write (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx,
+                 const byte * inbuf, size_t inlen)
 {
   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
-  const unsigned int blocksize = c->spec->blocksize;
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
   byte outbuf[MAX_BLOCKSIZE];
   unsigned int burn = 0;
   unsigned int nblocks;
+  size_t n;
 
-  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
-   * length, to allow better optimization of this function.  */
-  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return;
+  if (ctx->tag)
+    return GPG_ERR_INV_STATE;
 
-  if (!inlen || !inbuf)
-    return;
+  if (!inbuf)
+    return GPG_ERR_INV_ARG;
+
+  if (inlen == 0)
+    return 0;
 
   /* Last block is needed for cmac_final.  */
-  if (c->unused + inlen <= blocksize)
+  if (ctx->mac_unused + inlen <= blocksize)
     {
-      for (; inlen && c->unused < blocksize; inlen--)
-        c->lastiv[c->unused++] = *inbuf++;
-      return;
+      buf_cpy (&ctx->macbuf[ctx->mac_unused], inbuf, inlen);
+      ctx->mac_unused += inlen;
+      inbuf += inlen;
+      inlen -= inlen;
+
+      return 0;
     }
 
-  if (c->unused)
+  if (ctx->mac_unused)
     {
-      for (; inlen && c->unused < blocksize; inlen--)
-        c->lastiv[c->unused++] = *inbuf++;
+      n = inlen;
+      if (n > blocksize - ctx->mac_unused)
+       n = blocksize - ctx->mac_unused;
 
-      buf_xor (c->u_iv.iv, c->u_iv.iv, c->lastiv, blocksize);
-      set_burn (burn, enc_fn (&c->context.c, c->u_iv.iv, c->u_iv.iv));
+      buf_cpy (&ctx->macbuf[ctx->mac_unused], inbuf, n);
+      ctx->mac_unused += n;
+      inbuf += n;
+      inlen -= n;
 
-      c->unused = 0;
+      cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize);
+      set_burn (burn, enc_fn (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv));
+
+      ctx->mac_unused = 0;
     }
 
   if (c->bulk.cbc_enc && inlen > blocksize)
     {
-      nblocks = inlen / blocksize;
-      nblocks -= (nblocks * blocksize == inlen);
+      nblocks = inlen >> blocksize_shift;
+      nblocks -= ((nblocks << blocksize_shift) == inlen);
 
-      c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks, 1);
-      inbuf += nblocks * blocksize;
-      inlen -= nblocks * blocksize;
+      c->bulk.cbc_enc (&c->context.c, ctx->u_iv.iv, outbuf, inbuf, nblocks, 1);
+      inbuf += nblocks << blocksize_shift;
+      inlen -= nblocks << blocksize_shift;
 
       wipememory (outbuf, sizeof (outbuf));
     }
   else
     while (inlen > blocksize)
       {
-        buf_xor (c->u_iv.iv, c->u_iv.iv, inbuf, blocksize);
-        set_burn (burn, enc_fn (&c->context.c, c->u_iv.iv, c->u_iv.iv));
+        cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, inbuf, blocksize);
+        set_burn (burn, enc_fn (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv));
         inlen -= blocksize;
         inbuf += blocksize;
       }
@@ -93,16 +106,24 @@ cmac_write (gcry_cipher_hd_t c, const byte * inbuf, size_t inlen)
   if (inlen == 0)
     BUG ();
 
-  for (; inlen && c->unused < blocksize; inlen--)
-    c->lastiv[c->unused++] = *inbuf++;
+  n = inlen;
+  if (n > blocksize - ctx->mac_unused)
+    n = blocksize - ctx->mac_unused;
+
+  buf_cpy (&ctx->macbuf[ctx->mac_unused], inbuf, n);
+  ctx->mac_unused += n;
+  inbuf += n;
+  inlen -= n;
 
   if (burn)
     _gcry_burn_stack (burn + 4 * sizeof (void *));
+
+  return 0;
 }
 
 
-static void
-cmac_generate_subkeys (gcry_cipher_hd_t c)
+gcry_err_code_t
+_gcry_cmac_generate_subkeys (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx)
 {
   const unsigned int blocksize = c->spec->blocksize;
   byte rb, carry, t, bi;
@@ -117,7 +138,7 @@ cmac_generate_subkeys (gcry_cipher_hd_t c)
   /* Tell compiler that we require a cipher with a 64bit or 128 bit block
    * length, to allow better optimization of this function.  */
   if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return;
+    return GPG_ERR_INV_CIPHER_MODE;
 
   if (MAX_BLOCKSIZE < blocksize)
     BUG ();
@@ -127,7 +148,7 @@ cmac_generate_subkeys (gcry_cipher_hd_t c)
   burn = c->spec->encrypt (&c->context.c, u.buf, u.buf);
 
   /* Currently supported blocksizes are 16 and 8. */
-  rb = blocksize == 16 ? 0x87 : 0x1B /*blocksize == 8 */ ;
+  rb = blocksize == 16 ? 0x87 : 0x1B /* blocksize == 8 */ ;
 
   for (j = 0; j < 2; j++)
     {
@@ -139,93 +160,113 @@ cmac_generate_subkeys (gcry_cipher_hd_t c)
           t = carry | (bi << 1);
           carry = bi >> 7;
           u.buf[i] = t & 0xff;
-          c->u_mode.cmac.subkeys[j][i] = u.buf[i];
+          ctx->subkeys[j][i] = u.buf[i];
         }
       u.buf[blocksize - 1] ^= carry ? rb : 0;
-      c->u_mode.cmac.subkeys[j][blocksize - 1] = u.buf[blocksize - 1];
+      ctx->subkeys[j][blocksize - 1] = u.buf[blocksize - 1];
     }
 
   wipememory (&u, sizeof (u));
   if (burn)
     _gcry_burn_stack (burn + 4 * sizeof (void *));
+
+  return 0;
 }
 
 
-static void
-cmac_final (gcry_cipher_hd_t c)
+gcry_err_code_t
+_gcry_cmac_final (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx)
 {
   const unsigned int blocksize = c->spec->blocksize;
-  unsigned int count = c->unused;
+  unsigned int count = ctx->mac_unused;
   unsigned int burn;
   byte *subkey;
 
   /* Tell compiler that we require a cipher with a 64bit or 128 bit block
    * length, to allow better optimization of this function.  */
   if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return;
+    return GPG_ERR_INV_CIPHER_MODE;
 
   if (count == blocksize)
-    subkey = c->u_mode.cmac.subkeys[0];        /* K1 */
+    subkey = ctx->subkeys[0];        /* K1 */
   else
     {
-      subkey = c->u_mode.cmac.subkeys[1];      /* K2 */
-      c->lastiv[count++] = 0x80;
+      subkey = ctx->subkeys[1];      /* K2 */
+      ctx->macbuf[count++] = 0x80;
       while (count < blocksize)
-        c->lastiv[count++] = 0;
+        ctx->macbuf[count++] = 0;
     }
 
-  buf_xor (c->lastiv, c->lastiv, subkey, blocksize);
+  cipher_block_xor (ctx->macbuf, ctx->macbuf, subkey, blocksize);
 
-  buf_xor (c->u_iv.iv, c->u_iv.iv, c->lastiv, blocksize);
-  burn = c->spec->encrypt (&c->context.c, c->u_iv.iv, c->u_iv.iv);
+  cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize);
+  burn = c->spec->encrypt (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv);
   if (burn)
     _gcry_burn_stack (burn + 4 * sizeof (void *));
 
-  c->unused = 0;
+  ctx->mac_unused = 0;
+
+  return 0;
 }
 
 
 static gcry_err_code_t
-cmac_tag (gcry_cipher_hd_t c, unsigned char *tag, size_t taglen, int check)
+cmac_tag (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx,
+         unsigned char *tag, size_t taglen, int check)
 {
+  gcry_err_code_t ret;
+
   if (!tag || taglen == 0 || taglen > c->spec->blocksize)
     return GPG_ERR_INV_ARG;
 
-  if (!c->u_mode.cmac.tag)
+  if (!ctx->tag)
     {
-      cmac_final (c);
-      c->u_mode.cmac.tag = 1;
+      ret = _gcry_cmac_final (c, ctx);
+      if (ret != 0)
+       return ret;
+
+      ctx->tag = 1;
     }
 
   if (!check)
     {
-      memcpy (tag, c->u_iv.iv, taglen);
+      memcpy (tag, ctx->u_iv.iv, taglen);
       return GPG_ERR_NO_ERROR;
     }
   else
     {
-      return buf_eq_const (tag, c->u_iv.iv, taglen) ?
+      return buf_eq_const (tag, ctx->u_iv.iv, taglen) ?
         GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
     }
 }
 
 
+void
+_gcry_cmac_reset (gcry_cmac_context_t *ctx)
+{
+  char tmp_buf[sizeof(ctx->subkeys)];
+
+  /* Only keep subkeys when reseting context. */
+
+  buf_cpy (tmp_buf, ctx->subkeys, sizeof(ctx->subkeys));
+  memset (ctx, 0, sizeof(*ctx));
+  buf_cpy (ctx->subkeys, tmp_buf, sizeof(ctx->subkeys));
+  wipememory (tmp_buf, sizeof(tmp_buf));
+}
+
+
 gcry_err_code_t
 _gcry_cipher_cmac_authenticate (gcry_cipher_hd_t c,
                                 const unsigned char *abuf, size_t abuflen)
 {
   if (abuflen > 0 && !abuf)
     return GPG_ERR_INV_ARG;
-  if (c->u_mode.cmac.tag)
-    return GPG_ERR_INV_STATE;
   /* To support new blocksize, update cmac_generate_subkeys() then add new
      blocksize here. */
   if (c->spec->blocksize != 16 && c->spec->blocksize != 8)
     return GPG_ERR_INV_CIPHER_MODE;
 
-  cmac_write (c, abuf, abuflen);
-
-  return GPG_ERR_NO_ERROR;
+  return _gcry_cmac_write (c, &c->u_mode.cmac, abuf, abuflen);
 }
 
 
@@ -233,7 +274,7 @@ gcry_err_code_t
 _gcry_cipher_cmac_get_tag (gcry_cipher_hd_t c,
                            unsigned char *outtag, size_t taglen)
 {
-  return cmac_tag (c, outtag, taglen, 0);
+  return cmac_tag (c, &c->u_mode.cmac, outtag, taglen, 0);
 }
 
 
@@ -241,13 +282,11 @@ gcry_err_code_t
 _gcry_cipher_cmac_check_tag (gcry_cipher_hd_t c,
                              const unsigned char *intag, size_t taglen)
 {
-  return cmac_tag (c, (unsigned char *) intag, taglen, 1);
+  return cmac_tag (c, &c->u_mode.cmac, (unsigned char *) intag, taglen, 1);
 }
 
 gcry_err_code_t
 _gcry_cipher_cmac_set_subkeys (gcry_cipher_hd_t c)
 {
-  cmac_generate_subkeys (c);
-
-  return GPG_ERR_NO_ERROR;
+  return _gcry_cmac_generate_subkeys (c, &c->u_mode.cmac);
 }
index f9cb6b5..d66c568 100644 (file)
 
 
 gcry_err_code_t
-_gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
-                          unsigned char *outbuf, size_t outbuflen,
-                          const unsigned char *inbuf, size_t inbuflen)
+_gcry_cipher_ctr_encrypt_ctx (gcry_cipher_hd_t c,
+                             unsigned char *outbuf, size_t outbuflen,
+                             const unsigned char *inbuf, size_t inbuflen,
+                             void *algo_context)
 {
   size_t n;
   int i;
   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
-  unsigned int blocksize = c->spec->blocksize;
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
   size_t nblocks;
   unsigned int burn, nburn;
 
-  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
-   * length, to allow better optimization of this function.  */
-  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return GPG_ERR_INV_LENGTH;
-
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
@@ -66,13 +63,13 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
     }
 
   /* Use a bulk method if available.  */
-  nblocks = inbuflen / blocksize;
+  nblocks = inbuflen >> blocksize_shift;
   if (nblocks && c->bulk.ctr_enc)
     {
-      c->bulk.ctr_enc (&c->context.c, c->u_ctr.ctr, outbuf, inbuf, nblocks);
-      inbuf  += nblocks * blocksize;
-      outbuf += nblocks * blocksize;
-      inbuflen -= nblocks * blocksize;
+      c->bulk.ctr_enc (algo_context, c->u_ctr.ctr, outbuf, inbuf, nblocks);
+      inbuf  += nblocks << blocksize_shift;
+      outbuf += nblocks << blocksize_shift;
+      inbuflen -= nblocks << blocksize_shift;
     }
 
   /* If we don't have a bulk method use the standard method.  We also
@@ -81,24 +78,33 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
     {
       unsigned char tmp[MAX_BLOCKSIZE];
 
-      do {
-        nburn = enc_fn (&c->context.c, tmp, c->u_ctr.ctr);
-        burn = nburn > burn ? nburn : burn;
+      n = blocksize;
+      do
+        {
+          nburn = enc_fn (algo_context, tmp, c->u_ctr.ctr);
+          burn = nburn > burn ? nburn : burn;
+
+         cipher_block_add(c->u_ctr.ctr, 1, blocksize);
 
-        for (i = blocksize; i > 0; i--)
-          {
-            c->u_ctr.ctr[i-1]++;
-            if (c->u_ctr.ctr[i-1] != 0)
-              break;
-          }
+          if (inbuflen < blocksize)
+            break;
+          cipher_block_xor(outbuf, inbuf, tmp, blocksize);
 
-        n = blocksize < inbuflen ? blocksize : inbuflen;
-        buf_xor(outbuf, inbuf, tmp, n);
+          inbuflen -= n;
+          outbuf += n;
+          inbuf += n;
+        }
+      while (inbuflen);
 
-        inbuflen -= n;
-        outbuf += n;
-        inbuf += n;
-      } while (inbuflen);
+      if (inbuflen)
+        {
+          n = inbuflen;
+          buf_xor(outbuf, inbuf, tmp, inbuflen);
+
+          inbuflen -= n;
+          outbuf += n;
+          inbuf += n;
+        }
 
       /* Save the unused bytes of the counter.  */
       c->unused = blocksize - n;
@@ -113,3 +119,13 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
 
   return 0;
 }
+
+
+gcry_err_code_t
+_gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
+                         unsigned char *outbuf, size_t outbuflen,
+                         const unsigned char *inbuf, size_t inbuflen)
+{
+  return _gcry_cipher_ctr_encrypt_ctx (c, outbuf, outbuflen, inbuf, inbuflen,
+                                      &c->context.c);
+}
diff --git a/cipher/cipher-eax.c b/cipher/cipher-eax.c
new file mode 100644 (file)
index 0000000..08f815a
--- /dev/null
@@ -0,0 +1,289 @@
+/* cipher-eax.c  -  EAX implementation
+ * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+#include "bufhelp.h"
+#include "./cipher-internal.h"
+
+
+gcry_err_code_t
+_gcry_cipher_eax_encrypt (gcry_cipher_hd_t c,
+                          byte *outbuf, size_t outbuflen,
+                          const byte *inbuf, size_t inbuflen)
+{
+  gcry_err_code_t err;
+
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+  if (c->marks.tag)
+    return GPG_ERR_INV_STATE;
+
+  if (!c->marks.iv)
+    {
+      err = _gcry_cipher_eax_set_nonce (c, NULL, 0);
+      if (err != 0)
+       return err;
+    }
+
+  while (inbuflen)
+    {
+      size_t currlen = inbuflen;
+
+      /* Since checksumming is done after encryption, process input in 24KiB
+       * chunks to keep data loaded in L1 cache for checksumming. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
+
+      err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, currlen);
+      if (err != 0)
+       return err;
+
+      err = _gcry_cmac_write (c, &c->u_mode.eax.cmac_ciphertext, outbuf,
+                             currlen);
+      if (err != 0)
+       return err;
+
+      outbuf += currlen;
+      inbuf += currlen;
+      outbuflen -= currlen;
+      inbuflen -= currlen;
+    }
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_eax_decrypt (gcry_cipher_hd_t c,
+                          byte *outbuf, size_t outbuflen,
+                          const byte *inbuf, size_t inbuflen)
+{
+  gcry_err_code_t err;
+
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+  if (c->marks.tag)
+    return GPG_ERR_INV_STATE;
+
+  if (!c->marks.iv)
+    {
+      err = _gcry_cipher_eax_set_nonce (c, NULL, 0);
+      if (err != 0)
+       return err;
+    }
+
+  while (inbuflen)
+    {
+      size_t currlen = inbuflen;
+
+      /* Since checksumming is done before decryption, process input in 24KiB
+       * chunks to keep data loaded in L1 cache for decryption. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
+
+      err = _gcry_cmac_write (c, &c->u_mode.eax.cmac_ciphertext, inbuf,
+                             currlen);
+      if (err != 0)
+       return err;
+
+      err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, currlen);
+      if (err != 0)
+       return err;
+
+      outbuf += currlen;
+      inbuf += currlen;
+      outbuflen -= currlen;
+      inbuflen -= currlen;
+    }
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_eax_authenticate (gcry_cipher_hd_t c,
+                               const byte * aadbuf, size_t aadbuflen)
+{
+  gcry_err_code_t err;
+
+  if (c->marks.tag)
+    return GPG_ERR_INV_STATE;
+
+  if (!c->marks.iv)
+    {
+      err = _gcry_cipher_eax_set_nonce (c, NULL, 0);
+      if (err != 0)
+       return err;
+    }
+
+  return _gcry_cmac_write (c, &c->u_mode.eax.cmac_header, aadbuf, aadbuflen);
+}
+
+
+gcry_err_code_t
+_gcry_cipher_eax_setkey (gcry_cipher_hd_t c)
+{
+  gcry_err_code_t err;
+
+  err = _gcry_cmac_generate_subkeys (c, &c->u_mode.eax.cmac_header);
+  if (err != 0)
+    return err;
+
+  buf_cpy (c->u_mode.eax.cmac_ciphertext.subkeys,
+          c->u_mode.eax.cmac_header.subkeys,
+          sizeof(c->u_mode.eax.cmac_header.subkeys));
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_eax_set_nonce (gcry_cipher_hd_t c, const byte *nonce,
+                           size_t noncelen)
+{
+  gcry_cmac_context_t nonce_cmac;
+  unsigned char initbuf[MAX_BLOCKSIZE];
+  gcry_err_code_t err;
+
+  c->marks.iv = 0;
+  c->marks.tag = 0;
+
+  _gcry_cmac_reset (&c->u_mode.eax.cmac_header);
+  _gcry_cmac_reset (&c->u_mode.eax.cmac_ciphertext);
+
+  /* Calculate nonce CMAC */
+
+  memset(&nonce_cmac, 0, sizeof(nonce_cmac));
+  memset(&initbuf, 0, sizeof(initbuf));
+
+  buf_cpy (&nonce_cmac.subkeys, c->u_mode.eax.cmac_header.subkeys,
+          sizeof(c->u_mode.eax.cmac_header.subkeys));
+
+  err = _gcry_cmac_write (c, &nonce_cmac, initbuf, c->spec->blocksize);
+  if (err != 0)
+    return err;
+
+  if (noncelen != 0)
+    {
+      err = _gcry_cmac_write (c, &nonce_cmac, nonce, noncelen);
+      if (err != 0)
+        return err;
+    }
+
+  err = _gcry_cmac_final (c, &nonce_cmac);
+  if (err != 0)
+    return err;
+
+  cipher_block_cpy (c->u_iv.iv, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE);
+  cipher_block_cpy (c->u_ctr.ctr, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE);
+
+  wipememory (&nonce_cmac, sizeof(nonce_cmac));
+
+  /* Prepare header CMAC */
+
+  initbuf[c->spec->blocksize - 1] = 1;
+  err = _gcry_cmac_write (c, &c->u_mode.eax.cmac_header, initbuf,
+                         c->spec->blocksize);
+  if (err != 0)
+    return err;
+
+  /* Prepare ciphertext CMAC */
+
+  initbuf[c->spec->blocksize - 1] = 2;
+  err = _gcry_cmac_write (c, &c->u_mode.eax.cmac_ciphertext, initbuf,
+                         c->spec->blocksize);
+  if (err != 0)
+    return err;
+
+  c->marks.iv = 1;
+  c->marks.tag = 0;
+
+  return 0;
+}
+
+
+static gcry_err_code_t
+_gcry_cipher_eax_tag (gcry_cipher_hd_t c,
+                      byte *outbuf, size_t outbuflen, int check)
+{
+  gcry_err_code_t err;
+
+  if (!c->marks.tag)
+    {
+      err = _gcry_cmac_final (c, &c->u_mode.eax.cmac_header);
+      if (err != 0)
+       return err;
+
+      err = _gcry_cmac_final (c, &c->u_mode.eax.cmac_ciphertext);
+      if (err != 0)
+       return err;
+
+      cipher_block_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_header.u_iv.iv,
+                          MAX_BLOCKSIZE);
+      cipher_block_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_ciphertext.u_iv.iv,
+                          MAX_BLOCKSIZE);
+
+      _gcry_cmac_reset (&c->u_mode.eax.cmac_header);
+      _gcry_cmac_reset (&c->u_mode.eax.cmac_ciphertext);
+
+      c->marks.tag = 1;
+    }
+
+  if (!check)
+    {
+      if (outbuflen > c->spec->blocksize)
+        outbuflen = c->spec->blocksize;
+
+      /* NB: We already checked that OUTBUF is large enough to hold
+       * the result or has valid truncated length.  */
+      memcpy (outbuf, c->u_iv.iv, outbuflen);
+    }
+  else
+    {
+      /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
+       * and thus we need to compare its length first.  */
+      if (!(outbuflen <= c->spec->blocksize)
+          || !buf_eq_const (outbuf, c->u_iv.iv, outbuflen))
+        return GPG_ERR_CHECKSUM;
+    }
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_eax_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
+                          size_t taglen)
+{
+  return _gcry_cipher_eax_tag (c, outtag, taglen, 0);
+}
+
+gcry_err_code_t
+_gcry_cipher_eax_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
+                            size_t taglen)
+{
+  return _gcry_cipher_eax_tag (c, (unsigned char *) intag, taglen, 1);
+}
diff --git a/cipher/cipher-gcm-armv7-neon.S b/cipher/cipher-gcm-armv7-neon.S
new file mode 100644 (file)
index 0000000..16502b4
--- /dev/null
@@ -0,0 +1,341 @@
+/* cipher-gcm-armv7-neon.S - ARM/NEON accelerated GHASH
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \
+    defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_NEON)
+
+.syntax unified
+.fpu neon
+.arm
+
+.text
+
+#ifdef __PIC__
+#  define GET_DATA_POINTER(reg, name, rtmp) \
+               ldr reg, 1f; \
+               ldr rtmp, 2f; \
+               b 3f; \
+       1:      .word _GLOBAL_OFFSET_TABLE_-(3f+8); \
+       2:      .word name(GOT); \
+       3:      add reg, pc, reg; \
+               ldr reg, [reg, rtmp];
+#else
+#  define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name
+#endif
+
+
+/* Constants */
+
+.align 4
+gcry_gcm_reduction_constant:
+.Lrconst64:
+  .quad 0xc200000000000000
+
+/* Register macros */
+
+#define rhash q0
+#define rhash_l d0
+#define rhash_h d1
+
+#define rh1 q1
+#define rh1_l d2
+#define rh1_h d3
+
+#define rbuf q2
+#define rbuf_l d4
+#define rbuf_h d5
+
+#define rbuf1 q3
+#define rbuf1_l d6
+#define rbuf1_h d7
+
+#define t0q q4
+#define t0l d8
+#define t0h d9
+
+#define t1q q5
+#define t1l d10
+#define t1h d11
+
+#define t2q q6
+#define t2l d12
+#define t2h d13
+
+#define t3q q7
+#define t3l d14
+#define t3h d15
+
+/* q8 */
+#define k16 d16
+#define k32 d17
+
+/* q9 */
+#define k48 d18
+
+#define k0 q10
+
+#define rr0 q11
+#define rr0_l d22
+#define rr0_h d23
+
+#define rr1 q12
+#define rr1_l d24
+#define rr1_h d25
+
+#define rt0 q13
+#define rt0_l d26
+#define rt0_h d27
+
+#define rt1 q14
+#define rt1_l d28
+#define rt1_h d29
+
+#define rrconst q15
+#define rrconst_l d30
+#define rrconst_h d31
+
+/* Macro for 64x64=>128 carry-less multiplication using vmull.p8 instruction.
+ *
+ * From "Câmara, D.; Gouvêa, C. P. L.; López, J. & Dahab, R. Fast Software
+ * Polynomial Multiplication on ARM Processors using the NEON Engine. The
+ * Second International Workshop on Modern Cryptography and Security
+ * Engineering — MoCrySEn, 2013". */
+
+#define vmull_p64(rq, rl, rh, ad, bd) \
+       vext.8 t0l, ad, ad, $1; \
+       vmull.p8 t0q, t0l, bd; \
+       vext.8 rl, bd, bd, $1; \
+       vmull.p8 rq, ad, rl; \
+       vext.8 t1l, ad, ad, $2; \
+       vmull.p8 t1q, t1l, bd; \
+       vext.8 t3l, bd, bd, $2; \
+       vmull.p8 t3q, ad, t3l; \
+       vext.8 t2l, ad, ad, $3; \
+       vmull.p8 t2q, t2l, bd; \
+       veor t0q, t0q, rq; \
+       vext.8 rl, bd, bd, $3; \
+       vmull.p8 rq, ad, rl; \
+       veor t1q, t1q, t3q; \
+       vext.8 t3l, bd, bd, $4; \
+       vmull.p8 t3q, ad, t3l; \
+       veor t0l, t0l, t0h; \
+       vand t0h, t0h, k48; \
+       veor t1l, t1l, t1h; \
+       vand t1h, t1h, k32; \
+       veor t2q, t2q, rq; \
+       veor t0l, t0l, t0h; \
+       veor t1l, t1l, t1h; \
+       veor t2l, t2l, t2h; \
+       vand t2h, t2h, k16; \
+       veor t3l, t3l, t3h; \
+       vmov.i64 t3h, $0; \
+       vext.8 t0q, t0q, t0q, $15; \
+       veor t2l, t2l, t2h; \
+       vext.8 t1q, t1q, t1q, $14; \
+       vmull.p8 rq, ad, bd; \
+       vext.8 t2q, t2q, t2q, $13; \
+       vext.8 t3q, t3q, t3q, $12; \
+       veor t0q, t0q, t1q; \
+       veor t2q, t2q, t3q; \
+       veor rq, rq, t0q; \
+       veor rq, rq, t2q;
+
+/* GHASH macros.
+ *
+ * See "Gouvêa, C. P. L. & López, J. Implementing GCM on ARMv8. Topics in
+ * Cryptology — CT-RSA 2015" for details.
+ */
+
+/* Input: 'a' and 'b', Output: 'r0:r1' (low 128-bits in r0, high in r1)
+ *  Note: 'r1' may be 'a' or 'b', 'r0' must not be either 'a' or 'b'.
+ */
+#define PMUL_128x128(r0, r1, a, b, t1, t2, interleave_op) \
+        veor t1##_h, b##_l, b##_h; \
+        veor t1##_l, a##_l, a##_h; \
+        vmull_p64( r0, r0##_l, r0##_h, a##_l, b##_l ); \
+        vmull_p64( r1, r1##_l, r1##_h, a##_h, b##_h ); \
+        vmull_p64( t2, t2##_h, t2##_l, t1##_h, t1##_l ); \
+        interleave_op; \
+        veor t2, r0; \
+        veor t2, r1; \
+        veor r0##_h, t2##_l; \
+        veor r1##_l, t2##_h;
+
+/* Reduction using Xor and Shift.
+ * Input: 'r0:r1', Output: 'a'
+ *
+ * See "Shay Gueron, Michael E. Kounavis. Intel Carry-Less Multiplication
+ * Instruction and its Usage for Computing the GCM Mode" for details.
+ */
+#define REDUCTION(a, r0, r1, t, interleave_op) \
+        vshl.u32 t0q, r0, #31; \
+        vshl.u32 t1q, r0, #30; \
+        vshl.u32 t2q, r0, #25; \
+        veor t0q, t0q, t1q; \
+        veor t0q, t0q, t2q; \
+        vext.8 t, t0q, k0, #4; \
+        vext.8 t0q, k0, t0q, #(16-12); \
+        veor r0, r0, t0q; \
+        interleave_op; \
+        vshr.u32 t0q, r0, #1; \
+        vshr.u32 t1q, r0, #2; \
+        vshr.u32 t2q, r0, #7; \
+        veor t0q, t0q, t1q; \
+        veor t0q, t0q, t2q; \
+        veor t0q, t0q, t; \
+        veor r0, r0, t0q; \
+        veor a, r0, r1;
+
+#define _(...) __VA_ARGS__
+#define __ _()
+
+/* Other functional macros */
+
+#define CLEAR_REG(reg) vmov.i8 reg, #0;
+
+
+/*
+ * unsigned int _gcry_ghash_armv7_neon (void *gcm_key, byte *result,
+ *                                      const byte *buf, size_t nblocks);
+ */
+.align 3
+.globl _gcry_ghash_armv7_neon
+.type  _gcry_ghash_armv7_neon,%function;
+_gcry_ghash_armv7_neon:
+  /* input:
+   *    r0: gcm_key
+   *    r1: result/hash
+   *    r2: buf
+   *    r3: nblocks
+   */
+  push {r4-r6, lr}
+
+  cmp r3, #0
+  beq .Ldo_nothing
+
+  vpush {q4-q7}
+
+  vld1.64 {rhash}, [r1]
+  vld1.64 {rh1}, [r0]
+
+  vrev64.8 rhash, rhash /* byte-swap */
+
+  vmov.i64 k0, #0x0
+  vmov.i64 k16, #0xffff
+  vmov.i64 k32, #0xffffffff
+  vmov.i64 k48, #0xffffffffffff
+
+  vext.8 rhash, rhash, rhash, #8
+
+  /* Handle remaining blocks. */
+
+  vld1.64 {rbuf}, [r2]!
+  subs r3, r3, #1
+
+  vrev64.8 rbuf, rbuf /* byte-swap */
+  vext.8 rbuf, rbuf, rbuf, #8
+
+  veor rhash, rhash, rbuf
+
+  beq .Lend
+
+.Loop:
+  vld1.64 {rbuf}, [r2]!
+  PMUL_128x128(rr0, rr1, rhash, rh1, rt0, rt1, _(vrev64.8 rbuf, rbuf))
+  REDUCTION(rhash, rr0, rr1, rt0, _(vext.8 rbuf, rbuf, rbuf, #8))
+  subs r3, r3, #1
+  veor rhash, rhash, rbuf
+
+  bne .Loop
+
+.Lend:
+  PMUL_128x128(rr0, rr1, rhash, rh1, rt0, rt1, _(CLEAR_REG(rbuf)))
+  REDUCTION(rhash, rr0, rr1, rt0, _(CLEAR_REG(rh1)))
+
+.Ldone:
+  CLEAR_REG(rr1)
+  vrev64.8 rhash, rhash /* byte-swap */
+  CLEAR_REG(rt0)
+  CLEAR_REG(rr0)
+  vext.8 rhash, rhash, rhash, #8
+  CLEAR_REG(rt1)
+  CLEAR_REG(t0q)
+  CLEAR_REG(t1q)
+  CLEAR_REG(t2q)
+  CLEAR_REG(t3q)
+  vst1.64 {rhash}, [r1]
+  CLEAR_REG(rhash)
+
+  vpop {q4-q7}
+
+.Ldo_nothing:
+  mov r0, #0
+  pop {r4-r6, pc}
+.size _gcry_ghash_armv7_neon,.-_gcry_ghash_armv7_neon;
+
+
+/*
+ * void _gcry_ghash_armv7_neon (void *gcm_key);
+ */
+.align 3
+.globl _gcry_ghash_setup_armv7_neon
+.type  _gcry_ghash_setup_armv7_neon,%function;
+_gcry_ghash_setup_armv7_neon:
+  /* input:
+   *   r0: gcm_key
+   */
+
+  vpush {q4-q7}
+
+  GET_DATA_POINTER(r2, .Lrconst64, r3)
+
+  vld1.64 {rrconst_h}, [r2]
+
+#define GCM_LSH_1(r_out, ia, ib, const_d, oa, ob, ma) \
+        /* H <<< 1 */ \
+        vshr.s64 ma, ib, #63; \
+        vshr.u64 oa, ib, #63; \
+        vshr.u64 ob, ia, #63; \
+        vand ma, const_d; \
+        vshl.u64 ib, ib, #1; \
+        vshl.u64 ia, ia, #1; \
+        vorr ob, ib; \
+        vorr oa, ia; \
+        veor ob, ma; \
+        vst1.64 {oa, ob}, [r_out]
+
+  vld1.64 {rhash}, [r0]
+  vrev64.8 rhash, rhash /* byte-swap */
+  vext.8 rhash, rhash, rhash, #8
+
+  vmov rbuf1, rhash
+  GCM_LSH_1(r0, rhash_l, rhash_h, rrconst_h, rh1_l, rh1_h, rt1_l) /* H<<<1 */
+
+  CLEAR_REG(rh1)
+  CLEAR_REG(rhash)
+  CLEAR_REG(rbuf1)
+  CLEAR_REG(rrconst)
+  vpop {q4-q7}
+  bx lr
+.size _gcry_ghash_setup_armv7_neon,.-_gcry_ghash_setup_armv7_neon;
+
+#endif
index 1de66a1..00c547d 100644 (file)
@@ -180,7 +180,7 @@ gcry_gcm_reduction_constant:
 
 /* Other functional macros */
 
-#define CLEAR_REG(reg) veor reg, reg;
+#define CLEAR_REG(reg) vmov.i8 reg, #0;
 
 
 /*
@@ -359,6 +359,161 @@ _gcry_ghash_armv8_ce_pmull:
 
 
 /*
+ * unsigned int _gcry_polyval_armv8_ce_pmull (void *gcm_key, byte *result,
+ *                                            const byte *buf, size_t nblocks,
+ *                                            void *gcm_table);
+ */
+.align 3
+.globl _gcry_polyval_armv8_ce_pmull
+.type  _gcry_polyval_armv8_ce_pmull,%function;
+_gcry_polyval_armv8_ce_pmull:
+  /* input:
+   *    r0: gcm_key
+   *    r1: result/hash
+   *    r2: buf
+   *    r3: nblocks
+   *    %st+0: gcm_table
+   */
+  push {r4-r6, lr}
+
+  cmp r3, #0
+  beq .Lpolyval_do_nothing
+
+  GET_DATA_POINTER(r4, .Lrconst64, lr)
+
+  vld1.64 {rhash}, [r1]
+  vld1.64 {rh1}, [r0]
+
+  vrev64.8 rhash, rhash /* byte-swap */
+  vld1.64 {rrconst_h}, [r4]
+  vext.8 rhash, rhash, rhash, #8
+
+  cmp r3, #4
+  blo .Lpolyval_less_than_4
+
+  /* Bulk processing of 4 blocks per loop iteration. */
+
+  ldr r5, [sp, #(4*4)];
+  add r6, r5, #32
+
+  vpush {q4-q7}
+
+  vld1.64 {rh2-rh3}, [r5]
+  vld1.64 {rh4}, [r6]
+
+  vld1.64 {rbuf-rbuf1}, [r2]!
+  sub r3, r3, #4
+  vld1.64 {rbuf2-rbuf3}, [r2]!
+
+  cmp r3, #4
+  veor rhash, rhash, rbuf /* in0 ^ hash */
+
+  blo .Lpolyval_end_4
+
+.Lpolyval_loop_4:
+  /* (in0 ^ hash) * H⁴ => rr2:rr3 */
+  /* (in1) * H³ => rr0:rr1 */
+  PMUL_128x128_2(rr0, rr1, rbuf1, rh3, rr2, rr3, rhash, rh4, rt1, rt0, __)
+
+  vld1.64 {rbuf-rbuf1}, [r2]!
+  sub r3, r3, #4
+  veor rr0, rr0, rr2
+  veor rr1, rr1, rr3
+
+  /* (in2) * H² => rr2:rr3 */
+  /* (in3) * H¹ => rhash:rbuf3 */
+  PMUL_128x128_2(rr2, rr3, rbuf2, rh2, rhash, rbuf3, rbuf3, rh1, rt0, rt1, __)
+
+  vld1.64 {rbuf2}, [r2]!
+
+  veor rr0, rr0, rr2
+  veor rr1, rr1, rr3
+
+  cmp r3, #4
+
+  veor rr0, rr0, rhash
+  veor rr1, rr1, rbuf3
+
+  vld1.64 {rbuf3}, [r2]!
+
+  REDUCTION(rhash, rr0, rr1, rrconst_h, rt1, __)
+
+  veor rhash, rhash, rbuf /* in0 ^ hash */
+
+  bhs .Lpolyval_loop_4
+
+.Lpolyval_end_4:
+  /* (in0 ^ hash) * H⁴ => rr2:rr3 */
+  /* (in1) * H³ => rr0:rr1 */
+  PMUL_128x128_2(rr0, rr1, rbuf1, rh3, rr2, rr3, rhash, rh4, rt1, rt0, __)
+
+  /* (in2) * H² => rhash:rbuf */
+  /* (in3) * H¹ => rbuf1:rbuf2 */
+  PMUL_128x128_2(rhash, rbuf, rbuf2, rh2, rbuf1, rbuf2, rbuf3, rh1, rt0, rt1,
+                 _(veor rr0, rr0, rr2;
+                   veor rr1, rr1, rr3))
+
+  veor rr0, rr0, rhash
+  veor rr1, rr1, rbuf
+
+  veor rr0, rr0, rbuf1
+  veor rr1, rr1, rbuf2
+
+  REDUCTION(rhash, rr0, rr1, rrconst_h, rt1,
+            _(CLEAR_REG(rr2);
+              CLEAR_REG(rr3);
+              CLEAR_REG(rbuf1);
+              CLEAR_REG(rbuf2);
+              CLEAR_REG(rbuf3);
+              CLEAR_REG(rh2);
+              CLEAR_REG(rh3);
+              CLEAR_REG(rh4)))
+
+  vpop {q4-q7}
+
+  cmp r3, #0
+  beq .Lpolyval_done
+
+.Lpolyval_less_than_4:
+  /* Handle remaining blocks. */
+
+  vld1.64 {rbuf}, [r2]!
+  subs r3, r3, #1
+
+  veor rhash, rhash, rbuf
+
+  beq .Lpolyval_end
+
+.Lpolyval_loop:
+  vld1.64 {rbuf}, [r2]!
+  subs r3, r3, #1
+  PMUL_128x128(rr0, rr1, rhash, rh1, rt0, __)
+  REDUCTION(rhash, rr0, rr1, rrconst_h, rt0, __)
+  veor rhash, rhash, rbuf
+
+  bne .Lpolyval_loop
+
+.Lpolyval_end:
+  PMUL_128x128(rr0, rr1, rhash, rh1, rt0, _(CLEAR_REG(rbuf)))
+  REDUCTION(rhash, rr0, rr1, rrconst_h, rt0, _(CLEAR_REG(rh1)))
+
+.Lpolyval_done:
+  CLEAR_REG(rr1)
+  vrev64.8 rhash, rhash /* byte-swap */
+  CLEAR_REG(rt0)
+  CLEAR_REG(rr0)
+  vext.8 rhash, rhash, rhash, #8
+  CLEAR_REG(rt1)
+  vst1.64 {rhash}, [r1]
+  CLEAR_REG(rhash)
+
+.Lpolyval_do_nothing:
+  mov r0, #0
+  pop {r4-r6, pc}
+.size _gcry_polyval_armv8_ce_pmull,.-_gcry_polyval_armv8_ce_pmull;
+
+
+/*
  * void _gcry_ghash_setup_armv8_ce_pmull (void *gcm_key, void *gcm_table);
  */
 .align 3
index 0cfaf1c..e671424 100644 (file)
@@ -17,7 +17,7 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "asm-common-aarch64.h"
 
 #if defined(__AARCH64EL__) && \
     defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
 
 .text
 
-#define GET_DATA_POINTER(reg, name) \
-               adrp    reg, :got:name ; \
-               ldr     reg, [reg, #:got_lo12:name] ;
-
 
 /* Constants */
 
@@ -153,19 +149,27 @@ gcry_gcm_reduction_constant:
 #define _(...) __VA_ARGS__
 #define __ _()
 
-#define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
+#define CLEAR_REG(reg) movi reg.16b, #0;
 
 #define VPUSH_ABI \
         stp d8, d9, [sp, #-16]!; \
+        CFI_ADJUST_CFA_OFFSET(16); \
         stp d10, d11, [sp, #-16]!; \
+        CFI_ADJUST_CFA_OFFSET(16); \
         stp d12, d13, [sp, #-16]!; \
-        stp d14, d15, [sp, #-16]!;
+        CFI_ADJUST_CFA_OFFSET(16); \
+        stp d14, d15, [sp, #-16]!; \
+        CFI_ADJUST_CFA_OFFSET(16);
 
 #define VPOP_ABI \
         ldp d14, d15, [sp], #16; \
+        CFI_ADJUST_CFA_OFFSET(-16); \
         ldp d12, d13, [sp], #16; \
+        CFI_ADJUST_CFA_OFFSET(-16); \
         ldp d10, d11, [sp], #16; \
-        ldp d8, d9, [sp], #16;
+        CFI_ADJUST_CFA_OFFSET(-16); \
+        ldp d8, d9, [sp], #16; \
+        CFI_ADJUST_CFA_OFFSET(-16);
 
 /*
  * unsigned int _gcry_ghash_armv8_ce_pmull (void *gcm_key, byte *result,
@@ -174,7 +178,7 @@ gcry_gcm_reduction_constant:
  */
 .align 3
 .globl _gcry_ghash_armv8_ce_pmull
-.type  _gcry_ghash_armv8_ce_pmull,%function;
+ELF(.type  _gcry_ghash_armv8_ce_pmull,%function;)
 _gcry_ghash_armv8_ce_pmull:
   /* input:
    *    x0: gcm_key
@@ -183,6 +187,8 @@ _gcry_ghash_armv8_ce_pmull:
    *    x3: nblocks
    *    x4: gcm_table
    */
+  CFI_STARTPROC();
+
   cbz x3, .Ldo_nothing;
 
   GET_DATA_POINTER(x5, .Lrconst)
@@ -359,8 +365,237 @@ _gcry_ghash_armv8_ce_pmull:
 
 .Ldo_nothing:
   mov x0, #0
-  ret
-.size _gcry_ghash_armv8_ce_pmull,.-_gcry_ghash_armv8_ce_pmull;
+  ret_spec_stop
+  CFI_ENDPROC()
+ELF(.size _gcry_ghash_armv8_ce_pmull,.-_gcry_ghash_armv8_ce_pmull;)
+
+
+/*
+ * unsigned int _gcry_polyval_armv8_ce_pmull (void *gcm_key, byte *result,
+ *                                            const byte *buf, size_t nblocks,
+ *                                            void *gcm_table);
+ */
+.align 3
+.globl _gcry_polyval_armv8_ce_pmull
+ELF(.type  _gcry_polyval_armv8_ce_pmull,%function;)
+_gcry_polyval_armv8_ce_pmull:
+  /* input:
+   *    x0: gcm_key
+   *    x1: result/hash
+   *    x2: buf
+   *    x3: nblocks
+   *    x4: gcm_table
+   */
+  CFI_STARTPROC();
+
+  cbz x3, .Lpolyval_do_nothing;
+
+  GET_DATA_POINTER(x5, .Lrconst)
+
+  eor vZZ.16b, vZZ.16b, vZZ.16b
+  ld1 {rhash.16b}, [x1]
+  ld1 {rh1.16b}, [x0]
+
+  rbit rhash.16b, rhash.16b /* bit-swap */
+  ld1r {rrconst.2d}, [x5]
+
+  cmp x3, #6
+  b.lo .Lpolyval_less_than_6
+
+  add x6, x4, #64
+  VPUSH_ABI
+
+  ld1 {rh2.16b-rh5.16b}, [x4]
+  ld1 {rh6.16b}, [x6]
+
+  sub x3, x3, #6
+
+  ld1 {rbuf.16b-rbuf2.16b}, [x2], #(3*16)
+  ld1 {rbuf3.16b-rbuf5.16b}, [x2], #(3*16)
+  rev64 rbuf.16b, rbuf.16b /* byte-swap */
+  rev64 rbuf1.16b, rbuf1.16b /* byte-swap */
+  rev64 rbuf2.16b, rbuf2.16b /* byte-swap */
+  rev64 rbuf3.16b, rbuf3.16b /* byte-swap */
+  rev64 rbuf4.16b, rbuf4.16b /* byte-swap */
+  rev64 rbuf5.16b, rbuf5.16b /* byte-swap */
+  ext rbuf.16b, rbuf.16b, rbuf.16b, #8 /* byte-swap */
+  ext rbuf1.16b, rbuf1.16b, rbuf1.16b, #8 /* byte-swap */
+  ext rbuf2.16b, rbuf2.16b, rbuf2.16b, #8 /* byte-swap */
+  ext rbuf3.16b, rbuf3.16b, rbuf3.16b, #8 /* byte-swap */
+  ext rbuf4.16b, rbuf4.16b, rbuf4.16b, #8 /* byte-swap */
+  ext rbuf5.16b, rbuf5.16b, rbuf5.16b, #8 /* byte-swap */
+  rbit rbuf.16b, rbuf.16b /* bit-swap */
+  rbit rbuf1.16b, rbuf1.16b /* bit-swap */
+  rbit rbuf2.16b, rbuf2.16b /* bit-swap */
+  rbit rbuf3.16b, rbuf3.16b /* bit-swap */
+  rbit rbuf4.16b, rbuf4.16b /* bit-swap */
+  rbit rbuf5.16b, rbuf5.16b /* bit-swap */
+  eor rhash.16b, rhash.16b, rbuf.16b
+
+  cmp x3, #6
+  b.lo .Lpolyval_end_6
+
+.Lpolyval_loop_6:
+
+  /* (in1) * H⁵ => rr0:rr1 */
+  /* (in2) * H⁴ => rr2:rr3 */
+  /* (in0 ^ hash) * H⁶ => rr4:rr5 */
+  PMUL_128x128_3(rr0, rr1, rbuf1, rh5, t0, t1,
+                 rr2, rr3, rbuf2, rh4, t2, t3,
+                 rr4, rr5, rhash, rh6, t4, t5,
+                 _(sub x3, x3, #6))
+
+  ld1 {rbuf.16b-rbuf2.16b}, [x2], #(3*16)
+  cmp x3, #6
+
+  eor rr0.16b, rr0.16b, rr2.16b
+  eor rr1.16b, rr1.16b, rr3.16b
+
+  /* (in3) * H³ => rr2:rr3 */
+  /* (in4) * H² => rr6:rr7 */
+  /* (in5) * H¹ => rr8:rr9 */
+  PMUL_128x128_3(rr2, rr3, rbuf3, rh3, t0, t1,
+                 rr6, rr7, rbuf4, rh2, t2, t3,
+                 rr8, rr9, rbuf5, rh1, t4, t5,
+                 _(eor rr0.16b, rr0.16b, rr4.16b;
+                   eor rr1.16b, rr1.16b, rr5.16b))
+
+  rev64 rbuf.16b, rbuf.16b /* byte-swap */
+  rev64 rbuf1.16b, rbuf1.16b /* byte-swap */
+  rev64 rbuf2.16b, rbuf2.16b /* byte-swap */
+  ext rbuf.16b, rbuf.16b, rbuf.16b, #8 /* byte-swap */
+  ext rbuf1.16b, rbuf1.16b, rbuf1.16b, #8 /* byte-swap */
+  ext rbuf2.16b, rbuf2.16b, rbuf2.16b, #8 /* byte-swap */
+
+  eor rr0.16b, rr0.16b, rr2.16b
+  eor rr1.16b, rr1.16b, rr3.16b
+  rbit rbuf.16b, rbuf.16b /* bit-swap */
+  eor rr0.16b, rr0.16b, rr6.16b
+  eor rr1.16b, rr1.16b, rr7.16b
+  rbit rbuf1.16b, rbuf1.16b /* bit-swap */
+  eor rr0.16b, rr0.16b, rr8.16b
+  eor rr1.16b, rr1.16b, rr9.16b
+  ld1 {rbuf3.16b-rbuf5.16b}, [x2], #(3*16)
+
+  REDUCTION(rhash, rr0, rr1, rrconst, t0, t1,
+            _(rbit rbuf2.16b, rbuf2.16b), /* bit-swap */
+            _(rev64 rbuf3.16b, rbuf3.16b), /* byte-swap */
+            _(rev64 rbuf4.16b, rbuf4.16b)) /* byte-swap */
+
+  rev64 rbuf5.16b, rbuf5.16b /* byte-swap */
+  ext rbuf3.16b, rbuf3.16b, rbuf3.16b, #8 /* byte-swap */
+
+  eor rhash.16b, rhash.16b, rbuf.16b
+
+  ext rbuf4.16b, rbuf4.16b, rbuf4.16b, #8 /* byte-swap */
+  ext rbuf5.16b, rbuf5.16b, rbuf5.16b, #8 /* byte-swap */
+  rbit rbuf3.16b, rbuf3.16b /* bit-swap */
+  rbit rbuf4.16b, rbuf4.16b /* bit-swap */
+  rbit rbuf5.16b, rbuf5.16b /* bit-swap */
+
+  b.hs .Lpolyval_loop_6
+
+.Lpolyval_end_6:
+
+  /* (in1) * H⁵ => rr0:rr1 */
+  /* (in0 ^ hash) * H⁶ => rr2:rr3 */
+  /* (in2) * H⁴ => rr4:rr5 */
+  PMUL_128x128_3(rr0, rr1, rbuf1, rh5, t0, t1,
+                 rr2, rr3, rhash, rh6, t2, t3,
+                 rr4, rr5, rbuf2, rh4, t4, t5,
+                 __)
+  eor rr0.16b, rr0.16b, rr2.16b
+  eor rr1.16b, rr1.16b, rr3.16b
+  eor rr0.16b, rr0.16b, rr4.16b
+  eor rr1.16b, rr1.16b, rr5.16b
+
+  /* (in3) * H³ => rhash:rbuf */
+  /* (in4) * H² => rr6:rr7 */
+  /* (in5) * H¹ => rr8:rr9 */
+  PMUL_128x128_3(rhash, rbuf, rbuf3, rh3, t0, t1,
+                 rr6, rr7, rbuf4, rh2, t2, t3,
+                 rr8, rr9, rbuf5, rh1, t4, t5,
+                 _(CLEAR_REG(rh4);
+                   CLEAR_REG(rh5);
+                   CLEAR_REG(rh6)))
+  eor rr0.16b, rr0.16b, rhash.16b
+  eor rr1.16b, rr1.16b, rbuf.16b
+  eor rr0.16b, rr0.16b, rr6.16b
+  eor rr1.16b, rr1.16b, rr7.16b
+  eor rr0.16b, rr0.16b, rr8.16b
+  eor rr1.16b, rr1.16b, rr9.16b
+
+  REDUCTION(rhash, rr0, rr1, rrconst, t0, t1,
+            _(CLEAR_REG(rh2);
+              CLEAR_REG(rh3);
+              CLEAR_REG(rr2);
+              CLEAR_REG(rbuf2);
+              CLEAR_REG(rbuf3)),
+            _(CLEAR_REG(rr3);
+              CLEAR_REG(rr4);
+              CLEAR_REG(rr5);
+              CLEAR_REG(rr6);
+              CLEAR_REG(rr7)),
+            _(CLEAR_REG(rr8);
+              CLEAR_REG(rr9);
+              CLEAR_REG(rbuf1);
+              CLEAR_REG(rbuf2)))
+
+  CLEAR_REG(rbuf4)
+  CLEAR_REG(rbuf5)
+  CLEAR_REG(t2)
+  CLEAR_REG(t3)
+  CLEAR_REG(t4)
+  CLEAR_REG(t5)
+
+  VPOP_ABI
+
+  cbz x3, .Lpolyval_done
+
+.Lpolyval_less_than_6:
+  /* Handle remaining blocks. */
+
+  ld1 {rbuf.16b}, [x2], #16
+  sub x3, x3, #1
+
+  rev64 rbuf.16b, rbuf.16b /* byte-swap */
+  ext rbuf.16b, rbuf.16b, rbuf.16b, #8 /* byte-swap */
+  rbit rbuf.16b, rbuf.16b /* bit-swap */
+
+  eor rhash.16b, rhash.16b, rbuf.16b
+
+  cbz x3, .Lpolyval_end
+
+.Lpolyval_loop:
+  PMUL_128x128(rr0, rr1, rh1, rhash, t0, t1, _(ld1 {rbuf.16b}, [x2], #16))
+  REDUCTION(rhash, rr0, rr1, rrconst, t0, t1,
+            _(sub x3, x3, #1;
+              rev64 rbuf.16b, rbuf.16b), /* byte-swap */
+            _(ext rbuf.16b, rbuf.16b, rbuf.16b, #8), /* byte-swap */
+            _(rbit rbuf.16b, rbuf.16b)) /* bit-swap */
+  eor rhash.16b, rhash.16b, rbuf.16b
+
+  cbnz x3, .Lpolyval_loop
+
+.Lpolyval_end:
+  PMUL_128x128(rr0, rr1, rh1, rhash, t0, t1, _(CLEAR_REG(rbuf)))
+  REDUCTION(rhash, rr0, rr1, rrconst, t0, t1, __, _(CLEAR_REG(rh1)), __)
+
+.Lpolyval_done:
+  CLEAR_REG(rr1)
+  CLEAR_REG(rr0)
+  rbit rhash.16b, rhash.16b /* bit-swap */
+  CLEAR_REG(t0)
+  CLEAR_REG(t1)
+
+  st1 {rhash.2d}, [x1]
+  CLEAR_REG(rhash)
+
+.Lpolyval_do_nothing:
+  mov x0, #0
+  ret_spec_stop
+  CFI_ENDPROC()
+ELF(.size _gcry_polyval_armv8_ce_pmull,.-_gcry_polyval_armv8_ce_pmull;)
 
 
 /*
@@ -368,15 +603,18 @@ _gcry_ghash_armv8_ce_pmull:
  */
 .align 3
 .globl _gcry_ghash_setup_armv8_ce_pmull
-.type  _gcry_ghash_setup_armv8_ce_pmull,%function;
+ELF(.type  _gcry_ghash_setup_armv8_ce_pmull,%function;)
 _gcry_ghash_setup_armv8_ce_pmull:
   /* input:
    *   x0: gcm_key
    *   x1: gcm_table
    */
+  CFI_STARTPROC()
 
   GET_DATA_POINTER(x2, .Lrconst)
 
+  eor vZZ.16b, vZZ.16b, vZZ.16b
+
   /* H¹ */
   ld1 {rh1.16b}, [x0]
   rbit rh1.16b, rh1.16b
@@ -407,7 +645,8 @@ _gcry_ghash_setup_armv8_ce_pmull:
   st1 {rh2.16b-rh4.16b}, [x1], #(3*16)
   st1 {rh5.16b-rh6.16b}, [x1]
 
-  ret
-.size _gcry_ghash_setup_armv8_ce_pmull,.-_gcry_ghash_setup_armv8_ce_pmull;
+  ret_spec_stop
+  CFI_ENDPROC()
+ELF(.size _gcry_ghash_setup_armv8_ce_pmull,.-_gcry_ghash_setup_armv8_ce_pmull;)
 
 #endif
index a327249..daf807d 100644 (file)
@@ -1,6 +1,6 @@
 /* cipher-gcm-intel-pclmul.c  -  Intel PCLMUL accelerated Galois Counter Mode
  *                               implementation
- * Copyright (C) 2013-2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2013-2014,2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
 /* Prevent compiler from issuing SSE instructions between asm blocks. */
 #  pragma GCC target("no-sse")
 #endif
+#if __clang__
+#  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
+#endif
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR        NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE ASM_FUNC_ATTR ALWAYS_INLINE
 
 
 /*
   "Intel® Carry-Less Multiplication Instruction and its Usage for Computing the
    GCM Mode - Rev 2.01"; Shay Gueron, Michael E. Kounavis.
  */
-static inline void gfmul_pclmul(void)
+static ASM_FUNC_ATTR_INLINE void reduction(void)
+{
+  /* input: <xmm1:xmm3> */
+
+  asm volatile (/* first phase of the reduction */
+                "movdqa %%xmm3, %%xmm6\n\t"
+                "movdqa %%xmm3, %%xmm5\n\t"
+                "psllq $1, %%xmm6\n\t"  /* packed right shifting << 63 */
+                "pxor %%xmm3, %%xmm6\n\t"
+                "psllq $57, %%xmm5\n\t"  /* packed right shifting << 57 */
+                "psllq $62, %%xmm6\n\t"  /* packed right shifting << 62 */
+                "pxor %%xmm5, %%xmm6\n\t" /* xor the shifted versions */
+                "pshufd $0x6a, %%xmm6, %%xmm5\n\t"
+                "pshufd $0xae, %%xmm6, %%xmm6\n\t"
+                "pxor %%xmm5, %%xmm3\n\t" /* first phase of the reduction
+                                             complete */
+
+                /* second phase of the reduction */
+                "pxor %%xmm3, %%xmm1\n\t" /* xor the shifted versions */
+                "psrlq $1, %%xmm3\n\t"    /* packed left shifting >> 1 */
+                "pxor %%xmm3, %%xmm6\n\t"
+                "psrlq $1, %%xmm3\n\t"    /* packed left shifting >> 2 */
+                "pxor %%xmm3, %%xmm1\n\t"
+                "psrlq $5, %%xmm3\n\t"    /* packed left shifting >> 7 */
+                "pxor %%xmm3, %%xmm6\n\t"
+                "pxor %%xmm6, %%xmm1\n\t" /* the result is in xmm1 */
+                ::: "memory" );
+}
+
+static ASM_FUNC_ATTR_INLINE void gfmul_pclmul(void)
 {
   /* Input: XMM0 and XMM1, Output: XMM1. Input XMM0 stays unmodified.
      Input must be converted to little-endian.
@@ -57,245 +96,475 @@ static inline void gfmul_pclmul(void)
 
                 "movdqa %%xmm0, %%xmm3\n\t"
                 "pclmulqdq $0, %%xmm1, %%xmm3\n\t"  /* xmm3 holds a0*b0 */
-                "movdqa %%xmm0, %%xmm6\n\t"
-                "pclmulqdq $17, %%xmm1, %%xmm6\n\t" /* xmm6 holds a1*b1 */
+                "pclmulqdq $17, %%xmm0, %%xmm1\n\t" /* xmm6 holds a1*b1 */
                 "movdqa %%xmm3, %%xmm5\n\t"
                 "pclmulqdq $0, %%xmm2, %%xmm4\n\t"  /* xmm4 holds (a0+a1)*(b0+b1) */
 
-                "pxor %%xmm6, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */
+                "pxor %%xmm1, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */
                 "pxor %%xmm5, %%xmm4\n\t" /* xmm4 holds a0*b0+a1*b1+(a0+a1)*(b0+b1) */
                 "movdqa %%xmm4, %%xmm5\n\t"
                 "psrldq $8, %%xmm4\n\t"
                 "pslldq $8, %%xmm5\n\t"
                 "pxor %%xmm5, %%xmm3\n\t"
-                "pxor %%xmm4, %%xmm6\n\t" /* <xmm6:xmm3> holds the result of the
+                "pxor %%xmm4, %%xmm1\n\t" /* <xmm1:xmm3> holds the result of the
                                              carry-less multiplication of xmm0
                                              by xmm1 */
+                ::: "memory" );
 
-                /* shift the result by one bit position to the left cope for
-                   the fact that bits are reversed */
-                "movdqa %%xmm3, %%xmm4\n\t"
-                "movdqa %%xmm6, %%xmm5\n\t"
-                "pslld $1, %%xmm3\n\t"
-                "pslld $1, %%xmm6\n\t"
-                "psrld $31, %%xmm4\n\t"
-                "psrld $31, %%xmm5\n\t"
-                "movdqa %%xmm4, %%xmm1\n\t"
-                "pslldq $4, %%xmm5\n\t"
-                "pslldq $4, %%xmm4\n\t"
-                "psrldq $12, %%xmm1\n\t"
-                "por %%xmm4, %%xmm3\n\t"
-                "por %%xmm5, %%xmm6\n\t"
-                "por %%xmm6, %%xmm1\n\t"
-
-                /* first phase of the reduction */
-                "movdqa %%xmm3, %%xmm6\n\t"
-                "movdqa %%xmm3, %%xmm7\n\t"
-                "pslld $31, %%xmm6\n\t"  /* packed right shifting << 31 */
-                "movdqa %%xmm3, %%xmm5\n\t"
-                "pslld $30, %%xmm7\n\t"  /* packed right shifting shift << 30 */
-                "pslld $25, %%xmm5\n\t"  /* packed right shifting shift << 25 */
-                "pxor %%xmm7, %%xmm6\n\t" /* xor the shifted versions */
-                "pxor %%xmm5, %%xmm6\n\t"
-                "movdqa %%xmm6, %%xmm7\n\t"
-                "pslldq $12, %%xmm6\n\t"
-                "psrldq $4, %%xmm7\n\t"
-                "pxor %%xmm6, %%xmm3\n\t" /* first phase of the reduction
-                                             complete */
-
-                /* second phase of the reduction */
-                "movdqa %%xmm3, %%xmm2\n\t"
-                "movdqa %%xmm3, %%xmm4\n\t"
-                "psrld $1, %%xmm2\n\t"    /* packed left shifting >> 1 */
-                "movdqa %%xmm3, %%xmm5\n\t"
-                "psrld $2, %%xmm4\n\t"    /* packed left shifting >> 2 */
-                "psrld $7, %%xmm5\n\t"    /* packed left shifting >> 7 */
-                "pxor %%xmm4, %%xmm2\n\t" /* xor the shifted versions */
-                "pxor %%xmm5, %%xmm2\n\t"
-                "pxor %%xmm7, %%xmm2\n\t"
-                "pxor %%xmm2, %%xmm3\n\t"
-                "pxor %%xmm3, %%xmm1\n\t" /* the result is in xmm1 */
-                ::: "cc" );
+  reduction();
 }
 
+#define GFMUL_AGGR4_ASM_1(be_to_le)                                            \
+    /* perform clmul and merge results... */                                   \
+    "movdqu 2*16(%[h_table]), %%xmm2\n\t" /* Load H4 */                        \
+    "movdqu 0*16(%[buf]), %%xmm5\n\t"                                          \
+    be_to_le("pshufb %[be_mask], %%xmm5\n\t") /* be => le */                   \
+    "pxor %%xmm5, %%xmm1\n\t"                                                  \
+                                                                               \
+    "pshufd $78, %%xmm2, %%xmm5\n\t"                                           \
+    "pshufd $78, %%xmm1, %%xmm4\n\t"                                           \
+    "pxor %%xmm2, %%xmm5\n\t" /* xmm5 holds 4:a0+a1 */                         \
+    "pxor %%xmm1, %%xmm4\n\t" /* xmm4 holds 4:b0+b1 */                         \
+    "movdqa %%xmm2, %%xmm3\n\t"                                                \
+    "pclmulqdq $0, %%xmm1, %%xmm3\n\t"   /* xmm3 holds 4:a0*b0 */              \
+    "pclmulqdq $17, %%xmm2, %%xmm1\n\t"  /* xmm1 holds 4:a1*b1 */              \
+    "pclmulqdq $0, %%xmm5, %%xmm4\n\t"   /* xmm4 holds 4:(a0+a1)*(b0+b1) */    \
+                                                                               \
+    "movdqu 1*16(%[h_table]), %%xmm5\n\t" /* Load H3 */                        \
+    "movdqu 1*16(%[buf]), %%xmm2\n\t"                                          \
+    be_to_le("pshufb %[be_mask], %%xmm2\n\t") /* be => le */                   \
+                                                                               \
+    "pshufd $78, %%xmm5, %%xmm0\n\t"                                           \
+    "pshufd $78, %%xmm2, %%xmm7\n\t"                                           \
+    "pxor %%xmm5, %%xmm0\n\t" /* xmm0 holds 3:a0+a1 */                         \
+    "pxor %%xmm2, %%xmm7\n\t" /* xmm7 holds 3:b0+b1 */                         \
+    "movdqa %%xmm5, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm2, %%xmm6\n\t"  /* xmm6 holds 3:a0*b0 */               \
+    "pclmulqdq $17, %%xmm5, %%xmm2\n\t" /* xmm2 holds 3:a1*b1 */               \
+    "pclmulqdq $0, %%xmm0, %%xmm7\n\t" /* xmm7 holds 3:(a0+a1)*(b0+b1) */      \
+                                                                               \
+    "movdqu 2*16(%[buf]), %%xmm5\n\t"                                          \
+    be_to_le("pshufb %[be_mask], %%xmm5\n\t") /* be => le */                   \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 3+4:a0*b0 */                       \
+    "pxor %%xmm2, %%xmm1\n\t" /* xmm1 holds 3+4:a1*b1 */                       \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 3+4:(a0+a1)*(b0+b1) */             \
+                                                                               \
+    "movdqu 0*16(%[h_table]), %%xmm2\n\t" /* Load H2 */                        \
+                                                                               \
+    "pshufd $78, %%xmm2, %%xmm0\n\t"                                           \
+    "pshufd $78, %%xmm5, %%xmm7\n\t"                                           \
+    "pxor %%xmm2, %%xmm0\n\t" /* xmm0 holds 2:a0+a1 */                         \
+    "pxor %%xmm5, %%xmm7\n\t" /* xmm7 holds 2:b0+b1 */                         \
+    "movdqa %%xmm2, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm5, %%xmm6\n\t"  /* xmm6 holds 2:a0*b0 */               \
+    "pclmulqdq $17, %%xmm2, %%xmm5\n\t" /* xmm5 holds 2:a1*b1 */               \
+    "pclmulqdq $0, %%xmm0, %%xmm7\n\t" /* xmm7 holds 2:(a0+a1)*(b0+b1) */      \
+                                                                               \
+    "movdqu 3*16(%[buf]), %%xmm2\n\t"                                          \
+    be_to_le("pshufb %[be_mask], %%xmm2\n\t") /* be => le */                   \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 2+3+4:a0*b0 */                     \
+    "pxor %%xmm5, %%xmm1\n\t" /* xmm1 holds 2+3+4:a1*b1 */                     \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 2+3+4:(a0+a1)*(b0+b1) */
+
+#define GFMUL_AGGR4_ASM_2()                                                    \
+    "movdqu %[h_1], %%xmm5\n\t" /* Load H1 */                                  \
+                                                                               \
+    "pshufd $78, %%xmm5, %%xmm0\n\t"                                           \
+    "pshufd $78, %%xmm2, %%xmm7\n\t"                                           \
+    "pxor %%xmm5, %%xmm0\n\t" /* xmm0 holds 1:a0+a1 */                         \
+    "pxor %%xmm2, %%xmm7\n\t" /* xmm7 holds 1:b0+b1 */                         \
+    "movdqa %%xmm5, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm2, %%xmm6\n\t"  /* xmm6 holds 1:a0*b0 */               \
+    "pclmulqdq $17, %%xmm5, %%xmm2\n\t" /* xmm2 holds 1:a1*b1 */               \
+    "pclmulqdq $0, %%xmm0, %%xmm7\n\t" /* xmm7 holds 1:(a0+a1)*(b0+b1) */      \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 1+2+3+4:a0*b0 */                   \
+    "pxor %%xmm2, %%xmm1\n\t" /* xmm1 holds 1+2+3+4:a1*b1 */                   \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 1+2+3+4:(a0+a1)*(b0+b1) */         \
+                                                                               \
+    /* aggregated reduction... */                                              \
+    "movdqa %%xmm3, %%xmm5\n\t"                                                \
+    "pxor %%xmm1, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */                     \
+    "pxor %%xmm5, %%xmm4\n\t" /* xmm4 holds a0*b0+a1*b1+(a0+a1)*(b0+b1) */     \
+    "movdqa %%xmm4, %%xmm5\n\t"                                                \
+    "psrldq $8, %%xmm4\n\t"                                                    \
+    "pslldq $8, %%xmm5\n\t"                                                    \
+    "pxor %%xmm5, %%xmm3\n\t"                                                  \
+    "pxor %%xmm4, %%xmm1\n\t" /* <xmm1:xmm3> holds the result of the           \
+                                  carry-less multiplication of xmm0            \
+                                  by xmm1 */
+
+#define be_to_le(...) __VA_ARGS__
+#define le_to_le(...) /*_*/
+
+static ASM_FUNC_ATTR_INLINE void
+gfmul_pclmul_aggr4(const void *buf, const void *h_1, const void *h_table,
+                  const unsigned char *be_mask)
+{
+  /* Input:
+      Hash: XMM1
+     Output:
+      Hash: XMM1
+   */
+  asm volatile (GFMUL_AGGR4_ASM_1(be_to_le)
+                :
+                : [buf] "r" (buf),
+                  [h_table] "r" (h_table),
+                  [be_mask] "m" (*be_mask)
+                : "memory" );
 
-#ifdef __x86_64__
-static inline void gfmul_pclmul_aggr4(void)
+  asm volatile (GFMUL_AGGR4_ASM_2()
+                :
+                : [h_1] "m" (*(const unsigned char *)h_1)
+                : "memory" );
+
+  reduction();
+}
+
+static ASM_FUNC_ATTR_INLINE void
+gfmul_pclmul_aggr4_le(const void *buf, const void *h_1, const void *h_table)
 {
   /* Input:
-      H¹: XMM0          X_i            : XMM6
-      H²: XMM8          X_(i-1)        : XMM3
-      H³: XMM9          X_(i-2)        : XMM2
-      H⁴: XMM10         X_(i-3)⊕Y_(i-4): XMM1
+      Hash: XMM1
      Output:
-      Y_i: XMM1
-     Inputs XMM0 stays unmodified.
-     Input must be converted to little-endian.
+      Hash: XMM1
    */
-  asm volatile (/* perform clmul and merge results... */
-                "pshufd $78, %%xmm10, %%xmm11\n\t"
-                "pshufd $78, %%xmm1, %%xmm12\n\t"
-                "pxor %%xmm10, %%xmm11\n\t" /* xmm11 holds 4:a0+a1 */
-                "pxor %%xmm1, %%xmm12\n\t" /* xmm12 holds 4:b0+b1 */
-
-                "pshufd $78, %%xmm9, %%xmm13\n\t"
-                "pshufd $78, %%xmm2, %%xmm14\n\t"
-                "pxor %%xmm9, %%xmm13\n\t" /* xmm13 holds 3:a0+a1 */
-                "pxor %%xmm2, %%xmm14\n\t" /* xmm14 holds 3:b0+b1 */
-
-                "pshufd $78, %%xmm8, %%xmm5\n\t"
-                "pshufd $78, %%xmm3, %%xmm15\n\t"
-                "pxor %%xmm8, %%xmm5\n\t" /* xmm1 holds 2:a0+a1 */
-                "pxor %%xmm3, %%xmm15\n\t" /* xmm2 holds 2:b0+b1 */
-
-                "movdqa %%xmm10, %%xmm4\n\t"
-                "movdqa %%xmm9, %%xmm7\n\t"
-                "pclmulqdq $0, %%xmm1, %%xmm4\n\t"   /* xmm4 holds 4:a0*b0 */
-                "pclmulqdq $0, %%xmm2, %%xmm7\n\t"   /* xmm7 holds 3:a0*b0 */
-                "pclmulqdq $17, %%xmm10, %%xmm1\n\t" /* xmm1 holds 4:a1*b1 */
-                "pclmulqdq $17, %%xmm9, %%xmm2\n\t"  /* xmm9 holds 3:a1*b1 */
-                "pclmulqdq $0, %%xmm11, %%xmm12\n\t" /* xmm12 holds 4:(a0+a1)*(b0+b1) */
-                "pclmulqdq $0, %%xmm13, %%xmm14\n\t" /* xmm14 holds 3:(a0+a1)*(b0+b1) */
-
-                "pshufd $78, %%xmm0, %%xmm10\n\t"
-                "pshufd $78, %%xmm6, %%xmm11\n\t"
-                "pxor %%xmm0, %%xmm10\n\t" /* xmm10 holds 1:a0+a1 */
-                "pxor %%xmm6, %%xmm11\n\t" /* xmm11 holds 1:b0+b1 */
-
-                "pxor %%xmm4, %%xmm7\n\t"   /* xmm7 holds 3+4:a0*b0 */
-                "pxor %%xmm2, %%xmm1\n\t"   /* xmm1 holds 3+4:a1*b1 */
-                "pxor %%xmm14, %%xmm12\n\t" /* xmm12 holds 3+4:(a0+a1)*(b0+b1) */
-
-                "movdqa %%xmm8, %%xmm13\n\t"
-                "pclmulqdq $0, %%xmm3, %%xmm13\n\t"  /* xmm13 holds 2:a0*b0 */
-                "pclmulqdq $17, %%xmm8, %%xmm3\n\t"  /* xmm3 holds 2:a1*b1 */
-                "pclmulqdq $0, %%xmm5, %%xmm15\n\t" /* xmm15 holds 2:(a0+a1)*(b0+b1) */
-
-                "pxor %%xmm13, %%xmm7\n\t" /* xmm7 holds 2+3+4:a0*b0 */
-                "pxor %%xmm3, %%xmm1\n\t"  /* xmm1 holds 2+3+4:a1*b1 */
-                "pxor %%xmm15, %%xmm12\n\t" /* xmm12 holds 2+3+4:(a0+a1)*(b0+b1) */
+  asm volatile (GFMUL_AGGR4_ASM_1(le_to_le)
+                :
+                : [buf] "r" (buf),
+                  [h_table] "r" (h_table)
+                : "memory" );
 
-                "movdqa %%xmm0, %%xmm3\n\t"
-                "pclmulqdq $0, %%xmm6, %%xmm3\n\t"  /* xmm3 holds 1:a0*b0 */
-                "pclmulqdq $17, %%xmm0, %%xmm6\n\t" /* xmm6 holds 1:a1*b1 */
-                "movdqa %%xmm11, %%xmm4\n\t"
-                "pclmulqdq $0, %%xmm10, %%xmm4\n\t" /* xmm4 holds 1:(a0+a1)*(b0+b1) */
+  asm volatile (GFMUL_AGGR4_ASM_2()
+                :
+                : [h_1] "m" (*(const unsigned char *)h_1)
+                : "memory" );
 
-                "pxor %%xmm7, %%xmm3\n\t"  /* xmm3 holds 1+2+3+4:a0*b0 */
-                "pxor %%xmm1, %%xmm6\n\t"  /* xmm6 holds 1+2+3+4:a1*b1 */
-                "pxor %%xmm12, %%xmm4\n\t" /* xmm4 holds 1+2+3+4:(a0+a1)*(b0+b1) */
+  reduction();
+}
 
-                /* aggregated reduction... */
-                "movdqa %%xmm3, %%xmm5\n\t"
-                "pxor %%xmm6, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */
-                "pxor %%xmm5, %%xmm4\n\t" /* xmm4 holds a0*b0+a1*b1+(a0+a1)*(b0+b1) */
-                "movdqa %%xmm4, %%xmm5\n\t"
-                "psrldq $8, %%xmm4\n\t"
-                "pslldq $8, %%xmm5\n\t"
-                "pxor %%xmm5, %%xmm3\n\t"
-                "pxor %%xmm4, %%xmm6\n\t" /* <xmm6:xmm3> holds the result of the
-                                             carry-less multiplication of xmm0
-                                             by xmm1 */
+#ifdef __x86_64__
 
-                /* shift the result by one bit position to the left cope for
-                   the fact that bits are reversed */
-                "movdqa %%xmm3, %%xmm4\n\t"
-                "movdqa %%xmm6, %%xmm5\n\t"
-                "pslld $1, %%xmm3\n\t"
-                "pslld $1, %%xmm6\n\t"
-                "psrld $31, %%xmm4\n\t"
-                "psrld $31, %%xmm5\n\t"
-                "movdqa %%xmm4, %%xmm1\n\t"
-                "pslldq $4, %%xmm5\n\t"
-                "pslldq $4, %%xmm4\n\t"
-                "psrldq $12, %%xmm1\n\t"
-                "por %%xmm4, %%xmm3\n\t"
-                "por %%xmm5, %%xmm6\n\t"
-                "por %%xmm6, %%xmm1\n\t"
-
-                /* first phase of the reduction */
-                "movdqa %%xmm3, %%xmm6\n\t"
-                "movdqa %%xmm3, %%xmm7\n\t"
-                "pslld $31, %%xmm6\n\t"  /* packed right shifting << 31 */
-                "movdqa %%xmm3, %%xmm5\n\t"
-                "pslld $30, %%xmm7\n\t"  /* packed right shifting shift << 30 */
-                "pslld $25, %%xmm5\n\t"  /* packed right shifting shift << 25 */
-                "pxor %%xmm7, %%xmm6\n\t" /* xor the shifted versions */
-                "pxor %%xmm5, %%xmm6\n\t"
-                "movdqa %%xmm6, %%xmm7\n\t"
-                "pslldq $12, %%xmm6\n\t"
-                "psrldq $4, %%xmm7\n\t"
-                "pxor %%xmm6, %%xmm3\n\t" /* first phase of the reduction
-                                             complete */
+#define GFMUL_AGGR8_ASM(be_to_le)                                              \
+    /* Load H6, H7, H8. */                                                     \
+    "movdqu 6*16(%[h_table]), %%xmm10\n\t"                                     \
+    "movdqu 5*16(%[h_table]), %%xmm9\n\t"                                      \
+    "movdqu 4*16(%[h_table]), %%xmm8\n\t"                                      \
+                                                                               \
+    /* perform clmul and merge results... */                                   \
+    "movdqu 0*16(%[buf]), %%xmm5\n\t"                                          \
+    "movdqu 1*16(%[buf]), %%xmm2\n\t"                                          \
+    be_to_le("pshufb %%xmm15, %%xmm5\n\t") /* be => le */                      \
+    be_to_le("pshufb %%xmm15, %%xmm2\n\t") /* be => le */                      \
+    "pxor %%xmm5, %%xmm1\n\t"                                                  \
+                                                                               \
+    "pshufd $78, %%xmm10, %%xmm5\n\t"                                          \
+    "pshufd $78, %%xmm1, %%xmm4\n\t"                                           \
+    "pxor %%xmm10, %%xmm5\n\t" /* xmm5 holds 8:a0+a1 */                        \
+    "pxor %%xmm1, %%xmm4\n\t"  /* xmm4 holds 8:b0+b1 */                        \
+    "movdqa %%xmm10, %%xmm3\n\t"                                               \
+    "pclmulqdq $0, %%xmm1, %%xmm3\n\t"   /* xmm3 holds 8:a0*b0 */              \
+    "pclmulqdq $17, %%xmm10, %%xmm1\n\t" /* xmm1 holds 8:a1*b1 */              \
+    "pclmulqdq $0, %%xmm5, %%xmm4\n\t"   /* xmm4 holds 8:(a0+a1)*(b0+b1) */    \
+                                                                               \
+    "pshufd $78, %%xmm9, %%xmm11\n\t"                                          \
+    "pshufd $78, %%xmm2, %%xmm7\n\t"                                           \
+    "pxor %%xmm9, %%xmm11\n\t" /* xmm11 holds 7:a0+a1 */                       \
+    "pxor %%xmm2, %%xmm7\n\t"  /* xmm7 holds 7:b0+b1 */                        \
+    "movdqa %%xmm9, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm2, %%xmm6\n\t"  /* xmm6 holds 7:a0*b0 */               \
+    "pclmulqdq $17, %%xmm9, %%xmm2\n\t" /* xmm2 holds 7:a1*b1 */               \
+    "pclmulqdq $0, %%xmm11, %%xmm7\n\t" /* xmm7 holds 7:(a0+a1)*(b0+b1) */     \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 7+8:a0*b0 */                       \
+    "pxor %%xmm2, %%xmm1\n\t" /* xmm1 holds 7+8:a1*b1 */                       \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 7+8:(a0+a1)*(b0+b1) */             \
+                                                                               \
+    "movdqu 2*16(%[buf]), %%xmm5\n\t"                                          \
+    "movdqu 3*16(%[buf]), %%xmm2\n\t"                                          \
+    be_to_le("pshufb %%xmm15, %%xmm5\n\t") /* be => le */                      \
+    be_to_le("pshufb %%xmm15, %%xmm2\n\t") /* be => le */                      \
+                                                                               \
+    "pshufd $78, %%xmm8, %%xmm11\n\t"                                          \
+    "pshufd $78, %%xmm5, %%xmm7\n\t"                                           \
+    "pxor %%xmm8, %%xmm11\n\t" /* xmm11 holds 6:a0+a1 */                       \
+    "pxor %%xmm5, %%xmm7\n\t"  /* xmm7 holds 6:b0+b1 */                        \
+    "movdqa %%xmm8, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm5, %%xmm6\n\t"  /* xmm6 holds 6:a0*b0 */               \
+    "pclmulqdq $17, %%xmm8, %%xmm5\n\t" /* xmm5 holds 6:a1*b1 */               \
+    "pclmulqdq $0, %%xmm11, %%xmm7\n\t" /* xmm7 holds 6:(a0+a1)*(b0+b1) */     \
+                                                                               \
+    /* Load H3, H4, H5. */                                                     \
+    "movdqu 3*16(%[h_table]), %%xmm10\n\t"                                     \
+    "movdqu 2*16(%[h_table]), %%xmm9\n\t"                                      \
+    "movdqu 1*16(%[h_table]), %%xmm8\n\t"                                      \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 6+7+8:a0*b0 */                     \
+    "pxor %%xmm5, %%xmm1\n\t" /* xmm1 holds 6+7+8:a1*b1 */                     \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 6+7+8:(a0+a1)*(b0+b1) */           \
+                                                                               \
+    "pshufd $78, %%xmm10, %%xmm11\n\t"                                         \
+    "pshufd $78, %%xmm2, %%xmm7\n\t"                                           \
+    "pxor %%xmm10, %%xmm11\n\t" /* xmm11 holds 5:a0+a1 */                      \
+    "pxor %%xmm2, %%xmm7\n\t"   /* xmm7 holds 5:b0+b1 */                       \
+    "movdqa %%xmm10, %%xmm6\n\t"                                               \
+    "pclmulqdq $0, %%xmm2, %%xmm6\n\t"   /* xmm6 holds 5:a0*b0 */              \
+    "pclmulqdq $17, %%xmm10, %%xmm2\n\t" /* xmm2 holds 5:a1*b1 */              \
+    "pclmulqdq $0, %%xmm11, %%xmm7\n\t"  /* xmm7 holds 5:(a0+a1)*(b0+b1) */    \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 5+6+7+8:a0*b0 */                   \
+    "pxor %%xmm2, %%xmm1\n\t" /* xmm1 holds 5+6+7+8:a1*b1 */                   \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 5+6+7+8:(a0+a1)*(b0+b1) */         \
+                                                                               \
+    "movdqu 4*16(%[buf]), %%xmm5\n\t"                                          \
+    "movdqu 5*16(%[buf]), %%xmm2\n\t"                                          \
+    be_to_le("pshufb %%xmm15, %%xmm5\n\t") /* be => le */                      \
+    be_to_le("pshufb %%xmm15, %%xmm2\n\t") /* be => le */                      \
+                                                                               \
+    "pshufd $78, %%xmm9, %%xmm11\n\t"                                          \
+    "pshufd $78, %%xmm5, %%xmm7\n\t"                                           \
+    "pxor %%xmm9, %%xmm11\n\t" /* xmm11 holds 4:a0+a1 */                       \
+    "pxor %%xmm5, %%xmm7\n\t"  /* xmm7 holds 4:b0+b1 */                        \
+    "movdqa %%xmm9, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm5, %%xmm6\n\t"  /* xmm6 holds 4:a0*b0 */               \
+    "pclmulqdq $17, %%xmm9, %%xmm5\n\t" /* xmm5 holds 4:a1*b1 */               \
+    "pclmulqdq $0, %%xmm11, %%xmm7\n\t" /* xmm7 holds 4:(a0+a1)*(b0+b1) */     \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 4+5+6+7+8:a0*b0 */                 \
+    "pxor %%xmm5, %%xmm1\n\t" /* xmm1 holds 4+5+6+7+8:a1*b1 */                 \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 4+5+6+7+8:(a0+a1)*(b0+b1) */       \
+                                                                               \
+    "pshufd $78, %%xmm8, %%xmm11\n\t"                                          \
+    "pshufd $78, %%xmm2, %%xmm7\n\t"                                           \
+    "pxor %%xmm8, %%xmm11\n\t" /* xmm11 holds 3:a0+a1 */                       \
+    "pxor %%xmm2, %%xmm7\n\t"  /* xmm7 holds 3:b0+b1 */                        \
+    "movdqa %%xmm8, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm2, %%xmm6\n\t"  /* xmm6 holds 3:a0*b0 */               \
+    "pclmulqdq $17, %%xmm8, %%xmm2\n\t" /* xmm2 holds 3:a1*b1 */               \
+    "pclmulqdq $0, %%xmm11, %%xmm7\n\t" /* xmm7 holds 3:(a0+a1)*(b0+b1) */     \
+                                                                               \
+    "movdqu 0*16(%[h_table]), %%xmm8\n\t" /* Load H2 */                        \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 3+4+5+6+7+8:a0*b0 */               \
+    "pxor %%xmm2, %%xmm1\n\t" /* xmm1 holds 3+4+5+6+7+8:a1*b1 */               \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 3+4+5+6+7+8:(a0+a1)*(b0+b1) */     \
+                                                                               \
+    "movdqu 6*16(%[buf]), %%xmm5\n\t"                                          \
+    "movdqu 7*16(%[buf]), %%xmm2\n\t"                                          \
+    be_to_le("pshufb %%xmm15, %%xmm5\n\t") /* be => le */                      \
+    be_to_le("pshufb %%xmm15, %%xmm2\n\t") /* be => le */                      \
+                                                                               \
+    "pshufd $78, %%xmm8, %%xmm11\n\t"                                          \
+    "pshufd $78, %%xmm5, %%xmm7\n\t"                                           \
+    "pxor %%xmm8, %%xmm11\n\t"  /* xmm11 holds 4:a0+a1 */                      \
+    "pxor %%xmm5, %%xmm7\n\t"   /* xmm7 holds 4:b0+b1 */                       \
+    "movdqa %%xmm8, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm5, %%xmm6\n\t"   /* xmm6 holds 4:a0*b0 */              \
+    "pclmulqdq $17, %%xmm8, %%xmm5\n\t"  /* xmm5 holds 4:a1*b1 */              \
+    "pclmulqdq $0, %%xmm11, %%xmm7\n\t"  /* xmm7 holds 4:(a0+a1)*(b0+b1) */    \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 2+3+4+5+6+7+8:a0*b0 */             \
+    "pxor %%xmm5, %%xmm1\n\t" /* xmm1 holds 2+3+4+5+6+7+8:a1*b1 */             \
+    "pxor %%xmm7, %%xmm4\n\t" /* xmm4 holds 2+3+4+5+6+7+8:(a0+a1)*(b0+b1) */   \
+                                                                               \
+    "pshufd $78, %%xmm0, %%xmm11\n\t"                                          \
+    "pshufd $78, %%xmm2, %%xmm7\n\t"                                           \
+    "pxor %%xmm0, %%xmm11\n\t" /* xmm11 holds 3:a0+a1 */                       \
+    "pxor %%xmm2, %%xmm7\n\t"  /* xmm7 holds 3:b0+b1 */                        \
+    "movdqa %%xmm0, %%xmm6\n\t"                                                \
+    "pclmulqdq $0, %%xmm2, %%xmm6\n\t"  /* xmm6 holds 3:a0*b0 */               \
+    "pclmulqdq $17, %%xmm0, %%xmm2\n\t" /* xmm2 holds 3:a1*b1 */               \
+    "pclmulqdq $0, %%xmm11, %%xmm7\n\t" /* xmm7 holds 3:(a0+a1)*(b0+b1) */     \
+                                                                               \
+    "pxor %%xmm6, %%xmm3\n\t" /* xmm3 holds 1+2+3+3+4+5+6+7+8:a0*b0 */         \
+    "pxor %%xmm2, %%xmm1\n\t" /* xmm1 holds 1+2+3+3+4+5+6+7+8:a1*b1 */         \
+    "pxor %%xmm7, %%xmm4\n\t"/* xmm4 holds 1+2+3+3+4+5+6+7+8:(a0+a1)*(b0+b1) */\
+                                                                               \
+    /* aggregated reduction... */                                              \
+    "movdqa %%xmm3, %%xmm5\n\t"                                                \
+    "pxor %%xmm1, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */                     \
+    "pxor %%xmm5, %%xmm4\n\t" /* xmm4 holds a0*b0+a1*b1+(a0+a1)*(b0+b1) */     \
+    "movdqa %%xmm4, %%xmm5\n\t"                                                \
+    "psrldq $8, %%xmm4\n\t"                                                    \
+    "pslldq $8, %%xmm5\n\t"                                                    \
+    "pxor %%xmm5, %%xmm3\n\t"                                                  \
+    "pxor %%xmm4, %%xmm1\n\t" /* <xmm1:xmm3> holds the result of the           \
+                                  carry-less multiplication of xmm0            \
+                                  by xmm1 */
+
+static ASM_FUNC_ATTR_INLINE void
+gfmul_pclmul_aggr8(const void *buf, const void *h_table)
+{
+  /* Input:
+      H¹: XMM0
+      bemask: XMM15
+      Hash: XMM1
+     Output:
+      Hash: XMM1
+     Inputs XMM0 and XMM15 stays unmodified.
+   */
+  asm volatile (GFMUL_AGGR8_ASM(be_to_le)
+                :
+                : [buf] "r" (buf),
+                  [h_table] "r" (h_table)
+                : "memory" );
 
-                /* second phase of the reduction */
-                "movdqa %%xmm3, %%xmm2\n\t"
-                "movdqa %%xmm3, %%xmm4\n\t"
-                "psrld $1, %%xmm2\n\t"    /* packed left shifting >> 1 */
-                "movdqa %%xmm3, %%xmm5\n\t"
-                "psrld $2, %%xmm4\n\t"    /* packed left shifting >> 2 */
-                "psrld $7, %%xmm5\n\t"    /* packed left shifting >> 7 */
-                "pxor %%xmm4, %%xmm2\n\t" /* xor the shifted versions */
-                "pxor %%xmm5, %%xmm2\n\t"
-                "pxor %%xmm7, %%xmm2\n\t"
-                "pxor %%xmm2, %%xmm3\n\t"
-                "pxor %%xmm3, %%xmm1\n\t" /* the result is in xmm1 */
-                :::"cc");
+  reduction();
+}
+
+static ASM_FUNC_ATTR_INLINE void
+gfmul_pclmul_aggr8_le(const void *buf, const void *h_table)
+{
+  /* Input:
+      H¹: XMM0
+      Hash: XMM1
+     Output:
+      Hash: XMM1
+     Inputs XMM0 and XMM15 stays unmodified.
+   */
+  asm volatile (GFMUL_AGGR8_ASM(le_to_le)
+                :
+                : [buf] "r" (buf),
+                  [h_table] "r" (h_table)
+                : "memory" );
+
+  reduction();
 }
 #endif
 
+static ASM_FUNC_ATTR_INLINE void gcm_lsh(void *h, unsigned int hoffs)
+{
+  static const u64 pconst[2] __attribute__ ((aligned (16))) =
+    { U64_C(0x0000000000000001), U64_C(0xc200000000000000) };
+
+  asm volatile ("movdqu (%[h]), %%xmm2\n\t"
+                "pshufd $0xff, %%xmm2, %%xmm3\n\t"
+                "movdqa %%xmm2, %%xmm4\n\t"
+                "psrad $31, %%xmm3\n\t"
+                "pslldq $8, %%xmm4\n\t"
+                "pand %[pconst], %%xmm3\n\t"
+                "paddq %%xmm2, %%xmm2\n\t"
+                "psrlq $63, %%xmm4\n\t"
+                "pxor %%xmm3, %%xmm2\n\t"
+                "pxor %%xmm4, %%xmm2\n\t"
+                "movdqu %%xmm2, (%[h])\n\t"
+                :
+                : [pconst] "m" (*pconst),
+                  [h] "r" ((byte *)h + hoffs)
+                : "memory" );
+}
 
-void
+void ASM_FUNC_ATTR
 _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c)
 {
-  u64 tmp[2];
+  static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
+    { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
 #if defined(__x86_64__) && defined(__WIN64__)
-  char win64tmp[3 * 16];
+  char win64tmp[10 * 16];
 
-  /* XMM6-XMM8 need to be restored after use. */
-  asm volatile ("movdqu %%xmm6, 0*16(%0)\n\t"
-                "movdqu %%xmm7, 1*16(%0)\n\t"
-                "movdqu %%xmm8, 2*16(%0)\n\t"
+  /* XMM6-XMM15 need to be restored after use. */
+  asm volatile ("movdqu %%xmm6,  0*16(%0)\n\t"
+                "movdqu %%xmm7,  1*16(%0)\n\t"
+                "movdqu %%xmm8,  2*16(%0)\n\t"
+                "movdqu %%xmm9,  3*16(%0)\n\t"
+                "movdqu %%xmm10, 4*16(%0)\n\t"
+                "movdqu %%xmm11, 5*16(%0)\n\t"
+                "movdqu %%xmm12, 6*16(%0)\n\t"
+                "movdqu %%xmm13, 7*16(%0)\n\t"
+                "movdqu %%xmm14, 8*16(%0)\n\t"
+                "movdqu %%xmm15, 9*16(%0)\n\t"
                 :
                 : "r" (win64tmp)
-                : "memory");
+                : "memory" );
 #endif
 
   /* Swap endianness of hsub. */
-  tmp[0] = buf_get_be64(c->u_mode.gcm.u_ghash_key.key + 8);
-  tmp[1] = buf_get_be64(c->u_mode.gcm.u_ghash_key.key + 0);
-  buf_cpy (c->u_mode.gcm.u_ghash_key.key, tmp, GCRY_GCM_BLOCK_LEN);
+  asm volatile ("movdqu (%[key]), %%xmm0\n\t"
+                "pshufb %[be_mask], %%xmm0\n\t"
+                "movdqu %%xmm0, (%[key])\n\t"
+                :
+                : [key] "r" (c->u_mode.gcm.u_ghash_key.key),
+                  [be_mask] "m" (*be_mask)
+                : "memory");
+
+  gcm_lsh(c->u_mode.gcm.u_ghash_key.key, 0); /* H <<< 1 */
+
+  asm volatile ("movdqa %%xmm0, %%xmm1\n\t"
+                "movdqu (%[key]), %%xmm0\n\t" /* load H <<< 1 */
+                :
+                : [key] "r" (c->u_mode.gcm.u_ghash_key.key)
+                : "memory");
+
+  gfmul_pclmul (); /* H<<<1•H => H² */
+
+  asm volatile ("movdqu %%xmm1, 0*16(%[h_table])\n\t"
+                "movdqa %%xmm1, %%xmm7\n\t"
+                :
+                : [h_table] "r" (c->u_mode.gcm.gcm_table)
+                : "memory");
+
+  gcm_lsh(c->u_mode.gcm.gcm_table, 0 * 16); /* H² <<< 1 */
+  gfmul_pclmul (); /* H<<<1•H² => H³ */
+
+  asm volatile ("movdqa %%xmm7, %%xmm0\n\t"
+                "movdqu %%xmm1, 1*16(%[h_table])\n\t"
+                "movdqu 0*16(%[h_table]), %%xmm1\n\t" /* load H² <<< 1 */
+                :
+                : [h_table] "r" (c->u_mode.gcm.gcm_table)
+                : "memory");
+
+  gfmul_pclmul (); /* H²<<<1•H² => H⁴ */
+
+  asm volatile ("movdqu %%xmm1, 2*16(%[h_table])\n\t"
+                "movdqa %%xmm1, %%xmm0\n\t"
+                "movdqu (%[key]), %%xmm1\n\t" /* load H <<< 1 */
+                :
+                : [h_table] "r" (c->u_mode.gcm.gcm_table),
+                  [key] "r" (c->u_mode.gcm.u_ghash_key.key)
+                : "memory");
+
+  gcm_lsh(c->u_mode.gcm.gcm_table, 1 * 16); /* H³ <<< 1 */
+  gcm_lsh(c->u_mode.gcm.gcm_table, 2 * 16); /* H⁴ <<< 1 */
 
 #ifdef __x86_64__
-  asm volatile ("movdqu %[h_1], %%xmm0\n\t"
-                "movdqa %%xmm0, %%xmm1\n\t"
+  gfmul_pclmul (); /* H<<<1•H⁴ => H⁵ */
+
+  asm volatile ("movdqu %%xmm1, 3*16(%[h_table])\n\t"
+                "movdqu 0*16(%[h_table]), %%xmm1\n\t" /* load H² <<< 1 */
                 :
-                : [h_1] "m" (*tmp));
+                : [h_table] "r" (c->u_mode.gcm.gcm_table)
+                : "memory");
 
-  gfmul_pclmul (); /* H•H => H² */
+  gfmul_pclmul (); /* H²<<<1•H⁴ => H⁶ */
 
-  asm volatile ("movdqu %%xmm1, 0*16(%[h_234])\n\t"
-                "movdqa %%xmm1, %%xmm8\n\t"
+  asm volatile ("movdqu %%xmm1, 4*16(%[h_table])\n\t"
+                "movdqu 1*16(%[h_table]), %%xmm1\n\t" /* load H³ <<< 1 */
                 :
-                : [h_234] "r" (c->u_mode.gcm.gcm_table)
+                : [h_table] "r" (c->u_mode.gcm.gcm_table)
                 : "memory");
 
-  gfmul_pclmul (); /* H•H² => H³ */
+  gfmul_pclmul (); /* H³<<<1•H⁴ => H⁷ */
 
-  asm volatile ("movdqa %%xmm8, %%xmm0\n\t"
-                "movdqu %%xmm1, 1*16(%[h_234])\n\t"
-                "movdqa %%xmm8, %%xmm1\n\t"
+  asm volatile ("movdqu %%xmm1, 5*16(%[h_table])\n\t"
+                "movdqu 2*16(%[h_table]), %%xmm1\n\t" /* load H⁴ <<< 1 */
                 :
-                : [h_234] "r" (c->u_mode.gcm.gcm_table)
+                : [h_table] "r" (c->u_mode.gcm.gcm_table)
                 : "memory");
 
-  gfmul_pclmul (); /* H²â\80¢H² => Hâ\81´ */
+  gfmul_pclmul (); /* H³<<<1â\80¢Hâ\81´ => Hâ\81¸ */
 
-  asm volatile ("movdqu %%xmm1, 2*16(%[h_234])\n\t"
+  asm volatile ("movdqu %%xmm1, 6*16(%[h_table])\n\t"
                 :
-                : [h_234] "r" (c->u_mode.gcm.gcm_table)
+                : [h_table] "r" (c->u_mode.gcm.gcm_table)
                 : "memory");
 
+  gcm_lsh(c->u_mode.gcm.gcm_table, 3 * 16); /* H⁵ <<< 1 */
+  gcm_lsh(c->u_mode.gcm.gcm_table, 4 * 16); /* H⁶ <<< 1 */
+  gcm_lsh(c->u_mode.gcm.gcm_table, 5 * 16); /* H⁷ <<< 1 */
+  gcm_lsh(c->u_mode.gcm.gcm_table, 6 * 16); /* H⁸ <<< 1 */
+
 #ifdef __WIN64__
   /* Clear/restore used registers. */
   asm volatile( "pxor %%xmm0, %%xmm0\n\t"
@@ -307,9 +576,16 @@ _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c)
                 "movdqu 0*16(%0), %%xmm6\n\t"
                 "movdqu 1*16(%0), %%xmm7\n\t"
                 "movdqu 2*16(%0), %%xmm8\n\t"
+                "movdqu 3*16(%0), %%xmm9\n\t"
+                "movdqu 4*16(%0), %%xmm10\n\t"
+                "movdqu 5*16(%0), %%xmm11\n\t"
+                "movdqu 6*16(%0), %%xmm12\n\t"
+                "movdqu 7*16(%0), %%xmm13\n\t"
+                "movdqu 8*16(%0), %%xmm14\n\t"
+                "movdqu 9*16(%0), %%xmm15\n\t"
                 :
                 : "r" (win64tmp)
-                : "memory");
+                : "memory" );
 #else
   /* Clear used registers. */
   asm volatile( "pxor %%xmm0, %%xmm0\n\t"
@@ -321,30 +597,35 @@ _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c)
                 "pxor %%xmm6, %%xmm6\n\t"
                 "pxor %%xmm7, %%xmm7\n\t"
                 "pxor %%xmm8, %%xmm8\n\t"
-                ::: "cc" );
+                "pxor %%xmm9, %%xmm9\n\t"
+                "pxor %%xmm10, %%xmm10\n\t"
+                "pxor %%xmm11, %%xmm11\n\t"
+                "pxor %%xmm12, %%xmm12\n\t"
+                "pxor %%xmm13, %%xmm13\n\t"
+                "pxor %%xmm14, %%xmm14\n\t"
+                "pxor %%xmm15, %%xmm15\n\t"
+                ::: "memory" );
 #endif
 #endif
-
-  wipememory (tmp, sizeof(tmp));
 }
 
 
-unsigned int
+unsigned int ASM_FUNC_ATTR
 _gcry_ghash_intel_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf,
                           size_t nblocks)
 {
   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
   const unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
-#ifdef __WIN64__
+#if defined(__x86_64__) && defined(__WIN64__)
   char win64tmp[10 * 16];
 #endif
 
   if (nblocks == 0)
     return 0;
 
-#ifdef __WIN64__
-  /* XMM8-XMM15 need to be restored after use. */
+#if defined(__x86_64__) && defined(__WIN64__)
+  /* XMM6-XMM15 need to be restored after use. */
   asm volatile ("movdqu %%xmm6,  0*16(%0)\n\t"
                 "movdqu %%xmm7,  1*16(%0)\n\t"
                 "movdqu %%xmm8,  2*16(%0)\n\t"
@@ -360,46 +641,181 @@ _gcry_ghash_intel_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf,
                 : "memory" );
 #endif
 
-  /* Preload hash and H1. */
-  asm volatile ("movdqu %[hash], %%xmm1\n\t"
-                "movdqa %[hsub], %%xmm0\n\t"
-                "pshufb %[be_mask], %%xmm1\n\t" /* be => le */
+  /* Preload hash. */
+  asm volatile ("movdqa %[be_mask], %%xmm7\n\t"
+                "movdqu %[hash], %%xmm1\n\t"
+                "pshufb %%xmm7, %%xmm1\n\t" /* be => le */
                 :
-                : [hash] "m" (*result), [be_mask] "m" (*be_mask),
-                  [hsub] "m" (*c->u_mode.gcm.u_ghash_key.key));
+                : [hash] "m" (*result),
+                  [be_mask] "m" (*be_mask)
+                : "memory" );
 
 #ifdef __x86_64__
-  if (nblocks >= 4)
+  if (nblocks >= 8)
     {
-      do
+      /* Preload H1. */
+      asm volatile ("movdqa %%xmm7, %%xmm15\n\t"
+                    "movdqa %[h_1], %%xmm0\n\t"
+                    :
+                    : [h_1] "m" (*c->u_mode.gcm.u_ghash_key.key)
+                    : "memory" );
+
+      while (nblocks >= 8)
         {
-          asm volatile ("movdqa %[be_mask], %%xmm4\n\t"
-                        "movdqu 0*16(%[buf]), %%xmm5\n\t"
-                        "movdqu 1*16(%[buf]), %%xmm2\n\t"
-                        "movdqu 2*16(%[buf]), %%xmm3\n\t"
-                        "movdqu 3*16(%[buf]), %%xmm6\n\t"
-                        "pshufb %%xmm4, %%xmm5\n\t" /* be => le */
-
-                        /* Load H2, H3, H4. */
-                        "movdqu 2*16(%[h_234]), %%xmm10\n\t"
-                        "movdqu 1*16(%[h_234]), %%xmm9\n\t"
-                        "movdqu 0*16(%[h_234]), %%xmm8\n\t"
-
-                        "pxor %%xmm5, %%xmm1\n\t"
-                        "pshufb %%xmm4, %%xmm2\n\t" /* be => le */
-                        "pshufb %%xmm4, %%xmm3\n\t" /* be => le */
-                        "pshufb %%xmm4, %%xmm6\n\t" /* be => le */
+          gfmul_pclmul_aggr8 (buf, c->u_mode.gcm.gcm_table);
+
+          buf += 8 * blocksize;
+          nblocks -= 8;
+        }
+#ifndef __WIN64__
+      /* Clear used x86-64/XMM registers. */
+      asm volatile( "pxor %%xmm8, %%xmm8\n\t"
+                    "pxor %%xmm9, %%xmm9\n\t"
+                    "pxor %%xmm10, %%xmm10\n\t"
+                    "pxor %%xmm11, %%xmm11\n\t"
+                    "pxor %%xmm12, %%xmm12\n\t"
+                    "pxor %%xmm13, %%xmm13\n\t"
+                    "pxor %%xmm14, %%xmm14\n\t"
+                    "pxor %%xmm15, %%xmm15\n\t"
+                    ::: "memory" );
+#endif
+    }
+#endif
+
+  while (nblocks >= 4)
+    {
+      gfmul_pclmul_aggr4 (buf, c->u_mode.gcm.u_ghash_key.key,
+                          c->u_mode.gcm.gcm_table, be_mask);
+
+      buf += 4 * blocksize;
+      nblocks -= 4;
+    }
+
+  if (nblocks)
+    {
+      /* Preload H1. */
+      asm volatile ("movdqa %[h_1], %%xmm0\n\t"
+                    :
+                    : [h_1] "m" (*c->u_mode.gcm.u_ghash_key.key)
+                    : "memory" );
+
+      while (nblocks)
+        {
+          asm volatile ("movdqu %[buf], %%xmm2\n\t"
+                        "pshufb %[be_mask], %%xmm2\n\t" /* be => le */
+                        "pxor %%xmm2, %%xmm1\n\t"
                         :
-                        : [buf] "r" (buf), [be_mask] "m" (*be_mask),
-                          [h_234] "r" (c->u_mode.gcm.gcm_table));
+                        : [buf] "m" (*buf), [be_mask] "m" (*be_mask)
+                        : "memory" );
 
-          gfmul_pclmul_aggr4 ();
+          gfmul_pclmul ();
 
-          buf += 4 * blocksize;
-          nblocks -= 4;
+          buf += blocksize;
+          nblocks--;
         }
-      while (nblocks >= 4);
+    }
+
+  /* Store hash. */
+  asm volatile ("pshufb %[be_mask], %%xmm1\n\t" /* be => le */
+                "movdqu %%xmm1, %[hash]\n\t"
+                : [hash] "=m" (*result)
+                : [be_mask] "m" (*be_mask)
+                : "memory" );
+
+#if defined(__x86_64__) && defined(__WIN64__)
+  /* Clear/restore used registers. */
+  asm volatile( "pxor %%xmm0, %%xmm0\n\t"
+                "pxor %%xmm1, %%xmm1\n\t"
+                "pxor %%xmm2, %%xmm2\n\t"
+                "pxor %%xmm3, %%xmm3\n\t"
+                "pxor %%xmm4, %%xmm4\n\t"
+                "pxor %%xmm5, %%xmm5\n\t"
+                "movdqu 0*16(%0), %%xmm6\n\t"
+                "movdqu 1*16(%0), %%xmm7\n\t"
+                "movdqu 2*16(%0), %%xmm8\n\t"
+                "movdqu 3*16(%0), %%xmm9\n\t"
+                "movdqu 4*16(%0), %%xmm10\n\t"
+                "movdqu 5*16(%0), %%xmm11\n\t"
+                "movdqu 6*16(%0), %%xmm12\n\t"
+                "movdqu 7*16(%0), %%xmm13\n\t"
+                "movdqu 8*16(%0), %%xmm14\n\t"
+                "movdqu 9*16(%0), %%xmm15\n\t"
+                :
+                : "r" (win64tmp)
+                : "memory" );
+#else
+  /* Clear used registers. */
+  asm volatile( "pxor %%xmm0, %%xmm0\n\t"
+                "pxor %%xmm1, %%xmm1\n\t"
+                "pxor %%xmm2, %%xmm2\n\t"
+                "pxor %%xmm3, %%xmm3\n\t"
+                "pxor %%xmm4, %%xmm4\n\t"
+                "pxor %%xmm5, %%xmm5\n\t"
+                "pxor %%xmm6, %%xmm6\n\t"
+                "pxor %%xmm7, %%xmm7\n\t"
+                ::: "memory" );
+#endif
+
+  return 0;
+}
 
+unsigned int ASM_FUNC_ATTR
+_gcry_polyval_intel_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf,
+                            size_t nblocks)
+{
+  static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
+    { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+  const unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
+#if defined(__x86_64__) && defined(__WIN64__)
+  char win64tmp[10 * 16];
+#endif
+
+  if (nblocks == 0)
+    return 0;
+
+#if defined(__x86_64__) && defined(__WIN64__)
+  /* XMM6-XMM15 need to be restored after use. */
+  asm volatile ("movdqu %%xmm6,  0*16(%0)\n\t"
+                "movdqu %%xmm7,  1*16(%0)\n\t"
+                "movdqu %%xmm8,  2*16(%0)\n\t"
+                "movdqu %%xmm9,  3*16(%0)\n\t"
+                "movdqu %%xmm10, 4*16(%0)\n\t"
+                "movdqu %%xmm11, 5*16(%0)\n\t"
+                "movdqu %%xmm12, 6*16(%0)\n\t"
+                "movdqu %%xmm13, 7*16(%0)\n\t"
+                "movdqu %%xmm14, 8*16(%0)\n\t"
+                "movdqu %%xmm15, 9*16(%0)\n\t"
+                :
+                : "r" (win64tmp)
+                : "memory" );
+#endif
+
+  /* Preload hash. */
+  asm volatile ("pxor %%xmm7, %%xmm7\n\t"
+                "movdqu %[hash], %%xmm1\n\t"
+                "pshufb %[be_mask], %%xmm1\n\t" /* be => le */
+                :
+                : [hash] "m" (*result),
+                  [be_mask] "m" (*be_mask)
+                : "memory" );
+
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      /* Preload H1. */
+      asm volatile ("pxor %%xmm15, %%xmm15\n\t"
+                    "movdqa %[h_1], %%xmm0\n\t"
+                    :
+                    : [h_1] "m" (*c->u_mode.gcm.u_ghash_key.key)
+                    : "memory" );
+
+      while (nblocks >= 8)
+        {
+          gfmul_pclmul_aggr8_le (buf, c->u_mode.gcm.gcm_table);
+
+          buf += 8 * blocksize;
+          nblocks -= 8;
+        }
 #ifndef __WIN64__
       /* Clear used x86-64/XMM registers. */
       asm volatile( "pxor %%xmm8, %%xmm8\n\t"
@@ -410,31 +826,51 @@ _gcry_ghash_intel_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf,
                     "pxor %%xmm13, %%xmm13\n\t"
                     "pxor %%xmm14, %%xmm14\n\t"
                     "pxor %%xmm15, %%xmm15\n\t"
-                    ::: "cc" );
+                    ::: "memory" );
 #endif
     }
 #endif
 
-  while (nblocks--)
+  while (nblocks >= 4)
+    {
+      gfmul_pclmul_aggr4_le (buf, c->u_mode.gcm.u_ghash_key.key,
+                             c->u_mode.gcm.gcm_table);
+
+      buf += 4 * blocksize;
+      nblocks -= 4;
+    }
+
+  if (nblocks)
     {
-      asm volatile ("movdqu %[buf], %%xmm2\n\t"
-                    "pshufb %[be_mask], %%xmm2\n\t" /* be => le */
-                    "pxor %%xmm2, %%xmm1\n\t"
+      /* Preload H1. */
+      asm volatile ("movdqa %[h_1], %%xmm0\n\t"
                     :
-                    : [buf] "m" (*buf), [be_mask] "m" (*be_mask));
+                    : [h_1] "m" (*c->u_mode.gcm.u_ghash_key.key)
+                    : "memory" );
 
-      gfmul_pclmul ();
+      while (nblocks)
+        {
+          asm volatile ("movdqu %[buf], %%xmm2\n\t"
+                        "pxor %%xmm2, %%xmm1\n\t"
+                        :
+                        : [buf] "m" (*buf)
+                        : "memory" );
 
-      buf += blocksize;
+          gfmul_pclmul ();
+
+          buf += blocksize;
+          nblocks--;
+        }
     }
 
   /* Store hash. */
   asm volatile ("pshufb %[be_mask], %%xmm1\n\t" /* be => le */
                 "movdqu %%xmm1, %[hash]\n\t"
                 : [hash] "=m" (*result)
-                : [be_mask] "m" (*be_mask));
+                : [be_mask] "m" (*be_mask)
+                : "memory" );
 
-#ifdef __WIN64__
+#if defined(__x86_64__) && defined(__WIN64__)
   /* Clear/restore used registers. */
   asm volatile( "pxor %%xmm0, %%xmm0\n\t"
                 "pxor %%xmm1, %%xmm1\n\t"
@@ -465,10 +901,14 @@ _gcry_ghash_intel_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf,
                 "pxor %%xmm5, %%xmm5\n\t"
                 "pxor %%xmm6, %%xmm6\n\t"
                 "pxor %%xmm7, %%xmm7\n\t"
-                ::: "cc" );
+                ::: "memory" );
 #endif
 
   return 0;
 }
 
+#if __clang__
+#  pragma clang attribute pop
+#endif
+
 #endif /* GCM_USE_INTEL_PCLMUL */
diff --git a/cipher/cipher-gcm-ppc.c b/cipher/cipher-gcm-ppc.c
new file mode 100644 (file)
index 0000000..4f75e95
--- /dev/null
@@ -0,0 +1,551 @@
+/* cipher-gcm-ppc.c  -  Power 8 vpmsum accelerated Galois Counter Mode
+ *                      implementation
+ * Copyright (C) 2019 Shawn Landden <shawn@git.icu>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Based on GHASH implementation by Andy Polyakov from CRYPTOGAMS
+ * distribution (ppc/ghashp8-ppc.pl). Specifically, it uses his register
+ * allocation (which then defers to your compiler's register allocation),
+ * instead of re-implementing Gerald Estrin's Scheme of parallelized
+ * multiplication of polynomials, as I did not understand this algorithm at
+ * the time.
+ *
+ * Original copyright license follows:
+ *
+ *  Copyright (c) 2006, CRYPTOGAMS by <appro@openssl.org>
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *        * Redistributions of source code must retain copyright notices,
+ *          this list of conditions and the following disclaimer.
+ *
+ *        * Redistributions in binary form must reproduce the above
+ *          copyright notice, this list of conditions and the following
+ *          disclaimer in the documentation and/or other materials
+ *          provided with the distribution.
+ *
+ *        * Neither the name of the CRYPTOGAMS nor the names of its
+ *          copyright holder and contributors may be used to endorse or
+ *          promote products derived from this software without specific
+ *          prior written permission.
+ *
+ *  ALTERNATIVELY, provided that this notice is retained in full, this
+ *  product may be distributed under the terms of the GNU General Public
+ *  License (GPL), in which case the provisions of the GPL apply INSTEAD OF
+ *  those given above.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+#include "bufhelp.h"
+#include "./cipher-internal.h"
+
+#ifdef GCM_USE_PPC_VPMSUM
+
+#include <altivec.h>
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR        NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE ASM_FUNC_ATTR ALWAYS_INLINE
+
+#define ALIGNED_16 __attribute__ ((aligned (16)))
+
+typedef vector unsigned char vector16x_u8;
+typedef vector signed char vector16x_s8;
+typedef vector unsigned long long vector2x_u64;
+typedef vector unsigned long long block;
+
+static ASM_FUNC_ATTR_INLINE block
+asm_xor(block a, block b)
+{
+  block r;
+  __asm__ volatile ("xxlxor %x0, %x1, %x2"
+                   : "=wa" (r)
+                   : "wa" (a), "wa" (b));
+  return r;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_vpmsumd(block a, block b)
+{
+  block r;
+  __asm__ volatile ("vpmsumd %0, %1, %2"
+                   : "=v" (r)
+                   : "v" (a), "v" (b));
+  return r;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_swap_u64(block a)
+{
+  block r;
+  __asm__ volatile ("xxswapd %x0, %x1"
+                   : "=wa" (r)
+                   : "wa" (a));
+  return r;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_mergelo(block l, block r)
+{
+  block ret;
+  __asm__ volatile ("xxmrgld %x0, %x1, %x2\n\t"
+                   : "=wa" (ret)
+                   : "wa" (l), "wa" (r));
+  return ret;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_mergehi(block l, block r)
+{
+  block ret;
+  __asm__ volatile ("xxmrghd %x0, %x1, %x2\n\t"
+                   : "=wa" (ret)
+                   : "wa" (l), "wa" (r));
+  return ret;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_rot_block_left(block a)
+{
+  block r;
+  block zero = { 0, 0 };
+  __asm__ volatile ("xxmrgld %x0, %x1, %x2"
+                   : "=wa" (r)
+                   : "wa" (a), "wa" (zero));
+  return r;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_rot_block_right(block a)
+{
+  block r;
+  block zero = { 0, 0 };
+  __asm__ volatile ("xxsldwi %x0, %x2, %x1, 2"
+                   : "=wa" (r)
+                   : "wa" (a), "wa" (zero));
+  return r;
+}
+
+/* vsl is a slightly strange function in the way the shift is passed... */
+static ASM_FUNC_ATTR_INLINE block
+asm_ashl_128(block a, vector16x_u8 shift)
+{
+  block r;
+  __asm__ volatile ("vsl %0, %1, %2"
+                   : "=v" (r)
+                   : "v" (a), "v" (shift));
+  return r;
+}
+
+#define STORE_TABLE(gcm_table, slot, vec) \
+  vec_store_he (((block)vec), slot * 16, (unsigned char *)(gcm_table));
+
+static ASM_FUNC_ATTR_INLINE void
+vec_store_he(block vec, unsigned long offset, unsigned char *ptr)
+{
+  /* GCC vec_vsx_ld is generating two instructions on little-endian. Use
+   * lxvd2x directly instead. */
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("stxvd2x %x0, 0, %1\n\t"
+                   :
+                   : "wa" (vec), "r" ((uintptr_t)ptr)
+                   : "memory", "r0");
+  else
+#endif
+    __asm__ volatile ("stxvd2x %x0, %1, %2\n\t"
+                     :
+                     : "wa" (vec), "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+}
+
+#define VEC_LOAD_BE(in_ptr, bswap_const) \
+  vec_be_swap(vec_load_he (0, (const unsigned char *)(in_ptr)), bswap_const)
+
+static ASM_FUNC_ATTR_INLINE block
+vec_load_he(unsigned long offset, const unsigned char *ptr)
+{
+  block vec;
+  /* GCC vec_vsx_ld is generating two instructions on little-endian. Use
+   * lxvd2x directly instead. */
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("lxvd2x %x0, 0, %1\n\t"
+                   : "=wa" (vec)
+                   : "r" ((uintptr_t)ptr)
+                   : "memory", "r0");
+  else
+#endif
+    __asm__ volatile ("lxvd2x %x0, %1, %2\n\t"
+                     : "=wa" (vec)
+                     : "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+  return vec;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+vec_be_swap(block vec, vector16x_u8 be_bswap_const)
+{
+#ifndef WORDS_BIGENDIAN
+  __asm__ volatile ("vperm %0, %1, %1, %2\n\t"
+                   : "=v" (vec)
+                   : "v" (vec), "v" (be_bswap_const));
+#else
+  (void)be_bswap_const;
+#endif
+  return vec;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+vec_dup_byte_elem(block vec, int idx)
+{
+#ifndef WORDS_BIGENDIAN
+  return (block)vec_splat((vector16x_s8)vec, idx);
+#else
+  return (block)vec_splat((vector16x_s8)vec, (15 - idx) & 15);
+#endif
+}
+
+/* Power ghash based on papers:
+   "The Galois/Counter Mode of Operation (GCM)"; David A. McGrew, John Viega
+   "Intel® Carry-Less Multiplication Instruction and its Usage for Computing
+    the GCM Mode - Rev 2.01"; Shay Gueron, Michael E. Kounavis.
+
+   After saving the magic c2 constant and pre-formatted version of the key,
+   we pre-process the key for parallel hashing. This takes advantage of the
+   identity of addition over a galois field being identital to XOR, and thus
+   can be parellized (S 2.2, page 3). We multiply and add (galois field
+   versions) the key over multiple iterations and save the result. This can
+   later be galois added (XORed) with parallel processed input (Estrin's
+   Scheme).
+
+   The ghash "key" is a salt. */
+void ASM_FUNC_ATTR
+_gcry_ghash_setup_ppc_vpmsum (void *gcm_table_arg, void *gcm_key)
+{
+  static const vector16x_u8 bswap_const ALIGNED_16 =
+    { ~7, ~6, ~5, ~4, ~3, ~2, ~1, ~0, ~15, ~14, ~13, ~12, ~11, ~10, ~9, ~8 };
+  static const byte c2[16] ALIGNED_16 =
+    { 0xc2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+  static const vector16x_u8 one ALIGNED_16 =
+    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+  uint64_t *gcm_table = gcm_table_arg;
+  block T0, T1, T2;
+  block C2, H, H1, H1l, H1h, H2, H2l, H2h;
+  block H3l, H3, H3h, H4l, H4, H4h, T3, T4;
+  vector16x_s8 most_sig_of_H, t7, carry;
+
+  H = VEC_LOAD_BE(gcm_key, bswap_const);
+  C2 = VEC_LOAD_BE(c2, bswap_const);
+  most_sig_of_H = (vector16x_s8)vec_dup_byte_elem(H, 15);
+  t7 = vec_splat_s8(7);
+  carry = most_sig_of_H >> t7;
+  carry &= (vector16x_s8)C2; /* only interested in certain carries. */
+  H1 = asm_ashl_128(H, one);
+  H1 ^= (block)carry; /* complete the <<< 1 */
+
+  T1 = asm_swap_u64 (H1);
+  H1l = asm_rot_block_right (T1);
+  H1h = asm_rot_block_left (T1);
+  C2 = asm_rot_block_right (C2);
+
+  STORE_TABLE (gcm_table, 0, C2);
+  STORE_TABLE (gcm_table, 1, H1l);
+  STORE_TABLE (gcm_table, 2, T1);
+  STORE_TABLE (gcm_table, 3, H1h);
+
+  /* pre-process coefficients for Gerald Estrin's scheme for parallel
+   * multiplication of polynomials
+   */
+  H2l = asm_vpmsumd (H1l, H1); /* do not need to mask in
+                                  because 0 * anything -> 0 */
+  H2 = asm_vpmsumd (T1, H1);
+  H2h = asm_vpmsumd (H1h, H1);
+
+  /* reduce 1 */
+  T0 = asm_vpmsumd (H2l, C2);
+
+  H2l ^= asm_rot_block_left (H2);
+  H2h ^= asm_rot_block_right (H2);
+  H2l = asm_swap_u64 (H2l);
+  H2l ^= T0;
+  /* reduce 2 */
+  T0 = asm_swap_u64 (H2l);
+  H2l = asm_vpmsumd (H2l, C2);
+  H2 = H2l ^ H2h ^ T0;
+
+  T2 = asm_swap_u64 (H2);
+  H2l = asm_rot_block_right (T2);
+  H2h = asm_rot_block_left (T2);
+
+  STORE_TABLE (gcm_table, 4, H2l);
+  STORE_TABLE (gcm_table, 5, T2);
+  STORE_TABLE (gcm_table, 6, H2h);
+
+  H3l = asm_vpmsumd (H2l, H1);
+  H4l = asm_vpmsumd (H2l, H2);
+  H3 = asm_vpmsumd (T2, H1);
+  H4 = asm_vpmsumd (T2, H2);
+  H3h = asm_vpmsumd (H2h, H1);
+  H4h = asm_vpmsumd (H2h, H2);
+
+  T3 = asm_vpmsumd (H3l, C2);
+  T4 = asm_vpmsumd (H4l, C2);
+
+  H3l ^= asm_rot_block_left (H3);
+  H3h ^= asm_rot_block_right (H3);
+  H4l ^= asm_rot_block_left (H4);
+  H4h ^= asm_rot_block_right (H4);
+
+  H3 = asm_swap_u64 (H3l);
+  H4 = asm_swap_u64 (H4l);
+
+  H3 ^= T3;
+  H4 ^= T4;
+
+  /* We could have also b64 switched reduce and reduce2, however as we are
+     using the unrotated H and H2 above to vpmsum, this is marginally better. */
+  T3 = asm_swap_u64 (H3);
+  T4 = asm_swap_u64 (H4);
+
+  H3 = asm_vpmsumd (H3, C2);
+  H4 = asm_vpmsumd (H4, C2);
+
+  T3 ^= H3h;
+  T4 ^= H4h;
+  H3 ^= T3;
+  H4 ^= T4;
+  H3 = asm_swap_u64 (H3);
+  H4 = asm_swap_u64 (H4);
+
+  H3l = asm_rot_block_right (H3);
+  H3h = asm_rot_block_left (H3);
+  H4l = asm_rot_block_right (H4);
+  H4h = asm_rot_block_left (H4);
+
+  STORE_TABLE (gcm_table, 7, H3l);
+  STORE_TABLE (gcm_table, 8, H3);
+  STORE_TABLE (gcm_table, 9, H3h);
+  STORE_TABLE (gcm_table, 10, H4l);
+  STORE_TABLE (gcm_table, 11, H4);
+  STORE_TABLE (gcm_table, 12, H4h);
+}
+
+unsigned int ASM_FUNC_ATTR
+_gcry_ghash_ppc_vpmsum (byte *result, void *gcm_table,
+                       const byte *buf, const size_t nblocks)
+{
+  static const vector16x_u8 bswap_const ALIGNED_16 =
+    { ~7, ~6, ~5, ~4, ~3, ~2, ~1, ~0, ~15, ~14, ~13, ~12, ~11, ~10, ~9, ~8 };
+  block c2, H0l, H0m, H0h, H4l, H4m, H4h, H2m, H3l, H3m, H3h, Hl;
+  block Hm, Hh, in, in0, in1, in2, in3, Hm_right, Hl_rotate, cur;
+  size_t blocks_remaining = nblocks;
+  size_t not_multiple_of_four;
+  block t0;
+
+  cur = vec_be_swap (vec_load_he (0, result), bswap_const);
+
+  c2 = vec_load_he (0, gcm_table);
+  H0l = vec_load_he (16, gcm_table);
+  H0m = vec_load_he (32, gcm_table);
+  H0h = vec_load_he (48, gcm_table);
+
+  for (not_multiple_of_four = nblocks % 4; not_multiple_of_four;
+       not_multiple_of_four--)
+    {
+      in = vec_be_swap (vec_load_he (0, buf), bswap_const);
+      buf += 16;
+      blocks_remaining--;
+      cur ^= in;
+
+      Hl = asm_vpmsumd (cur, H0l);
+      Hm = asm_vpmsumd (cur, H0m);
+      Hh = asm_vpmsumd (cur, H0h);
+
+      t0 = asm_vpmsumd (Hl, c2);
+
+      Hl ^= asm_rot_block_left (Hm);
+
+      Hm_right = asm_rot_block_right (Hm);
+      Hh ^= Hm_right;
+      Hl_rotate = asm_swap_u64 (Hl);
+      Hl_rotate ^= t0;
+      Hl = asm_swap_u64 (Hl_rotate);
+      Hl_rotate = asm_vpmsumd (Hl_rotate, c2);
+      Hl ^= Hh;
+      Hl ^= Hl_rotate;
+
+      cur = Hl;
+  }
+
+  if (blocks_remaining > 0)
+    {
+      block Xl, Xm, Xh, Xl1, Xm1, Xh1, Xm2, Xl3, Xm3, Xh3, Xl_rotate;
+      block H21l, H21h, merge_l, merge_h;
+      block t1, t2;
+
+      H2m = vec_load_he (48 + 32, gcm_table);
+      H3l = vec_load_he (48 * 2 + 16, gcm_table);
+      H3m = vec_load_he (48 * 2 + 32, gcm_table);
+      H3h = vec_load_he (48 * 2 + 48, gcm_table);
+      H4l = vec_load_he (48 * 3 + 16, gcm_table);
+      H4m = vec_load_he (48 * 3 + 32, gcm_table);
+      H4h = vec_load_he (48 * 3 + 48, gcm_table);
+
+      in0 = vec_load_he (0, buf);
+      in1 = vec_load_he (16, buf);
+      in2 = vec_load_he (32, buf);
+      in3 = vec_load_he (48, buf);
+      in0 = vec_be_swap(in0, bswap_const);
+      in1 = vec_be_swap(in1, bswap_const);
+      in2 = vec_be_swap(in2, bswap_const);
+      in3 = vec_be_swap(in3, bswap_const);
+
+      Xh = asm_xor (in0, cur);
+
+      Xl1 = asm_vpmsumd (in1, H3l);
+      Xm1 = asm_vpmsumd (in1, H3m);
+      Xh1 = asm_vpmsumd (in1, H3h);
+
+      H21l = asm_mergehi (H2m, H0m);
+      H21h = asm_mergelo (H2m, H0m);
+      merge_l = asm_mergelo (in2, in3);
+      merge_h = asm_mergehi (in2, in3);
+
+      Xm2 = asm_vpmsumd (in2, H2m);
+      Xl3 = asm_vpmsumd (merge_l, H21l);
+      Xm3 = asm_vpmsumd (in3, H0m);
+      Xh3 = asm_vpmsumd (merge_h, H21h);
+
+      Xm2 = asm_xor (Xm2, Xm1);
+      Xl3 = asm_xor (Xl3, Xl1);
+      Xm3 = asm_xor (Xm3, Xm2);
+      Xh3 = asm_xor (Xh3, Xh1);
+
+      /* Gerald Estrin's scheme for parallel multiplication of polynomials */
+      while (1)
+        {
+         buf += 64;
+         blocks_remaining -= 4;
+         if (!blocks_remaining)
+           break;
+
+         in0 = vec_load_he (0, buf);
+         in1 = vec_load_he (16, buf);
+         in2 = vec_load_he (32, buf);
+         in3 = vec_load_he (48, buf);
+         in1 = vec_be_swap(in1, bswap_const);
+         in2 = vec_be_swap(in2, bswap_const);
+         in3 = vec_be_swap(in3, bswap_const);
+         in0 = vec_be_swap(in0, bswap_const);
+
+         Xl = asm_vpmsumd (Xh, H4l);
+         Xm = asm_vpmsumd (Xh, H4m);
+         Xh = asm_vpmsumd (Xh, H4h);
+         Xl1 = asm_vpmsumd (in1, H3l);
+         Xm1 = asm_vpmsumd (in1, H3m);
+         Xh1 = asm_vpmsumd (in1, H3h);
+
+         Xl = asm_xor (Xl, Xl3);
+         Xm = asm_xor (Xm, Xm3);
+         Xh = asm_xor (Xh, Xh3);
+         merge_l = asm_mergelo (in2, in3);
+         merge_h = asm_mergehi (in2, in3);
+
+         t0 = asm_vpmsumd (Xl, c2);
+         Xl3 = asm_vpmsumd (merge_l, H21l);
+         Xh3 = asm_vpmsumd (merge_h, H21h);
+
+         t1 = asm_rot_block_left (Xm);
+         t2 = asm_rot_block_right (Xm);
+         Xl = asm_xor(Xl, t1);
+         Xh = asm_xor(Xh, t2);
+
+         Xl = asm_swap_u64 (Xl);
+         Xl = asm_xor(Xl, t0);
+
+         Xl_rotate = asm_swap_u64 (Xl);
+         Xm2 = asm_vpmsumd (in2, H2m);
+         Xm3 = asm_vpmsumd (in3, H0m);
+         Xl = asm_vpmsumd (Xl, c2);
+
+         Xl3 = asm_xor (Xl3, Xl1);
+         Xh3 = asm_xor (Xh3, Xh1);
+         Xh = asm_xor (Xh, in0);
+         Xm2 = asm_xor (Xm2, Xm1);
+         Xh = asm_xor (Xh, Xl_rotate);
+         Xm3 = asm_xor (Xm3, Xm2);
+         Xh = asm_xor (Xh, Xl);
+       }
+
+      Xl = asm_vpmsumd (Xh, H4l);
+      Xm = asm_vpmsumd (Xh, H4m);
+      Xh = asm_vpmsumd (Xh, H4h);
+
+      Xl = asm_xor (Xl, Xl3);
+      Xm = asm_xor (Xm, Xm3);
+
+      t0 = asm_vpmsumd (Xl, c2);
+
+      Xh = asm_xor (Xh, Xh3);
+      t1 = asm_rot_block_left (Xm);
+      t2 = asm_rot_block_right (Xm);
+      Xl = asm_xor (Xl, t1);
+      Xh = asm_xor (Xh, t2);
+
+      Xl = asm_swap_u64 (Xl);
+      Xl = asm_xor (Xl, t0);
+
+      Xl_rotate = asm_swap_u64 (Xl);
+      Xl = asm_vpmsumd (Xl, c2);
+      Xh = asm_xor (Xh, Xl_rotate);
+      cur = asm_xor (Xh, Xl);
+    }
+
+  vec_store_he (vec_be_swap (cur, bswap_const), 0, result);
+
+  return 0;
+}
+
+#endif /* GCM_USE_PPC_VPMSUM */
diff --git a/cipher/cipher-gcm-siv.c b/cipher/cipher-gcm-siv.c
new file mode 100644 (file)
index 0000000..9ebc003
--- /dev/null
@@ -0,0 +1,664 @@
+/* cipher-gcm-siv.c  - GCM-SIV implementation (RFC 8452)
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+#include "bufhelp.h"
+#include "./cipher-internal.h"
+
+
+#define GCM_SIV_NONCE_LENGTH (96 / 8)
+
+
+static inline void
+mulx_ghash (byte *a)
+{
+  u64 t[2], mask;
+
+  t[0] = buf_get_be64(a + 0);
+  t[1] = buf_get_be64(a + 8);
+  mask = -(t[1] & 1) & 0xe1;
+  mask <<= 56;
+
+  buf_put_be64(a + 8, (t[1] >> 1) ^ (t[0] << 63));
+  buf_put_be64(a + 0, (t[0] >> 1) ^ mask);
+}
+
+
+static inline void
+gcm_siv_bytecounter_add (u32 ctr[2], size_t add)
+{
+  if (sizeof(add) > sizeof(u32))
+    {
+      u32 high_add = ((add >> 31) >> 1) & 0xffffffff;
+      ctr[1] += high_add;
+    }
+
+  ctr[0] += add;
+  if (ctr[0] >= add)
+    return;
+  ++ctr[1];
+}
+
+
+static inline int
+gcm_siv_check_len (u32 ctr[2])
+{
+  /* len(plaintext/aadlen) <= 2^39-256 bits == 2^36-32 bytes == 2^32-2 blocks */
+  if (ctr[1] > 0xfU)
+    return 0;
+  if (ctr[1] < 0xfU)
+    return 1;
+
+  if (ctr[0] <= 0xffffffe0U)
+    return 1;
+
+  return 0;
+}
+
+
+static void
+polyval_set_key (gcry_cipher_hd_t c, const byte *auth_key)
+{
+  cipher_block_bswap (c->u_mode.gcm.u_ghash_key.key, auth_key,
+                     GCRY_SIV_BLOCK_LEN);
+  mulx_ghash (c->u_mode.gcm.u_ghash_key.key);
+  _gcry_cipher_gcm_setupM (c);
+}
+
+
+static void
+do_polyval_buf(gcry_cipher_hd_t c, byte *hash, const byte *buf,
+              size_t buflen, int do_padding)
+{
+  unsigned int blocksize = GCRY_SIV_BLOCK_LEN;
+  unsigned int unused = c->u_mode.gcm.mac_unused;
+  ghash_fn_t ghash_fn = c->u_mode.gcm.ghash_fn;
+  ghash_fn_t polyval_fn = c->u_mode.gcm.polyval_fn;
+  byte tmp_blocks[16][GCRY_SIV_BLOCK_LEN];
+  size_t nblocks, n;
+  unsigned int burn = 0, nburn;
+  unsigned int num_blks_used = 0;
+
+  if (buflen == 0 && (unused == 0 || !do_padding))
+    return;
+
+  do
+    {
+      if (buflen > 0 && (buflen + unused < blocksize || unused > 0))
+        {
+          n = blocksize - unused;
+          n = n < buflen ? n : buflen;
+
+          buf_cpy (&c->u_mode.gcm.macbuf[unused], buf, n);
+
+          unused += n;
+          buf += n;
+          buflen -= n;
+        }
+      if (!buflen)
+        {
+          if (!do_padding && unused < blocksize)
+           {
+             break;
+           }
+
+         n = blocksize - unused;
+         if (n > 0)
+           {
+             memset (&c->u_mode.gcm.macbuf[unused], 0, n);
+             unused = blocksize;
+           }
+        }
+
+      if (unused > 0)
+        {
+          gcry_assert (unused == blocksize);
+
+          /* Process one block from macbuf.  */
+          if (polyval_fn)
+            {
+              nburn = polyval_fn (c, hash, c->u_mode.gcm.macbuf, 1);
+            }
+          else
+            {
+              cipher_block_bswap (c->u_mode.gcm.macbuf, c->u_mode.gcm.macbuf,
+                                  blocksize);
+              nburn = ghash_fn (c, hash, c->u_mode.gcm.macbuf, 1);
+            }
+
+          burn = nburn > burn ? nburn : burn;
+          unused = 0;
+        }
+
+      nblocks = buflen / blocksize;
+
+      while (nblocks)
+        {
+          if (polyval_fn)
+            {
+              n = nblocks;
+              nburn = polyval_fn (c, hash, buf, n);
+            }
+          else
+            {
+              for (n = 0; n < (nblocks > 16 ? 16 : nblocks); n++)
+                cipher_block_bswap (tmp_blocks[n], buf + n * blocksize,
+                                    blocksize);
+
+              num_blks_used = n > num_blks_used ? n : num_blks_used;
+
+              nburn = ghash_fn (c, hash, tmp_blocks[0], n);
+            }
+
+          burn = nburn > burn ? nburn : burn;
+          buf += n * blocksize;
+          buflen -= n * blocksize;
+          nblocks -= n;
+        }
+    }
+  while (buflen > 0);
+
+  c->u_mode.gcm.mac_unused = unused;
+
+  if (num_blks_used)
+    wipememory (tmp_blocks, num_blks_used * blocksize);
+  if (burn)
+    _gcry_burn_stack (burn);
+}
+
+
+static void
+do_ctr_le32 (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
+            size_t inbuflen)
+{
+  gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
+  unsigned char tmp[GCRY_SIV_BLOCK_LEN];
+  unsigned int burn = 0, nburn;
+  size_t nblocks;
+
+  if (inbuflen == 0)
+    return;
+
+  /* Use a bulk method if available.  */
+  nblocks = inbuflen / GCRY_SIV_BLOCK_LEN;
+  if (nblocks && c->bulk.ctr32le_enc)
+    {
+      c->bulk.ctr32le_enc (c->context.c, c->u_ctr.ctr, outbuf, inbuf, nblocks);
+      inbuf  += nblocks * GCRY_SIV_BLOCK_LEN;
+      outbuf += nblocks * GCRY_SIV_BLOCK_LEN;
+      inbuflen -= nblocks * GCRY_SIV_BLOCK_LEN;
+    }
+
+  do
+    {
+      nburn = enc_fn (c->context.c, tmp, c->u_ctr.ctr);
+      burn = nburn > burn ? nburn : burn;
+
+      buf_put_le32(c->u_ctr.ctr, buf_get_le32(c->u_ctr.ctr) + 1);
+
+      if (inbuflen < GCRY_SIV_BLOCK_LEN)
+       break;
+      cipher_block_xor(outbuf, inbuf, tmp, GCRY_SIV_BLOCK_LEN);
+
+      inbuflen -= GCRY_SIV_BLOCK_LEN;
+      outbuf += GCRY_SIV_BLOCK_LEN;
+      inbuf += GCRY_SIV_BLOCK_LEN;
+    }
+  while (inbuflen);
+
+  if (inbuflen)
+    {
+      buf_xor(outbuf, inbuf, tmp, inbuflen);
+
+      outbuf += inbuflen;
+      inbuf += inbuflen;
+      inbuflen -= inbuflen;
+    }
+
+  wipememory (tmp, sizeof(tmp));
+
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4 * sizeof(void *));
+}
+
+
+static int
+gcm_siv_selftest (gcry_cipher_hd_t c)
+{
+  static const byte in1[GCRY_SIV_BLOCK_LEN] =
+      "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+  static const byte out1[GCRY_SIV_BLOCK_LEN] =
+      "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+  static const byte in2[GCRY_SIV_BLOCK_LEN] =
+      "\x9c\x98\xc0\x4d\xf9\x38\x7d\xed\x82\x81\x75\xa9\x2b\xa6\x52\xd8";
+  static const byte out2[GCRY_SIV_BLOCK_LEN] =
+      "\x4e\x4c\x60\x26\xfc\x9c\x3e\xf6\xc1\x40\xba\xd4\x95\xd3\x29\x6c";
+  static const byte polyval_key[GCRY_SIV_BLOCK_LEN] =
+      "\x25\x62\x93\x47\x58\x92\x42\x76\x1d\x31\xf8\x26\xba\x4b\x75\x7b";
+  static const byte ghash_key[GCRY_SIV_BLOCK_LEN] =
+      "\xdc\xba\xa5\xdd\x13\x7c\x18\x8e\xbb\x21\x49\x2c\x23\xc9\xb1\x12";
+  static const byte polyval_data[GCRY_SIV_BLOCK_LEN * 2] =
+      "\x4f\x4f\x95\x66\x8c\x83\xdf\xb6\x40\x17\x62\xbb\x2d\x01\xa2\x62"
+      "\xd1\xa2\x4d\xdd\x27\x21\xd0\x06\xbb\xe4\x5f\x20\xd3\xc9\xf3\x62";
+  static const byte polyval_tag[GCRY_SIV_BLOCK_LEN] =
+      "\xf7\xa3\xb4\x7b\x84\x61\x19\xfa\xe5\xb7\x86\x6c\xf5\xe5\xb7\x7e";
+  byte tmp[GCRY_SIV_BLOCK_LEN];
+
+  /* Test mulx_ghash */
+  memcpy (tmp, in1, GCRY_SIV_BLOCK_LEN);
+  mulx_ghash (tmp);
+  if (memcmp (tmp, out1, GCRY_SIV_BLOCK_LEN) != 0)
+    return -1;
+
+  memcpy (tmp, in2, GCRY_SIV_BLOCK_LEN);
+  mulx_ghash (tmp);
+  if (memcmp (tmp, out2, GCRY_SIV_BLOCK_LEN) != 0)
+    return -1;
+
+  /* Test GHASH key generation */
+  memcpy (tmp, polyval_key, GCRY_SIV_BLOCK_LEN);
+  cipher_block_bswap (tmp, tmp, GCRY_SIV_BLOCK_LEN);
+  mulx_ghash (tmp);
+  if (memcmp (tmp, ghash_key, GCRY_SIV_BLOCK_LEN) != 0)
+    return -1;
+
+  /* Test POLYVAL */
+  memset (&c->u_mode.gcm, 0, sizeof(c->u_mode.gcm));
+  polyval_set_key (c, polyval_key);
+  memset (&tmp, 0, sizeof(tmp));
+  do_polyval_buf (c, tmp, polyval_data, GCRY_SIV_BLOCK_LEN * 2, 1);
+  cipher_block_bswap (tmp, tmp, GCRY_SIV_BLOCK_LEN);
+  if (memcmp (tmp, polyval_tag, GCRY_SIV_BLOCK_LEN) != 0)
+    return -1;
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gcm_siv_setkey (gcry_cipher_hd_t c, unsigned int keylen)
+{
+  static int done;
+
+  if (keylen != 16 && keylen != 32)
+    return GPG_ERR_INV_KEYLEN;
+
+  if (!done)
+    {
+      if (gcm_siv_selftest (c))
+       return GPG_ERR_SELFTEST_FAILED;
+
+      done = 1;
+    }
+
+  c->marks.iv = 0;
+  c->marks.tag = 0;
+  memset (&c->u_mode.gcm, 0, sizeof(c->u_mode.gcm));
+  c->u_mode.gcm.siv_keylen = keylen;
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gcm_siv_set_nonce (gcry_cipher_hd_t c, const byte *iv,
+                               size_t ivlen)
+{
+  byte auth_key[GCRY_SIV_BLOCK_LEN];
+  byte tmp_in[GCRY_SIV_BLOCK_LEN];
+  byte tmp[GCRY_SIV_BLOCK_LEN];
+  byte enc_key[32];
+  gcry_err_code_t err;
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (ivlen != GCM_SIV_NONCE_LENGTH)
+    return GPG_ERR_INV_ARG;
+  if (c->u_mode.gcm.siv_keylen == 0)
+    return GPG_ERR_INV_STATE;
+  if (c->marks.iv)
+    {
+      /* If nonce is already set, use cipher_reset or setkey first to reset
+       * cipher state. */
+      return GPG_ERR_INV_STATE;
+    }
+
+  memset (c->u_mode.gcm.aadlen, 0, sizeof(c->u_mode.gcm.aadlen));
+  memset (c->u_mode.gcm.datalen, 0, sizeof(c->u_mode.gcm.datalen));
+  memset (c->u_mode.gcm.u_tag.tag, 0, sizeof(c->u_mode.gcm.u_tag.tag));
+  c->u_mode.gcm.datalen_over_limits = 0;
+  c->u_mode.gcm.ghash_data_finalized = 0;
+  c->u_mode.gcm.ghash_aad_finalized = 0;
+
+  memset (c->u_iv.iv, 0, GCRY_SIV_BLOCK_LEN);
+  memcpy (c->u_iv.iv, iv, ivlen);
+  memcpy (tmp_in + 4, iv, ivlen);
+
+  /* Derive message authentication key */
+  buf_put_le32(tmp_in, 0);
+  c->spec->encrypt (&c->context.c, tmp, tmp_in);
+  memcpy (auth_key + 0, tmp, 8);
+
+  buf_put_le32(tmp_in, 1);
+  c->spec->encrypt (&c->context.c, tmp, tmp_in);
+  memcpy (auth_key + 8, tmp, 8);
+
+  polyval_set_key (c, auth_key);
+  wipememory (auth_key, sizeof(auth_key));
+
+  /* Derive message encryption key */
+  buf_put_le32(tmp_in, 2);
+  c->spec->encrypt (&c->context.c, tmp, tmp_in);
+  memcpy (enc_key + 0, tmp, 8);
+
+  buf_put_le32(tmp_in, 3);
+  c->spec->encrypt (&c->context.c, tmp, tmp_in);
+  memcpy (enc_key + 8, tmp, 8);
+
+  if (c->u_mode.gcm.siv_keylen >= 24)
+    {
+      buf_put_le32(tmp_in, 4);
+      c->spec->encrypt (&c->context.c, tmp, tmp_in);
+      memcpy (enc_key + 16, tmp, 8);
+    }
+
+  if (c->u_mode.gcm.siv_keylen >= 32)
+    {
+      buf_put_le32(tmp_in, 5);
+      c->spec->encrypt (&c->context.c, tmp, tmp_in);
+      memcpy (enc_key + 24, tmp, 8);
+    }
+
+  wipememory (tmp, sizeof(tmp));
+  wipememory (tmp_in, sizeof(tmp_in));
+
+  err = c->spec->setkey (&c->context.c, enc_key, c->u_mode.gcm.siv_keylen,
+                        &c->bulk);
+  wipememory (enc_key, sizeof(enc_key));
+  if (err)
+    return err;
+
+  c->marks.iv = 1;
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gcm_siv_authenticate (gcry_cipher_hd_t c,
+                                  const byte *aadbuf, size_t aadbuflen)
+{
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (c->u_mode.gcm.datalen_over_limits)
+    return GPG_ERR_INV_LENGTH;
+  if (c->marks.tag
+      || !c->marks.iv
+      || c->u_mode.gcm.ghash_aad_finalized
+      || c->u_mode.gcm.ghash_data_finalized
+      || !c->u_mode.gcm.ghash_fn)
+    return GPG_ERR_INV_STATE;
+
+  gcm_siv_bytecounter_add (c->u_mode.gcm.aadlen, aadbuflen);
+  if (!gcm_siv_check_len (c->u_mode.gcm.aadlen))
+    {
+      c->u_mode.gcm.datalen_over_limits = 1;
+      return GPG_ERR_INV_LENGTH;
+    }
+
+  do_polyval_buf (c, c->u_mode.gcm.u_tag.tag, aadbuf, aadbuflen, 0);
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gcm_siv_encrypt (gcry_cipher_hd_t c,
+                             byte *outbuf, size_t outbuflen,
+                             const byte *inbuf, size_t inbuflen)
+{
+  u32 bitlengths[2][2];
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+  if (c->u_mode.gcm.datalen_over_limits)
+    return GPG_ERR_INV_LENGTH;
+  if (c->marks.tag
+      || !c->marks.iv
+      || c->u_mode.gcm.ghash_data_finalized
+      || !c->u_mode.gcm.ghash_fn)
+    return GPG_ERR_INV_STATE;
+
+  if (!c->u_mode.gcm.ghash_aad_finalized)
+    {
+      /* Start of encryption marks end of AAD stream. */
+      do_polyval_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
+      c->u_mode.gcm.ghash_aad_finalized = 1;
+    }
+
+  gcm_siv_bytecounter_add (c->u_mode.gcm.datalen, inbuflen);
+  if (!gcm_siv_check_len (c->u_mode.gcm.datalen))
+    {
+      c->u_mode.gcm.datalen_over_limits = 1;
+      return GPG_ERR_INV_LENGTH;
+    }
+
+  /* Plaintext and padding to POLYVAL. */
+  do_polyval_buf (c, c->u_mode.gcm.u_tag.tag, inbuf, inbuflen, 1);
+  c->u_mode.gcm.ghash_data_finalized = 1;
+
+  /* aad length */
+  bitlengths[0][0] = le_bswap32(c->u_mode.gcm.aadlen[0] << 3);
+  bitlengths[0][1] = le_bswap32((c->u_mode.gcm.aadlen[0] >> 29) |
+                                (c->u_mode.gcm.aadlen[1] << 3));
+  /* data length */
+  bitlengths[1][0] = le_bswap32(c->u_mode.gcm.datalen[0] << 3);
+  bitlengths[1][1] = le_bswap32((c->u_mode.gcm.datalen[0] >> 29) |
+                                (c->u_mode.gcm.datalen[1] << 3));
+
+  /* Length block to POLYVAL. */
+  do_polyval_buf(c, c->u_mode.gcm.u_tag.tag, (byte *)bitlengths,
+                GCRY_SIV_BLOCK_LEN, 1);
+  wipememory (bitlengths, sizeof(bitlengths));
+
+  /* Prepare tag and counter. */
+  cipher_block_bswap (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.u_tag.tag,
+                     GCRY_SIV_BLOCK_LEN);
+  cipher_block_xor (c->u_mode.gcm.tagiv, c->u_iv.iv, c->u_mode.gcm.u_tag.tag,
+                   GCRY_SIV_BLOCK_LEN);
+  c->u_mode.gcm.tagiv[GCRY_SIV_BLOCK_LEN - 1] &= 0x7f;
+  c->spec->encrypt (&c->context.c, c->u_mode.gcm.tagiv, c->u_mode.gcm.tagiv);
+  c->marks.tag = 1;
+  memcpy (c->u_ctr.ctr, c->u_mode.gcm.tagiv, GCRY_SIV_BLOCK_LEN);
+  c->u_ctr.ctr[GCRY_SIV_BLOCK_LEN - 1] |= 0x80;
+
+  /* Encrypt data */
+  do_ctr_le32 (c, outbuf, inbuf, inbuflen);
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gcm_siv_set_decryption_tag (gcry_cipher_hd_t c,
+                                        const byte *tag, size_t taglen)
+{
+  if (taglen != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_INV_ARG;
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (c->marks.tag)
+    return GPG_ERR_INV_STATE;
+
+  memcpy (c->u_mode.gcm.tagiv, tag, GCRY_SIV_BLOCK_LEN);
+  c->marks.tag = 1;
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gcm_siv_decrypt (gcry_cipher_hd_t c,
+                             byte *outbuf, size_t outbuflen,
+                             const byte *inbuf, size_t inbuflen)
+{
+  byte expected_tag[GCRY_SIV_BLOCK_LEN];
+  u32 bitlengths[2][2];
+  gcry_err_code_t rc = 0;
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+  if (c->u_mode.gcm.datalen_over_limits)
+    return GPG_ERR_INV_LENGTH;
+  if (!c->marks.tag
+      || !c->marks.iv
+      || c->u_mode.gcm.ghash_data_finalized
+      || !c->u_mode.gcm.ghash_fn)
+    return GPG_ERR_INV_STATE;
+
+  if (!c->u_mode.gcm.ghash_aad_finalized)
+    {
+      /* Start of encryption marks end of AAD stream. */
+      do_polyval_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
+      c->u_mode.gcm.ghash_aad_finalized = 1;
+    }
+
+  gcm_siv_bytecounter_add (c->u_mode.gcm.datalen, inbuflen);
+  if (!gcm_siv_check_len (c->u_mode.gcm.datalen))
+    {
+      c->u_mode.gcm.datalen_over_limits = 1;
+      return GPG_ERR_INV_LENGTH;
+    }
+
+  /* Prepare counter. */
+  memcpy (c->u_ctr.ctr, c->u_mode.gcm.tagiv, GCRY_SIV_BLOCK_LEN);
+  c->u_ctr.ctr[GCRY_SIV_BLOCK_LEN - 1] |= 0x80;
+
+  /* Decrypt data. */
+  do_ctr_le32 (c, outbuf, inbuf, inbuflen);
+
+  /* Plaintext and padding to POLYVAL. */
+  do_polyval_buf (c, c->u_mode.gcm.u_tag.tag, outbuf, inbuflen, 1);
+  c->u_mode.gcm.ghash_data_finalized = 1;
+
+  /* aad length */
+  bitlengths[0][0] = le_bswap32(c->u_mode.gcm.aadlen[0] << 3);
+  bitlengths[0][1] = le_bswap32((c->u_mode.gcm.aadlen[0] >> 29) |
+                                (c->u_mode.gcm.aadlen[1] << 3));
+  /* data length */
+  bitlengths[1][0] = le_bswap32(c->u_mode.gcm.datalen[0] << 3);
+  bitlengths[1][1] = le_bswap32((c->u_mode.gcm.datalen[0] >> 29) |
+                                (c->u_mode.gcm.datalen[1] << 3));
+
+  /* Length block to POLYVAL. */
+  do_polyval_buf(c, c->u_mode.gcm.u_tag.tag, (byte *)bitlengths,
+                GCRY_SIV_BLOCK_LEN, 1);
+  wipememory (bitlengths, sizeof(bitlengths));
+
+  /* Prepare tag. */
+  cipher_block_bswap (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.u_tag.tag,
+                     GCRY_SIV_BLOCK_LEN);
+  cipher_block_xor (expected_tag, c->u_iv.iv, c->u_mode.gcm.u_tag.tag,
+                   GCRY_SIV_BLOCK_LEN);
+  expected_tag[GCRY_SIV_BLOCK_LEN - 1] &= 0x7f;
+  c->spec->encrypt (&c->context.c, expected_tag, expected_tag);
+
+  if (!buf_eq_const(c->u_mode.gcm.tagiv, expected_tag, GCRY_SIV_BLOCK_LEN))
+    {
+      wipememory (outbuf, inbuflen);
+      rc = GPG_ERR_CHECKSUM;
+    }
+
+  wipememory (expected_tag, sizeof(expected_tag));
+  return rc;
+}
+
+
+static gcry_err_code_t
+_gcry_cipher_gcm_siv_tag (gcry_cipher_hd_t c,
+                         byte * outbuf, size_t outbuflen, int check)
+{
+  gcry_err_code_t err;
+
+  if (!c->marks.tag)
+    {
+      if (!c->u_mode.gcm.ghash_fn)
+        return GPG_ERR_INV_STATE;
+
+      if (!c->marks.tag)
+        {
+          /* Finalize GCM-SIV with zero-length plaintext. */
+          err = _gcry_cipher_gcm_siv_encrypt (c, NULL, 0, NULL, 0);
+          if (err != 0)
+            return err;
+        }
+    }
+
+  if (c->u_mode.gcm.datalen_over_limits)
+    return GPG_ERR_INV_LENGTH;
+  if (!c->u_mode.gcm.ghash_data_finalized)
+    return GPG_ERR_INV_STATE;
+  if (!c->marks.tag)
+    return GPG_ERR_INV_STATE;
+
+  if (!check)
+    {
+      if (outbuflen > GCRY_SIV_BLOCK_LEN)
+        outbuflen = GCRY_SIV_BLOCK_LEN;
+
+      /* NB: We already checked that OUTBUF is large enough to hold
+       * the result or has valid truncated length.  */
+      memcpy (outbuf, c->u_mode.gcm.tagiv, outbuflen);
+    }
+  else
+    {
+      /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
+       * and thus we need to compare its length first.  */
+      if (outbuflen != GCRY_SIV_BLOCK_LEN
+          || !buf_eq_const (outbuf, c->u_mode.gcm.tagiv, outbuflen))
+        return GPG_ERR_CHECKSUM;
+    }
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gcm_siv_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
+                             size_t taglen)
+{
+  return _gcry_cipher_gcm_siv_tag (c, outtag, taglen, 0);
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gcm_siv_check_tag (gcry_cipher_hd_t c,
+                                  const unsigned char *intag,
+                                  size_t taglen)
+{
+  return _gcry_cipher_gcm_siv_tag (c, (unsigned char *)intag, taglen, 1);
+}
index 6169d14..fc79986 100644 (file)
@@ -1,6 +1,6 @@
 /* cipher-gcm.c  - Generic Galois Counter Mode implementation
  * Copyright (C) 2013 Dmitry Eremin-Solenikov
- * Copyright (C) 2013, 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2013, 2018-2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
 #include "./cipher-internal.h"
 
 
+/* Helper macro to force alignment to 16 or 64 bytes.  */
+#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
+# define ATTR_ALIGNED_64  __attribute__ ((aligned (64)))
+#else
+# define ATTR_ALIGNED_64
+#endif
+
+
 #ifdef GCM_USE_INTEL_PCLMUL
 extern void _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c);
 
 extern unsigned int _gcry_ghash_intel_pclmul (gcry_cipher_hd_t c, byte *result,
                                               const byte *buf, size_t nblocks);
+
+extern unsigned int _gcry_polyval_intel_pclmul (gcry_cipher_hd_t c,
+                                                byte *result,
+                                                const byte *buf,
+                                                size_t nblocks);
 #endif
 
 #ifdef GCM_USE_ARM_PMULL
@@ -44,6 +57,11 @@ extern unsigned int _gcry_ghash_armv8_ce_pmull (void *gcm_key, byte *result,
                                                 const byte *buf, size_t nblocks,
                                                 void *gcm_table);
 
+extern unsigned int _gcry_polyval_armv8_ce_pmull (void *gcm_key, byte *result,
+                                                  const byte *buf,
+                                                  size_t nblocks,
+                                                  void *gcm_table);
+
 static void
 ghash_setup_armv8_ce_pmull (gcry_cipher_hd_t c)
 {
@@ -59,44 +77,168 @@ ghash_armv8_ce_pmull (gcry_cipher_hd_t c, byte *result, const byte *buf,
                                     nblocks, c->u_mode.gcm.gcm_table);
 }
 
-#endif
+static unsigned int
+polyval_armv8_ce_pmull (gcry_cipher_hd_t c, byte *result, const byte *buf,
+                        size_t nblocks)
+{
+  return _gcry_polyval_armv8_ce_pmull(c->u_mode.gcm.u_ghash_key.key, result,
+                                      buf, nblocks, c->u_mode.gcm.gcm_table);
+}
+#endif /* GCM_USE_ARM_PMULL */
+
+#ifdef GCM_USE_ARM_NEON
+extern void _gcry_ghash_setup_armv7_neon (void *gcm_key);
+
+extern unsigned int _gcry_ghash_armv7_neon (void *gcm_key, byte *result,
+                                           const byte *buf, size_t nblocks);
+
+static void
+ghash_setup_armv7_neon (gcry_cipher_hd_t c)
+{
+  _gcry_ghash_setup_armv7_neon(c->u_mode.gcm.u_ghash_key.key);
+}
 
+static unsigned int
+ghash_armv7_neon (gcry_cipher_hd_t c, byte *result, const byte *buf,
+                 size_t nblocks)
+{
+  return _gcry_ghash_armv7_neon(c->u_mode.gcm.u_ghash_key.key, result, buf,
+                               nblocks);
+}
+#endif /* GCM_USE_ARM_NEON */
+
+#ifdef GCM_USE_S390X_CRYPTO
+#include "asm-inline-s390x.h"
+
+static unsigned int
+ghash_s390x_kimd (gcry_cipher_hd_t c, byte *result, const byte *buf,
+                 size_t nblocks)
+{
+  u128_t params[2];
+
+  memcpy (&params[0], result, 16);
+  memcpy (&params[1], c->u_mode.gcm.u_ghash_key.key, 16);
+
+  kimd_execute (KMID_FUNCTION_GHASH, &params, buf, nblocks * 16);
+
+  memcpy (result, &params[0], 16);
+  wipememory (params, sizeof(params));
+  return 0;
+}
+#endif /* GCM_USE_S390X_CRYPTO*/
+
+#ifdef GCM_USE_PPC_VPMSUM
+extern void _gcry_ghash_setup_ppc_vpmsum (void *gcm_table, void *gcm_key);
+
+/* result is 128-bits */
+extern unsigned int _gcry_ghash_ppc_vpmsum (byte *result, void *gcm_table,
+                                           const byte *buf, size_t nblocks);
+
+static void
+ghash_setup_ppc_vpmsum (gcry_cipher_hd_t c)
+{
+  _gcry_ghash_setup_ppc_vpmsum(c->u_mode.gcm.gcm_table,
+                              c->u_mode.gcm.u_ghash_key.key);
+}
+
+static unsigned int
+ghash_ppc_vpmsum (gcry_cipher_hd_t c, byte *result, const byte *buf,
+                 size_t nblocks)
+{
+  return _gcry_ghash_ppc_vpmsum(result, c->u_mode.gcm.gcm_table, buf,
+                               nblocks);
+}
+#endif /* GCM_USE_PPC_VPMSUM */
 
 #ifdef GCM_USE_TABLES
-static const u16 gcmR[256] = {
-  0x0000, 0x01c2, 0x0384, 0x0246, 0x0708, 0x06ca, 0x048c, 0x054e,
-  0x0e10, 0x0fd2, 0x0d94, 0x0c56, 0x0918, 0x08da, 0x0a9c, 0x0b5e,
-  0x1c20, 0x1de2, 0x1fa4, 0x1e66, 0x1b28, 0x1aea, 0x18ac, 0x196e,
-  0x1230, 0x13f2, 0x11b4, 0x1076, 0x1538, 0x14fa, 0x16bc, 0x177e,
-  0x3840, 0x3982, 0x3bc4, 0x3a06, 0x3f48, 0x3e8a, 0x3ccc, 0x3d0e,
-  0x3650, 0x3792, 0x35d4, 0x3416, 0x3158, 0x309a, 0x32dc, 0x331e,
-  0x2460, 0x25a2, 0x27e4, 0x2626, 0x2368, 0x22aa, 0x20ec, 0x212e,
-  0x2a70, 0x2bb2, 0x29f4, 0x2836, 0x2d78, 0x2cba, 0x2efc, 0x2f3e,
-  0x7080, 0x7142, 0x7304, 0x72c6, 0x7788, 0x764a, 0x740c, 0x75ce,
-  0x7e90, 0x7f52, 0x7d14, 0x7cd6, 0x7998, 0x785a, 0x7a1c, 0x7bde,
-  0x6ca0, 0x6d62, 0x6f24, 0x6ee6, 0x6ba8, 0x6a6a, 0x682c, 0x69ee,
-  0x62b0, 0x6372, 0x6134, 0x60f6, 0x65b8, 0x647a, 0x663c, 0x67fe,
-  0x48c0, 0x4902, 0x4b44, 0x4a86, 0x4fc8, 0x4e0a, 0x4c4c, 0x4d8e,
-  0x46d0, 0x4712, 0x4554, 0x4496, 0x41d8, 0x401a, 0x425c, 0x439e,
-  0x54e0, 0x5522, 0x5764, 0x56a6, 0x53e8, 0x522a, 0x506c, 0x51ae,
-  0x5af0, 0x5b32, 0x5974, 0x58b6, 0x5df8, 0x5c3a, 0x5e7c, 0x5fbe,
-  0xe100, 0xe0c2, 0xe284, 0xe346, 0xe608, 0xe7ca, 0xe58c, 0xe44e,
-  0xef10, 0xeed2, 0xec94, 0xed56, 0xe818, 0xe9da, 0xeb9c, 0xea5e,
-  0xfd20, 0xfce2, 0xfea4, 0xff66, 0xfa28, 0xfbea, 0xf9ac, 0xf86e,
-  0xf330, 0xf2f2, 0xf0b4, 0xf176, 0xf438, 0xf5fa, 0xf7bc, 0xf67e,
-  0xd940, 0xd882, 0xdac4, 0xdb06, 0xde48, 0xdf8a, 0xddcc, 0xdc0e,
-  0xd750, 0xd692, 0xd4d4, 0xd516, 0xd058, 0xd19a, 0xd3dc, 0xd21e,
-  0xc560, 0xc4a2, 0xc6e4, 0xc726, 0xc268, 0xc3aa, 0xc1ec, 0xc02e,
-  0xcb70, 0xcab2, 0xc8f4, 0xc936, 0xcc78, 0xcdba, 0xcffc, 0xce3e,
-  0x9180, 0x9042, 0x9204, 0x93c6, 0x9688, 0x974a, 0x950c, 0x94ce,
-  0x9f90, 0x9e52, 0x9c14, 0x9dd6, 0x9898, 0x995a, 0x9b1c, 0x9ade,
-  0x8da0, 0x8c62, 0x8e24, 0x8fe6, 0x8aa8, 0x8b6a, 0x892c, 0x88ee,
-  0x83b0, 0x8272, 0x8034, 0x81f6, 0x84b8, 0x857a, 0x873c, 0x86fe,
-  0xa9c0, 0xa802, 0xaa44, 0xab86, 0xaec8, 0xaf0a, 0xad4c, 0xac8e,
-  0xa7d0, 0xa612, 0xa454, 0xa596, 0xa0d8, 0xa11a, 0xa35c, 0xa29e,
-  0xb5e0, 0xb422, 0xb664, 0xb7a6, 0xb2e8, 0xb32a, 0xb16c, 0xb0ae,
-  0xbbf0, 0xba32, 0xb874, 0xb9b6, 0xbcf8, 0xbd3a, 0xbf7c, 0xbebe,
-};
+static struct
+{
+  volatile u32 counter_head;
+  u32 cacheline_align[64 / 4 - 1];
+  u16 R[256];
+  volatile u32 counter_tail;
+} gcm_table ATTR_ALIGNED_64 =
+  {
+    0,
+    { 0, },
+    {
+      0x0000, 0x01c2, 0x0384, 0x0246, 0x0708, 0x06ca, 0x048c, 0x054e,
+      0x0e10, 0x0fd2, 0x0d94, 0x0c56, 0x0918, 0x08da, 0x0a9c, 0x0b5e,
+      0x1c20, 0x1de2, 0x1fa4, 0x1e66, 0x1b28, 0x1aea, 0x18ac, 0x196e,
+      0x1230, 0x13f2, 0x11b4, 0x1076, 0x1538, 0x14fa, 0x16bc, 0x177e,
+      0x3840, 0x3982, 0x3bc4, 0x3a06, 0x3f48, 0x3e8a, 0x3ccc, 0x3d0e,
+      0x3650, 0x3792, 0x35d4, 0x3416, 0x3158, 0x309a, 0x32dc, 0x331e,
+      0x2460, 0x25a2, 0x27e4, 0x2626, 0x2368, 0x22aa, 0x20ec, 0x212e,
+      0x2a70, 0x2bb2, 0x29f4, 0x2836, 0x2d78, 0x2cba, 0x2efc, 0x2f3e,
+      0x7080, 0x7142, 0x7304, 0x72c6, 0x7788, 0x764a, 0x740c, 0x75ce,
+      0x7e90, 0x7f52, 0x7d14, 0x7cd6, 0x7998, 0x785a, 0x7a1c, 0x7bde,
+      0x6ca0, 0x6d62, 0x6f24, 0x6ee6, 0x6ba8, 0x6a6a, 0x682c, 0x69ee,
+      0x62b0, 0x6372, 0x6134, 0x60f6, 0x65b8, 0x647a, 0x663c, 0x67fe,
+      0x48c0, 0x4902, 0x4b44, 0x4a86, 0x4fc8, 0x4e0a, 0x4c4c, 0x4d8e,
+      0x46d0, 0x4712, 0x4554, 0x4496, 0x41d8, 0x401a, 0x425c, 0x439e,
+      0x54e0, 0x5522, 0x5764, 0x56a6, 0x53e8, 0x522a, 0x506c, 0x51ae,
+      0x5af0, 0x5b32, 0x5974, 0x58b6, 0x5df8, 0x5c3a, 0x5e7c, 0x5fbe,
+      0xe100, 0xe0c2, 0xe284, 0xe346, 0xe608, 0xe7ca, 0xe58c, 0xe44e,
+      0xef10, 0xeed2, 0xec94, 0xed56, 0xe818, 0xe9da, 0xeb9c, 0xea5e,
+      0xfd20, 0xfce2, 0xfea4, 0xff66, 0xfa28, 0xfbea, 0xf9ac, 0xf86e,
+      0xf330, 0xf2f2, 0xf0b4, 0xf176, 0xf438, 0xf5fa, 0xf7bc, 0xf67e,
+      0xd940, 0xd882, 0xdac4, 0xdb06, 0xde48, 0xdf8a, 0xddcc, 0xdc0e,
+      0xd750, 0xd692, 0xd4d4, 0xd516, 0xd058, 0xd19a, 0xd3dc, 0xd21e,
+      0xc560, 0xc4a2, 0xc6e4, 0xc726, 0xc268, 0xc3aa, 0xc1ec, 0xc02e,
+      0xcb70, 0xcab2, 0xc8f4, 0xc936, 0xcc78, 0xcdba, 0xcffc, 0xce3e,
+      0x9180, 0x9042, 0x9204, 0x93c6, 0x9688, 0x974a, 0x950c, 0x94ce,
+      0x9f90, 0x9e52, 0x9c14, 0x9dd6, 0x9898, 0x995a, 0x9b1c, 0x9ade,
+      0x8da0, 0x8c62, 0x8e24, 0x8fe6, 0x8aa8, 0x8b6a, 0x892c, 0x88ee,
+      0x83b0, 0x8272, 0x8034, 0x81f6, 0x84b8, 0x857a, 0x873c, 0x86fe,
+      0xa9c0, 0xa802, 0xaa44, 0xab86, 0xaec8, 0xaf0a, 0xad4c, 0xac8e,
+      0xa7d0, 0xa612, 0xa454, 0xa596, 0xa0d8, 0xa11a, 0xa35c, 0xa29e,
+      0xb5e0, 0xb422, 0xb664, 0xb7a6, 0xb2e8, 0xb32a, 0xb16c, 0xb0ae,
+      0xbbf0, 0xba32, 0xb874, 0xb9b6, 0xbcf8, 0xbd3a, 0xbf7c, 0xbebe,
+    },
+    0
+  };
+
+#define gcmR gcm_table.R
+
+static inline
+void prefetch_table(const void *tab, size_t len)
+{
+  const volatile byte *vtab = tab;
+  size_t i;
+
+  for (i = 0; len - i >= 8 * 32; i += 8 * 32)
+    {
+      (void)vtab[i + 0 * 32];
+      (void)vtab[i + 1 * 32];
+      (void)vtab[i + 2 * 32];
+      (void)vtab[i + 3 * 32];
+      (void)vtab[i + 4 * 32];
+      (void)vtab[i + 5 * 32];
+      (void)vtab[i + 6 * 32];
+      (void)vtab[i + 7 * 32];
+    }
+  for (; i < len; i += 32)
+    {
+      (void)vtab[i];
+    }
+
+  (void)vtab[len - 1];
+}
+
+static inline void
+do_prefetch_tables (const void *gcmM, size_t gcmM_size)
+{
+  /* Modify counters to trigger copy-on-write and unsharing if physical pages
+   * of look-up table are shared between processes.  Modifying counters also
+   * causes checksums for pages to change and hint same-page merging algorithm
+   * that these pages are frequently changing.  */
+  gcm_table.counter_head++;
+  gcm_table.counter_tail++;
+
+  /* Prefetch look-up tables to cache.  */
+  prefetch_table(gcmM, gcmM_size);
+  prefetch_table(&gcm_table, sizeof(gcm_table));
+}
 
 #ifdef GCM_TABLES_USE_U64
 static void
@@ -106,7 +248,7 @@ bshift (u64 * b0, u64 * b1)
 
   t[0] = *b0;
   t[1] = *b1;
-  mask = t[1] & 1 ? 0xe1 : 0;
+  mask = -(t[1] & 1) & 0xe1;
   mask <<= 56;
 
   *b1 = (t[1] >> 1) ^ (t[0] << 63);
@@ -138,6 +280,12 @@ do_fillM (unsigned char *h, u64 *M)
         M[(i + j) + 0] = M[i + 0] ^ M[j + 0];
         M[(i + j) + 16] = M[i + 16] ^ M[j + 16];
       }
+
+  for (i = 0; i < 16; i++)
+    {
+      M[i + 32] = (M[i + 0] >> 4) ^ ((u64) gcmR[(M[i + 16] & 0xf) << 4] << 48);
+      M[i + 48] = (M[i + 16] >> 4) ^ (M[i + 0] << 60);
+    }
 }
 
 static inline unsigned int
@@ -150,25 +298,23 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM)
   u32 A;
   int i;
 
-  buf_xor (V, result, buf, 16);
+  cipher_block_xor (V, result, buf, 16);
   V[0] = be_bswap64 (V[0]);
   V[1] = be_bswap64 (V[1]);
 
   /* First round can be manually tweaked based on fact that 'tmp' is zero. */
-  i = 15;
-
-  M = &gcmM[(V[1] & 0xf)];
+  M = &gcmM[(V[1] & 0xf) + 32];
   V[1] >>= 4;
-  tmp[0] = (M[0] >> 4) ^ ((u64) gcmR[(M[16] & 0xf) << 4] << 48);
-  tmp[1] = (M[16] >> 4) ^ (M[0] << 60);
+  tmp[0] = M[0];
+  tmp[1] = M[16];
   tmp[0] ^= gcmM[(V[1] & 0xf) + 0];
   tmp[1] ^= gcmM[(V[1] & 0xf) + 16];
   V[1] >>= 4;
 
-  --i;
+  i = 6;
   while (1)
     {
-      M = &gcmM[(V[1] & 0xf)];
+      M = &gcmM[(V[1] & 0xf) + 32];
       V[1] >>= 4;
 
       A = tmp[1] & 0xff;
@@ -176,15 +322,34 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM)
       tmp[0] = (T >> 8) ^ ((u64) gcmR[A] << 48) ^ gcmM[(V[1] & 0xf) + 0];
       tmp[1] = (T << 56) ^ (tmp[1] >> 8) ^ gcmM[(V[1] & 0xf) + 16];
 
-      tmp[0] ^= (M[0] >> 4) ^ ((u64) gcmR[(M[16] & 0xf) << 4] << 48);
-      tmp[1] ^= (M[16] >> 4) ^ (M[0] << 60);
+      tmp[0] ^= M[0];
+      tmp[1] ^= M[16];
 
       if (i == 0)
         break;
-      else if (i == 8)
-        V[1] = V[0];
-      else
-        V[1] >>= 4;
+
+      V[1] >>= 4;
+      --i;
+    }
+
+  i = 7;
+  while (1)
+    {
+      M = &gcmM[(V[0] & 0xf) + 32];
+      V[0] >>= 4;
+
+      A = tmp[1] & 0xff;
+      T = tmp[0];
+      tmp[0] = (T >> 8) ^ ((u64) gcmR[A] << 48) ^ gcmM[(V[0] & 0xf) + 0];
+      tmp[1] = (T << 56) ^ (tmp[1] >> 8) ^ gcmM[(V[0] & 0xf) + 16];
+
+      tmp[0] ^= M[0];
+      tmp[1] ^= M[16];
+
+      if (i == 0)
+        break;
+
+      V[0] >>= 4;
       --i;
     }
 
@@ -206,7 +371,7 @@ bshift (u32 * M, int i)
   t[1] = M[i * 4 + 1];
   t[2] = M[i * 4 + 2];
   t[3] = M[i * 4 + 3];
-  mask = t[3] & 1 ? 0xe1 : 0;
+  mask = -(t[3] & 1) & 0xe1;
 
   M[i * 4 + 3] = (t[3] >> 1) ^ (t[2] << 31);
   M[i * 4 + 2] = (t[2] >> 1) ^ (t[1] << 31);
@@ -247,6 +412,15 @@ do_fillM (unsigned char *h, u32 *M)
         M[(i + j) * 4 + 2] = M[i * 4 + 2] ^ M[j * 4 + 2];
         M[(i + j) * 4 + 3] = M[i * 4 + 3] ^ M[j * 4 + 3];
       }
+
+  for (i = 0; i < 4 * 16; i += 4)
+    {
+      M[i + 0 + 64] = (M[i + 0] >> 4)
+                      ^ ((u64) gcmR[(M[i + 3] << 4) & 0xf0] << 16);
+      M[i + 1 + 64] = (M[i + 1] >> 4) ^ (M[i + 0] << 28);
+      M[i + 2 + 64] = (M[i + 2] >> 4) ^ (M[i + 1] << 28);
+      M[i + 3 + 64] = (M[i + 3] >> 4) ^ (M[i + 2] << 28);
+    }
 }
 
 static inline unsigned int
@@ -259,25 +433,25 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM)
   u32 T[3];
   int i;
 
-  buf_xor (V, result, buf, 16); /* V is big-endian */
+  cipher_block_xor (V, result, buf, 16); /* V is big-endian */
 
   /* First round can be manually tweaked based on fact that 'tmp' is zero. */
   i = 15;
 
   v = V[i];
-  M = &gcmM[(v & 0xf) * 4];
+  M = &gcmM[(v & 0xf) * 4 + 64];
   v = (v & 0xf0) >> 4;
   m = &gcmM[v * 4];
   v = V[--i];
 
-  tmp[0] = (M[0] >> 4) ^ ((u64) gcmR[(M[3] << 4) & 0xf0] << 16) ^ m[0];
-  tmp[1] = (M[1] >> 4) ^ (M[0] << 28) ^ m[1];
-  tmp[2] = (M[2] >> 4) ^ (M[1] << 28) ^ m[2];
-  tmp[3] = (M[3] >> 4) ^ (M[2] << 28) ^ m[3];
+  tmp[0] = M[0] ^ m[0];
+  tmp[1] = M[1] ^ m[1];
+  tmp[2] = M[2] ^ m[2];
+  tmp[3] = M[3] ^ m[3];
 
   while (1)
     {
-      M = &gcmM[(v & 0xf) * 4];
+      M = &gcmM[(v & 0xf) * 4 + 64];
       v = (v & 0xf0) >> 4;
       m = &gcmM[v * 4];
 
@@ -289,10 +463,10 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM)
       tmp[2] = (T[1] << 24) ^ (tmp[2] >> 8) ^ m[2];
       tmp[3] = (T[2] << 24) ^ (tmp[3] >> 8) ^ m[3];
 
-      tmp[0] ^= (M[0] >> 4) ^ ((u64) gcmR[(M[3] << 4) & 0xf0] << 16);
-      tmp[1] ^= (M[1] >> 4) ^ (M[0] << 28);
-      tmp[2] ^= (M[2] >> 4) ^ (M[1] << 28);
-      tmp[3] ^= (M[3] >> 4) ^ (M[2] << 28);
+      tmp[0] ^= M[0];
+      tmp[1] ^= M[1];
+      tmp[2] ^= M[2];
+      tmp[3] ^= M[3];
 
       if (i == 0)
         break;
@@ -313,6 +487,8 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM)
 #define fillM(c) \
   do_fillM (c->u_mode.gcm.u_ghash_key.key, c->u_mode.gcm.gcm_table)
 #define GHASH(c, result, buf) do_ghash (result, buf, c->u_mode.gcm.gcm_table)
+#define prefetch_tables(c) \
+  do_prefetch_tables(c->u_mode.gcm.gcm_table, sizeof(c->u_mode.gcm.gcm_table))
 
 #else
 
@@ -342,7 +518,7 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf)
 #else
   unsigned long T[4];
 
-  buf_xor (V, result, buf, 16);
+  cipher_block_xor (V, result, buf, 16);
   for (i = 0; i < 4; i++)
     {
       V[i] = (V[i] & 0x00ff00ff) << 8 | (V[i] & 0xff00ff00) >> 8;
@@ -358,7 +534,7 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf)
       for (j = 0x80; j; j >>= 1)
         {
           if (hsub[i] & j)
-            buf_xor (p, p, V, 16);
+            cipher_block_xor (p, p, V, 16);
           if (bshift (V))
             V[0] ^= 0xe1000000;
         }
@@ -378,6 +554,7 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf)
 
 #define fillM(c) do { } while (0)
 #define GHASH(c, result, buf) do_ghash (c->u_mode.gcm.u_ghash_key.key, result, buf)
+#define prefetch_tables(c) do {} while (0)
 
 #endif /* !GCM_USE_TABLES */
 
@@ -389,6 +566,8 @@ ghash_internal (gcry_cipher_hd_t c, byte *result, const byte *buf,
   const unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
   unsigned int burn = 0;
 
+  prefetch_tables (c);
+
   while (nblocks)
     {
       burn = GHASH (c, result, buf);
@@ -403,16 +582,20 @@ ghash_internal (gcry_cipher_hd_t c, byte *result, const byte *buf,
 static void
 setupM (gcry_cipher_hd_t c)
 {
-#if defined(GCM_USE_INTEL_PCLMUL) || defined(GCM_USE_ARM_PMULL)
   unsigned int features = _gcry_get_hw_features ();
-#endif
+
+  c->u_mode.gcm.ghash_fn = NULL;
+  c->u_mode.gcm.polyval_fn = NULL;
 
   if (0)
-    ;
+    {
+      (void)features;
+    }
 #ifdef GCM_USE_INTEL_PCLMUL
   else if (features & HWF_INTEL_PCLMUL)
     {
       c->u_mode.gcm.ghash_fn = _gcry_ghash_intel_pclmul;
+      c->u_mode.gcm.polyval_fn = _gcry_polyval_intel_pclmul;
       _gcry_ghash_setup_intel_pclmul (c);
     }
 #endif
@@ -420,10 +603,35 @@ setupM (gcry_cipher_hd_t c)
   else if (features & HWF_ARM_PMULL)
     {
       c->u_mode.gcm.ghash_fn = ghash_armv8_ce_pmull;
+      c->u_mode.gcm.polyval_fn = polyval_armv8_ce_pmull;
       ghash_setup_armv8_ce_pmull (c);
     }
 #endif
-  else
+#ifdef GCM_USE_ARM_NEON
+  else if (features & HWF_ARM_NEON)
+    {
+      c->u_mode.gcm.ghash_fn = ghash_armv7_neon;
+      ghash_setup_armv7_neon (c);
+    }
+#endif
+#ifdef GCM_USE_PPC_VPMSUM
+  else if (features & HWF_PPC_VCRYPTO)
+    {
+      c->u_mode.gcm.ghash_fn = ghash_ppc_vpmsum;
+      ghash_setup_ppc_vpmsum (c);
+    }
+#endif
+#ifdef GCM_USE_S390X_CRYPTO
+  else if (features & HWF_S390X_MSA)
+    {
+      if (kimd_query () & km_function_to_mask (KMID_FUNCTION_GHASH))
+       {
+         c->u_mode.gcm.ghash_fn = ghash_s390x_kimd;
+       }
+    }
+#endif
+
+  if (c->u_mode.gcm.ghash_fn == NULL)
     {
       c->u_mode.gcm.ghash_fn = ghash_internal;
       fillM (c);
@@ -522,11 +730,17 @@ do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte *buf,
         }
       if (!buflen)
         {
-          if (!do_padding)
-            break;
-
-          while (unused < blocksize)
-            c->u_mode.gcm.macbuf[unused++] = 0;
+          if (!do_padding && unused < blocksize)
+           {
+             break;
+           }
+
+         n = blocksize - unused;
+         if (n > 0)
+           {
+             memset (&c->u_mode.gcm.macbuf[unused], 0, n);
+             unused = blocksize;
+           }
         }
 
       if (unused > 0)
@@ -598,7 +812,7 @@ gcm_ctr_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
                 }
 
               fix_ctr = 1;
-              buf_cpy(ctr_copy, c->u_ctr.ctr, GCRY_GCM_BLOCK_LEN);
+              cipher_block_cpy(ctr_copy, c->u_ctr.ctr, GCRY_GCM_BLOCK_LEN);
             }
         }
 
@@ -627,13 +841,83 @@ gcm_ctr_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
 }
 
 
+static gcry_err_code_t
+gcm_crypt_inner (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
+                const byte *inbuf, size_t inbuflen, int encrypt)
+{
+  gcry_err_code_t err;
+
+  while (inbuflen)
+    {
+      size_t currlen = inbuflen;
+
+      /* Use a bulk method if available.  */
+      if (c->bulk.gcm_crypt)
+       {
+         /* Bulk method requires that there is no cached data. */
+         if (inbuflen >= GCRY_GCM_BLOCK_LEN && c->u_mode.gcm.mac_unused == 0)
+           {
+             size_t nblks = inbuflen / GCRY_GCM_BLOCK_LEN;
+             size_t nleft;
+             size_t ndone;
+
+             nleft = c->bulk.gcm_crypt (c, outbuf, inbuf, nblks, encrypt);
+             ndone = nblks - nleft;
+
+             inbuf += ndone * GCRY_GCM_BLOCK_LEN;
+             outbuf += ndone * GCRY_GCM_BLOCK_LEN;
+             inbuflen -= ndone * GCRY_GCM_BLOCK_LEN;
+             outbuflen -= ndone * GCRY_GCM_BLOCK_LEN;
+
+             if (inbuflen == 0)
+               break;
+
+             currlen = inbuflen;
+           }
+         else if (c->u_mode.gcm.mac_unused > 0
+                  && inbuflen >= GCRY_GCM_BLOCK_LEN
+                         + (16 - c->u_mode.gcm.mac_unused))
+           {
+             /* Handle just enough data so that cache is depleted, and on
+              * next loop iteration use bulk method. */
+             currlen = 16 - c->u_mode.gcm.mac_unused;
+
+             gcry_assert(currlen);
+           }
+       }
+
+      /* Since checksumming is done after/before encryption/decryption,
+       * process input in 24KiB chunks to keep data loaded in L1 cache for
+       * checksumming/decryption. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
+
+      if (!encrypt)
+       do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, inbuf, currlen, 0);
+
+      err = gcm_ctr_encrypt(c, outbuf, outbuflen, inbuf, currlen);
+      if (err != 0)
+       return err;
+
+      if (encrypt)
+       do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, outbuf, currlen, 0);
+
+      outbuf += currlen;
+      inbuf += currlen;
+      outbuflen -= currlen;
+      inbuflen -= currlen;
+    }
+
+  return 0;
+}
+
+
 gcry_err_code_t
 _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c,
                           byte *outbuf, size_t outbuflen,
                           const byte *inbuf, size_t inbuflen)
 {
   static const unsigned char zerobuf[MAX_BLOCKSIZE];
-  gcry_err_code_t err;
 
   if (c->spec->blocksize != GCRY_GCM_BLOCK_LEN)
     return GPG_ERR_CIPHER_ALGO;
@@ -666,13 +950,7 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c,
       return GPG_ERR_INV_LENGTH;
     }
 
-  err = gcm_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen);
-  if (err != 0)
-    return err;
-
-  do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, outbuf, inbuflen, 0);
-
-  return 0;
+  return gcm_crypt_inner (c, outbuf, outbuflen, inbuf, inbuflen, 1);
 }
 
 
@@ -711,9 +989,7 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c,
       return GPG_ERR_INV_LENGTH;
     }
 
-  do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, inbuf, inbuflen, 0);
-
-  return gcm_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen);
+  return gcm_crypt_inner (c, outbuf, outbuflen, inbuf, inbuflen, 0);
 }
 
 
@@ -750,6 +1026,13 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c,
 
 
 void
+_gcry_cipher_gcm_setupM (gcry_cipher_hd_t c)
+{
+  setupM (c);
+}
+
+
+void
 _gcry_cipher_gcm_setkey (gcry_cipher_hd_t c)
 {
   memset (c->u_mode.gcm.u_ghash_key.key, 0, GCRY_GCM_BLOCK_LEN);
@@ -928,8 +1211,8 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
       /* Add bitlengths to tag. */
       do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, (byte*)bitlengths,
                    GCRY_GCM_BLOCK_LEN, 1);
-      buf_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv,
-               c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN);
+      cipher_block_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv,
+                        c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN);
       c->marks.tag = 1;
 
       wipememory (bitlengths, sizeof (bitlengths));
index b748125..c8a1097 100644 (file)
 # endif
 #endif /* GCM_USE_ARM_PMULL */
 
+/* GCM_USE_ARM_NEON indicates whether to compile GCM with ARMv7 NEON code. */
+#undef GCM_USE_ARM_NEON
+#if defined(GCM_USE_TABLES)
+#if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \
+    defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_NEON)
+#  define GCM_USE_ARM_NEON 1
+#endif
+#endif /* GCM_USE_ARM_NEON */
+
+/* GCM_USE_S390X_CRYPTO indicates whether to enable zSeries code. */
+#undef GCM_USE_S390X_CRYPTO
+#if defined(HAVE_GCC_INLINE_ASM_S390X)
+# define GCM_USE_S390X_CRYPTO 1
+#endif /* GCM_USE_S390X_CRYPTO */
+
+/* GCM_USE_PPC_VPMSUM indicates whether to compile GCM with PPC Power 8
+ * polynomial multiplication instruction. */
+#undef GCM_USE_PPC_VPMSUM
+#if defined(GCM_USE_TABLES)
+#if defined(ENABLE_PPC_CRYPTO_SUPPORT) && defined(__powerpc64__) && \
+    defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+    defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) && __GNUC__ >= 4
+#  define GCM_USE_PPC_VPMSUM 1
+#  define NEED_16BYTE_ALIGNED_CONTEXT 1 /* this also aligns gcm_table */
+#endif
+#endif /* GCM_USE_PPC_VPMSUM */
 
 typedef unsigned int (*ghash_fn_t) (gcry_cipher_hd_t c, byte *result,
                                     const byte *buf, size_t nblocks);
 
 
+/* A structure with function pointers for mode operations. */
+typedef struct cipher_mode_ops
+{
+  gcry_err_code_t (*encrypt)(gcry_cipher_hd_t c, unsigned char *outbuf,
+                            size_t outbuflen, const unsigned char *inbuf,
+                            size_t inbuflen);
+  gcry_err_code_t (*decrypt)(gcry_cipher_hd_t c, unsigned char *outbuf,
+                            size_t outbuflen, const unsigned char *inbuf,
+                            size_t inbuflen);
+  gcry_err_code_t (*setiv)(gcry_cipher_hd_t c, const unsigned char *iv,
+                          size_t ivlen);
+
+  gcry_err_code_t (*authenticate)(gcry_cipher_hd_t c,
+                                 const unsigned char *abuf, size_t abuflen);
+  gcry_err_code_t (*get_tag)(gcry_cipher_hd_t c, unsigned char *outtag,
+                            size_t taglen);
+  gcry_err_code_t (*check_tag)(gcry_cipher_hd_t c, const unsigned char *intag,
+                              size_t taglen);
+} cipher_mode_ops_t;
+
+
+/* A structure with function pointers for bulk operations.  The cipher
+   algorithm setkey function initializes them when bulk operations are
+   available and the actual encryption routines use them if they are
+   not NULL.  */
+typedef struct cipher_bulk_ops
+{
+  void (*cfb_enc)(void *context, unsigned char *iv, void *outbuf_arg,
+                 const void *inbuf_arg, size_t nblocks);
+  void (*cfb_dec)(void *context, unsigned char *iv, void *outbuf_arg,
+                 const void *inbuf_arg, size_t nblocks);
+  void (*cbc_enc)(void *context, unsigned char *iv, void *outbuf_arg,
+                 const void *inbuf_arg, size_t nblocks, int cbc_mac);
+  void (*cbc_dec)(void *context, unsigned char *iv, void *outbuf_arg,
+                 const void *inbuf_arg, size_t nblocks);
+  void (*ofb_enc)(void *context, unsigned char *iv, void *outbuf_arg,
+                 const void *inbuf_arg, size_t nblocks);
+  void (*ctr_enc)(void *context, unsigned char *iv, void *outbuf_arg,
+                 const void *inbuf_arg, size_t nblocks);
+  void (*ctr32le_enc)(void *context, unsigned char *iv, void *outbuf_arg,
+                     const void *inbuf_arg, size_t nblocks);
+  size_t (*ocb_crypt)(gcry_cipher_hd_t c, void *outbuf_arg,
+                     const void *inbuf_arg, size_t nblocks, int encrypt);
+  size_t (*ocb_auth)(gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks);
+  void (*xts_crypt)(void *context, unsigned char *tweak, void *outbuf_arg,
+                   const void *inbuf_arg, size_t nblocks, int encrypt);
+  size_t (*gcm_crypt)(gcry_cipher_hd_t c, void *outbuf_arg,
+                     const void *inbuf_arg, size_t nblocks, int encrypt);
+} cipher_bulk_ops_t;
+
+
 /* A VIA processor with the Padlock engine as well as the Intel AES_NI
    instructions require an alignment of most data on a 16 byte
    boundary.  Because we trick out the compiler while allocating the
@@ -109,6 +187,25 @@ typedef union
 } cipher_context_alignment_t;
 
 
+/* Storage structure for CMAC, for CMAC and EAX modes. */
+typedef struct {
+  /* The initialization vector. Also contains tag after finalization. */
+  union {
+    cipher_context_alignment_t iv_align;
+    unsigned char iv[MAX_BLOCKSIZE];
+  } u_iv;
+
+  /* Subkeys for tag creation, not cleared by gcry_cipher_reset. */
+  unsigned char subkeys[2][MAX_BLOCKSIZE];
+
+  /* Space to save partial input lengths for MAC. */
+  unsigned char macbuf[MAX_BLOCKSIZE];
+
+  int mac_unused;  /* Number of unprocessed bytes in MACBUF. */
+  unsigned int tag:1; /* Set to 1 if tag has been finalized.  */
+} gcry_cmac_context_t;
+
+
 /* The handle structure.  */
 struct gcry_cipher_handle
 {
@@ -121,36 +218,13 @@ struct gcry_cipher_handle
      interface does not easily allow to retrieve this value. */
   int algo;
 
+  /* A structure with function pointers for mode operations. */
+  cipher_mode_ops_t mode_ops;
+
   /* A structure with function pointers for bulk operations.  Due to
      limitations of the module system (we don't want to change the
-     API) we need to keep these function pointers here.  The cipher
-     open function initializes them and the actual encryption routines
-     use them if they are not NULL.  */
-  struct {
-    void (*cfb_enc)(void *context, unsigned char *iv,
-                    void *outbuf_arg, const void *inbuf_arg,
-                    size_t nblocks);
-    void (*cfb_dec)(void *context, unsigned char *iv,
-                    void *outbuf_arg, const void *inbuf_arg,
-                    size_t nblocks);
-    void (*cbc_enc)(void *context, unsigned char *iv,
-                    void *outbuf_arg, const void *inbuf_arg,
-                    size_t nblocks, int cbc_mac);
-    void (*cbc_dec)(void *context, unsigned char *iv,
-                    void *outbuf_arg, const void *inbuf_arg,
-                    size_t nblocks);
-    void (*ctr_enc)(void *context, unsigned char *iv,
-                    void *outbuf_arg, const void *inbuf_arg,
-                    size_t nblocks);
-    size_t (*ocb_crypt)(gcry_cipher_hd_t c, void *outbuf_arg,
-                       const void *inbuf_arg, size_t nblocks, int encrypt);
-    size_t (*ocb_auth)(gcry_cipher_hd_t c, const void *abuf_arg,
-                      size_t nblocks);
-    void (*xts_crypt)(gcry_cipher_hd_t c, unsigned char *tweak,
-                     void *outbuf_arg, const void *inbuf_arg,
-                     size_t nblocks, int encrypt);
-  } bulk;
-
+     API) we need to keep these function pointers here.  */
+  cipher_bulk_ops_t bulk;
 
   int mode;
   unsigned int flags;
@@ -160,6 +234,7 @@ struct gcry_cipher_handle
     unsigned int iv:1;  /* Set to 1 if a IV has been set.  */
     unsigned int tag:1; /* Set to 1 if a tag is finalized. */
     unsigned int finalize:1; /* Next encrypt/decrypt has the final data.  */
+    unsigned int allow_weak_key:1; /* Set to 1 if weak keys are allowed. */
   } marks;
 
   /* The initialization vector.  For best performance we make sure
@@ -197,7 +272,7 @@ struct gcry_cipher_handle
 
       unsigned char s0[GCRY_CCM_BLOCK_LEN];
 
-      unsigned int nonce:1;/* Set to 1 if nonce has been set.  */
+      unsigned int nonce:1; /* Set to 1 if nonce has been set.  */
       unsigned int lengths:1; /* Set to 1 if CCM length parameters has been
                                  processed.  */
     } ccm;
@@ -217,14 +292,18 @@ struct gcry_cipher_handle
     } poly1305;
 
     /* Mode specific storage for CMAC mode. */
+    gcry_cmac_context_t cmac;
+
+    /* Mode specific storage for EAX mode. */
     struct {
-      unsigned int tag:1; /* Set to 1 if tag has been finalized.  */
+      /* CMAC for header (AAD). */
+      gcry_cmac_context_t cmac_header;
 
-      /* Subkeys for tag creation, not cleared by gcry_cipher_reset. */
-      unsigned char subkeys[2][MAX_BLOCKSIZE];
-    } cmac;
+      /* CMAC for ciphertext. */
+      gcry_cmac_context_t cmac_ciphertext;
+    } eax;
 
-    /* Mode specific storage for GCM mode. */
+    /* Mode specific storage for GCM mode and GCM-SIV mode. */
     struct {
       /* The interim tag for GCM mode.  */
       union {
@@ -236,7 +315,6 @@ struct gcry_cipher_handle
       unsigned char macbuf[GCRY_CCM_BLOCK_LEN];
       int mac_unused;  /* Number of unprocessed bytes in MACBUF. */
 
-
       /* byte counters for GCM */
       u32 aadlen[2];
       u32 datalen[2];
@@ -258,27 +336,38 @@ struct gcry_cipher_handle
         unsigned char key[MAX_BLOCKSIZE];
       } u_ghash_key;
 
-      /* GHASH implementation in use. */
-      ghash_fn_t ghash_fn;
-
       /* Pre-calculated table for GCM. */
 #ifdef GCM_USE_TABLES
  #if (SIZEOF_UNSIGNED_LONG == 8 || defined(__x86_64__))
       #define GCM_TABLES_USE_U64 1
-      u64 gcm_table[2 * 16];
+      u64 gcm_table[4 * 16];
  #else
       #undef GCM_TABLES_USE_U64
-      u32 gcm_table[4 * 16];
+      u32 gcm_table[8 * 16];
  #endif
 #endif
+
+      /* GHASH implementation in use. */
+      ghash_fn_t ghash_fn;
+
+      /* POLYVAL implementation in use (GCM-SIV). */
+      ghash_fn_t polyval_fn;
+
+      /* Key length used for GCM-SIV key generating key. */
+      unsigned int siv_keylen;
     } gcm;
 
     /* Mode specific storage for OCB mode. */
     struct {
+      /* --- Following members are not cleared in gcry_cipher_reset --- */
+
       /* Helper variables and pre-computed table of L values.  */
       unsigned char L_star[OCB_BLOCK_LEN];
       unsigned char L_dollar[OCB_BLOCK_LEN];
-      unsigned char L[OCB_BLOCK_LEN][OCB_L_TABLE_SIZE];
+      unsigned char L0L1[OCB_BLOCK_LEN];
+      unsigned char L[OCB_L_TABLE_SIZE][OCB_BLOCK_LEN];
+
+      /* --- Following members are cleared in gcry_cipher_reset --- */
 
       /* The tag is valid if marks.tag has been set.  */
       unsigned char tag[OCB_BLOCK_LEN];
@@ -309,7 +398,6 @@ struct gcry_cipher_handle
          processed.  */
       unsigned int data_finalized:1;
       unsigned int aad_finalized:1;
-
     } ocb;
 
     /* Mode specific storage for XTS mode. */
@@ -318,6 +406,36 @@ struct gcry_cipher_handle
        * cipher context. */
       char *tweak_context;
     } xts;
+
+    /* Mode specific storage for SIV mode. */
+    struct {
+      /* Tag used for decryption. */
+      unsigned char dec_tag[GCRY_SIV_BLOCK_LEN];
+
+      /* S2V state. */
+      unsigned char s2v_d[GCRY_SIV_BLOCK_LEN];
+
+      /* Number of AAD elements processed. */
+      unsigned int aad_count:8;
+
+      /* Flags for SIV state. */
+      unsigned int dec_tag_set:1;
+
+      /* --- Following members are not cleared in gcry_cipher_reset --- */
+
+      /* S2V CMAC state. */
+      gcry_cmac_context_t s2v_cmac;
+      unsigned char s2v_zero_block[GCRY_SIV_BLOCK_LEN];
+
+      /* Pointer to CTR cipher context, allocated after actual
+       * cipher context. */
+      char *ctr_context;
+    } siv;
+
+    /* Mode specific storage for WRAP mode. */
+    struct {
+      unsigned char plen[4];
+    } wrap;
   } u_mode;
 
   /* What follows are two contexts of the cipher in use.  The first
@@ -338,6 +456,14 @@ gcry_err_code_t _gcry_cipher_cbc_decrypt
 /*           */ (gcry_cipher_hd_t c,
                  unsigned char *outbuf, size_t outbuflen,
                  const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_cbc_cts_encrypt
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outbuf, size_t outbuflen,
+                 const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_cbc_cts_decrypt
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outbuf, size_t outbuflen,
+                 const unsigned char *inbuf, size_t inbuflen);
 
 /*-- cipher-cfb.c --*/
 gcry_err_code_t _gcry_cipher_cfb_encrypt
@@ -365,6 +491,11 @@ gcry_err_code_t _gcry_cipher_ofb_encrypt
                  const unsigned char *inbuf, size_t inbuflen);
 
 /*-- cipher-ctr.c --*/
+gcry_err_code_t _gcry_cipher_ctr_encrypt_ctx
+/*           */ (gcry_cipher_hd_t c,
+                unsigned char *outbuf, size_t outbuflen,
+                const unsigned char *inbuf, size_t inbuflen,
+                void *algo_context);
 gcry_err_code_t _gcry_cipher_ctr_encrypt
 /*           */ (gcry_cipher_hd_t c,
                  unsigned char *outbuf, size_t outbuflen,
@@ -372,11 +503,15 @@ gcry_err_code_t _gcry_cipher_ctr_encrypt
 
 
 /*-- cipher-aeswrap.c --*/
-gcry_err_code_t _gcry_cipher_aeswrap_encrypt
+gcry_err_code_t _gcry_cipher_keywrap_encrypt
+/*           */   (gcry_cipher_hd_t c,
+                   byte *outbuf, size_t outbuflen,
+                   const byte *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_keywrap_encrypt_padding
 /*           */   (gcry_cipher_hd_t c,
                    byte *outbuf, size_t outbuflen,
                    const byte *inbuf, size_t inbuflen);
-gcry_err_code_t _gcry_cipher_aeswrap_decrypt
+gcry_err_code_t _gcry_cipher_keywrap_decrypt_auto
 /*           */   (gcry_cipher_hd_t c,
                    byte *outbuf, size_t outbuflen,
                    const byte *inbuf, size_t inbuflen);
@@ -406,6 +541,42 @@ gcry_err_code_t _gcry_cipher_ccm_check_tag
                  const unsigned char *intag, size_t taglen);
 
 
+/*-- cipher-cmac.c --*/
+gcry_err_code_t _gcry_cmac_generate_subkeys
+/*           */ (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx);
+gcry_err_code_t _gcry_cmac_write
+/*           */ (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx,
+                const byte * inbuf, size_t inlen);
+gcry_err_code_t _gcry_cmac_final
+/*           */ (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx);
+void _gcry_cmac_reset (gcry_cmac_context_t *ctx);
+
+
+/*-- cipher-eax.c --*/
+gcry_err_code_t _gcry_cipher_eax_encrypt
+/*           */   (gcry_cipher_hd_t c,
+                   unsigned char *outbuf, size_t outbuflen,
+                   const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_eax_decrypt
+/*           */   (gcry_cipher_hd_t c,
+                   unsigned char *outbuf, size_t outbuflen,
+                   const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_eax_set_nonce
+/*           */   (gcry_cipher_hd_t c,
+                   const unsigned char *nonce, size_t noncelen);
+gcry_err_code_t _gcry_cipher_eax_authenticate
+/*           */   (gcry_cipher_hd_t c,
+                   const unsigned char *aadbuf, size_t aadbuflen);
+gcry_err_code_t _gcry_cipher_eax_get_tag
+/*           */   (gcry_cipher_hd_t c,
+                   unsigned char *outtag, size_t taglen);
+gcry_err_code_t _gcry_cipher_eax_check_tag
+/*           */   (gcry_cipher_hd_t c,
+                   const unsigned char *intag, size_t taglen);
+gcry_err_code_t _gcry_cipher_eax_setkey
+/*           */   (gcry_cipher_hd_t c);
+
+
 /*-- cipher-gcm.c --*/
 gcry_err_code_t _gcry_cipher_gcm_encrypt
 /*           */   (gcry_cipher_hd_t c,
@@ -429,6 +600,8 @@ gcry_err_code_t _gcry_cipher_gcm_check_tag
                    const unsigned char *intag, size_t taglen);
 void _gcry_cipher_gcm_setkey
 /*           */   (gcry_cipher_hd_t c);
+void _gcry_cipher_gcm_setupM
+/*           */   (gcry_cipher_hd_t c);
 
 
 /*-- cipher-poly1305.c --*/
@@ -456,6 +629,15 @@ void _gcry_cipher_poly1305_setkey
 /*           */   (gcry_cipher_hd_t c);
 
 
+/*-- chacha20.c --*/
+gcry_err_code_t _gcry_chacha20_poly1305_encrypt
+/*           */   (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
+                  size_t length);
+gcry_err_code_t _gcry_chacha20_poly1305_decrypt
+/*           */   (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf,
+                  size_t length);
+
+
 /*-- cipher-ocb.c --*/
 gcry_err_code_t _gcry_cipher_ocb_encrypt
 /*           */ (gcry_cipher_hd_t c,
@@ -476,12 +658,70 @@ gcry_err_code_t _gcry_cipher_ocb_get_tag
 gcry_err_code_t _gcry_cipher_ocb_check_tag
 /*           */ (gcry_cipher_hd_t c,
                  const unsigned char *intag, size_t taglen);
+void _gcry_cipher_ocb_setkey
+/*           */ (gcry_cipher_hd_t c);
 
 
 /*-- cipher-xts.c --*/
-gcry_err_code_t _gcry_cipher_xts_crypt
+gcry_err_code_t _gcry_cipher_xts_encrypt
 /*           */ (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen,
-                const unsigned char *inbuf, size_t inbuflen, int encrypt);
+                const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_xts_decrypt
+/*           */ (gcry_cipher_hd_t c, unsigned char *outbuf, size_t outbuflen,
+                const unsigned char *inbuf, size_t inbuflen);
+
+
+/*-- cipher-siv.c --*/
+gcry_err_code_t _gcry_cipher_siv_encrypt
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outbuf, size_t outbuflen,
+                 const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_siv_decrypt
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outbuf, size_t outbuflen,
+                 const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_siv_set_nonce
+/*           */ (gcry_cipher_hd_t c, const unsigned char *nonce,
+                 size_t noncelen);
+gcry_err_code_t _gcry_cipher_siv_authenticate
+/*           */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen);
+gcry_err_code_t _gcry_cipher_siv_set_decryption_tag
+/*           */ (gcry_cipher_hd_t c, const byte *tag, size_t taglen);
+gcry_err_code_t _gcry_cipher_siv_get_tag
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outtag, size_t taglen);
+gcry_err_code_t _gcry_cipher_siv_check_tag
+/*           */ (gcry_cipher_hd_t c,
+                 const unsigned char *intag, size_t taglen);
+gcry_err_code_t _gcry_cipher_siv_setkey
+/*           */ (gcry_cipher_hd_t c,
+                 const unsigned char *ctrkey, size_t ctrkeylen);
+
+
+/*-- cipher-gcm-siv.c --*/
+gcry_err_code_t _gcry_cipher_gcm_siv_encrypt
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outbuf, size_t outbuflen,
+                 const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_gcm_siv_decrypt
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outbuf, size_t outbuflen,
+                 const unsigned char *inbuf, size_t inbuflen);
+gcry_err_code_t _gcry_cipher_gcm_siv_set_nonce
+/*           */ (gcry_cipher_hd_t c, const unsigned char *nonce,
+                 size_t noncelen);
+gcry_err_code_t _gcry_cipher_gcm_siv_authenticate
+/*           */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen);
+gcry_err_code_t _gcry_cipher_gcm_siv_set_decryption_tag
+/*           */ (gcry_cipher_hd_t c, const byte *tag, size_t taglen);
+gcry_err_code_t _gcry_cipher_gcm_siv_get_tag
+/*           */ (gcry_cipher_hd_t c,
+                 unsigned char *outtag, size_t taglen);
+gcry_err_code_t _gcry_cipher_gcm_siv_check_tag
+/*           */ (gcry_cipher_hd_t c,
+                 const unsigned char *intag, size_t taglen);
+gcry_err_code_t _gcry_cipher_gcm_siv_setkey
+/*           */ (gcry_cipher_hd_t c, unsigned int keylen);
 
 
 /* Return the L-value for block N.  Note: 'cipher_ocb.c' ensures that N
@@ -506,4 +746,201 @@ ocb_get_l (gcry_cipher_hd_t c, u64 n)
   return c->u_mode.ocb.L[ntz];
 }
 
+
+/* Return bit-shift of blocksize. */
+static inline unsigned int _gcry_blocksize_shift(gcry_cipher_hd_t c)
+{
+  /* Only blocksizes 8 and 16 are used. Return value in such way
+   * that compiler can optimize calling functions based on this.  */
+  return c->spec->blocksize == 8 ? 3 : 4;
+}
+
+
+/* Optimized function for adding value to cipher block. */
+static inline void
+cipher_block_add(void *_dstsrc, unsigned int add, size_t blocksize)
+{
+  byte *dstsrc = _dstsrc;
+  u64 s[2];
+
+  if (blocksize == 8)
+    {
+      buf_put_be64(dstsrc + 0, buf_get_be64(dstsrc + 0) + add);
+    }
+  else /* blocksize == 16 */
+    {
+      s[0] = buf_get_be64(dstsrc + 8);
+      s[1] = buf_get_be64(dstsrc + 0);
+      s[0] += add;
+      s[1] += (s[0] < add);
+      buf_put_be64(dstsrc + 8, s[0]);
+      buf_put_be64(dstsrc + 0, s[1]);
+    }
+}
+
+
+/* Optimized function for cipher block copying */
+static inline void
+cipher_block_cpy(void *_dst, const void *_src, size_t blocksize)
+{
+  byte *dst = _dst;
+  const byte *src = _src;
+  u64 s[2];
+
+  if (blocksize == 8)
+    {
+      buf_put_he64(dst + 0, buf_get_he64(src + 0));
+    }
+  else /* blocksize == 16 */
+    {
+      s[0] = buf_get_he64(src + 0);
+      s[1] = buf_get_he64(src + 8);
+      buf_put_he64(dst + 0, s[0]);
+      buf_put_he64(dst + 8, s[1]);
+    }
+}
+
+
+/* Optimized function for cipher block xoring */
+static inline void
+cipher_block_xor(void *_dst, const void *_src1, const void *_src2,
+                 size_t blocksize)
+{
+  byte *dst = _dst;
+  const byte *src1 = _src1;
+  const byte *src2 = _src2;
+  u64 s1[2];
+  u64 s2[2];
+
+  if (blocksize == 8)
+    {
+      buf_put_he64(dst + 0, buf_get_he64(src1 + 0) ^ buf_get_he64(src2 + 0));
+    }
+  else /* blocksize == 16 */
+    {
+      s1[0] = buf_get_he64(src1 + 0);
+      s1[1] = buf_get_he64(src1 + 8);
+      s2[0] = buf_get_he64(src2 + 0);
+      s2[1] = buf_get_he64(src2 + 8);
+      buf_put_he64(dst + 0, s1[0] ^ s2[0]);
+      buf_put_he64(dst + 8, s1[1] ^ s2[1]);
+    }
+}
+
+
+/* Optimized function for in-place cipher block xoring */
+static inline void
+cipher_block_xor_1(void *_dst, const void *_src, size_t blocksize)
+{
+  cipher_block_xor (_dst, _dst, _src, blocksize);
+}
+
+
+/* Optimized function for cipher block xoring with two destination cipher
+   blocks.  Used mainly by CFB mode encryption.  */
+static inline void
+cipher_block_xor_2dst(void *_dst1, void *_dst2, const void *_src,
+                      size_t blocksize)
+{
+  byte *dst1 = _dst1;
+  byte *dst2 = _dst2;
+  const byte *src = _src;
+  u64 d2[2];
+  u64 s[2];
+
+  if (blocksize == 8)
+    {
+      d2[0] = buf_get_he64(dst2 + 0) ^ buf_get_he64(src + 0);
+      buf_put_he64(dst2 + 0, d2[0]);
+      buf_put_he64(dst1 + 0, d2[0]);
+    }
+  else /* blocksize == 16 */
+    {
+      s[0] = buf_get_he64(src + 0);
+      s[1] = buf_get_he64(src + 8);
+      d2[0] = buf_get_he64(dst2 + 0);
+      d2[1] = buf_get_he64(dst2 + 8);
+      d2[0] = d2[0] ^ s[0];
+      d2[1] = d2[1] ^ s[1];
+      buf_put_he64(dst2 + 0, d2[0]);
+      buf_put_he64(dst2 + 8, d2[1]);
+      buf_put_he64(dst1 + 0, d2[0]);
+      buf_put_he64(dst1 + 8, d2[1]);
+    }
+}
+
+
+/* Optimized function for combined cipher block xoring and copying.
+   Used by mainly CBC mode decryption.  */
+static inline void
+cipher_block_xor_n_copy_2(void *_dst_xor, const void *_src_xor,
+                          void *_srcdst_cpy, const void *_src_cpy,
+                          size_t blocksize)
+{
+  byte *dst_xor = _dst_xor;
+  byte *srcdst_cpy = _srcdst_cpy;
+  const byte *src_xor = _src_xor;
+  const byte *src_cpy = _src_cpy;
+  u64 sc[2];
+  u64 sx[2];
+  u64 sdc[2];
+
+  if (blocksize == 8)
+    {
+      sc[0] = buf_get_he64(src_cpy + 0);
+      buf_put_he64(dst_xor + 0,
+                   buf_get_he64(srcdst_cpy + 0) ^ buf_get_he64(src_xor + 0));
+      buf_put_he64(srcdst_cpy + 0, sc[0]);
+    }
+  else /* blocksize == 16 */
+    {
+      sc[0] = buf_get_he64(src_cpy + 0);
+      sc[1] = buf_get_he64(src_cpy + 8);
+      sx[0] = buf_get_he64(src_xor + 0);
+      sx[1] = buf_get_he64(src_xor + 8);
+      sdc[0] = buf_get_he64(srcdst_cpy + 0);
+      sdc[1] = buf_get_he64(srcdst_cpy + 8);
+      sx[0] ^= sdc[0];
+      sx[1] ^= sdc[1];
+      buf_put_he64(dst_xor + 0, sx[0]);
+      buf_put_he64(dst_xor + 8, sx[1]);
+      buf_put_he64(srcdst_cpy + 0, sc[0]);
+      buf_put_he64(srcdst_cpy + 8, sc[1]);
+    }
+}
+
+
+/* Optimized function for combined cipher block byte-swapping.  */
+static inline void
+cipher_block_bswap (void *_dst_bswap, const void *_src_bswap,
+                    size_t blocksize)
+{
+  byte *dst_bswap = _dst_bswap;
+  const byte *src_bswap = _src_bswap;
+  u64 t[2];
+
+  if (blocksize == 8)
+    {
+      buf_put_le64(dst_bswap, buf_get_be64(src_bswap));
+    }
+  else
+    {
+      t[0] = buf_get_be64(src_bswap + 0);
+      t[1] = buf_get_be64(src_bswap + 8);
+      buf_put_le64(dst_bswap + 8, t[0]);
+      buf_put_le64(dst_bswap + 0, t[1]);
+    }
+}
+
+
+/* Optimized function for combined cipher block xoring and copying.
+   Used by mainly CFB mode decryption.  */
+static inline void
+cipher_block_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src,
+                        size_t blocksize)
+{
+  cipher_block_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, blocksize);
+}
+
+
 #endif /*G10_CIPHER_INTERNAL_H*/
index db42aaf..bfafa4c 100644 (file)
 
 /* Double the OCB_BLOCK_LEN sized block B in-place.  */
 static inline void
-double_block (unsigned char *b)
+double_block (u64 b[2])
 {
-#if OCB_BLOCK_LEN != 16
-  unsigned char b_0 = b[0];
-  int i;
-
-  for (i=0; i < OCB_BLOCK_LEN - 1; i++)
-    b[i] = (b[i] << 1) | (b[i+1] >> 7);
-
-  b[OCB_BLOCK_LEN-1] = (b[OCB_BLOCK_LEN-1] << 1) ^ ((b_0 >> 7) * 135);
-#else
-  /* This is the generic code for 16 byte blocks.  However it is not
-     faster than the straight byte by byte implementation.  */
   u64 l_0, l, r;
 
-  l = buf_get_be64 (b);
-  r = buf_get_be64 (b + 8);
+  l = b[1];
+  r = b[0];
 
   l_0 = -(l >> 63);
   l = (l + l) ^ (r >> 63);
   r = (r + r) ^ (l_0 & 135);
 
-  buf_put_be64 (b, l);
-  buf_put_be64 (b+8, r);
-#endif
-}
-
-
-/* Double the OCB_BLOCK_LEN sized block S and store it at D.  S and D
-   may point to the same memory location but they may not overlap.  */
-static void
-double_block_cpy (unsigned char *d, const unsigned char *s)
-{
-  if (d != s)
-    buf_cpy (d, s, OCB_BLOCK_LEN);
-  double_block (d);
+  b[1] = l;
+  b[0] = r;
 }
 
 
-/* Copy NBYTES from buffer S starting at bit offset BITOFF to buffer D.  */
+/* Copy OCB_BLOCK_LEN from buffer S starting at bit offset BITOFF to
+ * buffer D.  */
 static void
-bit_copy (unsigned char *d, const unsigned char *s,
-          unsigned int bitoff, unsigned int nbytes)
+bit_copy (unsigned char d[16], const unsigned char s[24], unsigned int bitoff)
 {
+  u64 s0l, s1l, s1r, s2r;
   unsigned int shift;
+  unsigned int byteoff;
 
-  s += bitoff / 8;
+  byteoff = bitoff / 8;
   shift = bitoff % 8;
-  if (shift)
-    {
-      for (; nbytes; nbytes--, d++, s++)
-        *d = (s[0] << shift) | (s[1] >> (8 - shift));
-    }
-  else
-    {
-      for (; nbytes; nbytes--, d++, s++)
-        *d = *s;
-    }
+
+  s0l = buf_get_be64 (s + byteoff + 0);
+  s1l = buf_get_be64 (s + byteoff + 8);
+  s1r = shift ? s1l : 0;
+  s2r = shift ? buf_get_be64 (s + 16) << (8 * byteoff) : 0;
+
+  buf_put_be64 (d + 0, (s0l << shift) | (s1r >> ((64 - shift) & 63)));
+  buf_put_be64 (d + 8, (s1l << shift) | (s2r >> ((64 - shift) & 63)));
 }
 
 
@@ -114,12 +91,59 @@ static void
 ocb_get_L_big (gcry_cipher_hd_t c, u64 n, unsigned char *l_buf)
 {
   int ntz = _gcry_ctz64 (n);
+  u64 L[2];
 
   gcry_assert(ntz >= OCB_L_TABLE_SIZE);
 
-  double_block_cpy (l_buf, c->u_mode.ocb.L[OCB_L_TABLE_SIZE - 1]);
-  for (ntz -= OCB_L_TABLE_SIZE; ntz; ntz--)
-    double_block (l_buf);
+  L[1] = buf_get_be64 (c->u_mode.ocb.L[OCB_L_TABLE_SIZE - 1]);
+  L[0] = buf_get_be64 (c->u_mode.ocb.L[OCB_L_TABLE_SIZE - 1] + 8);
+
+  for (ntz -= OCB_L_TABLE_SIZE - 1; ntz; ntz--)
+    double_block (L);
+
+  buf_put_be64 (l_buf + 0, L[1]);
+  buf_put_be64 (l_buf + 8, L[0]);
+}
+
+
+/* Called after key has been set. Sets up L table. */
+void
+_gcry_cipher_ocb_setkey (gcry_cipher_hd_t c)
+{
+  unsigned char ktop[OCB_BLOCK_LEN];
+  unsigned int burn = 0;
+  unsigned int nburn;
+  u64 L[2];
+  int i;
+
+  /* L_star = E(zero_128) */
+  memset (ktop, 0, OCB_BLOCK_LEN);
+  nburn = c->spec->encrypt (&c->context.c, c->u_mode.ocb.L_star, ktop);
+  burn = nburn > burn ? nburn : burn;
+  /* L_dollar = double(L_star)  */
+  L[1] = buf_get_be64 (c->u_mode.ocb.L_star);
+  L[0] = buf_get_be64 (c->u_mode.ocb.L_star + 8);
+  double_block (L);
+  buf_put_be64 (c->u_mode.ocb.L_dollar + 0, L[1]);
+  buf_put_be64 (c->u_mode.ocb.L_dollar + 8, L[0]);
+  /* L_0 = double(L_dollar), ...  */
+  double_block (L);
+  buf_put_be64 (c->u_mode.ocb.L[0] + 0, L[1]);
+  buf_put_be64 (c->u_mode.ocb.L[0] + 8, L[0]);
+  for (i = 1; i < OCB_L_TABLE_SIZE; i++)
+    {
+      double_block (L);
+      buf_put_be64 (c->u_mode.ocb.L[i] + 0, L[1]);
+      buf_put_be64 (c->u_mode.ocb.L[i] + 8, L[0]);
+    }
+  /* Precalculated offset L0+L1 */
+  cipher_block_xor (c->u_mode.ocb.L0L1,
+                   c->u_mode.ocb.L[0], c->u_mode.ocb.L[1], OCB_BLOCK_LEN);
+
+  /* Cleanup */
+  wipememory (ktop, sizeof ktop);
+  if (burn > 0)
+    _gcry_burn_stack (burn + 4*sizeof(void*));
 }
 
 
@@ -133,7 +157,6 @@ _gcry_cipher_ocb_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce,
   unsigned char ktop[OCB_BLOCK_LEN];
   unsigned char stretch[OCB_BLOCK_LEN + 8];
   unsigned int bottom;
-  int i;
   unsigned int burn = 0;
   unsigned int nburn;
 
@@ -159,20 +182,8 @@ _gcry_cipher_ocb_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce,
   if (noncelen > (120/8) || noncelen < (64/8) || noncelen >= OCB_BLOCK_LEN)
     return GPG_ERR_INV_LENGTH;
 
-  /* Set up the L table.  */
-  /* L_star = E(zero_128) */
-  memset (ktop, 0, OCB_BLOCK_LEN);
-  nburn = c->spec->encrypt (&c->context.c, c->u_mode.ocb.L_star, ktop);
-  burn = nburn > burn ? nburn : burn;
-  /* L_dollar = double(L_star)  */
-  double_block_cpy (c->u_mode.ocb.L_dollar, c->u_mode.ocb.L_star);
-  /* L_0 = double(L_dollar), ...  */
-  double_block_cpy (c->u_mode.ocb.L[0], c->u_mode.ocb.L_dollar);
-  for (i = 1; i < OCB_L_TABLE_SIZE; i++)
-    double_block_cpy (c->u_mode.ocb.L[i], c->u_mode.ocb.L[i-1]);
-
   /* Prepare the nonce.  */
-  memset (ktop, 0, (OCB_BLOCK_LEN - noncelen));
+  memset (ktop, 0, OCB_BLOCK_LEN);
   buf_cpy (ktop + (OCB_BLOCK_LEN - noncelen), nonce, noncelen);
   ktop[0] = ((c->u_mode.ocb.taglen * 8) % 128) << 1;
   ktop[OCB_BLOCK_LEN - noncelen - 1] |= 1;
@@ -181,11 +192,11 @@ _gcry_cipher_ocb_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce,
   nburn = c->spec->encrypt (&c->context.c, ktop, ktop);
   burn = nburn > burn ? nburn : burn;
   /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */
-  buf_cpy (stretch, ktop, OCB_BLOCK_LEN);
-  buf_xor (stretch + OCB_BLOCK_LEN, ktop, ktop + 1, 8);
+  cipher_block_cpy (stretch, ktop, OCB_BLOCK_LEN);
+  cipher_block_xor (stretch + OCB_BLOCK_LEN, ktop, ktop + 1, 8);
   /* Offset_0 = Stretch[1+bottom..128+bottom]
      (We use the IV field to store the offset) */
-  bit_copy (c->u_iv.iv, stretch, bottom, OCB_BLOCK_LEN);
+  bit_copy (c->u_iv.iv, stretch, bottom);
   c->marks.iv = 1;
 
   /* Checksum_0 = zeros(128)
@@ -238,6 +249,7 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
   unsigned char l_tmp[OCB_BLOCK_LEN];
   unsigned int burn = 0;
   unsigned int nburn;
+  size_t n;
 
   /* Check that a nonce and thus a key has been set and that we have
      not yet computed the tag.  We also return an error if the aad has
@@ -252,9 +264,15 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
   /* Process remaining data from the last call first.  */
   if (c->u_mode.ocb.aad_nleftover)
     {
-      for (; abuflen && c->u_mode.ocb.aad_nleftover < OCB_BLOCK_LEN;
-           abuf++, abuflen--)
-        c->u_mode.ocb.aad_leftover[c->u_mode.ocb.aad_nleftover++] = *abuf;
+      n = abuflen;
+      if (n > OCB_BLOCK_LEN - c->u_mode.ocb.aad_nleftover)
+       n = OCB_BLOCK_LEN - c->u_mode.ocb.aad_nleftover;
+
+      buf_cpy (&c->u_mode.ocb.aad_leftover[c->u_mode.ocb.aad_nleftover],
+              abuf, n);
+      c->u_mode.ocb.aad_nleftover += n;
+      abuf += n;
+      abuflen -= n;
 
       if (c->u_mode.ocb.aad_nleftover == OCB_BLOCK_LEN)
         {
@@ -267,18 +285,18 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
             }
           else
             {
-              buf_cpy (l_tmp, ocb_get_l (c, c->u_mode.ocb.aad_nblocks),
-                       OCB_BLOCK_LEN);
+              cipher_block_cpy (l_tmp, ocb_get_l (c, c->u_mode.ocb.aad_nblocks),
+                                OCB_BLOCK_LEN);
             }
 
           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-          buf_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN);
           /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
-          buf_xor (l_tmp, c->u_mode.ocb.aad_offset,
-                   c->u_mode.ocb.aad_leftover, OCB_BLOCK_LEN);
+          cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset,
+                            c->u_mode.ocb.aad_leftover, OCB_BLOCK_LEN);
           nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp);
           burn = nburn > burn ? nburn : burn;
-          buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
 
           c->u_mode.ocb.aad_nleftover = 0;
         }
@@ -309,12 +327,13 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
           ocb_get_L_big(c, c->u_mode.ocb.aad_nblocks, l_tmp);
 
           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-          buf_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN);
           /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
-          buf_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, OCB_BLOCK_LEN);
+          cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf,
+                            OCB_BLOCK_LEN);
           nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp);
           burn = nburn > burn ? nburn : burn;
-          buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
 
           abuf += OCB_BLOCK_LEN;
           abuflen -= OCB_BLOCK_LEN;
@@ -349,14 +368,15 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
           gcry_assert(c->u_mode.ocb.aad_nblocks & table_size_mask);
 
           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-          buf_xor_1 (c->u_mode.ocb.aad_offset,
-                     ocb_get_l (c, c->u_mode.ocb.aad_nblocks),
-                     OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_mode.ocb.aad_offset,
+                              ocb_get_l (c, c->u_mode.ocb.aad_nblocks),
+                              OCB_BLOCK_LEN);
           /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
-          buf_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, OCB_BLOCK_LEN);
+          cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf,
+                            OCB_BLOCK_LEN);
           nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp);
           burn = nburn > burn ? nburn : burn;
-          buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
 
           abuf += OCB_BLOCK_LEN;
           abuflen -= OCB_BLOCK_LEN;
@@ -365,9 +385,19 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
     }
 
   /* Store away the remaining data.  */
-  for (; abuflen && c->u_mode.ocb.aad_nleftover < OCB_BLOCK_LEN;
-       abuf++, abuflen--)
-    c->u_mode.ocb.aad_leftover[c->u_mode.ocb.aad_nleftover++] = *abuf;
+  if (abuflen)
+    {
+      n = abuflen;
+      if (n > OCB_BLOCK_LEN - c->u_mode.ocb.aad_nleftover)
+       n = OCB_BLOCK_LEN - c->u_mode.ocb.aad_nleftover;
+
+      buf_cpy (&c->u_mode.ocb.aad_leftover[c->u_mode.ocb.aad_nleftover],
+              abuf, n);
+      c->u_mode.ocb.aad_nleftover += n;
+      abuf += n;
+      abuflen -= n;
+    }
+
   gcry_assert (!abuflen);
 
   if (burn > 0)
@@ -397,18 +427,18 @@ ocb_aad_finalize (gcry_cipher_hd_t c)
   if (c->u_mode.ocb.aad_nleftover)
     {
       /* Offset_* = Offset_m xor L_*  */
-      buf_xor_1 (c->u_mode.ocb.aad_offset,
-                 c->u_mode.ocb.L_star, OCB_BLOCK_LEN);
+      cipher_block_xor_1 (c->u_mode.ocb.aad_offset,
+                          c->u_mode.ocb.L_star, OCB_BLOCK_LEN);
       /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_*  */
       buf_cpy (l_tmp, c->u_mode.ocb.aad_leftover, c->u_mode.ocb.aad_nleftover);
       memset (l_tmp + c->u_mode.ocb.aad_nleftover, 0,
               OCB_BLOCK_LEN - c->u_mode.ocb.aad_nleftover);
       l_tmp[c->u_mode.ocb.aad_nleftover] = 0x80;
-      buf_xor_1 (l_tmp, c->u_mode.ocb.aad_offset, OCB_BLOCK_LEN);
+      cipher_block_xor_1 (l_tmp, c->u_mode.ocb.aad_offset, OCB_BLOCK_LEN);
       /* Sum = Sum_m xor ENCIPHER(K, CipherInput)  */
       nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp);
       burn = nburn > burn ? nburn : burn;
-      buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
+      cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN);
 
       c->u_mode.ocb.aad_nleftover = 0;
     }
@@ -431,7 +461,7 @@ ocb_checksum (unsigned char *chksum, const unsigned char *plainbuf,
   while (nblks > 0)
     {
       /* Checksum_i = Checksum_{i-1} xor P_i  */
-      buf_xor_1(chksum, plainbuf, OCB_BLOCK_LEN);
+      cipher_block_xor_1(chksum, plainbuf, OCB_BLOCK_LEN);
 
       plainbuf += OCB_BLOCK_LEN;
       nblks--;
@@ -491,12 +521,12 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt,
             }
 
           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-          buf_xor_1 (c->u_iv.iv, l_tmp, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_iv.iv, l_tmp, OCB_BLOCK_LEN);
           /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
-          buf_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN);
+          cipher_block_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN);
           nburn = crypt_fn (&c->context.c, outbuf, outbuf);
           burn = nburn > burn ? nburn : burn;
-          buf_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN);
 
           if (!encrypt)
             {
@@ -517,6 +547,12 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt,
 
       nblks = nblks < nmaxblks ? nblks : nmaxblks;
 
+      /* Since checksum xoring is done before/after encryption/decryption,
+       process input in 24KiB chunks to keep data loaded in L1 cache for
+       checksumming. */
+      if (nblks > 24 * 1024 / OCB_BLOCK_LEN)
+       nblks = 24 * 1024 / OCB_BLOCK_LEN;
+
       /* Use a bulk method if available.  */
       if (nblks && c->bulk.ocb_crypt)
         {
@@ -551,14 +587,14 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt,
               gcry_assert(c->u_mode.ocb.data_nblocks & table_size_mask);
 
               /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-              buf_xor_1 (c->u_iv.iv,
-                         ocb_get_l (c, c->u_mode.ocb.data_nblocks),
-                         OCB_BLOCK_LEN);
+              cipher_block_xor_1 (c->u_iv.iv,
+                                  ocb_get_l (c, c->u_mode.ocb.data_nblocks),
+                                  OCB_BLOCK_LEN);
               /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
-              buf_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN);
+              cipher_block_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN);
               nburn = crypt_fn (&c->context.c, outbuf, outbuf);
               burn = nburn > burn ? nburn : burn;
-              buf_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN);
+              cipher_block_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN);
 
               inbuf += OCB_BLOCK_LEN;
               inbuflen -= OCB_BLOCK_LEN;
@@ -584,7 +620,7 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt,
       unsigned char pad[OCB_BLOCK_LEN];
 
       /* Offset_* = Offset_m xor L_*  */
-      buf_xor_1 (c->u_iv.iv, c->u_mode.ocb.L_star, OCB_BLOCK_LEN);
+      cipher_block_xor_1 (c->u_iv.iv, c->u_mode.ocb.L_star, OCB_BLOCK_LEN);
       /* Pad = ENCIPHER(K, Offset_*) */
       nburn = c->spec->encrypt (&c->context.c, pad, c->u_iv.iv);
       burn = nburn > burn ? nburn : burn;
@@ -596,7 +632,7 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt,
           buf_cpy (l_tmp, inbuf, inbuflen);
           memset (l_tmp + inbuflen, 0, OCB_BLOCK_LEN - inbuflen);
           l_tmp[inbuflen] = 0x80;
-          buf_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN);
           /* C_* = P_* xor Pad[1..bitlen(P_*)] */
           buf_xor (outbuf, inbuf, pad, inbuflen);
         }
@@ -604,13 +640,13 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt,
         {
           /* P_* = C_* xor Pad[1..bitlen(C_*)] */
           /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
-          buf_cpy (l_tmp, pad, OCB_BLOCK_LEN);
+          cipher_block_cpy (l_tmp, pad, OCB_BLOCK_LEN);
           buf_cpy (l_tmp, inbuf, inbuflen);
-          buf_xor_1 (l_tmp, pad, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (l_tmp, pad, OCB_BLOCK_LEN);
           l_tmp[inbuflen] = 0x80;
           buf_cpy (outbuf, l_tmp, inbuflen);
 
-          buf_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN);
+          cipher_block_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN);
         }
     }
 
@@ -618,8 +654,10 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt,
   if (c->marks.finalize)
     {
       /* Tag = ENCIPHER(K, Checksum xor Offset xor L_$) xor HASH(K,A) */
-      buf_xor (c->u_mode.ocb.tag, c->u_ctr.ctr, c->u_iv.iv, OCB_BLOCK_LEN);
-      buf_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.L_dollar, OCB_BLOCK_LEN);
+      cipher_block_xor (c->u_mode.ocb.tag, c->u_ctr.ctr, c->u_iv.iv,
+                        OCB_BLOCK_LEN);
+      cipher_block_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.L_dollar,
+                          OCB_BLOCK_LEN);
       nburn = c->spec->encrypt (&c->context.c,
                                 c->u_mode.ocb.tag, c->u_mode.ocb.tag);
       burn = nburn > burn ? nburn : burn;
@@ -672,7 +710,8 @@ compute_tag_if_needed (gcry_cipher_hd_t c)
   if (!c->marks.tag)
     {
       ocb_aad_finalize (c);
-      buf_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.aad_sum, OCB_BLOCK_LEN);
+      cipher_block_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.aad_sum,
+                          OCB_BLOCK_LEN);
       c->marks.tag = 1;
     }
 }
index f821d1b..09db397 100644 (file)
@@ -37,14 +37,10 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
 {
   unsigned char *ivp;
   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
-  size_t blocksize = c->spec->blocksize;
+  size_t blocksize_shift = _gcry_blocksize_shift(c);
+  size_t blocksize = 1 << blocksize_shift;
   unsigned int burn, nburn;
 
-  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
-   * length, to allow better optimization of this function.  */
-  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
-    return GPG_ERR_INV_LENGTH;
-
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
 
@@ -71,16 +67,28 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
     }
 
   /* Now we can process complete blocks. */
-  while ( inbuflen >= blocksize )
+  if (c->bulk.ofb_enc)
     {
-      /* Encrypt the IV (and save the current one). */
-      nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
-      burn = nburn > burn ? nburn : burn;
-      buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
-      outbuf += blocksize;
-      inbuf += blocksize;
-      inbuflen -= blocksize;
+      size_t nblocks = inbuflen >> blocksize_shift;
+      c->bulk.ofb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
+      outbuf += nblocks << blocksize_shift;
+      inbuf  += nblocks << blocksize_shift;
+      inbuflen -= nblocks << blocksize_shift;
     }
+  else
+    {
+      while ( inbuflen >= blocksize )
+       {
+         /* Encrypt the IV (and save the current one). */
+         nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+         burn = nburn > burn ? nburn : burn;
+         cipher_block_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
+         outbuf += blocksize;
+         inbuf += blocksize;
+         inbuflen -= blocksize;
+       }
+    }
+
   if ( inbuflen )
     { /* process the remaining bytes */
       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
index a2a74e8..bb47523 100644 (file)
@@ -1,4 +1,4 @@
-/* cipher-poly1305.c  -  Poly1305 based AEAD cipher mode, RFC-7539
+/* cipher-poly1305.c  -  Poly1305 based AEAD cipher mode, RFC-8439
  * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
@@ -164,9 +164,29 @@ _gcry_cipher_poly1305_encrypt (gcry_cipher_hd_t c,
       return GPG_ERR_INV_LENGTH;
     }
 
-  c->spec->stencrypt(&c->context.c, outbuf, (byte*)inbuf, inbuflen);
+  if (LIKELY(inbuflen > 0) && LIKELY(c->spec->algo == GCRY_CIPHER_CHACHA20))
+    {
+      return _gcry_chacha20_poly1305_encrypt (c, outbuf, inbuf, inbuflen);
+    }
+
+  while (inbuflen)
+    {
+      size_t currlen = inbuflen;
+
+      /* Since checksumming is done after encryption, process input in 24KiB
+       * chunks to keep data loaded in L1 cache for checksumming. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
 
-  _gcry_poly1305_update (&c->u_mode.poly1305.ctx, outbuf, inbuflen);
+      c->spec->stencrypt(&c->context.c, outbuf, (byte*)inbuf, currlen);
+
+      _gcry_poly1305_update (&c->u_mode.poly1305.ctx, outbuf, currlen);
+
+      outbuf += currlen;
+      inbuf += currlen;
+      outbuflen -= currlen;
+      inbuflen -= currlen;
+    }
 
   return 0;
 }
@@ -202,9 +222,30 @@ _gcry_cipher_poly1305_decrypt (gcry_cipher_hd_t c,
       return GPG_ERR_INV_LENGTH;
     }
 
-  _gcry_poly1305_update (&c->u_mode.poly1305.ctx, inbuf, inbuflen);
+  if (LIKELY(inbuflen > 0) && LIKELY(c->spec->algo == GCRY_CIPHER_CHACHA20))
+    {
+      return _gcry_chacha20_poly1305_decrypt (c, outbuf, inbuf, inbuflen);
+    }
+
+  while (inbuflen)
+    {
+      size_t currlen = inbuflen;
+
+      /* Since checksumming is done before decryption, process input in 24KiB
+       * chunks to keep data loaded in L1 cache for decryption. */
+      if (currlen > 24 * 1024)
+       currlen = 24 * 1024;
+
+      _gcry_poly1305_update (&c->u_mode.poly1305.ctx, inbuf, currlen);
+
+      c->spec->stdecrypt(&c->context.c, outbuf, (byte*)inbuf, currlen);
+
+      outbuf += currlen;
+      inbuf += currlen;
+      outbuflen -= currlen;
+      inbuflen -= currlen;
+    }
 
-  c->spec->stdecrypt(&c->context.c, outbuf, (byte*)inbuf, inbuflen);
   return 0;
 }
 
index cecbab7..d7f38a4 100644 (file)
@@ -1,5 +1,5 @@
 /* cipher-selftest.c - Helper functions for bulk encryption selftests.
- * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2013,2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
@@ -27,6 +27,7 @@
 #include "cipher.h"
 #include "bufhelp.h"
 #include "cipher-selftest.h"
+#include "cipher-internal.h"
 
 #ifdef HAVE_STDINT_H
 # include <stdint.h> /* uintptr_t */
@@ -72,10 +73,10 @@ _gcry_cipher_selftest_alloc_ctx (const int context_size, unsigned char **r_mem)
 const char *
 _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey_func,
                           gcry_cipher_encrypt_t encrypt_one,
-                          gcry_cipher_bulk_cbc_dec_t bulk_cbc_dec,
                           const int nblocks, const int blocksize,
                           const int context_size)
 {
+  cipher_bulk_ops_t bulk_ops = { 0, };
   int i, offs;
   unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
   unsigned int ctx_aligned_size, memsize;
@@ -105,7 +106,7 @@ _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey_func,
   ciphertext = plaintext2 + nblocks * blocksize;
 
   /* Initialize ctx */
-  if (setkey_func (ctx, key, sizeof(key)) != GPG_ERR_NO_ERROR)
+  if (setkey_func (ctx, key, sizeof(key), &bulk_ops) != GPG_ERR_NO_ERROR)
    {
      xfree(mem);
      return "setkey failed";
@@ -123,7 +124,7 @@ _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey_func,
   memcpy (iv, ciphertext, blocksize);
 
   /* CBC decrypt.  */
-  bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, 1);
+  bulk_ops.cbc_dec (ctx, iv2, plaintext2, ciphertext, 1);
   if (memcmp (plaintext2, plaintext, blocksize))
     {
       xfree (mem);
@@ -163,7 +164,7 @@ _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey_func,
     }
 
   /* Decrypt using bulk CBC and compare result.  */
-  bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, nblocks);
+  bulk_ops.cbc_dec (ctx, iv2, plaintext2, ciphertext, nblocks);
 
   if (memcmp (plaintext2, plaintext, nblocks * blocksize))
     {
@@ -195,10 +196,10 @@ _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey_func,
 const char *
 _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey_func,
                           gcry_cipher_encrypt_t encrypt_one,
-                          gcry_cipher_bulk_cfb_dec_t bulk_cfb_dec,
                           const int nblocks, const int blocksize,
                           const int context_size)
 {
+  cipher_bulk_ops_t bulk_ops = { 0, };
   int i, offs;
   unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
   unsigned int ctx_aligned_size, memsize;
@@ -228,7 +229,7 @@ _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey_func,
   ciphertext = plaintext2 + nblocks * blocksize;
 
   /* Initialize ctx */
-  if (setkey_func (ctx, key, sizeof(key)) != GPG_ERR_NO_ERROR)
+  if (setkey_func (ctx, key, sizeof(key), &bulk_ops) != GPG_ERR_NO_ERROR)
    {
      xfree(mem);
      return "setkey failed";
@@ -245,7 +246,7 @@ _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey_func,
   buf_xor_2dst (iv, ciphertext, plaintext, blocksize);
 
   /* CFB decrypt.  */
-  bulk_cfb_dec (ctx, iv2, plaintext2, ciphertext, 1);
+  bulk_ops.cfb_dec (ctx, iv2, plaintext2, ciphertext, 1);
   if (memcmp(plaintext2, plaintext, blocksize))
     {
       xfree(mem);
@@ -284,7 +285,7 @@ _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey_func,
     }
 
   /* Decrypt using bulk CBC and compare result.  */
-  bulk_cfb_dec (ctx, iv2, plaintext2, ciphertext, nblocks);
+  bulk_ops.cfb_dec (ctx, iv2, plaintext2, ciphertext, nblocks);
 
   if (memcmp(plaintext2, plaintext, nblocks * blocksize))
     {
@@ -316,10 +317,10 @@ _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey_func,
 const char *
 _gcry_selftest_helper_ctr (const char *cipher, gcry_cipher_setkey_t setkey_func,
                           gcry_cipher_encrypt_t encrypt_one,
-                          gcry_cipher_bulk_ctr_enc_t bulk_ctr_enc,
                           const int nblocks, const int blocksize,
                           const int context_size)
 {
+  cipher_bulk_ops_t bulk_ops = { 0, };
   int i, j, offs, diff;
   unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *ciphertext2,
                 *iv, *iv2, *mem;
@@ -351,7 +352,7 @@ _gcry_selftest_helper_ctr (const char *cipher, gcry_cipher_setkey_t setkey_func,
   ciphertext2 = ciphertext + nblocks * blocksize;
 
   /* Initialize ctx */
-  if (setkey_func (ctx, key, sizeof(key)) != GPG_ERR_NO_ERROR)
+  if (setkey_func (ctx, key, sizeof(key), &bulk_ops) != GPG_ERR_NO_ERROR)
    {
      xfree(mem);
      return "setkey failed";
@@ -374,7 +375,7 @@ _gcry_selftest_helper_ctr (const char *cipher, gcry_cipher_setkey_t setkey_func,
     }
 
   memset (iv2, 0xff, blocksize);
-  bulk_ctr_enc (ctx, iv2, plaintext2, ciphertext, 1);
+  bulk_ops.ctr_enc (ctx, iv2, plaintext2, ciphertext, 1);
 
   if (memcmp (plaintext2, plaintext, blocksize))
     {
@@ -429,7 +430,7 @@ _gcry_selftest_helper_ctr (const char *cipher, gcry_cipher_setkey_t setkey_func,
         }
     }
 
-  bulk_ctr_enc (ctx, iv2, ciphertext2, plaintext2, nblocks);
+  bulk_ops.ctr_enc (ctx, iv2, ciphertext2, plaintext2, nblocks);
 
   if (memcmp (ciphertext2, ciphertext, blocksize * nblocks))
     {
@@ -482,7 +483,7 @@ _gcry_selftest_helper_ctr (const char *cipher, gcry_cipher_setkey_t setkey_func,
     iv2[0] = iv2[1] = 0;
     iv2[2] = 0x07;
 
-    bulk_ctr_enc (ctx, iv2, plaintext2, ciphertext, nblocks);
+    bulk_ops.ctr_enc (ctx, iv2, plaintext2, ciphertext, nblocks);
 
     if (memcmp (plaintext2, plaintext, blocksize * nblocks))
       {
index a435080..c3090ad 100644 (file)
@@ -1,5 +1,5 @@
 /* cipher-selftest.h - Helper functions for bulk encryption selftests.
- * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2013,2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
@@ -49,7 +49,6 @@ void *_gcry_cipher_selftest_alloc_ctx (const int context_size,
 const char *
 _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey,
                           gcry_cipher_encrypt_t encrypt_one,
-                          gcry_cipher_bulk_cbc_dec_t bulk_cbc_dec,
                           const int nblocks, const int blocksize,
                           const int context_size);
 
@@ -57,7 +56,6 @@ _gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey,
 const char *
 _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey,
                           gcry_cipher_encrypt_t encrypt_one,
-                          gcry_cipher_bulk_cfb_dec_t bulk_cfb_dec,
                           const int nblocks, const int blocksize,
                           const int context_size);
 
@@ -65,7 +63,6 @@ _gcry_selftest_helper_cfb (const char *cipher, gcry_cipher_setkey_t setkey,
 const char *
 _gcry_selftest_helper_ctr (const char *cipher, gcry_cipher_setkey_t setkey,
                           gcry_cipher_encrypt_t encrypt_one,
-                          gcry_cipher_bulk_ctr_enc_t bulk_ctr_enc,
                           const int nblocks, const int blocksize,
                           const int context_size);
 
diff --git a/cipher/cipher-siv.c b/cipher/cipher-siv.c
new file mode 100644 (file)
index 0000000..160beb4
--- /dev/null
@@ -0,0 +1,375 @@
+/* cipher-siv.c  -  SIV implementation (RFC 5297)
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+#include "bufhelp.h"
+#include "./cipher-internal.h"
+
+
+static inline void
+s2v_double (unsigned char *d)
+{
+  u64 hi, lo, mask;
+
+  hi = buf_get_be64(d + 0);
+  lo = buf_get_be64(d + 8);
+
+  mask = -(hi >> 63);
+  hi = (hi << 1) ^ (lo >> 63);
+  lo = (lo << 1) ^ (mask & 0x87);
+
+  buf_put_be64(d + 0, hi);
+  buf_put_be64(d + 8, lo);
+}
+
+
+static void
+s2v_pad (unsigned char *out, const byte *in, size_t inlen)
+{
+  static const unsigned char padding[GCRY_SIV_BLOCK_LEN] = { 0x80 };
+
+  gcry_assert(inlen < GCRY_SIV_BLOCK_LEN);
+
+  buf_cpy (out, in, inlen);
+  buf_cpy (out + inlen, padding, GCRY_SIV_BLOCK_LEN - inlen);
+}
+
+
+gcry_err_code_t
+_gcry_cipher_siv_setkey (gcry_cipher_hd_t c,
+                        const unsigned char *ctrkey, size_t ctrkeylen)
+{
+  static const unsigned char zero[GCRY_SIV_BLOCK_LEN] = { 0 };
+  gcry_err_code_t err;
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+
+  c->u_mode.siv.aad_count = 0;
+  c->u_mode.siv.dec_tag_set = 0;
+  c->marks.tag = 0;
+  c->marks.iv = 0;
+
+  /* Set CTR mode key. */
+  err = c->spec->setkey (c->u_mode.siv.ctr_context, ctrkey, ctrkeylen,
+                        &c->bulk);
+  if (err != 0)
+    return err;
+
+  /* Initialize S2V. */
+  memset (&c->u_mode.siv.s2v_cmac, 0, sizeof(c->u_mode.siv.s2v_cmac));
+  err = _gcry_cmac_generate_subkeys (c, &c->u_mode.siv.s2v_cmac);
+  if (err != 0)
+    return err;
+
+  err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, zero, GCRY_SIV_BLOCK_LEN);
+  if (err != 0)
+    return err;
+
+  err = _gcry_cmac_final (c, &c->u_mode.siv.s2v_cmac);
+  if (err != 0)
+    return err;
+
+  memcpy (c->u_mode.siv.s2v_zero_block, c->u_mode.siv.s2v_cmac.u_iv.iv,
+         GCRY_SIV_BLOCK_LEN);
+  memcpy (c->u_mode.siv.s2v_d, c->u_mode.siv.s2v_zero_block,
+         GCRY_SIV_BLOCK_LEN);
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_siv_authenticate (gcry_cipher_hd_t c,
+                               const byte *aadbuf, size_t aadbuflen)
+{
+  gcry_err_code_t err;
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (c->marks.tag)
+    return GPG_ERR_INV_STATE;
+  if (c->marks.iv)
+    return GPG_ERR_INV_STATE;
+
+  if (c->u_mode.siv.aad_count >= 126)
+    return GPG_ERR_INV_STATE; /* Too many AD vector components. */
+
+  c->u_mode.siv.aad_count++;
+
+  _gcry_cmac_reset (&c->u_mode.siv.s2v_cmac);
+
+  err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, aadbuf, aadbuflen);
+  if (err != 0)
+    return err;
+
+  err = _gcry_cmac_final (c, &c->u_mode.siv.s2v_cmac);
+  if (err != 0)
+    return err;
+
+  s2v_double (c->u_mode.siv.s2v_d);
+  cipher_block_xor_1 (c->u_mode.siv.s2v_d, c->u_mode.siv.s2v_cmac.u_iv.iv,
+                     GCRY_SIV_BLOCK_LEN);
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_siv_set_nonce (gcry_cipher_hd_t c, const byte *nonce,
+                           size_t noncelen)
+{
+  gcry_err_code_t err;
+
+  err = _gcry_cipher_siv_authenticate (c, nonce, noncelen);
+  if (err)
+    return err;
+
+  /* Nonce is the last AD before plaintext. */
+  c->marks.iv = 1;
+
+  return 0;
+}
+
+
+static gcry_err_code_t
+s2v_plaintext (gcry_cipher_hd_t c, const byte *plain, size_t plainlen)
+{
+  gcry_err_code_t err;
+
+  if (c->u_mode.siv.aad_count >= 127)
+    return GPG_ERR_INV_STATE; /* Too many AD vector components. */
+
+  _gcry_cmac_reset (&c->u_mode.siv.s2v_cmac);
+
+  if (plainlen >= GCRY_SIV_BLOCK_LEN)
+    {
+      err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, plain,
+                             plainlen - GCRY_SIV_BLOCK_LEN);
+      if (err)
+        return err;
+
+      cipher_block_xor_1 (c->u_mode.siv.s2v_d,
+                         plain + plainlen - GCRY_SIV_BLOCK_LEN,
+                         GCRY_SIV_BLOCK_LEN);
+
+      err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, c->u_mode.siv.s2v_d,
+                             GCRY_SIV_BLOCK_LEN);
+      if (err)
+        return err;
+    }
+  else
+    {
+      unsigned char pad_sn[GCRY_SIV_BLOCK_LEN];
+
+      s2v_double (c->u_mode.siv.s2v_d);
+      s2v_pad (pad_sn, plain, plainlen);
+      cipher_block_xor_1 (pad_sn, c->u_mode.siv.s2v_d, GCRY_SIV_BLOCK_LEN);
+
+      err = _gcry_cmac_write (c, &c->u_mode.siv.s2v_cmac, pad_sn,
+                             GCRY_SIV_BLOCK_LEN);
+      wipememory (pad_sn, sizeof(pad_sn));
+      if (err)
+        return err;
+    }
+
+  c->u_mode.siv.aad_count++;
+
+  return _gcry_cmac_final (c, &c->u_mode.siv.s2v_cmac);
+}
+
+
+gcry_err_code_t
+_gcry_cipher_siv_encrypt (gcry_cipher_hd_t c,
+                          byte *outbuf, size_t outbuflen,
+                          const byte *inbuf, size_t inbuflen)
+{
+  gcry_err_code_t err;
+  u64 q_lo;
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+  if (c->marks.tag)
+    return GPG_ERR_INV_STATE;
+  if (c->u_mode.siv.dec_tag_set)
+    return GPG_ERR_INV_STATE;
+
+  /* Pass plaintext to S2V. */
+  err = s2v_plaintext (c, inbuf, inbuflen);
+  if (err != 0)
+    return err;
+
+  /* Clear 31th and 63th bits. */
+  memcpy (c->u_ctr.ctr, c->u_mode.siv.s2v_cmac.u_iv.iv, GCRY_SIV_BLOCK_LEN);
+  q_lo = buf_get_be64(c->u_ctr.ctr + 8);
+  q_lo &= ~((u64)1 << 31);
+  q_lo &= ~((u64)1 << 63);
+  buf_put_be64(c->u_ctr.ctr + 8, q_lo);
+
+  /* Encrypt plaintext. */
+  err = _gcry_cipher_ctr_encrypt_ctx(c, outbuf, outbuflen, inbuf, inbuflen,
+                                    c->u_mode.siv.ctr_context);
+  if (err != 0)
+    return err;
+
+  c->marks.tag = 1;
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_siv_set_decryption_tag (gcry_cipher_hd_t c,
+                                    const byte *tag, size_t taglen)
+{
+  if (taglen != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_INV_ARG;
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (c->marks.tag)
+    return GPG_ERR_INV_STATE;
+
+  memcpy (&c->u_mode.siv.dec_tag, tag, GCRY_SIV_BLOCK_LEN);
+  c->u_mode.siv.dec_tag_set = 1;
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_siv_decrypt (gcry_cipher_hd_t c,
+                          byte *outbuf, size_t outbuflen,
+                          const byte *inbuf, size_t inbuflen)
+{
+  gcry_err_code_t err;
+  u64 q_lo;
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (outbuflen < inbuflen)
+    return GPG_ERR_BUFFER_TOO_SHORT;
+  if (c->marks.tag)
+    return GPG_ERR_INV_STATE;
+  if (!c->u_mode.siv.dec_tag_set)
+    return GPG_ERR_INV_STATE;
+
+  /* Clear 31th and 63th bits. */
+  memcpy (c->u_ctr.ctr, c->u_mode.siv.dec_tag, GCRY_SIV_BLOCK_LEN);
+  q_lo = buf_get_be64(c->u_ctr.ctr + 8);
+  q_lo &= ~((u64)1 << 31);
+  q_lo &= ~((u64)1 << 63);
+  buf_put_be64(c->u_ctr.ctr + 8, q_lo);
+
+  /* Decrypt ciphertext. */
+  err = _gcry_cipher_ctr_encrypt_ctx(c, outbuf, outbuflen, inbuf, inbuflen,
+                                    c->u_mode.siv.ctr_context);
+  if (err != 0)
+    return err;
+
+  /* Pass plaintext to S2V. */
+  err = s2v_plaintext (c, outbuf, inbuflen);
+  if (err != 0)
+    return err;
+
+  c->marks.tag = 1;
+
+  if (!buf_eq_const(c->u_mode.siv.s2v_cmac.u_iv.iv, c->u_mode.siv.dec_tag,
+                   GCRY_SIV_BLOCK_LEN))
+    {
+      wipememory (outbuf, inbuflen);
+      return GPG_ERR_CHECKSUM;
+    }
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_siv_get_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
+                          size_t outbuflen)
+{
+  gcry_err_code_t err;
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+  if (c->u_mode.siv.dec_tag_set)
+    return GPG_ERR_INV_STATE;
+
+  if (!c->marks.tag)
+    {
+      /* Finalize SIV with zero-length plaintext. */
+      err = s2v_plaintext (c, NULL, 0);
+      if (err != 0)
+        return err;
+
+      c->marks.tag = 1;
+    }
+
+  if (outbuflen > GCRY_SIV_BLOCK_LEN)
+    outbuflen = GCRY_SIV_BLOCK_LEN;
+
+  /* We already checked that OUTBUF is large enough to hold
+   * the result or has valid truncated length.  */
+  memcpy (outbuf, c->u_mode.siv.s2v_cmac.u_iv.iv, outbuflen);
+
+  return 0;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_siv_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
+                            size_t taglen)
+{
+  gcry_err_code_t err;
+  size_t n;
+
+  if (c->spec->blocksize != GCRY_SIV_BLOCK_LEN)
+    return GPG_ERR_CIPHER_ALGO;
+
+  if (!c->marks.tag)
+    {
+      /* Finalize SIV with zero-length plaintext. */
+      err = s2v_plaintext (c, NULL, 0);
+      if (err != 0)
+        return err;
+
+      c->marks.tag = 1;
+    }
+
+  n = GCRY_SIV_BLOCK_LEN;
+  if (taglen < n)
+    n = taglen;
+
+  if (!buf_eq_const(c->u_mode.siv.s2v_cmac.u_iv.iv, intag, n)
+      || GCRY_SIV_BLOCK_LEN != taglen)
+    {
+      return GPG_ERR_CHECKSUM;
+    }
+
+  return 0;
+}
index 4da89e5..0522a27 100644 (file)
@@ -93,7 +93,8 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c,
   /* Use a bulk method if available.  */
   if (nblocks && c->bulk.xts_crypt)
     {
-      c->bulk.xts_crypt (c, c->u_ctr.ctr, outbuf, inbuf, nblocks, encrypt);
+      c->bulk.xts_crypt (&c->context.c, c->u_ctr.ctr, outbuf, inbuf, nblocks,
+                        encrypt);
       inbuf  += nblocks * GCRY_XTS_BLOCK_LEN;
       outbuf += nblocks * GCRY_XTS_BLOCK_LEN;
       inbuflen -= nblocks * GCRY_XTS_BLOCK_LEN;
@@ -106,10 +107,10 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c,
   while (nblocks)
     {
       /* Xor-Encrypt/Decrypt-Xor block. */
-      buf_xor (tmp.x64, inbuf, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
+      cipher_block_xor (tmp.x64, inbuf, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
       nburn = crypt_fn (&c->context.c, tmp.x1, tmp.x1);
       burn = nburn > burn ? nburn : burn;
-      buf_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
+      cipher_block_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
 
       outbuf += GCRY_XTS_BLOCK_LEN;
       inbuf += GCRY_XTS_BLOCK_LEN;
@@ -132,10 +133,10 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c,
          xts_gfmul_byA (tmp.x1, c->u_ctr.ctr);
 
          /* Decrypt last block first. */
-         buf_xor (outbuf, inbuf, tmp.x64, GCRY_XTS_BLOCK_LEN);
+         cipher_block_xor (outbuf, inbuf, tmp.x64, GCRY_XTS_BLOCK_LEN);
          nburn = crypt_fn (&c->context.c, outbuf, outbuf);
          burn = nburn > burn ? nburn : burn;
-         buf_xor (outbuf, outbuf, tmp.x64, GCRY_XTS_BLOCK_LEN);
+         cipher_block_xor (outbuf, outbuf, tmp.x64, GCRY_XTS_BLOCK_LEN);
 
          inbuflen -= GCRY_XTS_BLOCK_LEN;
          inbuf += GCRY_XTS_BLOCK_LEN;
@@ -146,15 +147,15 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c,
       outbuf -= GCRY_XTS_BLOCK_LEN;
 
       /* Steal ciphertext from previous block. */
-      buf_cpy (tmp.x64, outbuf, GCRY_XTS_BLOCK_LEN);
+      cipher_block_cpy (tmp.x64, outbuf, GCRY_XTS_BLOCK_LEN);
       buf_cpy (tmp.x64, inbuf, inbuflen);
       buf_cpy (outbuf + GCRY_XTS_BLOCK_LEN, outbuf, inbuflen);
 
       /* Decrypt/Encrypt last block. */
-      buf_xor (tmp.x64, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
+      cipher_block_xor (tmp.x64, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
       nburn = crypt_fn (&c->context.c, tmp.x1, tmp.x1);
       burn = nburn > burn ? nburn : burn;
-      buf_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
+      cipher_block_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN);
     }
 
   /* Auto-increment data-unit sequence number */
@@ -168,3 +169,21 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c,
 
   return 0;
 }
+
+
+gcry_err_code_t
+_gcry_cipher_xts_encrypt (gcry_cipher_hd_t c,
+                          unsigned char *outbuf, size_t outbuflen,
+                          const unsigned char *inbuf, size_t inbuflen)
+{
+  return _gcry_cipher_xts_crypt (c, outbuf, outbuflen, inbuf, inbuflen, 1);
+}
+
+
+gcry_err_code_t
+_gcry_cipher_xts_decrypt (gcry_cipher_hd_t c,
+                          unsigned char *outbuf, size_t outbuflen,
+                          const unsigned char *inbuf, size_t inbuflen)
+{
+  return _gcry_cipher_xts_crypt (c, outbuf, outbuflen, inbuf, inbuflen, 0);
+}
index 9812738..d1443a6 100644 (file)
@@ -33,7 +33,7 @@
 
 /* This is the list of the default ciphers, which are included in
    libgcrypt.  */
-static gcry_cipher_spec_t *cipher_list[] =
+static gcry_cipher_spec_t * const cipher_list[] =
   {
 #if USE_BLOWFISH
      &_gcry_cipher_spec_blowfish,
@@ -74,7 +74,7 @@ static gcry_cipher_spec_t *cipher_list[] =
      &_gcry_cipher_spec_camellia192,
      &_gcry_cipher_spec_camellia256,
 #endif
-#ifdef USE_IDEA
+#if USE_IDEA
      &_gcry_cipher_spec_idea,
 #endif
 #if USE_SALSA20
@@ -83,14 +83,138 @@ static gcry_cipher_spec_t *cipher_list[] =
 #endif
 #if USE_GOST28147
      &_gcry_cipher_spec_gost28147,
+     &_gcry_cipher_spec_gost28147_mesh,
 #endif
 #if USE_CHACHA20
      &_gcry_cipher_spec_chacha20,
 #endif
+#if USE_SM4
+     &_gcry_cipher_spec_sm4,
+#endif
+    NULL
+  };
+
+/* Cipher implementations starting with index 0 (enum gcry_cipher_algos) */
+static gcry_cipher_spec_t * const cipher_list_algo0[] =
+  {
+    NULL, /* GCRY_CIPHER_NONE */
+#if USE_IDEA
+    &_gcry_cipher_spec_idea,
+#else
+    NULL,
+#endif
+#if USE_DES
+    &_gcry_cipher_spec_tripledes,
+#else
+    NULL,
+#endif
+#if USE_CAST5
+    &_gcry_cipher_spec_cast5,
+#else
+    NULL,
+#endif
+#if USE_BLOWFISH
+    &_gcry_cipher_spec_blowfish,
+#else
+    NULL,
+#endif
+    NULL, /* GCRY_CIPHER_SAFER_SK128 */
+    NULL, /* GCRY_CIPHER_DES_SK */
+#if USE_AES
+    &_gcry_cipher_spec_aes,
+    &_gcry_cipher_spec_aes192,
+    &_gcry_cipher_spec_aes256,
+#else
+    NULL,
+    NULL,
+    NULL,
+#endif
+#if USE_TWOFISH
+    &_gcry_cipher_spec_twofish
+#else
     NULL
+#endif
+  };
+
+/* Cipher implementations starting with index 301 (enum gcry_cipher_algos) */
+static gcry_cipher_spec_t * const cipher_list_algo301[] =
+  {
+#if USE_ARCFOUR
+    &_gcry_cipher_spec_arcfour,
+#else
+    NULL,
+#endif
+#if USE_DES
+    &_gcry_cipher_spec_des,
+#else
+    NULL,
+#endif
+#if USE_TWOFISH
+    &_gcry_cipher_spec_twofish128,
+#else
+    NULL,
+#endif
+#if USE_SERPENT
+    &_gcry_cipher_spec_serpent128,
+    &_gcry_cipher_spec_serpent192,
+    &_gcry_cipher_spec_serpent256,
+#else
+    NULL,
+    NULL,
+    NULL,
+#endif
+#if USE_RFC2268
+    &_gcry_cipher_spec_rfc2268_40,
+    &_gcry_cipher_spec_rfc2268_128,
+#else
+    NULL,
+    NULL,
+#endif
+#if USE_SEED
+    &_gcry_cipher_spec_seed,
+#else
+    NULL,
+#endif
+#if USE_CAMELLIA
+    &_gcry_cipher_spec_camellia128,
+    &_gcry_cipher_spec_camellia192,
+    &_gcry_cipher_spec_camellia256,
+#else
+    NULL,
+    NULL,
+    NULL,
+#endif
+#if USE_SALSA20
+    &_gcry_cipher_spec_salsa20,
+    &_gcry_cipher_spec_salsa20r12,
+#else
+    NULL,
+    NULL,
+#endif
+#if USE_GOST28147
+    &_gcry_cipher_spec_gost28147,
+#else
+    NULL,
+#endif
+#if USE_CHACHA20
+    &_gcry_cipher_spec_chacha20,
+#else
+    NULL,
+#endif
+#if USE_GOST28147
+    &_gcry_cipher_spec_gost28147_mesh,
+#else
+    NULL,
+#endif
+#if USE_SM4
+     &_gcry_cipher_spec_sm4,
+#else
+    NULL,
+#endif
   };
 
 
+static void _gcry_cipher_setup_mode_ops(gcry_cipher_hd_t c, int mode);
 
 \f
 static int
@@ -105,15 +229,19 @@ map_algo (int algo)
 static gcry_cipher_spec_t *
 spec_from_algo (int algo)
 {
-  int idx;
-  gcry_cipher_spec_t *spec;
+  gcry_cipher_spec_t *spec = NULL;
 
   algo = map_algo (algo);
 
-  for (idx = 0; (spec = cipher_list[idx]); idx++)
-    if (algo == spec->algo)
-      return spec;
-  return NULL;
+  if (algo >= 0 && algo < DIM(cipher_list_algo0))
+    spec = cipher_list_algo0[algo];
+  else if (algo >= 301 && algo < 301 + DIM(cipher_list_algo301))
+    spec = cipher_list_algo301[algo - 301];
+
+  if (spec)
+    gcry_assert (spec->algo == algo);
+
+  return spec;
 }
 
 
@@ -146,7 +274,7 @@ static gcry_cipher_spec_t *
 spec_from_oid (const char *oid)
 {
   gcry_cipher_spec_t *spec;
-  gcry_cipher_oid_spec_t *oid_specs;
+  const gcry_cipher_oid_spec_t *oid_specs;
   int idx, j;
 
   for (idx=0; (spec = cipher_list[idx]); idx++)
@@ -284,7 +412,7 @@ check_cipher_algo (int algorithm)
   gcry_cipher_spec_t *spec;
 
   spec = spec_from_algo (algorithm);
-  if (spec && !spec->flags.disabled)
+  if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()))
     return 0;
 
   return GPG_ERR_CIPHER_ALGO;
@@ -381,6 +509,8 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
     err = GPG_ERR_CIPHER_ALGO;
   else if (spec->flags.disabled)
     err = GPG_ERR_CIPHER_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    err = GPG_ERR_CIPHER_ALGO;
   else
     err = 0;
 
@@ -390,39 +520,55 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
                     | GCRY_CIPHER_SECURE
                     | GCRY_CIPHER_ENABLE_SYNC
                     | GCRY_CIPHER_CBC_CTS
-                    | GCRY_CIPHER_CBC_MAC))
-         || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)))
+                    | GCRY_CIPHER_CBC_MAC
+                     | GCRY_CIPHER_EXTENDED))
+         || ((flags & GCRY_CIPHER_CBC_CTS) && (flags & GCRY_CIPHER_CBC_MAC))))
     err = GPG_ERR_CIPHER_ALGO;
 
   /* check that a valid mode has been requested */
   if (! err)
     switch (mode)
       {
-      case GCRY_CIPHER_MODE_CCM:
-       if (spec->blocksize != GCRY_CCM_BLOCK_LEN)
+      case GCRY_CIPHER_MODE_ECB:
+      case GCRY_CIPHER_MODE_CBC:
+      case GCRY_CIPHER_MODE_CFB:
+      case GCRY_CIPHER_MODE_CFB8:
+      case GCRY_CIPHER_MODE_OFB:
+      case GCRY_CIPHER_MODE_CTR:
+      case GCRY_CIPHER_MODE_AESWRAP:
+      case GCRY_CIPHER_MODE_CMAC:
+      case GCRY_CIPHER_MODE_EAX:
+       if (!spec->encrypt || !spec->decrypt)
          err = GPG_ERR_INV_CIPHER_MODE;
+       break;
+
+      case GCRY_CIPHER_MODE_CCM:
        if (!spec->encrypt || !spec->decrypt)
          err = GPG_ERR_INV_CIPHER_MODE;
+       else if (spec->blocksize != GCRY_CCM_BLOCK_LEN)
+         err = GPG_ERR_INV_CIPHER_MODE;
        break;
 
       case GCRY_CIPHER_MODE_XTS:
-       if (spec->blocksize != GCRY_XTS_BLOCK_LEN)
-         err = GPG_ERR_INV_CIPHER_MODE;
        if (!spec->encrypt || !spec->decrypt)
          err = GPG_ERR_INV_CIPHER_MODE;
+       else if (spec->blocksize != GCRY_XTS_BLOCK_LEN)
+         err = GPG_ERR_INV_CIPHER_MODE;
        break;
 
-      case GCRY_CIPHER_MODE_ECB:
-      case GCRY_CIPHER_MODE_CBC:
-      case GCRY_CIPHER_MODE_CFB:
-      case GCRY_CIPHER_MODE_CFB8:
-      case GCRY_CIPHER_MODE_OFB:
-      case GCRY_CIPHER_MODE_CTR:
-      case GCRY_CIPHER_MODE_AESWRAP:
-      case GCRY_CIPHER_MODE_CMAC:
       case GCRY_CIPHER_MODE_GCM:
        if (!spec->encrypt || !spec->decrypt)
          err = GPG_ERR_INV_CIPHER_MODE;
+       else if (spec->blocksize != GCRY_GCM_BLOCK_LEN)
+         err = GPG_ERR_INV_CIPHER_MODE;
+       break;
+
+      case GCRY_CIPHER_MODE_SIV:
+      case GCRY_CIPHER_MODE_GCM_SIV:
+       if (!spec->encrypt || !spec->decrypt)
+         err = GPG_ERR_INV_CIPHER_MODE;
+       else if (spec->blocksize != GCRY_SIV_BLOCK_LEN)
+         err = GPG_ERR_INV_CIPHER_MODE;
        break;
 
       case GCRY_CIPHER_MODE_POLY1305:
@@ -439,7 +585,7 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
            security too much.  */
        if (!spec->encrypt || !spec->decrypt)
          err = GPG_ERR_INV_CIPHER_MODE;
-       else if (spec->blocksize != (128/8))
+       else if (spec->blocksize != GCRY_OCB_BLOCK_LEN)
          err = GPG_ERR_INV_CIPHER_MODE;
        break;
 
@@ -480,6 +626,7 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
       switch (mode)
        {
        case GCRY_CIPHER_MODE_XTS:
+       case GCRY_CIPHER_MODE_SIV:
          /* Additional cipher context for tweak. */
          size += 2 * spec->contextsize + 15;
          break;
@@ -518,79 +665,8 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
          h->mode = mode;
          h->flags = flags;
 
-          /* Setup bulk encryption routines.  */
-          switch (algo)
-            {
-#ifdef USE_AES
-            case GCRY_CIPHER_AES128:
-            case GCRY_CIPHER_AES192:
-            case GCRY_CIPHER_AES256:
-              h->bulk.cfb_enc = _gcry_aes_cfb_enc;
-              h->bulk.cfb_dec = _gcry_aes_cfb_dec;
-              h->bulk.cbc_enc = _gcry_aes_cbc_enc;
-              h->bulk.cbc_dec = _gcry_aes_cbc_dec;
-              h->bulk.ctr_enc = _gcry_aes_ctr_enc;
-              h->bulk.ocb_crypt = _gcry_aes_ocb_crypt;
-              h->bulk.ocb_auth  = _gcry_aes_ocb_auth;
-              break;
-#endif /*USE_AES*/
-#ifdef USE_BLOWFISH
-           case GCRY_CIPHER_BLOWFISH:
-              h->bulk.cfb_dec = _gcry_blowfish_cfb_dec;
-              h->bulk.cbc_dec = _gcry_blowfish_cbc_dec;
-              h->bulk.ctr_enc = _gcry_blowfish_ctr_enc;
-              break;
-#endif /*USE_BLOWFISH*/
-#ifdef USE_CAST5
-           case GCRY_CIPHER_CAST5:
-              h->bulk.cfb_dec = _gcry_cast5_cfb_dec;
-              h->bulk.cbc_dec = _gcry_cast5_cbc_dec;
-              h->bulk.ctr_enc = _gcry_cast5_ctr_enc;
-              break;
-#endif /*USE_CAMELLIA*/
-#ifdef USE_CAMELLIA
-           case GCRY_CIPHER_CAMELLIA128:
-           case GCRY_CIPHER_CAMELLIA192:
-           case GCRY_CIPHER_CAMELLIA256:
-              h->bulk.cbc_dec = _gcry_camellia_cbc_dec;
-              h->bulk.cfb_dec = _gcry_camellia_cfb_dec;
-              h->bulk.ctr_enc = _gcry_camellia_ctr_enc;
-              h->bulk.ocb_crypt = _gcry_camellia_ocb_crypt;
-              h->bulk.ocb_auth  = _gcry_camellia_ocb_auth;
-              break;
-#endif /*USE_CAMELLIA*/
-#ifdef USE_DES
-            case GCRY_CIPHER_3DES:
-              h->bulk.cbc_dec =  _gcry_3des_cbc_dec;
-              h->bulk.cfb_dec =  _gcry_3des_cfb_dec;
-              h->bulk.ctr_enc =  _gcry_3des_ctr_enc;
-              break;
-#endif /*USE_DES*/
-#ifdef USE_SERPENT
-           case GCRY_CIPHER_SERPENT128:
-           case GCRY_CIPHER_SERPENT192:
-           case GCRY_CIPHER_SERPENT256:
-              h->bulk.cbc_dec = _gcry_serpent_cbc_dec;
-              h->bulk.cfb_dec = _gcry_serpent_cfb_dec;
-              h->bulk.ctr_enc = _gcry_serpent_ctr_enc;
-              h->bulk.ocb_crypt = _gcry_serpent_ocb_crypt;
-              h->bulk.ocb_auth  = _gcry_serpent_ocb_auth;
-              break;
-#endif /*USE_SERPENT*/
-#ifdef USE_TWOFISH
-           case GCRY_CIPHER_TWOFISH:
-           case GCRY_CIPHER_TWOFISH128:
-              h->bulk.cbc_dec = _gcry_twofish_cbc_dec;
-              h->bulk.cfb_dec = _gcry_twofish_cfb_dec;
-              h->bulk.ctr_enc = _gcry_twofish_ctr_enc;
-              h->bulk.ocb_crypt = _gcry_twofish_ocb_crypt;
-              h->bulk.ocb_auth  = _gcry_twofish_ocb_auth;
-              break;
-#endif /*USE_TWOFISH*/
-
-            default:
-              break;
-            }
+          /* Setup mode routines. */
+          _gcry_cipher_setup_mode_ops(h, mode);
 
           /* Setup defaults depending on the mode.  */
           switch (mode)
@@ -603,14 +679,18 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
              tc = h->context.c + spec->contextsize * 2;
              tc += (16 - (uintptr_t)tc % 16) % 16;
              h->u_mode.xts.tweak_context = tc;
+             break;
 
+           case GCRY_CIPHER_MODE_SIV:
+             tc = h->context.c + spec->contextsize * 2;
+             tc += (16 - (uintptr_t)tc % 16) % 16;
+             h->u_mode.siv.ctr_context = tc;
              break;
 
             default:
               break;
             }
-
-       }
+        }
     }
 
   /* Done.  */
@@ -674,9 +754,16 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
            return GPG_ERR_WEAK_KEY;
        }
     }
+  else if (c->mode == GCRY_CIPHER_MODE_SIV)
+    {
+      /* SIV uses two keys. */
+      if (keylen % 2)
+       return GPG_ERR_INV_KEYLEN;
+      keylen /= 2;
+    }
 
-  rc = c->spec->setkey (&c->context.c, key, keylen);
-  if (!rc)
+  rc = c->spec->setkey (&c->context.c, key, keylen, &c->bulk);
+  if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY))
     {
       /* Duplicate initial context.  */
       memcpy ((void *) ((char *) &c->context.c + c->spec->contextsize),
@@ -687,13 +774,27 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
       switch (c->mode)
         {
         case GCRY_CIPHER_MODE_CMAC:
-          _gcry_cipher_cmac_set_subkeys (c);
+          rc = _gcry_cipher_cmac_set_subkeys (c);
+          break;
+
+        case GCRY_CIPHER_MODE_EAX:
+          rc = _gcry_cipher_eax_setkey (c);
           break;
 
         case GCRY_CIPHER_MODE_GCM:
           _gcry_cipher_gcm_setkey (c);
           break;
 
+        case GCRY_CIPHER_MODE_GCM_SIV:
+          rc = _gcry_cipher_gcm_siv_setkey (c, keylen);
+          if (rc)
+           c->marks.key = 0;
+          break;
+
+        case GCRY_CIPHER_MODE_OCB:
+          _gcry_cipher_ocb_setkey (c);
+          break;
+
         case GCRY_CIPHER_MODE_POLY1305:
           _gcry_cipher_poly1305_setkey (c);
           break;
@@ -701,8 +802,8 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
        case GCRY_CIPHER_MODE_XTS:
          /* Setup tweak cipher with second part of XTS key. */
          rc = c->spec->setkey (c->u_mode.xts.tweak_context, key + keylen,
-                               keylen);
-         if (!rc)
+                               keylen, &c->bulk);
+         if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY))
            {
              /* Duplicate initial tweak context.  */
              memcpy (c->u_mode.xts.tweak_context + c->spec->contextsize,
@@ -712,9 +813,22 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen)
            c->marks.key = 0;
          break;
 
+        case GCRY_CIPHER_MODE_SIV:
+         /* Setup CTR cipher with second part of SIV key. */
+          rc = _gcry_cipher_siv_setkey (c, key + keylen, keylen);
+         if (!rc || (c->marks.allow_weak_key && rc == GPG_ERR_WEAK_KEY))
+           {
+             /* Duplicate initial CTR context.  */
+             memcpy (c->u_mode.siv.ctr_context + c->spec->contextsize,
+                     c->u_mode.siv.ctr_context, c->spec->contextsize);
+           }
+         else
+           c->marks.key = 0;
+          break;
+
         default:
           break;
-        };
+        }
     }
   else
     c->marks.key = 0;
@@ -763,9 +877,10 @@ cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
 static void
 cipher_reset (gcry_cipher_hd_t c)
 {
-  unsigned int marks_key;
+  unsigned int marks_key, marks_allow_weak_key;
 
   marks_key = c->marks.key;
+  marks_allow_weak_key = c->marks.allow_weak_key;
 
   memcpy (&c->context.c,
          (char *) &c->context.c + c->spec->contextsize,
@@ -777,15 +892,21 @@ cipher_reset (gcry_cipher_hd_t c)
   c->unused = 0;
 
   c->marks.key = marks_key;
+  c->marks.allow_weak_key = marks_allow_weak_key;
 
   switch (c->mode)
     {
     case GCRY_CIPHER_MODE_CMAC:
-      /* Only clear 'tag' for cmac, keep subkeys. */
-      c->u_mode.cmac.tag = 0;
+      _gcry_cmac_reset(&c->u_mode.cmac);
+      break;
+
+    case GCRY_CIPHER_MODE_EAX:
+      _gcry_cmac_reset(&c->u_mode.eax.cmac_header);
+      _gcry_cmac_reset(&c->u_mode.eax.cmac_ciphertext);
       break;
 
     case GCRY_CIPHER_MODE_GCM:
+    case GCRY_CIPHER_MODE_GCM_SIV:
       /* Only clear head of u_mode, keep ghash_key and gcm_table. */
       {
         byte *u_mode_pos = (void *)&c->u_mode;
@@ -805,9 +926,29 @@ cipher_reset (gcry_cipher_hd_t c)
       break;
 
     case GCRY_CIPHER_MODE_OCB:
-      memset (&c->u_mode.ocb, 0, sizeof c->u_mode.ocb);
-      /* Setup default taglen.  */
-      c->u_mode.ocb.taglen = 16;
+      {
+       const size_t table_maxblks = 1 << OCB_L_TABLE_SIZE;
+       byte *u_mode_head_pos = (void *)&c->u_mode.ocb;
+       byte *u_mode_tail_pos = (void *)&c->u_mode.ocb.tag;
+       size_t u_mode_head_length = u_mode_tail_pos - u_mode_head_pos;
+       size_t u_mode_tail_length = sizeof(c->u_mode.ocb) - u_mode_head_length;
+
+       if (c->u_mode.ocb.aad_nblocks < table_maxblks)
+         {
+           /* Precalculated L-values are still ok after reset, no need
+            * to clear. */
+           memset (u_mode_tail_pos, 0, u_mode_tail_length);
+         }
+       else
+         {
+           /* Reinitialize L table. */
+           memset (&c->u_mode.ocb, 0, sizeof(c->u_mode.ocb));
+           _gcry_cipher_ocb_setkey (c);
+         }
+
+       /* Setup default taglen.  */
+       c->u_mode.ocb.taglen = 16;
+      }
       break;
 
     case GCRY_CIPHER_MODE_XTS:
@@ -816,6 +957,24 @@ cipher_reset (gcry_cipher_hd_t c)
              c->spec->contextsize);
       break;
 
+    case GCRY_CIPHER_MODE_SIV:
+      /* Only clear head of u_mode, keep s2v_cmac and ctr_context. */
+      {
+        byte *u_mode_pos = (void *)&c->u_mode;
+        byte *tail_pos = (void *)&c->u_mode.siv.s2v_cmac;
+        size_t u_mode_head_length = tail_pos - u_mode_pos;
+
+        memset (&c->u_mode, 0, u_mode_head_length);
+
+       memcpy (c->u_mode.siv.ctr_context,
+               c->u_mode.siv.ctr_context + c->spec->contextsize,
+               c->spec->contextsize);
+
+       memcpy (c->u_mode.siv.s2v_d, c->u_mode.siv.s2v_zero_block,
+               GCRY_SIV_BLOCK_LEN);
+      }
+      break;
+
     default:
       break; /* u_mode unused by other modes. */
     }
@@ -872,85 +1031,78 @@ do_ecb_decrypt (gcry_cipher_hd_t c,
 }
 
 
-/****************
- * Encrypt INBUF to OUTBUF with the mode selected at open.
- * inbuf and outbuf may overlap or be the same.
- * Depending on the mode some constraints apply to INBUFLEN.
- */
 static gcry_err_code_t
-cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
-               const byte *inbuf, size_t inbuflen)
+do_stream_encrypt (gcry_cipher_hd_t c,
+                unsigned char *outbuf, size_t outbuflen,
+                const unsigned char *inbuf, size_t inbuflen)
+{
+  (void)outbuflen;
+  c->spec->stencrypt (&c->context.c, outbuf, (void *)inbuf, inbuflen);
+  return 0;
+}
+
+static gcry_err_code_t
+do_stream_decrypt (gcry_cipher_hd_t c,
+                unsigned char *outbuf, size_t outbuflen,
+                const unsigned char *inbuf, size_t inbuflen)
+{
+  (void)outbuflen;
+  c->spec->stdecrypt (&c->context.c, outbuf, (void *)inbuf, inbuflen);
+  return 0;
+}
+
+
+static gcry_err_code_t
+do_encrypt_none_unknown (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
+                         const byte *inbuf, size_t inbuflen)
 {
   gcry_err_code_t rc;
 
-  if (c->mode != GCRY_CIPHER_MODE_NONE && !c->marks.key)
-    {
-      log_error ("cipher_encrypt: key not set\n");
-      return GPG_ERR_MISSING_KEY;
-    }
+  (void)outbuflen;
 
   switch (c->mode)
     {
-    case GCRY_CIPHER_MODE_ECB:
-      rc = do_ecb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_CBC:
-      rc = _gcry_cipher_cbc_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_CFB:
-      rc = _gcry_cipher_cfb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+    case GCRY_CIPHER_MODE_CMAC:
+      rc = GPG_ERR_INV_CIPHER_MODE;
       break;
 
-    case GCRY_CIPHER_MODE_CFB8:
-      rc = _gcry_cipher_cfb8_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+    case GCRY_CIPHER_MODE_NONE:
+      if (fips_mode () || !_gcry_get_debug_flag (0))
+        {
+          fips_signal_error ("cipher mode NONE used");
+          rc = GPG_ERR_INV_CIPHER_MODE;
+        }
+      else
+        {
+          if (inbuf != outbuf)
+            memmove (outbuf, inbuf, inbuflen);
+          rc = 0;
+        }
       break;
 
-    case GCRY_CIPHER_MODE_OFB:
-      rc = _gcry_cipher_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
+    default:
+      log_fatal ("cipher_encrypt: invalid mode %d\n", c->mode );
+      rc = GPG_ERR_INV_CIPHER_MODE;
       break;
+    }
 
-    case GCRY_CIPHER_MODE_CTR:
-      rc = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
+  return rc;
+}
 
-    case GCRY_CIPHER_MODE_AESWRAP:
-      rc = _gcry_cipher_aeswrap_encrypt (c, outbuf, outbuflen,
-                                         inbuf, inbuflen);
-      break;
+static gcry_err_code_t
+do_decrypt_none_unknown (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
+                         const byte *inbuf, size_t inbuflen)
+{
+  gcry_err_code_t rc;
 
-    case GCRY_CIPHER_MODE_CCM:
-      rc = _gcry_cipher_ccm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
+  (void)outbuflen;
 
+  switch (c->mode)
+    {
     case GCRY_CIPHER_MODE_CMAC:
       rc = GPG_ERR_INV_CIPHER_MODE;
       break;
 
-    case GCRY_CIPHER_MODE_GCM:
-      rc = _gcry_cipher_gcm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_POLY1305:
-      rc = _gcry_cipher_poly1305_encrypt (c, outbuf, outbuflen,
-                                         inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_OCB:
-      rc = _gcry_cipher_ocb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_XTS:
-      rc = _gcry_cipher_xts_crypt (c, outbuf, outbuflen, inbuf, inbuflen, 1);
-      break;
-
-    case GCRY_CIPHER_MODE_STREAM:
-      c->spec->stencrypt (&c->context.c,
-                          outbuf, (byte*)/*arggg*/inbuf, inbuflen);
-      rc = 0;
-      break;
-
     case GCRY_CIPHER_MODE_NONE:
       if (fips_mode () || !_gcry_get_debug_flag (0))
         {
@@ -966,7 +1118,7 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
       break;
 
     default:
-      log_fatal ("cipher_encrypt: invalid mode %d\n", c->mode );
+      log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode );
       rc = GPG_ERR_INV_CIPHER_MODE;
       break;
     }
@@ -991,7 +1143,13 @@ _gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
       inlen = outsize;
     }
 
-  rc = cipher_encrypt (h, out, outsize, in, inlen);
+  if (h->mode != GCRY_CIPHER_MODE_NONE && !h->marks.key)
+    {
+      log_error ("cipher_encrypt: key not set\n");
+      return GPG_ERR_MISSING_KEY;
+    }
+
+  rc = h->mode_ops.encrypt (h, out, outsize, in, inlen);
 
   /* Failsafe: Make sure that the plaintext will never make it into
      OUT if the encryption returned an error.  */
@@ -1002,110 +1160,10 @@ _gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
 }
 
 
-
 /****************
- * Decrypt INBUF to OUTBUF with the mode selected at open.
- * inbuf and outbuf may overlap or be the same.
- * Depending on the mode some some constraints apply to INBUFLEN.
+ * Decrypt IN and write it to OUT.  If IN is NULL, in-place encryption has
+ * been requested.
  */
-static gcry_err_code_t
-cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen,
-                const byte *inbuf, size_t inbuflen)
-{
-  gcry_err_code_t rc;
-
-  if (c->mode != GCRY_CIPHER_MODE_NONE && !c->marks.key)
-    {
-      log_error ("cipher_decrypt: key not set\n");
-      return GPG_ERR_MISSING_KEY;
-    }
-
-  switch (c->mode)
-    {
-    case GCRY_CIPHER_MODE_ECB:
-      rc = do_ecb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_CBC:
-      rc = _gcry_cipher_cbc_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_CFB:
-      rc = _gcry_cipher_cfb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_CFB8:
-      rc = _gcry_cipher_cfb8_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_OFB:
-      rc = _gcry_cipher_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_CTR:
-      rc = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_AESWRAP:
-      rc = _gcry_cipher_aeswrap_decrypt (c, outbuf, outbuflen,
-                                         inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_CCM:
-      rc = _gcry_cipher_ccm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_CMAC:
-      rc = GPG_ERR_INV_CIPHER_MODE;
-      break;
-
-    case GCRY_CIPHER_MODE_GCM:
-      rc = _gcry_cipher_gcm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_POLY1305:
-      rc = _gcry_cipher_poly1305_decrypt (c, outbuf, outbuflen,
-                                         inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_OCB:
-      rc = _gcry_cipher_ocb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen);
-      break;
-
-    case GCRY_CIPHER_MODE_XTS:
-      rc = _gcry_cipher_xts_crypt (c, outbuf, outbuflen, inbuf, inbuflen, 0);
-      break;
-
-    case GCRY_CIPHER_MODE_STREAM:
-      c->spec->stdecrypt (&c->context.c,
-                          outbuf, (byte*)/*arggg*/inbuf, inbuflen);
-      rc = 0;
-      break;
-
-    case GCRY_CIPHER_MODE_NONE:
-      if (fips_mode () || !_gcry_get_debug_flag (0))
-        {
-          fips_signal_error ("cipher mode NONE used");
-          rc = GPG_ERR_INV_CIPHER_MODE;
-        }
-      else
-        {
-          if (inbuf != outbuf)
-            memmove (outbuf, inbuf, inbuflen);
-          rc = 0;
-        }
-      break;
-
-    default:
-      log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode );
-      rc = GPG_ERR_INV_CIPHER_MODE;
-      break;
-    }
-
-  return rc;
-}
-
-
 gcry_err_code_t
 _gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
                       const void *in, size_t inlen)
@@ -1116,9 +1174,14 @@ _gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize,
       inlen = outsize;
     }
 
-  return cipher_decrypt (h, out, outsize, in, inlen);
-}
+  if (h->mode != GCRY_CIPHER_MODE_NONE && !h->marks.key)
+    {
+      log_error ("cipher_decrypt: key not set\n");
+      return GPG_ERR_MISSING_KEY;
+    }
 
+  return h->mode_ops.decrypt (h, out, outsize, in, inlen);
+}
 
 
 /****************
@@ -1149,33 +1212,10 @@ _gcry_cipher_setkey (gcry_cipher_hd_t hd, const void *key, size_t keylen)
 gcry_err_code_t
 _gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen)
 {
-  gcry_err_code_t rc = 0;
-
-  switch (hd->mode)
-    {
-      case GCRY_CIPHER_MODE_CCM:
-        rc = _gcry_cipher_ccm_set_nonce (hd, iv, ivlen);
-        break;
-
-      case GCRY_CIPHER_MODE_GCM:
-        rc =  _gcry_cipher_gcm_setiv (hd, iv, ivlen);
-        break;
-
-      case GCRY_CIPHER_MODE_POLY1305:
-        rc =  _gcry_cipher_poly1305_setiv (hd, iv, ivlen);
-        break;
-
-      case GCRY_CIPHER_MODE_OCB:
-        rc = _gcry_cipher_ocb_set_nonce (hd, iv, ivlen);
-        break;
-
-      default:
-        rc = cipher_setiv (hd, iv, ivlen);
-        break;
-    }
-  return rc;
+  return hd->mode_ops.setiv (hd, iv, ivlen);
 }
 
+
 /* Set counter for CTR mode.  (CTR,CTRLEN) must denote a buffer of
    block size length, or (NULL,0) to set the CTR to the all-zero
    block. */
@@ -1209,115 +1249,263 @@ _gcry_cipher_getctr (gcry_cipher_hd_t hd, void *ctr, size_t ctrlen)
   return 0;
 }
 
+
 gcry_err_code_t
 _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf,
                            size_t abuflen)
 {
   gcry_err_code_t rc;
 
-  switch (hd->mode)
+  if (hd->mode_ops.authenticate)
+    {
+      rc = hd->mode_ops.authenticate (hd, abuf, abuflen);
+    }
+  else
+    {
+      log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode);
+      rc = GPG_ERR_INV_CIPHER_MODE;
+    }
+
+  return rc;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen)
+{
+  gcry_err_code_t rc;
+
+  if (hd->mode_ops.get_tag)
+    {
+      rc = hd->mode_ops.get_tag (hd, outtag, taglen);
+    }
+  else
+    {
+      log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode);
+      rc = GPG_ERR_INV_CIPHER_MODE;
+    }
+
+  return rc;
+}
+
+
+gcry_err_code_t
+_gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen)
+{
+  gcry_err_code_t rc;
+
+  if (hd->mode_ops.check_tag)
     {
+      rc = hd->mode_ops.check_tag (hd, intag, taglen);
+    }
+  else
+    {
+      log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode);
+      rc = GPG_ERR_INV_CIPHER_MODE;
+    }
+
+  return rc;
+}
+
+
+
+static void
+_gcry_cipher_setup_mode_ops(gcry_cipher_hd_t c, int mode)
+{
+  /* Setup encryption and decryption routines. */
+  switch (mode)
+    {
+    case GCRY_CIPHER_MODE_STREAM:
+      c->mode_ops.encrypt = do_stream_encrypt;
+      c->mode_ops.decrypt = do_stream_decrypt;
+      break;
+
+    case GCRY_CIPHER_MODE_ECB:
+      c->mode_ops.encrypt = do_ecb_encrypt;
+      c->mode_ops.decrypt = do_ecb_decrypt;
+      break;
+
+    case GCRY_CIPHER_MODE_CBC:
+      if (!(c->flags & GCRY_CIPHER_CBC_CTS))
+        {
+          c->mode_ops.encrypt = _gcry_cipher_cbc_encrypt;
+          c->mode_ops.decrypt = _gcry_cipher_cbc_decrypt;
+        }
+      else
+        {
+          c->mode_ops.encrypt = _gcry_cipher_cbc_cts_encrypt;
+          c->mode_ops.decrypt = _gcry_cipher_cbc_cts_decrypt;
+        }
+      break;
+
+    case GCRY_CIPHER_MODE_CFB:
+      c->mode_ops.encrypt = _gcry_cipher_cfb_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_cfb_decrypt;
+      break;
+
+    case GCRY_CIPHER_MODE_CFB8:
+      c->mode_ops.encrypt = _gcry_cipher_cfb8_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_cfb8_decrypt;
+      break;
+
+    case GCRY_CIPHER_MODE_OFB:
+      c->mode_ops.encrypt = _gcry_cipher_ofb_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_ofb_encrypt;
+      break;
+
+    case GCRY_CIPHER_MODE_CTR:
+      c->mode_ops.encrypt = _gcry_cipher_ctr_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_ctr_encrypt;
+      break;
+
+    case GCRY_CIPHER_MODE_AESWRAP:
+      c->mode_ops.decrypt = _gcry_cipher_keywrap_decrypt_auto;
+      if (!(c->flags & GCRY_CIPHER_EXTENDED))
+        c->mode_ops.encrypt = _gcry_cipher_keywrap_encrypt;
+      else
+        c->mode_ops.encrypt = _gcry_cipher_keywrap_encrypt_padding;
+      break;
+
     case GCRY_CIPHER_MODE_CCM:
-      rc = _gcry_cipher_ccm_authenticate (hd, abuf, abuflen);
+      c->mode_ops.encrypt = _gcry_cipher_ccm_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_ccm_decrypt;
       break;
 
-    case GCRY_CIPHER_MODE_CMAC:
-      rc = _gcry_cipher_cmac_authenticate (hd, abuf, abuflen);
+    case GCRY_CIPHER_MODE_EAX:
+      c->mode_ops.encrypt = _gcry_cipher_eax_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_eax_decrypt;
       break;
 
     case GCRY_CIPHER_MODE_GCM:
-      rc = _gcry_cipher_gcm_authenticate (hd, abuf, abuflen);
+      c->mode_ops.encrypt = _gcry_cipher_gcm_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_gcm_decrypt;
       break;
 
     case GCRY_CIPHER_MODE_POLY1305:
-      rc = _gcry_cipher_poly1305_authenticate (hd, abuf, abuflen);
+      c->mode_ops.encrypt = _gcry_cipher_poly1305_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_poly1305_decrypt;
       break;
 
     case GCRY_CIPHER_MODE_OCB:
-      rc = _gcry_cipher_ocb_authenticate (hd, abuf, abuflen);
+      c->mode_ops.encrypt = _gcry_cipher_ocb_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_ocb_decrypt;
       break;
 
-    default:
-      log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode);
-      rc = GPG_ERR_INV_CIPHER_MODE;
+    case GCRY_CIPHER_MODE_XTS:
+      c->mode_ops.encrypt = _gcry_cipher_xts_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_xts_decrypt;
       break;
-    }
 
-  return rc;
-}
+    case GCRY_CIPHER_MODE_SIV:
+      c->mode_ops.encrypt = _gcry_cipher_siv_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_siv_decrypt;
+      break;
 
+    case GCRY_CIPHER_MODE_GCM_SIV:
+      c->mode_ops.encrypt = _gcry_cipher_gcm_siv_encrypt;
+      c->mode_ops.decrypt = _gcry_cipher_gcm_siv_decrypt;
+      break;
 
-gcry_err_code_t
-_gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen)
-{
-  gcry_err_code_t rc;
+    default:
+      c->mode_ops.encrypt = do_encrypt_none_unknown;
+      c->mode_ops.decrypt = do_decrypt_none_unknown;
+      break;
+    }
 
-  switch (hd->mode)
+  /* Setup IV setting routine. */
+  switch (mode)
     {
     case GCRY_CIPHER_MODE_CCM:
-      rc = _gcry_cipher_ccm_get_tag (hd, outtag, taglen);
+      c->mode_ops.setiv = _gcry_cipher_ccm_set_nonce;
       break;
 
-    case GCRY_CIPHER_MODE_CMAC:
-      rc = _gcry_cipher_cmac_get_tag (hd, outtag, taglen);
+    case GCRY_CIPHER_MODE_EAX:
+      c->mode_ops.setiv = _gcry_cipher_eax_set_nonce;
       break;
 
     case GCRY_CIPHER_MODE_GCM:
-      rc = _gcry_cipher_gcm_get_tag (hd, outtag, taglen);
+      c->mode_ops.setiv =  _gcry_cipher_gcm_setiv;
       break;
 
     case GCRY_CIPHER_MODE_POLY1305:
-      rc = _gcry_cipher_poly1305_get_tag (hd, outtag, taglen);
+      c->mode_ops.setiv = _gcry_cipher_poly1305_setiv;
       break;
 
     case GCRY_CIPHER_MODE_OCB:
-      rc = _gcry_cipher_ocb_get_tag (hd, outtag, taglen);
+      c->mode_ops.setiv = _gcry_cipher_ocb_set_nonce;
       break;
 
-    default:
-      log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode);
-      rc = GPG_ERR_INV_CIPHER_MODE;
+    case GCRY_CIPHER_MODE_SIV:
+      c->mode_ops.setiv = _gcry_cipher_siv_set_nonce;
       break;
-    }
 
-  return rc;
-}
+    case GCRY_CIPHER_MODE_GCM_SIV:
+      c->mode_ops.setiv = _gcry_cipher_gcm_siv_set_nonce;
+      break;
 
+    default:
+      c->mode_ops.setiv = cipher_setiv;
+      break;
+    }
 
-gcry_err_code_t
-_gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen)
-{
-  gcry_err_code_t rc;
 
-  switch (hd->mode)
+  /* Setup authentication routines for AEAD modes. */
+  switch (mode)
     {
     case GCRY_CIPHER_MODE_CCM:
-      rc = _gcry_cipher_ccm_check_tag (hd, intag, taglen);
+      c->mode_ops.authenticate = _gcry_cipher_ccm_authenticate;
+      c->mode_ops.get_tag      = _gcry_cipher_ccm_get_tag;
+      c->mode_ops.check_tag    = _gcry_cipher_ccm_check_tag;
       break;
 
     case GCRY_CIPHER_MODE_CMAC:
-      rc = _gcry_cipher_cmac_check_tag (hd, intag, taglen);
+      c->mode_ops.authenticate = _gcry_cipher_cmac_authenticate;
+      c->mode_ops.get_tag      = _gcry_cipher_cmac_get_tag;
+      c->mode_ops.check_tag    = _gcry_cipher_cmac_check_tag;
+      break;
+
+    case GCRY_CIPHER_MODE_EAX:
+      c->mode_ops.authenticate = _gcry_cipher_eax_authenticate;
+      c->mode_ops.get_tag      = _gcry_cipher_eax_get_tag;
+      c->mode_ops.check_tag    = _gcry_cipher_eax_check_tag;
       break;
 
     case GCRY_CIPHER_MODE_GCM:
-      rc = _gcry_cipher_gcm_check_tag (hd, intag, taglen);
+      c->mode_ops.authenticate = _gcry_cipher_gcm_authenticate;
+      c->mode_ops.get_tag      = _gcry_cipher_gcm_get_tag;
+      c->mode_ops.check_tag    = _gcry_cipher_gcm_check_tag;
       break;
 
     case GCRY_CIPHER_MODE_POLY1305:
-      rc = _gcry_cipher_poly1305_check_tag (hd, intag, taglen);
+      c->mode_ops.authenticate = _gcry_cipher_poly1305_authenticate;
+      c->mode_ops.get_tag      = _gcry_cipher_poly1305_get_tag;
+      c->mode_ops.check_tag    = _gcry_cipher_poly1305_check_tag;
       break;
 
     case GCRY_CIPHER_MODE_OCB:
-      rc = _gcry_cipher_ocb_check_tag (hd, intag, taglen);
+      c->mode_ops.authenticate = _gcry_cipher_ocb_authenticate;
+      c->mode_ops.get_tag      = _gcry_cipher_ocb_get_tag;
+      c->mode_ops.check_tag    = _gcry_cipher_ocb_check_tag;
+      break;
+
+    case GCRY_CIPHER_MODE_SIV:
+      c->mode_ops.authenticate = _gcry_cipher_siv_authenticate;
+      c->mode_ops.get_tag      = _gcry_cipher_siv_get_tag;
+      c->mode_ops.check_tag    = _gcry_cipher_siv_check_tag;
+      break;
+
+    case GCRY_CIPHER_MODE_GCM_SIV:
+      c->mode_ops.authenticate = _gcry_cipher_gcm_siv_authenticate;
+      c->mode_ops.get_tag      = _gcry_cipher_gcm_siv_get_tag;
+      c->mode_ops.check_tag    = _gcry_cipher_gcm_siv_check_tag;
       break;
 
     default:
-      log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode);
-      rc = GPG_ERR_INV_CIPHER_MODE;
+      c->mode_ops.authenticate = NULL;
+      c->mode_ops.get_tag      = NULL;
+      c->mode_ops.check_tag    = NULL;
       break;
     }
-
-  return rc;
 }
 
 
@@ -1386,6 +1574,20 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
       }
       break;
 
+    case GCRYCTL_SET_DECRYPTION_TAG:
+      {
+        if (!buffer)
+          return GPG_ERR_INV_ARG;
+
+        if (h->mode == GCRY_CIPHER_MODE_SIV)
+          rc = _gcry_cipher_siv_set_decryption_tag (h, buffer, buflen);
+        else if (h->mode == GCRY_CIPHER_MODE_GCM_SIV)
+          rc = _gcry_cipher_gcm_siv_set_decryption_tag (h, buffer, buflen);
+        else
+          rc = GPG_ERR_INV_CIPHER_MODE;
+      }
+      break;
+
     case GCRYCTL_SET_TAGLEN:
       if (!h || !buffer || buflen != sizeof(int) )
        return GPG_ERR_INV_ARG;
@@ -1457,6 +1659,13 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
         rc = GPG_ERR_NOT_SUPPORTED;
       break;
 
+    case GCRYCTL_SET_ALLOW_WEAK_KEY:
+      /* Expecting BUFFER to be NULL and buflen to be on/off flag (0 or 1). */
+      if (!h || buffer || buflen > 1)
+       return GPG_ERR_CIPHER_ALGO;
+      h->marks.allow_weak_key = buflen ? 1 : 0;
+      break;
+
     default:
       rc = GPG_ERR_INV_OP;
     }
@@ -1476,6 +1685,12 @@ _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
  *      BUFFER must be given as NULL.  On success the result is stored
  *      at NBYTES.  The taglen is returned in bytes.
  *
+ *  GCRYCTL_GET_KEYLEN:
+ *      Return the length of the key wrapped for AES-WRAP mode.  The
+ *      length is encoded in big-endian 4 bytes, when the key is
+ *      unwrapped with KWP.  Return 00 00 00 00, when the key is
+ *      unwrapped with KW.
+ *
  * The function returns 0 on success or an error code.
  */
 gcry_err_code_t
@@ -1500,6 +1715,10 @@ _gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
               *nbytes = h->u_mode.ccm.authlen;
               break;
 
+            case GCRY_CIPHER_MODE_EAX:
+              *nbytes = h->spec->blocksize;
+              break;
+
             case GCRY_CIPHER_MODE_GCM:
               *nbytes = GCRY_GCM_BLOCK_LEN;
               break;
@@ -1508,6 +1727,33 @@ _gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes)
               *nbytes = POLY1305_TAGLEN;
               break;
 
+            case GCRY_CIPHER_MODE_SIV:
+              *nbytes = GCRY_SIV_BLOCK_LEN;
+              break;
+
+            case GCRY_CIPHER_MODE_GCM_SIV:
+              *nbytes = GCRY_SIV_BLOCK_LEN;
+              break;
+
+            default:
+              rc = GPG_ERR_INV_CIPHER_MODE;
+              break;
+            }
+        }
+      break;
+
+    case GCRYCTL_GET_KEYLEN:
+      if (!h || !buffer || !nbytes)
+       rc = GPG_ERR_INV_ARG;
+      else
+        {
+          switch (h->mode)
+            {
+            case GCRY_CIPHER_MODE_AESWRAP:
+              *nbytes = 4;
+              memcpy (buffer, h->u_mode.wrap.plen, 4);
+              break;
+
             default:
               rc = GPG_ERR_INV_CIPHER_MODE;
               break;
@@ -1640,17 +1886,6 @@ _gcry_cipher_get_algo_blklen (int algo)
 gcry_err_code_t
 _gcry_cipher_init (void)
 {
-  if (fips_mode())
-    {
-      /* disable algorithms that are disallowed in fips */
-      int idx;
-      gcry_cipher_spec_t *spec;
-
-      for (idx = 0; (spec = cipher_list[idx]); idx++)
-        if (!spec->flags.fips)
-          spec->flags.disabled = 1;
-    }
-
   return 0;
 }
 
@@ -1664,14 +1899,17 @@ _gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report)
   gcry_cipher_spec_t *spec;
 
   spec = spec_from_algo (algo);
-  if (spec && !spec->flags.disabled && spec->selftest)
+  if (spec && !spec->flags.disabled
+      && (spec->flags.fips || !fips_mode ())
+      && spec->selftest)
     ec = spec->selftest (algo, extended, report);
   else
     {
       ec = GPG_ERR_CIPHER_ALGO;
       if (report)
         report ("cipher", algo, "module",
-                (spec && !spec->flags.disabled)?
+                spec && !spec->flags.disabled
+                && (spec->flags.fips || !fips_mode ())?
                 "no selftest available" :
                 spec? "algorithm disabled" : "algorithm not found");
     }
diff --git a/cipher/crc-armv8-aarch64-ce.S b/cipher/crc-armv8-aarch64-ce.S
new file mode 100644 (file)
index 0000000..7ac884a
--- /dev/null
@@ -0,0 +1,497 @@
+/* crc-armv8-aarch64-ce.S - ARMv8/CE PMULL accelerated CRC implementation
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "asm-common-aarch64.h"
+
+#if defined(__AARCH64EL__) && \
+    defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO)
+
+.cpu generic+simd+crypto
+
+.text
+
+
+/* Structure of crc32_consts_s */
+
+#define consts_k(idx)    ((idx) * 8)
+#define consts_my_p(idx) (consts_k(6) + (idx) * 8)
+
+/* Constants */
+
+.align 6
+.Lcrc32_constants:
+.Lcrc32_partial_fold_input_mask:
+  .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+.Lcrc32_refl_shuf_shift:
+  .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+  .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+  .byte 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+  .byte 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+.Lcrc32_shuf_shift:
+  .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+  .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+.Lcrc32_bswap_shuf:
+  .byte 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08
+  .byte 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
+  .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+  .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+
+
+/*
+ * void _gcry_crc32r_armv8_ce_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
+ *                                  const struct crc32_consts_s *consts);
+ */
+.align 3
+.globl _gcry_crc32r_armv8_ce_bulk
+ELF(.type  _gcry_crc32r_armv8_ce_bulk,%function;)
+_gcry_crc32r_armv8_ce_bulk:
+  /* input:
+   *    x0: pcrc
+   *    x1: inbuf
+   *    x2: inlen
+   *    x3: consts
+   */
+  CFI_STARTPROC()
+
+  GET_DATA_POINTER(x7, .Lcrc32_constants)
+  add x9, x3, #consts_k(5 - 1)
+  cmp x2, #128
+
+  b.lo .Lcrc32r_fold_by_one_setup
+
+  eor v4.16b, v4.16b, v4.16b
+  add x4, x3, #consts_k(1 - 1)
+  ld1 {v4.s}[0], [x0]             /* load pcrc */
+  ld1 {v0.16b-v3.16b}, [x1], #64  /* load 64 bytes of input */
+  sub x2, x2, #64
+  ld1 {v6.16b}, [x4]
+  eor v0.16b, v0.16b, v4.16b
+
+  add x4, x3, #consts_k(3 - 1)
+  add x5, x3, #consts_my_p(0)
+
+.Lcrc32r_fold_by_four:
+
+  /* Fold by 4. */
+  ld1 {v16.16b-v19.16b}, [x1], #64 /* load 64 bytes of input */
+  sub x2, x2, #64
+  pmull v20.1q, v0.1d, v6.1d
+  pmull v21.1q, v1.1d, v6.1d
+  pmull v22.1q, v2.1d, v6.1d
+  pmull v23.1q, v3.1d, v6.1d
+  cmp x2, #64
+  pmull2 v24.1q, v0.2d, v6.2d
+  pmull2 v25.1q, v1.2d, v6.2d
+  pmull2 v26.1q, v2.2d, v6.2d
+  pmull2 v27.1q, v3.2d, v6.2d
+  eor v0.16b, v20.16b, v16.16b
+  eor v1.16b, v21.16b, v17.16b
+  eor v2.16b, v22.16b, v18.16b
+  eor v3.16b, v23.16b, v19.16b
+  eor v0.16b, v0.16b, v24.16b
+  eor v1.16b, v1.16b, v25.16b
+  eor v2.16b, v2.16b, v26.16b
+  eor v3.16b, v3.16b, v27.16b
+  b.hs .Lcrc32r_fold_by_four
+
+  ld1 {v6.16b}, [x4]
+  ld1 {v5.16b}, [x5]
+
+  cmp x2, #16
+
+  /* Fold 4 to 1. */
+
+  pmull v16.1q, v0.1d, v6.1d
+  pmull2 v4.1q, v0.2d, v6.2d
+  eor v0.16b, v16.16b, v1.16b
+  eor v0.16b, v0.16b, v4.16b
+
+  pmull v16.1q, v0.1d, v6.1d
+  pmull2 v4.1q, v0.2d, v6.2d
+  eor v0.16b, v16.16b, v2.16b
+  eor v0.16b, v0.16b, v4.16b
+
+  pmull v16.1q, v0.1d, v6.1d
+  pmull2 v4.1q, v0.2d, v6.2d
+  eor v0.16b, v16.16b, v3.16b
+  eor v0.16b, v0.16b, v4.16b
+
+  b.lo .Lcrc32r_fold_by_one_done
+  b .Lcrc32r_fold_by_one
+
+.Lcrc32r_fold_by_one_setup:
+
+  eor v1.16b, v1.16b, v1.16b
+  add x4, x3, #consts_k(3 - 1)
+  add x5, x3, #consts_my_p(0)
+  sub x2, x2, #16
+  ld1 {v1.s}[0], [x0]             /* load pcrc */
+  ld1 {v0.16b}, [x1], #16         /* load 16 bytes of input */
+  cmp x2, #16
+  ld1 {v6.16b}, [x4]              /* load k3k4 */
+  ld1 {v5.16b}, [x5]              /* load my_p */
+  eor v0.16b, v0.16b, v1.16b
+  b.lo .Lcrc32r_fold_by_one_done
+
+.Lcrc32r_fold_by_one:
+  sub x2, x2, #16
+  ld1 {v2.16b}, [x1], #16         /* load 16 bytes of input */
+  pmull v3.1q, v0.1d, v6.1d
+  pmull2 v1.1q, v0.2d, v6.2d
+  cmp x2, #16
+  eor v0.16b, v3.16b, v2.16b
+  eor v0.16b, v0.16b, v1.16b
+
+  b.hs .Lcrc32r_fold_by_one
+
+.Lcrc32r_fold_by_one_done:
+
+  cmp x2, #0
+  b.eq .Lcrc32r_final_fold
+
+  /* Partial fold. */
+
+  add x4, x7, #.Lcrc32_refl_shuf_shift - .Lcrc32_constants
+  add x5, x7, #.Lcrc32_refl_shuf_shift - .Lcrc32_constants + 16
+  add x6, x7, #.Lcrc32_partial_fold_input_mask - .Lcrc32_constants
+  sub x8, x2, #16
+  add x4, x4, x2
+  add x5, x5, x2
+  add x6, x6, x2
+  add x8, x1, x8
+
+  /* Load last input and add padding zeros. */
+  ld1 {v4.16b}, [x4]
+  eor x2, x2, x2
+  ld1 {v3.16b}, [x5]
+  ld1 {v2.16b}, [x6]
+  tbl v30.16b, {v0.16b}, v4.16b
+  ld1 {v4.16b}, [x8]
+  tbl v1.16b, {v0.16b}, v3.16b
+
+  pmull v0.1q, v30.1d, v6.1d
+  and v2.16b, v2.16b, v4.16b
+  pmull2 v31.1q, v30.2d, v6.2d
+  orr v2.16b, v2.16b, v1.16b
+  eor v0.16b, v0.16b, v31.16b
+  eor v0.16b, v0.16b, v2.16b
+
+.Lcrc32r_final_fold:
+
+  /* Final fold. */
+
+  eor v2.16b, v2.16b, v2.16b      /* zero reg */
+  ld1 {v7.16b}, [x9]
+
+  /* reduce 128-bits to 96-bits */
+  ext v6.16b, v6.16b, v6.16b, #8  /* swap high and low parts */
+  mov v1.16b, v0.16b
+  pmull v0.1q, v0.1d, v6.1d
+  ext v6.16b, v5.16b, v5.16b, #8  /* swap high and low parts */
+  ext v1.16b, v1.16b, v2.16b, #8  /* high to low, high zeroed */
+  eor v3.16b, v0.16b, v1.16b
+
+  /* reduce 96-bits to 64-bits */
+  eor v1.16b, v1.16b, v1.16b
+  ext v0.16b, v3.16b, v2.16b, #4  /* [00][00][x2][x1] */
+  mov v1.s[0], v3.s[0]            /* [00][00][00][x0] */
+  eor v3.16b, v3.16b, v3.16b
+  pmull v1.1q, v1.1d, v7.1d       /* [00][00][xx][xx] */
+  eor v0.16b, v0.16b, v1.16b      /* top 64-bit are zero */
+
+  /* barrett reduction */
+  mov v3.s[1], v0.s[0]            /* [00][00][x1][00] */
+  ext v0.16b, v2.16b, v0.16b, #12 /* [??][x1][??][00] */
+  pmull v1.1q, v3.1d, v5.1d       /* [00][xx][xx][00] */
+  pmull v1.1q, v1.1d, v6.1d       /* [00][xx][xx][00] */
+  eor v0.16b, v0.16b, v1.16b
+
+  /* store CRC */
+  st1 {v0.s}[2], [x0]
+
+  ret_spec_stop
+  CFI_ENDPROC()
+ELF(.size _gcry_crc32r_armv8_ce_bulk,.-_gcry_crc32r_armv8_ce_bulk;)
+
+/*
+ * void _gcry_crc32r_armv8_ce_reduction_4 (u32 *pcrc, u32 data, u32 crc,
+ *                                         const struct crc32_consts_s *consts);
+ */
+.align 3
+.globl _gcry_crc32r_armv8_ce_reduction_4
+ELF(.type  _gcry_crc32r_armv8_ce_reduction_4,%function;)
+_gcry_crc32r_armv8_ce_reduction_4:
+  /* input:
+   *    w0: data
+   *    w1: crc
+   *    x2: crc32 constants
+   */
+  CFI_STARTPROC()
+
+  eor v0.16b, v0.16b, v0.16b
+  add x2, x2, #consts_my_p(0)
+  eor v1.16b, v1.16b, v1.16b
+  ld1 {v5.16b}, [x2]
+
+  mov v0.s[0], w0
+  pmull v0.1q, v0.1d, v5.1d     /* [00][00][xx][xx] */
+  mov v1.s[1], w1
+  mov v0.s[2], v0.s[0]          /* [00][x0][x1][x0] */
+  pmull2 v0.1q, v0.2d, v5.2d    /* [00][00][xx][xx] */
+  eor v0.16b, v0.16b, v1.16b
+
+  mov w0, v0.s[1]
+
+  ret_spec_stop
+  CFI_ENDPROC()
+ELF(.size _gcry_crc32r_armv8_ce_reduction_4,.-_gcry_crc32r_armv8_ce_reduction_4;)
+
+/*
+ * void _gcry_crc32_armv8_ce_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
+ *                                 const struct crc32_consts_s *consts);
+ */
+.align 3
+.globl _gcry_crc32_armv8_ce_bulk
+ELF(.type  _gcry_crc32_armv8_ce_bulk,%function;)
+_gcry_crc32_armv8_ce_bulk:
+  /* input:
+   *    x0: pcrc
+   *    x1: inbuf
+   *    x2: inlen
+   *    x3: consts
+   */
+  CFI_STARTPROC()
+
+  GET_DATA_POINTER(x7, .Lcrc32_constants)
+  add x4, x7, #.Lcrc32_bswap_shuf - .Lcrc32_constants
+  cmp x2, #128
+  ld1 {v7.16b}, [x4]
+
+  b.lo .Lcrc32_fold_by_one_setup
+
+  eor v4.16b, v4.16b, v4.16b
+  add x4, x3, #consts_k(1 - 1)
+  ld1 {v4.s}[0], [x0]            /* load pcrc */
+  ld1 {v0.16b-v3.16b}, [x1], #64 /* load 64 bytes of input */
+  sub x2, x2, #64
+  ld1 {v6.16b}, [x4]
+  eor v0.16b, v0.16b, v4.16b
+  ext v4.16b, v6.16b, v6.16b, #8
+  tbl v0.16b, { v0.16b }, v7.16b /* byte swap */
+  tbl v1.16b, { v1.16b }, v7.16b /* byte swap */
+  tbl v2.16b, { v2.16b }, v7.16b /* byte swap */
+  tbl v3.16b, { v3.16b }, v7.16b /* byte swap */
+
+  add x4, x3, #consts_k(3 - 1)
+  add x5, x3, #consts_my_p(0)
+
+.Lcrc32_fold_by_four:
+
+  /* Fold by 4. */
+  ld1 {v16.16b-v19.16b}, [x1], #64 /* load 64 bytes of input */
+  sub x2, x2, #64
+  tbl v16.16b, { v16.16b }, v7.16b /* byte swap */
+  tbl v17.16b, { v17.16b }, v7.16b /* byte swap */
+  tbl v18.16b, { v18.16b }, v7.16b /* byte swap */
+  tbl v19.16b, { v19.16b }, v7.16b /* byte swap */
+  cmp x2, #64
+  pmull2 v20.1q, v0.2d, v4.2d
+  pmull2 v21.1q, v1.2d, v4.2d
+  pmull2 v22.1q, v2.2d, v4.2d
+  pmull2 v23.1q, v3.2d, v4.2d
+  pmull v24.1q, v0.1d, v4.1d
+  pmull v25.1q, v1.1d, v4.1d
+  pmull v26.1q, v2.1d, v4.1d
+  pmull v27.1q, v3.1d, v4.1d
+  eor v0.16b, v20.16b, v16.16b
+  eor v1.16b, v21.16b, v17.16b
+  eor v2.16b, v22.16b, v18.16b
+  eor v3.16b, v23.16b, v19.16b
+  eor v0.16b, v0.16b, v24.16b
+  eor v1.16b, v1.16b, v25.16b
+  eor v2.16b, v2.16b, v26.16b
+  eor v3.16b, v3.16b, v27.16b
+  b.hs .Lcrc32_fold_by_four
+
+  ld1 {v6.16b}, [x4]
+  ld1 {v5.16b}, [x5]
+  ext v6.16b, v6.16b, v6.16b, #8
+  ext v5.16b, v5.16b, v5.16b, #8
+
+  cmp x2, #16
+
+  /* Fold 4 to 1. */
+
+  pmull2 v16.1q, v0.2d, v6.2d
+  pmull v4.1q, v0.1d, v6.1d
+  eor v0.16b, v16.16b, v1.16b
+  eor v0.16b, v0.16b, v4.16b
+
+  pmull2 v16.1q, v0.2d, v6.2d
+  pmull v4.1q, v0.1d, v6.1d
+  eor v0.16b, v16.16b, v2.16b
+  eor v0.16b, v0.16b, v4.16b
+
+  pmull2 v16.1q, v0.2d, v6.2d
+  pmull v4.1q, v0.1d, v6.1d
+  eor v0.16b, v16.16b, v3.16b
+  eor v0.16b, v0.16b, v4.16b
+
+  b.lo .Lcrc32_fold_by_one_done
+  b .Lcrc32_fold_by_one
+
+.Lcrc32_fold_by_one_setup:
+
+  eor v1.16b, v1.16b, v1.16b
+  add x4, x3, #consts_k(3 - 1)
+  add x5, x3, #consts_my_p(0)
+  ld1 {v1.s}[0], [x0]            /* load pcrc */
+  sub x2, x2, #16
+  ld1 {v0.16b}, [x1], #16        /* load 16 bytes of input */
+  ld1 {v6.16b}, [x4]             /* load k3k4 */
+  ld1 {v5.16b}, [x5]             /* load my_p */
+  eor v0.16b, v0.16b, v1.16b
+  cmp x2, #16
+  ext v6.16b, v6.16b, v6.16b, #8 /* swap high and low parts */
+  ext v5.16b, v5.16b, v5.16b, #8 /* swap high and low parts */
+  tbl v0.16b, { v0.16b }, v7.16b /* byte swap */
+  b.lo .Lcrc32_fold_by_one_done
+
+.Lcrc32_fold_by_one:
+  sub x2, x2, #16
+  ld1 {v2.16b}, [x1], #16        /* load 16 bytes of input */
+  pmull2 v3.1q, v0.2d, v6.2d
+  tbl v2.16b, { v2.16b }, v7.16b /* byte swap */
+  pmull v1.1q, v0.1d, v6.1d
+  cmp x2, #16
+  eor v0.16b, v3.16b, v2.16b
+  eor v0.16b, v0.16b, v1.16b
+
+  b.hs .Lcrc32_fold_by_one
+
+.Lcrc32_fold_by_one_done:
+
+  cmp x2, #0
+  b.eq .Lcrc32_final_fold
+
+  /* Partial fold. */
+
+  add x4, x7, #.Lcrc32_refl_shuf_shift - .Lcrc32_constants + 32
+  add x5, x7, #.Lcrc32_shuf_shift - .Lcrc32_constants + 16
+  add x6, x7, #.Lcrc32_partial_fold_input_mask - .Lcrc32_constants
+  sub x8, x2, #16
+  sub x4, x4, x2
+  add x5, x5, x2
+  add x6, x6, x2
+  add x8, x1, x8
+
+  /* Load last input and add padding zeros. */
+  ld1 {v4.16b}, [x4]
+  eor x2, x2, x2
+  ld1 {v3.16b}, [x5]
+  ld1 {v2.16b}, [x6]
+  tbl v30.16b, {v0.16b}, v4.16b
+  ld1 {v4.16b}, [x8]
+  tbl v1.16b, {v0.16b}, v3.16b
+  and v2.16b, v2.16b, v4.16b
+
+  pmull2 v0.1q, v30.2d, v6.2d
+  orr v2.16b, v2.16b, v1.16b
+  pmull v1.1q, v30.1d, v6.1d
+  tbl v2.16b, {v2.16b}, v7.16b   /* byte swap */
+  eor v0.16b, v0.16b, v1.16b
+  eor v0.16b, v0.16b, v2.16b
+
+.Lcrc32_final_fold:
+
+  /* Final fold. */
+
+  eor v2.16b, v2.16b, v2.16b     /* zero reg */
+
+  /* reduce 128-bits to 96-bits */
+  add x4, x3, #consts_k(4)
+  ext v3.16b, v6.16b, v6.16b, #8 /* swap high and low parts */
+  eor v6.16b, v6.16b, v6.16b
+  mov v1.16b, v0.16b
+  pmull2 v0.1q, v0.2d, v3.2d
+  ld1 {v6.d}[1], [x4]            /* load k4 */
+  ext v1.16b, v2.16b, v1.16b, #8 /* low to high, low zeroed */
+  eor v3.16b, v0.16b, v1.16b     /* bottom 32-bit are zero */
+
+  /* reduce 96-bits to 64-bits */
+  eor v0.16b, v0.16b, v0.16b
+  eor v1.16b, v1.16b, v1.16b
+  mov v0.s[1], v3.s[1]           /* [00][00][x1][00] */
+  mov v1.s[2], v3.s[3]           /* [00][x3][00][00] */
+  mov v0.s[2], v3.s[2]           /* [00][x2][x1][00] */
+  eor v3.16b, v3.16b, v3.16b
+  pmull2 v1.1q, v1.2d, v6.2d     /* [00][xx][xx][00] */
+  eor v0.16b, v0.16b, v1.16b     /* top and bottom 32-bit are zero */
+
+  /* barrett reduction */
+  mov v3.s[0], v0.s[1]           /* [00][00][00][x1] */
+  pmull2 v0.1q, v0.2d, v5.2d     /* [00][xx][xx][xx] */
+  ext v0.16b, v0.16b, v2.16b, #4 /* [00][00][xx][xx] */
+  pmull v0.1q, v0.1d, v5.1d
+  eor v0.16b, v0.16b, v3.16b
+
+  /* store CRC in input endian */
+  rev32 v0.8b, v0.8b             /* byte swap */
+  st1 {v0.s}[0], [x0]
+
+  ret_spec_stop
+  CFI_ENDPROC()
+ELF(.size _gcry_crc32_armv8_ce_bulk,.-_gcry_crc32_armv8_ce_bulk;)
+
+/*
+ * void _gcry_crc32_armv8_ce_reduction_4 (u32 *pcrc, u32 data, u32 crc,
+ *                                        const struct crc32_consts_s *consts);
+ */
+.align 3
+.globl _gcry_crc32_armv8_ce_reduction_4
+ELF(.type  _gcry_crc32_armv8_ce_reduction_4,%function;)
+_gcry_crc32_armv8_ce_reduction_4:
+  /* input:
+   *    w0: data
+   *    w1: crc
+   *    x2: crc32 constants
+   */
+  CFI_STARTPROC()
+
+  eor v0.16b, v0.16b, v0.16b
+  add x2, x2, #consts_my_p(0)
+  eor v1.16b, v1.16b, v1.16b
+  ld1 {v5.16b}, [x2]
+
+  mov v0.s[1], w0
+  pmull v0.1q, v0.1d, v5.1d     /* [00][xx][xx][00] */
+  mov v1.s[0], w1
+  pmull2 v0.1q, v0.2d, v5.2d    /* [00][00][xx][xx] */
+  eor v0.16b, v0.16b, v1.16b
+
+  rev32 v0.8b, v0.8b            /* Return in input endian */
+  mov w0, v0.s[0]
+
+  ret_spec_stop
+  CFI_ENDPROC()
+ELF(.size _gcry_crc32_armv8_ce_reduction_4,.-_gcry_crc32_armv8_ce_reduction_4;)
+
+#endif
diff --git a/cipher/crc-armv8-ce.c b/cipher/crc-armv8-ce.c
new file mode 100644 (file)
index 0000000..17e5554
--- /dev/null
@@ -0,0 +1,229 @@
+/* crc-armv8-ce.c - ARMv8-CE PMULL accelerated CRC implementation
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "g10lib.h"
+
+#include "bithelp.h"
+#include "bufhelp.h"
+
+
+#if defined(ENABLE_ARM_CRYPTO_SUPPORT) && defined(__AARCH64EL__) && \
+    defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO)
+
+
+#define ALIGNED_16 __attribute__ ((aligned (16)))
+
+
+struct u16_unaligned_s
+{
+  u16 a;
+} __attribute__((packed, aligned (1), may_alias));
+
+struct u32_unaligned_s
+{
+  u32 a;
+} __attribute__((packed, aligned (1), may_alias));
+
+
+/* Constants structure for generic reflected/non-reflected CRC32 PMULL
+ * functions. */
+struct crc32_consts_s
+{
+  /* k: { x^(32*17), x^(32*15), x^(32*5), x^(32*3), x^(32*2), 0 } mod P(x) */
+  u64 k[6];
+  /* my_p: { floor(x^64 / P(x)), P(x) } */
+  u64 my_p[2];
+};
+
+/* PMULL constants for CRC32 and CRC32RFC1510. */
+static const struct crc32_consts_s crc32_consts ALIGNED_16 =
+{
+  { /* k[6] = reverse_33bits( x^(32*y) mod P(x) ) */
+    U64_C(0x154442bd4), U64_C(0x1c6e41596), /* y = { 17, 15 } */
+    U64_C(0x1751997d0), U64_C(0x0ccaa009e), /* y = { 5, 3 } */
+    U64_C(0x163cd6124), 0                   /* y = 2 */
+  },
+  { /* my_p[2] = reverse_33bits ( { floor(x^64 / P(x)), P(x) } ) */
+    U64_C(0x1f7011641), U64_C(0x1db710641)
+  }
+};
+
+/* PMULL constants for CRC24RFC2440 (polynomial multiplied with x⁸). */
+static const struct crc32_consts_s crc24rfc2440_consts ALIGNED_16 =
+{
+  { /* k[6] = x^(32*y) mod P(x) << 32*/
+    U64_C(0x08289a00) << 32, U64_C(0x74b44a00) << 32, /* y = { 17, 15 } */
+    U64_C(0xc4b14d00) << 32, U64_C(0xfd7e0c00) << 32, /* y = { 5, 3 } */
+    U64_C(0xd9fe8c00) << 32, 0                        /* y = 2 */
+  },
+  { /* my_p[2] = { floor(x^64 / P(x)), P(x) } */
+    U64_C(0x1f845fe24), U64_C(0x1864cfb00)
+  }
+};
+
+
+u32 _gcry_crc32r_armv8_ce_reduction_4 (u32 data, u32 crc,
+                                      const struct crc32_consts_s *consts);
+void _gcry_crc32r_armv8_ce_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
+                                 const struct crc32_consts_s *consts);
+
+u32 _gcry_crc32_armv8_ce_reduction_4 (u32 data, u32 crc,
+                                     const struct crc32_consts_s *consts);
+void _gcry_crc32_armv8_ce_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
+                                const struct crc32_consts_s *consts);
+
+
+static inline void
+crc32r_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
+                    const struct crc32_consts_s *consts)
+{
+  u32 crc = *pcrc;
+  u32 data;
+
+  while (inlen >= 4)
+    {
+      data = ((const struct u32_unaligned_s *)inbuf)->a;
+      data ^= crc;
+
+      inlen -= 4;
+      inbuf += 4;
+
+      crc = _gcry_crc32r_armv8_ce_reduction_4 (data, 0, consts);
+    }
+
+  switch (inlen)
+    {
+    case 0:
+      break;
+    case 1:
+      data = inbuf[0];
+      data ^= crc;
+      data <<= 24;
+      crc >>= 8;
+      crc = _gcry_crc32r_armv8_ce_reduction_4 (data, crc, consts);
+      break;
+    case 2:
+      data = ((const struct u16_unaligned_s *)inbuf)->a;
+      data ^= crc;
+      data <<= 16;
+      crc >>= 16;
+      crc = _gcry_crc32r_armv8_ce_reduction_4 (data, crc, consts);
+      break;
+    case 3:
+      data = ((const struct u16_unaligned_s *)inbuf)->a;
+      data |= inbuf[2] << 16;
+      data ^= crc;
+      data <<= 8;
+      crc >>= 24;
+      crc = _gcry_crc32r_armv8_ce_reduction_4 (data, crc, consts);
+      break;
+    }
+
+  *pcrc = crc;
+}
+
+static inline void
+crc32_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
+                   const struct crc32_consts_s *consts)
+{
+  u32 crc = *pcrc;
+  u32 data;
+
+  while (inlen >= 4)
+    {
+      data = ((const struct u32_unaligned_s *)inbuf)->a;
+      data ^= crc;
+      data = _gcry_bswap32(data);
+
+      inlen -= 4;
+      inbuf += 4;
+
+      crc = _gcry_crc32_armv8_ce_reduction_4 (data, 0, consts);
+    }
+
+  switch (inlen)
+    {
+    case 0:
+      break;
+    case 1:
+      data = inbuf[0];
+      data ^= crc;
+      data = data & 0xffU;
+      crc = _gcry_bswap32(crc >> 8);
+      crc = _gcry_crc32_armv8_ce_reduction_4 (data, crc, consts);
+      break;
+    case 2:
+      data = ((const struct u16_unaligned_s *)inbuf)->a;
+      data ^= crc;
+      data = _gcry_bswap32(data << 16);
+      crc = _gcry_bswap32(crc >> 16);
+      crc = _gcry_crc32_armv8_ce_reduction_4 (data, crc, consts);
+      break;
+    case 3:
+      data = ((const struct u16_unaligned_s *)inbuf)->a;
+      data |= inbuf[2] << 16;
+      data ^= crc;
+      data = _gcry_bswap32(data << 8);
+      crc = crc & 0xff000000U;
+      crc = _gcry_crc32_armv8_ce_reduction_4 (data, crc, consts);
+      break;
+    }
+
+  *pcrc = crc;
+}
+
+void
+_gcry_crc32_armv8_ce_pmull (u32 *pcrc, const byte *inbuf, size_t inlen)
+{
+  const struct crc32_consts_s *consts = &crc32_consts;
+
+  if (!inlen)
+    return;
+
+  if (inlen >= 16)
+    _gcry_crc32r_armv8_ce_bulk (pcrc, inbuf, inlen, consts);
+  else
+    crc32r_less_than_16 (pcrc, inbuf, inlen, consts);
+}
+
+void
+_gcry_crc24rfc2440_armv8_ce_pmull (u32 *pcrc, const byte *inbuf, size_t inlen)
+{
+  const struct crc32_consts_s *consts = &crc24rfc2440_consts;
+
+  if (!inlen)
+    return;
+
+  /* Note: *pcrc in input endian. */
+
+  if (inlen >= 16)
+    _gcry_crc32_armv8_ce_bulk (pcrc, inbuf, inlen, consts);
+  else
+    crc32_less_than_16 (pcrc, inbuf, inlen, consts);
+}
+
+#endif
index 8ff08ec..8c8b191 100644 (file)
 /* Prevent compiler from issuing SSE instructions between asm blocks. */
 #  pragma GCC target("no-sse")
 #endif
+#if __clang__
+#  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
+#endif
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR        NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE ASM_FUNC_ATTR ALWAYS_INLINE
 
 
 #define ALIGNED_16 __attribute__ ((aligned (16)))
@@ -132,7 +142,7 @@ static const u64 crc32_merge5to7_shuf[7 - 5 + 1][2] ALIGNED_16 =
   };
 
 /* PCLMUL functions for reflected CRC32. */
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 crc32_reflected_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
                      const struct crc32_consts_s *consts)
 {
@@ -328,7 +338,7 @@ crc32_reflected_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
                );
 }
 
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 crc32_reflected_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
                              const struct crc32_consts_s *consts)
 {
@@ -477,7 +487,7 @@ crc32_reflected_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
 }
 
 /* PCLMUL functions for non-reflected CRC32. */
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 crc32_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
            const struct crc32_consts_s *consts)
 {
@@ -692,7 +702,7 @@ crc32_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
                : "eax" );
 }
 
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 crc32_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
                    const struct crc32_consts_s *consts)
 {
@@ -854,7 +864,7 @@ crc32_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
     }
 }
 
-void
+void ASM_FUNC_ATTR
 _gcry_crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen)
 {
   const struct crc32_consts_s *consts = &crc32_consts;
@@ -887,7 +897,7 @@ _gcry_crc32_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen)
 #endif
 }
 
-void
+void ASM_FUNC_ATTR
 _gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen)
 {
   const struct crc32_consts_s *consts = &crc24rfc2440_consts;
@@ -922,4 +932,8 @@ _gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf, size_t inlen)
 #endif
 }
 
+#if __clang__
+#  pragma clang attribute pop
+#endif
+
 #endif /* USE_INTEL_PCLMUL */
diff --git a/cipher/crc-ppc.c b/cipher/crc-ppc.c
new file mode 100644 (file)
index 0000000..b9a4013
--- /dev/null
@@ -0,0 +1,656 @@
+/* crc-ppc.c - POWER8 vpmsum accelerated CRC implementation
+ * Copyright (C) 2019-2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "g10lib.h"
+
+#include "bithelp.h"
+#include "bufhelp.h"
+
+
+#if defined(ENABLE_PPC_CRYPTO_SUPPORT) && \
+    defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+    defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) && \
+    __GNUC__ >= 4
+
+#include <altivec.h>
+#include "bufhelp.h"
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR          NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE   ASM_FUNC_ATTR ALWAYS_INLINE
+#define ASM_FUNC_ATTR_NOINLINE ASM_FUNC_ATTR NO_INLINE
+
+#define ALIGNED_64 __attribute__ ((aligned (64)))
+
+
+typedef vector unsigned char vector16x_u8;
+typedef vector unsigned int vector4x_u32;
+typedef vector unsigned long long vector2x_u64;
+
+
+/* Constants structure for generic reflected/non-reflected CRC32 PMULL
+ * functions. */
+struct crc32_consts_s
+{
+  /* k: { x^(32*17), x^(32*15), x^(32*5), x^(32*3), x^(32*2), 0 } mod P(x) */
+  unsigned long long k[6];
+  /* my_p: { floor(x^64 / P(x)), P(x) } */
+  unsigned long long my_p[2];
+};
+
+/* PMULL constants for CRC32 and CRC32RFC1510. */
+static const struct crc32_consts_s crc32_consts ALIGNED_64 =
+{
+  { /* k[6] = reverse_33bits( x^(32*y) mod P(x) ) */
+    U64_C(0x154442bd4), U64_C(0x1c6e41596), /* y = { 17, 15 } */
+    U64_C(0x1751997d0), U64_C(0x0ccaa009e), /* y = { 5, 3 } */
+    U64_C(0x163cd6124), 0                   /* y = 2 */
+  },
+  { /* my_p[2] = reverse_33bits ( { floor(x^64 / P(x)), P(x) } ) */
+    U64_C(0x1f7011641), U64_C(0x1db710641)
+  }
+};
+
+/* PMULL constants for CRC24RFC2440 (polynomial multiplied with x⁸). */
+static const struct crc32_consts_s crc24rfc2440_consts ALIGNED_64 =
+{
+  { /* k[6] = x^(32*y) mod P(x) << 32*/
+    U64_C(0x08289a00) << 32, U64_C(0x74b44a00) << 32, /* y = { 17, 15 } */
+    U64_C(0xc4b14d00) << 32, U64_C(0xfd7e0c00) << 32, /* y = { 5, 3 } */
+    U64_C(0xd9fe8c00) << 32, 0                        /* y = 2 */
+  },
+  { /* my_p[2] = { floor(x^64 / P(x)), P(x) } */
+    U64_C(0x1f845fe24), U64_C(0x1864cfb00)
+  }
+};
+
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+asm_vpmsumd(vector2x_u64 a, vector2x_u64 b)
+{
+  __asm__("vpmsumd %0, %1, %2"
+         : "=v" (a)
+         : "v" (a), "v" (b));
+  return a;
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+asm_swap_u64(vector2x_u64 a)
+{
+  __asm__("xxswapd %x0, %x1"
+         : "=wa" (a)
+         : "wa" (a));
+  return a;
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector4x_u32
+vec_sld_u32(vector4x_u32 a, vector4x_u32 b, unsigned int idx)
+{
+  return vec_sld (a, b, (4 * idx) & 15);
+}
+
+
+static const byte crc32_partial_fold_input_mask[16 + 16] ALIGNED_64 =
+  {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  };
+static const byte crc32_shuf_shift[3 * 16] ALIGNED_64 =
+  {
+    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+    0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+    0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+  };
+static const byte crc32_refl_shuf_shift[3 * 16] ALIGNED_64 =
+  {
+    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+    0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+  };
+static const vector16x_u8 bswap_const ALIGNED_64 =
+  { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+
+
+#define CRC_VEC_SWAP(v) ({ vector2x_u64 __vecu64 = (v); \
+                           vec_perm(__vecu64, __vecu64, bswap_const); })
+
+#ifdef WORDS_BIGENDIAN
+# define CRC_VEC_U64_DEF(lo, hi) { (hi), (lo) }
+# define CRC_VEC_U64_LOAD(offs, ptr) \
+         asm_swap_u64(asm_vec_u64_load(offs, ptr))
+# define CRC_VEC_U64_LOAD_LE(offs, ptr) \
+         CRC_VEC_SWAP(asm_vec_u64_load(offs, ptr))
+# define CRC_VEC_U64_LOAD_BE(offs, ptr) \
+         asm_vec_u64_load(offs, ptr)
+# define CRC_VEC_SWAP_TO_LE(v) CRC_VEC_SWAP(v)
+# define CRC_VEC_SWAP_TO_BE(v) (v)
+# define VEC_U64_LO 1
+# define VEC_U64_HI 0
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+asm_vec_u64_load(unsigned long offset, const void *ptr)
+{
+  vector2x_u64 vecu64;
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("lxvd2x %x0,0,%1\n\t"
+                     : "=wa" (vecu64)
+                     : "r" ((uintptr_t)ptr)
+                     : "memory");
+  else
+#endif
+    __asm__ volatile ("lxvd2x %x0,%1,%2\n\t"
+                     : "=wa" (vecu64)
+                     : "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+  return vecu64;
+}
+#else
+# define CRC_VEC_U64_DEF(lo, hi) { (lo), (hi) }
+# define CRC_VEC_U64_LOAD(offs, ptr) asm_vec_u64_load_le(offs, ptr)
+# define CRC_VEC_U64_LOAD_LE(offs, ptr) asm_vec_u64_load_le(offs, ptr)
+# define CRC_VEC_U64_LOAD_BE(offs, ptr) asm_vec_u64_load_be(offs, ptr)
+# define CRC_VEC_SWAP_TO_LE(v) (v)
+# define CRC_VEC_SWAP_TO_BE(v) CRC_VEC_SWAP(v)
+# define VEC_U64_LO 0
+# define VEC_U64_HI 1
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+asm_vec_u64_load_le(unsigned long offset, const void *ptr)
+{
+  vector2x_u64 vecu64;
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("lxvd2x %x0,0,%1\n\t"
+                     : "=wa" (vecu64)
+                     : "r" ((uintptr_t)ptr)
+                     : "memory");
+  else
+#endif
+    __asm__ volatile ("lxvd2x %x0,%1,%2\n\t"
+                     : "=wa" (vecu64)
+                     : "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+  return asm_swap_u64(vecu64);
+}
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+asm_vec_u64_load_be(unsigned int offset, const void *ptr)
+{
+  static const vector16x_u8 vec_load_le_const =
+    { ~7, ~6, ~5, ~4, ~3, ~2, ~1, ~0, ~15, ~14, ~13, ~12, ~11, ~10, ~9, ~8 };
+  vector2x_u64 vecu64;
+
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ ("lxvd2x %%vs32,0,%1\n\t"
+            "vperm %0,%%v0,%%v0,%2\n\t"
+            : "=v" (vecu64)
+            : "r" ((uintptr_t)(ptr)), "v" (vec_load_le_const)
+            : "memory", "v0");
+#endif
+  else
+    __asm__ ("lxvd2x %%vs32,%1,%2\n\t"
+            "vperm %0,%%v0,%%v0,%3\n\t"
+            : "=v" (vecu64)
+            : "r" (offset), "r" ((uintptr_t)(ptr)),
+              "v" (vec_load_le_const)
+            : "memory", "r0", "v0");
+
+  return vecu64;
+}
+#endif
+
+
+static ASM_FUNC_ATTR_INLINE void
+crc32r_ppc8_ce_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
+                    const struct crc32_consts_s *consts)
+{
+  vector4x_u32 zero = { 0, 0, 0, 0 };
+  vector2x_u64 low_64bit_mask = CRC_VEC_U64_DEF((u64)-1, 0);
+  vector2x_u64 low_32bit_mask = CRC_VEC_U64_DEF((u32)-1, 0);
+  vector2x_u64 my_p = CRC_VEC_U64_LOAD(0, &consts->my_p[0]);
+  vector2x_u64 k1k2 = CRC_VEC_U64_LOAD(0, &consts->k[1 - 1]);
+  vector2x_u64 k3k4 = CRC_VEC_U64_LOAD(0, &consts->k[3 - 1]);
+  vector2x_u64 k4lo = CRC_VEC_U64_DEF(k3k4[VEC_U64_HI], 0);
+  vector2x_u64 k5lo = CRC_VEC_U64_LOAD(0, &consts->k[5 - 1]);
+  vector2x_u64 crc = CRC_VEC_U64_DEF(*pcrc, 0);
+  vector2x_u64 crc0, crc1, crc2, crc3;
+  vector2x_u64 v0;
+
+  if (inlen >= 8 * 16)
+    {
+      crc0 = CRC_VEC_U64_LOAD_LE(0 * 16, inbuf);
+      crc0 ^= crc;
+      crc1 = CRC_VEC_U64_LOAD_LE(1 * 16, inbuf);
+      crc2 = CRC_VEC_U64_LOAD_LE(2 * 16, inbuf);
+      crc3 = CRC_VEC_U64_LOAD_LE(3 * 16, inbuf);
+
+      inbuf += 4 * 16;
+      inlen -= 4 * 16;
+
+      /* Fold by 4. */
+      while (inlen >= 4 * 16)
+       {
+         v0 = CRC_VEC_U64_LOAD_LE(0 * 16, inbuf);
+         crc0 = asm_vpmsumd(crc0, k1k2) ^ v0;
+
+         v0 = CRC_VEC_U64_LOAD_LE(1 * 16, inbuf);
+         crc1 = asm_vpmsumd(crc1, k1k2) ^ v0;
+
+         v0 = CRC_VEC_U64_LOAD_LE(2 * 16, inbuf);
+         crc2 = asm_vpmsumd(crc2, k1k2) ^ v0;
+
+         v0 = CRC_VEC_U64_LOAD_LE(3 * 16, inbuf);
+         crc3 = asm_vpmsumd(crc3, k1k2) ^ v0;
+
+         inbuf += 4 * 16;
+         inlen -= 4 * 16;
+       }
+
+      /* Fold 4 to 1. */
+      crc1 ^= asm_vpmsumd(crc0, k3k4);
+      crc2 ^= asm_vpmsumd(crc1, k3k4);
+      crc3 ^= asm_vpmsumd(crc2, k3k4);
+      crc = crc3;
+    }
+  else
+    {
+      v0 = CRC_VEC_U64_LOAD_LE(0, inbuf);
+      crc ^= v0;
+
+      inbuf += 16;
+      inlen -= 16;
+    }
+
+  /* Fold by 1. */
+  while (inlen >= 16)
+    {
+      v0 = CRC_VEC_U64_LOAD_LE(0, inbuf);
+      crc = asm_vpmsumd(k3k4, crc);
+      crc ^= v0;
+
+      inbuf += 16;
+      inlen -= 16;
+    }
+
+  /* Partial fold. */
+  if (inlen)
+    {
+      /* Load last input and add padding zeros. */
+      vector2x_u64 mask = CRC_VEC_U64_LOAD_LE(inlen, crc32_partial_fold_input_mask);
+      vector2x_u64 shl_shuf = CRC_VEC_U64_LOAD_LE(inlen, crc32_refl_shuf_shift);
+      vector2x_u64 shr_shuf = CRC_VEC_U64_LOAD_LE(inlen + 16, crc32_refl_shuf_shift);
+
+      v0 = CRC_VEC_U64_LOAD_LE(inlen - 16, inbuf);
+      v0 &= mask;
+
+      crc = CRC_VEC_SWAP_TO_LE(crc);
+      v0 |= (vector2x_u64)vec_perm((vector16x_u8)crc, (vector16x_u8)zero,
+                                  (vector16x_u8)shr_shuf);
+      crc = (vector2x_u64)vec_perm((vector16x_u8)crc, (vector16x_u8)zero,
+                                  (vector16x_u8)shl_shuf);
+      crc = asm_vpmsumd(k3k4, crc);
+      crc ^= v0;
+
+      inbuf += inlen;
+      inlen -= inlen;
+    }
+
+  /* Final fold. */
+
+  /* reduce 128-bits to 96-bits */
+  v0 = asm_swap_u64(crc);
+  v0 &= low_64bit_mask;
+  crc = asm_vpmsumd(k4lo, crc);
+  crc ^= v0;
+
+  /* reduce 96-bits to 64-bits */
+  v0 = (vector2x_u64)vec_sld_u32((vector4x_u32)crc,
+                                (vector4x_u32)crc, 3);  /* [x0][x3][x2][x1] */
+  v0 &= low_64bit_mask;                                  /* [00][00][x2][x1] */
+  crc = crc & low_32bit_mask;                            /* [00][00][00][x0] */
+  crc = v0 ^ asm_vpmsumd(k5lo, crc);                     /* [00][00][xx][xx] */
+
+  /* barrett reduction */
+  v0 = crc << 32;                                        /* [00][00][x0][00] */
+  v0 = asm_vpmsumd(my_p, v0);
+  v0 = asm_swap_u64(v0);
+  v0 = asm_vpmsumd(my_p, v0);
+  crc = (vector2x_u64)vec_sld_u32((vector4x_u32)crc,
+                                 zero, 1);              /* [00][x1][x0][00] */
+  crc ^= v0;
+
+  *pcrc = (u32)crc[VEC_U64_HI];
+}
+
+
+static ASM_FUNC_ATTR_INLINE u32
+crc32r_ppc8_ce_reduction_4 (u32 data, u32 crc,
+                           const struct crc32_consts_s *consts)
+{
+  vector4x_u32 zero = { 0, 0, 0, 0 };
+  vector2x_u64 my_p = CRC_VEC_U64_LOAD(0, &consts->my_p[0]);
+  vector2x_u64 v0 = CRC_VEC_U64_DEF((u64)data, 0);
+  v0 = asm_vpmsumd(v0, my_p);                          /* [00][00][xx][xx] */
+  v0 = (vector2x_u64)vec_sld_u32((vector4x_u32)v0,
+                                zero, 3);             /* [x0][00][00][00] */
+  v0 = (vector2x_u64)vec_sld_u32((vector4x_u32)v0,
+                                (vector4x_u32)v0, 3); /* [00][x0][00][00] */
+  v0 = asm_vpmsumd(v0, my_p);                          /* [00][00][xx][xx] */
+  return (v0[VEC_U64_LO] >> 32) ^ crc;
+}
+
+
+static ASM_FUNC_ATTR_INLINE void
+crc32r_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
+                    const struct crc32_consts_s *consts)
+{
+  u32 crc = *pcrc;
+  u32 data;
+
+  while (inlen >= 4)
+    {
+      data = buf_get_le32(inbuf);
+      data ^= crc;
+
+      inlen -= 4;
+      inbuf += 4;
+
+      crc = crc32r_ppc8_ce_reduction_4 (data, 0, consts);
+    }
+
+  switch (inlen)
+    {
+    case 0:
+      break;
+    case 1:
+      data = inbuf[0];
+      data ^= crc;
+      data <<= 24;
+      crc >>= 8;
+      crc = crc32r_ppc8_ce_reduction_4 (data, crc, consts);
+      break;
+    case 2:
+      data = inbuf[0] << 0;
+      data |= inbuf[1] << 8;
+      data ^= crc;
+      data <<= 16;
+      crc >>= 16;
+      crc = crc32r_ppc8_ce_reduction_4 (data, crc, consts);
+      break;
+    case 3:
+      data = inbuf[0] << 0;
+      data |= inbuf[1] << 8;
+      data |= inbuf[2] << 16;
+      data ^= crc;
+      data <<= 8;
+      crc >>= 24;
+      crc = crc32r_ppc8_ce_reduction_4 (data, crc, consts);
+      break;
+    }
+
+  *pcrc = crc;
+}
+
+
+static ASM_FUNC_ATTR_INLINE void
+crc32_ppc8_ce_bulk (u32 *pcrc, const byte *inbuf, size_t inlen,
+                   const struct crc32_consts_s *consts)
+{
+  vector4x_u32 zero = { 0, 0, 0, 0 };
+  vector2x_u64 low_96bit_mask = CRC_VEC_U64_DEF(~0, ~((u64)(u32)-1 << 32));
+  vector2x_u64 p_my = asm_swap_u64(CRC_VEC_U64_LOAD(0, &consts->my_p[0]));
+  vector2x_u64 p_my_lo, p_my_hi;
+  vector2x_u64 k2k1 = asm_swap_u64(CRC_VEC_U64_LOAD(0, &consts->k[1 - 1]));
+  vector2x_u64 k4k3 = asm_swap_u64(CRC_VEC_U64_LOAD(0, &consts->k[3 - 1]));
+  vector2x_u64 k4hi = CRC_VEC_U64_DEF(0, consts->k[4 - 1]);
+  vector2x_u64 k5hi = CRC_VEC_U64_DEF(0, consts->k[5 - 1]);
+  vector2x_u64 crc = CRC_VEC_U64_DEF(0, _gcry_bswap64(*pcrc));
+  vector2x_u64 crc0, crc1, crc2, crc3;
+  vector2x_u64 v0;
+
+  if (inlen >= 8 * 16)
+    {
+      crc0 = CRC_VEC_U64_LOAD_BE(0 * 16, inbuf);
+      crc0 ^= crc;
+      crc1 = CRC_VEC_U64_LOAD_BE(1 * 16, inbuf);
+      crc2 = CRC_VEC_U64_LOAD_BE(2 * 16, inbuf);
+      crc3 = CRC_VEC_U64_LOAD_BE(3 * 16, inbuf);
+
+      inbuf += 4 * 16;
+      inlen -= 4 * 16;
+
+      /* Fold by 4. */
+      while (inlen >= 4 * 16)
+       {
+         v0 = CRC_VEC_U64_LOAD_BE(0 * 16, inbuf);
+         crc0 = asm_vpmsumd(crc0, k2k1) ^ v0;
+
+         v0 = CRC_VEC_U64_LOAD_BE(1 * 16, inbuf);
+         crc1 = asm_vpmsumd(crc1, k2k1) ^ v0;
+
+         v0 = CRC_VEC_U64_LOAD_BE(2 * 16, inbuf);
+         crc2 = asm_vpmsumd(crc2, k2k1) ^ v0;
+
+         v0 = CRC_VEC_U64_LOAD_BE(3 * 16, inbuf);
+         crc3 = asm_vpmsumd(crc3, k2k1) ^ v0;
+
+         inbuf += 4 * 16;
+         inlen -= 4 * 16;
+       }
+
+      /* Fold 4 to 1. */
+      crc1 ^= asm_vpmsumd(crc0, k4k3);
+      crc2 ^= asm_vpmsumd(crc1, k4k3);
+      crc3 ^= asm_vpmsumd(crc2, k4k3);
+      crc = crc3;
+    }
+  else
+    {
+      v0 = CRC_VEC_U64_LOAD_BE(0, inbuf);
+      crc ^= v0;
+
+      inbuf += 16;
+      inlen -= 16;
+    }
+
+  /* Fold by 1. */
+  while (inlen >= 16)
+    {
+      v0 = CRC_VEC_U64_LOAD_BE(0, inbuf);
+      crc = asm_vpmsumd(k4k3, crc);
+      crc ^= v0;
+
+      inbuf += 16;
+      inlen -= 16;
+    }
+
+  /* Partial fold. */
+  if (inlen)
+    {
+      /* Load last input and add padding zeros. */
+      vector2x_u64 mask = CRC_VEC_U64_LOAD_LE(inlen, crc32_partial_fold_input_mask);
+      vector2x_u64 shl_shuf = CRC_VEC_U64_LOAD_LE(32 - inlen, crc32_refl_shuf_shift);
+      vector2x_u64 shr_shuf = CRC_VEC_U64_LOAD_LE(inlen + 16, crc32_shuf_shift);
+
+      v0 = CRC_VEC_U64_LOAD_LE(inlen - 16, inbuf);
+      v0 &= mask;
+
+      crc = CRC_VEC_SWAP_TO_LE(crc);
+      crc2 = (vector2x_u64)vec_perm((vector16x_u8)crc, (vector16x_u8)zero,
+                                   (vector16x_u8)shr_shuf);
+      v0 |= crc2;
+      v0 = CRC_VEC_SWAP(v0);
+      crc = (vector2x_u64)vec_perm((vector16x_u8)crc, (vector16x_u8)zero,
+                                  (vector16x_u8)shl_shuf);
+      crc = asm_vpmsumd(k4k3, crc);
+      crc ^= v0;
+
+      inbuf += inlen;
+      inlen -= inlen;
+    }
+
+  /* Final fold. */
+
+  /* reduce 128-bits to 96-bits */
+  v0 = (vector2x_u64)vec_sld_u32((vector4x_u32)crc,
+                                (vector4x_u32)zero, 2);
+  crc = asm_vpmsumd(k4hi, crc);
+  crc ^= v0; /* bottom 32-bit are zero */
+
+  /* reduce 96-bits to 64-bits */
+  v0 = crc & low_96bit_mask;    /* [00][x2][x1][00] */
+  crc >>= 32;                   /* [00][x3][00][x0] */
+  crc = asm_vpmsumd(k5hi, crc); /* [00][xx][xx][00] */
+  crc ^= v0;                    /* top and bottom 32-bit are zero */
+
+  /* barrett reduction */
+  p_my_hi = p_my;
+  p_my_lo = p_my;
+  p_my_hi[VEC_U64_LO] = 0;
+  p_my_lo[VEC_U64_HI] = 0;
+  v0 = crc >> 32;                                        /* [00][00][00][x1] */
+  crc = asm_vpmsumd(p_my_hi, crc);                       /* [00][xx][xx][xx] */
+  crc = (vector2x_u64)vec_sld_u32((vector4x_u32)crc,
+                                 (vector4x_u32)crc, 3); /* [x0][00][x2][x1] */
+  crc = asm_vpmsumd(p_my_lo, crc);                       /* [00][xx][xx][xx] */
+  crc ^= v0;
+
+  *pcrc = _gcry_bswap32(crc[VEC_U64_LO]);
+}
+
+
+static ASM_FUNC_ATTR_INLINE u32
+crc32_ppc8_ce_reduction_4 (u32 data, u32 crc,
+                          const struct crc32_consts_s *consts)
+{
+  vector2x_u64 my_p = CRC_VEC_U64_LOAD(0, &consts->my_p[0]);
+  vector2x_u64 v0 = CRC_VEC_U64_DEF((u64)data << 32, 0);
+  v0 = asm_vpmsumd(v0, my_p); /* [00][x1][x0][00] */
+  v0[VEC_U64_LO] = 0;         /* [00][x1][00][00] */
+  v0 = asm_vpmsumd(v0, my_p); /* [00][00][xx][xx] */
+  return _gcry_bswap32(v0[VEC_U64_LO]) ^ crc;
+}
+
+
+static ASM_FUNC_ATTR_INLINE void
+crc32_less_than_16 (u32 *pcrc, const byte *inbuf, size_t inlen,
+                   const struct crc32_consts_s *consts)
+{
+  u32 crc = *pcrc;
+  u32 data;
+
+  while (inlen >= 4)
+    {
+      data = buf_get_le32(inbuf);
+      data ^= crc;
+      data = _gcry_bswap32(data);
+
+      inlen -= 4;
+      inbuf += 4;
+
+      crc = crc32_ppc8_ce_reduction_4 (data, 0, consts);
+    }
+
+  switch (inlen)
+    {
+    case 0:
+      break;
+    case 1:
+      data = inbuf[0];
+      data ^= crc;
+      data = data & 0xffU;
+      crc = crc >> 8;
+      crc = crc32_ppc8_ce_reduction_4 (data, crc, consts);
+      break;
+    case 2:
+      data = inbuf[0] << 0;
+      data |= inbuf[1] << 8;
+      data ^= crc;
+      data = _gcry_bswap32(data << 16);
+      crc = crc >> 16;
+      crc = crc32_ppc8_ce_reduction_4 (data, crc, consts);
+      break;
+    case 3:
+      data = inbuf[0] << 0;
+      data |= inbuf[1] << 8;
+      data |= inbuf[2] << 16;
+      data ^= crc;
+      data = _gcry_bswap32(data << 8);
+      crc = crc >> 24;
+      crc = crc32_ppc8_ce_reduction_4 (data, crc, consts);
+      break;
+    }
+
+  *pcrc = crc;
+}
+
+void ASM_FUNC_ATTR
+_gcry_crc32_ppc8_vpmsum (u32 *pcrc, const byte *inbuf, size_t inlen)
+{
+  const struct crc32_consts_s *consts = &crc32_consts;
+
+  if (!inlen)
+    return;
+
+  if (inlen >= 16)
+    crc32r_ppc8_ce_bulk (pcrc, inbuf, inlen, consts);
+  else
+    crc32r_less_than_16 (pcrc, inbuf, inlen, consts);
+}
+
+void ASM_FUNC_ATTR
+_gcry_crc24rfc2440_ppc8_vpmsum (u32 *pcrc, const byte *inbuf, size_t inlen)
+{
+  const struct crc32_consts_s *consts = &crc24rfc2440_consts;
+
+  if (!inlen)
+    return;
+
+  /* Note: *pcrc in input endian. */
+
+  if (inlen >= 16)
+    crc32_ppc8_ce_bulk (pcrc, inbuf, inlen, consts);
+  else
+    crc32_less_than_16 (pcrc, inbuf, inlen, consts);
+}
+
+#endif
index a1ce50b..b38869e 100644 (file)
 # endif
 #endif /* USE_INTEL_PCLMUL */
 
+/* USE_ARM_PMULL indicates whether to compile GCM with ARMv8 PMULL code. */
+#undef USE_ARM_PMULL
+#if defined(ENABLE_ARM_CRYPTO_SUPPORT)
+# if defined(__AARCH64EL__) && \
+    defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO)
+#  define USE_ARM_PMULL 1
+# endif
+#endif /* USE_ARM_PMULL */
+
+/* USE_PPC_VPMSUM indicates whether to enable PowerPC vector
+ * accelerated code. */
+#undef USE_PPC_VPMSUM
+#ifdef ENABLE_PPC_CRYPTO_SUPPORT
+# if defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+     defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC)
+#  if __GNUC__ >= 4
+#   define USE_PPC_VPMSUM 1
+#  endif
+# endif
+#endif /* USE_PPC_VPMSUM */
+
 
 typedef struct
 {
@@ -49,6 +71,12 @@ typedef struct
 #ifdef USE_INTEL_PCLMUL
   unsigned int use_pclmul:1;           /* Intel PCLMUL shall be used.  */
 #endif
+#ifdef USE_ARM_PMULL
+  unsigned int use_pmull:1;            /* ARMv8 PMULL shall be used. */
+#endif
+#ifdef USE_PPC_VPMSUM
+  unsigned int use_vpmsum:1;           /* POWER vpmsum shall be used. */
+#endif
   byte buf[4];
 }
 CRC_CONTEXT;
@@ -61,6 +89,20 @@ void _gcry_crc24rfc2440_intel_pclmul (u32 *pcrc, const byte *inbuf,
                                      size_t inlen);
 #endif
 
+#ifdef USE_ARM_PMULL
+/*-- crc-armv8-ce.c --*/
+void _gcry_crc32_armv8_ce_pmull (u32 *pcrc, const byte *inbuf, size_t inlen);
+void _gcry_crc24rfc2440_armv8_ce_pmull (u32 *pcrc, const byte *inbuf,
+                                       size_t inlen);
+#endif
+
+#ifdef USE_PPC_VPMSUM
+/*-- crc-ppc.c --*/
+void _gcry_crc32_ppc8_vpmsum (u32 *pcrc, const byte *inbuf, size_t inlen);
+void _gcry_crc24rfc2440_ppc8_vpmsum (u32 *pcrc, const byte *inbuf,
+                                    size_t inlen);
+#endif
+
 
 /*
  * Code generated by universal_crc by Danjel McGougan
@@ -361,13 +403,20 @@ static void
 crc32_init (void *context, unsigned int flags)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
-#ifdef USE_INTEL_PCLMUL
   u32 hwf = _gcry_get_hw_features ();
 
+#ifdef USE_INTEL_PCLMUL
   ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL);
 #endif
+#ifdef USE_ARM_PMULL
+  ctx->use_pmull = (hwf & HWF_ARM_NEON) && (hwf & HWF_ARM_PMULL);
+#endif
+#ifdef USE_PPC_VPMSUM
+  ctx->use_vpmsum = !!(hwf & HWF_PPC_ARCH_2_07);
+#endif
 
   (void)flags;
+  (void)hwf;
 
   ctx->CRC = 0 ^ 0xffffffffL;
 }
@@ -386,6 +435,20 @@ crc32_write (void *context, const void *inbuf_arg, size_t inlen)
       return;
     }
 #endif
+#ifdef USE_ARM_PMULL
+  if (ctx->use_pmull)
+    {
+      _gcry_crc32_armv8_ce_pmull(&ctx->CRC, inbuf, inlen);
+      return;
+    }
+#endif
+#ifdef USE_PPC_VPMSUM
+  if (ctx->use_vpmsum)
+    {
+      _gcry_crc32_ppc8_vpmsum(&ctx->CRC, inbuf, inlen);
+      return;
+    }
+#endif
 
   if (!inbuf || !inlen)
     return;
@@ -439,13 +502,20 @@ static void
 crc32rfc1510_init (void *context, unsigned int flags)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
-#ifdef USE_INTEL_PCLMUL
   u32 hwf = _gcry_get_hw_features ();
 
+#ifdef USE_INTEL_PCLMUL
   ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL);
 #endif
+#ifdef USE_ARM_PMULL
+  ctx->use_pmull = (hwf & HWF_ARM_NEON) && (hwf & HWF_ARM_PMULL);
+#endif
+#ifdef USE_PPC_VPMSUM
+  ctx->use_vpmsum = !!(hwf & HWF_PPC_ARCH_2_07);
+#endif
 
   (void)flags;
+  (void)hwf;
 
   ctx->CRC = 0;
 }
@@ -769,12 +839,19 @@ static void
 crc24rfc2440_init (void *context, unsigned int flags)
 {
   CRC_CONTEXT *ctx = (CRC_CONTEXT *) context;
-#ifdef USE_INTEL_PCLMUL
   u32 hwf = _gcry_get_hw_features ();
 
+#ifdef USE_INTEL_PCLMUL
   ctx->use_pclmul = (hwf & HWF_INTEL_SSE4_1) && (hwf & HWF_INTEL_PCLMUL);
 #endif
+#ifdef USE_ARM_PMULL
+  ctx->use_pmull = (hwf & HWF_ARM_NEON) && (hwf & HWF_ARM_PMULL);
+#endif
+#ifdef USE_PPC_VPMSUM
+  ctx->use_vpmsum = !!(hwf & HWF_PPC_ARCH_2_07);
+#endif
 
+  (void)hwf;
   (void)flags;
 
   ctx->CRC = crc24_init();
@@ -794,6 +871,20 @@ crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen)
       return;
     }
 #endif
+#ifdef USE_ARM_PMULL
+  if (ctx->use_pmull)
+    {
+      _gcry_crc24rfc2440_armv8_ce_pmull(&ctx->CRC, inbuf, inlen);
+      return;
+    }
+#endif
+#ifdef USE_PPC_VPMSUM
+  if (ctx->use_vpmsum)
+    {
+      _gcry_crc24rfc2440_ppc8_vpmsum(&ctx->CRC, inbuf, inlen);
+      return;
+    }
+#endif
 
   if (!inbuf || !inlen)
     return;
@@ -836,26 +927,29 @@ crc24rfc2440_final (void *context)
 /* We allow the CRC algorithms even in FIPS mode because they are
    actually no cryptographic primitives.  */
 
-gcry_md_spec_t _gcry_digest_spec_crc32 =
+const 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,
     sizeof (CRC_CONTEXT)
   };
 
-gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510 =
+const 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,
     sizeof (CRC_CONTEXT)
   };
 
-gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440 =
+const 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,
     sizeof (CRC_CONTEXT)
   };
index 1b7cfba..c1bf9f2 100644 (file)
 #if defined(USE_DES) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
 
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -200,15 +190,25 @@ _gcry_3des_amd64_crypt_block:
         *      %rsi: dst
         *      %rdx: src
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
        pushq %r14;
+       CFI_PUSH(%r14);
        pushq %r15;
+       CFI_PUSH(%r15);
        pushq %rsi; /*dst*/
+       CFI_PUSH(%rsi);
 
-       leaq .L_s1 RIP, SBOXES;
+       leaq .L_s1 rRIP, SBOXES;
 
        read_block(%rdx, RL0, RR0);
        initial_permutation(RL0, RR0);
@@ -267,17 +267,26 @@ _gcry_3des_amd64_crypt_block:
        round1(32+15, RL0, RR0, dummy2);
 
        popq RW2; /*dst*/
+       CFI_POP_TMP_REG();
        final_permutation(RR0, RL0);
        write_block(RW2, RR0, RL0);
 
        popq %r15;
+       CFI_POP(%r15);
        popq %r14;
+       CFI_POP(%r14);
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
+       CFI_POP(%rbp);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_3des_amd64_crypt_block,.-_gcry_3des_amd64_crypt_block;)
 
 /***********************************************************************
@@ -472,8 +481,9 @@ _gcry_3des_amd64_crypt_blk3:
         *  RL0d, RR0d, RL1d, RR1d, RL2d, RR2d: 3 input blocks
         *  RR0d, RL0d, RR1d, RL1d, RR2d, RL2d: 3 output blocks
         */
+       CFI_STARTPROC();
 
-       leaq .L_s1 RIP, SBOXES;
+       leaq .L_s1 rRIP, SBOXES;
 
        initial_permutation3(RL, RR);
 
@@ -534,7 +544,8 @@ _gcry_3des_amd64_crypt_blk3:
 
        final_permutation3(RR, RL);
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_3des_amd64_crypt_blk3,.-_gcry_3des_amd64_crypt_blk3;)
 
 .align 8
@@ -547,17 +558,28 @@ _gcry_3des_amd64_cbc_dec:
         *      %rdx: src (3 blocks)
         *      %rcx: iv (64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
        pushq %r14;
+       CFI_PUSH(%r14);
        pushq %r15;
+       CFI_PUSH(%r15);
 
        pushq %rsi; /*dst*/
+       CFI_PUSH(%rsi);
        pushq %rdx; /*src*/
+       CFI_PUSH(%rdx);
        pushq %rcx; /*iv*/
+       CFI_PUSH(%rcx);
 
        /* load input */
        movl 0 * 4(%rdx), RL0d;
@@ -577,8 +599,11 @@ _gcry_3des_amd64_cbc_dec:
        call _gcry_3des_amd64_crypt_blk3;
 
        popq %rcx; /*iv*/
+       CFI_POP_TMP_REG();
        popq %rdx; /*src*/
+       CFI_POP_TMP_REG();
        popq %rsi; /*dst*/
+       CFI_POP_TMP_REG();
 
        bswapl RR0d;
        bswapl RL0d;
@@ -604,13 +629,21 @@ _gcry_3des_amd64_cbc_dec:
        movl RL2d, 5 * 4(%rsi);
 
        popq %r15;
+       CFI_POP(%r15);
        popq %r14;
+       CFI_POP(%r14);
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
+       CFI_POP(%rbp);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec;)
 
 .align 8
@@ -623,16 +656,26 @@ _gcry_3des_amd64_ctr_enc:
         *      %rdx: src (3 blocks)
         *      %rcx: iv (64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
 
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
        pushq %r14;
+       CFI_PUSH(%r14);
        pushq %r15;
+       CFI_PUSH(%r15);
 
        pushq %rsi; /*dst*/
+       CFI_PUSH(%rsi);
        pushq %rdx; /*src*/
+       CFI_PUSH(%rdx);
        movq %rcx, RW2;
 
        /* load IV and byteswap */
@@ -658,7 +701,9 @@ _gcry_3des_amd64_ctr_enc:
        call _gcry_3des_amd64_crypt_blk3;
 
        popq %rdx; /*src*/
+       CFI_POP_TMP_REG();
        popq %rsi; /*dst*/
+       CFI_POP_TMP_REG();
 
        bswapl RR0d;
        bswapl RL0d;
@@ -682,13 +727,21 @@ _gcry_3des_amd64_ctr_enc:
        movl RL2d, 5 * 4(%rsi);
 
        popq %r15;
+       CFI_POP(%r15);
        popq %r14;
+       CFI_POP(%r14);
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
+       CFI_POP(%rbp);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec;)
 
 .align 8
@@ -701,15 +754,26 @@ _gcry_3des_amd64_cfb_dec:
         *      %rdx: src (3 blocks)
         *      %rcx: iv (64bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        pushq %rbp;
+       CFI_PUSH(%rbp);
        pushq %rbx;
+       CFI_PUSH(%rbx);
        pushq %r12;
+       CFI_PUSH(%r12);
        pushq %r13;
+       CFI_PUSH(%r13);
        pushq %r14;
+       CFI_PUSH(%r14);
        pushq %r15;
+       CFI_PUSH(%r15);
 
        pushq %rsi; /*dst*/
+       CFI_PUSH(%rsi);
        pushq %rdx; /*src*/
+       CFI_PUSH(%rdx);
        movq %rcx, RW2;
 
        /* Load input */
@@ -734,7 +798,9 @@ _gcry_3des_amd64_cfb_dec:
        call _gcry_3des_amd64_crypt_blk3;
 
        popq %rdx; /*src*/
+       CFI_POP_TMP_REG();
        popq %rsi; /*dst*/
+       CFI_POP_TMP_REG();
 
        bswapl RR0d;
        bswapl RL0d;
@@ -758,12 +824,21 @@ _gcry_3des_amd64_cfb_dec:
        movl RL2d, 5 * 4(%rsi);
 
        popq %r15;
+       CFI_POP(%r15);
        popq %r14;
+       CFI_POP(%r14);
        popq %r13;
+       CFI_POP(%r13);
        popq %r12;
+       CFI_POP(%r12);
        popq %rbx;
+       CFI_POP(%rbx);
        popq %rbp;
-       ret;
+       CFI_POP(%rbp);
+
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_3des_amd64_cfb_dec,.-_gcry_3des_amd64_cfb_dec;)
 
 .align 16
index 5c99f50..51116fc 100644 (file)
 #include "g10lib.h"
 #include "cipher.h"
 #include "bufhelp.h"
+#include "cipher-internal.h"
 #include "cipher-selftest.h"
 
 
@@ -197,7 +198,8 @@ static unsigned int do_tripledes_encrypt(void *context, byte *outbuf,
 static unsigned int do_tripledes_decrypt(void *context, byte *outbuf,
                                         const byte *inbuf );
 static gcry_err_code_t do_tripledes_setkey(void *context, const byte *key,
-                                           unsigned keylen);
+                                           unsigned keylen,
+                                           cipher_bulk_ops_t *bulk_ops);
 
 static int initialized;
 
@@ -772,23 +774,6 @@ extern void _gcry_3des_amd64_cfb_dec(const void *keys, byte *out,
 
 #define TRIPLEDES_ECB_BURN_STACK (8 * sizeof(void *))
 
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-static inline void
-call_sysv_fn (const void *fn, const void *arg1, const void *arg2,
-              const void *arg3, const void *arg4)
-{
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  asm volatile ("callq *%0\n\t"
-                : "+a" (fn),
-                  "+D" (arg1),
-                  "+S" (arg2),
-                  "+d" (arg3),
-                  "+c" (arg4)
-                :
-                : "cc", "memory", "r8", "r9", "r10", "r11");
-}
-#endif
 
 /*
  * Electronic Codebook Mode Triple-DES encryption/decryption of data
@@ -803,11 +788,7 @@ tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from,
 
   keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys;
 
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_3des_amd64_crypt_block, keys, to, from, NULL);
-#else
   _gcry_3des_amd64_crypt_block(keys, to, from);
-#endif
 
   return 0;
 }
@@ -815,31 +796,19 @@ tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from,
 static inline void
 tripledes_amd64_ctr_enc(const void *keys, byte *out, const byte *in, byte *ctr)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_3des_amd64_ctr_enc, keys, out, in, ctr);
-#else
   _gcry_3des_amd64_ctr_enc(keys, out, in, ctr);
-#endif
 }
 
 static inline void
 tripledes_amd64_cbc_dec(const void *keys, byte *out, const byte *in, byte *iv)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_3des_amd64_cbc_dec, keys, out, in, iv);
-#else
   _gcry_3des_amd64_cbc_dec(keys, out, in, iv);
-#endif
 }
 
 static inline void
 tripledes_amd64_cfb_dec(const void *keys, byte *out, const byte *in, byte *iv)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn (_gcry_3des_amd64_cfb_dec, keys, out, in, iv);
-#else
   _gcry_3des_amd64_cfb_dec(keys, out, in, iv);
-#endif
 }
 
 #else /*USE_AMD64_ASM*/
@@ -903,7 +872,7 @@ tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from,
 /* Bulk encryption of complete blocks in CTR mode.  This function is only
    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
    of size DES_BLOCKSIZE. */
-void
+static void
 _gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
                    const void *inbuf_arg, size_t nblocks)
 {
@@ -912,7 +881,6 @@ _gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
   const unsigned char *inbuf = inbuf_arg;
   unsigned char tmpbuf[DES_BLOCKSIZE];
   int burn_stack_depth = TRIPLEDES_ECB_BURN_STACK;
-  int i;
 
 #ifdef USE_AMD64_ASM
   {
@@ -940,16 +908,11 @@ _gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
       /* Encrypt the counter. */
       tripledes_ecb_encrypt (ctx, ctr, tmpbuf);
       /* XOR the input with the encrypted counter and store in output.  */
-      buf_xor(outbuf, tmpbuf, inbuf, DES_BLOCKSIZE);
+      cipher_block_xor(outbuf, tmpbuf, inbuf, DES_BLOCKSIZE);
       outbuf += DES_BLOCKSIZE;
       inbuf  += DES_BLOCKSIZE;
       /* Increment the counter.  */
-      for (i = DES_BLOCKSIZE; i > 0; i--)
-        {
-          ctr[i-1]++;
-          if (ctr[i-1])
-            break;
-        }
+      cipher_block_add(ctr, 1, DES_BLOCKSIZE);
     }
 
   wipememory(tmpbuf, sizeof(tmpbuf));
@@ -959,7 +922,7 @@ _gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
 
 /* Bulk decryption of complete blocks in CBC mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_3des_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
                    const void *inbuf_arg, size_t nblocks)
 {
@@ -996,7 +959,7 @@ _gcry_3des_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
          the intermediate result to SAVEBUF.  */
       tripledes_ecb_decrypt (ctx, inbuf, savebuf);
 
-      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, DES_BLOCKSIZE);
+      cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, DES_BLOCKSIZE);
       inbuf += DES_BLOCKSIZE;
       outbuf += DES_BLOCKSIZE;
     }
@@ -1008,7 +971,7 @@ _gcry_3des_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
 
 /* Bulk decryption of complete blocks in CFB mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_3des_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
                   const void *inbuf_arg, size_t nblocks)
 {
@@ -1041,7 +1004,7 @@ _gcry_3des_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
   for ( ;nblocks; nblocks-- )
     {
       tripledes_ecb_encrypt (ctx, iv, iv);
-      buf_xor_n_copy(outbuf, iv, inbuf, DES_BLOCKSIZE);
+      cipher_block_xor_n_copy(outbuf, iv, inbuf, DES_BLOCKSIZE);
       outbuf += DES_BLOCKSIZE;
       inbuf  += DES_BLOCKSIZE;
     }
@@ -1086,7 +1049,8 @@ is_weak_key ( const byte *key )
 
 /* Alternative setkey for selftests; need larger key than default. */
 static gcry_err_code_t
-bulk_selftest_setkey (void *context, const byte *__key, unsigned __keylen)
+bulk_selftest_setkey (void *context, const byte *__key, unsigned __keylen,
+                      cipher_bulk_ops_t *bulk_ops)
 {
   static const unsigned char key[24] ATTR_ALIGNED_16 = {
       0x66,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
@@ -1097,7 +1061,7 @@ bulk_selftest_setkey (void *context, const byte *__key, unsigned __keylen)
   (void)__key;
   (void)__keylen;
 
-  return do_tripledes_setkey(context, key, sizeof(key));
+  return do_tripledes_setkey(context, key, sizeof(key), bulk_ops);
 }
 
 
@@ -1111,8 +1075,7 @@ selftest_ctr (void)
   const int context_size = sizeof(struct _tripledes_ctx);
 
   return _gcry_selftest_helper_ctr("3DES", &bulk_selftest_setkey,
-           &do_tripledes_encrypt, &_gcry_3des_ctr_enc, nblocks, blocksize,
-           context_size);
+           &do_tripledes_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1126,8 +1089,7 @@ selftest_cbc (void)
   const int context_size = sizeof(struct _tripledes_ctx);
 
   return _gcry_selftest_helper_cbc("3DES", &bulk_selftest_setkey,
-           &do_tripledes_encrypt, &_gcry_3des_cbc_dec, nblocks, blocksize,
-           context_size);
+           &do_tripledes_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1141,8 +1103,7 @@ selftest_cfb (void)
   const int context_size = sizeof(struct _tripledes_ctx);
 
   return _gcry_selftest_helper_cfb("3DES", &bulk_selftest_setkey,
-           &do_tripledes_encrypt, &_gcry_3des_cfb_dec, nblocks, blocksize,
-           context_size);
+           &do_tripledes_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1349,13 +1310,20 @@ selftest (void)
 
 
 static gcry_err_code_t
-do_tripledes_setkey ( void *context, const byte *key, unsigned keylen )
+do_tripledes_setkey ( void *context, const byte *key, unsigned keylen,
+                      cipher_bulk_ops_t *bulk_ops )
 {
   struct _tripledes_ctx *ctx = (struct _tripledes_ctx *) context;
 
   if( keylen != 24 )
     return GPG_ERR_INV_KEYLEN;
 
+  /* Setup bulk encryption routines.  */
+  memset (bulk_ops, 0, sizeof(*bulk_ops));
+  bulk_ops->cbc_dec =  _gcry_3des_cbc_dec;
+  bulk_ops->cfb_dec =  _gcry_3des_cfb_dec;
+  bulk_ops->ctr_enc =  _gcry_3des_ctr_enc;
+
   tripledes_set3keys ( ctx, key, key+8, key+16);
 
   if (ctx->flags.no_weak_key)
@@ -1413,10 +1381,13 @@ do_tripledes_decrypt( void *context, byte *outbuf, const byte *inbuf )
 }
 
 static gcry_err_code_t
-do_des_setkey (void *context, const byte *key, unsigned keylen)
+do_des_setkey (void *context, const byte *key, unsigned keylen,
+               cipher_bulk_ops_t *bulk_ops)
 {
   struct _des_ctx *ctx = (struct _des_ctx *) context;
 
+  (void)bulk_ops;
+
   if (keylen != 8)
     return GPG_ERR_INV_KEYLEN;
 
@@ -1515,7 +1486,7 @@ gcry_cipher_spec_t _gcry_cipher_spec_des =
     do_des_setkey, do_des_encrypt, do_des_decrypt
   };
 
-static gcry_cipher_oid_spec_t oids_tripledes[] =
+static const gcry_cipher_oid_spec_t oids_tripledes[] =
   {
     { "1.2.840.113549.3.7", GCRY_CIPHER_MODE_CBC },
     /* Teletrust specific OID for 3DES. */
@@ -1527,7 +1498,7 @@ static gcry_cipher_oid_spec_t oids_tripledes[] =
 
 gcry_cipher_spec_t _gcry_cipher_spec_tripledes =
   {
-    GCRY_CIPHER_3DES, {0, 1},
+    GCRY_CIPHER_3DES, {0, 0},
     "3DES", NULL, oids_tripledes, 8, 192, sizeof (struct _tripledes_ctx),
     do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt,
     NULL, NULL,
index 6f2c2f9..7000903 100644 (file)
 
 
 /*
+ * Modify K, so that computation time difference can be small,
+ * by making K large enough.
+ *
+ * Originally, (EC)DSA computation requires k where 0 < k < q.  Here,
+ * we add q (the order), to keep k in a range: q < k < 2*q (or,
+ * addming more q, to keep k in a range: 2*q < k < 3*q), so that
+ * timing difference of the EC multiply (or exponentiation) operation
+ * can be small.  The result of (EC)DSA computation is same.
+ */
+void
+_gcry_dsa_modify_k (gcry_mpi_t k, gcry_mpi_t q, int qbits)
+{
+  gcry_mpi_t k1 = mpi_new (qbits+2);
+
+  mpi_resize (k, (qbits+2+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB);
+  k->nlimbs = k->alloced;
+  mpi_add (k, k, q);
+  mpi_add (k1, k, q);
+  mpi_set_cond (k, k1, !mpi_test_bit (k, qbits));
+
+  mpi_free (k1);
+}
+
+/*
  * Generate a random secret exponent K less than Q.
  * Note that ECDSA uses this code also to generate D.
  */
@@ -265,7 +289,7 @@ _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
   memcpy (V, _gcry_md_read (hd, 0), hlen);
 
   /* Step h. */
-  t = xtrymalloc ((qbits+7)/8+hlen);
+  t = xtrymalloc_secure ((qbits+7)/8+hlen);
   if (!t)
     {
       rc = gpg_err_code_from_syserror ();
@@ -360,6 +384,61 @@ _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
   return rc;
 }
 
+
+
+/*
+ * For DSA/ECDSA, as prehash function, compute hash with HASHALGO for
+ * INPUT.  Result hash value is returned in R_HASH as an opaque MPI.
+ * Returns error code.
+ */
+gpg_err_code_t
+_gcry_dsa_compute_hash (gcry_mpi_t *r_hash, gcry_mpi_t input, int hashalgo)
+{
+  gpg_err_code_t rc = 0;
+  size_t hlen;
+  void *hashbuf;
+  void *abuf;
+  unsigned int abits;
+  unsigned int n;
+
+  hlen = _gcry_md_get_algo_dlen (hashalgo);
+  hashbuf = xtrymalloc (hlen);
+  if (!hashbuf)
+    {
+      rc = gpg_err_code_from_syserror ();
+      return rc;
+    }
+
+  if (mpi_is_opaque (input))
+    {
+      abuf = mpi_get_opaque (input, &abits);
+      n = (abits+7)/8;
+      _gcry_md_hash_buffer (hashalgo, hashbuf, abuf, n);
+    }
+  else
+    {
+      abits = mpi_get_nbits (input);
+      n = (abits+7)/8;
+      abuf = xtrymalloc (n);
+      if (!abuf)
+        {
+          rc = gpg_err_code_from_syserror ();
+          xfree (hashbuf);
+          return rc;
+        }
+      _gcry_mpi_to_octet_string (NULL, abuf, input, n);
+      _gcry_md_hash_buffer (hashalgo, hashbuf, abuf, n);
+      xfree (abuf);
+    }
+
+  *r_hash = mpi_set_opaque (NULL, hashbuf, hlen*8);
+  if (!*r_hash)
+    rc = GPG_ERR_INV_OBJ;
+
+  return rc;
+}
+
+
 /*
  * Truncate opaque hash value to qbits for DSA.
  * Non-opaque input is not truncated, in hope that user
index 22d8d78..e559f9f 100644 (file)
@@ -133,10 +133,11 @@ static gpg_err_code_t generate (DSA_secret_key *sk,
                                 int transient_key,
                                 dsa_domain_t *domain,
                                 gcry_mpi_t **ret_factors);
-static gpg_err_code_t sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input,
+static gpg_err_code_t sign (gcry_mpi_t r, gcry_mpi_t s,
+                            gcry_mpi_t input, gcry_mpi_t k,
                             DSA_secret_key *skey, int flags, int hashalgo);
 static gpg_err_code_t verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input,
-                   DSA_public_key *pkey);
+                              DSA_public_key *pkey, int flags, int hashalgo);
 static unsigned int dsa_get_nbits (gcry_sexp_t parms);
 
 
@@ -144,6 +145,17 @@ static void (*progress_cb) (void *,const char *, int, int, int );
 static void *progress_cb_data;
 
 
+/* Check the DSA key length is acceptable for key generation or usage */
+static gpg_err_code_t
+dsa_check_keysize (unsigned int nbits)
+{
+  if (fips_mode () && nbits < 2048)
+    return GPG_ERR_INV_VALUE;
+
+  return 0;
+}
+
+
 void
 _gcry_register_pk_dsa_progress (void (*cb) (void *, const char *,
                                             int, int, int),
@@ -182,15 +194,15 @@ test_keys (DSA_secret_key *sk, unsigned int qbits)
   _gcry_mpi_randomize (data, qbits, GCRY_WEAK_RANDOM);
 
   /* Sign DATA using the secret key.  */
-  sign (sig_a, sig_b, data, sk, 0, 0);
+  sign (sig_a, sig_b, data, NULL, sk, 0, 0);
 
   /* Verify the signature using the public key.  */
-  if ( verify (sig_a, sig_b, data, &pk) )
+  if ( verify (sig_a, sig_b, data, &pk, 0, 0) )
     goto leave; /* Signature does not match.  */
 
   /* Modify the data and check that the signing fails.  */
   mpi_add_ui (data, data, 1);
-  if ( !verify (sig_a, sig_b, data, &pk) )
+  if ( !verify (sig_a, sig_b, data, &pk, 0, 0) )
     goto leave; /* Signature matches but should not.  */
 
   result = 0; /* The test succeeded.  */
@@ -246,14 +258,6 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
   if (nbits < 2*qbits || nbits > 15360)
     return GPG_ERR_INV_VALUE;
 
-  if (fips_mode ())
-    {
-      if (nbits < 1024)
-        return GPG_ERR_INV_VALUE;
-      if (transient_key)
-        return GPG_ERR_INV_VALUE;
-    }
-
   if (domain->p && domain->q && domain->g)
     {
       /* Domain parameters are given; use them.  */
@@ -426,6 +430,10 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
   else
     return GPG_ERR_INV_VALUE;
 
+  ec = dsa_check_keysize (nbits);
+  if (ec)
+    return ec;
+
   if (domain->p && domain->q && domain->g)
     {
       /* Domain parameters are given; use them.  */
@@ -458,7 +466,9 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits,
                                              r_counter,
                                              r_seed, r_seedlen);
       else
-        ec = _gcry_generate_fips186_3_prime (nbits, qbits, NULL, 0,
+        ec = _gcry_generate_fips186_3_prime (nbits, qbits,
+                                             initial_seed.seed,
+                                             initial_seed.seedlen,
                                              &prime_q, &prime_p,
                                              r_counter,
                                              r_seed, r_seedlen, NULL);
@@ -586,13 +596,16 @@ check_secret_key( DSA_secret_key *sk )
    internally converted to a plain MPI.  FLAGS and HASHALGO may both
    be 0 for standard operation mode.
 
+   The random value, K_SUPPLIED, may be supplied externally.  If not,
+   it is generated internally.
+
    The return value is 0 on success or an error code.  Note that for
    backward compatibility the function will not return any error if
    FLAGS and HASHALGO are both 0 and INPUT is a plain MPI.
  */
 static gpg_err_code_t
-sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_secret_key *skey,
-      int flags, int hashalgo)
+sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, gcry_mpi_t k_supplied,
+      DSA_secret_key *skey, int flags, int hashalgo)
 {
   gpg_err_code_t rc;
   gcry_mpi_t hash;
@@ -602,17 +615,31 @@ sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_secret_key *skey,
   const void *abuf;
   unsigned int abits, qbits;
   int extraloops = 0;
+  gcry_mpi_t hash_computed_internally = NULL;
 
   qbits = mpi_get_nbits (skey->q);
 
+  if ((flags & PUBKEY_FLAG_PREHASH))
+    {
+      rc = _gcry_dsa_compute_hash (&hash_computed_internally, input, hashalgo);
+      if (rc)
+        return rc;
+      input = hash_computed_internally;
+    }
+
   /* Convert the INPUT into an MPI.  */
   rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
   if (rc)
-    return rc;
+    {
+      mpi_free (hash_computed_internally);
+      return rc;
+    }
 
  again:
+  if (k_supplied)
+    k = k_supplied;
   /* Create the K value.  */
-  if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
+  else if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
     {
       /* Use Pornin's method for deterministic DSA.  If this flag is
          set, it is expected that HASH is an opaque MPI with the to be
@@ -635,26 +662,35 @@ sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_secret_key *skey,
       k = _gcry_dsa_gen_k (skey->q, GCRY_STRONG_RANDOM);
     }
 
-  /* r = (a^k mod p) mod q */
-  mpi_powm( r, skey->g, k, skey->p );
-  mpi_fdiv_r( r, r, skey->q );
-
   /* kinv = k^(-1) mod q */
   kinv = mpi_alloc( mpi_get_nlimbs(k) );
   mpi_invm(kinv, k, skey->q );
 
+  _gcry_dsa_modify_k (k, skey->q, qbits);
+
+  /* r = (a^k mod p) mod q */
+  mpi_powm( r, skey->g, k, skey->p );
+  mpi_fdiv_r( r, r, skey->q );
+
   /* s = (kinv * ( hash + x * r)) mod q */
   tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
   mpi_mul( tmp, skey->x, r );
   mpi_add( tmp, tmp, hash );
   mpi_mulm( s , kinv, tmp, skey->q );
 
-  mpi_free(k);
+  if (!k_supplied)
+    mpi_free(k);
   mpi_free(kinv);
   mpi_free(tmp);
 
   if (!mpi_cmp_ui (r, 0))
     {
+      if (k_supplied)
+        {
+          rc = GPG_ERR_INV_VALUE;
+          goto leave;
+        }
+
       /* This is a highly unlikely code path.  */
       extraloops++;
       goto again;
@@ -665,6 +701,7 @@ sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_secret_key *skey,
  leave:
   if (hash != input)
     mpi_free (hash);
+  mpi_free (hash_computed_internally);
 
   return rc;
 }
@@ -674,7 +711,8 @@ sign (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_secret_key *skey,
    Returns true if the signature composed from R and S is valid.
  */
 static gpg_err_code_t
-verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_public_key *pkey )
+verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_public_key *pkey,
+        int flags, int hashalgo)
 {
   gpg_err_code_t rc = 0;
   gcry_mpi_t w, u1, u2, v;
@@ -682,6 +720,7 @@ verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_public_key *pkey )
   gcry_mpi_t ex[3];
   gcry_mpi_t hash;
   unsigned int nbits;
+  gcry_mpi_t hash_computed_internally = NULL;
 
   if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
     return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n  failed.  */
@@ -689,9 +728,19 @@ verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_public_key *pkey )
     return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n  failed.  */
 
   nbits = mpi_get_nbits (pkey->q);
+  if ((flags & PUBKEY_FLAG_PREHASH))
+    {
+      rc = _gcry_dsa_compute_hash (&hash_computed_internally, input, hashalgo);
+      if (rc)
+        return rc;
+      input = hash_computed_internally;
+    }
   rc = _gcry_dsa_normalize_hash (input, &hash, nbits);
   if (rc)
-    return rc;
+    {
+      mpi_free (hash_computed_internally);
+      return rc;
+    }
 
   w  = mpi_alloc( mpi_get_nlimbs(pkey->q) );
   u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
@@ -733,6 +782,7 @@ verify (gcry_mpi_t r, gcry_mpi_t s, gcry_mpi_t input, DSA_public_key *pkey )
   mpi_free(v);
   if (hash != input)
     mpi_free (hash);
+  mpi_free (hash_computed_internally);
 
   return rc;
 }
@@ -1027,12 +1077,17 @@ dsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   gcry_err_code_t rc;
   struct pk_encoding_ctx ctx;
   gcry_mpi_t data = NULL;
+  gcry_mpi_t k = NULL;
   DSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL};
   gcry_mpi_t sig_r = NULL;
   gcry_mpi_t sig_s = NULL;
+  unsigned int nbits = dsa_get_nbits (keyparms);
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN,
-                                   dsa_get_nbits (keyparms));
+  rc = dsa_check_keysize (nbits);
+  if (rc)
+    return rc;
+
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
@@ -1041,6 +1096,11 @@ dsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   if (DBG_CIPHER)
     log_mpidump ("dsa_sign   data", data);
 
+  if (ctx.label)
+    rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, ctx.label, ctx.labellen, NULL);
+  if (rc)
+    goto leave;
+
   /* Extract the key.  */
   rc = _gcry_sexp_extract_param (keyparms, NULL, "pqgyx",
                                  &sk.p, &sk.q, &sk.g, &sk.y, &sk.x, NULL);
@@ -1058,7 +1118,7 @@ dsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
 
   sig_r = mpi_new (0);
   sig_s = mpi_new (0);
-  rc = sign (sig_r, sig_s, data, &sk, ctx.flags, ctx.hash_algo);
+  rc = sign (sig_r, sig_s, data, k, &sk, ctx.flags, ctx.hash_algo);
   if (rc)
     goto leave;
   if (DBG_CIPHER)
@@ -1077,6 +1137,7 @@ dsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   _gcry_mpi_release (sk.y);
   _gcry_mpi_release (sk.x);
   _gcry_mpi_release (data);
+  _gcry_mpi_release (k);
   _gcry_pk_util_free_encoding_ctx (&ctx);
   if (DBG_CIPHER)
     log_debug ("dsa_sign      => %s\n", gpg_strerror (rc));
@@ -1094,9 +1155,13 @@ dsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
   gcry_mpi_t sig_s = NULL;
   gcry_mpi_t data = NULL;
   DSA_public_key pk = { NULL, NULL, NULL, NULL };
+  unsigned int nbits = dsa_get_nbits (s_keyparms);
+
+  rc = dsa_check_keysize (nbits);
+  if (rc)
+    return rc;
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
-                                   dsa_get_nbits (s_keyparms));
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
@@ -1132,7 +1197,7 @@ dsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
     }
 
   /* Verify the signature.  */
-  rc = verify (sig_r, sig_s, data, &pk);
+  rc = verify (sig_r, sig_s, data, &pk, ctx.flags, ctx.hash_algo);
 
  leave:
   _gcry_mpi_release (pk.p);
@@ -1191,8 +1256,9 @@ selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey)
 {
   /* Sample data from RFC 6979 section A.2.2, hash is of message "sample" */
   static const char sample_data[] =
-    "(data (flags rfc6979)"
-    " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e9891562113d8a62add1bf#))";
+    "(data (flags rfc6979 prehash)"
+    " (hash-algo sha256)"
+    " (value 6:sample))";
   static const char sample_data_bad[] =
     "(data (flags rfc6979)"
     " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e9891562113d8a62add1bf#))";
@@ -1375,7 +1441,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
 \f
 gcry_pk_spec_t _gcry_pubkey_spec_dsa =
   {
-    GCRY_PK_DSA, { 0, 1 },
+    GCRY_PK_DSA, { 0, 0 },
     GCRY_PK_USAGE_SIGN,
     "DSA", dsa_names,
     "pqgy", "pqgyx", "", "rs", "pqgy",
index 748e6db..01fb904 100644 (file)
@@ -32,26 +32,11 @@ typedef struct
                            or d as used by Twisted Edwards curves.  */
   mpi_point_struct G;   /* Base point (generator).  */
   gcry_mpi_t n;         /* Order of G.  */
-  gcry_mpi_t h;         /* Cofactor.  */
+  unsigned int h;       /* Cofactor.  */
   const char *name;     /* Name of the curve or NULL.  */
 } elliptic_curve_t;
 
 
-typedef struct
-{
-  elliptic_curve_t E;
-  mpi_point_struct Q; /* Q = [d]G  */
-} ECC_public_key;
-
-
-typedef struct
-{
-  elliptic_curve_t E;
-  mpi_point_struct Q;
-  gcry_mpi_t d;
-} ECC_secret_key;
-
-
 
 /* Set the value from S into D.  */
 static inline void
@@ -76,7 +61,7 @@ gpg_err_code_t _gcry_ecc_update_curve_param (const char *name,
                                              enum ecc_dialects *dialect,
                                              gcry_mpi_t *p, gcry_mpi_t *a,
                                              gcry_mpi_t *b, gcry_mpi_t *g,
-                                             gcry_mpi_t *n, gcry_mpi_t *h);
+                                             gcry_mpi_t *n);
 
 const char *_gcry_ecc_get_curve (gcry_sexp_t keyparms,
                                  int iterator,
@@ -88,20 +73,26 @@ void _gcry_ecc_curve_free (elliptic_curve_t *E);
 elliptic_curve_t _gcry_ecc_curve_copy (elliptic_curve_t E);
 const char *_gcry_ecc_model2str (enum gcry_mpi_ec_models model);
 const char *_gcry_ecc_dialect2str (enum ecc_dialects dialect);
+unsigned char *_gcry_ecc_ec2os_buf (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p,
+                                    unsigned int *r_length);
 gcry_mpi_t   _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p);
 
-mpi_point_t  _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
-                                       mpi_point_t G, gcry_mpi_t d);
+mpi_point_t  _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec);
+gpg_err_code_t _gcry_ecc_mont_encodepoint (gcry_mpi_t x, unsigned int nbits,
+                                           int with_prefix,
+                                           unsigned char **r_buffer,
+                                           unsigned int *r_buflen);
 
 
 /*-- ecc.c --*/
 
 /*-- ecc-ecdsa.c --*/
-gpg_err_code_t _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
+gpg_err_code_t _gcry_ecc_ecdsa_sign (gcry_mpi_t input, gcry_mpi_t k, mpi_ec_t ec,
                                      gcry_mpi_t r, gcry_mpi_t s,
                                      int flags, int hashalgo);
-gpg_err_code_t _gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
-                                       gcry_mpi_t r, gcry_mpi_t s);
+gpg_err_code_t _gcry_ecc_ecdsa_verify (gcry_mpi_t input, mpi_ec_t ec,
+                                       gcry_mpi_t r, gcry_mpi_t s,
+                                       int flags, int hashalgo);
 
 /*-- ecc-eddsa.c --*/
 gpg_err_code_t _gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign,
@@ -116,26 +107,37 @@ gpg_err_code_t _gcry_ecc_eddsa_ensure_compact (gcry_mpi_t value,
 
 
 gpg_err_code_t _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
-                                            gcry_mpi_t d, mpi_ec_t ec);
+                                            mpi_ec_t ec);
 
-gpg_err_code_t _gcry_ecc_eddsa_genkey (ECC_secret_key *sk,
-                                       elliptic_curve_t *E,
-                                       mpi_ec_t ctx,
-                                       int flags);
+gpg_err_code_t _gcry_ecc_eddsa_genkey (mpi_ec_t ec, int flags);
 gpg_err_code_t _gcry_ecc_eddsa_sign (gcry_mpi_t input,
-                                     ECC_secret_key *sk,
+                                     mpi_ec_t ec,
                                      gcry_mpi_t r_r, gcry_mpi_t s,
-                                     int hashalgo, gcry_mpi_t pk);
+                                     struct pk_encoding_ctx *ctx);
 gpg_err_code_t _gcry_ecc_eddsa_verify (gcry_mpi_t input,
-                                       ECC_public_key *pk,
+                                       mpi_ec_t ec,
                                        gcry_mpi_t r, gcry_mpi_t s,
-                                       int hashalgo, gcry_mpi_t pkmpi);
+                                       struct pk_encoding_ctx *ctx);
+void reverse_buffer (unsigned char *buffer, unsigned int length);
+
 
 /*-- ecc-gost.c --*/
-gpg_err_code_t _gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
+gpg_err_code_t _gcry_ecc_gost_sign (gcry_mpi_t input, mpi_ec_t ec,
                                     gcry_mpi_t r, gcry_mpi_t s);
-gpg_err_code_t _gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey,
+gpg_err_code_t _gcry_ecc_gost_verify (gcry_mpi_t input, mpi_ec_t ec,
                                       gcry_mpi_t r, gcry_mpi_t s);
 
 
+/*-- ecc-sm2.c --*/
+gpg_err_code_t _gcry_ecc_sm2_encrypt (gcry_sexp_t *r_ciph,
+                                      gcry_mpi_t input, mpi_ec_t ec);
+gpg_err_code_t _gcry_ecc_sm2_decrypt (gcry_sexp_t *r_plain,
+                                      gcry_sexp_t data_list, mpi_ec_t ec);
+gpg_err_code_t _gcry_ecc_sm2_sign (gcry_mpi_t input, mpi_ec_t ec,
+                                   gcry_mpi_t r, gcry_mpi_t s,
+                                   int flags, int hashalgo);
+gpg_err_code_t _gcry_ecc_sm2_verify (gcry_mpi_t input, mpi_ec_t ec,
+                                     gcry_mpi_t r, gcry_mpi_t s);
+
+
 #endif /*GCRY_ECC_COMMON_H*/
index 39bad1a..7c86e12 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "g10lib.h"
 #include "mpi.h"
+#include "mpi-internal.h"
 #include "cipher.h"
 #include "context.h"
 #include "ec-context.h"
 #include "ecc-common.h"
 
 
+static gpg_err_code_t
+point_from_keyparam (gcry_mpi_point_t *r_a,
+                     gcry_sexp_t keyparam, const char *name, mpi_ec_t ec);
+
 /* This tables defines aliases for curve names.  */
 static const struct
 {
@@ -40,8 +45,15 @@ static const struct
   const char *other; /* Other name. */
 } curve_aliases[] =
   {
-    { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },
-    { "Ed25519",    "1.3.6.1.4.1.11591.15.1" },
+    { "Ed25519",    "1.3.6.1.4.1.11591.15.1" }, /* OpenPGP */
+    { "Ed25519",    "1.3.101.112" },         /* rfc8410 */
+
+    { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" }, /* OpenPGP */
+    { "Curve25519", "1.3.101.110" },         /* rfc8410 */
+    { "Curve25519", "X25519" },              /* rfc8410 */
+
+    { "Ed448",      "1.3.101.113" },         /* rfc8410 */
+    { "X448",       "1.3.101.111" },         /* rfc8410 */
 
     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
     { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
@@ -82,11 +94,26 @@ static const struct
     { "GOST2001-CryptoPro-A", "1.2.643.2.2.36.0" },
     { "GOST2001-CryptoPro-C", "1.2.643.2.2.36.1" },
 
-    { "GOST2012-tc26-A", "1.2.643.7.1.2.1.2.1" },
-    { "GOST2012-tc26-B", "1.2.643.7.1.2.1.2.2" },
+    { "GOST2012-256-tc26-A", "1.2.643.7.1.2.1.1.1" },
+    { "GOST2001-CryptoPro-A", "1.2.643.7.1.2.1.1.2" },
+    { "GOST2001-CryptoPro-A", "GOST2012-256-tc26-B" },
+    { "GOST2001-CryptoPro-B", "1.2.643.7.1.2.1.1.3" },
+    { "GOST2001-CryptoPro-B", "GOST2012-256-tc26-C" },
+    { "GOST2001-CryptoPro-C", "1.2.643.7.1.2.1.1.4" },
+    { "GOST2001-CryptoPro-C", "GOST2012-256-tc26-D" },
+
+    { "GOST2012-512-test", "GOST2012-test" },
+    { "GOST2012-512-test", "1.2.643.7.1.2.1.2.0" },
+    { "GOST2012-512-tc26-A", "GOST2012-tc26-A" },
+    { "GOST2012-512-tc26-B", "GOST2012-tc26-B" },
+    { "GOST2012-512-tc26-A", "1.2.643.7.1.2.1.2.1" },
+    { "GOST2012-512-tc26-B", "1.2.643.7.1.2.1.2.2" },
+    { "GOST2012-512-tc26-C", "1.2.643.7.1.2.1.2.3" },
 
     { "secp256k1", "1.3.132.0.10" },
 
+    { "sm2p256v1", "1.2.156.10197.1.301" },
+
     { NULL, NULL}
   };
 
@@ -95,7 +122,7 @@ typedef struct
 {
   const char *desc;           /* Description of the curve.  */
   unsigned int nbits;         /* Number of bits.  */
-  unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
+  unsigned int fips:1;        /* True if this is a FIPS140-3 approved curve. */
 
   /* The model describing this curve.  This is mainly used to select
      the group equation. */
@@ -111,7 +138,7 @@ typedef struct
                                  Curves (a,b) has ((A-2)/4,B^-1).  */
   const char *n;              /* The order of the base point.  */
   const char *g_x, *g_y;      /* Base point.  */
-  const char *h;              /* Cofactor.  */
+  unsigned int h;             /* Cofactor.  */
 } ecc_domain_parms_t;
 
 
@@ -120,7 +147,7 @@ static const ecc_domain_parms_t domain_parms[] =
   {
     {
       /* (-x^2 + y^2 = 1 + dx^2y^2) */
-      "Ed25519", 256, 0,
+      "Ed25519", 255, 0,
       MPI_EC_EDWARDS, ECC_DIALECT_ED25519,
       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
       "-0x01",
@@ -128,11 +155,11 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
       "0x6666666666666666666666666666666666666666666666666666666666666658",
-      "0x08"
+      8
     },
     {
       /* (y^2 = x^3 + 486662*x^2 + x) */
-      "Curve25519", 256, 0,
+      "Curve25519", 255, 0,
       MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD,
       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
       "0x01DB41",
@@ -140,7 +167,45 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
       "0x0000000000000000000000000000000000000000000000000000000000000009",
       "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
-      "0x08"
+      8
+      /* Note: As per RFC-7748 errata eid4730 the g_y value should be
+       * "0x5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14"
+       * but that breaks the keygrip.  The new value is recovered in
+       * the function _gcry_ecc_fill_in_curve.  See bug #4712.
+       */
+    },
+    {
+      /* (x^2 + y^2 = 1 + dx^2y^2) */
+      "Ed448", 448, 0,
+      MPI_EC_EDWARDS, ECC_DIALECT_SAFECURVE,
+      "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+      "0x01",
+      "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6756",
+      "0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+      "7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3",
+      "0x4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324"
+      "A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E",
+      "0x693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E"
+      "05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14",
+      4,
+    },
+    {
+      /* (y^2 = x^3 + 156326*x^2 + x) */
+      "X448", 448, 0,
+      MPI_EC_MONTGOMERY, ECC_DIALECT_SAFECURVE,
+      "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+      "0x98A9",
+      "0x01",
+      "0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+      "7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3",
+      "0x00000000000000000000000000000000000000000000000000000000"
+      "00000000000000000000000000000000000000000000000000000005",
+      "0x7D235D1295F5B1F66C98AB6E58326FCECBAE5D34F55545D060F75DC2"
+      "8DF3F6EDB8027E2346430D211312C4B150677AF76FD7223D457B5B1A",
+      4,
     },
 #if 0 /* No real specs yet found.  */
     {
@@ -156,7 +221,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x1A334905141443300218C0631C326E5FCD46369F44C03EC7F57FF35498A4AB4D"
       "6D6BA111301A73FAA8537C64C4FD3812F3CBC595",
       "0x22",
-      "0x08"
+      8
     },
 #endif /*0*/
     {
@@ -169,7 +234,7 @@ static const ecc_domain_parms_t domain_parms[] =
 
       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
-      "0x01"
+      1
     },
     {
       "NIST P-224", 224, 1,
@@ -181,7 +246,7 @@ static const ecc_domain_parms_t domain_parms[] =
 
       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
-      "0x01"
+      1
     },
     {
       "NIST P-256", 256, 1,
@@ -193,7 +258,7 @@ static const ecc_domain_parms_t domain_parms[] =
 
       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
-      "0x01"
+      1
     },
     {
       "NIST P-384", 384, 1,
@@ -211,7 +276,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "5502f25dbf55296c3a545e3872760ab7",
       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
       "0a60b1ce1d7e819d7a431d7c90ea0e5f",
-      "0x01"
+      1
     },
     {
       "NIST P-521", 521, 1,
@@ -222,14 +287,14 @@ static const ecc_domain_parms_t domain_parms[] =
       "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
       "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
       "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
-      "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-      "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
+      "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+      "fffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
 
       "0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d"
       "3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
       "0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e"
       "662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
-      "0x01"
+      1
     },
 
     { "brainpoolP160r1", 160, 0,
@@ -240,7 +305,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xe95e4a5f737059dc60df5991d45029409e60fc09",
       "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
       "0x1667cb477a1a8ec338f94741669c976316da6321",
-      "0x01"
+      1
     },
 
     { "brainpoolP192r1", 192, 0,
@@ -251,7 +316,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
       "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f",
-      "0x01"
+      1
     },
 
     { "brainpoolP224r1", 224, 0,
@@ -262,7 +327,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
       "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd",
-      "0x01"
+      1
     },
 
     { "brainpoolP256r1", 256, 0,
@@ -273,7 +338,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
       "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997",
-      "0x01"
+      1
     },
 
     { "brainpoolP320r1", 320, 0,
@@ -290,7 +355,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "10af8d0d39e20611",
       "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
       "d35245d1692e8ee1",
-      "0x01"
+      1
     },
 
     { "brainpoolP384r1", 384, 0,
@@ -307,7 +372,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "e826e03436d646aaef87b2e247d4af1e",
       "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
       "0e4646217791811142820341263c5315",
-      "0x01"
+      1
     },
 
     { "brainpoolP512r1", 512, 0,
@@ -324,7 +389,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
       "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892",
-      "0x01"
+      1
     },
     {
       "GOST2001-test", 256, 0,
@@ -336,7 +401,7 @@ static const ecc_domain_parms_t domain_parms[] =
 
       "0x0000000000000000000000000000000000000000000000000000000000000002",
       "0x08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8",
-      "0x01"
+      1
     },
     {
       "GOST2001-CryptoPro-A", 256, 0,
@@ -347,7 +412,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xffffffffffffffffffffffffffffffff6c611070995ad10045841b09b761b893",
       "0x0000000000000000000000000000000000000000000000000000000000000001",
       "0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14",
-      "0x01"
+      1
     },
     {
       "GOST2001-CryptoPro-B", 256, 0,
@@ -358,7 +423,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x800000000000000000000000000000015f700cfff1a624e5e497161bcc8a198f",
       "0x0000000000000000000000000000000000000000000000000000000000000001",
       "0x3fa8124359f96680b83d1c3eb2c070e5c545c9858d03ecfb744bf8d717717efc",
-      "0x01"
+      1
     },
     {
       "GOST2001-CryptoPro-C", 256, 0,
@@ -369,10 +434,21 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x9b9f605f5a858107ab1ec85e6b41c8aa582ca3511eddfb74f02f3a6598980bb9",
       "0x0000000000000000000000000000000000000000000000000000000000000000",
       "0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67",
-      "0x01"
+      1
     },
     {
-      "GOST2012-test", 511, 0,
+      "GOST2012-256-A", 256, 0,
+      MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
+      "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd97",
+      "0xc2173f1513981673af4892c23035a27ce25e2013bf95aa33b22c656f277e7335",
+      "0x295f9bae7428ed9ccc20e7c359a9d41a22fccd9108e17bf7ba9337a6f8ae9513",
+      "0x400000000000000000000000000000000fd8cddfc87b6635c115af556c360c67",
+      "0x91e38443a5e82c0d880923425712b2bb658b9196932e02c78b2582fe742daa28",
+      "0x32879423ab1a0375895786c4bb46e9565fde0b5344766740af268adb32322e5c",
+      4
+    },
+    {
+      "GOST2012-512-test", 511, 0,
       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
       "0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
       "f1d852741af4704a0458047e80e4546d35b8336fac224dd81664bbf528be6373",
@@ -386,10 +462,10 @@ static const ecc_domain_parms_t domain_parms[] =
       "fd60611262cd838dc6b60aa7eee804e28bc849977fac33b4b530f1b120248a9a",
       "0x2bb312a43bd2ce6e0d020613c857acddcfbf061e91e5f2c3f32447c259f39b2"
       "c83ab156d77f1496bf7eb3351e1ee4e43dc1a18b91b24640b6dbb92cb1add371e",
-      "0x01"
+      1
     },
     {
-      "GOST2012-tc26-A", 512, 0,
+      "GOST2012-512-tc26-A", 512, 0,
       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
       "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
         "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc7",
@@ -403,10 +479,10 @@ static const ecc_domain_parms_t domain_parms[] =
         "0000000000000000000000000000000000000000000000000000000000000003",
       "0x7503cfe87a836ae3a61b8816e25450e6ce5e1c93acf1abc1778064fdcbefa921"
         "df1626be4fd036e93d75e6a50e3a41e98028fe5fc235f5b889a589cb5215f2a4",
-      "0x01"
+      1
     },
     {
-      "GOST2012-tc26-B", 512, 0,
+      "GOST2012-512-tc26-B", 512, 0,
       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
       "0x8000000000000000000000000000000000000000000000000000000000000000"
         "000000000000000000000000000000000000000000000000000000000000006f",
@@ -420,7 +496,24 @@ static const ecc_domain_parms_t domain_parms[] =
         "0000000000000000000000000000000000000000000000000000000000000002",
       "0x1a8f7eda389b094c2c071e3647a8940f3c123b697578c213be6dd9e6c8ec7335"
         "dcb228fd1edf4a39152cbcaaf8c0398828041055f94ceeec7e21340780fe41bd",
-      "0x01"
+      1
+    },
+    {
+      "GOST2012-512-tc26-C", 512, 0,
+      MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
+      "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+        "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc7",
+      "0xdc9203e514a721875485a529d2c722fb187bc8980eb866644de41c68e1430645"
+        "46e861c0e2c9edd92ade71f46fcf50ff2ad97f951fda9f2a2eb6546f39689bd3",
+      "0xb4c4ee28cebc6c2c8ac12952cf37f16ac7efb6a9f69f4b57ffda2e4f0de5ade0"
+        "38cbc2fff719d2c18de0284b8bfef3b52b8cc7a5f5bf0a3c8d2319a5312557e1",
+      "0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+        "c98cdba46506ab004c33a9ff5147502cc8eda9e7a769a12694623cef47f023ed",
+      "0xe2e31edfc23de7bdebe241ce593ef5de2295b7a9cbaef021d385f7074cea043a"
+        "a27272a7ae602bf2a7b9033db9ed3610c6fb85487eae97aac5bc7928c1950148",
+      "0xf5ce40d95b5eb899abbccff5911cb8577939804d6527378b8c108c3d2090ff9be"
+        "18e2d33e3021ed2ef32d85822423b6304f726aa854bae07d0396e9a9addc40f",
+      4
     },
 
     {
@@ -432,7 +525,19 @@ static const ecc_domain_parms_t domain_parms[] =
       "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
       "0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
       "0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
-      "0x01"
+      1
+    },
+
+    {
+      "sm2p256v1", 256, 0,
+      MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
+      "0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff",
+      "0xfffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc",
+      "0x28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93",
+      "0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123",
+      "0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
+      "0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
+      1
     },
 
     { NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }
@@ -563,22 +668,43 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
         {
           curve->a = scanval (domain_parms[idx].a);
           if (curve->a->sign)
-            mpi_add (curve->a, curve->p, curve->a);
+            {
+              mpi_resize (curve->a, curve->p->nlimbs);
+              _gcry_mpih_sub_n (curve->a->d, curve->p->d,
+                                curve->a->d, curve->p->nlimbs);
+              curve->a->nlimbs = curve->p->nlimbs;
+              curve->a->sign = 0;
+            }
         }
       if (!curve->b)
         {
           curve->b = scanval (domain_parms[idx].b);
           if (curve->b->sign)
-            mpi_add (curve->b, curve->p, curve->b);
+            {
+              mpi_resize (curve->b, curve->p->nlimbs);
+              _gcry_mpih_sub_n (curve->b->d, curve->p->d,
+                                curve->b->d, curve->p->nlimbs);
+              curve->b->nlimbs = curve->p->nlimbs;
+              curve->b->sign = 0;
+            }
         }
       if (!curve->n)
         curve->n = scanval (domain_parms[idx].n);
-      if (!curve->h)
-        curve->h = scanval (domain_parms[idx].h);
       if (!curve->G.x)
         curve->G.x = scanval (domain_parms[idx].g_x);
       if (!curve->G.y)
         curve->G.y = scanval (domain_parms[idx].g_y);
+      curve->h = domain_parms[idx].h;
+
+      /*
+       * In the constants of domain_parms, we defined Curve25519
+       * domain parameters as the ones in RFC-7748 before the errata
+       * (eid4730).  To keep the computation having exact same values,
+       * we recover the new value of g_y, here.
+       */
+      if (!strcmp (resname, "Curve25519"))
+        mpi_sub (curve->G.y, curve->p, curve->G.y);
+
       if (!curve->G.z)
         curve->G.z = mpi_alloc_set_ui (1);
       if (!curve->name)
@@ -590,15 +716,15 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
 
 
 /* Give the name of the curve NAME, store the curve parameters into P,
-   A, B, G, N, and H if they point to NULL value.  Note that G is returned
-   in standard uncompressed format.  Also update MODEL and DIALECT if
-   they are not NULL. */
+   A, B, G, and N if they point to NULL value.  Note that G is
+   returned in standard uncompressed format.  Also update MODEL and
+   DIALECT if they are not NULL. */
 gpg_err_code_t
 _gcry_ecc_update_curve_param (const char *name,
                               enum gcry_mpi_ec_models *model,
                               enum ecc_dialects *dialect,
                               gcry_mpi_t *p, gcry_mpi_t *a, gcry_mpi_t *b,
-                              gcry_mpi_t *g, gcry_mpi_t *n, gcry_mpi_t *h)
+                              gcry_mpi_t *g, gcry_mpi_t *n)
 {
   int idx;
 
@@ -648,11 +774,6 @@ _gcry_ecc_update_curve_param (const char *name,
       _gcry_mpi_release (*n);
       *n = scanval (domain_parms[idx].n);
     }
-  if (h)
-    {
-      _gcry_mpi_release (*h);
-      *h = scanval (domain_parms[idx].h);
-    }
   return 0;
 }
 
@@ -665,7 +786,7 @@ _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
   gpg_err_code_t rc;
   const char *result = NULL;
   elliptic_curve_t E;
-  gcry_mpi_t mpi_g = NULL;
+  gcry_mpi_point_t G = NULL;
   gcry_mpi_t tmp = NULL;
   int idx;
 
@@ -690,9 +811,8 @@ _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
   /*
    * Extract the curve parameters..
    */
-  rc = gpg_err_code (sexp_extract_param (keyparms, NULL, "-pabgnh",
-                                         &E.p, &E.a, &E.b, &mpi_g, &E.n, &E.h,
-                                         NULL));
+  rc = gpg_err_code (sexp_extract_param (keyparms, NULL, "pabn",
+                                         &E.p, &E.a, &E.b, &E.n, NULL));
   if (rc == GPG_ERR_NO_OBJ)
     {
       /* This might be the second use case of checking whether a
@@ -723,72 +843,100 @@ _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
   if (rc)
     goto leave;
 
-  if (mpi_g)
-    {
-      _gcry_mpi_point_init (&E.G);
-      if (_gcry_ecc_os2ec (&E.G, mpi_g))
-        goto leave;
-    }
+  rc = point_from_keyparam (&G, keyparms, "g", NULL);
+  if (rc)
+    goto leave;
+
+  _gcry_mpi_point_init (&E.G);
+  _gcry_mpi_point_set (&E.G, G->x, G->y, G->z);
 
   for (idx = 0; domain_parms[idx].desc; idx++)
     {
       mpi_free (tmp);
       tmp = scanval (domain_parms[idx].p);
-      if (!mpi_cmp (tmp, E.p))
+      if (mpi_cmp (tmp, E.p))
+        continue;
+
+      mpi_free (tmp);
+      tmp = scanval (domain_parms[idx].a);
+      if (tmp->sign)
         {
-          mpi_free (tmp);
-          tmp = scanval (domain_parms[idx].a);
-          if (!mpi_cmp (tmp, E.a))
+          if (!mpi_cmpabs (tmp, E.a))
+            /* For backward compatibility to <= libgcrypt 1.8, we
+               allow this match to support existing keys in SEXP.  */
+            ;
+          else
             {
-              mpi_free (tmp);
-              tmp = scanval (domain_parms[idx].b);
-              if (!mpi_cmp (tmp, E.b))
-                {
-                  mpi_free (tmp);
-                  tmp = scanval (domain_parms[idx].n);
-                  if (!mpi_cmp (tmp, E.n))
-                    {
-                      mpi_free (tmp);
-                      tmp = scanval (domain_parms[idx].h);
-                      if (!mpi_cmp (tmp, E.h))
-                        {
-                          mpi_free (tmp);
-                          tmp = scanval (domain_parms[idx].g_x);
-                          if (!mpi_cmp (tmp, E.G.x))
-                            {
-                              mpi_free (tmp);
-                              tmp = scanval (domain_parms[idx].g_y);
-                              if (!mpi_cmp (tmp, E.G.y))
-                                {
-                                  result = domain_parms[idx].desc;
-                                  if (r_nbits)
-                                    *r_nbits = domain_parms[idx].nbits;
-                                  goto leave;
-                                }
-                            }
-                        }
-                    }
-                }
+              mpi_resize (tmp, E.p->nlimbs);
+              _gcry_mpih_sub_n (tmp->d, E.p->d,
+                                tmp->d, E.p->nlimbs);
+              tmp->nlimbs = E.p->nlimbs;
+              tmp->sign = 0;
+              if (mpi_cmp (tmp, E.a))
+                continue;
+            }
+        }
+      else if (mpi_cmp (tmp, E.a))
+        continue;
+
+      mpi_free (tmp);
+      tmp = scanval (domain_parms[idx].b);
+      if (tmp->sign)
+        {
+          if (!mpi_cmpabs (tmp, E.b))
+            /* Same for backward compatibility, see above.  */
+            ;
+          else
+            {
+              mpi_resize (tmp, E.p->nlimbs);
+              _gcry_mpih_sub_n (tmp->d, E.p->d,
+                                tmp->d, E.p->nlimbs);
+              tmp->nlimbs = E.p->nlimbs;
+              tmp->sign = 0;
+              if (mpi_cmp (tmp, E.b))
+                continue;
             }
         }
+      else if (mpi_cmp (tmp, E.b))
+        continue;
+
+      mpi_free (tmp);
+      tmp = scanval (domain_parms[idx].n);
+      if (mpi_cmp (tmp, E.n))
+        continue;
+
+      mpi_free (tmp);
+      tmp = scanval (domain_parms[idx].g_x);
+      if (mpi_cmp (tmp, E.G.x))
+        continue;
+
+      mpi_free (tmp);
+      tmp = scanval (domain_parms[idx].g_y);
+      if (mpi_cmp (tmp, E.G.y))
+        continue;
+
+      result = domain_parms[idx].desc;
+      if (r_nbits)
+        *r_nbits = domain_parms[idx].nbits;
+      break;
     }
 
  leave:
+  _gcry_mpi_point_release (G);
   _gcry_mpi_release (tmp);
   _gcry_mpi_release (E.p);
   _gcry_mpi_release (E.a);
   _gcry_mpi_release (E.b);
-  _gcry_mpi_release (mpi_g);
   _gcry_mpi_point_free_parts (&E.G);
   _gcry_mpi_release (E.n);
-  _gcry_mpi_release (E.h);
   return result;
 }
 
 
 /* Helper to extract an MPI from key parameters.  */
 static gpg_err_code_t
-mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
+mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name,
+                   int opaque)
 {
   gcry_err_code_t ec = 0;
   gcry_sexp_t l1;
@@ -796,7 +944,7 @@ mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
   l1 = sexp_find_token (keyparam, name, 0);
   if (l1)
     {
-      *r_a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
+      *r_a = sexp_nth_mpi (l1, 1, opaque? GCRYMPI_FMT_OPAQUE : GCRYMPI_FMT_USG);
       sexp_release (l1);
       if (!*r_a)
         ec = GPG_ERR_INV_OBJ;
@@ -828,10 +976,7 @@ point_from_keyparam (gcry_mpi_point_t *r_a,
         return GPG_ERR_INV_OBJ;
 
       point = mpi_point_new (0);
-      if (ec && ec->dialect == ECC_DIALECT_ED25519)
-        rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL);
-      else
-        rc = _gcry_ecc_os2ec (point, a);
+      rc = _gcry_mpi_ec_decode_point (point, a, ec);
       mpi_free (a);
       if (rc)
         {
@@ -850,14 +995,14 @@ point_from_keyparam (gcry_mpi_point_t *r_a,
       if (!tmpname)
         return gpg_err_code_from_syserror ();
       strcpy (stpcpy (tmpname, name), ".x");
-      rc = mpi_from_keyparam (&x, keyparam, tmpname);
+      rc = mpi_from_keyparam (&x, keyparam, tmpname, 0);
       if (rc)
         {
           xfree (tmpname);
           return rc;
         }
       strcpy (stpcpy (tmpname, name), ".y");
-      rc = mpi_from_keyparam (&y, keyparam, tmpname);
+      rc = mpi_from_keyparam (&y, keyparam, tmpname, 0);
       if (rc)
         {
           mpi_free (x);
@@ -865,7 +1010,7 @@ point_from_keyparam (gcry_mpi_point_t *r_a,
           return rc;
         }
       strcpy (stpcpy (tmpname, name), ".z");
-      rc = mpi_from_keyparam (&z, keyparam, tmpname);
+      rc = mpi_from_keyparam (&z, keyparam, tmpname, 0);
       if (rc)
         {
           mpi_free (y);
@@ -893,33 +1038,22 @@ point_from_keyparam (gcry_mpi_point_t *r_a,
 }
 
 
-/* This function creates a new context for elliptic curve operations.
-   Either KEYPARAM or CURVENAME must be given.  If both are given and
-   KEYPARAM has no curve parameter, CURVENAME is used to add missing
-   parameters.  On success 0 is returned and the new context stored at
-   R_CTX.  On error NULL is stored at R_CTX and an error code is
-   returned.  The context needs to be released using
-   gcry_ctx_release.  */
-gpg_err_code_t
-_gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
-                  gcry_sexp_t keyparam, const char *curvename)
+
+static gpg_err_code_t
+mpi_ec_get_elliptic_curve (elliptic_curve_t *E, int *r_flags,
+                           gcry_sexp_t keyparam, const char *curvename)
 {
   gpg_err_code_t errc;
-  gcry_ctx_t ctx = NULL;
-  enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS;
-  enum ecc_dialects dialect = ECC_DIALECT_STANDARD;
-  gcry_mpi_t p = NULL;
-  gcry_mpi_t a = NULL;
-  gcry_mpi_t b = NULL;
-  gcry_mpi_point_t G = NULL;
-  gcry_mpi_t n = NULL;
-  gcry_mpi_t h = NULL;
-  gcry_mpi_point_t Q = NULL;
-  gcry_mpi_t d = NULL;
-  int flags = 0;
+  unsigned int nbits;
   gcry_sexp_t l1;
 
-  *r_ctx = NULL;
+  errc = _gcry_pk_util_get_nbits (keyparam, &nbits);
+  if (errc)
+    return errc;
+
+  E->model = MPI_EC_WEIERSTRASS;
+  E->dialect = ECC_DIALECT_STANDARD;
+  E->h = 1;
 
   if (keyparam)
     {
@@ -927,11 +1061,23 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
       l1 = sexp_find_token (keyparam, "flags", 0);
       if (l1)
         {
+          int flags = 0;
+
           errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
           sexp_release (l1);
           l1 = NULL;
           if (errc)
             goto leave;
+
+          *r_flags |= flags;
+        }
+
+      /* Parse the deprecated optional transient-key flag.  */
+      l1 = sexp_find_token (keyparam, "transient-key", 0);
+      if (l1)
+        {
+          *r_flags |= PUBKEY_FLAG_TRANSIENT_KEY;
+          sexp_release (l1);
         }
 
       /* Check whether a curve name was given.  */
@@ -939,26 +1085,41 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
 
       /* If we don't have a curve name or if override parameters have
          explicitly been requested, parse them.  */
-      if (!l1 || (flags & PUBKEY_FLAG_PARAM))
+      if (!l1 || (*r_flags & PUBKEY_FLAG_PARAM))
         {
-          errc = mpi_from_keyparam (&p, keyparam, "p");
+          gcry_mpi_point_t G = NULL;
+          gcry_mpi_t cofactor = NULL;
+
+          errc = mpi_from_keyparam (&E->p, keyparam, "p", 0);
           if (errc)
             goto leave;
-          errc = mpi_from_keyparam (&a, keyparam, "a");
+          errc = mpi_from_keyparam (&E->a, keyparam, "a", 0);
           if (errc)
             goto leave;
-          errc = mpi_from_keyparam (&b, keyparam, "b");
+          errc = mpi_from_keyparam (&E->b, keyparam, "b", 0);
           if (errc)
             goto leave;
           errc = point_from_keyparam (&G, keyparam, "g", NULL);
           if (errc)
             goto leave;
-          errc = mpi_from_keyparam (&n, keyparam, "n");
+          if (G)
+            {
+              _gcry_mpi_point_init (&E->G);
+              mpi_point_set (&E->G, G->x, G->y, G->z);
+              mpi_point_set (G, NULL, NULL, NULL);
+              mpi_point_release (G);
+            }
+          errc = mpi_from_keyparam (&E->n, keyparam, "n", 0);
           if (errc)
             goto leave;
-          errc = mpi_from_keyparam (&h, keyparam, "h");
+          errc = mpi_from_keyparam (&cofactor, keyparam, "h", 0);
           if (errc)
             goto leave;
+          if (cofactor)
+            {
+              mpi_get_ui (&E->h, cofactor);
+              mpi_free (cofactor);
+            }
         }
     }
   else
@@ -968,10 +1129,9 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
      in missing values.  If no curve parameter is available try an
      optional provided curvename.  If only the curvename has been
      given use that one. */
-  if (l1 || curvename)
+  if (l1 || curvename || nbits)
     {
       char *name;
-      elliptic_curve_t *E;
 
       if (l1)
         {
@@ -986,129 +1146,231 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
       else
         name = NULL;
 
-      E = xtrycalloc (1, sizeof *E);
-      if (!E)
-        {
-          errc = gpg_err_code_from_syserror ();
-          xfree (name);
-          goto leave;
-        }
-
-      errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL);
+      errc = _gcry_ecc_fill_in_curve (nbits, name? name : curvename, E, NULL);
       xfree (name);
       if (errc)
-        {
-          xfree (E);
-          goto leave;
-        }
+        goto leave;
+    }
+
+ leave:
+  return errc;
+}
 
-      model = E->model;
-      dialect = E->dialect;
+static gpg_err_code_t
+mpi_ec_setup_elliptic_curve (mpi_ec_t ec, int flags,
+                             elliptic_curve_t *E, gcry_sexp_t keyparam)
+{
+  gpg_err_code_t errc = 0;
+
+  ec->G = mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
+  E->G.x = NULL;
+  E->G.y = NULL;
+  E->G.z = NULL;
+  ec->n = E->n;
+  E->n = NULL;
+  ec->h = E->h;
+  ec->name = E->name;
+
+  /* Now that we know the curve name we can look for the public key
+     Q.  point_from_keyparam needs to know the curve parameters so
+     that it is able to use the correct decompression.  Parsing
+     the private key D could have been done earlier but it is less
+     surprising if we do it here as well.  */
+  if (keyparam)
+    {
+      int is_opaque_bytes = ((ec->dialect == ECC_DIALECT_ED25519
+                              && (flags & PUBKEY_FLAG_EDDSA))
+                             || (ec->dialect == ECC_DIALECT_SAFECURVE));
 
-      if (!p)
-        {
-          p = E->p;
-          E->p = NULL;
-        }
-      if (!a)
-        {
-          a = E->a;
-          E->a = NULL;
-        }
-      if (!b)
-        {
-          b = E->b;
-          E->b = NULL;
-        }
-      if (!G)
-        {
-          G = mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
-          E->G.x = NULL;
-          E->G.y = NULL;
-          E->G.z = NULL;
-        }
-      if (!n)
-        {
-          n = E->n;
-          E->n = NULL;
-        }
-      if (!h)
+      errc = point_from_keyparam (&ec->Q, keyparam, "q", ec);
+      if (errc)
+        return errc;
+      errc = mpi_from_keyparam (&ec->d, keyparam, "d", is_opaque_bytes);
+
+      /* Size of opaque bytes should match size of P.  */
+      if (!errc && ec->d && is_opaque_bytes)
         {
-          h = E->h;
-          E->h = NULL;
+          unsigned int n = mpi_get_nbits (ec->d);
+          unsigned int len;
+
+          len = (ec->nbits+7)/8;
+          /* EdDSA requires additional bit for sign.  */
+          if ((ec->nbits%8) == 0 && ec->model == MPI_EC_EDWARDS)
+            len++;
+
+          if ((n+7)/8 != len)
+            {
+              if (ec->dialect == ECC_DIALECT_ED25519)
+                {
+                  /*
+                   * GnuPG (<= 2.2) or OpenPGP implementations with no
+                   * SOS support may remove zeros at the beginning.
+                   * Recover those zeros.
+                   */
+                  /*
+                   * Also, GnuPG (<= 2.2) may add additional zero at
+                   * the beginning, when private key is moved from
+                   * OpenPGP to gpg-agent.  Remove such a zero-prefix.
+                   */
+                  const unsigned char *buf;
+                  unsigned char *value;
+
+                  buf = mpi_get_opaque (ec->d, &n);
+                  if (!buf)
+                    return GPG_ERR_INV_OBJ;
+
+                  value = xtrymalloc_secure (len);
+                  if (!value)
+                    return gpg_err_code_from_syserror ();
+
+                  if ((n+7)/8 < len)
+                    /* Recover zeros.  */
+                    {
+                      memset (value, 0, len - (n+7)/8);
+                      memcpy (value + len - (n+7)/8, buf, (n+7)/8);
+                    }
+                  else if ((n+7)/8 == len + 1)
+                    /* Remove a zero.  */
+                    memcpy (value, buf+1, len);
+                  else
+                    {
+                      xfree (value);
+                      return GPG_ERR_INV_OBJ;
+                    }
+
+                  mpi_set_opaque (ec->d, value, len*8);
+                }
+              else
+                {
+                  if (DBG_CIPHER)
+                    log_debug ("scalar size (%d) != prime size (%d)",
+                               (n+7)/8, len);
+
+                  errc = GPG_ERR_INV_OBJ;
+                }
+            }
         }
-      _gcry_ecc_curve_free (E);
-      xfree (E);
     }
 
+  return errc;
+}
+
+gpg_err_code_t
+_gcry_mpi_ec_internal_new (mpi_ec_t *r_ec, int *r_flags, const char *name_op,
+                           gcry_sexp_t keyparam, const char *curvename)
+{
+  gpg_err_code_t errc;
+  elliptic_curve_t E;
+  mpi_ec_t ec;
+
+  *r_ec = NULL;
+
+  memset (&E, 0, sizeof E);
+  errc = mpi_ec_get_elliptic_curve (&E, r_flags, keyparam, curvename);
+  if (errc)
+    goto leave;
+
+  ec = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, *r_flags,
+                                    E.p, E.a, E.b);
+  if (!ec)
+    goto leave;
 
-  errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b);
-  if (!errc)
+  errc = mpi_ec_setup_elliptic_curve (ec, *r_flags, &E, keyparam);
+  if (errc)
     {
-      mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+      _gcry_mpi_ec_free (ec);
+      goto leave;
+    }
+  else
+    *r_ec = ec;
 
-      if (b)
-        {
-          mpi_free (ec->b);
-          ec->b = b;
-          b = NULL;
-        }
-      if (G)
-        {
-          ec->G = G;
-          G = NULL;
-        }
-      if (n)
-        {
-          ec->n = n;
-          n = NULL;
-        }
-      if (h)
-        {
-          ec->h = h;
-          h = NULL;
-        }
+  if (!errc && DBG_CIPHER)
+    {
+      gcry_mpi_t mpi_q = NULL;
+      gcry_sexp_t l1;
+      char msg[80];
 
-      /* Now that we know the curve name we can look for the public key
-         Q.  point_from_keyparam needs to know the curve parameters so
-         that it is able to use the correct decompression.  Parsing
-         the private key D could have been done earlier but it is less
-         surprising if we do it here as well.  */
-      if (keyparam)
+      l1 = sexp_find_token (keyparam, "q", 0);
+      if (l1)
         {
-          errc = point_from_keyparam (&Q, keyparam, "q", ec);
-          if (errc)
-            goto leave;
-          errc = mpi_from_keyparam (&d, keyparam, "d");
-          if (errc)
-            goto leave;
+          mpi_q = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
+          sexp_release (l1);
         }
 
-      if (Q)
+      log_debug ("%s info: %s/%s%s\n", name_op,
+                 _gcry_ecc_model2str (ec->model),
+                 _gcry_ecc_dialect2str (ec->dialect),
+                 (*r_flags & PUBKEY_FLAG_EDDSA)? "+EdDSA" : "");
+      if (ec->name)
+        log_debug  ("%s name: %s\n", name_op, ec->name);
+      snprintf (msg, sizeof msg, "%s    p", name_op);
+      log_printmpi (msg, ec->p);
+      snprintf (msg, sizeof msg, "%s    a", name_op);
+      log_printmpi (msg, ec->a);
+      snprintf (msg, sizeof msg, "%s    b", name_op);
+      log_printmpi (msg, ec->b);
+      snprintf (msg, sizeof msg, "%s  g", name_op);
+      log_printpnt (msg, ec->G, NULL);
+      snprintf (msg, sizeof msg, "%s    n", name_op);
+      log_printmpi (msg, ec->n);
+      log_debug ("%s    h:+%02x\n", name_op, ec->h);
+      if (mpi_q)
         {
-          ec->Q = Q;
-          Q = NULL;
+          snprintf (msg, sizeof msg, "%s    q", name_op);
+          log_printmpi (msg, mpi_q);
+          mpi_free (mpi_q);
         }
-      if (d)
+      if (!fips_mode () && ec->d)
         {
-          ec->d = d;
-          d = NULL;
+          snprintf (msg, sizeof msg, "%s    d", name_op);
+          log_printmpi (msg, ec->d);
         }
-
-      *r_ctx = ctx;
-      ctx = NULL;
     }
 
  leave:
+  _gcry_ecc_curve_free (&E);
+  return errc;
+}
+
+/* This function creates a new context for elliptic curve operations.
+   Either KEYPARAM or CURVENAME must be given.  If both are given and
+   KEYPARAM has no curve parameter, CURVENAME is used to add missing
+   parameters.  On success 0 is returned and the new context stored at
+   R_CTX.  On error NULL is stored at R_CTX and an error code is
+   returned.  The context needs to be released using
+   gcry_ctx_release.  */
+gpg_err_code_t
+_gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
+                  gcry_sexp_t keyparam, const char *curvename)
+{
+  gpg_err_code_t errc;
+  elliptic_curve_t E;
+  gcry_ctx_t ctx = NULL;
+  int flags = 0;
+  mpi_ec_t ec;
+
+  *r_ctx = NULL;
+
+  memset (&E, 0, sizeof E);
+  errc = mpi_ec_get_elliptic_curve (&E, &flags, keyparam, curvename);
+  if (errc)
+    goto leave;
+
+  errc = _gcry_mpi_ec_p_new (&ctx, E.model, E.dialect, flags, E.p, E.a, E.b);
+  if (errc)
+    goto leave;
+
+  ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+  errc = mpi_ec_setup_elliptic_curve (ec, flags, &E, keyparam);
+  if (errc)
+    goto leave;
+
+  *r_ctx = ctx;
+  ctx = NULL;
+
+ leave:
+  _gcry_ecc_curve_free (&E);
   _gcry_ctx_release (ctx);
-  mpi_free (p);
-  mpi_free (a);
-  mpi_free (b);
-  _gcry_mpi_point_release (G);
-  mpi_free (n);
-  mpi_free (h);
-  _gcry_mpi_point_release (Q);
-  mpi_free (d);
   return errc;
 }
 
@@ -1117,47 +1379,27 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
 gcry_sexp_t
 _gcry_ecc_get_param_sexp (const char *name)
 {
-  unsigned int nbits;
   elliptic_curve_t E;
-  mpi_ec_t ctx;
-  gcry_mpi_t g_x, g_y;
-  gcry_mpi_t pkey[7];
+  gcry_mpi_t pkey[5];
   gcry_sexp_t result;
-  int i;
 
   memset (&E, 0, sizeof E);
-  if (_gcry_ecc_fill_in_curve (0, name, &E, &nbits))
+  if (_gcry_ecc_fill_in_curve (0, name, &E, NULL))
     return NULL;
 
-  g_x = mpi_new (0);
-  g_y = mpi_new (0);
-  ctx = _gcry_mpi_ec_p_internal_new (MPI_EC_WEIERSTRASS,
-                                     ECC_DIALECT_STANDARD,
-                                     0,
-                                     E.p, E.a, NULL);
-  if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
-    log_fatal ("ecc get param: Failed to get affine coordinates\n");
-  _gcry_mpi_ec_free (ctx);
-  _gcry_mpi_point_free_parts (&E.G);
-
   pkey[0] = E.p;
   pkey[1] = E.a;
   pkey[2] = E.b;
-  pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p);
+  pkey[3] = _gcry_ecc_ec2os (E.G.x, E.G.y, E.p);
   pkey[4] = E.n;
-  pkey[5] = E.h;
-  pkey[6] = NULL;
-
-  mpi_free (g_x);
-  mpi_free (g_y);
 
   if (sexp_build (&result, NULL,
-                  "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)))",
-                  pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]))
+                  "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%u)))",
+                  pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], E.h))
     result = NULL;
 
-  for (i=0; pkey[i]; i++)
-    _gcry_mpi_release (pkey[i]);
+  _gcry_ecc_curve_free (&E);
+  _gcry_mpi_release (pkey[3]);
 
   return result;
 }
@@ -1180,8 +1422,12 @@ _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
     return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b);
   if (!strcmp (name, "n") && ec->n)
     return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n);
-  if (!strcmp (name, "h") && ec->h)
-    return mpi_is_const (ec->h) && !copy? ec->h : mpi_copy (ec->h);
+  if (!strcmp (name, "h"))
+    {
+      gcry_mpi_t h = _gcry_mpi_get_const (ec->h);
+
+      return !copy? h : mpi_set (NULL, h);
+    }
   if (!strcmp (name, "d") && ec->d)
     return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d);
 
@@ -1207,7 +1453,7 @@ _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
     {
       /* If only the private key is given, compute the public key.  */
       if (!ec->Q)
-        ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
+        ec->Q = _gcry_ecc_compute_public (NULL, ec);
 
       if (!ec->Q)
         return NULL;
@@ -1240,7 +1486,7 @@ _gcry_ecc_get_point (const char *name, mpi_ec_t ec)
     {
       /* If only the private key is given, compute the public key.  */
       if (!ec->Q)
-        ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
+        ec->Q = _gcry_ecc_compute_public (NULL, ec);
 
       if (ec->Q)
         return point_copy (ec->Q);
@@ -1282,8 +1528,7 @@ _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
     }
   else if (!strcmp (name, "h"))
     {
-      mpi_free (ec->h);
-      ec->h = mpi_copy (newvalue);
+      mpi_get_ui (&ec->h, newvalue);
     }
   else if (*name == 'q' && (!name[1] || name[1] == '@'))
     {
@@ -1291,10 +1536,7 @@ _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
         {
           if (!ec->Q)
             ec->Q = mpi_point_new (0);
-          if (ec->dialect == ECC_DIALECT_ED25519)
-            rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL);
-          else
-            rc = _gcry_ecc_os2ec (ec->Q, newvalue);
+          rc = _gcry_mpi_ec_decode_point (ec->Q, newvalue, ec);
         }
       if (rc || !newvalue)
         {
diff --git a/cipher/ecc-ecdh.c b/cipher/ecc-ecdh.c
new file mode 100644 (file)
index 0000000..d6b8991
--- /dev/null
@@ -0,0 +1,127 @@
+/* ecc-ecdh.c  -  Elliptic Curve Diffie-Hellman key agreement
+ * Copyright (C) 2019 g10 Code GmbH
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "mpi.h"
+#include "cipher.h"
+#include "context.h"
+#include "ec-context.h"
+#include "ecc-common.h"
+
+#define ECC_CURVE25519_BYTES 32
+#define ECC_CURVE448_BYTES   56
+
+static gpg_err_code_t
+prepare_ec (mpi_ec_t *r_ec, const char *name)
+{
+  int flags = 0;
+
+  if (!strcmp (name, "Curve25519"))
+    flags = PUBKEY_FLAG_DJB_TWEAK;
+
+  return _gcry_mpi_ec_internal_new (r_ec, &flags, "ecc_mul_point", NULL, name);
+}
+
+unsigned int
+_gcry_ecc_get_algo_keylen (int curveid)
+{
+  unsigned int len = 0;
+
+  if (curveid == GCRY_ECC_CURVE25519)
+    len = ECC_CURVE25519_BYTES;
+  else if (curveid == GCRY_ECC_CURVE448)
+    len = ECC_CURVE448_BYTES;
+
+  return len;
+}
+
+gpg_error_t
+_gcry_ecc_mul_point (int curveid, unsigned char *result,
+                     const unsigned char *scalar, const unsigned char *point)
+{
+  unsigned int nbits;
+  unsigned int nbytes;
+  const char *curve;
+  gpg_err_code_t err;
+  gcry_mpi_t mpi_k;
+  mpi_ec_t ec;
+  mpi_point_struct Q;
+  gcry_mpi_t x;
+  unsigned int len;
+  unsigned char *buf;
+
+  if (curveid == GCRY_ECC_CURVE25519)
+    curve = "Curve25519";
+  else if (curveid == GCRY_ECC_CURVE448)
+    curve = "X448";
+  else
+    return gpg_error (GPG_ERR_UNKNOWN_CURVE);
+
+  err = prepare_ec (&ec, curve);
+  if (err)
+    return err;
+
+  nbits = ec->nbits;
+  nbytes = (nbits + 7)/8;
+
+  mpi_k = _gcry_mpi_set_opaque_copy (NULL, scalar, nbytes*8);
+  x = mpi_new (nbits);
+  point_init (&Q);
+
+  if (point)
+    {
+      gcry_mpi_t mpi_u = _gcry_mpi_set_opaque_copy (NULL, point, nbytes*8);
+      mpi_point_struct P;
+
+      point_init (&P);
+      err = _gcry_ecc_mont_decodepoint (mpi_u, ec, &P);
+      _gcry_mpi_release (mpi_u);
+      if (err)
+        goto leave;
+      _gcry_mpi_ec_mul_point (&Q, mpi_k, &P, ec);
+      point_free (&P);
+    }
+  else
+    _gcry_mpi_ec_mul_point (&Q, mpi_k, ec->G, ec);
+
+  _gcry_mpi_ec_get_affine (x, NULL, &Q, ec);
+
+  buf = _gcry_mpi_get_buffer (x, nbytes, &len, NULL);
+  if (!buf)
+    err = gpg_error_from_syserror ();
+  else
+    {
+      memcpy (result, buf, nbytes);
+      xfree (buf);
+    }
+
+ leave:
+  _gcry_mpi_release (x);
+  point_free (&Q);
+  _gcry_mpi_release (mpi_k);
+  _gcry_mpi_ec_free (ec);
+  return err;
+}
index 140e8c0..3f3ef97 100644 (file)
@@ -38,7 +38,7 @@
  * must have allocated R and S.
  */
 gpg_err_code_t
-_gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
+_gcry_ecc_ecdsa_sign (gcry_mpi_t input, gcry_mpi_t k_supplied, mpi_ec_t ec,
                       gcry_mpi_t r, gcry_mpi_t s,
                       int flags, int hashalgo)
 {
@@ -49,28 +49,40 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
   gcry_mpi_t hash;
   const void *abuf;
   unsigned int abits, qbits;
-  mpi_ec_t ctx;
   gcry_mpi_t b;                /* Random number needed for blinding.  */
   gcry_mpi_t bi;               /* multiplicative inverse of B.        */
+  gcry_mpi_t hash_computed_internally = NULL;
 
   if (DBG_CIPHER)
     log_mpidump ("ecdsa sign hash  ", input );
 
-  qbits = mpi_get_nbits (skey->E.n);
+  qbits = mpi_get_nbits (ec->n);
+
+  if ((flags & PUBKEY_FLAG_PREHASH))
+    {
+      rc = _gcry_dsa_compute_hash (&hash_computed_internally, input, hashalgo);
+      if (rc)
+        return rc;
+      input = hash_computed_internally;
+    }
 
   /* Convert the INPUT into an MPI if needed.  */
   rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
+
   if (rc)
-    return rc;
+    {
+      mpi_free (hash_computed_internally);
+      return rc;
+    }
 
   b  = mpi_snew (qbits);
   bi = mpi_snew (qbits);
   do
     {
       _gcry_mpi_randomize (b, qbits, GCRY_WEAK_RANDOM);
-      mpi_mod (b, b, skey->E.n);
+      mpi_mod (b, b, ec->n);
     }
-  while (!mpi_invm (bi, b, skey->E.n));
+  while (!mpi_invm (bi, b, ec->n));
 
   k = NULL;
   dr = mpi_alloc (0);
@@ -79,62 +91,84 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
   x = mpi_alloc (0);
   point_init (&I);
 
-  ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0,
-                                     skey->E.p, skey->E.a, skey->E.b);
-
   /* Two loops to avoid R or S are zero.  This is more of a joke than
      a real demand because the probability of them being zero is less
      than any hardware failure.  Some specs however require it.  */
-  do
+  while (1)
     {
-      do
+      while (1)
         {
-          mpi_free (k);
-          k = NULL;
-          if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
+          if (k_supplied)
+            k = k_supplied;
+          else
             {
-              /* Use Pornin's method for deterministic DSA.  If this
-                 flag is set, it is expected that HASH is an opaque
-                 MPI with the to be signed hash.  That hash is also
-                 used as h1 from 3.2.a.  */
-              if (!mpi_is_opaque (input))
+              mpi_free (k);
+              k = NULL;
+              if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
                 {
-                  rc = GPG_ERR_CONFLICT;
-                  goto leave;
-                }
+                  /* Use Pornin's method for deterministic DSA.  If this
+                     flag is set, it is expected that HASH is an opaque
+                     MPI with the to be signed hash.  That hash is also
+                     used as h1 from 3.2.a.  */
+                  if (!mpi_is_opaque (input))
+                    {
+                      rc = GPG_ERR_CONFLICT;
+                      goto leave;
+                    }
 
-              abuf = mpi_get_opaque (input, &abits);
-              rc = _gcry_dsa_gen_rfc6979_k (&k, skey->E.n, skey->d,
-                                            abuf, (abits+7)/8,
-                                            hashalgo, extraloops);
-              if (rc)
-                goto leave;
-              extraloops++;
+                  abuf = mpi_get_opaque (input, &abits);
+                  rc = _gcry_dsa_gen_rfc6979_k (&k, ec->n, ec->d,
+                                                abuf, (abits+7)/8,
+                                                hashalgo, extraloops);
+                  if (rc)
+                    goto leave;
+                  extraloops++;
+                }
+              else
+                k = _gcry_dsa_gen_k (ec->n, GCRY_STRONG_RANDOM);
             }
-          else
-            k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM);
 
-          _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
-          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
+          mpi_invm (k_1, k, ec->n);     /* k_1 = k^(-1) mod n  */
+
+          _gcry_dsa_modify_k (k, ec->n, qbits);
+
+          _gcry_mpi_ec_mul_point (&I, k, ec->G, ec);
+          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ec))
             {
               if (DBG_CIPHER)
                 log_debug ("ecc sign: Failed to get affine coordinates\n");
               rc = GPG_ERR_BAD_SIGNATURE;
               goto leave;
             }
-          mpi_mod (r, x, skey->E.n);  /* r = x mod n */
+          mpi_mod (r, x, ec->n);  /* r = x mod n */
+
+          if (mpi_cmp_ui (r, 0))
+            break;
+
+          if (k_supplied)
+            {
+              rc = GPG_ERR_INV_VALUE;
+              goto leave;
+            }
+        }
+
+      /* Computation of dr, sum, and s are blinded with b.  */
+      mpi_mulm (dr, b, ec->d, ec->n);
+      mpi_mulm (dr, dr, r, ec->n);      /* dr = d*r mod n */
+      mpi_mulm (sum, b, hash, ec->n);
+      mpi_addm (sum, sum, dr, ec->n);   /* sum = hash + (d*r) mod n */
+      mpi_mulm (s, k_1, sum, ec->n);    /* s = k^(-1)*(hash+(d*r)) mod n */
+      /* Undo blinding by b^-1 */
+      mpi_mulm (s, bi, s, ec->n);
+      if (mpi_cmp_ui (s, 0))
+        break;
+
+      if (k_supplied)
+        {
+          rc = GPG_ERR_INV_VALUE;
+          break;
         }
-      while (!mpi_cmp_ui (r, 0));
-
-      mpi_mulm (dr, b, skey->d, skey->E.n);
-      mpi_mulm (dr, dr, r, skey->E.n);      /* dr = d*r mod n (blinded with b) */
-      mpi_mulm (sum, b, hash, skey->E.n);
-      mpi_addm (sum, sum, dr, skey->E.n);   /* sum = hash + (d*r) mod n  (blinded with b) */
-      mpi_mulm (sum, bi, sum, skey->E.n);   /* undo blinding by b^-1 */
-      mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
-      mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
     }
-  while (!mpi_cmp_ui (s, 0));
 
   if (DBG_CIPHER)
     {
@@ -145,16 +179,17 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
  leave:
   mpi_free (b);
   mpi_free (bi);
-  _gcry_mpi_ec_free (ctx);
   point_free (&I);
   mpi_free (x);
   mpi_free (k_1);
   mpi_free (sum);
   mpi_free (dr);
-  mpi_free (k);
+  if (!k_supplied)
+    mpi_free (k);
 
   if (hash != input)
     mpi_free (hash);
+  mpi_free (hash_computed_internally);
 
   return rc;
 }
@@ -164,24 +199,39 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
  * Check if R and S verifies INPUT.
  */
 gpg_err_code_t
-_gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
-                        gcry_mpi_t r, gcry_mpi_t s)
+_gcry_ecc_ecdsa_verify (gcry_mpi_t input, mpi_ec_t ec,
+                        gcry_mpi_t r, gcry_mpi_t s, int flags, int hashalgo)
 {
   gpg_err_code_t err = 0;
   gcry_mpi_t hash, h, h1, h2, x;
   mpi_point_struct Q, Q1, Q2;
-  mpi_ec_t ctx;
   unsigned int nbits;
+  gcry_mpi_t hash_computed_internally = NULL;
 
-  if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
+  if (!_gcry_mpi_ec_curve_point (ec->Q, ec))
+    return GPG_ERR_BROKEN_PUBKEY;
+
+  if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, ec->n) < 0) )
     return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n  failed.  */
-  if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
+  if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, ec->n) < 0) )
     return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n  failed.  */
 
-  nbits = mpi_get_nbits (pkey->E.n);
+  nbits = mpi_get_nbits (ec->n);
+  if ((flags & PUBKEY_FLAG_PREHASH))
+    {
+      err = _gcry_dsa_compute_hash (&hash_computed_internally, input,
+                                    hashalgo);
+      if (err)
+        return err;
+      input = hash_computed_internally;
+    }
+
   err = _gcry_dsa_normalize_hash (input, &hash, nbits);
   if (err)
-    return err;
+    {
+      mpi_free (hash_computed_internally);
+      return err;
+    }
 
   h  = mpi_alloc (0);
   h1 = mpi_alloc (0);
@@ -191,21 +241,18 @@ _gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
   point_init (&Q1);
   point_init (&Q2);
 
-  ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0,
-                                     pkey->E.p, pkey->E.a, pkey->E.b);
-
   /* h  = s^(-1) (mod n) */
-  mpi_invm (h, s, pkey->E.n);
+  mpi_invm (h, s, ec->n);
   /* h1 = hash * s^(-1) (mod n) */
-  mpi_mulm (h1, hash, h, pkey->E.n);
+  mpi_mulm (h1, hash, h, ec->n);
   /* Q1 = [ hash * s^(-1) ]G  */
-  _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx);
+  _gcry_mpi_ec_mul_point (&Q1, h1, ec->G, ec);
   /* h2 = r * s^(-1) (mod n) */
-  mpi_mulm (h2, r, h, pkey->E.n);
+  mpi_mulm (h2, r, h, ec->n);
   /* Q2 = [ r * s^(-1) ]Q */
-  _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx);
+  _gcry_mpi_ec_mul_point (&Q2, h2, ec->Q, ec);
   /* Q  = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
-  _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);
+  _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ec);
 
   if (!mpi_cmp_ui (Q.z, 0))
     {
@@ -214,14 +261,14 @@ _gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
       err = GPG_ERR_BAD_SIGNATURE;
       goto leave;
     }
-  if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ctx))
+  if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ec))
     {
       if (DBG_CIPHER)
         log_debug ("ecc verify: Failed to get affine coordinates\n");
       err = GPG_ERR_BAD_SIGNATURE;
       goto leave;
     }
-  mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */
+  mpi_mod (x, x, ec->n); /* x = x mod E_n */
   if (mpi_cmp (x, r))   /* x != r */
     {
       if (DBG_CIPHER)
@@ -235,7 +282,6 @@ _gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
     }
 
  leave:
-  _gcry_mpi_ec_free (ctx);
   point_free (&Q2);
   point_free (&Q1);
   point_free (&Q);
@@ -245,6 +291,7 @@ _gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
   mpi_free (h);
   if (hash != input)
     mpi_free (hash);
+  mpi_free (hash_computed_internally);
 
   return err;
 }
index 89b708a..ce79b48 100644 (file)
@@ -32,7 +32,7 @@
 
 
 \f
-static void
+void
 reverse_buffer (unsigned char *buffer, unsigned int length)
 {
   unsigned int tmp, i;
@@ -66,11 +66,12 @@ scanval (const char *string)
    malloced buffer with the encoded point is stored at R_BUFFER; the
    length of this buffer is stored at R_BUFLEN.  */
 static gpg_err_code_t
-eddsa_encodempi (gcry_mpi_t mpi, unsigned int minlen,
+eddsa_encodempi (gcry_mpi_t mpi, unsigned int nbits,
                  unsigned char **r_buffer, unsigned int *r_buflen)
 {
   unsigned char *rawmpi;
   unsigned int rawmpilen;
+  unsigned int minlen = (nbits%8) == 0 ? (nbits/8 + 1): (nbits+7)/8;
 
   rawmpi = _gcry_mpi_get_buffer (mpi, minlen, &rawmpilen, NULL);
   if (!rawmpi)
@@ -82,19 +83,20 @@ eddsa_encodempi (gcry_mpi_t mpi, unsigned int minlen,
 }
 
 
-/* Encode (X,Y) using the EdDSA scheme.  MINLEN is the required length
-   in bytes for the result.  If WITH_PREFIX is set the returned buffer
-   is prefixed with a 0x40 byte.  On success 0 is returned and a
-   malloced buffer with the encoded point is stored at R_BUFFER; the
+/* Encode (X,Y) using the EdDSA scheme.  NBITS is the number of bits
+   of the field of the curve.  If WITH_PREFIX is set the returned
+   buffer is prefixed with a 0x40 byte.  On success 0 is returned and
+   malloced buffer with the encoded point is stored at R_BUFFER; the
    length of this buffer is stored at R_BUFLEN.  */
 static gpg_err_code_t
-eddsa_encode_x_y (gcry_mpi_t x, gcry_mpi_t y, unsigned int minlen,
+eddsa_encode_x_y (gcry_mpi_t x, gcry_mpi_t y, unsigned int nbits,
                   int with_prefix,
                   unsigned char **r_buffer, unsigned int *r_buflen)
 {
   unsigned char *rawmpi;
   unsigned int rawmpilen;
   int off = with_prefix? 1:0;
+  unsigned int minlen = (nbits%8) == 0 ? (nbits/8 + 1): (nbits+7)/8;
 
   rawmpi = _gcry_mpi_get_buffer_extra (y, minlen, off?-1:0, &rawmpilen, NULL);
   if (!rawmpi)
@@ -133,7 +135,7 @@ _gcry_ecc_eddsa_encodepoint (mpi_point_t point, mpi_ec_t ec,
       rc = GPG_ERR_INTERNAL;
     }
   else
-    rc = eddsa_encode_x_y (x, y, ec->nbits/8, with_prefix, r_buffer, r_buflen);
+    rc = eddsa_encode_x_y (x, y, ec->nbits, with_prefix, r_buffer, r_buflen);
 
   if (!x_in)
     mpi_free (x);
@@ -168,11 +170,11 @@ _gcry_ecc_eddsa_ensure_compact (gcry_mpi_t value, unsigned int nbits)
         {
           /* Buffer is in SEC1 uncompressed format.  Extract y and
              compress.  */
-          rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD,
+          rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG,
                                buf+1, (rawmpilen-1)/2, NULL);
           if (rc)
             return rc;
-          rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD,
+          rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_USG,
                                buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2, NULL);
           if (rc)
             {
@@ -180,7 +182,7 @@ _gcry_ecc_eddsa_ensure_compact (gcry_mpi_t value, unsigned int nbits)
               return rc;
             }
 
-          rc = eddsa_encode_x_y (x, y, nbits/8, 0, &enc, &enclen);
+          rc = eddsa_encode_x_y (x, y, nbits, 0, &enc, &enclen);
           mpi_free (x);
           mpi_free (y);
           if (rc)
@@ -202,6 +204,76 @@ _gcry_ecc_eddsa_ensure_compact (gcry_mpi_t value, unsigned int nbits)
 }
 
 
+static gpg_err_code_t
+ecc_ed448_recover_x (gcry_mpi_t x, gcry_mpi_t y, int x_0, mpi_ec_t ec)
+{
+  gpg_err_code_t rc = 0;
+  gcry_mpi_t u, v, u3, v3, t;
+  static gcry_mpi_t p34; /* Hard coded (P-3)/4 */
+
+  if (mpi_cmp (y, ec->p) >= 0)
+    rc = GPG_ERR_INV_OBJ;
+
+  if (!p34)
+    p34 = scanval ("3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+                   "BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
+
+  u   = mpi_new (0);
+  v   = mpi_new (0);
+  u3  = mpi_new (0);
+  v3  = mpi_new (0);
+  t   = mpi_new (0);
+
+  /* Compute u and v */
+  /* u = y^2    */
+  mpi_mulm (u, y, y, ec->p);
+  /* v = b*y^2   */
+  mpi_mulm (v, ec->b, u, ec->p);
+  /* u = y^2-1  */
+  mpi_sub_ui (u, u, 1);
+  /* v = b*y^2-1 */
+  mpi_sub_ui (v, v, 1);
+
+  /* Compute sqrt(u/v) */
+  /* u3 = u^3 */
+  mpi_powm (u3, u, mpi_const (MPI_C_THREE), ec->p);
+  mpi_powm (v3, v, mpi_const (MPI_C_THREE), ec->p);
+  /* t = u^4 * u * v3 = u^5 * v^3 */
+  mpi_powm (t, u, mpi_const (MPI_C_FOUR), ec->p);
+  mpi_mulm (t, t, u, ec->p);
+  mpi_mulm (t, t, v3, ec->p);
+  /* t = t^((p-3)/4) = (u^5 * v^3)^((p-3)/4)  */
+  mpi_powm (t, t, p34, ec->p);
+  /* x = t * u^3 * v = (u^3 * v) * (u^5 * v^3)^((p-3)/4) */
+  mpi_mulm (t, t, u3, ec->p);
+  mpi_mulm (x, t, v, ec->p);
+
+  /* t = v * x^2  */
+  mpi_mulm (t, x, x, ec->p);
+  mpi_mulm (t, t, v, ec->p);
+
+  if (mpi_cmp (t, u) != 0)
+    rc = GPG_ERR_INV_OBJ;
+  else
+    {
+      if (!mpi_cmp_ui (x, 0) && x_0)
+        rc = GPG_ERR_INV_OBJ;
+
+      /* Choose the desired square root according to parity */
+      if (mpi_test_bit (x, 0) != !!x_0)
+        mpi_sub (x, ec->p, x);
+    }
+
+  mpi_free (t);
+  mpi_free (u3);
+  mpi_free (v3);
+  mpi_free (v);
+  mpi_free (u);
+
+  return rc;
+}
+
+
 /* Recover X from Y and SIGN (which actually is a parity bit).  */
 gpg_err_code_t
 _gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign, mpi_ec_t ec)
@@ -210,8 +282,16 @@ _gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign, mpi_ec_t ec)
   gcry_mpi_t u, v, v3, t;
   static gcry_mpi_t p58, seven;
 
+  /*
+   * This routine is actually curve specific.  Now, only supports
+   * Ed25519 and Ed448.
+   */
+
   if (ec->dialect != ECC_DIALECT_ED25519)
-    return GPG_ERR_NOT_IMPLEMENTED;
+    /* For now, it's only Ed448.  */
+    return ecc_ed448_recover_x (x, y, sign, ec);
+
+  /* It's Ed25519.  */
 
   if (!p58)
     p58 = scanval ("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
@@ -299,15 +379,23 @@ _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
   if (mpi_is_opaque (pk))
     {
       const unsigned char *buf;
+      unsigned int len;
+
+      len = (ctx->nbits%8) == 0 ? (ctx->nbits/8 + 1): (ctx->nbits+7)/8;
 
       buf = mpi_get_opaque (pk, &rawmpilen);
       if (!buf)
         return GPG_ERR_INV_OBJ;
       rawmpilen = (rawmpilen + 7)/8;
 
+      if (!(rawmpilen == len
+            || rawmpilen == len + 1
+            || rawmpilen == len * 2 + 1))
+        return GPG_ERR_INV_OBJ;
+
       /* Handle compression prefixes.  The size of the buffer will be
          odd in this case.  */
-      if (rawmpilen > 1 && (rawmpilen%2))
+      if (rawmpilen > 1 && (rawmpilen == len + 1 || rawmpilen == len * 2 + 1))
         {
           /* First check whether the public key has been given in
              standard uncompressed format (SEC1).  No need to recover
@@ -316,11 +404,11 @@ _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
             {
               gcry_mpi_t x, y;
 
-              rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD,
+              rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG,
                                    buf+1, (rawmpilen-1)/2, NULL);
               if (rc)
                 return rc;
-              rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD,
+              rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_USG,
                                    buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2,NULL);
               if (rc)
                 {
@@ -330,7 +418,7 @@ _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
 
               if (r_encpk)
                 {
-                  rc = eddsa_encode_x_y (x, y, ctx->nbits/8, 0,
+                  rc = eddsa_encode_x_y (x, y, ctx->nbits, 0,
                                          r_encpk, r_encpklen);
                   if (rc)
                     {
@@ -356,7 +444,7 @@ _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
         }
 
       /* EdDSA compressed point.  */
-      rawmpi = xtrymalloc (rawmpilen? rawmpilen:1);
+      rawmpi = xtrymalloc (rawmpilen);
       if (!rawmpi)
         return gpg_err_code_from_syserror ();
       memcpy (rawmpi, buf, rawmpilen);
@@ -367,7 +455,7 @@ _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
       /* Note: Without using an opaque MPI it is not reliable possible
          to find out whether the public key has been given in
          uncompressed format.  Thus we expect native EdDSA format.  */
-      rawmpi = _gcry_mpi_get_buffer (pk, ctx->nbits/8, &rawmpilen, NULL);
+      rawmpi = _gcry_mpi_get_buffer (pk, (ctx->nbits+7)/8, &rawmpilen, NULL);
       if (!rawmpi)
         return gpg_err_code_from_syserror ();
     }
@@ -406,25 +494,36 @@ _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
    bytes represent the A value.  NULL is returned on error and NULL
    stored at R_DIGEST.  */
 gpg_err_code_t
-_gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
-                             gcry_mpi_t d, mpi_ec_t ec)
+_gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest, mpi_ec_t ec)
 {
   gpg_err_code_t rc;
   unsigned char *rawmpi = NULL;
   unsigned int rawmpilen;
   unsigned char *digest;
+  int hashalgo, b, digestlen;
   gcry_buffer_t hvec[2];
-  int hashalgo, b;
 
   *r_digest = NULL;
 
-  hashalgo = GCRY_MD_SHA512;
-  if (hashalgo != GCRY_MD_SHA512)
-    return GPG_ERR_DIGEST_ALGO;
-
   b = (ec->nbits+7)/8;
-  if (b != 256/8)
-    return GPG_ERR_INTERNAL; /* We only support 256 bit. */
+
+  /*
+   * Choice of hashalgo is curve specific.
+   * For now, it's determine by the bit size of the field.
+   */
+  if (ec->nbits == 255)
+    {
+      hashalgo = GCRY_MD_SHA512;
+      digestlen = 64;
+    }
+  else if (ec->nbits == 448)
+    {
+      b++;
+      hashalgo = GCRY_MD_SHAKE256;
+      digestlen = 2 * b;
+    }
+  else
+    return GPG_ERR_NOT_IMPLEMENTED;
 
   /* Note that we clear DIGEST so we can use it as input to left pad
      the key with zeroes for hashing.  */
@@ -432,22 +531,22 @@ _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
   if (!digest)
     return gpg_err_code_from_syserror ();
 
-  memset (hvec, 0, sizeof hvec);
-
-  rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL);
+  rawmpi = _gcry_mpi_get_buffer (ec->d, 0, &rawmpilen, NULL);
   if (!rawmpi)
     {
       xfree (digest);
       return gpg_err_code_from_syserror ();
     }
 
+  memset (hvec, 0, sizeof hvec);
+
   hvec[0].data = digest;
-  hvec[0].off = 0;
-  hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
+  hvec[0].len = (hashalgo == GCRY_MD_SHA512 && b > rawmpilen)
+                 ? b - rawmpilen : 0;
   hvec[1].data = rawmpi;
-  hvec[1].off = 0;
   hvec[1].len = rawmpilen;
-  rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2);
+  rc = _gcry_md_hash_buffers_extract (hashalgo, 0, digest, digestlen, hvec, 2);
+
   xfree (rawmpi);
   if (rc)
     {
@@ -456,9 +555,20 @@ _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
     }
 
   /* Compute the A value.  */
-  reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
-  digest[0]   = (digest[0] & 0x7f) | 0x40;
-  digest[31] &= 0xf8;
+  reverse_buffer (digest, b);  /* Only the first half of the hash.  */
+
+  /* Field specific handling of clearing/setting bits. */
+  if (ec->nbits == 255)
+    {
+      digest[0]   = (digest[0] & 0x7f) | 0x40;
+      digest[31] &= 0xf8;
+    }
+  else
+    {
+      digest[0]   = 0;
+      digest[1]  |= 0x80;
+      digest[56] &= 0xfc;
+    }
 
   *r_digest = digest;
   return 0;
@@ -468,9 +578,7 @@ _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
 /**
  * _gcry_ecc_eddsa_genkey - EdDSA version of the key generation.
  *
- * @sk:  A struct to receive the secret key.
- * @E:   Parameters of the curve.
- * @ctx: Elliptic curve computation context.
+ * @ec: Elliptic curve computation context.
  * @flags: Flags controlling aspects of the creation.
  *
  * Return: An error code.
@@ -479,80 +587,63 @@ _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
  * to use a faster RNG.
  */
 gpg_err_code_t
-_gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
-                        int flags)
+_gcry_ecc_eddsa_genkey (mpi_ec_t ec, int flags)
 {
   gpg_err_code_t rc;
-  int b = 256/8;             /* The only size we currently support.  */
+  int b;
   gcry_mpi_t a, x, y;
   mpi_point_struct Q;
   gcry_random_level_t random_level;
   char *dbuf;
   size_t dlen;
-  gcry_buffer_t hvec[1];
   unsigned char *hash_d = NULL;
 
-  point_init (&Q);
-  memset (hvec, 0, sizeof hvec);
-
   if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
     random_level = GCRY_STRONG_RANDOM;
   else
     random_level = GCRY_VERY_STRONG_RANDOM;
 
+  b = (ec->nbits+7)/8;
+
+  if (ec->nbits == 255)
+    ;
+  else if (ec->nbits == 448)
+    b++;
+  else
+    return GPG_ERR_NOT_IMPLEMENTED;
+
+  dlen = b;
+
   a = mpi_snew (0);
   x = mpi_new (0);
   y = mpi_new (0);
 
   /* Generate a secret.  */
-  hash_d = xtrymalloc_secure (2*b);
-  if (!hash_d)
-    {
-      rc = gpg_err_code_from_syserror ();
-      goto leave;
-    }
-  dlen = b;
   dbuf = _gcry_random_bytes_secure (dlen, random_level);
-
-  /* Compute the A value.  */
-  hvec[0].data = dbuf;
-  hvec[0].len = dlen;
-  rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, hash_d, hvec, 1);
+  ec->d = _gcry_mpi_set_opaque (NULL, dbuf, dlen*8);
+  rc = _gcry_ecc_eddsa_compute_h_d (&hash_d, ec);
   if (rc)
     goto leave;
-  sk->d = _gcry_mpi_set_opaque (NULL, dbuf, dlen*8);
-  dbuf = NULL;
-  reverse_buffer (hash_d, 32);  /* Only the first half of the hash.  */
-  hash_d[0] = (hash_d[0] & 0x7f) | 0x40;
-  hash_d[31] &= 0xf8;
-  _gcry_mpi_set_buffer (a, hash_d, 32, 0);
-  xfree (hash_d); hash_d = NULL;
+
+  _gcry_mpi_set_buffer (a, hash_d, b, 0);
+  xfree (hash_d);
   /* log_printmpi ("ecgen         a", a); */
 
   /* Compute Q.  */
-  _gcry_mpi_ec_mul_point (&Q, a, &E->G, ctx);
+  point_init (&Q);
+  _gcry_mpi_ec_mul_point (&Q, a, ec->G, ec);
   if (DBG_CIPHER)
-    log_printpnt ("ecgen      pk", &Q, ctx);
-
-  /* Copy the stuff to the key structures. */
-  sk->E.model = E->model;
-  sk->E.dialect = E->dialect;
-  sk->E.p = mpi_copy (E->p);
-  sk->E.a = mpi_copy (E->a);
-  sk->E.b = mpi_copy (E->b);
-  point_init (&sk->E.G);
-  point_set (&sk->E.G, &E->G);
-  sk->E.n = mpi_copy (E->n);
-  sk->E.h = mpi_copy (E->h);
-  point_init (&sk->Q);
-  point_set (&sk->Q, &Q);
+    log_printpnt ("ecgen      pk", &Q, ec);
+
+  ec->Q = mpi_point_snatch_set (NULL, Q.x, Q.y, Q.z);
+  Q.x = NULL;
+  Q.y = NULL;
+  Q.x = NULL;
 
  leave:
-  point_free (&Q);
   _gcry_mpi_release (a);
   _gcry_mpi_release (x);
   _gcry_mpi_release (y);
-  xfree (hash_d);
   return rc;
 }
 
@@ -566,81 +657,89 @@ _gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
  *
  * Despite that this function requires the specification of a hash
  * algorithm, we only support what has been specified by the paper.
- * This may change in the future.  Note that we don't check the used
- * curve; the user is responsible to use Ed25519.
+ * This may change in the future.
  *
  * Return the signature struct (r,s) from the message hash.  The caller
  * must have allocated R_R and S.
  */
+
+/* String to be used with Ed448 */
+#define DOM25519     "SigEd25519 no Ed25519 collisions"
+#define DOM25519_LEN 32
+#define DOM448       "SigEd448"
+#define DOM448_LEN   8
+
 gpg_err_code_t
-_gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
-                      gcry_mpi_t r_r, gcry_mpi_t s, int hashalgo, gcry_mpi_t pk)
+_gcry_ecc_eddsa_sign (gcry_mpi_t input, mpi_ec_t ec,
+                      gcry_mpi_t r_r, gcry_mpi_t s,
+                      struct pk_encoding_ctx *ctx)
 {
   int rc;
-  mpi_ec_t ctx = NULL;
-  int b;
   unsigned int tmp;
   unsigned char *digest = NULL;
-  gcry_buffer_t hvec[3];
   const void *mbuf;
   size_t mlen;
   unsigned char *rawmpi = NULL;
-  unsigned int rawmpilen;
+  unsigned int rawmpilen = 0;
   unsigned char *encpk = NULL; /* Encoded public key.  */
-  unsigned int encpklen;
+  unsigned int encpklen = 0;
   mpi_point_struct I;          /* Intermediate value.  */
-  mpi_point_struct Q;          /* Public key.  */
   gcry_mpi_t a, x, y, r;
+  const char *dom;
+  int domlen, digestlen;
+  int b, i;
+  unsigned char x_olen[2];
+  unsigned char prehashed_msg[64];
+  gcry_buffer_t hvec[6];
+  gcry_buffer_t hvec2[1];
 
-  memset (hvec, 0, sizeof hvec);
+  b = (ec->nbits+7)/8;
+
+  if (ec->nbits == 255)
+    {
+      dom = DOM25519;
+      domlen = DOM25519_LEN;
+      digestlen = 64;
+    }
+  else if (ec->nbits == 448)
+    {
+      b++;
+      dom = DOM448;
+      domlen = DOM448_LEN;
+      digestlen = 2 * b;
+    }
+  else
+    return GPG_ERR_NOT_IMPLEMENTED;
 
   if (!mpi_is_opaque (input))
     return GPG_ERR_INV_DATA;
 
   /* Initialize some helpers.  */
   point_init (&I);
-  point_init (&Q);
   a = mpi_snew (0);
   x = mpi_new (0);
   y = mpi_new (0);
   r = mpi_snew (0);
-  ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0,
-                                     skey->E.p, skey->E.a, skey->E.b);
-  b = (ctx->nbits+7)/8;
-  if (b != 256/8) {
-    rc = GPG_ERR_INTERNAL; /* We only support 256 bit. */
-    goto leave;
-  }
 
-  rc = _gcry_ecc_eddsa_compute_h_d (&digest, skey->d, ctx);
+  rc = _gcry_ecc_eddsa_compute_h_d (&digest, ec);
   if (rc)
     goto leave;
-  _gcry_mpi_set_buffer (a, digest, 32, 0);
+  _gcry_mpi_set_buffer (a, digest, b, 0);
 
-  /* Compute the public key if it has not been supplied as optional
-     parameter.  */
-  if (pk)
+  /* Compute the public key if it's not available (only secret part).  */
+  if (ec->Q == NULL)
     {
-      rc = _gcry_ecc_eddsa_decodepoint (pk, ctx, &Q,  &encpk, &encpklen);
-      if (rc)
-        goto leave;
-      if (DBG_CIPHER)
-        log_printhex ("* e_pk", encpk, encpklen);
-      if (!_gcry_mpi_ec_curve_point (&Q, ctx))
-        {
-          rc = GPG_ERR_BROKEN_PUBKEY;
-          goto leave;
-        }
-    }
-  else
-    {
-      _gcry_mpi_ec_mul_point (&Q, a, &skey->E.G, ctx);
-      rc = _gcry_ecc_eddsa_encodepoint (&Q, ctx, x, y, 0, &encpk, &encpklen);
-      if (rc)
-        goto leave;
-      if (DBG_CIPHER)
-        log_printhex ("  e_pk", encpk, encpklen);
+      mpi_point_struct Q;
+
+      point_init (&Q);
+      _gcry_mpi_ec_mul_point (&Q, a, ec->G, ec);
+      ec->Q = mpi_point_snatch_set (NULL, Q.x, Q.y, Q.z);
     }
+  rc = _gcry_ecc_eddsa_encodepoint (ec->Q, ec, x, y, 0, &encpk, &encpklen);
+  if (rc)
+    goto leave;
+  if (DBG_CIPHER)
+    log_printhex ("  e_pk", encpk, encpklen);
 
   /* Compute R.  */
   mbuf = mpi_get_opaque (input, &tmp);
@@ -648,40 +747,112 @@ _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
   if (DBG_CIPHER)
     log_printhex ("     m", mbuf, mlen);
 
-  hvec[0].data = digest;
-  hvec[0].off  = 32;
-  hvec[0].len  = 32;
-  hvec[1].data = (char*)mbuf;
-  hvec[1].len  = mlen;
-  rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2);
+  memset (hvec, 0, sizeof hvec);
+  i = 0;
+
+  if ((ctx->flags & PUBKEY_FLAG_PREHASH) || ctx->labellen || ec->nbits == 448)
+    {
+      hvec[i].data = (void *)dom;
+      hvec[i].len  = domlen;
+      i++;
+      x_olen[0] = !!(ctx->flags & PUBKEY_FLAG_PREHASH);
+      x_olen[1] = ctx->labellen;
+      hvec[i].data = x_olen;
+      hvec[i].len  = 2;
+      i++;
+      if (ctx->labellen)
+       {
+         hvec[i].data = ctx->label;
+         hvec[i].len  = ctx->labellen;
+         i++;
+       }
+    }
+
+  hvec[i].data = digest;
+  hvec[i].off  = b;
+  hvec[i].len  = b;
+  i++;
+  if ((ctx->flags & PUBKEY_FLAG_PREHASH))
+    {
+      memset (hvec2, 0, sizeof hvec2);
+
+      hvec2[0].data = (char*)mbuf;
+      hvec2[0].len  = mlen;
+
+      _gcry_md_hash_buffers_extract (ctx->hash_algo, 0, prehashed_msg, 64,
+                                    hvec2, 1);
+      hvec[i].data = (char*)prehashed_msg;
+      hvec[i].len  = 64;
+    }
+  else
+    {
+      hvec[i].data = (char*)mbuf;
+      hvec[i].len  = mlen;
+    }
+  i++;
+
+  rc = _gcry_md_hash_buffers_extract (ctx->hash_algo, 0, digest, digestlen,
+                                     hvec, i);
   if (rc)
     goto leave;
-  reverse_buffer (digest, 64);
+  reverse_buffer (digest, digestlen);
   if (DBG_CIPHER)
-    log_printhex ("     r", digest, 64);
-  _gcry_mpi_set_buffer (r, digest, 64, 0);
-  _gcry_mpi_ec_mul_point (&I, r, &skey->E.G, ctx);
+    log_printhex ("     r", digest, digestlen);
+  _gcry_mpi_set_buffer (r, digest, digestlen, 0);
+  mpi_mod (r, r, ec->n);
+  _gcry_mpi_ec_mul_point (&I, r, ec->G, ec);
   if (DBG_CIPHER)
-    log_printpnt ("   r", &I, ctx);
+    log_printpnt ("   r", &I, ec);
 
   /* Convert R into affine coordinates and apply encoding.  */
-  rc = _gcry_ecc_eddsa_encodepoint (&I, ctx, x, y, 0, &rawmpi, &rawmpilen);
+  rc = _gcry_ecc_eddsa_encodepoint (&I, ec, x, y, 0, &rawmpi, &rawmpilen);
   if (rc)
     goto leave;
   if (DBG_CIPHER)
     log_printhex ("   e_r", rawmpi, rawmpilen);
 
-  /* S = r + a * H(encodepoint(R) + encodepoint(pk) + m) mod n  */
-  hvec[0].data = rawmpi;  /* (this is R) */
-  hvec[0].off  = 0;
-  hvec[0].len  = rawmpilen;
-  hvec[1].data = encpk;
-  hvec[1].off  = 0;
-  hvec[1].len  = encpklen;
-  hvec[2].data = (char*)mbuf;
-  hvec[2].off  = 0;
-  hvec[2].len  = mlen;
-  rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 3);
+  memset (hvec, 0, sizeof hvec);
+  i = 0;
+
+  if ((ctx->flags & PUBKEY_FLAG_PREHASH) || ctx->labellen || ec->nbits == 448)
+    {
+      hvec[i].data = (void *)dom;
+      hvec[i].len  = domlen;
+      i++;
+      x_olen[0] = !!(ctx->flags & PUBKEY_FLAG_PREHASH);
+      x_olen[1] = ctx->labellen;
+      hvec[i].data = x_olen;
+      hvec[i].len  = 2;
+      i++;
+      if (ctx->labellen)
+       {
+         hvec[i].data = ctx->label;
+         hvec[i].len  = ctx->labellen;
+         i++;
+       }
+    }
+
+  /* S = r + a * H(dom2(F,C)+encodepoint(R)+encodepoint(pk)+m) mod n  */
+  hvec[i].data = rawmpi;  /* (this is R) */
+  hvec[i].len  = rawmpilen;
+  i++;
+  hvec[i].data = encpk;
+  hvec[i].len  = encpklen;
+  i++;
+  if ((ctx->flags & PUBKEY_FLAG_PREHASH))
+    {
+      hvec[i].data = (char*)prehashed_msg;
+      hvec[i].len  = 64;
+    }
+  else
+    {
+      hvec[i].data = (char*)mbuf;
+      hvec[i].len  = mlen;
+    }
+  i++;
+
+  rc = _gcry_md_hash_buffers_extract (ctx->hash_algo, 0, digest, digestlen,
+                                     hvec, i);
   if (rc)
     goto leave;
 
@@ -689,13 +860,13 @@ _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
   mpi_set_opaque (r_r, rawmpi, rawmpilen*8);
   rawmpi = NULL;
 
-  reverse_buffer (digest, 64);
+  reverse_buffer (digest, digestlen);
   if (DBG_CIPHER)
-    log_printhex (" H(R+)", digest, 64);
-  _gcry_mpi_set_buffer (s, digest, 64, 0);
-  mpi_mulm (s, s, a, skey->E.n);
-  mpi_addm (s, s, r, skey->E.n);
-  rc = eddsa_encodempi (s, b, &rawmpi, &rawmpilen);
+    log_printhex (" H(R+)", digest, digestlen);
+  _gcry_mpi_set_buffer (s, digest, digestlen, 0);
+  mpi_mulm (s, s, a, ec->n);
+  mpi_addm (s, s, r, ec->n);
+  rc = eddsa_encodempi (s, ec->nbits, &rawmpi, &rawmpilen);
   if (rc)
     goto leave;
   if (DBG_CIPHER)
@@ -711,9 +882,7 @@ _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
   _gcry_mpi_release (y);
   _gcry_mpi_release (r);
   xfree (digest);
-  _gcry_mpi_ec_free (ctx);
   point_free (&I);
-  point_free (&Q);
   xfree (encpk);
   xfree (rawmpi);
   return rc;
@@ -721,55 +890,65 @@ _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
 
 
 /* Verify an EdDSA signature.  See sign_eddsa for the reference.
- * Check if R_IN and S_IN verifies INPUT.  PKEY has the curve
- * parameters and PK is the EdDSA style encoded public key.
+ * Check if R_IN and S_IN verifies INPUT.
  */
 gpg_err_code_t
-_gcry_ecc_eddsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
-                        gcry_mpi_t r_in, gcry_mpi_t s_in, int hashalgo,
-                        gcry_mpi_t pk)
+_gcry_ecc_eddsa_verify (gcry_mpi_t input, mpi_ec_t ec,
+                        gcry_mpi_t r_in, gcry_mpi_t s_in,
+                        struct pk_encoding_ctx *ctx)
 {
   int rc;
-  mpi_ec_t ctx = NULL;
   int b;
   unsigned int tmp;
-  mpi_point_struct Q;          /* Public key.  */
   unsigned char *encpk = NULL; /* Encoded public key.  */
-  unsigned int encpklen;
+  unsigned int encpklen = 0;
   const void *mbuf, *rbuf;
   unsigned char *tbuf = NULL;
   size_t mlen, rlen;
   unsigned int tlen;
-  unsigned char digest[64];
-  gcry_buffer_t hvec[3];
+  unsigned char digest[114];
   gcry_mpi_t h, s;
   mpi_point_struct Ia, Ib;
+  const char *dom;
+  int domlen, digestlen;
+  int i;
+  unsigned char x_olen[2];
+  unsigned char prehashed_msg[64];
+  gcry_buffer_t hvec[6];
+  gcry_buffer_t hvec2[1];
 
   if (!mpi_is_opaque (input) || !mpi_is_opaque (r_in) || !mpi_is_opaque (s_in))
     return GPG_ERR_INV_DATA;
-  if (hashalgo != GCRY_MD_SHA512)
-    return GPG_ERR_DIGEST_ALGO;
 
-  point_init (&Q);
+  b = (ec->nbits+7)/8;
+
+  if (ec->nbits == 255)
+    {
+      dom = DOM25519;
+      domlen = DOM25519_LEN;
+      digestlen = 64;
+    }
+  else if (ec->nbits == 448)
+    {
+      b++;
+      dom = DOM448;
+      domlen = DOM448_LEN;
+      digestlen = 2 * b;
+    }
+  else
+    return GPG_ERR_NOT_IMPLEMENTED;
+
   point_init (&Ia);
   point_init (&Ib);
   h = mpi_new (0);
   s = mpi_new (0);
 
-  ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0,
-                                     pkey->E.p, pkey->E.a, pkey->E.b);
-  b = ctx->nbits/8;
-  if (b != 256/8)
-    {
-      rc = GPG_ERR_INTERNAL; /* We only support 256 bit. */
-      goto leave;
-    }
-
-  /* Decode and check the public key.  */
-  rc = _gcry_ecc_eddsa_decodepoint (pk, ctx, &Q, &encpk, &encpklen);
+  /* Encode and check the public key.  */
+  rc = _gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, 0,
+                                    &encpk, &encpklen);
   if (rc)
     goto leave;
-  if (!_gcry_mpi_ec_curve_point (&Q, ctx))
+  if (!_gcry_mpi_ec_curve_point (ec->Q, ec))
     {
       rc = GPG_ERR_BROKEN_PUBKEY;
       goto leave;
@@ -797,23 +976,61 @@ _gcry_ecc_eddsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
       goto leave;
     }
 
-  /* h = H(encodepoint(R) + encodepoint(pk) + m)  */
-  hvec[0].data = (char*)rbuf;
-  hvec[0].off  = 0;
-  hvec[0].len  = rlen;
-  hvec[1].data = encpk;
-  hvec[1].off  = 0;
-  hvec[1].len  = encpklen;
-  hvec[2].data = (char*)mbuf;
-  hvec[2].off  = 0;
-  hvec[2].len  = mlen;
-  rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 3);
+  memset (hvec, 0, sizeof hvec);
+  i = 0;
+
+  /* h = H(dom2(F,C)+encodepoint(R)+encodepoint(pk)+m)  */
+  if ((ctx->flags & PUBKEY_FLAG_PREHASH) || ctx->labellen || ec->nbits == 448)
+    {
+      hvec[i].data = (void *)dom;
+      hvec[i].len  = domlen;
+      i++;
+      x_olen[0] = !!(ctx->flags & PUBKEY_FLAG_PREHASH);
+      x_olen[1] = ctx->labellen;
+      hvec[i].data = x_olen;
+      hvec[i].len  = 2;
+      i++;
+      if (ctx->labellen)
+       {
+         hvec[i].data = ctx->label;
+         hvec[i].len  = ctx->labellen;
+         i++;
+       }
+    }
+
+  hvec[i].data = (char*)rbuf;
+  hvec[i].len  = rlen;
+  i++;
+  hvec[i].data = encpk;
+  hvec[i].len  = encpklen;
+  i++;
+  if ((ctx->flags & PUBKEY_FLAG_PREHASH))
+    {
+      memset (hvec2, 0, sizeof hvec2);
+
+      hvec2[0].data = (char*)mbuf;
+      hvec2[0].len  = mlen;
+
+      _gcry_md_hash_buffers_extract (ctx->hash_algo, 0, prehashed_msg, 64,
+                                     hvec2, 1);
+      hvec[i].data = (char*)prehashed_msg;
+      hvec[i].len  = 64;
+    }
+  else
+    {
+      hvec[i].data = (char*)mbuf;
+      hvec[i].len  = mlen;
+    }
+  i++;
+
+  rc = _gcry_md_hash_buffers_extract (ctx->hash_algo, 0, digest, digestlen,
+                                     hvec, i);
   if (rc)
     goto leave;
-  reverse_buffer (digest, 64);
+  reverse_buffer (digest, digestlen);
   if (DBG_CIPHER)
-    log_printhex (" H(R+)", digest, 64);
-  _gcry_mpi_set_buffer (h, digest, 64, 0);
+    log_printhex (" H(R+)", digest, digestlen);
+  _gcry_mpi_set_buffer (h, digest, digestlen, 0);
 
   /* According to the paper the best way for verification is:
          encodepoint(sG - h·Q) = encodepoint(r)
@@ -836,11 +1053,11 @@ _gcry_ecc_eddsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
       }
   }
 
-  _gcry_mpi_ec_mul_point (&Ia, s, &pkey->E.G, ctx);
-  _gcry_mpi_ec_mul_point (&Ib, h, &Q, ctx);
-  _gcry_mpi_sub (Ib.x, ctx->p, Ib.x);
-  _gcry_mpi_ec_add_points (&Ia, &Ia, &Ib, ctx);
-  rc = _gcry_ecc_eddsa_encodepoint (&Ia, ctx, s, h, 0, &tbuf, &tlen);
+  _gcry_mpi_ec_mul_point (&Ia, s, ec->G, ec);
+  _gcry_mpi_ec_mul_point (&Ib, h, ec->Q, ec);
+  _gcry_mpi_sub (Ib.x, ec->p, Ib.x);
+  _gcry_mpi_ec_add_points (&Ia, &Ia, &Ib, ec);
+  rc = _gcry_ecc_eddsa_encodepoint (&Ia, ec, s, h, 0, &tbuf, &tlen);
   if (rc)
     goto leave;
   if (tlen != rlen || memcmp (tbuf, rbuf, tlen))
@@ -854,11 +1071,9 @@ _gcry_ecc_eddsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
  leave:
   xfree (encpk);
   xfree (tbuf);
-  _gcry_mpi_ec_free (ctx);
   _gcry_mpi_release (s);
   _gcry_mpi_release (h);
   point_free (&Ia);
   point_free (&Ib);
-  point_free (&Q);
   return rc;
 }
index a34fa08..36230f8 100644 (file)
  * must have allocated R and S.
  */
 gpg_err_code_t
-_gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
+_gcry_ecc_gost_sign (gcry_mpi_t input, mpi_ec_t ec,
                      gcry_mpi_t r, gcry_mpi_t s)
 {
   gpg_err_code_t rc = 0;
   gcry_mpi_t k, dr, sum, ke, x, e;
   mpi_point_struct I;
   gcry_mpi_t hash;
-  const void *abuf;
-  unsigned int abits, qbits;
-  mpi_ec_t ctx;
+  unsigned int qbits;
 
   if (DBG_CIPHER)
     log_mpidump ("gost sign hash  ", input );
 
-  qbits = mpi_get_nbits (skey->E.n);
+  qbits = mpi_get_nbits (ec->n);
 
   /* Convert the INPUT into an MPI if needed.  */
-  if (mpi_is_opaque (input))
-    {
-      abuf = mpi_get_opaque (input, &abits);
-      rc = _gcry_mpi_scan (&hash, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL);
-      if (rc)
-        return rc;
-      if (abits > qbits)
-        mpi_rshift (hash, hash, abits - qbits);
-    }
-  else
-    hash = input;
-
+  rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
+  if (rc)
+    return rc;
 
   k = NULL;
   dr = mpi_alloc (0);
@@ -76,10 +65,7 @@ _gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
   x = mpi_alloc (0);
   point_init (&I);
 
-  ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0,
-                                     skey->E.p, skey->E.a, skey->E.b);
-
-  mpi_mod (e, input, skey->E.n); /* e = hash mod n */
+  mpi_mod (e, input, ec->n); /* e = hash mod n */
 
   if (!mpi_cmp_ui (e, 0))
     mpi_set_ui (e, 1);
@@ -92,22 +78,24 @@ _gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
       do
         {
           mpi_free (k);
-          k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM);
+          k = _gcry_dsa_gen_k (ec->n, GCRY_STRONG_RANDOM);
 
-          _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
-          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
+          _gcry_dsa_modify_k (k, ec->n, qbits);
+
+          _gcry_mpi_ec_mul_point (&I, k, ec->G, ec);
+          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ec))
             {
               if (DBG_CIPHER)
                 log_debug ("ecc sign: Failed to get affine coordinates\n");
               rc = GPG_ERR_BAD_SIGNATURE;
               goto leave;
             }
-          mpi_mod (r, x, skey->E.n);  /* r = x mod n */
+          mpi_mod (r, x, ec->n);  /* r = x mod n */
         }
       while (!mpi_cmp_ui (r, 0));
-      mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
-      mpi_mulm (ke, k, e, skey->E.n); /* ke = k*e mod n */
-      mpi_addm (s, ke, dr, skey->E.n); /* sum = (k*e+ d*r) mod n  */
+      mpi_mulm (dr, ec->d, r, ec->n); /* dr = d*r mod n  */
+      mpi_mulm (ke, k, e, ec->n); /* ke = k*e mod n */
+      mpi_addm (s, ke, dr, ec->n); /* sum = (k*e+ d*r) mod n  */
     }
   while (!mpi_cmp_ui (s, 0));
 
@@ -118,7 +106,6 @@ _gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
     }
 
  leave:
-  _gcry_mpi_ec_free (ctx);
   point_free (&I);
   mpi_free (x);
   mpi_free (e);
@@ -138,17 +125,19 @@ _gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
  * Check if R and S verifies INPUT.
  */
 gpg_err_code_t
-_gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey,
+_gcry_ecc_gost_verify (gcry_mpi_t input, mpi_ec_t ec,
                        gcry_mpi_t r, gcry_mpi_t s)
 {
   gpg_err_code_t err = 0;
   gcry_mpi_t e, x, z1, z2, v, rv, zero;
   mpi_point_struct Q, Q1, Q2;
-  mpi_ec_t ctx;
 
-  if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
+  if (!_gcry_mpi_ec_curve_point (ec->Q, ec))
+    return GPG_ERR_BROKEN_PUBKEY;
+
+  if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, ec->n) < 0) )
     return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < r < n  failed.  */
-  if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
+  if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, ec->n) < 0) )
     return GPG_ERR_BAD_SIGNATURE; /* Assertion 0 < s < n  failed.  */
 
   x = mpi_alloc (0);
@@ -163,26 +152,23 @@ _gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey,
   point_init (&Q1);
   point_init (&Q2);
 
-  ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0,
-                                     pkey->E.p, pkey->E.a, pkey->E.b);
-
-  mpi_mod (e, input, pkey->E.n); /* e = hash mod n */
+  mpi_mod (e, input, ec->n); /* e = hash mod n */
   if (!mpi_cmp_ui (e, 0))
     mpi_set_ui (e, 1);
-  mpi_invm (v, e, pkey->E.n); /* v = e^(-1) (mod n) */
-  mpi_mulm (z1, s, v, pkey->E.n); /* z1 = s*v (mod n) */
-  mpi_mulm (rv, r, v, pkey->E.n); /* rv = s*v (mod n) */
-  mpi_subm (z2, zero, rv, pkey->E.n); /* z2 = -r*v (mod n) */
+  mpi_invm (v, e, ec->n); /* v = e^(-1) (mod n) */
+  mpi_mulm (z1, s, v, ec->n); /* z1 = s*v (mod n) */
+  mpi_mulm (rv, r, v, ec->n); /* rv = r*v (mod n) */
+  mpi_subm (z2, zero, rv, ec->n); /* z2 = -r*v (mod n) */
 
-  _gcry_mpi_ec_mul_point (&Q1, z1, &pkey->E.G, ctx);
+  _gcry_mpi_ec_mul_point (&Q1, z1, ec->G, ec);
 /*   log_mpidump ("Q1.x", Q1.x); */
 /*   log_mpidump ("Q1.y", Q1.y); */
 /*   log_mpidump ("Q1.z", Q1.z); */
-  _gcry_mpi_ec_mul_point (&Q2, z2, &pkey->Q, ctx);
+  _gcry_mpi_ec_mul_point (&Q2, z2, ec->Q, ec);
 /*   log_mpidump ("Q2.x", Q2.x); */
 /*   log_mpidump ("Q2.y", Q2.y); */
 /*   log_mpidump ("Q2.z", Q2.z); */
-  _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);
+  _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ec);
 /*   log_mpidump (" Q.x", Q.x); */
 /*   log_mpidump (" Q.y", Q.y); */
 /*   log_mpidump (" Q.z", Q.z); */
@@ -194,14 +180,14 @@ _gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey,
       err = GPG_ERR_BAD_SIGNATURE;
       goto leave;
     }
-  if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ctx))
+  if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ec))
     {
       if (DBG_CIPHER)
         log_debug ("ecc verify: Failed to get affine coordinates\n");
       err = GPG_ERR_BAD_SIGNATURE;
       goto leave;
     }
-  mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */
+  mpi_mod (x, x, ec->n); /* x = x mod E_n */
   if (mpi_cmp (x, r))   /* x != r */
     {
       if (DBG_CIPHER)
@@ -218,7 +204,6 @@ _gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey,
     log_debug ("ecc verify: Accepted\n");
 
  leave:
-  _gcry_mpi_ec_free (ctx);
   point_free (&Q2);
   point_free (&Q1);
   point_free (&Q);
index 41debe4..37b4fa1 100644 (file)
@@ -43,7 +43,6 @@ _gcry_ecc_curve_free (elliptic_curve_t *E)
   mpi_free (E->b);  E->b = NULL;
   _gcry_mpi_point_free_parts (&E->G);
   mpi_free (E->n);  E->n = NULL;
-  mpi_free (E->h);  E->h = NULL;
 }
 
 
@@ -64,7 +63,7 @@ _gcry_ecc_curve_copy (elliptic_curve_t E)
   _gcry_mpi_point_init (&R.G);
   point_set (&R.G, &E.G);
   R.n = mpi_copy (E.n);
-  R.h = mpi_copy (E.h);
+  R.h = E.h;
 
   return R;
 }
@@ -98,19 +97,23 @@ _gcry_ecc_dialect2str (enum ecc_dialects dialect)
     {
     case ECC_DIALECT_STANDARD:  str = "Standard"; break;
     case ECC_DIALECT_ED25519:   str = "Ed25519"; break;
+    case ECC_DIALECT_SAFECURVE: str = "SafeCurve"; break;
     }
   return str;
 }
 
 
-gcry_mpi_t
-_gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
+/* Return an uncompressed point (X,Y) in P as a malloced buffer with
+ * its byte length stored at R_LENGTH.  May not be used for sensitive
+ * data. */
+unsigned char *
+_gcry_ecc_ec2os_buf (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p,
+                     unsigned int *r_length)
 {
   gpg_err_code_t rc;
   int pbytes = (mpi_get_nbits (p)+7)/8;
   size_t n;
   unsigned char *buf, *ptr;
-  gcry_mpi_t result;
 
   buf = xmalloc ( 1 + 2*pbytes );
   *buf = 04; /* Uncompressed point.  */
@@ -133,29 +136,35 @@ _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
       memset (ptr, 0, (pbytes-n));
     }
 
-  rc = _gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL);
-  if (rc)
-    log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc));
-  xfree (buf);
-
-  return result;
+  *r_length = 1 + 2*pbytes;
+  return buf;
 }
 
 
+gcry_mpi_t
+_gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
+{
+  unsigned char *buf;
+  unsigned int buflen;
+
+  buf = _gcry_ecc_ec2os_buf (x, y, p, &buflen);
+  return mpi_set_opaque (NULL, buf, 8*buflen);
+}
+
 /* Convert POINT into affine coordinates using the context CTX and
    return a newly allocated MPI.  If the conversion is not possible
    NULL is returned.  This function won't print an error message.  */
 gcry_mpi_t
-_gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx)
+_gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ec)
 {
   gcry_mpi_t g_x, g_y, result;
 
   g_x = mpi_new (0);
   g_y = mpi_new (0);
-  if (_gcry_mpi_ec_get_affine (g_x, g_y, point, ectx))
+  if (_gcry_mpi_ec_get_affine (g_x, g_y, point, ec))
     result = NULL;
   else
-    result = _gcry_ecc_ec2os (g_x, g_y, ectx->p);
+    result = _gcry_ecc_ec2os (g_x, g_y, ec->p);
   mpi_free (g_x);
   mpi_free (g_y);
 
@@ -163,12 +172,13 @@ _gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx)
 }
 
 
-/* RESULT must have been initialized and is set on success to the
+/* Decode octet string in VALUE into RESULT, in the format defined by SEC 1.
+   RESULT must have been initialized and is set on success to the
    point given by VALUE.  */
-gcry_err_code_t
-_gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
+gpg_err_code_t
+_gcry_ecc_sec_decodepoint  (gcry_mpi_t value, mpi_ec_t ec, mpi_point_t result)
 {
-  gcry_err_code_t rc;
+  gpg_err_code_t rc;
   size_t n;
   const unsigned char *buf;
   unsigned char *buf_memory;
@@ -202,29 +212,88 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
       xfree (buf_memory);
       return GPG_ERR_INV_OBJ;
     }
-  if (*buf != 4)
+
+  if (*buf == 2 || *buf == 3)
     {
+      gcry_mpi_t x3;
+      gcry_mpi_t t;
+      gcry_mpi_t p1_4;
+      int y_bit = (*buf == 3);
+
+      if (!mpi_test_bit (ec->p, 1))
+        {
+          xfree (buf_memory);
+          return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
+        }
+
+      n = n - 1;
+      rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
       xfree (buf_memory);
-      return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
+      if (rc)
+        return rc;
+
+      /*
+       * Recover Y.  The Weierstrass curve: y^2 = x^3 + a*x + b
+       */
+
+      x3 = mpi_new (0);
+      t = mpi_new (0);
+      p1_4 = mpi_new (0);
+      y = mpi_new (0);
+
+      /* Compute right hand side.  */
+      mpi_powm (x3, x, mpi_const (MPI_C_THREE), ec->p);
+      mpi_mul (t, ec->a, x);
+      mpi_mod (t, t, ec->p);
+      mpi_add (t, t, ec->b);
+      mpi_mod (t, t, ec->p);
+      mpi_add (t, t, x3);
+      mpi_mod (t, t, ec->p);
+
+      /*
+       * When p mod 4 = 3, modular square root of A can be computed by
+       * A^((p+1)/4) mod p
+       */
+
+      /* Compute (p+1)/4 into p1_4 */
+      mpi_rshift (p1_4, ec->p, 2);
+      _gcry_mpi_add_ui (p1_4, p1_4, 1);
+
+      mpi_powm (y, t, p1_4, ec->p);
+
+      if (y_bit != mpi_test_bit (y, 0))
+        mpi_sub (y, ec->p, y);
+
+      mpi_free (p1_4);
+      mpi_free (t);
+      mpi_free (x3);
     }
-  if ( ((n-1)%2) )
+  else if (*buf == 4)
     {
+      if ( ((n-1)%2) )
+        {
+          xfree (buf_memory);
+          return GPG_ERR_INV_OBJ;
+        }
+      n = (n-1)/2;
+      rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
+      if (rc)
+        {
+          xfree (buf_memory);
+          return rc;
+        }
+      rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
       xfree (buf_memory);
-      return GPG_ERR_INV_OBJ;
+      if (rc)
+        {
+          mpi_free (x);
+          return rc;
+        }
     }
-  n = (n-1)/2;
-  rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
-  if (rc)
+  else
     {
       xfree (buf_memory);
-      return rc;
-    }
-  rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
-  xfree (buf_memory);
-  if (rc)
-    {
-      mpi_free (x);
-      return rc;
+      return GPG_ERR_INV_OBJ;
     }
 
   mpi_set (result->x, x);
@@ -244,26 +313,20 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
    is returned.  If G or D are given they override the values taken
    from EC. */
 mpi_point_t
-_gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
-                          mpi_point_t G, gcry_mpi_t d)
+_gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec)
 {
-  if (!G)
-    G = ec->G;
-  if (!d)
-    d = ec->d;
-
-  if (!d || !G || !ec->p || !ec->a)
+  if (!ec->d || !ec->G || !ec->p || !ec->a)
     return NULL;
   if (ec->model == MPI_EC_EDWARDS && !ec->b)
     return NULL;
 
-  if (ec->dialect == ECC_DIALECT_ED25519
-      && (ec->flags & PUBKEY_FLAG_EDDSA))
+  if ((ec->dialect == ECC_DIALECT_ED25519 && (ec->flags & PUBKEY_FLAG_EDDSA))
+      || (ec->model == MPI_EC_EDWARDS && ec->dialect == ECC_DIALECT_SAFECURVE))
     {
       gcry_mpi_t a;
       unsigned char *digest;
 
-      if (_gcry_ecc_eddsa_compute_h_d (&digest, d, ec))
+      if (_gcry_ecc_eddsa_compute_h_d (&digest, ec))
         return NULL;
 
       a = mpi_snew (0);
@@ -274,7 +337,7 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
       if (!Q)
         Q = mpi_point_new (0);
       if (Q)
-        _gcry_mpi_ec_mul_point (Q, a, G, ec);
+        _gcry_mpi_ec_mul_point (Q, a, ec->G, ec);
       mpi_free (a);
     }
   else
@@ -282,7 +345,7 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
       if (!Q)
         Q = mpi_point_new (0);
       if (Q)
-        _gcry_mpi_ec_mul_point (Q, d, G, ec);
+        _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec);
     }
 
   return Q;
@@ -290,10 +353,53 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
 
 
 gpg_err_code_t
-_gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result)
+_gcry_ecc_mont_encodepoint (gcry_mpi_t x, unsigned int nbits,
+                            int with_prefix,
+                            unsigned char **r_buffer, unsigned int *r_buflen)
+{
+  unsigned char *rawmpi;
+  unsigned int rawmpilen;
+
+  rawmpi = _gcry_mpi_get_buffer_extra (x, (nbits+7)/8,
+                                       with_prefix? -1 : 0, &rawmpilen, NULL);
+  if (rawmpi == NULL)
+    return gpg_err_code_from_syserror ();
+
+  if (with_prefix)
+    {
+      rawmpi[0] = 0x40;
+      rawmpilen++;
+    }
+
+  *r_buffer = rawmpi;
+  *r_buflen = rawmpilen;
+  return 0;
+}
+
+
+gpg_err_code_t
+_gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ec, mpi_point_t result)
 {
   unsigned char *rawmpi;
   unsigned int rawmpilen;
+  unsigned int nbytes = (ec->nbits+7)/8;
+
+  /*
+   * It is not reliable to assume that the first byte of 0x40
+   * means the prefix.
+   *
+   * For newer implementation, it is reliable since we always put
+   * 0x40 for x-only coordinate.
+   *
+   * For data by older implementation (non-released development
+   * version in 2015), there is no 0x40 prefix added.
+   *
+   * So, it is possible to have shorter length of data when it was
+   * handled as MPI, removing preceding zeros.
+   *
+   * Besides, when data was parsed as MPI, we might have 0x00
+   * prefix (when the MSB in the first byte is set).
+   */
 
   if (mpi_is_opaque (pk))
     {
@@ -305,52 +411,36 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result)
         return GPG_ERR_INV_OBJ;
       rawmpilen = (rawmpilen + 7)/8;
 
-      if (rawmpilen > 1 && (rawmpilen%2) && buf[0] == 0x40)
+      if (rawmpilen == nbytes + 1
+          && (buf[0] == 0x00 || buf[0] == 0x40))
         {
           rawmpilen--;
           buf++;
         }
+      else if (rawmpilen > nbytes)
+        return GPG_ERR_INV_OBJ;
 
-      rawmpi = xtrymalloc (rawmpilen? rawmpilen:1);
+      rawmpi = xtrymalloc (nbytes);
       if (!rawmpi)
         return gpg_err_code_from_syserror ();
 
       p = rawmpi + rawmpilen;
       while (p > rawmpi)
         *--p = *buf++;
+
+      if (rawmpilen < nbytes)
+        memset (rawmpi + nbytes - rawmpilen, 0, nbytes - rawmpilen);
     }
   else
     {
-      unsigned int nbytes = (ctx->nbits+7)/8;
-
       rawmpi = _gcry_mpi_get_buffer (pk, nbytes, &rawmpilen, NULL);
       if (!rawmpi)
         return gpg_err_code_from_syserror ();
-      /*
-       * It is not reliable to assume that 0x40 means the prefix.
-       *
-       * For newer implementation, it is reliable since we always put
-       * 0x40 for x-only coordinate.
-       *
-       * For data with older implementation (non-released development
-       * version), it is possible to have the 0x40 as a part of data.
-       * Besides, when data was parsed as MPI, we might have 0x00
-       * prefix.
-       *
-       * So, we need to check if it's really the prefix or not.
-       * Only when it's the prefix, we remove it.
-       */
-      if (pk->nlimbs * BYTES_PER_MPI_LIMB < nbytes)
-        {/*
-          * It is possible for data created by older implementation
-          * to have shorter length when it was parsed as MPI.
-          */
-          unsigned int len = pk->nlimbs * BYTES_PER_MPI_LIMB;
-
-          memmove (rawmpi + nbytes - len, rawmpi, len);
-          memset (rawmpi, 0, nbytes - len);
+      if (rawmpilen > nbytes + BYTES_PER_MPI_LIMB)
+        {
+          xfree (rawmpi);
+          return GPG_ERR_INV_OBJ;
         }
-
       /*
        * When we have the prefix (0x40 or 0x00), it comes at the end,
        * since it is taken by _gcry_mpi_get_buffer with little endian.
@@ -360,7 +450,8 @@ _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result)
       rawmpilen = nbytes;
     }
 
-  rawmpi[0] &= (1 << (ctx->nbits % 8)) - 1;
+  if ((ec->nbits % 8))
+    rawmpi[0] &= (1 << (ec->nbits % 8)) - 1;
   _gcry_mpi_set_buffer (result->x, rawmpi, rawmpilen, 0);
   xfree (rawmpi);
   mpi_set_ui (result->z, 1);
diff --git a/cipher/ecc-sm2.c b/cipher/ecc-sm2.c
new file mode 100644 (file)
index 0000000..c52629f
--- /dev/null
@@ -0,0 +1,569 @@
+/* ecc-sm2.c  -  Elliptic Curve SM2 implementation
+ * Copyright (C) 2020 Tianjia Zhang
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "bithelp.h"
+#include "mpi.h"
+#include "cipher.h"
+#include "context.h"
+#include "ec-context.h"
+#include "pubkey-internal.h"
+#include "ecc-common.h"
+
+#define MPI_NBYTES(m)   ((mpi_get_nbits(m) + 7) / 8)
+
+
+/* Key derivation function from X9.63/SECG */
+static gpg_err_code_t
+kdf_x9_63 (int algo, const void *in, size_t inlen, void *out, size_t outlen)
+{
+  gpg_err_code_t rc;
+  gcry_md_hd_t hd;
+  int mdlen;
+  u32 counter = 1;
+  u32 counter_be;
+  unsigned char *dgst;
+  unsigned char *pout = out;
+  size_t rlen = outlen;
+  size_t len;
+
+  rc = _gcry_md_open (&hd, algo, 0);
+  if (rc)
+    return rc;
+
+  mdlen = _gcry_md_get_algo_dlen (algo);
+
+  while (rlen > 0)
+    {
+      counter_be = be_bswap32 (counter);   /* cpu_to_be32 */
+      counter++;
+
+      _gcry_md_write (hd, in, inlen);
+      _gcry_md_write (hd, &counter_be, sizeof(counter_be));
+
+      dgst = _gcry_md_read (hd, algo);
+      if (dgst == NULL)
+        {
+          rc = GPG_ERR_DIGEST_ALGO;
+          break;
+        }
+
+      len = mdlen < rlen ? mdlen : rlen;  /* min(mdlen, rlen) */
+      memcpy (pout, dgst, len);
+      rlen -= len;
+      pout += len;
+
+      _gcry_md_reset (hd);
+    }
+
+  _gcry_md_close (hd);
+  return rc;
+}
+
+
+/* _gcry_ecc_sm2_encrypt description:
+ *   input:
+ *     data[0] : octet string
+ *   output: A new S-expression with the parameters:
+ *     a: c1 : generated ephemeral public key (kG)
+ *     b: c3 : Hash(x2 || IN || y2)
+ *     c: c2 : cipher
+ *
+ * sm2_decrypt description:
+ *   in contrast to encrypt
+ */
+gpg_err_code_t
+_gcry_ecc_sm2_encrypt (gcry_sexp_t *r_ciph, gcry_mpi_t input, mpi_ec_t ec)
+{
+  gpg_err_code_t rc;
+  const int algo = GCRY_MD_SM3;
+  gcry_md_hd_t md = NULL;
+  int mdlen;
+  unsigned char *dgst;
+  gcry_mpi_t k = NULL;
+  mpi_point_struct kG, kP;
+  gcry_mpi_t x1, y1;
+  gcry_mpi_t x2, y2;
+  gcry_mpi_t x2y2 = NULL;
+  unsigned char *in = NULL;
+  unsigned int inlen;
+  unsigned char *raw;
+  unsigned int rawlen;
+  unsigned char *cipher = NULL;
+  int i;
+
+  point_init (&kG);
+  point_init (&kP);
+  x1 = mpi_new (0);
+  y1 = mpi_new (0);
+  x2 = mpi_new (0);
+  y2 = mpi_new (0);
+
+  in = _gcry_mpi_get_buffer (input, 0, &inlen, NULL);
+  if (!in)
+    {
+      rc = gpg_err_code_from_syserror ();
+      goto leave;
+    }
+
+  cipher = xtrymalloc (inlen);
+  if (!cipher)
+    {
+      rc = gpg_err_code_from_syserror ();
+      goto leave;
+    }
+
+  /* rand k in [1, n-1] */
+  k = _gcry_dsa_gen_k (ec->n, GCRY_VERY_STRONG_RANDOM);
+
+  /* [k]G = (x1, y1) */
+  _gcry_mpi_ec_mul_point (&kG, k, ec->G, ec);
+  if (_gcry_mpi_ec_get_affine (x1, y1, &kG, ec))
+    {
+      if (DBG_CIPHER)
+        log_debug ("Bad check: kG can not be a Point at Infinity!\n");
+      rc = GPG_ERR_INV_DATA;
+      goto leave;
+    }
+
+  /* [k]P = (x2, y2) */
+  _gcry_mpi_ec_mul_point (&kP, k, ec->Q, ec);
+  if (_gcry_mpi_ec_get_affine (x2, y2, &kP, ec))
+    {
+      rc = GPG_ERR_INV_DATA;
+      goto leave;
+    }
+
+  /* t = KDF(x2 || y2, klen) */
+  x2y2 = _gcry_mpi_ec_ec2os (&kP, ec);
+  raw = mpi_get_opaque (x2y2, &rawlen);
+  rawlen = (rawlen + 7) / 8;
+
+  /* skip the prefix '0x04' */
+  raw += 1;
+  rawlen -= 1;
+  rc = kdf_x9_63 (algo, raw, rawlen, cipher, inlen);
+  if (rc)
+    goto leave;
+
+  /* cipher = t xor in */
+  for (i = 0; i < inlen; i++)
+    cipher[i] ^= in[i];
+
+  /* hash(x2 || IN || y2) */
+  mdlen = _gcry_md_get_algo_dlen (algo);
+  rc = _gcry_md_open (&md, algo, 0);
+  if (rc)
+    goto leave;
+  _gcry_md_write (md, raw, MPI_NBYTES(x2));
+  _gcry_md_write (md, in, inlen);
+  _gcry_md_write (md, raw + MPI_NBYTES(x2), MPI_NBYTES(y2));
+  dgst = _gcry_md_read (md, algo);
+  if (dgst == NULL)
+    {
+      rc = GPG_ERR_DIGEST_ALGO;
+      goto leave;
+    }
+
+  if (!rc)
+    {
+      gcry_mpi_t c1;
+      gcry_mpi_t c3;
+      gcry_mpi_t c2;
+
+      c3 = mpi_new (0);
+      c2 = mpi_new (0);
+
+      c1 = _gcry_ecc_ec2os (x1, y1, ec->p);
+      _gcry_mpi_set_opaque_copy (c3, dgst, mdlen * 8);
+      _gcry_mpi_set_opaque_copy (c2, cipher, inlen * 8);
+
+      rc = sexp_build (r_ciph, NULL,
+                       "(enc-val(flags sm2)(sm2(a%M)(b%M)(c%M)))",
+                       c1, c3, c2);
+
+      mpi_free (c1);
+      mpi_free (c3);
+      mpi_free (c2);
+    }
+
+leave:
+  _gcry_md_close (md);
+  mpi_free (x2y2);
+  mpi_free (k);
+
+  point_free (&kG);
+  point_free (&kP);
+  mpi_free (x1);
+  mpi_free (y1);
+  mpi_free (x2);
+  mpi_free (y2);
+
+  xfree (cipher);
+  xfree (in);
+
+  return rc;
+}
+
+
+gpg_err_code_t
+_gcry_ecc_sm2_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t data_list, mpi_ec_t ec)
+{
+  gpg_err_code_t rc;
+  gcry_mpi_t data_c1 = NULL;
+  gcry_mpi_t data_c3 = NULL;
+  gcry_mpi_t data_c2 = NULL;
+
+  /*
+   * Extract the data.
+   */
+  rc = sexp_extract_param (data_list, NULL, "/a/b/c",
+                           &data_c1, &data_c3, &data_c2, NULL);
+  if (rc)
+    goto leave;
+  if (DBG_CIPHER)
+    {
+      log_printmpi ("ecc_decrypt  d_c1", data_c1);
+      log_printmpi ("ecc_decrypt  d_c3", data_c3);
+      log_printmpi ("ecc_decrypt  d_c2", data_c2);
+    }
+
+  {
+    const int algo = GCRY_MD_SM3;
+    gcry_md_hd_t md = NULL;
+    int mdlen;
+    unsigned char *dgst;
+    mpi_point_struct c1;
+    mpi_point_struct kP;
+    gcry_mpi_t x2, y2;
+    gcry_mpi_t x2y2 = NULL;
+    unsigned char *in = NULL;
+    unsigned int inlen;
+    unsigned char *plain = NULL;
+    unsigned char *raw;
+    unsigned int rawlen;
+    unsigned char *c3 = NULL;
+    unsigned int c3_len;
+    int i;
+
+    point_init (&c1);
+    point_init (&kP);
+    x2 = mpi_new (0);
+    y2 = mpi_new (0);
+
+    in = mpi_get_opaque (data_c2, &inlen);
+    inlen = (inlen + 7) / 8;
+    plain = xtrymalloc (inlen);
+    if (!plain)
+      {
+        rc = gpg_err_code_from_syserror ();
+        goto leave_main;
+      }
+
+    rc = _gcry_ecc_sec_decodepoint (data_c1, ec, &c1);
+    if (rc)
+      goto leave_main;
+
+    if (!_gcry_mpi_ec_curve_point (&c1, ec))
+      {
+        rc = GPG_ERR_INV_DATA;
+        goto leave_main;
+      }
+
+    /* [d]C1 = (x2, y2), C1 = [k]G */
+    _gcry_mpi_ec_mul_point (&kP, ec->d, &c1, ec);
+    if (_gcry_mpi_ec_get_affine (x2, y2, &kP, ec))
+      {
+        rc = GPG_ERR_INV_DATA;
+        goto leave_main;
+      }
+
+    /* t = KDF(x2 || y2, inlen) */
+    x2y2 = _gcry_mpi_ec_ec2os (&kP, ec);
+    raw = mpi_get_opaque (x2y2, &rawlen);
+    rawlen = (rawlen + 7) / 8;
+    /* skip the prefix '0x04' */
+    raw += 1;
+    rawlen -= 1;
+    rc = kdf_x9_63 (algo, raw, rawlen, plain, inlen);
+    if (rc)
+      goto leave_main;
+
+    /* plain = C2 xor t */
+    for (i = 0; i < inlen; i++)
+      plain[i] ^= in[i];
+
+    /* Hash(x2 || IN || y2) == C3 */
+    mdlen = _gcry_md_get_algo_dlen (algo);
+    rc = _gcry_md_open (&md, algo, 0);
+    if (rc)
+      goto leave_main;
+    _gcry_md_write (md, raw, MPI_NBYTES(x2));
+    _gcry_md_write (md, plain, inlen);
+    _gcry_md_write (md, raw + MPI_NBYTES(x2), MPI_NBYTES(y2));
+    dgst = _gcry_md_read (md, algo);
+    if (dgst == NULL)
+      {
+        memset (plain, 0, inlen);
+        rc = GPG_ERR_DIGEST_ALGO;
+        goto leave_main;
+      }
+    c3 = mpi_get_opaque (data_c3, &c3_len);
+    c3_len = (c3_len + 7) / 8;
+    if (c3_len != mdlen || memcmp (dgst, c3, c3_len) != 0)
+      {
+        memset (plain, 0, inlen);
+        rc = GPG_ERR_INV_DATA;
+        goto leave_main;
+      }
+
+    if (!rc)
+      {
+        gcry_mpi_t r;
+
+        r = mpi_new (inlen * 8);
+        _gcry_mpi_set_buffer (r, plain, inlen, 0);
+
+        rc = sexp_build (r_plain, NULL, "(value %m)", r);
+
+        mpi_free (r);
+      }
+
+  leave_main:
+    _gcry_md_close (md);
+    mpi_free (x2y2);
+    xfree (plain);
+
+    point_free (&c1);
+    point_free (&kP);
+    mpi_free (x2);
+    mpi_free (y2);
+  }
+
+ leave:
+  _gcry_mpi_release (data_c1);
+  _gcry_mpi_release (data_c3);
+  _gcry_mpi_release (data_c2);
+
+  return rc;
+}
+
+
+/* Compute an SM2 signature.
+ * Return the signature struct (r,s) from the message hash.  The caller
+ * must have allocated R and S.
+ */
+gpg_err_code_t
+_gcry_ecc_sm2_sign (gcry_mpi_t input, mpi_ec_t ec,
+                    gcry_mpi_t r, gcry_mpi_t s,
+                    int flags, int hashalgo)
+{
+  gpg_err_code_t rc = 0;
+  int extraloops = 0;
+  gcry_mpi_t hash;
+  const void *abuf;
+  unsigned int abits, qbits;
+  gcry_mpi_t tmp = NULL;
+  gcry_mpi_t k = NULL;
+  gcry_mpi_t rk = NULL;
+  mpi_point_struct kG;
+  gcry_mpi_t x1;
+
+  if (DBG_CIPHER)
+    log_mpidump ("sm2 sign hash  ", input);
+
+  qbits = mpi_get_nbits (ec->n);
+
+  /* Convert the INPUT into an MPI if needed.  */
+  rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
+  if (rc)
+    return rc;
+
+  point_init (&kG);
+  x1 = mpi_new (0);
+  rk = mpi_new (0);
+  tmp = mpi_new (0);
+
+  for (;;)
+    {
+      /* rand k in [1, n-1] */
+      if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
+        {
+          /* Use Pornin's method for deterministic DSA.  If this
+             flag is set, it is expected that HASH is an opaque
+             MPI with the to be signed hash.  That hash is also
+             used as h1 from 3.2.a.  */
+          if (!mpi_is_opaque (input))
+            {
+              rc = GPG_ERR_CONFLICT;
+              goto leave;
+            }
+
+          abuf = mpi_get_opaque (input, &abits);
+          rc = _gcry_dsa_gen_rfc6979_k (&k, ec->n, ec->d,
+                                        abuf, (abits+7)/8,
+                                        hashalgo, extraloops);
+          if (rc)
+            goto leave;
+          extraloops++;
+        }
+      else
+        k = _gcry_dsa_gen_k (ec->n, GCRY_VERY_STRONG_RANDOM);
+
+      _gcry_dsa_modify_k (k, ec->n, qbits);
+
+      /* [k]G = (x1, y1) */
+      _gcry_mpi_ec_mul_point (&kG, k, ec->G, ec);
+      if (_gcry_mpi_ec_get_affine (x1, NULL, &kG, ec))
+        {
+          rc = GPG_ERR_INV_DATA;
+          goto leave;
+        }
+
+      /* r = (e + x1) % n */
+      mpi_addm (r, hash, x1, ec->n);
+
+      /* r != 0 && r + k != n */
+      if (mpi_cmp_ui (r, 0) == 0)
+        continue;
+      mpi_add (rk, r, k);
+      if (mpi_cmp (rk, ec->n) == 0)
+        continue;
+
+      /* s = ((d + 1)^-1 * (k - rd)) % n */
+      mpi_addm (s, ec->d, GCRYMPI_CONST_ONE, ec->n);
+      mpi_invm (s, s, ec->n);
+      mpi_mulm (tmp, r, ec->d, ec->n);
+      mpi_subm (tmp, k, tmp, ec->n);
+      mpi_mulm (s, s, tmp, ec->n);
+
+      /* s != 0 */
+      if (mpi_cmp_ui (s, 0) == 0)
+        continue;
+
+      break;    /* Okay */
+    }
+
+  if (DBG_CIPHER)
+    {
+      log_mpidump ("sm2 sign result r ", r);
+      log_mpidump ("sm2 sign result s ", s);
+    }
+
+leave:
+  point_free (&kG);
+  mpi_free (k);
+  mpi_free (x1);
+  mpi_free (rk);
+  mpi_free (tmp);
+
+  if (hash != input)
+    mpi_free (hash);
+
+  return rc;
+}
+
+
+/* Verify an SM2 signature.
+ * Check if R and S verifies INPUT.
+ */
+gpg_err_code_t
+_gcry_ecc_sm2_verify (gcry_mpi_t input, mpi_ec_t ec,
+                      gcry_mpi_t r, gcry_mpi_t s)
+{
+  gpg_err_code_t err = 0;
+  gcry_mpi_t hash = NULL;
+  gcry_mpi_t t = NULL;
+  mpi_point_struct sG, tP;
+  gcry_mpi_t x1, y1;
+  unsigned int nbits;
+
+  if (!_gcry_mpi_ec_curve_point (ec->Q, ec))
+    return GPG_ERR_BROKEN_PUBKEY;
+
+  /* r, s within [1, n-1] */
+  if (mpi_cmp_ui (r, 1) < 0 || mpi_cmp (r, ec->n) > 0)
+    return GPG_ERR_BAD_SIGNATURE;
+  if (mpi_cmp_ui (s, 1) < 0 || mpi_cmp (s, ec->n) > 0)
+    return GPG_ERR_BAD_SIGNATURE;
+
+  nbits = mpi_get_nbits (ec->n);
+  err = _gcry_dsa_normalize_hash (input, &hash, nbits);
+  if (err)
+    return err;
+
+  point_init (&sG);
+  point_init (&tP);
+  x1 = mpi_new (0);
+  y1 = mpi_new (0);
+  t = mpi_new (0);
+
+  /* t = (r + s) % n, t != 0 */
+  mpi_addm (t, r, s, ec->n);
+  if (mpi_cmp_ui (t, 0) == 0)
+    {
+      err = GPG_ERR_BAD_SIGNATURE;
+      goto leave;
+    }
+
+  /* sG + tP = (x1, y1) */
+  _gcry_mpi_ec_mul_point (&sG, s, ec->G, ec);
+  _gcry_mpi_ec_mul_point (&tP, t, ec->Q, ec);
+  _gcry_mpi_ec_add_points (&sG, &sG, &tP, ec);
+  if (_gcry_mpi_ec_get_affine (x1, y1, &sG, ec))
+    {
+      err = GPG_ERR_INV_DATA;
+      goto leave;
+    }
+
+  /* R = (e + x1) % n */
+  mpi_addm (t, hash, x1, ec->n);
+
+  /* check R == r */
+  if (mpi_cmp (t, r))
+    {
+      if (DBG_CIPHER)
+        {
+          log_mpidump ("     R", t);
+          log_mpidump ("     r", r);
+          log_mpidump ("     s", s);
+        }
+      err = GPG_ERR_BAD_SIGNATURE;
+      goto leave;
+    }
+  if (DBG_CIPHER)
+    log_debug ("sm2 verify: Accepted\n");
+
+ leave:
+  point_free (&sG);
+  point_free (&tP);
+  mpi_free (x1);
+  mpi_free (y1);
+  mpi_free (t);
+  if (hash != input)
+    mpi_free (hash);
+
+  return err;
+}
index 3f221a2..9f0e7b1 100644 (file)
@@ -69,6 +69,7 @@ static const char *ecc_names[] =
     "ecdh",
     "eddsa",
     "gost",
+    "sm2",
     NULL,
   };
 
@@ -99,8 +100,8 @@ static void *progress_cb_data;
 
 \f
 /* Local prototypes. */
-static void test_keys (ECC_secret_key * sk, unsigned int nbits);
-static void test_ecdh_only_keys (ECC_secret_key * sk, unsigned int nbits, int flags);
+static void test_keys (mpi_ec_t ec, unsigned int nbits);
+static void test_ecdh_only_keys (mpi_ec_t ec, unsigned int nbits, int flags);
 static unsigned int ecc_get_nbits (gcry_sexp_t parms);
 
 
@@ -126,11 +127,8 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
 \f
 /**
  * nist_generate_key - Standard version of the ECC key generation.
- * @sk:  A struct to receive the secret key.
- * @E:   Parameters of the curve.
- * @ctx: Elliptic curve computation context.
+ * @ec: Elliptic curve computation context.
  * @flags: Flags controlling aspects of the creation.
- * @nbits: Only for testing
  * @r_x: On success this receives an allocated MPI with the affine
  *       x-coordinate of the poblic key.  On error NULL is stored.
  * @r_y: Ditto for the y-coordinate.
@@ -144,14 +142,13 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
  * FIXME: Check whether N is needed.
  */
 static gpg_err_code_t
-nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
-                   int flags, unsigned int nbits,
+nist_generate_key (mpi_ec_t ec, int flags,
                    gcry_mpi_t *r_x, gcry_mpi_t *r_y)
 {
   mpi_point_struct Q;
   gcry_random_level_t random_level;
   gcry_mpi_t x, y;
-  const unsigned int pbits = mpi_get_nbits (E->p);
+  const unsigned int pbits = ec->nbits;
 
   point_init (&Q);
 
@@ -161,43 +158,39 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
     random_level = GCRY_VERY_STRONG_RANDOM;
 
   /* Generate a secret.  */
-  if (ctx->dialect == ECC_DIALECT_ED25519 || (flags & PUBKEY_FLAG_DJB_TWEAK))
+  if (ec->dialect == ECC_DIALECT_ED25519
+      || ec->dialect == ECC_DIALECT_SAFECURVE
+      || (flags & PUBKEY_FLAG_DJB_TWEAK))
     {
       char *rndbuf;
+      int len = (pbits+7)/8;
 
-      sk->d = mpi_snew (256);
-      rndbuf = _gcry_random_bytes_secure (32, random_level);
-      rndbuf[0] &= 0x7f;  /* Clear bit 255. */
-      rndbuf[0] |= 0x40;  /* Set bit 254.   */
-      rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0  */
-      _gcry_mpi_set_buffer (sk->d, rndbuf, 32, 0);
-      xfree (rndbuf);
+      rndbuf = _gcry_random_bytes_secure (len, random_level);
+      if (ec->dialect == ECC_DIALECT_SAFECURVE)
+        ec->d = mpi_set_opaque (NULL, rndbuf, len*8);
+      else
+        {
+          ec->d = mpi_snew (pbits);
+          if ((pbits % 8))
+            rndbuf[0] &= (1 << (pbits % 8)) - 1;
+          rndbuf[0] |= (1 << ((pbits + 7) % 8));
+          rndbuf[len-1] &= (256 - ec->h);
+          _gcry_mpi_set_buffer (ec->d, rndbuf, len, 0);
+          xfree (rndbuf);
+        }
     }
   else
-    sk->d = _gcry_dsa_gen_k (E->n, random_level);
-
+    ec->d = _gcry_dsa_gen_k (ec->n, random_level);
 
   /* Compute Q.  */
-  _gcry_mpi_ec_mul_point (&Q, sk->d, &E->G, ctx);
-
-  /* Copy the stuff to the key structures. */
-  sk->E.model = E->model;
-  sk->E.dialect = E->dialect;
-  sk->E.p = mpi_copy (E->p);
-  sk->E.a = mpi_copy (E->a);
-  sk->E.b = mpi_copy (E->b);
-  point_init (&sk->E.G);
-  point_set (&sk->E.G, &E->G);
-  sk->E.n = mpi_copy (E->n);
-  sk->E.h = mpi_copy (E->h);
-  point_init (&sk->Q);
+  _gcry_mpi_ec_mul_point (&Q, ec->d, ec->G, ec);
 
   x = mpi_new (pbits);
   if (r_y == NULL)
     y = NULL;
   else
     y = mpi_new (pbits);
-  if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
+  if (_gcry_mpi_ec_get_affine (x, y, &Q, ec))
     log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
 
   /* We want the Q=(x,y) be a "compliant key" in terms of the
@@ -209,24 +202,24 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
    * possibilities without any loss of security.  Note that we don't
    * do that for Ed25519 so that we do not violate the special
    * construction of the secret key.  */
-  if (r_y == NULL || E->dialect == ECC_DIALECT_ED25519)
-    point_set (&sk->Q, &Q);
+  if (r_y == NULL || ec->dialect == ECC_DIALECT_ED25519)
+    ec->Q = mpi_point_set (NULL, Q.x, Q.y, Q.z);
   else
     {
       gcry_mpi_t negative;
 
       negative = mpi_new (pbits);
 
-      if (E->model == MPI_EC_WEIERSTRASS)
-        mpi_sub (negative, E->p, y);      /* negative = p - y */
+      if (ec->model == MPI_EC_WEIERSTRASS)
+        mpi_sub (negative, ec->p, y);      /* negative = p - y */
       else
-        mpi_sub (negative, E->p, x);      /* negative = p - x */
+        mpi_sub (negative, ec->p, x);      /* negative = p - x */
 
       if (mpi_cmp (negative, y) < 0)   /* p - y < p */
         {
           /* We need to end up with -Q; this assures that new Q's y is
              the smallest one */
-          if (E->model == MPI_EC_WEIERSTRASS)
+          if (ec->model == MPI_EC_WEIERSTRASS)
             {
               mpi_free (y);
               y = negative;
@@ -236,8 +229,8 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
               mpi_free (x);
               x = negative;
             }
-          mpi_sub (sk->d, E->n, sk->d);   /* d = order - d */
-          mpi_point_set (&sk->Q, x, y, mpi_const (MPI_C_ONE));
+          mpi_sub (ec->d, ec->n, ec->d);   /* d = order - d */
+          ec->Q = mpi_point_set (NULL, x, y, mpi_const (MPI_C_ONE));
 
           if (DBG_CIPHER)
             log_debug ("ecgen converted Q to a compliant point\n");
@@ -246,7 +239,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
         {
           /* No change is needed exactly 50% of the time: just copy. */
           mpi_free (negative);
-          point_set (&sk->Q, &Q);
+          ec->Q = mpi_point_set (NULL, Q.x, Q.y, Q.z);
           if (DBG_CIPHER)
             log_debug ("ecgen didn't need to convert Q to a compliant point\n");
         }
@@ -260,10 +253,10 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
   /* Now we can test our keys (this should never fail!).  */
   if ((flags & PUBKEY_FLAG_NO_KEYTEST))
     ; /* User requested to skip the test.  */
-  else if (sk->E.model != MPI_EC_MONTGOMERY)
-    test_keys (sk, nbits - 64);
+  else if (ec->model == MPI_EC_MONTGOMERY)
+    test_ecdh_only_keys (ec, ec->nbits - 63, flags);
   else
-    test_ecdh_only_keys (sk, nbits - 64, flags);
+    test_keys (ec, ec->nbits - 64);
 
   return 0;
 }
@@ -276,9 +269,8 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
  * Second, test with the sign and verify functions.
  */
 static void
-test_keys (ECC_secret_key *sk, unsigned int nbits)
+test_keys (mpi_ec_t ec, unsigned int nbits)
 {
-  ECC_public_key pk;
   gcry_mpi_t test = mpi_new (nbits);
   mpi_point_struct R_;
   gcry_mpi_t c = mpi_new (nbits);
@@ -291,16 +283,12 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
 
   point_init (&R_);
 
-  pk.E = _gcry_ecc_curve_copy (sk->E);
-  point_init (&pk.Q);
-  point_set (&pk.Q, &sk->Q);
-
   _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
 
-  if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) )
+  if (_gcry_ecc_ecdsa_sign (test, NULL, ec, r, s, 0, 0) )
     log_fatal ("ECDSA operation: sign failed\n");
 
-  if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
+  if (_gcry_ecc_ecdsa_verify (test, ec, r, s, 0, 0))
     {
       log_fatal ("ECDSA operation: sign, verify failed\n");
     }
@@ -308,9 +296,6 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
   if (DBG_CIPHER)
     log_debug ("ECDSA operation: sign, verify ok.\n");
 
-  point_free (&pk.Q);
-  _gcry_ecc_curve_free (&pk.E);
-
   point_free (&R_);
   mpi_free (s);
   mpi_free (r);
@@ -321,34 +306,36 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
 
 
 static void
-test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits, int flags)
+test_ecdh_only_keys (mpi_ec_t ec, unsigned int nbits, int flags)
 {
-  ECC_public_key pk;
   gcry_mpi_t test;
   mpi_point_struct R_;
   gcry_mpi_t x0, x1;
-  mpi_ec_t ec;
 
   if (DBG_CIPHER)
     log_debug ("Testing ECDH only key.\n");
 
   point_init (&R_);
 
-  pk.E = _gcry_ecc_curve_copy (sk->E);
-  point_init (&pk.Q);
-  point_set (&pk.Q, &sk->Q);
-
-  if ((flags & PUBKEY_FLAG_DJB_TWEAK))
+  if (ec->dialect == ECC_DIALECT_SAFECURVE || (flags & PUBKEY_FLAG_DJB_TWEAK))
     {
       char *rndbuf;
+      const unsigned int pbits = ec->nbits;
+      int len = (pbits+7)/8;
 
-      test = mpi_new (256);
-      rndbuf = _gcry_random_bytes (32, GCRY_WEAK_RANDOM);
-      rndbuf[0] &= 0x7f;  /* Clear bit 255. */
-      rndbuf[0] |= 0x40;  /* Set bit 254.   */
-      rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0  */
-      _gcry_mpi_set_buffer (test, rndbuf, 32, 0);
-      xfree (rndbuf);
+      rndbuf = _gcry_random_bytes (len, GCRY_WEAK_RANDOM);
+      if (ec->dialect == ECC_DIALECT_SAFECURVE)
+        test = mpi_set_opaque (NULL, rndbuf, len*8);
+      else
+        {
+          test = mpi_new (pbits);
+          if ((pbits % 8))
+            rndbuf[0] &= (1 << (pbits % 8)) - 1;
+          rndbuf[0] |= (1 << ((pbits + 7) % 8));
+          rndbuf[len-1] &= (256 - ec->h);
+          _gcry_mpi_set_buffer (test, rndbuf, len, 0);
+          xfree (rndbuf);
+        }
     }
   else
     {
@@ -356,23 +343,21 @@ test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits, int flags)
       _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
     }
 
-  ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, flags,
-                                    pk.E.p, pk.E.a, pk.E.b);
   x0 = mpi_new (0);
   x1 = mpi_new (0);
 
   /* R_ = hkQ  <=>  R_ = hkdG  */
-  _gcry_mpi_ec_mul_point (&R_, test, &pk.Q, ec);
-  if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
-    _gcry_mpi_ec_mul_point (&R_, ec->h, &R_, ec);
+  _gcry_mpi_ec_mul_point (&R_, test, ec->Q, ec);
+  if (ec->dialect == ECC_DIALECT_STANDARD && !(flags & PUBKEY_FLAG_DJB_TWEAK))
+    _gcry_mpi_ec_mul_point (&R_, _gcry_mpi_get_const (ec->h), &R_, ec);
   if (_gcry_mpi_ec_get_affine (x0, NULL, &R_, ec))
     log_fatal ("ecdh: Failed to get affine coordinates for hkQ\n");
 
-  _gcry_mpi_ec_mul_point (&R_, test, &pk.E.G, ec);
-  _gcry_mpi_ec_mul_point (&R_, sk->d, &R_, ec);
+  _gcry_mpi_ec_mul_point (&R_, test, ec->G, ec);
+  _gcry_mpi_ec_mul_point (&R_, ec->d, &R_, ec);
   /* R_ = hdkG */
-  if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
-    _gcry_mpi_ec_mul_point (&R_, ec->h, &R_, ec);
+  if (ec->dialect == ECC_DIALECT_STANDARD && !(flags & PUBKEY_FLAG_DJB_TWEAK))
+    _gcry_mpi_ec_mul_point (&R_, _gcry_mpi_get_const (ec->h), &R_, ec);
 
   if (_gcry_mpi_ec_get_affine (x1, NULL, &R_, ec))
     log_fatal ("ecdh: Failed to get affine coordinates for hdkG\n");
@@ -384,10 +369,6 @@ test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits, int flags)
 
   mpi_free (x0);
   mpi_free (x1);
-  _gcry_mpi_ec_free (ec);
-
-  point_free (&pk.Q);
-  _gcry_ecc_curve_free (&pk.E);
 
   point_free (&R_);
   mpi_free (test);
@@ -399,7 +380,7 @@ test_ecdh_only_keys (ECC_secret_key *sk, unsigned int nbits, int flags)
  * between the public value and the secret one.
  */
 static int
-check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
+check_secret_key (mpi_ec_t ec, int flags)
 {
   int rc = 1;
   mpi_point_struct Q;
@@ -415,7 +396,7 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
     y1 = mpi_new (0);
 
   /* G in E(F_p) */
-  if (!_gcry_mpi_ec_curve_point (&sk->E.G, ec))
+  if (!_gcry_mpi_ec_curve_point (ec->G, ec))
     {
       if (DBG_CIPHER)
         log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
@@ -423,7 +404,7 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
     }
 
   /* G != PaI */
-  if (!mpi_cmp_ui (sk->E.G.z, 0))
+  if (!mpi_cmp_ui (ec->G->z, 0))
     {
       if (DBG_CIPHER)
         log_debug ("Bad check: 'G' cannot be Point at Infinity!\n");
@@ -431,9 +412,9 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
     }
 
   /* Check order of curve.  */
-  if (sk->E.dialect != ECC_DIALECT_ED25519 && !(flags & PUBKEY_FLAG_DJB_TWEAK))
+  if (ec->dialect == ECC_DIALECT_STANDARD && !(flags & PUBKEY_FLAG_DJB_TWEAK))
     {
-      _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ec);
+      _gcry_mpi_ec_mul_point (&Q, ec->n, ec->G, ec);
       if (mpi_cmp_ui (Q.z, 0))
         {
           if (DBG_CIPHER)
@@ -443,7 +424,7 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
     }
 
   /* Pubkey cannot be PaI */
-  if (!mpi_cmp_ui (sk->Q.z, 0))
+  if (!mpi_cmp_ui (ec->Q->z, 0))
     {
       if (DBG_CIPHER)
         log_debug ("Bad check: Q can not be a Point at Infinity!\n");
@@ -451,7 +432,7 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
     }
 
   /* pubkey = [d]G over E */
-  if (!_gcry_ecc_compute_public (&Q, ec, &sk->E.G, sk->d))
+  if (!_gcry_ecc_compute_public (&Q, ec))
     {
       if (DBG_CIPHER)
         log_debug ("Bad check: computation of dG failed\n");
@@ -464,12 +445,13 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
       goto leave;
     }
 
-  if ((flags & PUBKEY_FLAG_EDDSA))
+  if ((flags & PUBKEY_FLAG_EDDSA)
+      || (ec->model == MPI_EC_EDWARDS && ec->dialect == ECC_DIALECT_SAFECURVE))
     ; /* Fixme: EdDSA is special.  */
-  else if (!mpi_cmp_ui (sk->Q.z, 1))
+  else if (!mpi_cmp_ui (ec->Q->z, 1))
     {
       /* Fast path if Q is already in affine coordinates.  */
-      if (mpi_cmp (x1, sk->Q.x) || (y1 && mpi_cmp (y1, sk->Q.y)))
+      if (mpi_cmp (x1, ec->Q->x) || (y1 && mpi_cmp (y1, ec->Q->y)))
         {
           if (DBG_CIPHER)
             log_debug
@@ -481,7 +463,7 @@ check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
     {
       x2 = mpi_new (0);
       y2 = mpi_new (0);
-      if (_gcry_mpi_ec_get_affine (x2, y2, &sk->Q, ec))
+      if (_gcry_mpi_ec_get_affine (x2, y2, ec->Q, ec))
         {
           if (DBG_CIPHER)
             log_debug ("Bad check: Q can not be a Point at Infinity!\n");
@@ -517,124 +499,57 @@ static gcry_err_code_t
 ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
 {
   gpg_err_code_t rc;
-  unsigned int nbits;
-  elliptic_curve_t E;
-  ECC_secret_key sk;
   gcry_mpi_t Gx = NULL;
   gcry_mpi_t Gy = NULL;
   gcry_mpi_t Qx = NULL;
   gcry_mpi_t Qy = NULL;
-  char *curve_name = NULL;
-  gcry_sexp_t l1;
-  mpi_ec_t ctx = NULL;
+  mpi_ec_t ec = NULL;
   gcry_sexp_t curve_info = NULL;
   gcry_sexp_t curve_flags = NULL;
   gcry_mpi_t base = NULL;
   gcry_mpi_t public = NULL;
-  gcry_mpi_t secret = NULL;
   int flags = 0;
 
-  memset (&E, 0, sizeof E);
-  memset (&sk, 0, sizeof sk);
-
-  rc = _gcry_pk_util_get_nbits (genparms, &nbits);
-  if (rc)
-    return rc;
-
-  /* Parse the optional "curve" parameter. */
-  l1 = sexp_find_token (genparms, "curve", 0);
-  if (l1)
-    {
-      curve_name = _gcry_sexp_nth_string (l1, 1);
-      sexp_release (l1);
-      if (!curve_name)
-        return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
-    }
-
-  /* Parse the optional flags list.  */
-  l1 = sexp_find_token (genparms, "flags", 0);
-  if (l1)
-    {
-      rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
-      sexp_release (l1);
-      if (rc)
-        goto leave;
-    }
-
-  /* Parse the deprecated optional transient-key flag.  */
-  l1 = sexp_find_token (genparms, "transient-key", 0);
-  if (l1)
-    {
-      flags |= PUBKEY_FLAG_TRANSIENT_KEY;
-      sexp_release (l1);
-    }
-
-  /* NBITS is required if no curve name has been given.  */
-  if (!nbits && !curve_name)
-    return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
-
-  rc = _gcry_ecc_fill_in_curve (nbits, curve_name, &E, &nbits);
+  rc = _gcry_mpi_ec_internal_new (&ec, &flags, "ecgen curve", genparms, NULL);
   if (rc)
     goto leave;
 
-  if (DBG_CIPHER)
-    {
-      log_debug ("ecgen curve info: %s/%s\n",
-                 _gcry_ecc_model2str (E.model),
-                 _gcry_ecc_dialect2str (E.dialect));
-      if (E.name)
-        log_debug ("ecgen curve used: %s\n", E.name);
-      log_printmpi ("ecgen curve   p", E.p);
-      log_printmpi ("ecgen curve   a", E.a);
-      log_printmpi ("ecgen curve   b", E.b);
-      log_printmpi ("ecgen curve   n", E.n);
-      log_printmpi ("ecgen curve   h", E.h);
-      log_printpnt ("ecgen curve G", &E.G, NULL);
-    }
-
-  ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, flags, E.p, E.a, E.b);
-
-  if (E.model == MPI_EC_MONTGOMERY)
-    rc = nist_generate_key (&sk, &E, ctx, flags, nbits, &Qx, NULL);
-  else if ((flags & PUBKEY_FLAG_EDDSA))
-    rc = _gcry_ecc_eddsa_genkey (&sk, &E, ctx, flags);
+  if ((flags & PUBKEY_FLAG_EDDSA)
+      || (ec->model == MPI_EC_EDWARDS && ec->dialect == ECC_DIALECT_SAFECURVE))
+    rc = _gcry_ecc_eddsa_genkey (ec, flags);
+  else if (ec->model == MPI_EC_MONTGOMERY)
+    rc = nist_generate_key (ec, flags, &Qx, NULL);
   else
-    rc = nist_generate_key (&sk, &E, ctx, flags, nbits, &Qx, &Qy);
+    rc = nist_generate_key (ec, flags, &Qx, &Qy);
   if (rc)
     goto leave;
 
   /* Copy data to the result.  */
   Gx = mpi_new (0);
   Gy = mpi_new (0);
-  if (E.model != MPI_EC_MONTGOMERY)
+  if (ec->model != MPI_EC_MONTGOMERY)
     {
-      if (_gcry_mpi_ec_get_affine (Gx, Gy, &sk.E.G, ctx))
+      if (_gcry_mpi_ec_get_affine (Gx, Gy, ec->G, ec))
         log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G");
-      base = _gcry_ecc_ec2os (Gx, Gy, sk.E.p);
+      base = _gcry_ecc_ec2os (Gx, Gy, ec->p);
     }
-  if ((sk.E.dialect == ECC_DIALECT_ED25519 || E.model == MPI_EC_MONTGOMERY)
+  if (((ec->dialect == ECC_DIALECT_SAFECURVE && ec->model == MPI_EC_EDWARDS)
+       || ec->dialect == ECC_DIALECT_ED25519 || ec->model == MPI_EC_MONTGOMERY)
       && !(flags & PUBKEY_FLAG_NOCOMP))
     {
       unsigned char *encpk;
       unsigned int encpklen;
 
-      if (E.model != MPI_EC_MONTGOMERY)
+      if (ec->model == MPI_EC_MONTGOMERY)
+        rc = _gcry_ecc_mont_encodepoint (Qx, ec->nbits,
+                                         ec->dialect != ECC_DIALECT_SAFECURVE,
+                                         &encpk, &encpklen);
+      else
         /* (Gx and Gy are used as scratch variables)  */
-        rc = _gcry_ecc_eddsa_encodepoint (&sk.Q, ctx, Gx, Gy,
-                                          !!(flags & PUBKEY_FLAG_COMP),
+        rc = _gcry_ecc_eddsa_encodepoint (ec->Q, ec, Gx, Gy,
+                                          (ec->dialect != ECC_DIALECT_SAFECURVE
+                                           && !!(flags & PUBKEY_FLAG_COMP)),
                                           &encpk, &encpklen);
-      else
-        {
-          encpk = _gcry_mpi_get_buffer_extra (Qx, nbits/8,
-                                              -1, &encpklen, NULL);
-          if (encpk == NULL)
-            rc = gpg_err_code_from_syserror ();
-          else
-            {
-              encpk[0] = 0x40;
-              encpklen++;
-            }
-        }
       if (rc)
         goto leave;
       public = mpi_new (0);
@@ -648,15 +563,14 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
              with no compression.  */
           Qx = mpi_new (0);
           Qy = mpi_new (0);
-          if (_gcry_mpi_ec_get_affine (Qx, Qy, &sk.Q, ctx))
+          if (_gcry_mpi_ec_get_affine (Qx, Qy, ec->Q, ec))
             log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
         }
-      public = _gcry_ecc_ec2os (Qx, Qy, sk.E.p);
+      public = _gcry_ecc_ec2os (Qx, Qy, ec->p);
     }
-  secret = sk.d; sk.d = NULL;
-  if (E.name)
+  if (ec->name)
     {
-      rc = sexp_build (&curve_info, NULL, "(curve %s)", E.name);
+      rc = sexp_build (&curve_info, NULL, "(curve %s)", ec->name);
       if (rc)
         goto leave;
     }
@@ -668,7 +582,7 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
         (&curve_flags, NULL,
          ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))?
          "(flags param eddsa)" :
-         ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))?
+         ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_DJB_TWEAK))?
          "(flags param djb-tweak)" :
          ((flags & PUBKEY_FLAG_PARAM))?
          "(flags param)" : ((flags & PUBKEY_FLAG_EDDSA))?
@@ -677,19 +591,19 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
         goto leave;
     }
 
-  if ((flags & PUBKEY_FLAG_PARAM) && E.name)
+  if ((flags & PUBKEY_FLAG_PARAM) && ec->name)
     rc = sexp_build (r_skey, NULL,
                      "(key-data"
                      " (public-key"
-                     "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)))"
+                     "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%u)(q%m)))"
                      " (private-key"
-                     "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)(d%m)))"
+                     "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(h%u)(q%m)(d%m)))"
                      " )",
                      curve_info, curve_flags,
-                     sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, sk.E.h, public,
+                     ec->p, ec->a, ec->b, base, ec->n, ec->h, public,
                      curve_info, curve_flags,
-                     sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, sk.E.h, public,
-                                                                   secret);
+                     ec->p, ec->a, ec->b, base, ec->n, ec->h, public,
+                     ec->d);
   else
     rc = sexp_build (r_skey, NULL,
                      "(key-data"
@@ -701,40 +615,32 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
                      curve_info, curve_flags,
                      public,
                      curve_info, curve_flags,
-                     public, secret);
+                     public, ec->d);
   if (rc)
     goto leave;
 
   if (DBG_CIPHER)
     {
-      log_printmpi ("ecgen result  p", sk.E.p);
-      log_printmpi ("ecgen result  a", sk.E.a);
-      log_printmpi ("ecgen result  b", sk.E.b);
+      log_printmpi ("ecgen result  p", ec->p);
+      log_printmpi ("ecgen result  a", ec->a);
+      log_printmpi ("ecgen result  b", ec->b);
       log_printmpi ("ecgen result  G", base);
-      log_printmpi ("ecgen result  n", sk.E.n);
-      log_printmpi ("ecgen result  h", sk.E.h);
+      log_printmpi ("ecgen result  n", ec->n);
+      log_debug    ("ecgen result  h:+%02x\n", ec->h);
       log_printmpi ("ecgen result  Q", public);
-      log_printmpi ("ecgen result  d", secret);
+      log_printmpi ("ecgen result  d", ec->d);
       if ((flags & PUBKEY_FLAG_EDDSA))
         log_debug ("ecgen result  using Ed25519+EdDSA\n");
     }
 
  leave:
-  mpi_free (secret);
   mpi_free (public);
   mpi_free (base);
-  {
-    _gcry_ecc_curve_free (&sk.E);
-    point_free (&sk.Q);
-    mpi_free (sk.d);
-  }
-  _gcry_ecc_curve_free (&E);
   mpi_free (Gx);
   mpi_free (Gy);
   mpi_free (Qx);
   mpi_free (Qy);
-  _gcry_mpi_ec_free (ctx);
-  xfree (curve_name);
+  _gcry_mpi_ec_free (ec);
   sexp_release (curve_flags);
   sexp_release (curve_info);
   return rc;
@@ -745,135 +651,28 @@ static gcry_err_code_t
 ecc_check_secret_key (gcry_sexp_t keyparms)
 {
   gcry_err_code_t rc;
-  gcry_sexp_t l1 = NULL;
   int flags = 0;
-  char *curvename = NULL;
-  gcry_mpi_t mpi_g = NULL;
-  gcry_mpi_t mpi_q = NULL;
-  ECC_secret_key sk;
   mpi_ec_t ec = NULL;
 
-  memset (&sk, 0, sizeof sk);
-
-  /* Look for flags. */
-  l1 = sexp_find_token (keyparms, "flags", 0);
-  if (l1)
-    {
-      rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
-      if (rc)
-        goto leave;
-    }
-
-  /* Extract the parameters.  */
-  if ((flags & PUBKEY_FLAG_PARAM))
-    rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?/q?+d",
-                             &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
-                             &sk.E.h, &mpi_q, &sk.d, NULL);
-  else
-    rc = sexp_extract_param (keyparms, NULL, "/q?+d",
-                             &mpi_q, &sk.d, NULL);
+  /*
+   * Extract the key.
+   */
+  rc = _gcry_mpi_ec_internal_new (&ec, &flags, "ecc_testkey", keyparms, NULL);
   if (rc)
     goto leave;
-
-  /* Add missing parameters using the optional curve parameter.  */
-  sexp_release (l1);
-  l1 = sexp_find_token (keyparms, "curve", 5);
-  if (l1)
-    {
-      curvename = sexp_nth_string (l1, 1);
-      if (curvename)
-        {
-          rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
-          if (rc)
-            goto leave;
-        }
-    }
-  if (mpi_g)
-    {
-      if (!sk.E.G.x)
-        point_init (&sk.E.G);
-      rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
-      if (rc)
-        goto leave;
-    }
-
-  /* Guess required fields if a curve parameter has not been given.
-     FIXME: This is a crude hacks.  We need to fix that.  */
-  if (!curvename)
-    {
-      sk.E.model = ((flags & PUBKEY_FLAG_EDDSA)
-               ? MPI_EC_EDWARDS
-               : MPI_EC_WEIERSTRASS);
-      sk.E.dialect = ((flags & PUBKEY_FLAG_EDDSA)
-                      ? ECC_DIALECT_ED25519
-                      : ECC_DIALECT_STANDARD);
-      if (!sk.E.h)
-       sk.E.h = mpi_const (MPI_C_ONE);
-    }
-  if (DBG_CIPHER)
-    {
-      log_debug ("ecc_testkey inf: %s/%s\n",
-                 _gcry_ecc_model2str (sk.E.model),
-                 _gcry_ecc_dialect2str (sk.E.dialect));
-      if (sk.E.name)
-        log_debug  ("ecc_testkey nam: %s\n", sk.E.name);
-      log_printmpi ("ecc_testkey   p", sk.E.p);
-      log_printmpi ("ecc_testkey   a", sk.E.a);
-      log_printmpi ("ecc_testkey   b", sk.E.b);
-      log_printpnt ("ecc_testkey g",   &sk.E.G, NULL);
-      log_printmpi ("ecc_testkey   n", sk.E.n);
-      log_printmpi ("ecc_testkey   h", sk.E.h);
-      log_printmpi ("ecc_testkey   q", mpi_q);
-      if (!fips_mode ())
-        log_printmpi ("ecc_testkey   d", sk.d);
-    }
-  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
+  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n || !ec->Q || !ec->d)
     {
       rc = GPG_ERR_NO_OBJ;
       goto leave;
     }
 
-  ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, flags,
-                                    sk.E.p, sk.E.a, sk.E.b);
-
-  if (mpi_q)
-    {
-      point_init (&sk.Q);
-      if (ec->dialect == ECC_DIALECT_ED25519)
-        rc = _gcry_ecc_eddsa_decodepoint (mpi_q, ec, &sk.Q, NULL, NULL);
-      else if (ec->model == MPI_EC_MONTGOMERY)
-        rc = _gcry_ecc_mont_decodepoint (mpi_q, ec, &sk.Q);
-      else
-        rc = _gcry_ecc_os2ec (&sk.Q, mpi_q);
-      if (rc)
-        goto leave;
-    }
-  else
-    {
-      /* The secret key test requires Q.  */
-      rc = GPG_ERR_NO_OBJ;
-      goto leave;
-    }
-
-  if (check_secret_key (&sk, ec, flags))
+  if (check_secret_key (ec, flags))
     rc = GPG_ERR_BAD_SECKEY;
 
  leave:
   _gcry_mpi_ec_free (ec);
-  _gcry_mpi_release (sk.E.p);
-  _gcry_mpi_release (sk.E.a);
-  _gcry_mpi_release (sk.E.b);
-  _gcry_mpi_release (mpi_g);
-  point_free (&sk.E.G);
-  _gcry_mpi_release (sk.E.n);
-  _gcry_mpi_release (sk.E.h);
-  _gcry_mpi_release (mpi_q);
-  point_free (&sk.Q);
-  _gcry_mpi_release (sk.d);
-  xfree (curvename);
-  sexp_release (l1);
   if (DBG_CIPHER)
-    log_debug ("ecc_testkey   => %s\n", gpg_strerror (rc));
+    log_debug ("ecc_testkey    => %s\n", gpg_strerror (rc));
   return rc;
 }
 
@@ -884,18 +683,33 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   gcry_err_code_t rc;
   struct pk_encoding_ctx ctx;
   gcry_mpi_t data = NULL;
-  gcry_sexp_t l1 = NULL;
-  char *curvename = NULL;
-  gcry_mpi_t mpi_g = NULL;
-  gcry_mpi_t mpi_q = NULL;
-  ECC_secret_key sk;
+  gcry_mpi_t k = NULL;
   gcry_mpi_t sig_r = NULL;
   gcry_mpi_t sig_s = NULL;
-
-  memset (&sk, 0, sizeof sk);
+  mpi_ec_t ec = NULL;
+  int flags = 0;
 
   _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, 0);
 
+  /*
+   * Extract the key.
+   */
+  rc = _gcry_mpi_ec_internal_new (&ec, &flags, "ecc_sign", keyparms, NULL);
+  if (rc)
+    goto leave;
+  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n || !ec->d)
+    {
+      rc = GPG_ERR_NO_OBJ;
+      goto leave;
+    }
+
+  ctx.flags |= flags;
+  if (ec->model == MPI_EC_EDWARDS && ec->dialect == ECC_DIALECT_SAFECURVE)
+    ctx.flags |= PUBKEY_FLAG_EDDSA;
+  /* Clear hash algo for EdDSA.  */
+  if ((ctx.flags & PUBKEY_FLAG_EDDSA))
+    ctx.hash_algo = GCRY_MD_NONE;
+
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
   if (rc)
@@ -903,118 +717,60 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   if (DBG_CIPHER)
     log_mpidump ("ecc_sign   data", data);
 
-  /*
-   * Extract the key.
-   */
-  if ((ctx.flags & PUBKEY_FLAG_PARAM))
-    rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?/q?+d",
-                             &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
-                             &sk.E.h, &mpi_q, &sk.d, NULL);
-  else
-    rc = sexp_extract_param (keyparms, NULL, "/q?+d",
-                             &mpi_q, &sk.d, NULL);
+  if (ctx.label)
+    rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, ctx.label, ctx.labellen, NULL);
   if (rc)
     goto leave;
-  if (mpi_g)
-    {
-      point_init (&sk.E.G);
-      rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
-      if (rc)
-        goto leave;
-    }
-  /* Add missing parameters using the optional curve parameter.  */
-  l1 = sexp_find_token (keyparms, "curve", 5);
-  if (l1)
-    {
-      curvename = sexp_nth_string (l1, 1);
-      if (curvename)
-        {
-          rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
-          if (rc)
-            goto leave;
-        }
-    }
-  /* Guess required fields if a curve parameter has not been given.
-     FIXME: This is a crude hacks.  We need to fix that.  */
-  if (!curvename)
-    {
-      sk.E.model = ((ctx.flags & PUBKEY_FLAG_EDDSA)
-                    ? MPI_EC_EDWARDS
-                    : MPI_EC_WEIERSTRASS);
-      sk.E.dialect = ((ctx.flags & PUBKEY_FLAG_EDDSA)
-                      ? ECC_DIALECT_ED25519
-                      : ECC_DIALECT_STANDARD);
-      if (!sk.E.h)
-       sk.E.h = mpi_const (MPI_C_ONE);
-    }
-  if (DBG_CIPHER)
-    {
-      log_debug ("ecc_sign   info: %s/%s%s\n",
-                 _gcry_ecc_model2str (sk.E.model),
-                 _gcry_ecc_dialect2str (sk.E.dialect),
-                 (ctx.flags & PUBKEY_FLAG_EDDSA)? "+EdDSA":"");
-      if (sk.E.name)
-        log_debug  ("ecc_sign   name: %s\n", sk.E.name);
-      log_printmpi ("ecc_sign      p", sk.E.p);
-      log_printmpi ("ecc_sign      a", sk.E.a);
-      log_printmpi ("ecc_sign      b", sk.E.b);
-      log_printpnt ("ecc_sign    g",   &sk.E.G, NULL);
-      log_printmpi ("ecc_sign      n", sk.E.n);
-      log_printmpi ("ecc_sign      h", sk.E.h);
-      log_printmpi ("ecc_sign      q", mpi_q);
-      if (!fips_mode ())
-        log_printmpi ("ecc_sign      d", sk.d);
-    }
-  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
+
+  /* Hash algo is determined by curve in EdDSA.  Fill it if not specified.  */
+  if ((ctx.flags & PUBKEY_FLAG_EDDSA) && !ctx.hash_algo)
     {
-      rc = GPG_ERR_NO_OBJ;
-      goto leave;
+      if (ec->dialect == ECC_DIALECT_ED25519)
+        ctx.hash_algo = GCRY_MD_SHA512;
+      else if (ec->dialect == ECC_DIALECT_SAFECURVE)
+        ctx.hash_algo = GCRY_MD_SHAKE256;
     }
 
-
   sig_r = mpi_new (0);
   sig_s = mpi_new (0);
   if ((ctx.flags & PUBKEY_FLAG_EDDSA))
     {
       /* EdDSA requires the public key.  */
-      rc = _gcry_ecc_eddsa_sign (data, &sk, sig_r, sig_s, ctx.hash_algo, mpi_q);
+      rc = _gcry_ecc_eddsa_sign (data, ec, sig_r, sig_s, &ctx);
       if (!rc)
         rc = sexp_build (r_sig, NULL,
                          "(sig-val(eddsa(r%M)(s%M)))", sig_r, sig_s);
     }
   else if ((ctx.flags & PUBKEY_FLAG_GOST))
     {
-      rc = _gcry_ecc_gost_sign (data, &sk, sig_r, sig_s);
+      rc = _gcry_ecc_gost_sign (data, ec, sig_r, sig_s);
       if (!rc)
         rc = sexp_build (r_sig, NULL,
                          "(sig-val(gost(r%M)(s%M)))", sig_r, sig_s);
     }
+  else if ((ctx.flags & PUBKEY_FLAG_SM2))
+    {
+      rc = _gcry_ecc_sm2_sign (data, ec, sig_r, sig_s,
+                               ctx.flags, ctx.hash_algo);
+      if (!rc)
+        rc = sexp_build (r_sig, NULL,
+                         "(sig-val(sm2(r%M)(s%M)))", sig_r, sig_s);
+    }
   else
     {
-      rc = _gcry_ecc_ecdsa_sign (data, &sk, sig_r, sig_s,
+      rc = _gcry_ecc_ecdsa_sign (data, k, ec, sig_r, sig_s,
                                  ctx.flags, ctx.hash_algo);
       if (!rc)
         rc = sexp_build (r_sig, NULL,
                          "(sig-val(ecdsa(r%M)(s%M)))", sig_r, sig_s);
     }
 
-
  leave:
-  _gcry_mpi_release (sk.E.p);
-  _gcry_mpi_release (sk.E.a);
-  _gcry_mpi_release (sk.E.b);
-  _gcry_mpi_release (mpi_g);
-  point_free (&sk.E.G);
-  _gcry_mpi_release (sk.E.n);
-  _gcry_mpi_release (sk.E.h);
-  _gcry_mpi_release (mpi_q);
-  point_free (&sk.Q);
-  _gcry_mpi_release (sk.d);
   _gcry_mpi_release (sig_r);
   _gcry_mpi_release (sig_s);
-  xfree (curvename);
   _gcry_mpi_release (data);
-  sexp_release (l1);
+  _gcry_mpi_release (k);
+  _gcry_mpi_ec_free (ec);
   _gcry_pk_util_free_encoding_ctx (&ctx);
   if (DBG_CIPHER)
     log_debug ("ecc_sign      => %s\n", gpg_strerror (rc));
@@ -1028,19 +784,44 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
   gcry_err_code_t rc;
   struct pk_encoding_ctx ctx;
   gcry_sexp_t l1 = NULL;
-  char *curvename = NULL;
-  gcry_mpi_t mpi_g = NULL;
-  gcry_mpi_t mpi_q = NULL;
   gcry_mpi_t sig_r = NULL;
   gcry_mpi_t sig_s = NULL;
   gcry_mpi_t data = NULL;
-  ECC_public_key pk;
   int sigflags;
+  mpi_ec_t ec = NULL;
+  int flags = 0;
 
-  memset (&pk, 0, sizeof pk);
   _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
                                    ecc_get_nbits (s_keyparms));
 
+  /*
+   * Extract the key.
+   */
+  rc = _gcry_mpi_ec_internal_new (&ec, &flags, "ecc_verify",
+                                  s_keyparms, NULL);
+  if (rc)
+    goto leave;
+  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n || !ec->Q)
+    {
+      rc = GPG_ERR_NO_OBJ;
+      goto leave;
+    }
+
+  if (ec->model == MPI_EC_MONTGOMERY)
+    {
+      if (DBG_CIPHER)
+        log_debug ("ecc_verify: Can't use a Montgomery curve\n");
+      rc = GPG_ERR_INTERNAL;
+      goto leave;
+    }
+
+  ctx.flags |= flags;
+  if (ec->model == MPI_EC_EDWARDS && ec->dialect == ECC_DIALECT_SAFECURVE)
+    ctx.flags |= PUBKEY_FLAG_EDDSA;
+  /* Clear hash algo for EdDSA.  */
+  if ((ctx.flags & PUBKEY_FLAG_EDDSA))
+    ctx.hash_algo = GCRY_MD_NONE;
+
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
   if (rc)
@@ -1048,6 +829,15 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
   if (DBG_CIPHER)
     log_mpidump ("ecc_verify data", data);
 
+  /* Hash algo is determined by curve in EdDSA.  Fill it if not specified.  */
+  if ((ctx.flags & PUBKEY_FLAG_EDDSA) && !ctx.hash_algo)
+    {
+      if (ec->dialect == ECC_DIALECT_ED25519)
+        ctx.hash_algo = GCRY_MD_SHA512;
+      else if (ec->dialect == ECC_DIALECT_SAFECURVE)
+        ctx.hash_algo = GCRY_MD_SHAKE256;
+    }
+
   /*
    * Extract the signature value.
    */
@@ -1069,152 +859,32 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
       goto leave;
     }
 
-
-  /*
-   * Extract the key.
-   */
-  if ((ctx.flags & PUBKEY_FLAG_PARAM))
-    rc = sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?h?/q",
-                             &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n,
-                             &pk.E.h, &mpi_q, NULL);
-  else
-    rc = sexp_extract_param (s_keyparms, NULL, "/q",
-                             &mpi_q, NULL);
-  if (rc)
-    goto leave;
-  if (mpi_g)
-    {
-      point_init (&pk.E.G);
-      rc = _gcry_ecc_os2ec (&pk.E.G, mpi_g);
-      if (rc)
-        goto leave;
-    }
-  /* Add missing parameters using the optional curve parameter.  */
-  sexp_release (l1);
-  l1 = sexp_find_token (s_keyparms, "curve", 5);
-  if (l1)
-    {
-      curvename = sexp_nth_string (l1, 1);
-      if (curvename)
-        {
-          rc = _gcry_ecc_fill_in_curve (0, curvename, &pk.E, NULL);
-          if (rc)
-            goto leave;
-        }
-    }
-  /* Guess required fields if a curve parameter has not been given.
-     FIXME: This is a crude hacks.  We need to fix that.  */
-  if (!curvename)
-    {
-      pk.E.model = ((sigflags & PUBKEY_FLAG_EDDSA)
-                    ? MPI_EC_EDWARDS
-                    : MPI_EC_WEIERSTRASS);
-      pk.E.dialect = ((sigflags & PUBKEY_FLAG_EDDSA)
-                      ? ECC_DIALECT_ED25519
-                      : ECC_DIALECT_STANDARD);
-      if (!pk.E.h)
-       pk.E.h = mpi_const (MPI_C_ONE);
-    }
-
-  if (DBG_CIPHER)
-    {
-      log_debug ("ecc_verify info: %s/%s%s\n",
-                 _gcry_ecc_model2str (pk.E.model),
-                 _gcry_ecc_dialect2str (pk.E.dialect),
-                 (sigflags & PUBKEY_FLAG_EDDSA)? "+EdDSA":"");
-      if (pk.E.name)
-        log_debug  ("ecc_verify name: %s\n", pk.E.name);
-      log_printmpi ("ecc_verify    p", pk.E.p);
-      log_printmpi ("ecc_verify    a", pk.E.a);
-      log_printmpi ("ecc_verify    b", pk.E.b);
-      log_printpnt ("ecc_verify  g",   &pk.E.G, NULL);
-      log_printmpi ("ecc_verify    n", pk.E.n);
-      log_printmpi ("ecc_verify    h", pk.E.h);
-      log_printmpi ("ecc_verify    q", mpi_q);
-    }
-  if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !pk.E.h || !mpi_q)
-    {
-      rc = GPG_ERR_NO_OBJ;
-      goto leave;
-    }
-
-
   /*
    * Verify the signature.
    */
   if ((sigflags & PUBKEY_FLAG_EDDSA))
     {
-      rc = _gcry_ecc_eddsa_verify (data, &pk, sig_r, sig_s,
-                                   ctx.hash_algo, mpi_q);
+      rc = _gcry_ecc_eddsa_verify (data, ec, sig_r, sig_s, &ctx);
     }
   else if ((sigflags & PUBKEY_FLAG_GOST))
     {
-      point_init (&pk.Q);
-      rc = _gcry_ecc_os2ec (&pk.Q, mpi_q);
-      if (rc)
-        goto leave;
-
-      rc = _gcry_ecc_gost_verify (data, &pk, sig_r, sig_s);
+      rc = _gcry_ecc_gost_verify (data, ec, sig_r, sig_s);
+    }
+  else if ((sigflags & PUBKEY_FLAG_SM2))
+    {
+      rc = _gcry_ecc_sm2_verify (data, ec, sig_r, sig_s);
     }
   else
     {
-      point_init (&pk.Q);
-      if (pk.E.dialect == ECC_DIALECT_ED25519)
-        {
-          mpi_ec_t ec;
-
-          /* Fixme: Factor the curve context setup out of eddsa_verify
-             and ecdsa_verify. So that we don't do it twice.  */
-          ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0,
-                                            pk.E.p, pk.E.a, pk.E.b);
-
-          rc = _gcry_ecc_eddsa_decodepoint (mpi_q, ec, &pk.Q, NULL, NULL);
-          _gcry_mpi_ec_free (ec);
-        }
-      else
-        {
-          rc = _gcry_ecc_os2ec (&pk.Q, mpi_q);
-        }
-      if (rc)
-        goto leave;
-
-      if (mpi_is_opaque (data))
-        {
-          const void *abuf;
-          unsigned int abits, qbits;
-          gcry_mpi_t a;
-
-          qbits = mpi_get_nbits (pk.E.n);
-
-          abuf = mpi_get_opaque (data, &abits);
-          rc = _gcry_mpi_scan (&a, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL);
-          if (!rc)
-            {
-              if (abits > qbits)
-                mpi_rshift (a, a, abits - qbits);
-
-              rc = _gcry_ecc_ecdsa_verify (a, &pk, sig_r, sig_s);
-              _gcry_mpi_release (a);
-            }
-        }
-      else
-        rc = _gcry_ecc_ecdsa_verify (data, &pk, sig_r, sig_s);
+      rc = _gcry_ecc_ecdsa_verify (data, ec, sig_r, sig_s,
+                                   ctx.flags, ctx.hash_algo);
     }
 
  leave:
-  _gcry_mpi_release (pk.E.p);
-  _gcry_mpi_release (pk.E.a);
-  _gcry_mpi_release (pk.E.b);
-  _gcry_mpi_release (mpi_g);
-  point_free (&pk.E.G);
-  _gcry_mpi_release (pk.E.n);
-  _gcry_mpi_release (pk.E.h);
-  _gcry_mpi_release (mpi_q);
-  point_free (&pk.Q);
   _gcry_mpi_release (data);
   _gcry_mpi_release (sig_r);
   _gcry_mpi_release (sig_s);
-  xfree (curvename);
+  _gcry_mpi_ec_free (ec);
   sexp_release (l1);
   _gcry_pk_util_free_encoding_ctx (&ctx);
   if (DBG_CIPHER)
@@ -1257,81 +927,39 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   unsigned int nbits;
   gcry_err_code_t rc;
   struct pk_encoding_ctx ctx;
-  gcry_sexp_t l1 = NULL;
-  char *curvename = NULL;
-  gcry_mpi_t mpi_g = NULL;
-  gcry_mpi_t mpi_q = NULL;
   gcry_mpi_t mpi_s = NULL;
   gcry_mpi_t mpi_e = NULL;
   gcry_mpi_t data = NULL;
-  ECC_public_key pk;
   mpi_ec_t ec = NULL;
   int flags = 0;
+  int no_error_on_infinity;
 
-  memset (&pk, 0, sizeof pk);
   _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
                                    (nbits = ecc_get_nbits (keyparms)));
 
-  /* Look for flags. */
-  l1 = sexp_find_token (keyparms, "flags", 0);
-  if (l1)
-    {
-      rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
-      if (rc)
-        goto leave;
-    }
-  sexp_release (l1);
-  l1 = NULL;
-
   /*
-   * Extract the data.
+   * Extract the key.
    */
-  rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
+  rc = _gcry_mpi_ec_internal_new (&ec, &flags, "ecc_encrypt", keyparms, NULL);
   if (rc)
     goto leave;
-  if (mpi_is_opaque (data))
+
+  if (ec->dialect == ECC_DIALECT_SAFECURVE)
     {
-      rc = GPG_ERR_INV_DATA;
-      goto leave;
+      ctx.flags |= PUBKEY_FLAG_RAW_FLAG;
+      no_error_on_infinity = 1;
     }
+  else if ((flags & PUBKEY_FLAG_DJB_TWEAK))
+    no_error_on_infinity = 1;
+  else
+    no_error_on_infinity = 0;
 
   /*
-   * Extract the key.
+   * Extract the data.
    */
-  rc = sexp_extract_param (keyparms, NULL,
-                           (flags & PUBKEY_FLAG_DJB_TWEAK)?
-                           "-p?a?b?g?n?h?/q" : "-p?a?b?g?n?h?+q",
-                           &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, &pk.E.h,
-                           &mpi_q, NULL);
+  rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
   if (rc)
     goto leave;
-  if (mpi_g)
-    {
-      point_init (&pk.E.G);
-      rc = _gcry_ecc_os2ec (&pk.E.G, mpi_g);
-      if (rc)
-        goto leave;
-    }
-  /* Add missing parameters using the optional curve parameter.  */
-  l1 = sexp_find_token (keyparms, "curve", 5);
-  if (l1)
-    {
-      curvename = sexp_nth_string (l1, 1);
-      if (curvename)
-        {
-          rc = _gcry_ecc_fill_in_curve (0, curvename, &pk.E, NULL);
-          if (rc)
-            goto leave;
-        }
-    }
-  /* Guess required fields if a curve parameter has not been given.  */
-  if (!curvename)
-    {
-      pk.E.model = MPI_EC_WEIERSTRASS;
-      pk.E.dialect = ECC_DIALECT_STANDARD;
-      if (!pk.E.h)
-       pk.E.h = mpi_const (MPI_C_ONE);
-    }
 
   /*
    * Tweak the scalar bits by cofactor and number of bits of the field.
@@ -1341,48 +969,24 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     {
       int i;
 
-      for (i = 0; i < mpi_get_nbits (pk.E.h) - 1; i++)
+      for (i = 0; (ec->h & (1 << i)) == 0; i++)
         mpi_clear_bit (data, i);
-      mpi_set_highbit (data, mpi_get_nbits (pk.E.p) - 1);
+      mpi_set_highbit (data, ec->nbits - 1);
     }
   if (DBG_CIPHER)
     log_mpidump ("ecc_encrypt data", data);
 
-  if (DBG_CIPHER)
-    {
-      log_debug ("ecc_encrypt info: %s/%s\n",
-                 _gcry_ecc_model2str (pk.E.model),
-                 _gcry_ecc_dialect2str (pk.E.dialect));
-      if (pk.E.name)
-        log_debug  ("ecc_encrypt name: %s\n", pk.E.name);
-      log_printmpi ("ecc_encrypt    p", pk.E.p);
-      log_printmpi ("ecc_encrypt    a", pk.E.a);
-      log_printmpi ("ecc_encrypt    b", pk.E.b);
-      log_printpnt ("ecc_encrypt  g",   &pk.E.G, NULL);
-      log_printmpi ("ecc_encrypt    n", pk.E.n);
-      log_printmpi ("ecc_encrypt    h", pk.E.h);
-      log_printmpi ("ecc_encrypt    q", mpi_q);
-    }
-  if (!pk.E.p || !pk.E.a || !pk.E.b || !pk.E.G.x || !pk.E.n || !pk.E.h || !mpi_q)
+  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n || !ec->Q)
     {
       rc = GPG_ERR_NO_OBJ;
       goto leave;
     }
 
-  /* Compute the encrypted value.  */
-  ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, flags,
-                                    pk.E.p, pk.E.a, pk.E.b);
-
-  /* Convert the public key.  */
-  if (mpi_q)
+  if ((ctx.flags & PUBKEY_FLAG_SM2))
     {
-      point_init (&pk.Q);
-      if (ec->model == MPI_EC_MONTGOMERY)
-        rc = _gcry_ecc_mont_decodepoint (mpi_q, ec, &pk.Q);
-      else
-        rc = _gcry_ecc_os2ec (&pk.Q, mpi_q);
-      if (rc)
-        goto leave;
+      /* All encryption will be done, return it.  */
+      rc = _gcry_ecc_sm2_encrypt (r_ciph, data, ec);
+      goto leave;
     }
 
   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
@@ -1402,7 +1006,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     point_init (&R);
 
     /* R = kQ  <=>  R = kdG  */
-    _gcry_mpi_ec_mul_point (&R, data, &pk.Q, ec);
+    _gcry_mpi_ec_mul_point (&R, data, ec->Q, ec);
 
     if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
       {
@@ -1416,30 +1020,27 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
          * imported public key which might not follow the key
          * generation procedure.
          */
-        if (!(flags & PUBKEY_FLAG_DJB_TWEAK))
+        if (!no_error_on_infinity)
           { /* It's not for X25519, then, the input data was simply wrong.  */
             rc = GPG_ERR_INV_DATA;
             goto leave_main;
           }
       }
     if (y)
-      mpi_s = _gcry_ecc_ec2os (x, y, pk.E.p);
+      mpi_s = _gcry_ecc_ec2os (x, y, ec->p);
     else
       {
-        rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL);
-        if (!rawmpi)
-          rc = gpg_err_code_from_syserror ();
-        else
-          {
-            rawmpi[0] = 0x40;
-            rawmpilen++;
-            mpi_s = mpi_new (0);
-            mpi_set_opaque (mpi_s, rawmpi, rawmpilen*8);
-          }
+        rc = _gcry_ecc_mont_encodepoint (x, nbits,
+                                         ec->dialect != ECC_DIALECT_SAFECURVE,
+                                         &rawmpi, &rawmpilen);
+        if (rc)
+          goto leave_main;
+        mpi_s = mpi_new (0);
+        mpi_set_opaque (mpi_s, rawmpi, rawmpilen*8);
       }
 
     /* R = kG */
-    _gcry_mpi_ec_mul_point (&R, data, &pk.E.G, ec);
+    _gcry_mpi_ec_mul_point (&R, data, ec->G, ec);
 
     if (_gcry_mpi_ec_get_affine (x, y, &R, ec))
       {
@@ -1447,16 +1048,14 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
         goto leave_main;
       }
     if (y)
-      mpi_e = _gcry_ecc_ec2os (x, y, pk.E.p);
+      mpi_e = _gcry_ecc_ec2os (x, y, ec->p);
     else
       {
-        rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1, &rawmpilen, NULL);
-        if (!rawmpi)
-          rc = gpg_err_code_from_syserror ();
-        else
+        rc = _gcry_ecc_mont_encodepoint (x, nbits,
+                                         ec->dialect != ECC_DIALECT_SAFECURVE,
+                                         &rawmpi, &rawmpilen);
+        if (!rc)
           {
-            rawmpi[0] = 0x40;
-            rawmpilen++;
             mpi_e = mpi_new (0);
             mpi_set_opaque (mpi_e, rawmpi, rawmpilen*8);
           }
@@ -1474,20 +1073,9 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     rc = sexp_build (r_ciph, NULL, "(enc-val(ecdh(s%m)(e%m)))", mpi_s, mpi_e);
 
  leave:
-  _gcry_mpi_release (pk.E.p);
-  _gcry_mpi_release (pk.E.a);
-  _gcry_mpi_release (pk.E.b);
-  _gcry_mpi_release (mpi_g);
-  point_free (&pk.E.G);
-  _gcry_mpi_release (pk.E.n);
-  _gcry_mpi_release (pk.E.h);
-  _gcry_mpi_release (mpi_q);
-  point_free (&pk.Q);
   _gcry_mpi_release (data);
   _gcry_mpi_release (mpi_s);
   _gcry_mpi_release (mpi_e);
-  xfree (curvename);
-  sexp_release (l1);
   _gcry_mpi_ec_free (ec);
   _gcry_pk_util_free_encoding_ctx (&ctx);
   if (DBG_CIPHER)
@@ -1511,111 +1099,57 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   struct pk_encoding_ctx ctx;
   gcry_sexp_t l1 = NULL;
   gcry_mpi_t data_e = NULL;
-  ECC_secret_key sk;
-  gcry_mpi_t mpi_g = NULL;
-  char *curvename = NULL;
   mpi_ec_t ec = NULL;
   mpi_point_struct kG;
   mpi_point_struct R;
   gcry_mpi_t r = NULL;
   int flags = 0;
+  int enable_specific_point_validation;
 
-  memset (&sk, 0, sizeof sk);
   point_init (&kG);
   point_init (&R);
 
   _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
                                    (nbits = ecc_get_nbits (keyparms)));
 
-  /* Look for flags. */
-  l1 = sexp_find_token (keyparms, "flags", 0);
-  if (l1)
-    {
-      rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
-      if (rc)
-        goto leave;
-    }
-  sexp_release (l1);
-  l1 = NULL;
-
   /*
-   * Extract the data.
+   * Extract the key.
    */
-  rc = _gcry_pk_util_preparse_encval (s_data, ecc_names, &l1, &ctx);
-  if (rc)
-    goto leave;
-  rc = sexp_extract_param (l1, NULL, "e", &data_e, NULL);
+  rc = _gcry_mpi_ec_internal_new (&ec, &flags, "ecc_decrypt", keyparms, NULL);
   if (rc)
     goto leave;
-  if (DBG_CIPHER)
-    log_printmpi ("ecc_decrypt  d_e", data_e);
-  if (mpi_is_opaque (data_e))
+
+  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n || !ec->d)
     {
-      rc = GPG_ERR_INV_DATA;
+      rc = GPG_ERR_NO_OBJ;
       goto leave;
     }
 
   /*
-   * Extract the key.
+   * Extract the data.
    */
-  rc = sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?h?+d",
-                           &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
-                           &sk.E.h, &sk.d, NULL);
+  rc = _gcry_pk_util_preparse_encval (s_data, ecc_names, &l1, &ctx);
   if (rc)
     goto leave;
-  if (mpi_g)
-    {
-      point_init (&sk.E.G);
-      rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
-      if (rc)
-        goto leave;
-    }
-  /* Add missing parameters using the optional curve parameter.  */
-  sexp_release (l1);
-  l1 = sexp_find_token (keyparms, "curve", 5);
-  if (l1)
+  if ((ctx.flags & PUBKEY_FLAG_SM2))
     {
-      curvename = sexp_nth_string (l1, 1);
-      if (curvename)
-        {
-          rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
-          if (rc)
-            goto leave;
-        }
-    }
-  /* Guess required fields if a curve parameter has not been given.  */
-  if (!curvename)
-    {
-      sk.E.model = MPI_EC_WEIERSTRASS;
-      sk.E.dialect = ECC_DIALECT_STANDARD;
-      if (!sk.E.h)
-       sk.E.h = mpi_const (MPI_C_ONE);
+      /* All decryption will be done, return it.  */
+      rc = _gcry_ecc_sm2_decrypt (r_plain, l1, ec);
+      goto leave;
     }
-  if (DBG_CIPHER)
-    {
-      log_debug ("ecc_decrypt info: %s/%s\n",
-                 _gcry_ecc_model2str (sk.E.model),
-                 _gcry_ecc_dialect2str (sk.E.dialect));
-      if (sk.E.name)
-        log_debug  ("ecc_decrypt name: %s\n", sk.E.name);
-      log_printmpi ("ecc_decrypt    p", sk.E.p);
-      log_printmpi ("ecc_decrypt    a", sk.E.a);
-      log_printmpi ("ecc_decrypt    b", sk.E.b);
-      log_printpnt ("ecc_decrypt  g",   &sk.E.G, NULL);
-      log_printmpi ("ecc_decrypt    n", sk.E.n);
-      log_printmpi ("ecc_decrypt    h", sk.E.h);
-      if (!fips_mode ())
-        log_printmpi ("ecc_decrypt    d", sk.d);
-    }
-  if (!sk.E.p || !sk.E.a || !sk.E.b || !sk.E.G.x || !sk.E.n || !sk.E.h || !sk.d)
+  else
     {
-      rc = GPG_ERR_NO_OBJ;
-      goto leave;
+      rc = sexp_extract_param (l1, NULL, "/e", &data_e, NULL);
+      if (rc)
+        goto leave;
+      if (DBG_CIPHER)
+        log_printmpi ("ecc_decrypt  d_e", data_e);
     }
 
-
-  ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, flags,
-                                    sk.E.p, sk.E.a, sk.E.b);
+  if (ec->dialect == ECC_DIALECT_SAFECURVE || (flags & PUBKEY_FLAG_DJB_TWEAK))
+    enable_specific_point_validation = 1;
+  else
+    enable_specific_point_validation = 0;
 
   /*
    * Compute the plaintext.
@@ -1623,14 +1157,14 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   if (ec->model == MPI_EC_MONTGOMERY)
     rc = _gcry_ecc_mont_decodepoint (data_e, ec, &kG);
   else
-    rc = _gcry_ecc_os2ec (&kG, data_e);
+    rc = _gcry_ecc_sec_decodepoint (data_e, ec, &kG);
   if (rc)
     goto leave;
 
   if (DBG_CIPHER)
     log_printpnt ("ecc_decrypt    kG", &kG, NULL);
 
-  if ((flags & PUBKEY_FLAG_DJB_TWEAK))
+  if (enable_specific_point_validation)
     {
       /* For X25519, by its definition, validation should not be done.  */
       /* (Instead, we do output check.)
@@ -1652,7 +1186,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     }
 
   /* R = dkG */
-  _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ec);
+  _gcry_mpi_ec_mul_point (&R, ec->d, &kG, ec);
 
   /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so:  */
   {
@@ -1678,7 +1212,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
          * For X25519 ECDH, comming here means that it might be
          * decrypted by anyone with the shared secret of 0 (the result
          * of this function could be always 0 by other scalar values,
-         * other than the private key of SK.D).
+         * other than the private key of D).
          *
          * So, it looks like an encrypted message but it can be
          * decrypted by anyone, or at least something wrong
@@ -1692,26 +1226,21 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
       }
 
     if (y)
-      r = _gcry_ecc_ec2os (x, y, sk.E.p);
+      r = _gcry_ecc_ec2os (x, y, ec->p);
     else
       {
+
         unsigned char *rawmpi;
         unsigned int rawmpilen;
 
-        rawmpi = _gcry_mpi_get_buffer_extra (x, nbits/8, -1,
-                                             &rawmpilen, NULL);
-        if (!rawmpi)
-          {
-            rc = gpg_err_code_from_syserror ();
-            goto leave;
-          }
-        else
-          {
-            rawmpi[0] = 0x40;
-            rawmpilen++;
-            r = mpi_new (0);
-            mpi_set_opaque (r, rawmpi, rawmpilen*8);
-          }
+        rc = _gcry_ecc_mont_encodepoint (x, nbits,
+                                         ec->dialect != ECC_DIALECT_SAFECURVE,
+                                         &rawmpi, &rawmpilen);
+        if (rc)
+          goto leave;
+
+        r = mpi_new (0);
+        mpi_set_opaque (r, rawmpi, rawmpilen*8);
       }
     if (!r)
       rc = gpg_err_code_from_syserror ();
@@ -1730,16 +1259,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   point_free (&R);
   point_free (&kG);
   _gcry_mpi_release (r);
-  _gcry_mpi_release (sk.E.p);
-  _gcry_mpi_release (sk.E.a);
-  _gcry_mpi_release (sk.E.b);
-  _gcry_mpi_release (mpi_g);
-  point_free (&sk.E.G);
-  _gcry_mpi_release (sk.E.n);
-  _gcry_mpi_release (sk.E.h);
-  _gcry_mpi_release (sk.d);
   _gcry_mpi_release (data_e);
-  xfree (curvename);
   sexp_release (l1);
   _gcry_mpi_ec_free (ec);
   _gcry_pk_util_free_encoding_ctx (&ctx);
@@ -1806,8 +1326,8 @@ ecc_get_nbits (gcry_sexp_t parms)
 static gpg_err_code_t
 compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
 {
-#define N_COMPONENTS 7
-  static const char names[N_COMPONENTS] = "pabgnhq";
+#define N_COMPONENTS 6
+  static const char names[N_COMPONENTS] = "pabgnq";
   gpg_err_code_t rc;
   gcry_sexp_t l1;
   gcry_mpi_t values[N_COMPONENTS];
@@ -1816,6 +1336,9 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
   int flags = 0;
   enum gcry_mpi_ec_models model = 0;
   enum ecc_dialects dialect = 0;
+  const unsigned char *raw;
+  unsigned int n;
+  int maybe_uncompress;
 
   /* Clear the values first.  */
   for (idx=0; idx < N_COMPONENTS; idx++)
@@ -1833,27 +1356,12 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
 
   /* Extract the parameters.  */
   if ((flags & PUBKEY_FLAG_PARAM))
-    {
-      if ((flags & PUBKEY_FLAG_DJB_TWEAK))
-        rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?h?/q",
-                                 &values[0], &values[1], &values[2],
-                                 &values[3], &values[4], &values[5],
-                                 &values[6], NULL);
-      else
-        rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?h?q",
-                                 &values[0], &values[1], &values[2],
-                                 &values[3], &values[4], &values[5],
-                                 &values[6], NULL);
-    }
+    rc = sexp_extract_param (keyparms, NULL, "p?a?b?g?n?/q",
+                             &values[0], &values[1], &values[2],
+                             &values[3], &values[4], &values[5],
+                             NULL);
   else
-    {
-      if ((flags & PUBKEY_FLAG_DJB_TWEAK))
-        rc = sexp_extract_param (keyparms, NULL, "/q",
-                                 &values[6], NULL);
-      else
-        rc = sexp_extract_param (keyparms, NULL, "q",
-                                 &values[6], NULL);
-    }
+    rc = sexp_extract_param (keyparms, NULL, "/q", &values[5], NULL);
   if (rc)
     goto leave;
 
@@ -1869,7 +1377,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
           rc = _gcry_ecc_update_curve_param (curvename,
                                              &model, &dialect,
                                              &values[0], &values[1], &values[2],
-                                             &values[3], &values[4], &values[5]);
+                                             &values[3], &values[4]);
           if (rc)
             goto leave;
         }
@@ -1885,8 +1393,6 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
       dialect = ((flags & PUBKEY_FLAG_EDDSA)
                  ? ECC_DIALECT_ED25519
                  : ECC_DIALECT_STANDARD);
-      if (!values[5])
-       values[5] = mpi_const (MPI_C_ONE);
     }
 
   /* Check that all parameters are known and normalize all MPIs (that
@@ -1906,50 +1412,155 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparms)
      the compressed version.  Because we don't support any non-eddsa
      compression, the only thing we need to do is to compress
      EdDSA.  */
-  if ((flags & PUBKEY_FLAG_DJB_TWEAK))
+  if ((flags & PUBKEY_FLAG_EDDSA) && dialect == ECC_DIALECT_ED25519)
     {
-      rc = _gcry_ecc_eddsa_ensure_compact (values[6], 256);
+      const unsigned int pbits = mpi_get_nbits (values[0]);
+
+      rc = _gcry_ecc_eddsa_ensure_compact (values[5], pbits);
       if (rc)
         goto leave;
+      maybe_uncompress = 0;
+    }
+  else if ((flags & PUBKEY_FLAG_DJB_TWEAK))
+    {
+      /* Remove the prefix 0x40 for keygrip computation.  */
+      raw = mpi_get_opaque (values[5], &n);
+      if (raw)
+        {
+          n = (n + 7)/8;
+
+          if (n > 1 && (n%2) && raw[0] == 0x40)
+            if (!_gcry_mpi_set_opaque_copy (values[5], raw + 1, (n - 1)*8))
+                rc = gpg_err_code_from_syserror ();
+        }
+      else
+        {
+          rc = GPG_ERR_INV_OBJ;
+          goto leave;
+        }
+      maybe_uncompress = 0;
     }
+  else
+    maybe_uncompress = 1;
 
   /* Hash them all.  */
   for (idx = 0; idx < N_COMPONENTS; idx++)
     {
       char buf[30];
-
-      if (idx == 5)
-        continue;               /* Skip cofactor. */
+      unsigned char *rawbuffer;
+      unsigned int rawlen;
 
       if (mpi_is_opaque (values[idx]))
         {
-          const unsigned char *raw;
-          unsigned int n;
-
-          raw = mpi_get_opaque (values[idx], &n);
-          n = (n + 7)/8;
-          snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], n);
-          _gcry_md_write (md, buf, strlen (buf));
-          _gcry_md_write (md, raw, n);
-          _gcry_md_write (md, ")", 1);
+          rawbuffer = NULL;
+          raw = mpi_get_opaque (values[idx], &rawlen);
+          rawlen = (rawlen + 7)/8;
         }
       else
         {
-          unsigned char *rawmpi;
-          unsigned int rawmpilen;
-
-          rawmpi = _gcry_mpi_get_buffer (values[idx], 0, &rawmpilen, NULL);
-          if (!rawmpi)
+          rawbuffer = _gcry_mpi_get_buffer (values[idx], 0, &rawlen, NULL);
+          if (!rawbuffer)
             {
               rc = gpg_err_code_from_syserror ();
               goto leave;
             }
-          snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawmpilen);
-          _gcry_md_write (md, buf, strlen (buf));
-          _gcry_md_write (md, rawmpi, rawmpilen);
-          _gcry_md_write (md, ")", 1);
-          xfree (rawmpi);
+          raw = rawbuffer;
         }
+
+      if (maybe_uncompress && idx == 5 && rawlen > 1
+          && (*raw == 0x02 || *raw == 0x03))
+        {
+          /* This is a compressed Q - uncompress.  */
+          mpi_ec_t ec = NULL;
+          gcry_mpi_t x, y;
+          gcry_mpi_t x3;
+          gcry_mpi_t t;
+          gcry_mpi_t p1_4;
+          int y_bit = (*raw == 0x03);
+
+          /* We need to get the curve parameters as MPIs so that we
+           * can do computations.  We have them in VALUES but it is
+           * possible that the caller provided them as opaque MPIs. */
+          rc = _gcry_mpi_ec_internal_new (&ec, &flags, "ecc_keygrip",
+                                          keyparms, NULL);
+          if (rc)
+            goto leave;
+          if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n)
+            {
+              rc = GPG_ERR_NO_OBJ;
+              _gcry_mpi_ec_free (ec);
+              goto leave;
+            }
+
+          if (!mpi_test_bit (ec->p, 1))
+            {
+              /* No support for point compression for this curve.  */
+              rc = GPG_ERR_NOT_IMPLEMENTED;
+              _gcry_mpi_ec_free (ec);
+              xfree (rawbuffer);
+              goto leave;
+            }
+
+          raw++;
+          rawlen--;
+          rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG, raw, rawlen, NULL);
+          if (rc)
+            {
+              _gcry_mpi_ec_free (ec);
+              xfree (rawbuffer);
+              goto leave;
+            }
+
+          /*
+           * Recover Y.  The Weierstrass curve: y^2 = x^3 + a*x + b
+           */
+
+          x3 = mpi_new (0);
+          t = mpi_new (0);
+          p1_4 = mpi_new (0);
+          y = mpi_new (0);
+
+          /* Compute right hand side.  */
+          mpi_powm (x3, x, mpi_const (MPI_C_THREE), ec->p);
+          mpi_mul (t, ec->a, x);
+          mpi_mod (t, t, ec->p);
+          mpi_add (t, t, ec->b);
+          mpi_mod (t, t, ec->p);
+          mpi_add (t, t, x3);
+          mpi_mod (t, t, ec->p);
+
+          /*
+           * When p mod 4 = 3, modular square root of A can be computed by
+           * A^((p+1)/4) mod p
+           */
+
+          /* Compute (p+1)/4 into p1_4 */
+          mpi_rshift (p1_4, ec->p, 2);
+          _gcry_mpi_add_ui (p1_4, p1_4, 1);
+
+          mpi_powm (y, t, p1_4, ec->p);
+
+          if (y_bit != mpi_test_bit (y, 0))
+            mpi_sub (y, ec->p, y);
+
+          mpi_free (p1_4);
+          mpi_free (t);
+          mpi_free (x3);
+
+          xfree (rawbuffer);
+          rawbuffer = _gcry_ecc_ec2os_buf (x, y, ec->p, &rawlen);
+          raw = rawbuffer;
+
+          mpi_free (x);
+          mpi_free (y);
+          _gcry_mpi_ec_free (ec);
+        }
+
+      snprintf (buf, sizeof buf, "(1:%c%u:", names[idx], rawlen);
+      _gcry_md_write (md, buf, strlen (buf));
+      _gcry_md_write (md, raw, rawlen);
+      _gcry_md_write (md, ")", 1);
+      xfree (rawbuffer);
     }
 
  leave:
@@ -1978,7 +1589,7 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
   gcry_mpi_t mpi_G = NULL;
   gcry_mpi_t mpi_Q = NULL;
 
-  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n || !ec->h)
+  if (!ec->p || !ec->a || !ec->b || !ec->G || !ec->n)
     return GPG_ERR_BAD_CRYPT_CTX;
 
   if (mode == GCRY_PK_GET_SECKEY && !ec->d)
@@ -1986,7 +1597,7 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
 
   /* Compute the public point if it is missing.  */
   if (!ec->Q && ec->d)
-    ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
+    ec->Q = _gcry_ecc_compute_public (NULL, ec);
 
   /* Encode G and Q.  */
   mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec);
@@ -2013,6 +1624,18 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
       mpi_Q = mpi_set_opaque (NULL, encpk, encpklen*8);
       encpk = NULL;
     }
+  else if (ec->model == MPI_EC_MONTGOMERY)
+    {
+      unsigned char *encpk;
+      unsigned int encpklen;
+
+      rc = _gcry_ecc_mont_encodepoint (ec->Q->x, ec->nbits,
+                                       ec->dialect != ECC_DIALECT_SAFECURVE,
+                                       &encpk, &encpklen);
+      if (rc)
+        goto leave;
+      mpi_Q = mpi_set_opaque (NULL, encpk, encpklen*8);
+    }
   else
     {
       mpi_Q = _gcry_mpi_ec_ec2os (ec->Q, ec);
@@ -2030,14 +1653,14 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
     {
       /* Let's return a private key. */
       rc = sexp_build (r_sexp, NULL,
-                       "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)(d%m)))",
+                       "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%u)(q%m)(d%m)))",
                        ec->p, ec->a, ec->b, mpi_G, ec->n, ec->h, mpi_Q, ec->d);
     }
   else if (ec->Q)
     {
       /* Let's return a public key.  */
       rc = sexp_build (r_sexp, NULL,
-                       "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)(q%m)))",
+                       "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%u)(q%m)))",
                        ec->p, ec->a, ec->b, mpi_G, ec->n, ec->h, mpi_Q);
     }
   else
@@ -2060,9 +1683,9 @@ selftest_sign (gcry_sexp_t pkey, gcry_sexp_t skey)
 {
   /* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */
   static const char sample_data[] =
-    "(data (flags rfc6979)"
-    " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
-    /**/           "62113d8a62add1bf#))";
+    "(data (flags rfc6979 prehash)"
+    " (hash-algo sha256)"
+    " (value 6:sample))";
   static const char sample_data_bad[] =
     "(data (flags rfc6979)"
     " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915"
@@ -2241,7 +1864,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecc =
     GCRY_PK_ECC, { 0, 1 },
     (GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR),
     "ECC", ecc_names,
-    "pabgnhq", "pabgnhqd", "sw", "rs", "pabgnhq",
+    "pabgnhq", "pabgnhqd", "se", "rs", "pabgnhq",
     ecc_generate,
     ecc_check_secret_key,
     ecc_encrypt_raw,
index 4eb52d6..eead450 100644 (file)
@@ -66,7 +66,7 @@ static const char *elg_names[] =
 
 
 static int test_keys (ELG_secret_key *sk, unsigned int nbits, int nodie);
-static gcry_mpi_t gen_k (gcry_mpi_t p, int small_k);
+static gcry_mpi_t gen_k (gcry_mpi_t p);
 static gcry_err_code_t generate (ELG_secret_key *sk, unsigned nbits,
                                  gcry_mpi_t **factors);
 static int  check_secret_key (ELG_secret_key *sk);
@@ -189,11 +189,10 @@ test_keys ( ELG_secret_key *sk, unsigned int nbits, int nodie )
 
 /****************
  * Generate a random secret exponent k from prime p, so that k is
- * relatively prime to p-1.  With SMALL_K set, k will be selected for
- * better encryption performance - this must never be used signing!
+ * relatively prime to p-1.
  */
 static gcry_mpi_t
-gen_k( gcry_mpi_t p, int small_k )
+gen_k( gcry_mpi_t p )
 {
   gcry_mpi_t k = mpi_alloc_secure( 0 );
   gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(p) );
@@ -202,18 +201,7 @@ gen_k( gcry_mpi_t p, int small_k )
   unsigned int nbits, nbytes;
   char *rndbuf = NULL;
 
-  if (small_k)
-    {
-      /* Using a k much lesser than p is sufficient for encryption and
-       * it greatly improves the encryption performance.  We use
-       * Wiener's table and add a large safety margin. */
-      nbits = wiener_map( orig_nbits ) * 3 / 2;
-      if( nbits >= orig_nbits )
-        BUG();
-    }
-  else
-    nbits = orig_nbits;
-
+  nbits = orig_nbits;
 
   nbytes = (nbits+7)/8;
   if( DBG_CIPHER )
@@ -492,7 +480,7 @@ do_encrypt(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey )
    * error code.
    */
 
-  k = gen_k( pkey->p, 1 );
+  k = gen_k( pkey->p );
   mpi_powm (a, pkey->g, k, pkey->p);
 
   /* b = (y^k * input) mod p
@@ -522,8 +510,9 @@ do_encrypt(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_public_key *pkey )
 static void
 decrypt (gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey )
 {
-  gcry_mpi_t t1, t2, r;
+  gcry_mpi_t t1, t2, r, r1, h;
   unsigned int nbits = mpi_get_nbits (skey->p);
+  gcry_mpi_t x_blind;
 
   mpi_normalize (a);
   mpi_normalize (b);
@@ -534,20 +523,33 @@ decrypt (gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey )
 
   t2 = mpi_snew (nbits);
   r  = mpi_new (nbits);
+  r1 = mpi_new (nbits);
+  h  = mpi_new (nbits);
+  x_blind = mpi_snew (nbits);
 
   /* We need a random number of about the prime size.  The random
      number merely needs to be unpredictable; thus we use level 0.  */
   _gcry_mpi_randomize (r, nbits, GCRY_WEAK_RANDOM);
 
+  /* Also, exponent blinding: x_blind = x + (p-1)*r1 */
+  _gcry_mpi_randomize (r1, nbits, GCRY_WEAK_RANDOM);
+  mpi_set_highbit (r1, nbits - 1);
+  mpi_sub_ui (h, skey->p, 1);
+  mpi_mul (x_blind, h, r1);
+  mpi_add (x_blind, skey->x, x_blind);
+
   /* t1 = r^x mod p */
-  mpi_powm (t1, r, skey->x, skey->p);
+  mpi_powm (t1, r, x_blind, skey->p);
   /* t2 = (a * r)^-x mod p */
   mpi_mulm (t2, a, r, skey->p);
-  mpi_powm (t2, t2, skey->x, skey->p);
+  mpi_powm (t2, t2, x_blind, skey->p);
   mpi_invm (t2, t2, skey->p);
   /* t1 = (t1 * t2) mod p*/
   mpi_mulm (t1, t1, t2, skey->p);
 
+  mpi_free (x_blind);
+  mpi_free (h);
+  mpi_free (r1);
   mpi_free (r);
   mpi_free (t2);
 
@@ -594,7 +596,7 @@ sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey )
     *
     */
     mpi_sub_ui(p_1, p_1, 1);
-    k = gen_k( skey->p, 0 /* no small K ! */ );
+    k = gen_k( skey->p );
     mpi_powm( a, skey->g, k, skey->p );
     mpi_mul(t, skey->x, a );
     mpi_subm(t, input, t, p_1 );
index 7aa5444..5d5ed7d 100644 (file)
@@ -26,9 +26,11 @@ struct gost_sbox
 {
   const char *name;
   const char *oid;
+  unsigned int keymeshing;
   unsigned char sbox[16*8];
 } gost_sboxes[] = {
-  { "test_3411", "1.2.643.2.2.30.0", {
+  { "test_3411", "1.2.643.2.2.30.0", 0,
+    {
       0x4, 0xE, 0x5, 0x7, 0x6, 0x4, 0xD, 0x1,
       0xA, 0xB, 0x8, 0xD, 0xC, 0xB, 0xB, 0xF,
       0x9, 0x4, 0x1, 0xA, 0x7, 0xA, 0x4, 0xD,
@@ -50,7 +52,8 @@ struct gost_sbox
       0x3, 0x9, 0xB, 0x3, 0x2, 0xE, 0xC, 0xC,
     }
   },
-  { "CryptoPro_3411", "1.2.643.2.2.30.1", {
+  { "CryptoPro_3411", "1.2.643.2.2.30.1", 0,
+     {
       0xA, 0x5, 0x7, 0x4, 0x7, 0x7, 0xD, 0x1,
       0x4, 0xF, 0xF, 0xA, 0x6, 0x6, 0xE, 0x3,
       0x5, 0x4, 0xC, 0x7, 0x4, 0x2, 0x4, 0xA,
@@ -72,7 +75,8 @@ struct gost_sbox
       0xF, 0x8, 0xD, 0x3, 0x5, 0x3, 0xB, 0xC,
     }
   },
-  { "Test_89", "1.2.643.2.2.31.0", {
+  { "Test_89", "1.2.643.2.2.31.0", 0,
+    {
       0x4, 0xC, 0xD, 0xE, 0x3, 0x8, 0x9, 0xC,
       0x2, 0x9, 0x8, 0x9, 0xE, 0xF, 0xB, 0x6,
       0xF, 0xF, 0xE, 0xB, 0x5, 0x6, 0xC, 0x5,
@@ -94,7 +98,8 @@ struct gost_sbox
       0x6, 0x5, 0xB, 0x8, 0x4, 0x4, 0xD, 0x8,
     }
   },
-  { "CryptoPro_A", "1.2.643.2.2.31.1", {
+  { "CryptoPro_A", "1.2.643.2.2.31.1", 1,
+    {
       0x9, 0x3, 0xE, 0xE, 0xB, 0x3, 0x1, 0xB,
       0x6, 0x7, 0x4, 0x7, 0x5, 0xA, 0xD, 0xA,
       0x3, 0xE, 0x6, 0xA, 0x1, 0xD, 0x2, 0xF,
@@ -116,7 +121,8 @@ struct gost_sbox
       0x5, 0x1, 0x9, 0x6, 0x6, 0x6, 0xE, 0x4,
     }
   },
-  { "CryptoPro_B", "1.2.643.2.2.31.2", {
+  { "CryptoPro_B", "1.2.643.2.2.31.2", 1,
+    {
       0x8, 0x0, 0xE, 0x7, 0x2, 0x8, 0x5, 0x0,
       0x4, 0x1, 0xC, 0x5, 0x7, 0x3, 0x2, 0x4,
       0xB, 0x2, 0x0, 0x0, 0xC, 0x2, 0xA, 0xB,
@@ -138,7 +144,8 @@ struct gost_sbox
       0xF, 0xE, 0x4, 0x8, 0x3, 0x5, 0xE, 0xC,
     }
   },
-  { "CryptoPro_C", "1.2.643.2.2.31.3", {
+  { "CryptoPro_C", "1.2.643.2.2.31.3", 1,
+    {
       0x1, 0x0, 0x8, 0x3, 0x8, 0xC, 0xA, 0x7,
       0xB, 0x1, 0x2, 0x6, 0xD, 0x9, 0x9, 0x4,
       0xC, 0x7, 0x5, 0x0, 0xB, 0xB, 0x6, 0x0,
@@ -160,7 +167,8 @@ struct gost_sbox
       0x3, 0x3, 0xB, 0x4, 0x7, 0xD, 0x7, 0x8,
     }
   },
-  { "CryptoPro_D", "1.2.643.2.2.31.4", {
+  { "CryptoPro_D", "1.2.643.2.2.31.4", 1,
+    {
       0xF, 0xB, 0x1, 0x1, 0x0, 0x8, 0x3, 0x1,
       0xC, 0x6, 0xC, 0x5, 0xC, 0x0, 0x0, 0xA,
       0x2, 0x3, 0xB, 0xE, 0x8, 0xF, 0x6, 0x6,
@@ -182,7 +190,8 @@ struct gost_sbox
       0x3, 0x1, 0x2, 0x8, 0x1, 0x6, 0x7, 0xE,
     }
   },
-  { "TC26_Z", "1.2.643.7.1.2.5.1.1", {
+  { "TC26_Z", "1.2.643.7.1.2.5.1.1", 1,
+    {
       0xc, 0x6, 0xb, 0xc, 0x7, 0x5, 0x8, 0x1,
       0x4, 0x8, 0x3, 0x8, 0xf, 0xd, 0xe, 0x7,
       0x6, 0x2, 0x5, 0x2, 0x5, 0xf, 0x2, 0xe,
@@ -242,14 +251,14 @@ int main(int argc, char **argv)
       fprintf (f, "\n  };\n\n");
     }
 
-  fprintf (f, "static struct\n{\n  const char *oid;\n  const u32 *sbox;\n} gost_oid_map[] = {\n");
+  fprintf (f, "static struct\n{\n  const char *oid;\n  const u32 *sbox;\n  const int keymeshing;\n} gost_oid_map[] = {\n");
 
   for (s = 0; s < DIM(gost_sboxes); s++)
     {
-      fprintf (f, "  { \"%s\", sbox_%s },\n", gost_sboxes[s].oid, gost_sboxes[s].name );
+      fprintf (f, "  { \"%s\", sbox_%s, %d },\n", gost_sboxes[s].oid, gost_sboxes[s].name, gost_sboxes[s].keymeshing );
     }
 
-  fprintf(f, "  { NULL, NULL }\n};\n");
+  fprintf(f, "  { NULL, NULL, 0 }\n};\n");
 
   fclose (f);
 
index 025119c..53a4050 100644 (file)
 typedef struct {
   u32 key[8];
   const u32 *sbox;
+  unsigned int mesh_counter;
+  unsigned int mesh_limit;
 } GOST28147_context;
 
 /* This is a simple interface that will be used by GOST R 34.11-94 */
-unsigned int _gcry_gost_enc_data (GOST28147_context *c, const u32 *key,
+unsigned int _gcry_gost_enc_data (const u32 *key,
     u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro);
 
 #endif
index 4ff80b4..f094d5b 100644 (file)
  * - OFB-like mode with additional transformation on keystream
  *   RFC 5830 names this 'counter encryption' mode
  *   Original GOST text uses the term 'gammirovanie'
- * - MAC mode
+ * - MAC mode ('imitovstavka')
  *
  * This implementation handles ECB and CFB modes via usual libgcrypt handling.
- * OFB-like and MAC modes are unsupported.
+ * OFB-like modes are unsupported.
  */
 
 #include <config.h>
 #include "types.h"
 #include "g10lib.h"
 #include "cipher.h"
+#include "mac-internal.h"
 #include "bufhelp.h"
+#include "cipher-internal.h"
 
 #include "gost.h"
 #include "gost-sb.h"
 
+static void
+gost_do_set_sbox (GOST28147_context *ctx, unsigned int index)
+{
+  ctx->sbox = gost_oid_map[index].sbox;
+  ctx->mesh_limit = gost_oid_map[index].keymeshing ? 1024 : 0;
+}
+
 static gcry_err_code_t
-gost_setkey (void *c, const byte *key, unsigned keylen)
+gost_setkey (void *c, const byte *key, unsigned keylen,
+             cipher_bulk_ops_t *bulk_ops)
 {
   int i;
   GOST28147_context *ctx = c;
 
+  (void)bulk_ops;
+
   if (keylen != 256 / 8)
     return GPG_ERR_INV_KEYLEN;
 
   if (!ctx->sbox)
-    ctx->sbox = sbox_test_3411;
+    gost_do_set_sbox (ctx, 0);
 
   for (i = 0; i < 8; i++)
     {
       ctx->key[i] = buf_get_le32(&key[4*i]);
     }
+
+  ctx->mesh_counter = 0;
+
   return GPG_ERR_NO_ERROR;
 }
 
-static u32
-gost_val (GOST28147_context *ctx, u32 cm1, int subkey)
+static inline u32
+gost_val (u32 subkey, u32 cm1, const u32 *sbox)
 {
-  cm1 += ctx->key[subkey];
-  cm1 = ctx->sbox[0*256 + ((cm1 >>  0) & 0xff)] |
-        ctx->sbox[1*256 + ((cm1 >>  8) & 0xff)] |
-        ctx->sbox[2*256 + ((cm1 >> 16) & 0xff)] |
-        ctx->sbox[3*256 + ((cm1 >> 24) & 0xff)];
+  cm1 += subkey;
+  cm1 = sbox[0*256 + ((cm1 >>  0) & 0xff)] |
+        sbox[1*256 + ((cm1 >>  8) & 0xff)] |
+        sbox[2*256 + ((cm1 >> 16) & 0xff)] |
+        sbox[3*256 + ((cm1 >> 24) & 0xff)];
   return cm1;
 }
 
 static unsigned int
-_gost_encrypt_data (void *c, u32 *o1, u32 *o2, u32 n1, u32 n2)
+_gost_encrypt_data (const u32 *sbox, const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2)
 {
-  GOST28147_context *ctx = c;
-
-  n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
-  n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
-  n2 ^= gost_val (ctx, n1, 4); n1 ^= gost_val (ctx, n2, 5);
-  n2 ^= gost_val (ctx, n1, 6); n1 ^= gost_val (ctx, n2, 7);
-
-  n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
-  n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
-  n2 ^= gost_val (ctx, n1, 4); n1 ^= gost_val (ctx, n2, 5);
-  n2 ^= gost_val (ctx, n1, 6); n1 ^= gost_val (ctx, n2, 7);
-
-  n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
-  n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
-  n2 ^= gost_val (ctx, n1, 4); n1 ^= gost_val (ctx, n2, 5);
-  n2 ^= gost_val (ctx, n1, 6); n1 ^= gost_val (ctx, n2, 7);
-
-  n2 ^= gost_val (ctx, n1, 7); n1 ^= gost_val (ctx, n2, 6);
-  n2 ^= gost_val (ctx, n1, 5); n1 ^= gost_val (ctx, n2, 4);
-  n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
-  n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
+  n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox);
+  n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox);
+  n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox);
+  n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox);
+
+  n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox);
+  n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox);
+  n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox);
+  n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox);
+
+  n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox);
+  n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox);
+  n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox);
+  n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox);
+
+  n2 ^= gost_val (key[7], n1, sbox); n1 ^= gost_val (key[6], n2, sbox);
+  n2 ^= gost_val (key[5], n1, sbox); n1 ^= gost_val (key[4], n2, sbox);
+  n2 ^= gost_val (key[3], n1, sbox); n1 ^= gost_val (key[2], n2, sbox);
+  n2 ^= gost_val (key[1], n1, sbox); n1 ^= gost_val (key[0], n2, sbox);
 
   *o1 = n2;
   *o2 = n1;
@@ -111,7 +124,7 @@ gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
   n1 = buf_get_le32 (inbuf);
   n2 = buf_get_le32 (inbuf+4);
 
-  burn = _gost_encrypt_data(ctx, &n1, &n2, n1, n2);
+  burn = _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2);
 
   buf_put_le32 (outbuf+0, n1);
   buf_put_le32 (outbuf+4, n2);
@@ -119,15 +132,15 @@ gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
   return /* burn_stack */ burn + 6*sizeof(void*) /* func call */;
 }
 
-unsigned int _gcry_gost_enc_data (GOST28147_context *c, const u32 *key,
+unsigned int _gcry_gost_enc_data (const u32 *key,
     u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro)
 {
+  const u32 *sbox;
   if (cryptopro)
-    c->sbox = sbox_CryptoPro_3411;
+    sbox = sbox_CryptoPro_3411;
   else
-    c->sbox = sbox_test_3411;
-  memcpy (c->key, key, 8*4);
-  return _gost_encrypt_data (c, o1, o2, n1, n2) + 7 * sizeof(void *);
+    sbox = sbox_test_3411;
+  return _gost_encrypt_data (sbox, key, o1, o2, n1, n2) + 7 * sizeof(void *);
 }
 
 static unsigned int
@@ -135,29 +148,30 @@ gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf)
 {
   GOST28147_context *ctx = c;
   u32 n1, n2;
+  const u32 *sbox = ctx->sbox;
 
   n1 = buf_get_le32 (inbuf);
   n2 = buf_get_le32 (inbuf+4);
 
-  n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
-  n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
-  n2 ^= gost_val (ctx, n1, 4); n1 ^= gost_val (ctx, n2, 5);
-  n2 ^= gost_val (ctx, n1, 6); n1 ^= gost_val (ctx, n2, 7);
+  n2 ^= gost_val (ctx->key[0], n1, sbox); n1 ^= gost_val (ctx->key[1], n2, sbox);
+  n2 ^= gost_val (ctx->key[2], n1, sbox); n1 ^= gost_val (ctx->key[3], n2, sbox);
+  n2 ^= gost_val (ctx->key[4], n1, sbox); n1 ^= gost_val (ctx->key[5], n2, sbox);
+  n2 ^= gost_val (ctx->key[6], n1, sbox); n1 ^= gost_val (ctx->key[7], n2, sbox);
 
-  n2 ^= gost_val (ctx, n1, 7); n1 ^= gost_val (ctx, n2, 6);
-  n2 ^= gost_val (ctx, n1, 5); n1 ^= gost_val (ctx, n2, 4);
-  n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
-  n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
+  n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox);
+  n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox);
+  n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox);
+  n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox);
 
-  n2 ^= gost_val (ctx, n1, 7); n1 ^= gost_val (ctx, n2, 6);
-  n2 ^= gost_val (ctx, n1, 5); n1 ^= gost_val (ctx, n2, 4);
-  n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
-  n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
+  n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox);
+  n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox);
+  n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox);
+  n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox);
 
-  n2 ^= gost_val (ctx, n1, 7); n1 ^= gost_val (ctx, n2, 6);
-  n2 ^= gost_val (ctx, n1, 5); n1 ^= gost_val (ctx, n2, 4);
-  n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
-  n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
+  n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox);
+  n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox);
+  n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox);
+  n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox);
 
   buf_put_le32 (outbuf+0, n2);
   buf_put_le32 (outbuf+4, n1);
@@ -176,7 +190,7 @@ gost_set_sbox (GOST28147_context *ctx, const char *oid)
     {
       if (!strcmp(gost_oid_map[i].oid, oid))
         {
-          ctx->sbox = gost_oid_map[i].sbox;
+          gost_do_set_sbox (ctx, i);
           return 0;
         }
     }
@@ -205,8 +219,67 @@ gost_set_extra_info (void *c, int what, const void *buffer, size_t buflen)
   return ec;
 }
 
-static gcry_cipher_oid_spec_t oids_gost28147[] =
+static const byte CryptoProKeyMeshingKey[] = {
+    0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23,
+    0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
+    0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
+    0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
+};
+
+/* Implements key meshing algorithm by modifing ctx and returning new IV.
+   Thanks to Dmitry Belyavskiy. */
+static void
+cryptopro_key_meshing (GOST28147_context *ctx)
+{
+    unsigned char newkey[32];
+    unsigned int i;
+
+    /* "Decrypt" the static keymeshing key */
+    for (i = 0; i < 4; i++)
+      {
+       gost_decrypt_block (ctx, newkey + i*8, CryptoProKeyMeshingKey + i*8);
+      }
+
+    /* Set new key */
+    for (i = 0; i < 8; i++)
+      {
+       ctx->key[i] = buf_get_le32(&newkey[4*i]);
+      }
+
+    ctx->mesh_counter = 0;
+}
+
+static unsigned int
+gost_encrypt_block_mesh (void *c, byte *outbuf, const byte *inbuf)
+{
+  GOST28147_context *ctx = c;
+  u32 n1, n2;
+  unsigned int burn;
+
+  n1 = buf_get_le32 (inbuf);
+  n2 = buf_get_le32 (inbuf+4);
+
+  if (ctx->mesh_limit && (ctx->mesh_counter == ctx->mesh_limit))
+    {
+      cryptopro_key_meshing (ctx);
+      /* Yes, encrypt twice: once for KeyMeshing procedure per RFC 4357,
+       * once for block encryption */
+      _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2);
+    }
+
+  burn = _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2);
+
+  ctx->mesh_counter += 8;
+
+  buf_put_le32 (outbuf+0, n1);
+  buf_put_le32 (outbuf+4, n2);
+
+  return /* burn_stack */ burn + 6*sizeof(void*) /* func call */;
+}
+
+static const gcry_cipher_oid_spec_t oids_gost28147_mesh[] =
   {
+    { "1.2.643.2.2.21", GCRY_CIPHER_MODE_CFB },
     /* { "1.2.643.2.2.31.0", GCRY_CIPHER_MODE_CNTGOST }, */
     { "1.2.643.2.2.31.1", GCRY_CIPHER_MODE_CFB },
     { "1.2.643.2.2.31.2", GCRY_CIPHER_MODE_CFB },
@@ -218,10 +291,263 @@ static gcry_cipher_oid_spec_t oids_gost28147[] =
 gcry_cipher_spec_t _gcry_cipher_spec_gost28147 =
   {
     GCRY_CIPHER_GOST28147, {0, 0},
-    "GOST28147", NULL, oids_gost28147, 8, 256,
+    "GOST28147", NULL, NULL, 8, 256,
     sizeof (GOST28147_context),
     gost_setkey,
     gost_encrypt_block,
     gost_decrypt_block,
     NULL, NULL, NULL, gost_set_extra_info,
   };
+
+/* Meshing is used only for CFB, so no need to have separate
+ * gost_decrypt_block_mesh.
+ * Moreover key meshing is specified as encrypting the block (IV). Decrypting
+ * it afterwards would be meaningless. */
+gcry_cipher_spec_t _gcry_cipher_spec_gost28147_mesh =
+  {
+    GCRY_CIPHER_GOST28147_MESH, {0, 0},
+    "GOST28147_MESH", NULL, oids_gost28147_mesh, 8, 256,
+    sizeof (GOST28147_context),
+    gost_setkey,
+    gost_encrypt_block_mesh,
+    gost_decrypt_block,
+    NULL, NULL, NULL, gost_set_extra_info,
+  };
+
+static gcry_err_code_t
+gost_imit_open (gcry_mac_hd_t h)
+{
+  memset(&h->u.imit, 0, sizeof(h->u.imit));
+  return 0;
+}
+
+static void
+gost_imit_close (gcry_mac_hd_t h)
+{
+  (void) h;
+}
+
+static gcry_err_code_t
+gost_imit_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen)
+{
+  int i;
+
+  if (keylen != 256 / 8)
+    return GPG_ERR_INV_KEYLEN;
+
+  if (!h->u.imit.ctx.sbox)
+    h->u.imit.ctx.sbox = sbox_CryptoPro_A;
+
+  for (i = 0; i < 8; i++)
+    {
+      h->u.imit.ctx.key[i] = buf_get_le32(&key[4*i]);
+    }
+
+  return 0;
+}
+
+static gcry_err_code_t
+gost_imit_setiv (gcry_mac_hd_t h,
+                const unsigned char *iv,
+                size_t ivlen)
+{
+  if (ivlen != 8)
+    return GPG_ERR_INV_LENGTH;
+
+  h->u.imit.n1 = buf_get_le32 (iv + 0);
+  h->u.imit.n2 = buf_get_le32 (iv + 4);
+
+  return 0;
+}
+
+static gcry_err_code_t
+gost_imit_reset (gcry_mac_hd_t h)
+{
+  h->u.imit.n1 = h->u.imit.n2 = 0;
+  h->u.imit.unused = 0;
+  return 0;
+}
+
+static unsigned int
+_gost_imit_block (const u32 *sbox, const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2)
+{
+  n1 ^= *o1;
+  n2 ^= *o2;
+
+  n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox);
+  n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox);
+  n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox);
+  n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox);
+
+  n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox);
+  n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox);
+  n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox);
+  n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox);
+
+  *o1 = n1;
+  *o2 = n2;
+
+  return /* burn_stack */ 4*sizeof(void*) /* func call */ +
+                          3*sizeof(void*) /* stack */ +
+                          4*sizeof(void*) /* gost_val call */;
+}
+
+static inline unsigned int
+gost_imit_block (GOST28147_context *ctx, u32 *n1, u32 *n2, const unsigned char *buf)
+{
+  if (ctx->mesh_limit && (ctx->mesh_counter == ctx->mesh_limit))
+    cryptopro_key_meshing (ctx);
+
+  return _gost_imit_block (ctx->sbox, ctx->key,
+                          n1, n2,
+                          buf_get_le32 (buf+0),
+                          buf_get_le32 (buf+4));
+}
+
+static gcry_err_code_t
+gost_imit_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
+{
+  const int blocksize = 8;
+  unsigned int burn = 0;
+  if (!buflen || !buf)
+    return GPG_ERR_NO_ERROR;
+
+  if (h->u.imit.unused)
+    {
+      for (; buflen && h->u.imit.unused < blocksize; buflen --)
+        h->u.imit.lastiv[h->u.imit.unused++] = *buf++;
+
+      if (h->u.imit.unused < blocksize)
+        return GPG_ERR_NO_ERROR;
+
+      h->u.imit.count ++;
+      burn = gost_imit_block (&h->u.imit.ctx,
+                             &h->u.imit.n1, &h->u.imit.n2,
+                             h->u.imit.lastiv);
+
+      h->u.imit.unused = 0;
+    }
+
+  while (buflen >= blocksize)
+    {
+      h->u.imit.count ++;
+      burn = gost_imit_block (&h->u.imit.ctx,
+                             &h->u.imit.n1, &h->u.imit.n2,
+                             buf);
+      buf += blocksize;
+      buflen -= blocksize;
+    }
+
+  for (; buflen; buflen--)
+    h->u.imit.lastiv[h->u.imit.unused++] = *buf++;
+
+  _gcry_burn_stack (burn);
+
+  return GPG_ERR_NO_ERROR;
+}
+
+static void
+gost_imit_finish (gcry_mac_hd_t h)
+{
+  static const unsigned char zero[8] = {0};
+
+  /* Fill till full block */
+  if (h->u.imit.unused)
+    gost_imit_write(h, zero, 8 - h->u.imit.unused);
+
+  if (h->u.imit.count == 1)
+    gost_imit_write(h, zero, 8);
+}
+
+static gcry_err_code_t
+gost_imit_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen)
+{
+  unsigned int dlen = 8;
+  unsigned char digest[8];
+
+  gost_imit_finish (h);
+
+  buf_put_le32 (digest+0, h->u.imit.n1);
+  buf_put_le32 (digest+4, h->u.imit.n2);
+
+  if (*outlen <= dlen)
+    buf_cpy (outbuf, digest, *outlen);
+  else
+    {
+      buf_cpy (outbuf, digest, dlen);
+      *outlen = dlen;
+    }
+  return 0;
+}
+
+static gcry_err_code_t
+gost_imit_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
+{
+  unsigned char tbuf[8];
+
+  gost_imit_finish (h);
+
+  buf_put_le32 (tbuf+0, h->u.imit.n1);
+  buf_put_le32 (tbuf+4, h->u.imit.n2);
+
+  return buf_eq_const(tbuf, buf, buflen) ?
+             GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
+}
+
+static unsigned int
+gost_imit_get_maclen (int algo)
+{
+  (void) algo;
+  return 4; /* or 8 */
+}
+
+
+static unsigned int
+gost_imit_get_keylen (int algo)
+{
+  (void) algo;
+  return 256 / 8;
+}
+
+static gpg_err_code_t
+gost_imit_set_extra_info (gcry_mac_hd_t hd, int what, const void *buffer, size_t buflen)
+{
+  gpg_err_code_t ec = 0;
+
+  (void)buffer;
+  (void)buflen;
+
+  switch (what)
+    {
+    case GCRYCTL_SET_SBOX:
+      ec = gost_set_sbox (&hd->u.imit.ctx, buffer);
+      break;
+
+    default:
+      ec = GPG_ERR_INV_OP;
+      break;
+    }
+  return ec;
+}
+
+
+static gcry_mac_spec_ops_t gost_imit_ops = {
+  gost_imit_open,
+  gost_imit_close,
+  gost_imit_setkey,
+  gost_imit_setiv,
+  gost_imit_reset,
+  gost_imit_write,
+  gost_imit_read,
+  gost_imit_verify,
+  gost_imit_get_maclen,
+  gost_imit_get_keylen,
+  gost_imit_set_extra_info,
+  NULL
+};
+
+const gcry_mac_spec_t _gcry_mac_type_spec_gost28147_imit =
+  {
+    GCRY_MAC_GOST28147_IMIT, {0, 0}, "GOST28147_IMIT",
+    &gost_imit_ops
+  };
index a782427..93de83b 100644 (file)
@@ -35,7 +35,6 @@
 
 typedef struct {
   gcry_md_block_ctx_t bctx;
-  GOST28147_context hd;
   union {
     u32 h[8];
     byte result[32];
@@ -55,13 +54,12 @@ gost3411_init (void *context, unsigned int flags)
 
   (void)flags;
 
-  memset (&hd->hd, 0, sizeof(hd->hd));
   memset (hd->h, 0, 32);
   memset (hd->sigma, 0, 32);
 
   hd->bctx.nblocks = 0;
   hd->bctx.count = 0;
-  hd->bctx.blocksize = 32;
+  hd->bctx.blocksize_shift = _gcry_ctz(32);
   hd->bctx.bwrite = transform;
   hd->cryptopro = 0;
 }
@@ -83,17 +81,45 @@ do_p (u32 *p, u32 *u, u32 *v)
   for (k = 0; k < 8; k++)
     t[k] = u[k] ^ v[k];
 
-  for (k = 0; k < 4; k++)
-    {
-          p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
-                   ((t[2] >> (8*k)) & 0xff) << 8 |
-                   ((t[4] >> (8*k)) & 0xff) << 16 |
-                   ((t[6] >> (8*k)) & 0xff) << 24;
-          p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
-                   ((t[3] >> (8*k)) & 0xff) << 8 |
-                   ((t[5] >> (8*k)) & 0xff) << 16 |
-                   ((t[7] >> (8*k)) & 0xff) << 24;
-    }
+  k = 0;
+  p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
+           ((t[2] >> (8*k)) & 0xff) << 8 |
+           ((t[4] >> (8*k)) & 0xff) << 16 |
+           ((t[6] >> (8*k)) & 0xff) << 24;
+  p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
+           ((t[3] >> (8*k)) & 0xff) << 8 |
+           ((t[5] >> (8*k)) & 0xff) << 16 |
+           ((t[7] >> (8*k)) & 0xff) << 24;
+
+  k = 1;
+  p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
+           ((t[2] >> (8*k)) & 0xff) << 8 |
+           ((t[4] >> (8*k)) & 0xff) << 16 |
+           ((t[6] >> (8*k)) & 0xff) << 24;
+  p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
+           ((t[3] >> (8*k)) & 0xff) << 8 |
+           ((t[5] >> (8*k)) & 0xff) << 16 |
+           ((t[7] >> (8*k)) & 0xff) << 24;
+
+  k = 2;
+  p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
+           ((t[2] >> (8*k)) & 0xff) << 8 |
+           ((t[4] >> (8*k)) & 0xff) << 16 |
+           ((t[6] >> (8*k)) & 0xff) << 24;
+  p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
+           ((t[3] >> (8*k)) & 0xff) << 8 |
+           ((t[5] >> (8*k)) & 0xff) << 16 |
+           ((t[7] >> (8*k)) & 0xff) << 24;
+
+  k = 3;
+  p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
+           ((t[2] >> (8*k)) & 0xff) << 8 |
+           ((t[4] >> (8*k)) & 0xff) << 16 |
+           ((t[6] >> (8*k)) & 0xff) << 24;
+  p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
+           ((t[3] >> (8*k)) & 0xff) << 8 |
+           ((t[5] >> (8*k)) & 0xff) << 16 |
+           ((t[7] >> (8*k)) & 0xff) << 24;
 }
 
 static void
@@ -200,7 +226,7 @@ do_hash_step (GOSTR3411_CONTEXT *hd, u32 *h, u32 *m)
   for (i = 0; i < 4; i++) {
     do_p (k, u, v);
 
-    burn = _gcry_gost_enc_data (&hd->hd, k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro);
+    burn = _gcry_gost_enc_data (k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro);
 
     do_a (u);
     if (i == 1)
@@ -327,10 +353,10 @@ gost3411_read (void *context)
   return hd->result;
 }
 
-static unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */
+static const unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */
   { 0x2a, 0x85, 0x03, 0x02, 0x02, 0x03 };
 
-static gcry_md_oid_spec_t oid_spec_gostr3411[] =
+static const gcry_md_oid_spec_t oid_spec_gostr3411[] =
   {
     /* iso.member-body.ru.rans.cryptopro.3 (gostR3411-94-with-gostR3410-2001) */
     { "1.2.643.2.2.3" },
@@ -339,17 +365,19 @@ static gcry_md_oid_spec_t oid_spec_gostr3411[] =
     {NULL},
   };
 
-gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
+const 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,
     sizeof (GOSTR3411_CONTEXT)
   };
-gcry_md_spec_t _gcry_digest_spec_gost3411_cp =
+const 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,
     sizeof (GOSTR3411_CONTEXT)
   };
index a750d64..ed2d7ca 100644 (file)
@@ -26,6 +26,7 @@
 #endif
 
 #include "g10lib.h"
+#include "bufhelp.h"
 #include "hash-common.h"
 
 
@@ -121,8 +122,11 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen)
   const unsigned char *inbuf = inbuf_arg;
   gcry_md_block_ctx_t *hd = context;
   unsigned int stack_burn = 0;
-  const unsigned int blocksize = hd->blocksize;
+  unsigned int nburn;
+  const unsigned int blocksize_shift = hd->blocksize_shift;
+  const unsigned int blocksize = 1 << blocksize_shift;
   size_t inblocks;
+  size_t copylen;
 
   if (sizeof(hd->buf) < blocksize)
     BUG();
@@ -130,38 +134,60 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen)
   if (!hd->bwrite)
     return;
 
-  if (hd->count == blocksize)  /* Flush the buffer. */
+  if (hd->count > blocksize)
     {
-      stack_burn = hd->bwrite (hd, hd->buf, 1);
-      _gcry_burn_stack (stack_burn);
-      stack_burn = 0;
+      /* This happens only when gcry_md_write is called after final.
+       * Writing after final is used for mitigating timing attacks. */
       hd->count = 0;
-      if (!++hd->nblocks)
-        hd->nblocks_high++;
     }
-  if (!inbuf)
-    return;
 
-  if (hd->count)
+  while (hd->count)
     {
-      for (; inlen && hd->count < blocksize; inlen--)
-        hd->buf[hd->count++] = *inbuf++;
-      _gcry_md_block_write (hd, NULL, 0);
-      if (!inlen)
-        return;
+      if (hd->count == blocksize)  /* Flush the buffer. */
+       {
+         nburn = hd->bwrite (hd, hd->buf, 1);
+         stack_burn = nburn > stack_burn ? nburn : stack_burn;
+         hd->count = 0;
+         if (!++hd->nblocks)
+           hd->nblocks_high++;
+       }
+      else
+       {
+         copylen = inlen;
+         if (copylen > blocksize - hd->count)
+           copylen = blocksize - hd->count;
+
+         if (copylen == 0)
+           break;
+
+         buf_cpy (&hd->buf[hd->count], inbuf, copylen);
+         hd->count += copylen;
+         inbuf += copylen;
+         inlen -= copylen;
+       }
     }
 
+  if (inlen == 0)
+    return;
+
   if (inlen >= blocksize)
     {
-      inblocks = inlen / blocksize;
-      stack_burn = hd->bwrite (hd, inbuf, inblocks);
+      inblocks = inlen >> blocksize_shift;
+      nburn = hd->bwrite (hd, inbuf, inblocks);
+      stack_burn = nburn > stack_burn ? nburn : stack_burn;
       hd->count = 0;
       hd->nblocks_high += (hd->nblocks + inblocks < inblocks);
       hd->nblocks += inblocks;
-      inlen -= inblocks * blocksize;
-      inbuf += inblocks * blocksize;
+      inlen -= inblocks << blocksize_shift;
+      inbuf += inblocks << blocksize_shift;
     }
-  _gcry_burn_stack (stack_burn);
-  for (; inlen && hd->count < blocksize; inlen--)
-    hd->buf[hd->count++] = *inbuf++;
+
+  if (inlen)
+    {
+      buf_cpy (hd->buf, inbuf, inlen);
+      hd->count = inlen;
+    }
+
+  if (stack_burn > 0)
+    _gcry_burn_stack (stack_burn);
 }
index 23f81ed..561e77a 100644 (file)
@@ -42,13 +42,16 @@ typedef unsigned int (*_gcry_md_block_write_t) (void *c,
 # define MD_NBLOCKS_TYPE u32
 #endif
 
+/* SHA1 needs 2x64 bytes and SHA-512 needs 128 bytes. */
+#define MD_BLOCK_CTX_BUFFER_SIZE 128
+
 typedef struct gcry_md_block_ctx
 {
-    byte buf[MD_BLOCK_MAX_BLOCKSIZE];
+    byte buf[MD_BLOCK_CTX_BUFFER_SIZE];
     MD_NBLOCKS_TYPE nblocks;
     MD_NBLOCKS_TYPE nblocks_high;
     int count;
-    size_t blocksize;
+    unsigned int blocksize_shift;
     _gcry_md_block_write_t bwrite;
 } gcry_md_block_ctx_t;
 
diff --git a/cipher/hmac-tests.c b/cipher/hmac-tests.c
deleted file mode 100644 (file)
index 78d260a..0000000
+++ /dev/null
@@ -1,1160 +0,0 @@
-/* hmac-tests.c - HMAC selftests.
- * Copyright (C) 2008 Free Software Foundation, Inc.
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-/*
-   Although algorithm self-tests are usually implemented in the module
-   implementing the algorithm, the case for HMAC is different because
-   HMAC is implemented on a higher level using a special feature of the
-   gcry_md_ functions.  It would be possible to do this also in the
-   digest algorithm modules, but that would blow up the code too much
-   and spread the hmac tests over several modules.
-
-   Thus we implement all HMAC tests in this test module and provide a
-   function to run the tests.
-
-   To run all the Libgcrypt selftest in a verbose mode, use
-
-   $ tests/basic --selftest
-
-*/
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-#include "g10lib.h"
-#include "cipher.h"
-#include "hmac256.h"
-
-/* Check one HMAC with digest ALGO using the regualr HAMC
- * API. (DATA,DATALEN) is the data to be MACed, (KEY,KEYLEN) the key
- * and (EXPECT,EXPECTLEN) the expected result.  If TRUNC is set, the
- * EXPECTLEN may be less than the digest length.  Returns NULL on
- * success or a string describing the failure.  */
-static const char *
-check_one (int algo,
-           const void *data, size_t datalen,
-           const void *key, size_t keylen,
-           const void *expect, size_t expectlen, int trunc)
-{
-  gcry_md_hd_t hd;
-  const unsigned char *digest;
-
-/*   printf ("HMAC algo %d\n", algo); */
-  if (trunc)
-    {
-      if (_gcry_md_get_algo_dlen (algo) < expectlen)
-        return "invalid tests data";
-    }
-  else
-    {
-      if (_gcry_md_get_algo_dlen (algo) != expectlen)
-        return "invalid tests data";
-    }
-  if (_gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC))
-    return "gcry_md_open failed";
-  if (_gcry_md_setkey (hd, key, keylen))
-    {
-      _gcry_md_close (hd);
-      return "gcry_md_setkey failed";
-    }
-  _gcry_md_write (hd, data, datalen);
-  digest = _gcry_md_read (hd, algo);
-  if (!digest)
-    {
-      _gcry_md_close (hd);
-      return "gcry_md_read failed";
-    }
-  if (memcmp (digest, expect, expectlen))
-    {
-/*       int i; */
-
-/*       fputs ("        {", stdout); */
-/*       for (i=0; i < expectlen-1; i++) */
-/*         { */
-/*           if (i && !(i % 8)) */
-/*             fputs ("\n         ", stdout); */
-/*           printf (" 0x%02x,", digest[i]); */
-/*         } */
-/*       printf (" 0x%02x } },\n", digest[i]); */
-
-      _gcry_md_close (hd);
-      return "does not match";
-    }
-  _gcry_md_close (hd);
-  return NULL;
-}
-
-
-static gpg_err_code_t
-selftests_sha1 (int extended, selftest_report_func_t report)
-{
-  const char *what;
-  const char *errtxt;
-  unsigned char key[128];
-  int i, j;
-
-  what = "FIPS-198a, A.1";
-  for (i=0; i < 64; i++)
-    key[i] = i;
-  errtxt = check_one (GCRY_MD_SHA1,
-                      "Sample #1", 9,
-                      key, 64,
-                      "\x4f\x4c\xa3\xd5\xd6\x8b\xa7\xcc\x0a\x12"
-                      "\x08\xc9\xc6\x1e\x9c\x5d\xa0\x40\x3c\x0a", 20, 0);
-  if (errtxt)
-    goto failed;
-
-  if (extended)
-    {
-      what = "FIPS-198a, A.2";
-      for (i=0, j=0x30; i < 20; i++)
-        key[i] = j++;
-      errtxt = check_one (GCRY_MD_SHA1,
-                          "Sample #2", 9,
-                          key, 20,
-                          "\x09\x22\xd3\x40\x5f\xaa\x3d\x19\x4f\x82"
-                          "\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24", 20, 0);
-      if (errtxt)
-        goto failed;
-
-      what = "FIPS-198a, A.3";
-      for (i=0, j=0x50; i < 100; i++)
-        key[i] = j++;
-      errtxt = check_one (GCRY_MD_SHA1,
-                          "Sample #3", 9,
-                          key, 100,
-                          "\xbc\xf4\x1e\xab\x8b\xb2\xd8\x02\xf3\xd0"
-                          "\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", 20, 0);
-      if (errtxt)
-        goto failed;
-
-      what = "FIPS-198a, A.4";
-      for (i=0, j=0x70; i < 49; i++)
-        key[i] = j++;
-      errtxt = check_one (GCRY_MD_SHA1,
-                          "Sample #4", 9,
-                          key, 49,
-                          "\x9e\xa8\x86\xef\xe2\x68\xdb\xec\xce\x42"
-                          "\x0c\x75\x24\xdf\x32\xe0\x75\x1a\x2a\x26", 20, 0);
-      if (errtxt)
-        goto failed;
-    }
-
-  return 0; /* Succeeded. */
-
- failed:
-  if (report)
-    report ("hmac", GCRY_MD_SHA1, what, errtxt);
-  return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-
-static gpg_err_code_t
-selftests_sha224 (int extended, selftest_report_func_t report)
-{
-  static struct
-  {
-    const char * const desc;
-    const char * const data;
-    const char * const key;
-    const char expect[28];
-  } tv[] =
-    {
-      { "data-28 key-4",
-        "what do ya want for nothing?",
-        "Jefe",
-        { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf,
-          0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
-          0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00,
-          0x8f, 0xd0, 0x5e, 0x44 } },
-
-      { "data-9 key-20",
-        "Hi There",
-       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
-        "\x0b\x0b\x0b\x0b",
-        { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19,
-          0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
-          0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f,
-          0x53, 0x68, 0x4b, 0x22 } },
-
-      { "data-50 key-20",
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa",
-        { 0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6,
-          0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64,
-          0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1,
-          0xec, 0x83, 0x33, 0xea } },
-
-      { "data-50 key-26",
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd",
-       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
-        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
-        { 0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac,
-          0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c,
-          0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d,
-          0xe7, 0xaf, 0xec, 0x5a } },
-
-      { "data-54 key-131",
-        "Test Using Larger Than Block-Size Key - Hash Key First",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-        { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad,
-          0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
-          0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27,
-          0x3f, 0xa6, 0x87, 0x0e } },
-
-      { "data-152 key-131",
-        "This is a test using a larger than block-size key and a larger "
-        "than block-size data. The key needs to be hashed before being "
-        "used by the HMAC algorithm.",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-        { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02,
-          0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
-          0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9,
-          0xf6, 0xf5, 0x65, 0xd1 } },
-
-      { NULL }
-    };
-  const char *what;
-  const char *errtxt;
-  int tvidx;
-
-  for (tvidx=0; tv[tvidx].desc; tvidx++)
-    {
-      what = tv[tvidx].desc;
-      errtxt = check_one (GCRY_MD_SHA224,
-                          tv[tvidx].data, strlen (tv[tvidx].data),
-                          tv[tvidx].key, strlen (tv[tvidx].key),
-                          tv[tvidx].expect, DIM (tv[tvidx].expect), 0);
-      if (errtxt)
-        goto failed;
-      if (!extended)
-        break;
-    }
-
-  return 0; /* Succeeded. */
-
- failed:
-  if (report)
-    report ("hmac", GCRY_MD_SHA224, what, errtxt);
-  return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-static gpg_err_code_t
-selftests_sha256 (int extended, selftest_report_func_t report)
-{
-  static struct
-  {
-    const char * const desc;
-    const char * const data;
-    const char * const key;
-    const char expect[32];
-  } tv[] =
-    {
-      { "data-28 key-4",
-        "what do ya want for nothing?",
-        "Jefe",
-       { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
-          0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
-          0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
-          0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } },
-
-      { "data-9 key-20",
-        "Hi There",
-       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
-        "\x0b\x0b\x0b\x0b",
-        { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
-          0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
-          0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
-          0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } },
-
-      { "data-50 key-20",
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa",
-        { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
-          0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
-          0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
-          0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } },
-
-      { "data-50 key-26",
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd",
-       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
-        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
-       { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
-          0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
-          0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
-          0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } },
-
-      { "data-54 key-131",
-        "Test Using Larger Than Block-Size Key - Hash Key First",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-       { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
-          0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
-          0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
-          0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } },
-
-      { "data-152 key-131",
-        "This is a test using a larger than block-size key and a larger "
-        "than block-size data. The key needs to be hashed before being "
-        "used by the HMAC algorithm.",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-       { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
-          0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
-          0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
-          0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } },
-
-      { NULL }
-    };
-  const char *what;
-  const char *errtxt;
-  int tvidx;
-
-  for (tvidx=0; tv[tvidx].desc; tvidx++)
-    {
-      hmac256_context_t hmachd;
-      const unsigned char *digest;
-      size_t dlen;
-
-      what = tv[tvidx].desc;
-      errtxt = check_one (GCRY_MD_SHA256,
-                          tv[tvidx].data, strlen (tv[tvidx].data),
-                          tv[tvidx].key, strlen (tv[tvidx].key),
-                          tv[tvidx].expect, DIM (tv[tvidx].expect), 0);
-      if (errtxt)
-        goto failed;
-
-      hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key));
-      if (!hmachd)
-        {
-          errtxt = "_gcry_hmac256_new failed";
-          goto failed;
-        }
-      _gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data));
-      digest = _gcry_hmac256_finalize (hmachd, &dlen);
-      if (!digest)
-        {
-          errtxt = "_gcry_hmac256_finalize failed";
-          _gcry_hmac256_release (hmachd);
-          goto failed;
-        }
-      if (dlen != DIM (tv[tvidx].expect)
-          || memcmp (digest, tv[tvidx].expect, DIM (tv[tvidx].expect)))
-        {
-          errtxt = "does not match in second implementation";
-          _gcry_hmac256_release (hmachd);
-          goto failed;
-        }
-      _gcry_hmac256_release (hmachd);
-
-      if (!extended)
-        break;
-    }
-
-  return 0; /* Succeeded. */
-
- failed:
-  if (report)
-    report ("hmac", GCRY_MD_SHA256, what, errtxt);
-  return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-static gpg_err_code_t
-selftests_sha384 (int extended, selftest_report_func_t report)
-{
-  static struct
-  {
-    const char * const desc;
-    const char * const data;
-    const char * const key;
-    const char expect[48];
-  } tv[] =
-    {
-      { "data-28 key-4",
-        "what do ya want for nothing?",
-        "Jefe",
-        { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31,
-          0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
-          0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
-          0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
-          0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7,
-          0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 } },
-
-      { "data-9 key-20",
-        "Hi There",
-       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
-        "\x0b\x0b\x0b\x0b",
-        { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62,
-          0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
-          0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
-          0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
-          0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f,
-          0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 } },
-
-      { "data-50 key-20",
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa",
-        { 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a,
-          0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f,
-          0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb,
-          0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b,
-          0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9,
-          0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27 } },
-
-      { "data-50 key-26",
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd",
-       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
-        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
-        { 0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85,
-          0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7,
-          0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c,
-          0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e,
-          0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79,
-          0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb } },
-
-      { "data-54 key-131",
-        "Test Using Larger Than Block-Size Key - Hash Key First",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-        { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90,
-          0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
-          0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
-          0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
-          0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82,
-          0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 } },
-
-      { "data-152 key-131",
-        "This is a test using a larger than block-size key and a larger "
-        "than block-size data. The key needs to be hashed before being "
-        "used by the HMAC algorithm.",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-        { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d,
-          0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
-          0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
-          0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
-          0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d,
-          0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e } },
-
-      { NULL }
-    };
-  const char *what;
-  const char *errtxt;
-  int tvidx;
-
-  for (tvidx=0; tv[tvidx].desc; tvidx++)
-    {
-      what = tv[tvidx].desc;
-      errtxt = check_one (GCRY_MD_SHA384,
-                          tv[tvidx].data, strlen (tv[tvidx].data),
-                          tv[tvidx].key, strlen (tv[tvidx].key),
-                          tv[tvidx].expect, DIM (tv[tvidx].expect), 0);
-      if (errtxt)
-        goto failed;
-      if (!extended)
-        break;
-    }
-
-  return 0; /* Succeeded. */
-
- failed:
-  if (report)
-    report ("hmac", GCRY_MD_SHA384, what, errtxt);
-  return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-static gpg_err_code_t
-selftests_sha512 (int extended, selftest_report_func_t report)
-{
-  static struct
-  {
-    const char * const desc;
-    const char * const data;
-    const char * const key;
-    const char expect[64];
-  } tv[] =
-    {
-      { "data-28 key-4",
-        "what do ya want for nothing?",
-        "Jefe",
-        { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
-          0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
-          0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
-          0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
-          0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a,
-          0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
-          0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b,
-          0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 } },
-
-      { "data-9 key-20",
-        "Hi There",
-       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
-        "\x0b\x0b\x0b\x0b",
-        { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
-          0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
-          0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
-          0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
-          0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
-          0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
-          0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70,
-          0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 } },
-
-      { "data-50 key-20",
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa",
-        { 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84,
-          0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
-          0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
-          0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39,
-          0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8,
-          0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07,
-          0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26,
-          0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb } },
-
-      { "data-50 key-26",
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd",
-       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
-        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
-        { 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69,
-          0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7,
-          0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d,
-          0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb,
-          0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4,
-          0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63,
-          0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d,
-          0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd } },
-
-      { "data-54 key-131",
-        "Test Using Larger Than Block-Size Key - Hash Key First",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-        { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb,
-          0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
-          0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
-          0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
-          0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98,
-          0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
-          0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec,
-          0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 } },
-
-      { "data-152 key-131",
-        "This is a test using a larger than block-size key and a larger "
-        "than block-size data. The key needs to be hashed before being "
-        "used by the HMAC algorithm.",
-       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-        { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba,
-          0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
-          0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
-          0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
-          0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1,
-          0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
-          0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60,
-          0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 } },
-
-      { NULL }
-    };
-  const char *what;
-  const char *errtxt;
-  int tvidx;
-
-  for (tvidx=0; tv[tvidx].desc; tvidx++)
-    {
-      what = tv[tvidx].desc;
-      errtxt = check_one (GCRY_MD_SHA512,
-                          tv[tvidx].data, strlen (tv[tvidx].data),
-                          tv[tvidx].key, strlen (tv[tvidx].key),
-                          tv[tvidx].expect, DIM (tv[tvidx].expect), 0);
-      if (errtxt)
-        goto failed;
-      if (!extended)
-        break;
-    }
-
-  return 0; /* Succeeded. */
-
- failed:
-  if (report)
-    report ("hmac", GCRY_MD_SHA512, what, errtxt);
-  return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-
-/* Test for the SHA3 algorithms.  Vectors taken on 2017-07-18 from
- * http://www.wolfgang-ehrhardt.de/hmac-sha3-testvectors.html  */
-static gpg_err_code_t
-selftests_sha3 (int hashalgo, int extended, selftest_report_func_t report)
-{
-  static struct
-  {
-    const char * const desc;
-    const char * const data;
-    const char * const key;
-    const char expect_224[28];
-    const char expect_256[32];
-    const char expect_384[48];
-    const char expect_512[64];
-    unsigned char trunc;
-  } tv[] =
-    {
-      { "data-9 key-20", /* Test 1 */
-        "Hi There",
-       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
-        "\x0b\x0b\x0b\x0b",
-
-        { 0x3b, 0x16, 0x54, 0x6b, 0xbc, 0x7b, 0xe2, 0x70,
-          0x6a, 0x03, 0x1d, 0xca, 0xfd, 0x56, 0x37, 0x3d,
-          0x98, 0x84, 0x36, 0x76, 0x41, 0xd8, 0xc5, 0x9a,
-          0xf3, 0xc8, 0x60, 0xf7                          },
-        { 0xba, 0x85, 0x19, 0x23, 0x10, 0xdf, 0xfa, 0x96,
-          0xe2, 0xa3, 0xa4, 0x0e, 0x69, 0x77, 0x43, 0x51,
-          0x14, 0x0b, 0xb7, 0x18, 0x5e, 0x12, 0x02, 0xcd,
-          0xcc, 0x91, 0x75, 0x89, 0xf9, 0x5e, 0x16, 0xbb  },
-        { 0x68, 0xd2, 0xdc, 0xf7, 0xfd, 0x4d, 0xdd, 0x0a,
-          0x22, 0x40, 0xc8, 0xa4, 0x37, 0x30, 0x5f, 0x61,
-          0xfb, 0x73, 0x34, 0xcf, 0xb5, 0xd0, 0x22, 0x6e,
-          0x1b, 0xc2, 0x7d, 0xc1, 0x0a, 0x2e, 0x72, 0x3a,
-          0x20, 0xd3, 0x70, 0xb4, 0x77, 0x43, 0x13, 0x0e,
-          0x26, 0xac, 0x7e, 0x3d, 0x53, 0x28, 0x86, 0xbd  },
-        { 0xeb, 0x3f, 0xbd, 0x4b, 0x2e, 0xaa, 0xb8, 0xf5,
-          0xc5, 0x04, 0xbd, 0x3a, 0x41, 0x46, 0x5a, 0xac,
-          0xec, 0x15, 0x77, 0x0a, 0x7c, 0xab, 0xac, 0x53,
-          0x1e, 0x48, 0x2f, 0x86, 0x0b, 0x5e, 0xc7, 0xba,
-          0x47, 0xcc, 0xb2, 0xc6, 0xf2, 0xaf, 0xce, 0x8f,
-          0x88, 0xd2, 0x2b, 0x6d, 0xc6, 0x13, 0x80, 0xf2,
-          0x3a, 0x66, 0x8f, 0xd3, 0x88, 0x8b, 0xb8, 0x05,
-          0x37, 0xc0, 0xa0, 0xb8, 0x64, 0x07, 0x68, 0x9e  }
-      },
-
-      { "data-28 key-4",  /* Test 2  */
-        /* Test with a key shorter than the length of the HMAC output. */
-        "what do ya want for nothing?",
-        "Jefe",
-
-        { 0x7f, 0xdb, 0x8d, 0xd8, 0x8b, 0xd2, 0xf6, 0x0d,
-          0x1b, 0x79, 0x86, 0x34, 0xad, 0x38, 0x68, 0x11,
-          0xc2, 0xcf, 0xc8, 0x5b, 0xfa, 0xf5, 0xd5, 0x2b,
-          0xba, 0xce, 0x5e, 0x66                          },
-        { 0xc7, 0xd4, 0x07, 0x2e, 0x78, 0x88, 0x77, 0xae,
-          0x35, 0x96, 0xbb, 0xb0, 0xda, 0x73, 0xb8, 0x87,
-          0xc9, 0x17, 0x1f, 0x93, 0x09, 0x5b, 0x29, 0x4a,
-          0xe8, 0x57, 0xfb, 0xe2, 0x64, 0x5e, 0x1b, 0xa5  },
-        { 0xf1, 0x10, 0x1f, 0x8c, 0xbf, 0x97, 0x66, 0xfd,
-          0x67, 0x64, 0xd2, 0xed, 0x61, 0x90, 0x3f, 0x21,
-          0xca, 0x9b, 0x18, 0xf5, 0x7c, 0xf3, 0xe1, 0xa2,
-          0x3c, 0xa1, 0x35, 0x08, 0xa9, 0x32, 0x43, 0xce,
-          0x48, 0xc0, 0x45, 0xdc, 0x00, 0x7f, 0x26, 0xa2,
-          0x1b, 0x3f, 0x5e, 0x0e, 0x9d, 0xf4, 0xc2, 0x0a  },
-        { 0x5a, 0x4b, 0xfe, 0xab, 0x61, 0x66, 0x42, 0x7c,
-          0x7a, 0x36, 0x47, 0xb7, 0x47, 0x29, 0x2b, 0x83,
-          0x84, 0x53, 0x7c, 0xdb, 0x89, 0xaf, 0xb3, 0xbf,
-          0x56, 0x65, 0xe4, 0xc5, 0xe7, 0x09, 0x35, 0x0b,
-          0x28, 0x7b, 0xae, 0xc9, 0x21, 0xfd, 0x7c, 0xa0,
-          0xee, 0x7a, 0x0c, 0x31, 0xd0, 0x22, 0xa9, 0x5e,
-          0x1f, 0xc9, 0x2b, 0xa9, 0xd7, 0x7d, 0xf8, 0x83,
-          0x96, 0x02, 0x75, 0xbe, 0xb4, 0xe6, 0x20, 0x24  }
-      },
-
-      { "data-50 key-20",  /* Test 3 */
-        /* Test with a combined length of key and data that is larger
-         * than 64 bytes (= block-size of SHA-224 and SHA-256).  */
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
-        "\xdd\xdd",
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa",
-
-        { 0x67, 0x6c, 0xfc, 0x7d, 0x16, 0x15, 0x36, 0x38,
-          0x78, 0x03, 0x90, 0x69, 0x2b, 0xe1, 0x42, 0xd2,
-          0xdf, 0x7c, 0xe9, 0x24, 0xb9, 0x09, 0xc0, 0xc0,
-          0x8d, 0xbf, 0xdc, 0x1a  },
-        { 0x84, 0xec, 0x79, 0x12, 0x4a, 0x27, 0x10, 0x78,
-          0x65, 0xce, 0xdd, 0x8b, 0xd8, 0x2d, 0xa9, 0x96,
-          0x5e, 0x5e, 0xd8, 0xc3, 0x7b, 0x0a, 0xc9, 0x80,
-          0x05, 0xa7, 0xf3, 0x9e, 0xd5, 0x8a, 0x42, 0x07  },
-        { 0x27, 0x5c, 0xd0, 0xe6, 0x61, 0xbb, 0x8b, 0x15,
-          0x1c, 0x64, 0xd2, 0x88, 0xf1, 0xf7, 0x82, 0xfb,
-          0x91, 0xa8, 0xab, 0xd5, 0x68, 0x58, 0xd7, 0x2b,
-          0xab, 0xb2, 0xd4, 0x76, 0xf0, 0x45, 0x83, 0x73,
-          0xb4, 0x1b, 0x6a, 0xb5, 0xbf, 0x17, 0x4b, 0xec,
-          0x42, 0x2e, 0x53, 0xfc, 0x31, 0x35, 0xac, 0x6e  },
-        { 0x30, 0x9e, 0x99, 0xf9, 0xec, 0x07, 0x5e, 0xc6,
-          0xc6, 0xd4, 0x75, 0xed, 0xa1, 0x18, 0x06, 0x87,
-          0xfc, 0xf1, 0x53, 0x11, 0x95, 0x80, 0x2a, 0x99,
-          0xb5, 0x67, 0x74, 0x49, 0xa8, 0x62, 0x51, 0x82,
-          0x85, 0x1c, 0xb3, 0x32, 0xaf, 0xb6, 0xa8, 0x9c,
-          0x41, 0x13, 0x25, 0xfb, 0xcb, 0xcd, 0x42, 0xaf,
-          0xcb, 0x7b, 0x6e, 0x5a, 0xab, 0x7e, 0xa4, 0x2c,
-          0x66, 0x0f, 0x97, 0xfd, 0x85, 0x84, 0xbf, 0x03  }
-      },
-
-      { "data-50 key-25",  /* Test 4 */
-        /* Test with a combined length of key and data that is larger
-         * than 64 bytes (= block-size of SHA-224 and SHA-256).  */
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
-        "\xcd\xcd",
-        "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
-        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
-
-        { 0xa9, 0xd7, 0x68, 0x5a, 0x19, 0xc4, 0xe0, 0xdb,
-          0xd9, 0xdf, 0x25, 0x56, 0xcc, 0x8a, 0x7d, 0x2a,
-          0x77, 0x33, 0xb6, 0x76, 0x25, 0xce, 0x59, 0x4c,
-          0x78, 0x27, 0x0e, 0xeb   },
-        { 0x57, 0x36, 0x6a, 0x45, 0xe2, 0x30, 0x53, 0x21,
-          0xa4, 0xbc, 0x5a, 0xa5, 0xfe, 0x2e, 0xf8, 0xa9,
-          0x21, 0xf6, 0xaf, 0x82, 0x73, 0xd7, 0xfe, 0x7b,
-          0xe6, 0xcf, 0xed, 0xb3, 0xf0, 0xae, 0xa6, 0xd7  },
-        { 0x3a, 0x5d, 0x7a, 0x87, 0x97, 0x02, 0xc0, 0x86,
-          0xbc, 0x96, 0xd1, 0xdd, 0x8a, 0xa1, 0x5d, 0x9c,
-          0x46, 0x44, 0x6b, 0x95, 0x52, 0x13, 0x11, 0xc6,
-          0x06, 0xfd, 0xc4, 0xe3, 0x08, 0xf4, 0xb9, 0x84,
-          0xda, 0x2d, 0x0f, 0x94, 0x49, 0xb3, 0xba, 0x84,
-          0x25, 0xec, 0x7f, 0xb8, 0xc3, 0x1b, 0xc1, 0x36  },
-        { 0xb2, 0x7e, 0xab, 0x1d, 0x6e, 0x8d, 0x87, 0x46,
-          0x1c, 0x29, 0xf7, 0xf5, 0x73, 0x9d, 0xd5, 0x8e,
-          0x98, 0xaa, 0x35, 0xf8, 0xe8, 0x23, 0xad, 0x38,
-          0xc5, 0x49, 0x2a, 0x20, 0x88, 0xfa, 0x02, 0x81,
-          0x99, 0x3b, 0xbf, 0xff, 0x9a, 0x0e, 0x9c, 0x6b,
-          0xf1, 0x21, 0xae, 0x9e, 0xc9, 0xbb, 0x09, 0xd8,
-          0x4a, 0x5e, 0xba, 0xc8, 0x17, 0x18, 0x2e, 0xa9,
-          0x74, 0x67, 0x3f, 0xb1, 0x33, 0xca, 0x0d, 0x1d  }
-      },
-
-      { "data-20 key-20 trunc",  /* Test 5 */
-        /* Test with a truncation of output to 128 bits.  */
-        "Test With Truncation",
-        "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
-        "\x0c\x0c\x0c\x0c",
-
-        { 0x49, 0xfd, 0xd3, 0xab, 0xd0, 0x05, 0xeb, 0xb8,
-          0xae, 0x63, 0xfe, 0xa9, 0x46, 0xd1, 0x88, 0x3c  },
-        { 0x6e, 0x02, 0xc6, 0x45, 0x37, 0xfb, 0x11, 0x80,
-          0x57, 0xab, 0xb7, 0xfb, 0x66, 0xa2, 0x3b, 0x3c  },
-        { 0x47, 0xc5, 0x1a, 0xce, 0x1f, 0xfa, 0xcf, 0xfd,
-          0x74, 0x94, 0x72, 0x46, 0x82, 0x61, 0x57, 0x83  },
-        { 0x0f, 0xa7, 0x47, 0x59, 0x48, 0xf4, 0x3f, 0x48,
-          0xca, 0x05, 0x16, 0x67, 0x1e, 0x18, 0x97, 0x8c  },
-        16
-      },
-
-      { "data-54 key-131",  /* Test 6 */
-        /* Test with a key larger than 128 bytes (= block-size of
-         * SHA-384 and SHA-512).  */
-        "Test Using Larger Than Block-Size Key - Hash Key First",
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-
-        { 0xb4, 0xa1, 0xf0, 0x4c, 0x00, 0x28, 0x7a, 0x9b,
-          0x7f, 0x60, 0x75, 0xb3, 0x13, 0xd2, 0x79, 0xb8,
-          0x33, 0xbc, 0x8f, 0x75, 0x12, 0x43, 0x52, 0xd0,
-          0x5f, 0xb9, 0x99, 0x5f  },
-        { 0xed, 0x73, 0xa3, 0x74, 0xb9, 0x6c, 0x00, 0x52,
-          0x35, 0xf9, 0x48, 0x03, 0x2f, 0x09, 0x67, 0x4a,
-          0x58, 0xc0, 0xce, 0x55, 0x5c, 0xfc, 0x1f, 0x22,
-          0x3b, 0x02, 0x35, 0x65, 0x60, 0x31, 0x2c, 0x3b  },
-        { 0x0f, 0xc1, 0x95, 0x13, 0xbf, 0x6b, 0xd8, 0x78,
-          0x03, 0x70, 0x16, 0x70, 0x6a, 0x0e, 0x57, 0xbc,
-          0x52, 0x81, 0x39, 0x83, 0x6b, 0x9a, 0x42, 0xc3,
-          0xd4, 0x19, 0xe4, 0x98, 0xe0, 0xe1, 0xfb, 0x96,
-          0x16, 0xfd, 0x66, 0x91, 0x38, 0xd3, 0x3a, 0x11,
-          0x05, 0xe0, 0x7c, 0x72, 0xb6, 0x95, 0x3b, 0xcc  },
-        { 0x00, 0xf7, 0x51, 0xa9, 0xe5, 0x06, 0x95, 0xb0,
-          0x90, 0xed, 0x69, 0x11, 0xa4, 0xb6, 0x55, 0x24,
-          0x95, 0x1c, 0xdc, 0x15, 0xa7, 0x3a, 0x5d, 0x58,
-          0xbb, 0x55, 0x21, 0x5e, 0xa2, 0xcd, 0x83, 0x9a,
-          0xc7, 0x9d, 0x2b, 0x44, 0xa3, 0x9b, 0xaf, 0xab,
-          0x27, 0xe8, 0x3f, 0xde, 0x9e, 0x11, 0xf6, 0x34,
-          0x0b, 0x11, 0xd9, 0x91, 0xb1, 0xb9, 0x1b, 0xf2,
-          0xee, 0xe7, 0xfc, 0x87, 0x24, 0x26, 0xc3, 0xa4  }
-      },
-
-      { "data-54 key-147",  /* Test 6a */
-        /* Test with a key larger than 144 bytes (= block-size of
-         * SHA3-224).  */
-        "Test Using Larger Than Block-Size Key - Hash Key First",
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-
-        { 0xb9, 0x6d, 0x73, 0x0c, 0x14, 0x8c, 0x2d, 0xaa,
-          0xd8, 0x64, 0x9d, 0x83, 0xde, 0xfa, 0xa3, 0x71,
-          0x97, 0x38, 0xd3, 0x47, 0x75, 0x39, 0x7b, 0x75,
-          0x71, 0xc3, 0x85, 0x15  },
-        { 0xa6, 0x07, 0x2f, 0x86, 0xde, 0x52, 0xb3, 0x8b,
-          0xb3, 0x49, 0xfe, 0x84, 0xcd, 0x6d, 0x97, 0xfb,
-          0x6a, 0x37, 0xc4, 0xc0, 0xf6, 0x2a, 0xae, 0x93,
-          0x98, 0x11, 0x93, 0xa7, 0x22, 0x9d, 0x34, 0x67  },
-        { 0x71, 0x3d, 0xff, 0x03, 0x02, 0xc8, 0x50, 0x86,
-          0xec, 0x5a, 0xd0, 0x76, 0x8d, 0xd6, 0x5a, 0x13,
-          0xdd, 0xd7, 0x90, 0x68, 0xd8, 0xd4, 0xc6, 0x21,
-          0x2b, 0x71, 0x2e, 0x41, 0x64, 0x94, 0x49, 0x11,
-          0x14, 0x80, 0x23, 0x00, 0x44, 0x18, 0x5a, 0x99,
-          0x10, 0x3e, 0xd8, 0x20, 0x04, 0xdd, 0xbf, 0xcc  },
-        { 0xb1, 0x48, 0x35, 0xc8, 0x19, 0xa2, 0x90, 0xef,
-          0xb0, 0x10, 0xac, 0xe6, 0xd8, 0x56, 0x8d, 0xc6,
-          0xb8, 0x4d, 0xe6, 0x0b, 0xc4, 0x9b, 0x00, 0x4c,
-          0x3b, 0x13, 0xed, 0xa7, 0x63, 0x58, 0x94, 0x51,
-          0xe5, 0xdd, 0x74, 0x29, 0x28, 0x84, 0xd1, 0xbd,
-          0xce, 0x64, 0xe6, 0xb9, 0x19, 0xdd, 0x61, 0xdc,
-          0x9c, 0x56, 0xa2, 0x82, 0xa8, 0x1c, 0x0b, 0xd1,
-          0x4f, 0x1f, 0x36, 0x5b, 0x49, 0xb8, 0x3a, 0x5b  }
-      },
-
-      { "data-152 key-131",  /* Test 7  */
-        /* Test with a key and data that is larger than 128 bytes (=
-         * block-size of SHA-384 and SHA-512).  */
-        "This is a test using a larger than block-size key and a larger "
-        "than block-size data. The key needs to be hashed before being "
-        "used by the HMAC algorithm.",
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-
-        { 0x05, 0xd8, 0xcd, 0x6d, 0x00, 0xfa, 0xea, 0x8d,
-          0x1e, 0xb6, 0x8a, 0xde, 0x28, 0x73, 0x0b, 0xbd,
-          0x3c, 0xba, 0xb6, 0x92, 0x9f, 0x0a, 0x08, 0x6b,
-          0x29, 0xcd, 0x62, 0xa0  },
-        { 0x65, 0xc5, 0xb0, 0x6d, 0x4c, 0x3d, 0xe3, 0x2a,
-          0x7a, 0xef, 0x87, 0x63, 0x26, 0x1e, 0x49, 0xad,
-          0xb6, 0xe2, 0x29, 0x3e, 0xc8, 0xe7, 0xc6, 0x1e,
-          0x8d, 0xe6, 0x17, 0x01, 0xfc, 0x63, 0xe1, 0x23  },
-        { 0x02, 0x6f, 0xdf, 0x6b, 0x50, 0x74, 0x1e, 0x37,
-          0x38, 0x99, 0xc9, 0xf7, 0xd5, 0x40, 0x6d, 0x4e,
-          0xb0, 0x9f, 0xc6, 0x66, 0x56, 0x36, 0xfc, 0x1a,
-          0x53, 0x00, 0x29, 0xdd, 0xf5, 0xcf, 0x3c, 0xa5,
-          0xa9, 0x00, 0xed, 0xce, 0x01, 0xf5, 0xf6, 0x1e,
-          0x2f, 0x40, 0x8c, 0xdf, 0x2f, 0xd3, 0xe7, 0xe8  },
-        { 0x38, 0xa4, 0x56, 0xa0, 0x04, 0xbd, 0x10, 0xd3,
-          0x2c, 0x9a, 0xb8, 0x33, 0x66, 0x84, 0x11, 0x28,
-          0x62, 0xc3, 0xdb, 0x61, 0xad, 0xcc, 0xa3, 0x18,
-          0x29, 0x35, 0x5e, 0xaf, 0x46, 0xfd, 0x5c, 0x73,
-          0xd0, 0x6a, 0x1f, 0x0d, 0x13, 0xfe, 0xc9, 0xa6,
-          0x52, 0xfb, 0x38, 0x11, 0xb5, 0x77, 0xb1, 0xb1,
-          0xd1, 0xb9, 0x78, 0x9f, 0x97, 0xae, 0x5b, 0x83,
-          0xc6, 0xf4, 0x4d, 0xfc, 0xf1, 0xd6, 0x7e, 0xba  }
-      },
-
-      { "data-152 key-147",  /* Test 7a  */
-        /* Test with a key larger than 144 bytes (= block-size of
-         * SHA3-224). */
-        "This is a test using a larger than block-size key and a larger "
-        "than block-size data. The key needs to be hashed before being "
-        "used by the HMAC algorithm.",
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
-        "\xaa\xaa\xaa",
-
-        { 0xc7, 0x9c, 0x9b, 0x09, 0x34, 0x24, 0xe5, 0x88,
-          0xa9, 0x87, 0x8b, 0xbc, 0xb0, 0x89, 0xe0, 0x18,
-          0x27, 0x00, 0x96, 0xe9, 0xb4, 0xb1, 0xa9, 0xe8,
-          0x22, 0x0c, 0x86, 0x6a  },
-        { 0xe6, 0xa3, 0x6d, 0x9b, 0x91, 0x5f, 0x86, 0xa0,
-          0x93, 0xca, 0xc7, 0xd1, 0x10, 0xe9, 0xe0, 0x4c,
-          0xf1, 0xd6, 0x10, 0x0d, 0x30, 0x47, 0x55, 0x09,
-          0xc2, 0x47, 0x5f, 0x57, 0x1b, 0x75, 0x8b, 0x5a  },
-        { 0xca, 0xd1, 0x8a, 0x8f, 0xf6, 0xc4, 0xcc, 0x3a,
-          0xd4, 0x87, 0xb9, 0x5f, 0x97, 0x69, 0xe9, 0xb6,
-          0x1c, 0x06, 0x2a, 0xef, 0xd6, 0x95, 0x25, 0x69,
-          0xe6, 0xe6, 0x42, 0x18, 0x97, 0x05, 0x4c, 0xfc,
-          0x70, 0xb5, 0xfd, 0xc6, 0x60, 0x5c, 0x18, 0x45,
-          0x71, 0x12, 0xfc, 0x6a, 0xaa, 0xd4, 0x55, 0x85  },
-        { 0xdc, 0x03, 0x0e, 0xe7, 0x88, 0x70, 0x34, 0xf3,
-          0x2c, 0xf4, 0x02, 0xdf, 0x34, 0x62, 0x2f, 0x31,
-          0x1f, 0x3e, 0x6c, 0xf0, 0x48, 0x60, 0xc6, 0xbb,
-          0xd7, 0xfa, 0x48, 0x86, 0x74, 0x78, 0x2b, 0x46,
-          0x59, 0xfd, 0xbd, 0xf3, 0xfd, 0x87, 0x78, 0x52,
-          0x88, 0x5c, 0xfe, 0x6e, 0x22, 0x18, 0x5f, 0xe7,
-          0xb2, 0xee, 0x95, 0x20, 0x43, 0x62, 0x9b, 0xc9,
-          0xd5, 0xf3, 0x29, 0x8a, 0x41, 0xd0, 0x2c, 0x66  }
-      }/*,*/
-
-      /* Our API does not allow to specify a bit count and thus we
-       * can't use the following test.  */
-      /* { "data-5bit key-4",  /\* Test 8  *\/ */
-      /*   /\* Test with data bit size no multiple of 8, the data bits are */
-      /*    * '11001' from the NIST example using SHA-3 order (= 5 bits */
-      /*    * from LSB hex byte 13 or 5 bits from MSB hex byte c8).  *\/ */
-      /*   "\xc8", */
-      /*   "Jefe", */
-
-      /*   { 0x5f, 0x8c, 0x0e, 0xa7, 0xfa, 0xfe, 0xcd, 0x0c, */
-      /*     0x34, 0x63, 0xaa, 0xd0, 0x97, 0x42, 0xce, 0xce, */
-      /*     0xb1, 0x42, 0xfe, 0x0a, 0xb6, 0xf4, 0x53, 0x94, */
-      /*     0x38, 0xc5, 0x9d, 0xe8  }, */
-      /*   { 0xec, 0x82, 0x22, 0x77, 0x3f, 0xac, 0x68, 0xb3, */
-      /*     0xd3, 0xdc, 0xb1, 0x82, 0xae, 0xc8, 0xb0, 0x50, */
-      /*     0x7a, 0xce, 0x44, 0x48, 0xd2, 0x0a, 0x11, 0x47, */
-      /*     0xe6, 0x82, 0x11, 0x8d, 0xa4, 0xe3, 0xf4, 0x4c  }, */
-      /*   { 0x21, 0xfb, 0xd3, 0xbf, 0x3e, 0xbb, 0xa3, 0xcf, */
-      /*     0xc9, 0xef, 0x64, 0xc0, 0x59, 0x1c, 0x92, 0xc5, */
-      /*     0xac, 0xb2, 0x65, 0xe9, 0x2d, 0x87, 0x61, 0xd1, */
-      /*     0xf9, 0x1a, 0x52, 0xa1, 0x03, 0xa6, 0xc7, 0x96, */
-      /*     0x94, 0xcf, 0xd6, 0x7a, 0x9a, 0x2a, 0xc1, 0x32, */
-      /*     0x4f, 0x02, 0xfe, 0xa6, 0x3b, 0x81, 0xef, 0xfc  }, */
-      /*   { 0x27, 0xf9, 0x38, 0x8c, 0x15, 0x67, 0xef, 0x4e, */
-      /*     0xf2, 0x00, 0x60, 0x2a, 0x6c, 0xf8, 0x71, 0xd6, */
-      /*     0x8a, 0x6f, 0xb0, 0x48, 0xd4, 0x73, 0x7a, 0xc4, */
-      /*     0x41, 0x8a, 0x2f, 0x02, 0x12, 0x89, 0xd1, 0x3d, */
-      /*     0x1f, 0xd1, 0x12, 0x0f, 0xec, 0xb9, 0xcf, 0x96, */
-      /*     0x4c, 0x5b, 0x11, 0x7a, 0xb5, 0xb1, 0x1c, 0x61, */
-      /*     0x4b, 0x2d, 0xa3, 0x9d, 0xad, 0xd5, 0x1f, 0x2f, */
-      /*     0x5e, 0x22, 0xaa, 0xcc, 0xec, 0x7d, 0x57, 0x6e  } */
-      /* } */
-
-    };
-  const char *what;
-  const char *errtxt;
-  int tvidx;
-  const char *expect;
-  int nexpect;
-
-  for (tvidx=0; tvidx < DIM(tv); tvidx++)
-    {
-      what = tv[tvidx].desc;
-      if (hashalgo == GCRY_MD_SHA3_224)
-        {
-          expect = tv[tvidx].expect_224;
-          nexpect = DIM (tv[tvidx].expect_224);
-        }
-      else if (hashalgo == GCRY_MD_SHA3_256)
-        {
-          expect = tv[tvidx].expect_256;
-          nexpect = DIM (tv[tvidx].expect_256);
-        }
-      else if (hashalgo == GCRY_MD_SHA3_384)
-        {
-          expect = tv[tvidx].expect_384;
-          nexpect = DIM (tv[tvidx].expect_384);
-        }
-      else if (hashalgo == GCRY_MD_SHA3_512)
-        {
-          expect = tv[tvidx].expect_512;
-          nexpect = DIM (tv[tvidx].expect_512);
-        }
-      else
-        BUG();
-
-      if (tv[tvidx].trunc && tv[tvidx].trunc < nexpect)
-        nexpect = tv[tvidx].trunc;
-
-      errtxt = check_one (hashalgo,
-                          tv[tvidx].data, strlen (tv[tvidx].data),
-                          tv[tvidx].key, strlen (tv[tvidx].key),
-                          expect, nexpect, !!tv[tvidx].trunc);
-      if (errtxt)
-        goto failed;
-      if (!extended)
-        break;
-    }
-
-  return 0; /* Succeeded. */
-
- failed:
-  if (report)
-    report ("hmac", hashalgo, what, errtxt);
-  return GPG_ERR_SELFTEST_FAILED;
-}
-
-
-/* Run a full self-test for ALGO and return 0 on success.  */
-static gpg_err_code_t
-run_selftests (int algo, int extended, selftest_report_func_t report)
-{
-  gpg_err_code_t ec;
-
-  switch (algo)
-    {
-    case GCRY_MD_SHA1:
-      ec = selftests_sha1 (extended, report);
-      break;
-    case GCRY_MD_SHA224:
-      ec = selftests_sha224 (extended, report);
-      break;
-    case GCRY_MD_SHA256:
-      ec = selftests_sha256 (extended, report);
-      break;
-    case GCRY_MD_SHA384:
-      ec = selftests_sha384 (extended, report);
-      break;
-    case GCRY_MD_SHA512:
-      ec = selftests_sha512 (extended, report);
-      break;
-
-    case GCRY_MD_SHA3_224:
-    case GCRY_MD_SHA3_256:
-    case GCRY_MD_SHA3_384:
-    case GCRY_MD_SHA3_512:
-      ec = selftests_sha3 (algo, extended, report);
-      break;
-
-    default:
-      ec = GPG_ERR_DIGEST_ALGO;
-      break;
-    }
-  return ec;
-}
-
-
-
-
-/* Run the selftests for HMAC with digest algorithm ALGO with optional
-   reporting function REPORT.  */
-gpg_error_t
-_gcry_hmac_selftest (int algo, int extended, selftest_report_func_t report)
-{
-  gcry_err_code_t ec = 0;
-
-  if (!_gcry_md_test_algo (algo))
-    {
-      ec = run_selftests (algo, extended, report);
-    }
-  else
-    {
-      ec = GPG_ERR_DIGEST_ALGO;
-      if (report)
-        report ("hmac", algo, "module", "algorithm not available");
-    }
-  return gpg_error (ec);
-}
index ffe821d..7f70666 100644 (file)
@@ -48,6 +48,7 @@
 #include "types.h"  /* for byte and u32 typedefs */
 #include "g10lib.h"
 #include "cipher.h"
+#include "cipher-internal.h"
 
 
 #define IDEA_KEYSIZE 16
@@ -250,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 );
@@ -258,10 +261,12 @@ do_setkey( IDEA_context *c, const byte *key, unsigned int keylen )
 }
 
 static gcry_err_code_t
-idea_setkey (void *context, const byte *key, unsigned int keylen)
+idea_setkey (void *context, const byte *key, unsigned int keylen,
+             cipher_bulk_ops_t *bulk_ops)
 {
     IDEA_context *ctx = context;
     int rc = do_setkey (ctx, key, keylen);
+    (void)bulk_ops;
     _gcry_burn_stack (23+6*sizeof(void*));
     return rc;
 }
index 7079860..9e9a432 100644 (file)
@@ -36,5 +36,8 @@ _gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen,
                   unsigned long iterations,
                   size_t dklen, unsigned char *dk);
 
+/*-- blake2.c --*/
+gcry_err_code_t
+blake2b_vl_hash (const void *in, size_t inlen, size_t outputlen, void *output);
 
 #endif /*GCRY_KDF_INTERNAL_H*/
index 27f5789..b207be6 100644 (file)
@@ -1,5 +1,5 @@
 /* kdf.c  - Key Derivation Functions
- * Copyright (C) 1998, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 2008, 2011 Free Software Foundation, Inc.
  * Copyright (C) 2013 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
@@ -65,7 +65,7 @@ openpgp_s2k (const void *passphrase, size_t passphraselen,
           _gcry_md_reset (md);
           for (i=0; i < pass; i++) /* Preset the hash context.  */
             _gcry_md_putc (md, 0);
-       }
+        }
 
       if (algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K)
         {
@@ -305,3 +305,900 @@ _gcry_kdf_derive (const void *passphrase, size_t passphraselen,
  leave:
   return ec;
 }
+\f
+#include "bufhelp.h"
+
+typedef struct argon2_context *argon2_ctx_t;
+
+/* Per thread data for Argon2.  */
+struct argon2_thread_data {
+  argon2_ctx_t a;
+  unsigned int pass;
+  unsigned int slice;
+  unsigned int lane;
+};
+
+/* Argon2 context */
+struct argon2_context {
+  int algo;
+  int hash_type;
+
+  unsigned int outlen;
+
+  const unsigned char *password;
+  size_t passwordlen;
+
+  const unsigned char *salt;
+  size_t saltlen;
+
+  const unsigned char *key;
+  size_t keylen;
+
+  const unsigned char *ad;
+  size_t adlen;
+
+  unsigned int m_cost;
+
+  unsigned int passes;
+  unsigned int memory_blocks;
+  unsigned int segment_length;
+  unsigned int lane_length;
+  unsigned int lanes;
+
+  u64 *block;
+  struct argon2_thread_data *thread_data;
+
+  unsigned char out[1];  /* In future, we may use flexible array member.  */
+};
+
+#define ARGON2_VERSION 0x13
+
+#define ARGON2_WORDS_IN_BLOCK (1024/8)
+
+static void
+xor_block (u64 *dst, const u64 *src)
+{
+  int i;
+
+  for (i = 0; i < ARGON2_WORDS_IN_BLOCK; i++)
+    dst[i] ^= src[i];
+}
+
+static void
+beswap64_block (u64 *dst)
+{
+#ifdef WORDS_BIGENDIAN
+  int i;
+
+  /* Swap a block in big-endian 64-bit word into one in
+     little-endian.  */
+  for (i = 0; i < ARGON2_WORDS_IN_BLOCK; i++)
+    dst[i] = _gcry_bswap64 (dst[i]);
+#else
+  /* Nothing to do.  */
+  (void)dst;
+#endif
+}
+
+
+static gpg_err_code_t
+argon2_fill_first_blocks (argon2_ctx_t a)
+{
+  unsigned char h0_01_i[72];
+  unsigned char buf[10][4];
+  gcry_buffer_t iov[8];
+  unsigned int iov_count = 0;
+  int i;
+
+  /* Generate H0.  */
+  buf_put_le32 (buf[0], a->lanes);
+  buf_put_le32 (buf[1], a->outlen);
+  buf_put_le32 (buf[2], a->m_cost);
+  buf_put_le32 (buf[3], a->passes);
+  buf_put_le32 (buf[4], ARGON2_VERSION);
+  buf_put_le32 (buf[5], a->hash_type);
+  buf_put_le32 (buf[6], a->passwordlen);
+  iov[iov_count].data = buf[0];
+  iov[iov_count].len = 4 * 7;
+  iov[iov_count].off = 0;
+  iov_count++;
+  iov[iov_count].data = (void *)a->password;
+  iov[iov_count].len = a->passwordlen;
+  iov[iov_count].off = 0;
+  iov_count++;
+
+  buf_put_le32 (buf[7], a->saltlen);
+  iov[iov_count].data = buf[7];
+  iov[iov_count].len = 4;
+  iov[iov_count].off = 0;
+  iov_count++;
+  iov[iov_count].data = (void *)a->salt;
+  iov[iov_count].len = a->saltlen;
+  iov[iov_count].off = 0;
+  iov_count++;
+
+  buf_put_le32 (buf[8], a->keylen);
+  iov[iov_count].data = buf[8];
+  iov[iov_count].len = 4;
+  iov[iov_count].off = 0;
+  iov_count++;
+  if (a->key)
+    {
+      iov[iov_count].data = (void *)a->key;
+      iov[iov_count].len = a->keylen;
+      iov[iov_count].off = 0;
+      iov_count++;
+    }
+
+  buf_put_le32 (buf[9], a->adlen);
+  iov[iov_count].data = buf[9];
+  iov[iov_count].len = 4;
+  iov[iov_count].off = 0;
+  iov_count++;
+  if (a->ad)
+    {
+      iov[iov_count].data = (void *)a->ad;
+      iov[iov_count].len = a->adlen;
+      iov[iov_count].off = 0;
+      iov_count++;
+    }
+
+  _gcry_digest_spec_blake2b_512.hash_buffers (h0_01_i, 64, iov, iov_count);
+
+  for (i = 0; i < a->lanes; i++)
+    {
+      memset (h0_01_i+64, 0, 4);
+      buf_put_le32 (h0_01_i+64+4, i);
+      blake2b_vl_hash (h0_01_i, 72, 1024,
+                       &a->block[i*a->lane_length*ARGON2_WORDS_IN_BLOCK]);
+      beswap64_block (&a->block[i*a->lane_length*ARGON2_WORDS_IN_BLOCK]);
+
+      buf_put_le32 (h0_01_i+64, 1);
+      blake2b_vl_hash (h0_01_i, 72, 1024,
+                       &a->block[(i*a->lane_length+1)*ARGON2_WORDS_IN_BLOCK]);
+      beswap64_block (&a->block[(i*a->lane_length+1)*ARGON2_WORDS_IN_BLOCK]);
+    }
+  return 0;
+}
+
+static gpg_err_code_t
+argon2_init (argon2_ctx_t a, unsigned int parallelism,
+             unsigned int m_cost, unsigned int t_cost)
+{
+  gpg_err_code_t ec = 0;
+  unsigned int memory_blocks;
+  unsigned int segment_length;
+  void *block;
+  struct argon2_thread_data *thread_data;
+
+  memory_blocks = m_cost;
+  if (memory_blocks < 8 * parallelism)
+    memory_blocks = 8 * parallelism;
+
+  segment_length = memory_blocks / (parallelism * 4);
+  memory_blocks = segment_length * parallelism * 4;
+
+  a->passes = t_cost;
+  a->memory_blocks = memory_blocks;
+  a->segment_length = segment_length;
+  a->lane_length = segment_length * 4;
+  a->lanes = parallelism;
+
+  a->block = NULL;
+  a->thread_data = NULL;
+
+  block = xtrymalloc (1024 * memory_blocks);
+  if (!block)
+    {
+      ec = gpg_err_code_from_errno (errno);
+      return ec;
+    }
+  memset (block, 0, 1024 * memory_blocks);
+
+  thread_data = xtrymalloc (a->lanes * sizeof (struct argon2_thread_data));
+  if (!thread_data)
+    {
+      ec = gpg_err_code_from_errno (errno);
+      xfree (block);
+      return ec;
+    }
+
+  memset (thread_data, 0, a->lanes * sizeof (struct argon2_thread_data));
+
+  a->block = block;
+  a->thread_data = thread_data;
+  return 0;
+}
+
+
+static u64 fBlaMka (u64 x, u64 y)
+{
+  const u64 m = U64_C(0xFFFFFFFF);
+  return x + y + 2 * (x & m) * (y & m);
+}
+
+static u64 rotr64 (u64 w, unsigned int c)
+{
+  return (w >> c) | (w << (64 - c));
+}
+
+#define G(a, b, c, d)                                                          \
+    do {                                                                       \
+        a = fBlaMka(a, b);                                                     \
+        d = rotr64(d ^ a, 32);                                                 \
+        c = fBlaMka(c, d);                                                     \
+        b = rotr64(b ^ c, 24);                                                 \
+        a = fBlaMka(a, b);                                                     \
+        d = rotr64(d ^ a, 16);                                                 \
+        c = fBlaMka(c, d);                                                     \
+        b = rotr64(b ^ c, 63);                                                 \
+    } while ((void)0, 0)
+
+#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,   \
+                           v12, v13, v14, v15)                                 \
+    do {                                                                       \
+        G(v0, v4, v8, v12);                                                    \
+        G(v1, v5, v9, v13);                                                    \
+        G(v2, v6, v10, v14);                                                   \
+        G(v3, v7, v11, v15);                                                   \
+        G(v0, v5, v10, v15);                                                   \
+        G(v1, v6, v11, v12);                                                   \
+        G(v2, v7, v8, v13);                                                    \
+        G(v3, v4, v9, v14);                                                    \
+    } while ((void)0, 0)
+
+static void
+fill_block (const u64 *prev_block, const u64 *ref_block, u64 *curr_block,
+            int with_xor)
+{
+  u64 block_r[ARGON2_WORDS_IN_BLOCK];
+  u64 block_tmp[ARGON2_WORDS_IN_BLOCK];
+  int i;
+
+  memcpy (block_r, ref_block, 1024);
+  if (prev_block)
+    xor_block (block_r, prev_block);
+  memcpy (block_tmp, block_r, 1024);
+
+  if (with_xor)
+    xor_block (block_tmp, curr_block);
+
+  for (i = 0; i < 8; ++i)
+    BLAKE2_ROUND_NOMSG
+      (block_r[16 * i],      block_r[16 * i + 1],  block_r[16 * i + 2],
+       block_r[16 * i + 3],  block_r[16 * i + 4],  block_r[16 * i + 5],
+       block_r[16 * i + 6],  block_r[16 * i + 7],  block_r[16 * i + 8],
+       block_r[16 * i + 9],  block_r[16 * i + 10], block_r[16 * i + 11],
+       block_r[16 * i + 12], block_r[16 * i + 13], block_r[16 * i + 14],
+       block_r[16 * i + 15]);
+
+  for (i = 0; i < 8; i++)
+    BLAKE2_ROUND_NOMSG
+      (block_r[2 * i],      block_r[2 * i + 1],  block_r[2 * i + 16],
+       block_r[2 * i + 17], block_r[2 * i + 32], block_r[2 * i + 33],
+       block_r[2 * i + 48], block_r[2 * i + 49], block_r[2 * i + 64],
+       block_r[2 * i + 65], block_r[2 * i + 80], block_r[2 * i + 81],
+       block_r[2 * i + 96], block_r[2 * i + 97], block_r[2 * i + 112],
+       block_r[2 * i + 113]);
+
+  memcpy (curr_block, block_tmp, 1024);
+  xor_block (curr_block, block_r);
+}
+
+static void
+pseudo_random_generate (u64 *random_block, u64 *input_block)
+{
+  input_block[6]++;
+  fill_block (NULL, input_block, random_block, 0);
+  fill_block (NULL, random_block, random_block, 0);
+}
+
+static u32
+index_alpha (argon2_ctx_t a, const struct argon2_thread_data *t,
+             int segment_index, u32 random, int same_lane)
+{
+  u32 reference_area_size;
+  u64 relative_position;
+  u32 start_position;
+
+  if (t->pass == 0)
+    {
+      if (t->slice == 0)
+        reference_area_size = segment_index - 1;
+      else
+        {
+          if (same_lane)
+            reference_area_size = t->slice * a->segment_length
+              + segment_index - 1;
+          else
+            reference_area_size = t->slice * a->segment_length +
+              ((segment_index == 0) ? -1 : 0);
+        }
+    }
+  else
+    {
+      if (same_lane)
+        reference_area_size = a->lane_length
+          - a->segment_length + segment_index - 1;
+      else
+        reference_area_size = a->lane_length
+          - a->segment_length + ((segment_index == 0) ? -1 : 0);
+    }
+
+  relative_position = (random * (u64)random) >> 32;
+  relative_position = reference_area_size - 1 -
+    ((reference_area_size * relative_position) >> 32);
+
+  if (t->pass == 0)
+    start_position = 0;
+  else
+    start_position = (t->slice == 4 - 1)
+      ? 0
+      : (t->slice + 1) * a->segment_length;
+
+  return (start_position + relative_position) % a->lane_length;
+}
+
+static void
+argon2_compute_segment (void *priv)
+{
+  const struct argon2_thread_data *t = (const struct argon2_thread_data *)priv;
+  argon2_ctx_t a = t->a;
+  int i;
+  int prev_offset, curr_offset;
+  u32 ref_index, ref_lane;
+  u64 input_block[1024/sizeof (u64)];
+  u64 address_block[1024/sizeof (u64)];
+  u64 *random_block = NULL;
+
+  if (a->hash_type == GCRY_KDF_ARGON2I
+      || (a->hash_type == GCRY_KDF_ARGON2ID && t->pass == 0 && t->slice < 2))
+    {
+      memset (input_block, 0, 1024);
+      input_block[0] = t->pass;
+      input_block[1] = t->lane;
+      input_block[2] = t->slice;
+      input_block[3] = a->memory_blocks;
+      input_block[4] = a->passes;
+      input_block[5] = a->hash_type;
+      random_block = address_block;
+    }
+
+  if (t->pass == 0 && t->slice == 0)
+    {
+      if (random_block)
+        pseudo_random_generate (random_block, input_block);
+      i = 2;
+    }
+  else
+    i = 0;
+
+  curr_offset = t->lane * a->lane_length + t->slice * a->segment_length + i;
+  if ((curr_offset % a->lane_length))
+    prev_offset = curr_offset - 1;
+  else
+    prev_offset = curr_offset + a->lane_length - 1;
+
+  for (; i < a->segment_length; i++, curr_offset++, prev_offset++)
+    {
+      u64 *ref_block, *curr_block;
+      u64 rand64;
+
+      if ((curr_offset % a->lane_length) == 1)
+        prev_offset = curr_offset - 1;
+
+      if (random_block)
+        {
+          if ((i % (1024/sizeof (u64))) == 0)
+            pseudo_random_generate (random_block, input_block);
+
+          rand64 = random_block[(i% (1024/sizeof (u64)))];
+        }
+      else
+        rand64 = a->block[prev_offset*ARGON2_WORDS_IN_BLOCK];
+
+      if (t->pass == 0 && t->slice == 0)
+        ref_lane = t->lane;
+      else
+        ref_lane = (rand64 >> 32) % a->lanes;
+
+      ref_index = index_alpha (a, t, i, (rand64 & 0xffffffff),
+                               ref_lane == t->lane);
+      ref_block =
+        &a->block[(a->lane_length * ref_lane + ref_index)* ARGON2_WORDS_IN_BLOCK];
+
+      curr_block = &a->block[curr_offset * ARGON2_WORDS_IN_BLOCK];
+      fill_block (&a->block[prev_offset * ARGON2_WORDS_IN_BLOCK], ref_block,
+                  curr_block, t->pass != 0);
+    }
+}
+
+
+static gpg_err_code_t
+argon2_compute (argon2_ctx_t a, const struct gcry_kdf_thread_ops *ops)
+{
+  gpg_err_code_t ec;
+  unsigned int r;
+  unsigned int s;
+  unsigned int l;
+  int ret;
+
+  ec = argon2_fill_first_blocks (a);
+  if (ec)
+    return ec;
+
+  for (r = 0; r < a->passes; r++)
+    for (s = 0; s < 4; s++)
+      {
+        for (l = 0; l < a->lanes; l++)
+          {
+            struct argon2_thread_data *thread_data;
+
+            /* launch a thread.  */
+            thread_data = &a->thread_data[l];
+            thread_data->a = a;
+            thread_data->pass = r;
+            thread_data->slice = s;
+            thread_data->lane = l;
+
+            if (ops)
+             {
+               ret = ops->dispatch_job (ops->jobs_context,
+                                        argon2_compute_segment, thread_data);
+               if (ret < 0)
+                 return GPG_ERR_CANCELED;
+             }
+            else
+              argon2_compute_segment (thread_data);
+          }
+
+        if (ops)
+         {
+           ret = ops->wait_all_jobs (ops->jobs_context);
+           if (ret < 0)
+             return GPG_ERR_CANCELED;
+         }
+      }
+
+  return 0;
+}
+
+
+static gpg_err_code_t
+argon2_final (argon2_ctx_t a, size_t resultlen, void *result)
+{
+  int i;
+
+  if (resultlen != a->outlen)
+    return GPG_ERR_INV_VALUE;
+
+  memset (a->block, 0, 1024);
+  for (i = 0; i < a->lanes; i++)
+    {
+      u64 *last_block;
+
+      last_block = &a->block[(a->lane_length * i + (a->lane_length - 1))
+                             * ARGON2_WORDS_IN_BLOCK];
+      xor_block (a->block, last_block);
+    }
+
+  beswap64_block (a->block);
+  blake2b_vl_hash (a->block, 1024, a->outlen, result);
+  return 0;
+}
+
+static void
+argon2_close (argon2_ctx_t a)
+{
+  size_t n;
+
+  n = offsetof (struct argon2_context, out) + a->outlen;
+
+  if (a->block)
+    {
+      wipememory (a->block, 1024 * a->memory_blocks);
+      xfree (a->block);
+    }
+
+  if (a->thread_data)
+    xfree (a->thread_data);
+
+  wipememory (a, n);
+  xfree (a);
+}
+
+static gpg_err_code_t
+argon2_open (gcry_kdf_hd_t *hd, int subalgo,
+             const unsigned long *param, unsigned int paramlen,
+             const void *password, size_t passwordlen,
+             const void *salt, size_t saltlen,
+             const void *key, size_t keylen,
+             const void *ad, size_t adlen)
+{
+  int hash_type;
+  unsigned int taglen;
+  unsigned int t_cost;
+  unsigned int m_cost;
+  unsigned int parallelism = 1;
+  argon2_ctx_t a;
+  gpg_err_code_t ec;
+  size_t n;
+
+  if (subalgo != GCRY_KDF_ARGON2D
+      && subalgo != GCRY_KDF_ARGON2I
+      && subalgo != GCRY_KDF_ARGON2ID)
+    return GPG_ERR_INV_VALUE;
+  else
+    hash_type = subalgo;
+
+  /* param : [ tag_length, t_cost, m_cost, parallelism ] */
+  if (paramlen < 3 || paramlen > 4)
+    return GPG_ERR_INV_VALUE;
+  else
+    {
+      taglen = (unsigned int)param[0];
+      t_cost = (unsigned int)param[1];
+      m_cost = (unsigned int)param[2];
+      if (paramlen >= 4)
+        parallelism = (unsigned int)param[3];
+    }
+
+  n = offsetof (struct argon2_context, out) + taglen;
+  a = xtrymalloc (n);
+  if (!a)
+    return gpg_err_code_from_errno (errno);
+
+  a->algo = GCRY_KDF_ARGON2;
+  a->hash_type = hash_type;
+
+  a->outlen = taglen;
+
+  a->password = password;
+  a->passwordlen = passwordlen;
+  a->salt = salt;
+  a->saltlen = saltlen;
+  a->key = key;
+  a->keylen = keylen;
+  a->ad = ad;
+  a->adlen = adlen;
+
+  a->m_cost = m_cost;
+
+  a->block = NULL;
+  a->thread_data = NULL;
+
+  ec = argon2_init (a, parallelism, m_cost, t_cost);
+  if (ec)
+    {
+      xfree (a);
+      return ec;
+    }
+
+  *hd = (void *)a;
+  return 0;
+}
+
+
+static gpg_err_code_t
+balloon_open (gcry_kdf_hd_t *hd, int subalgo,
+              const unsigned long *param, unsigned int paramlen,
+              const void *passphrase, size_t passphraselen,
+              const void *salt, size_t saltlen)
+{
+  /*
+   * It should have space_cost and time_cost.
+   * Optionally, for parallelised version, it has parallelism.
+   */
+  if (paramlen != 2 && paramlen != 3)
+    return GPG_ERR_INV_VALUE;
+
+  (void)param;
+  (void)subalgo;
+  (void)passphrase;
+  (void)passphraselen;
+  (void)salt;
+  (void)saltlen;
+  *hd = NULL;
+  return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+
+struct gcry_kdf_handle {
+  int algo;
+  /* And algo specific parts come.  */
+};
+
+gpg_err_code_t
+_gcry_kdf_open (gcry_kdf_hd_t *hd, int algo, int subalgo,
+                const unsigned long *param, unsigned int paramlen,
+                const void *passphrase, size_t passphraselen,
+                const void *salt, size_t saltlen,
+                const void *key, size_t keylen,
+                const void *ad, size_t adlen)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_KDF_ARGON2:
+      if (!passphraselen || !saltlen)
+        ec = GPG_ERR_INV_VALUE;
+      else
+        ec = argon2_open (hd, subalgo, param, paramlen,
+                          passphrase, passphraselen, salt, saltlen,
+                          key, keylen, ad, adlen);
+      break;
+
+    case GCRY_KDF_BALLOON:
+      if (!passphraselen || !saltlen)
+        ec = GPG_ERR_INV_VALUE;
+      else
+        {
+          (void)key;
+          (void)keylen;
+          (void)ad;
+          (void)adlen;
+          ec = balloon_open (hd, subalgo, param, paramlen,
+                             passphrase, passphraselen, salt, saltlen);
+        }
+      break;
+
+    default:
+      ec = GPG_ERR_UNKNOWN_ALGORITHM;
+      break;
+    }
+
+  return ec;
+}
+
+gpg_err_code_t
+_gcry_kdf_compute (gcry_kdf_hd_t h, const struct gcry_kdf_thread_ops *ops)
+{
+  gpg_err_code_t ec;
+
+  switch (h->algo)
+    {
+    case GCRY_KDF_ARGON2:
+      ec = argon2_compute ((argon2_ctx_t)(void *)h, ops);
+      break;
+
+    default:
+      ec = GPG_ERR_UNKNOWN_ALGORITHM;
+      break;
+    }
+
+  return ec;
+}
+
+
+gpg_err_code_t
+_gcry_kdf_final (gcry_kdf_hd_t h, size_t resultlen, void *result)
+{
+  gpg_err_code_t ec;
+
+  switch (h->algo)
+    {
+    case GCRY_KDF_ARGON2:
+      ec = argon2_final ((argon2_ctx_t)(void *)h, resultlen, result);
+      break;
+
+    default:
+      ec = GPG_ERR_UNKNOWN_ALGORITHM;
+      break;
+    }
+
+  return ec;
+}
+
+void
+_gcry_kdf_close (gcry_kdf_hd_t h)
+{
+  switch (h->algo)
+    {
+    case GCRY_KDF_ARGON2:
+      argon2_close ((argon2_ctx_t)(void *)h);
+      break;
+
+    default:
+      break;
+    }
+}
+
+/* Check one KDF call with ALGO and HASH_ALGO using the regular KDF
+ * API. (passphrase,passphraselen) is the password to be derived,
+ * (salt,saltlen) the salt for the key derivation,
+ * iterations is the number of the kdf iterations,
+ * and (expect,expectlen) the expected result. Returns NULL on
+ * success or a string describing the failure.  */
+
+static const char *
+check_one (int algo, int hash_algo,
+           const void *passphrase, size_t passphraselen,
+           const void *salt, size_t saltlen,
+           unsigned long iterations,
+           const void *expect, size_t expectlen)
+{
+  unsigned char key[512]; /* hardcoded to avoid allocation */
+  size_t keysize = expectlen;
+
+  /* Skip test with shoter passphrase in FIPS mode.  */
+  if (fips_mode () && passphraselen < 14)
+    return NULL;
+
+  if (keysize > sizeof(key))
+    return "invalid tests data";
+
+  if (_gcry_kdf_derive (passphrase, passphraselen, algo,
+                        hash_algo, salt, saltlen, iterations,
+                        keysize, key))
+    return "gcry_kdf_derive failed";
+
+  if (memcmp (key, expect, expectlen))
+    return "does not match";
+
+  return NULL;
+}
+
+
+static gpg_err_code_t
+selftest_pbkdf2 (int extended, selftest_report_func_t report)
+{
+  static const struct {
+    const char *desc;
+    const char *p;   /* Passphrase.  */
+    size_t plen;     /* Length of P. */
+    const char *salt;
+    size_t saltlen;
+    int hashalgo;
+    unsigned long c; /* Iterations.  */
+    int dklen;       /* Requested key length.  */
+    const char *dk;  /* Derived key.  */
+    int disabled;
+  } tv[] = {
+#if USE_SHA1
+#define NUM_TEST_VECTORS 9
+    /* SHA1 test vectors are from RFC-6070.  */
+    {
+      "Basic PBKDF2 SHA1 #1",
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_SHA1,
+      1,
+      20,
+      "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
+      "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6"
+    },
+    {
+      "Basic PBKDF2 SHA1 #2",
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_SHA1,
+      2,
+      20,
+      "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
+      "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57"
+    },
+    {
+      "Basic PBKDF2 SHA1 #3",
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_SHA1,
+      4096,
+      20,
+      "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
+      "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1"
+    },
+    {
+      "Basic PBKDF2 SHA1 #4",
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_SHA1,
+      16777216,
+      20,
+      "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
+      "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84",
+      1 /* This test takes too long.  */
+    },
+    {
+      "Basic PBKDF2 SHA1 #5",
+      "passwordPASSWORDpassword", 24,
+      "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+      GCRY_MD_SHA1,
+      4096,
+      25,
+      "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
+      "\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96"
+      "\x4c\xf2\xf0\x70\x38"
+    },
+    {
+      "Basic PBKDF2 SHA1 #6",
+      "pass\0word", 9,
+      "sa\0lt", 5,
+      GCRY_MD_SHA1,
+      4096,
+      16,
+      "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
+      "\xd7\xf0\x34\x25\xe0\xc3"
+    },
+    { /* empty password test, not in RFC-6070 */
+      "Basic PBKDF2 SHA1 #7",
+      "", 0,
+      "salt", 4,
+      GCRY_MD_SHA1,
+      2,
+      20,
+      "\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2"
+      "\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97"
+    },
+#else
+#define NUM_TEST_VECTORS 2
+#endif
+    {
+      "Basic PBKDF2 SHA256",
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_SHA256,
+      2,
+      32,
+      "\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9\x28\xf0\x6d\xd0"
+      "\x2a\x30\x3f\x8e\xf3\xc2\x51\xdf\xd6\xe2\xd8\x5a\x95\x47\x4c\x43"
+    },
+    {
+      "Extended PBKDF2 SHA256",
+      "passwordPASSWORDpassword", 24,
+      "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+      GCRY_MD_SHA256,
+      4096,
+      40,
+      "\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11\x6e\x84\xcf"
+      "\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c\x4e\x2a\x1f\xb8\xdd\x53\xe1"
+      "\xc6\x35\x51\x8c\x7d\xac\x47\xe9"
+    },
+    { NULL }
+  };
+  const char *what;
+  const char *errtxt;
+  int tvidx;
+
+  for (tvidx=0; tv[tvidx].desc; tvidx++)
+    {
+      what = tv[tvidx].desc;
+      if (tv[tvidx].disabled)
+        continue;
+      errtxt = check_one (GCRY_KDF_PBKDF2, tv[tvidx].hashalgo,
+                          tv[tvidx].p, tv[tvidx].plen,
+                          tv[tvidx].salt, tv[tvidx].saltlen,
+                          tv[tvidx].c,
+                          tv[tvidx].dk, tv[tvidx].dklen);
+      if (errtxt)
+        goto failed;
+      if (tvidx >= NUM_TEST_VECTORS - 1 && !extended)
+        break;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("kdf", GCRY_KDF_PBKDF2, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run the selftests for KDF with KDF algorithm ALGO with optional
+   reporting function REPORT.  */
+gpg_error_t
+_gcry_kdf_selftest (int algo, int extended, selftest_report_func_t report)
+{
+  gcry_err_code_t ec = 0;
+
+  if (algo == GCRY_KDF_PBKDF2)
+    ec = selftest_pbkdf2 (extended, report);
+  else
+    {
+      ec = GPG_ERR_UNSUPPORTED_ALGORITHM;
+      if (report)
+        report ("kdf", algo, "module", "algorithm not available");
+    }
+  return gpg_error (ec);
+}
index 0bb3155..f350202 100644 (file)
 
 /* USE_64BIT_BMI2 indicates whether to compile with 64-bit Intel BMI2 code. */
 #undef USE_64BIT_BMI2
-#if defined(USE_64BIT) && defined(HAVE_GCC_INLINE_ASM_BMI2)
+#if defined(USE_64BIT) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \
+    defined(HAVE_CPU_ARCH_X86)
 # define USE_64BIT_BMI2 1
 #endif
 
 
 /* USE_64BIT_SHLD indicates whether to compile with 64-bit Intel SHLD code. */
 #undef USE_64BIT_SHLD
-#if defined(USE_64BIT) && defined (__GNUC__) && defined(__x86_64__)
+#if defined(USE_64BIT) && defined (__GNUC__) && defined(__x86_64__) && \
+    defined(HAVE_CPU_ARCH_X86)
 # define USE_64BIT_SHLD 1
 #endif
 
 
 /* USE_32BIT_BMI2 indicates whether to compile with 32-bit Intel BMI2 code. */
 #undef USE_32BIT_BMI2
-#if defined(USE_32BIT) && defined(HAVE_GCC_INLINE_ASM_BMI2)
+#if defined(USE_32BIT) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \
+    defined(HAVE_CPU_ARCH_X86)
 # define USE_32BIT_BMI2 1
 #endif
 
 #endif /*ENABLE_NEON_SUPPORT*/
 
 
+/* USE_S390X_CRYPTO indicates whether to enable zSeries code. */
+#undef USE_S390X_CRYPTO
+#if defined(HAVE_GCC_INLINE_ASM_S390X)
+# define USE_S390X_CRYPTO 1
+#endif /* USE_S390X_CRYPTO */
+
+
 #if defined(USE_64BIT) || defined(USE_64BIT_ARM_NEON)
 # define NEED_COMMON64 1
 #endif
@@ -115,6 +125,11 @@ typedef struct KECCAK_CONTEXT_S
   unsigned int count;
   unsigned int suffix;
   const keccak_ops_t *ops;
+#ifdef USE_S390X_CRYPTO
+  unsigned int kimd_func;
+  unsigned int buf_pos;
+  byte buf[1344 / 8]; /* SHAKE128 requires biggest buffer, 1344 bits. */
+#endif
 } KECCAK_CONTEXT;
 
 
@@ -619,7 +634,155 @@ static const keccak_ops_t keccak_bmi2_32bi_ops =
   .extract = keccak_extract32bi_bmi2,
 };
 
-#endif /* USE_32BIT */
+#endif /* USE_32BIT_BMI2 */
+
+
+#ifdef USE_S390X_CRYPTO
+#include "asm-inline-s390x.h"
+
+static inline void
+keccak_bwrite_s390x (void *context, const byte *in, size_t inlen)
+{
+  KECCAK_CONTEXT *ctx = context;
+
+  /* Write full-blocks. */
+  kimd_execute (ctx->kimd_func, &ctx->state, in, inlen);
+  return;
+}
+
+static inline void
+keccak_final_s390x (void *context)
+{
+  KECCAK_CONTEXT *ctx = context;
+
+  if (ctx->suffix == SHA3_DELIMITED_SUFFIX)
+    {
+      klmd_execute (ctx->kimd_func, &ctx->state, ctx->buf, ctx->count);
+    }
+  else
+    {
+      klmd_shake_execute (ctx->kimd_func, &ctx->state, NULL, 0, ctx->buf,
+                         ctx->count);
+      ctx->count = 0;
+      ctx->buf_pos = 0;
+    }
+
+  return;
+}
+
+static inline void
+keccak_bextract_s390x (void *context, byte *out, size_t outlen)
+{
+  KECCAK_CONTEXT *ctx = context;
+
+  /* Extract full-blocks. */
+  klmd_shake_execute (ctx->kimd_func | KLMD_PADDING_STATE, &ctx->state,
+                     out, outlen, NULL, 0);
+  return;
+}
+
+static void
+keccak_write_s390x (void *context, const byte *inbuf, size_t inlen)
+{
+  KECCAK_CONTEXT *hd = context;
+  const size_t blocksize = hd->blocksize;
+  size_t inblocks;
+  size_t copylen;
+
+  while (hd->count)
+    {
+      if (hd->count == blocksize)  /* Flush the buffer. */
+       {
+         keccak_bwrite_s390x (hd, hd->buf, blocksize);
+         hd->count = 0;
+       }
+      else
+       {
+         copylen = inlen;
+         if (copylen > blocksize - hd->count)
+           copylen = blocksize - hd->count;
+
+         if (copylen == 0)
+           break;
+
+         buf_cpy (&hd->buf[hd->count], inbuf, copylen);
+         hd->count += copylen;
+         inbuf += copylen;
+         inlen -= copylen;
+       }
+    }
+
+  if (inlen == 0)
+    return;
+
+  if (inlen >= blocksize)
+    {
+      inblocks = inlen / blocksize;
+      keccak_bwrite_s390x (hd, inbuf, inblocks * blocksize);
+      hd->count = 0;
+      inlen -= inblocks * blocksize;
+      inbuf += inblocks * blocksize;
+    }
+
+  if (inlen)
+    {
+      buf_cpy (hd->buf, inbuf, inlen);
+      hd->count = inlen;
+    }
+}
+
+static void
+keccak_extract_s390x (void *context, void *outbuf_arg, size_t outlen)
+{
+  KECCAK_CONTEXT *hd = context;
+  const size_t blocksize = hd->blocksize;
+  byte *outbuf = outbuf_arg;
+
+  while (outlen)
+    {
+      gcry_assert(hd->count == 0 || hd->buf_pos < hd->count);
+
+      if (hd->buf_pos < hd->count && outlen)
+       {
+         size_t copylen = hd->count - hd->buf_pos;
+
+         if (copylen > outlen)
+           copylen = outlen;
+
+         buf_cpy (outbuf, &hd->buf[hd->buf_pos], copylen);
+
+         outbuf += copylen;
+         outlen -= copylen;
+         hd->buf_pos += copylen;
+       }
+
+      if (hd->buf_pos == hd->count)
+       {
+         hd->buf_pos = 0;
+         hd->count = 0;
+       }
+
+      if (outlen == 0)
+       return;
+
+      if (outlen >= blocksize)
+       {
+         size_t outblocks = outlen / blocksize;
+
+         keccak_bextract_s390x (context, outbuf, outblocks * blocksize);
+
+         outlen -= outblocks * blocksize;
+         outbuf += outblocks * blocksize;
+
+         if (outlen == 0)
+           return;
+       }
+
+      keccak_bextract_s390x (context, hd->buf, blocksize);
+      hd->count = blocksize;
+    }
+}
+#endif /* USE_S390X_CRYPTO */
 
 
 static void
@@ -633,6 +796,14 @@ keccak_write (void *context, const void *inbuf_arg, size_t inlen)
   unsigned int count, i;
   unsigned int pos, nlanes;
 
+#ifdef USE_S390X_CRYPTO
+  if (ctx->kimd_func)
+    {
+      keccak_write_s390x (context, inbuf, inlen);
+      return;
+    }
+#endif
+
   count = ctx->count;
 
   if (inlen && (count % 8))
@@ -777,6 +948,42 @@ keccak_init (int algo, void *context, unsigned int flags)
     default:
       BUG();
     }
+
+#ifdef USE_S390X_CRYPTO
+  ctx->kimd_func = 0;
+  if ((features & HWF_S390X_MSA) != 0)
+    {
+      unsigned int kimd_func = 0;
+
+      switch (algo)
+       {
+       case GCRY_MD_SHA3_224:
+         kimd_func = KMID_FUNCTION_SHA3_224;
+         break;
+       case GCRY_MD_SHA3_256:
+         kimd_func = KMID_FUNCTION_SHA3_256;
+         break;
+       case GCRY_MD_SHA3_384:
+         kimd_func = KMID_FUNCTION_SHA3_384;
+         break;
+       case GCRY_MD_SHA3_512:
+         kimd_func = KMID_FUNCTION_SHA3_512;
+         break;
+       case GCRY_MD_SHAKE128:
+         kimd_func = KMID_FUNCTION_SHAKE128;
+         break;
+       case GCRY_MD_SHAKE256:
+         kimd_func = KMID_FUNCTION_SHAKE256;
+         break;
+       }
+
+      if ((kimd_query () & km_function_to_mask (kimd_func)) &&
+         (klmd_query () & km_function_to_mask (kimd_func)))
+       {
+         ctx->kimd_func = kimd_func;
+       }
+    }
+#endif
 }
 
 static void
@@ -833,6 +1040,14 @@ keccak_final (void *context)
   unsigned int lastbytes;
   byte lane[8];
 
+#ifdef USE_S390X_CRYPTO
+  if (ctx->kimd_func)
+    {
+      keccak_final_s390x (context);
+      return;
+    }
+#endif
+
   lastbytes = ctx->count;
 
   /* Do the padding and switch to the squeezing phase */
@@ -894,6 +1109,14 @@ keccak_extract (void *context, void *out, size_t outlen)
   unsigned int i;
   byte lane[8];
 
+#ifdef USE_S390X_CRYPTO
+  if (ctx->kimd_func)
+    {
+      keccak_extract_s390x (context, out, outlen);
+      return;
+    }
+#endif
+
   count = ctx->count;
 
   while (count && outlen && (outlen < 8 || count % 8))
@@ -998,6 +1221,72 @@ 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, size_t nbytes, const gcry_buffer_t *iov,
+                        int iovcnt, const gcry_md_spec_t *spec)
+{
+  KECCAK_CONTEXT hd;
+
+  spec->init (&hd, 0);
+  for (;iovcnt > 0; iov++, iovcnt--)
+    keccak_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len);
+  keccak_final (&hd);
+  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, size_t nbytes,
+                            const gcry_buffer_t *iov, int iovcnt)
+{
+  _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt,
+                          &_gcry_digest_spec_sha3_224);
+}
+
+static void
+_gcry_sha3_256_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_sha3_256);
+}
+
+static void
+_gcry_sha3_384_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_sha3_384);
+}
+
+static void
+_gcry_sha3_512_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_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);
+}
+
 \f
 /*
      Self-test section.
@@ -1167,48 +1456,48 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
 
 
 \f
-static byte sha3_224_asn[] = { 0x30 };
-static gcry_md_oid_spec_t oid_spec_sha3_224[] =
+static const byte sha3_224_asn[] = { 0x30 };
+static const gcry_md_oid_spec_t oid_spec_sha3_224[] =
   {
     { "2.16.840.1.101.3.4.2.7" },
     /* PKCS#1 sha3_224WithRSAEncryption */
     { "?" },
     { NULL }
   };
-static byte sha3_256_asn[] = { 0x30 };
-static gcry_md_oid_spec_t oid_spec_sha3_256[] =
+static const byte sha3_256_asn[] = { 0x30 };
+static const gcry_md_oid_spec_t oid_spec_sha3_256[] =
   {
     { "2.16.840.1.101.3.4.2.8" },
     /* PKCS#1 sha3_256WithRSAEncryption */
     { "?" },
     { NULL }
   };
-static byte sha3_384_asn[] = { 0x30 };
-static gcry_md_oid_spec_t oid_spec_sha3_384[] =
+static const byte sha3_384_asn[] = { 0x30 };
+static const gcry_md_oid_spec_t oid_spec_sha3_384[] =
   {
     { "2.16.840.1.101.3.4.2.9" },
     /* PKCS#1 sha3_384WithRSAEncryption */
     { "?" },
     { NULL }
   };
-static byte sha3_512_asn[] = { 0x30 };
-static gcry_md_oid_spec_t oid_spec_sha3_512[] =
+static const byte sha3_512_asn[] = { 0x30 };
+static const gcry_md_oid_spec_t oid_spec_sha3_512[] =
   {
     { "2.16.840.1.101.3.4.2.10" },
     /* PKCS#1 sha3_512WithRSAEncryption */
     { "?" },
     { NULL }
   };
-static byte shake128_asn[] = { 0x30 };
-static gcry_md_oid_spec_t oid_spec_shake128[] =
+static const byte shake128_asn[] = { 0x30 };
+static const gcry_md_oid_spec_t oid_spec_shake128[] =
   {
     { "2.16.840.1.101.3.4.2.11" },
     /* PKCS#1 shake128WithRSAEncryption */
     { "?" },
     { NULL }
   };
-static byte shake256_asn[] = { 0x30 };
-static gcry_md_oid_spec_t oid_spec_shake256[] =
+static const byte shake256_asn[] = { 0x30 };
+static const gcry_md_oid_spec_t oid_spec_shake256[] =
   {
     { "2.16.840.1.101.3.4.2.12" },
     /* PKCS#1 shake256WithRSAEncryption */
@@ -1216,51 +1505,57 @@ static gcry_md_oid_spec_t oid_spec_shake256[] =
     { NULL }
   };
 
-gcry_md_spec_t _gcry_digest_spec_sha3_224 =
+const 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_buffers,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
-gcry_md_spec_t _gcry_digest_spec_sha3_256 =
+const 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_buffers,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
-gcry_md_spec_t _gcry_digest_spec_sha3_384 =
+const 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_buffers,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
-gcry_md_spec_t _gcry_digest_spec_sha3_512 =
+const 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_buffers,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
-gcry_md_spec_t _gcry_digest_spec_shake128 =
+const 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,
+    _gcry_shake128_hash_buffers,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
-gcry_md_spec_t _gcry_digest_spec_shake256 =
+const 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,
+    _gcry_shake256_hash_buffers,
     sizeof (KECCAK_CONTEXT),
     run_selftests
   };
index e42a764..b80c340 100644 (file)
@@ -1,5 +1,6 @@
 /* mac-cmac.c  -  CMAC glue for MAC API
  * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -57,6 +58,8 @@ map_mac_algo_to_cipher (int mac_algo)
       return GCRY_CIPHER_RFC2268_128;
     case GCRY_MAC_CMAC_GOST28147:
       return GCRY_CIPHER_GOST28147;
+    case GCRY_MAC_CMAC_SM4:
+      return GCRY_CIPHER_SM4;
     }
 }
 
@@ -66,7 +69,7 @@ cmac_open (gcry_mac_hd_t h)
 {
   gcry_err_code_t err;
   gcry_cipher_hd_t hd;
-  int secure = (h->magic == CTX_MAGIC_SECURE);
+  int secure = (h->magic == CTX_MAC_MAGIC_SECURE);
   int cipher_algo;
   unsigned int flags;
 
@@ -144,6 +147,293 @@ cmac_get_keylen (int algo)
 }
 
 
+/* Check one CMAC with MAC ALGO using the regular MAC
+ * API. (DATA,DATALEN) is the data to be MACed, (KEY,KEYLEN) the key
+ * and (EXPECT,EXPECTLEN) the expected result.  Returns NULL on
+ * success or a string describing the failure.  */
+static const char *
+check_one (int algo, const char *data, size_t datalen,
+           const char *key, size_t keylen,
+           const char *expect, size_t expectlen)
+{
+  gcry_mac_hd_t hd;
+  unsigned char mac[512]; /* hardcoded to avoid allocation */
+  unsigned int maclen;
+  size_t macoutlen;
+  int i;
+  gcry_error_t err = 0;
+
+  err = _gcry_mac_open (&hd, algo, 0, NULL);
+  if (err)
+    return "gcry_mac_open failed";
+
+  i = _gcry_mac_get_algo (hd);
+  if (i != algo)
+    return "gcry_mac_get_algo failed";
+
+  maclen = _gcry_mac_get_algo_maclen (algo);
+  if (maclen < 1 || maclen > 500)
+    return "gcry_mac_get_algo_maclen failed";
+
+  if (maclen != expectlen)
+    return "invalid tests data";
+
+  err = _gcry_mac_setkey (hd, key, keylen);
+  if (err)
+    {
+      _gcry_mac_close (hd);
+      return "gcry_mac_setkey failed";
+    }
+
+  err = _gcry_mac_write (hd, data, datalen);
+  if (err)
+    {
+      _gcry_mac_close (hd);
+      return "gcry_mac_write failed";
+    }
+
+  err = _gcry_mac_verify (hd, expect, maclen);
+  if (err)
+    {
+      _gcry_mac_close (hd);
+      return "gcry_mac_verify failed";
+    }
+
+  macoutlen = maclen;
+  err = _gcry_mac_read (hd, mac, &macoutlen);
+  _gcry_mac_close (hd);
+  if (err)
+    return "gcry_mac_read failed";
+
+  if (memcmp (mac, expect, maclen))
+    return "does not match";
+
+  return NULL;
+}
+
+
+/*
+ * CMAC AES and DES test vectors are from
+ * http://web.archive.org/web/20130930212819/http://csrc.nist.gov/publica \
+ * tions/nistpubs/800-38B/Updated_CMAC_Examples.pdf
+ */
+
+static gpg_err_code_t
+selftests_cmac_3des (int extended, selftest_report_func_t report)
+{
+  static const struct
+  {
+    const char *desc;
+    const char *data;
+    const char *key;
+    const char *expect;
+  } tv[] =
+    {
+      { "Basic 3DES",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57",
+        "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58"
+        "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5",
+        "\x74\x3d\xdb\xe0\xce\x2d\xc2\xed" },
+      { "Extended 3DES #1",
+        "",
+        "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58"
+        "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5",
+        "\xb7\xa6\x88\xe1\x22\xff\xaf\x95" },
+      { "Extended 3DES #2",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96",
+        "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58"
+        "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5",
+        "\x8e\x8f\x29\x31\x36\x28\x37\x97" },
+      { "Extended 3DES #3",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
+        "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58"
+        "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5",
+        "\x33\xe6\xb1\x09\x24\x00\xea\xe5" },
+      { "Extended 3DES #4",
+        "",
+        "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38"
+        "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5",
+        "\xbd\x2e\xbf\x9a\x3b\xa0\x03\x61" },
+      { "Extended 3DES #5",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96",
+        "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38"
+        "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5",
+        "\x4f\xf2\xab\x81\x3c\x53\xce\x83" },
+      { "Extended 3DES #6",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57",
+        "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38"
+        "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5",
+        "\x62\xdd\x1b\x47\x19\x02\xbd\x4e" },
+      { "Extended 3DES #7",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51",
+        "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38"
+        "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5",
+        "\x31\xb1\xe4\x31\xda\xbc\x4e\xb8" },
+      { NULL }
+    };
+  const char *what;
+  const char *errtxt;
+  int tvidx;
+
+  for (tvidx=0; tv[tvidx].desc; tvidx++)
+    {
+      what = tv[tvidx].desc;
+      errtxt = check_one (GCRY_MAC_CMAC_3DES,
+                          tv[tvidx].data, strlen (tv[tvidx].data),
+                          tv[tvidx].key, strlen (tv[tvidx].key),
+                          tv[tvidx].expect, 8);
+      if (errtxt)
+        goto failed;
+      if (!extended)
+        break;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("cmac", GCRY_MAC_CMAC_3DES, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+
+static gpg_err_code_t
+selftests_cmac_aes (int extended, selftest_report_func_t report)
+{
+  static const struct
+  {
+    const char *desc;
+    const char *data;
+    const char *key;
+    const char *expect;
+  } tv[] =
+    {
+      { "Basic AES128",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+        "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11",
+        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+        "\xdf\xa6\x67\x47\xde\x9a\xe6\x30\x30\xca\x32\x61\x14\x97\xc8\x27" },
+      { "Basic AES192",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+        "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11",
+        "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+        "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+        "\x8a\x1d\xe5\xbe\x2e\xb3\x1a\xad\x08\x9a\x82\xe6\xee\x90\x8b\x0e" },
+      { "Basic AES256",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+        "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11",
+        "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+        "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+        "\xaa\xf3\xd8\xf1\xde\x56\x40\xc2\x32\xf5\xb1\x69\xb9\xc9\x11\xe6" },
+      { "Extended AES #1",
+        "",
+        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+        "\xbb\x1d\x69\x29\xe9\x59\x37\x28\x7f\xa3\x7d\x12\x9b\x75\x67\x46" },
+      { "Extended AES #2",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
+        "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+        "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+        "\x9e\x99\xa7\xbf\x31\xe7\x10\x90\x06\x62\xf6\x5e\x61\x7c\x51\x84" },
+      { "Extended AES #3",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+        "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+        "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+        "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+        "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+        "\xe1\x99\x21\x90\x54\x9f\x6e\xd5\x69\x6a\x2c\x05\x6c\x31\x54\x10" },
+      { "Extended AES #4",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
+        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+        "\x07\x0a\x16\xb4\x6b\x4d\x41\x44\xf7\x9b\xdd\x9d\xd0\x4a\x28\x7c" },
+      { "Extended AES #5",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+        "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+        "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
+        "\x51\xf0\xbe\xbf\x7e\x3b\x9d\x92\xfc\x49\x74\x17\x79\x36\x3c\xfe" },
+      { "Extended AES #6",
+        "",
+        "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+        "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+        "\xd1\x7d\xdf\x46\xad\xaa\xcd\xe5\x31\xca\xc4\x83\xde\x7a\x93\x67" },
+      { "Extended AES #7",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+        "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+        "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+        "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
+        "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
+        "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
+        "\xa1\xd5\xdf\x0e\xed\x79\x0f\x79\x4d\x77\x58\x96\x59\xf3\x9a\x11" },
+      { "Extended AES #8",
+        "",
+        "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+        "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+        "\x02\x89\x62\xf6\x1b\x7b\xf8\x9e\xfc\x6b\x55\x1f\x46\x67\xd9\x83" },
+      { "Extended AES #9",
+        "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
+        "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+        "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
+        "\x28\xa7\x02\x3f\x45\x2e\x8f\x82\xbd\x4b\xf2\x8d\x8c\x37\xc3\x5c" },
+      { NULL }
+    };
+  const char *what;
+  const char *errtxt;
+  int tvidx;
+
+  for (tvidx=0; tv[tvidx].desc; tvidx++)
+    {
+      what = tv[tvidx].desc;
+      errtxt = check_one (GCRY_MAC_CMAC_AES,
+                          tv[tvidx].data, strlen (tv[tvidx].data),
+                          tv[tvidx].key, strlen (tv[tvidx].key),
+                          tv[tvidx].expect, strlen (tv[tvidx].expect));
+      if (errtxt)
+        goto failed;
+      if (tvidx >= 2 && !extended)
+        break;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("cmac", GCRY_MAC_CMAC_AES, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+static gpg_err_code_t
+cmac_selftest (int algo, int extended, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_MAC_CMAC_3DES:
+      ec = selftests_cmac_3des (extended, report);
+      break;
+    case GCRY_MAC_CMAC_AES:
+      ec = selftests_cmac_aes (extended, report);
+      break;
+
+    default:
+      ec = GPG_ERR_MAC_ALGO;
+      break;
+    }
+
+  return ec;
+}
+
+
 static gcry_mac_spec_ops_t cmac_ops = {
   cmac_open,
   cmac_close,
@@ -154,73 +444,81 @@ static gcry_mac_spec_ops_t cmac_ops = {
   cmac_read,
   cmac_verify,
   cmac_get_maclen,
-  cmac_get_keylen
+  cmac_get_keylen,
+  NULL,
+  cmac_selftest
 };
 
 
 #if USE_BLOWFISH
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish = {
   GCRY_MAC_CMAC_BLOWFISH, {0, 0}, "CMAC_BLOWFISH",
   &cmac_ops
 };
 #endif
 #if USE_DES
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes = {
-  GCRY_MAC_CMAC_3DES, {0, 1}, "CMAC_3DES",
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes = {
+  GCRY_MAC_CMAC_3DES, {0, 0}, "CMAC_3DES",
   &cmac_ops
 };
 #endif
 #if USE_CAST5
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5 = {
   GCRY_MAC_CMAC_CAST5, {0, 0}, "CMAC_CAST5",
   &cmac_ops
 };
 #endif
 #if USE_AES
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes = {
   GCRY_MAC_CMAC_AES, {0, 1}, "CMAC_AES",
   &cmac_ops
 };
 #endif
 #if USE_TWOFISH
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish = {
   GCRY_MAC_CMAC_TWOFISH, {0, 0}, "CMAC_TWOFISH",
   &cmac_ops
 };
 #endif
 #if USE_SERPENT
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent = {
   GCRY_MAC_CMAC_SERPENT, {0, 0}, "CMAC_SERPENT",
   &cmac_ops
 };
 #endif
 #if USE_RFC2268
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268 = {
   GCRY_MAC_CMAC_RFC2268, {0, 0}, "CMAC_RFC2268",
   &cmac_ops
 };
 #endif
 #if USE_SEED
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed = {
   GCRY_MAC_CMAC_SEED, {0, 0}, "CMAC_SEED",
   &cmac_ops
 };
 #endif
 #if USE_CAMELLIA
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia = {
   GCRY_MAC_CMAC_CAMELLIA, {0, 0}, "CMAC_CAMELLIA",
   &cmac_ops
 };
 #endif
-#ifdef USE_IDEA
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea = {
+#if USE_IDEA
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea = {
   GCRY_MAC_CMAC_IDEA, {0, 0}, "CMAC_IDEA",
   &cmac_ops
 };
 #endif
 #if USE_GOST28147
-gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147 = {
   GCRY_MAC_CMAC_GOST28147, {0, 0}, "CMAC_GOST28147",
   &cmac_ops
 };
 #endif
+#if USE_SM4
+const gcry_mac_spec_t _gcry_mac_type_spec_cmac_sm4 = {
+  GCRY_MAC_CMAC_SM4, {0, 0}, "CMAC_SM4",
+  &cmac_ops
+};
+#endif
index 9bc86d9..12f515e 100644 (file)
@@ -54,7 +54,7 @@ gmac_open (gcry_mac_hd_t h)
 {
   gcry_err_code_t err;
   gcry_cipher_hd_t hd;
-  int secure = (h->magic == CTX_MAGIC_SECURE);
+  int secure = (h->magic == CTX_MAC_MAGIC_SECURE);
   int cipher_algo;
   unsigned int flags;
 
@@ -149,36 +149,38 @@ static gcry_mac_spec_ops_t gmac_ops = {
   gmac_read,
   gmac_verify,
   gmac_get_maclen,
-  gmac_get_keylen
+  gmac_get_keylen,
+  NULL,
+  NULL
 };
 
 
 #if USE_AES
-gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes = {
-  GCRY_MAC_GMAC_AES, {0, 1}, "GMAC_AES",
+const gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes = {
+  GCRY_MAC_GMAC_AES, {0, 0}, "GMAC_AES",
   &gmac_ops
 };
 #endif
 #if USE_TWOFISH
-gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish = {
+const gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish = {
   GCRY_MAC_GMAC_TWOFISH, {0, 0}, "GMAC_TWOFISH",
   &gmac_ops
 };
 #endif
 #if USE_SERPENT
-gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent = {
+const gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent = {
   GCRY_MAC_GMAC_SERPENT, {0, 0}, "GMAC_SERPENT",
   &gmac_ops
 };
 #endif
 #if USE_SEED
-gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed = {
+const gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed = {
   GCRY_MAC_GMAC_SEED, {0, 0}, "GMAC_SEED",
   &gmac_ops
 };
 #endif
 #if USE_CAMELLIA
-gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia = {
+const gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia = {
   GCRY_MAC_GMAC_CAMELLIA, {0, 0}, "GMAC_CAMELLIA",
   &gmac_ops
 };
index 9379f4b..f1ab568 100644 (file)
@@ -1,5 +1,6 @@
 /* mac-hmac.c  -  HMAC glue for MAC API
  * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2008 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
@@ -26,6 +27,7 @@
 #include "g10lib.h"
 #include "./mac-internal.h"
 #include "bufhelp.h"
+#include "cipher.h"
 
 
 static int
@@ -51,6 +53,10 @@ map_mac_algo_to_md (int mac_algo)
       return GCRY_MD_SHA384;
     case GCRY_MAC_HMAC_SHA512:
       return GCRY_MD_SHA512;
+    case GCRY_MAC_HMAC_SHA512_256:
+      return GCRY_MD_SHA512_256;
+    case GCRY_MAC_HMAC_SHA512_224:
+      return GCRY_MD_SHA512_224;
     case GCRY_MAC_HMAC_SHA3_224:
       return GCRY_MD_SHA3_224;
     case GCRY_MAC_HMAC_SHA3_256:
@@ -67,10 +73,30 @@ map_mac_algo_to_md (int mac_algo)
       return GCRY_MD_WHIRLPOOL;
     case GCRY_MAC_HMAC_GOSTR3411_94:
       return GCRY_MD_GOSTR3411_94;
+    case GCRY_MAC_HMAC_GOSTR3411_CP:
+      return GCRY_MD_GOSTR3411_CP;
     case GCRY_MAC_HMAC_STRIBOG256:
       return GCRY_MD_STRIBOG256;
     case GCRY_MAC_HMAC_STRIBOG512:
       return GCRY_MD_STRIBOG512;
+    case GCRY_MAC_HMAC_BLAKE2B_512:
+      return GCRY_MD_BLAKE2B_512;
+    case GCRY_MAC_HMAC_BLAKE2B_384:
+      return GCRY_MD_BLAKE2B_384;
+    case GCRY_MAC_HMAC_BLAKE2B_256:
+      return GCRY_MD_BLAKE2B_256;
+    case GCRY_MAC_HMAC_BLAKE2B_160:
+      return GCRY_MD_BLAKE2B_160;
+    case GCRY_MAC_HMAC_BLAKE2S_256:
+      return GCRY_MD_BLAKE2S_256;
+    case GCRY_MAC_HMAC_BLAKE2S_224:
+      return GCRY_MD_BLAKE2S_224;
+    case GCRY_MAC_HMAC_BLAKE2S_160:
+      return GCRY_MD_BLAKE2S_160;
+    case GCRY_MAC_HMAC_BLAKE2S_128:
+      return GCRY_MD_BLAKE2S_128;
+    case GCRY_MAC_HMAC_SM3:
+      return GCRY_MD_SM3;
     }
 }
 
@@ -80,7 +106,7 @@ hmac_open (gcry_mac_hd_t h)
 {
   gcry_err_code_t err;
   gcry_md_hd_t hd;
-  int secure = (h->magic == CTX_MAGIC_SECURE);
+  int secure = (h->magic == CTX_MAC_MAGIC_SECURE);
   unsigned int flags;
   int md_algo;
 
@@ -199,6 +225,1077 @@ hmac_get_keylen (int algo)
 }
 
 
+/* Check one HMAC with digest ALGO using the regualr HAMC
+ * API. (DATA,DATALEN) is the data to be MACed, (KEY,KEYLEN) the key
+ * and (EXPECT,EXPECTLEN) the expected result.  If TRUNC is set, the
+ * EXPECTLEN may be less than the digest length.  Returns NULL on
+ * success or a string describing the failure.  */
+static const char *
+check_one (int algo,
+           const void *data, size_t datalen,
+           const void *key, size_t keylen,
+           const void *expect, size_t expectlen, int trunc)
+{
+  gcry_md_hd_t hd;
+  const unsigned char *digest;
+
+/*   printf ("HMAC algo %d\n", algo); */
+
+  /* Skip test with shoter key in FIPS mode.  */
+  if (fips_mode () && keylen < 14)
+    return NULL;
+
+  if (trunc)
+    {
+      if (_gcry_md_get_algo_dlen (algo) < expectlen)
+        return "invalid tests data";
+    }
+  else
+    {
+      if (_gcry_md_get_algo_dlen (algo) != expectlen)
+        return "invalid tests data";
+    }
+  if (_gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC))
+    return "gcry_md_open failed";
+  if (_gcry_md_setkey (hd, key, keylen))
+    {
+      _gcry_md_close (hd);
+      return "gcry_md_setkey failed";
+    }
+  _gcry_md_write (hd, data, datalen);
+  digest = _gcry_md_read (hd, algo);
+  if (!digest)
+    {
+      _gcry_md_close (hd);
+      return "gcry_md_read failed";
+    }
+  if (memcmp (digest, expect, expectlen))
+    {
+/*       int i; */
+
+/*       fputs ("        {", stdout); */
+/*       for (i=0; i < expectlen-1; i++) */
+/*         { */
+/*           if (i && !(i % 8)) */
+/*             fputs ("\n         ", stdout); */
+/*           printf (" 0x%02x,", digest[i]); */
+/*         } */
+/*       printf (" 0x%02x } },\n", digest[i]); */
+
+      _gcry_md_close (hd);
+      return "does not match";
+    }
+  _gcry_md_close (hd);
+  return NULL;
+}
+
+
+static gpg_err_code_t
+selftests_sha1 (int extended, selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+  unsigned char key[128];
+  int i, j;
+
+  what = "FIPS-198a, A.1";
+  for (i=0; i < 64; i++)
+    key[i] = i;
+  errtxt = check_one (GCRY_MD_SHA1,
+                      "Sample #1", 9,
+                      key, 64,
+                      "\x4f\x4c\xa3\xd5\xd6\x8b\xa7\xcc\x0a\x12"
+                      "\x08\xc9\xc6\x1e\x9c\x5d\xa0\x40\x3c\x0a", 20, 0);
+  if (errtxt)
+    goto failed;
+
+  if (extended)
+    {
+      what = "FIPS-198a, A.2";
+      for (i=0, j=0x30; i < 20; i++)
+        key[i] = j++;
+      errtxt = check_one (GCRY_MD_SHA1,
+                          "Sample #2", 9,
+                          key, 20,
+                          "\x09\x22\xd3\x40\x5f\xaa\x3d\x19\x4f\x82"
+                          "\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24", 20, 0);
+      if (errtxt)
+        goto failed;
+
+      what = "FIPS-198a, A.3";
+      for (i=0, j=0x50; i < 100; i++)
+        key[i] = j++;
+      errtxt = check_one (GCRY_MD_SHA1,
+                          "Sample #3", 9,
+                          key, 100,
+                          "\xbc\xf4\x1e\xab\x8b\xb2\xd8\x02\xf3\xd0"
+                          "\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", 20, 0);
+      if (errtxt)
+        goto failed;
+
+      what = "FIPS-198a, A.4";
+      for (i=0, j=0x70; i < 49; i++)
+        key[i] = j++;
+      errtxt = check_one (GCRY_MD_SHA1,
+                          "Sample #4", 9,
+                          key, 49,
+                          "\x9e\xa8\x86\xef\xe2\x68\xdb\xec\xce\x42"
+                          "\x0c\x75\x24\xdf\x32\xe0\x75\x1a\x2a\x26", 20, 0);
+      if (errtxt)
+        goto failed;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("hmac", GCRY_MD_SHA1, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+
+static gpg_err_code_t
+selftests_sha224 (int extended, selftest_report_func_t report)
+{
+  static struct
+  {
+    const char * const desc;
+    const char * const data;
+    const char * const key;
+    const char expect[28];
+  } tv[] =
+    {
+      { "data-28 key-4",
+        "what do ya want for nothing?",
+        "Jefe",
+        { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf,
+          0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
+          0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00,
+          0x8f, 0xd0, 0x5e, 0x44 } },
+
+      { "data-9 key-20",
+        "Hi There",
+       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+        "\x0b\x0b\x0b\x0b",
+        { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19,
+          0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
+          0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f,
+          0x53, 0x68, 0x4b, 0x22 } },
+
+      { "data-50 key-20",
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa",
+        { 0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6,
+          0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64,
+          0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1,
+          0xec, 0x83, 0x33, 0xea } },
+
+      { "data-50 key-26",
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd",
+       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
+        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+        { 0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac,
+          0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c,
+          0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d,
+          0xe7, 0xaf, 0xec, 0x5a } },
+
+      { "data-54 key-131",
+        "Test Using Larger Than Block-Size Key - Hash Key First",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+        { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad,
+          0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
+          0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27,
+          0x3f, 0xa6, 0x87, 0x0e } },
+
+      { "data-152 key-131",
+        "This is a test using a larger than block-size key and a larger "
+        "than block-size data. The key needs to be hashed before being "
+        "used by the HMAC algorithm.",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+        { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02,
+          0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
+          0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9,
+          0xf6, 0xf5, 0x65, 0xd1 } },
+
+      { NULL }
+    };
+  const char *what;
+  const char *errtxt;
+  int tvidx;
+
+  for (tvidx=0; tv[tvidx].desc; tvidx++)
+    {
+      what = tv[tvidx].desc;
+      errtxt = check_one (GCRY_MD_SHA224,
+                          tv[tvidx].data, strlen (tv[tvidx].data),
+                          tv[tvidx].key, strlen (tv[tvidx].key),
+                          tv[tvidx].expect, DIM (tv[tvidx].expect), 0);
+      if (errtxt)
+        goto failed;
+      if (!extended)
+        break;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("hmac", GCRY_MD_SHA224, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+static gpg_err_code_t
+selftests_sha256 (int extended, selftest_report_func_t report)
+{
+  static struct
+  {
+    const char * const desc;
+    const char * const data;
+    const char * const key;
+    const char expect[32];
+  } tv[] =
+    {
+      { "data-28 key-4",
+        "what do ya want for nothing?",
+        "Jefe",
+       { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
+          0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+          0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
+          0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } },
+
+      { "data-9 key-20",
+        "Hi There",
+       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+        "\x0b\x0b\x0b\x0b",
+        { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
+          0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
+          0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
+          0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } },
+
+      { "data-50 key-20",
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa",
+        { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46,
+          0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7,
+          0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,
+          0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } },
+
+      { "data-50 key-26",
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd",
+       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
+        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+       { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e,
+          0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
+          0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07,
+          0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } },
+
+      { "data-54 key-131",
+        "Test Using Larger Than Block-Size Key - Hash Key First",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+       { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
+          0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
+          0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
+          0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } },
+
+      { "data-152 key-131",
+        "This is a test using a larger than block-size key and a larger "
+        "than block-size data. The key needs to be hashed before being "
+        "used by the HMAC algorithm.",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+       { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb,
+          0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
+          0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93,
+          0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } },
+
+      { NULL }
+    };
+  const char *what;
+  const char *errtxt;
+  int tvidx;
+
+  for (tvidx=0; tv[tvidx].desc; tvidx++)
+    {
+      what = tv[tvidx].desc;
+      errtxt = check_one (GCRY_MD_SHA256,
+                          tv[tvidx].data, strlen (tv[tvidx].data),
+                          tv[tvidx].key, strlen (tv[tvidx].key),
+                          tv[tvidx].expect, DIM (tv[tvidx].expect), 0);
+      if (errtxt)
+        goto failed;
+      if (!extended)
+        break;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("hmac", GCRY_MD_SHA256, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+static gpg_err_code_t
+selftests_sha384 (int extended, selftest_report_func_t report)
+{
+  static struct
+  {
+    const char * const desc;
+    const char * const data;
+    const char * const key;
+    const char expect[48];
+  } tv[] =
+    {
+      { "data-28 key-4",
+        "what do ya want for nothing?",
+        "Jefe",
+        { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31,
+          0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b,
+          0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47,
+          0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e,
+          0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7,
+          0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 } },
+
+      { "data-9 key-20",
+        "Hi There",
+       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+        "\x0b\x0b\x0b\x0b",
+        { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62,
+          0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f,
+          0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6,
+          0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c,
+          0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f,
+          0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 } },
+
+      { "data-50 key-20",
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa",
+        { 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a,
+          0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f,
+          0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb,
+          0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b,
+          0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9,
+          0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27 } },
+
+      { "data-50 key-26",
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd",
+       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
+        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+        { 0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85,
+          0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7,
+          0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c,
+          0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e,
+          0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79,
+          0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb } },
+
+      { "data-54 key-131",
+        "Test Using Larger Than Block-Size Key - Hash Key First",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+        { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90,
+          0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4,
+          0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
+          0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6,
+          0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82,
+          0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 } },
+
+      { "data-152 key-131",
+        "This is a test using a larger than block-size key and a larger "
+        "than block-size data. The key needs to be hashed before being "
+        "used by the HMAC algorithm.",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+        { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d,
+          0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c,
+          0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
+          0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5,
+          0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d,
+          0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e } },
+
+      { NULL }
+    };
+  const char *what;
+  const char *errtxt;
+  int tvidx;
+
+  for (tvidx=0; tv[tvidx].desc; tvidx++)
+    {
+      what = tv[tvidx].desc;
+      errtxt = check_one (GCRY_MD_SHA384,
+                          tv[tvidx].data, strlen (tv[tvidx].data),
+                          tv[tvidx].key, strlen (tv[tvidx].key),
+                          tv[tvidx].expect, DIM (tv[tvidx].expect), 0);
+      if (errtxt)
+        goto failed;
+      if (!extended)
+        break;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("hmac", GCRY_MD_SHA384, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+static gpg_err_code_t
+selftests_sha512 (int extended, selftest_report_func_t report)
+{
+  static struct
+  {
+    const char * const desc;
+    const char * const data;
+    const char * const key;
+    const char expect[64];
+  } tv[] =
+    {
+      { "data-28 key-4",
+        "what do ya want for nothing?",
+        "Jefe",
+        { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
+          0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+          0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+          0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54,
+          0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a,
+          0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd,
+          0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b,
+          0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 } },
+
+      { "data-9 key-20",
+        "Hi There",
+       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+        "\x0b\x0b\x0b\x0b",
+        { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
+          0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+          0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+          0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde,
+          0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
+          0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4,
+          0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70,
+          0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 } },
+
+      { "data-50 key-20",
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa",
+        { 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84,
+          0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
+          0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
+          0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39,
+          0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8,
+          0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07,
+          0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26,
+          0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb } },
+
+      { "data-50 key-26",
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd",
+       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
+        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+        { 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69,
+          0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7,
+          0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d,
+          0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb,
+          0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4,
+          0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63,
+          0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d,
+          0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd } },
+
+      { "data-54 key-131",
+        "Test Using Larger Than Block-Size Key - Hash Key First",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+        { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb,
+          0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4,
+          0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1,
+          0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52,
+          0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98,
+          0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52,
+          0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec,
+          0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 } },
+
+      { "data-152 key-131",
+        "This is a test using a larger than block-size key and a larger "
+        "than block-size data. The key needs to be hashed before being "
+        "used by the HMAC algorithm.",
+       "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+        { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba,
+          0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd,
+          0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86,
+          0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44,
+          0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1,
+          0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15,
+          0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60,
+          0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 } },
+
+      { NULL }
+    };
+  const char *what;
+  const char *errtxt;
+  int tvidx;
+
+  for (tvidx=0; tv[tvidx].desc; tvidx++)
+    {
+      what = tv[tvidx].desc;
+      errtxt = check_one (GCRY_MD_SHA512,
+                          tv[tvidx].data, strlen (tv[tvidx].data),
+                          tv[tvidx].key, strlen (tv[tvidx].key),
+                          tv[tvidx].expect, DIM (tv[tvidx].expect), 0);
+      if (errtxt)
+        goto failed;
+      if (!extended)
+        break;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("hmac", GCRY_MD_SHA512, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+
+/* Test for the SHA3 algorithms.  Vectors taken on 2017-07-18 from
+ * http://www.wolfgang-ehrhardt.de/hmac-sha3-testvectors.html  */
+static gpg_err_code_t
+selftests_sha3 (int hashalgo, int extended, selftest_report_func_t report)
+{
+  static struct
+  {
+    const char * const desc;
+    const char * const data;
+    const char * const key;
+    const char expect_224[28];
+    const char expect_256[32];
+    const char expect_384[48];
+    const char expect_512[64];
+    unsigned char trunc;
+  } tv[] =
+    {
+      { "data-9 key-20", /* Test 1 */
+        "Hi There",
+       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+        "\x0b\x0b\x0b\x0b",
+
+        { 0x3b, 0x16, 0x54, 0x6b, 0xbc, 0x7b, 0xe2, 0x70,
+          0x6a, 0x03, 0x1d, 0xca, 0xfd, 0x56, 0x37, 0x3d,
+          0x98, 0x84, 0x36, 0x76, 0x41, 0xd8, 0xc5, 0x9a,
+          0xf3, 0xc8, 0x60, 0xf7                          },
+        { 0xba, 0x85, 0x19, 0x23, 0x10, 0xdf, 0xfa, 0x96,
+          0xe2, 0xa3, 0xa4, 0x0e, 0x69, 0x77, 0x43, 0x51,
+          0x14, 0x0b, 0xb7, 0x18, 0x5e, 0x12, 0x02, 0xcd,
+          0xcc, 0x91, 0x75, 0x89, 0xf9, 0x5e, 0x16, 0xbb  },
+        { 0x68, 0xd2, 0xdc, 0xf7, 0xfd, 0x4d, 0xdd, 0x0a,
+          0x22, 0x40, 0xc8, 0xa4, 0x37, 0x30, 0x5f, 0x61,
+          0xfb, 0x73, 0x34, 0xcf, 0xb5, 0xd0, 0x22, 0x6e,
+          0x1b, 0xc2, 0x7d, 0xc1, 0x0a, 0x2e, 0x72, 0x3a,
+          0x20, 0xd3, 0x70, 0xb4, 0x77, 0x43, 0x13, 0x0e,
+          0x26, 0xac, 0x7e, 0x3d, 0x53, 0x28, 0x86, 0xbd  },
+        { 0xeb, 0x3f, 0xbd, 0x4b, 0x2e, 0xaa, 0xb8, 0xf5,
+          0xc5, 0x04, 0xbd, 0x3a, 0x41, 0x46, 0x5a, 0xac,
+          0xec, 0x15, 0x77, 0x0a, 0x7c, 0xab, 0xac, 0x53,
+          0x1e, 0x48, 0x2f, 0x86, 0x0b, 0x5e, 0xc7, 0xba,
+          0x47, 0xcc, 0xb2, 0xc6, 0xf2, 0xaf, 0xce, 0x8f,
+          0x88, 0xd2, 0x2b, 0x6d, 0xc6, 0x13, 0x80, 0xf2,
+          0x3a, 0x66, 0x8f, 0xd3, 0x88, 0x8b, 0xb8, 0x05,
+          0x37, 0xc0, 0xa0, 0xb8, 0x64, 0x07, 0x68, 0x9e  }
+      },
+
+      { "data-28 key-4",  /* Test 2  */
+        /* Test with a key shorter than the length of the HMAC output. */
+        "what do ya want for nothing?",
+        "Jefe",
+
+        { 0x7f, 0xdb, 0x8d, 0xd8, 0x8b, 0xd2, 0xf6, 0x0d,
+          0x1b, 0x79, 0x86, 0x34, 0xad, 0x38, 0x68, 0x11,
+          0xc2, 0xcf, 0xc8, 0x5b, 0xfa, 0xf5, 0xd5, 0x2b,
+          0xba, 0xce, 0x5e, 0x66                          },
+        { 0xc7, 0xd4, 0x07, 0x2e, 0x78, 0x88, 0x77, 0xae,
+          0x35, 0x96, 0xbb, 0xb0, 0xda, 0x73, 0xb8, 0x87,
+          0xc9, 0x17, 0x1f, 0x93, 0x09, 0x5b, 0x29, 0x4a,
+          0xe8, 0x57, 0xfb, 0xe2, 0x64, 0x5e, 0x1b, 0xa5  },
+        { 0xf1, 0x10, 0x1f, 0x8c, 0xbf, 0x97, 0x66, 0xfd,
+          0x67, 0x64, 0xd2, 0xed, 0x61, 0x90, 0x3f, 0x21,
+          0xca, 0x9b, 0x18, 0xf5, 0x7c, 0xf3, 0xe1, 0xa2,
+          0x3c, 0xa1, 0x35, 0x08, 0xa9, 0x32, 0x43, 0xce,
+          0x48, 0xc0, 0x45, 0xdc, 0x00, 0x7f, 0x26, 0xa2,
+          0x1b, 0x3f, 0x5e, 0x0e, 0x9d, 0xf4, 0xc2, 0x0a  },
+        { 0x5a, 0x4b, 0xfe, 0xab, 0x61, 0x66, 0x42, 0x7c,
+          0x7a, 0x36, 0x47, 0xb7, 0x47, 0x29, 0x2b, 0x83,
+          0x84, 0x53, 0x7c, 0xdb, 0x89, 0xaf, 0xb3, 0xbf,
+          0x56, 0x65, 0xe4, 0xc5, 0xe7, 0x09, 0x35, 0x0b,
+          0x28, 0x7b, 0xae, 0xc9, 0x21, 0xfd, 0x7c, 0xa0,
+          0xee, 0x7a, 0x0c, 0x31, 0xd0, 0x22, 0xa9, 0x5e,
+          0x1f, 0xc9, 0x2b, 0xa9, 0xd7, 0x7d, 0xf8, 0x83,
+          0x96, 0x02, 0x75, 0xbe, 0xb4, 0xe6, 0x20, 0x24  }
+      },
+
+      { "data-50 key-20",  /* Test 3 */
+        /* Test with a combined length of key and data that is larger
+         * than 64 bytes (= block-size of SHA-224 and SHA-256).  */
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+        "\xdd\xdd",
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa",
+
+        { 0x67, 0x6c, 0xfc, 0x7d, 0x16, 0x15, 0x36, 0x38,
+          0x78, 0x03, 0x90, 0x69, 0x2b, 0xe1, 0x42, 0xd2,
+          0xdf, 0x7c, 0xe9, 0x24, 0xb9, 0x09, 0xc0, 0xc0,
+          0x8d, 0xbf, 0xdc, 0x1a  },
+        { 0x84, 0xec, 0x79, 0x12, 0x4a, 0x27, 0x10, 0x78,
+          0x65, 0xce, 0xdd, 0x8b, 0xd8, 0x2d, 0xa9, 0x96,
+          0x5e, 0x5e, 0xd8, 0xc3, 0x7b, 0x0a, 0xc9, 0x80,
+          0x05, 0xa7, 0xf3, 0x9e, 0xd5, 0x8a, 0x42, 0x07  },
+        { 0x27, 0x5c, 0xd0, 0xe6, 0x61, 0xbb, 0x8b, 0x15,
+          0x1c, 0x64, 0xd2, 0x88, 0xf1, 0xf7, 0x82, 0xfb,
+          0x91, 0xa8, 0xab, 0xd5, 0x68, 0x58, 0xd7, 0x2b,
+          0xab, 0xb2, 0xd4, 0x76, 0xf0, 0x45, 0x83, 0x73,
+          0xb4, 0x1b, 0x6a, 0xb5, 0xbf, 0x17, 0x4b, 0xec,
+          0x42, 0x2e, 0x53, 0xfc, 0x31, 0x35, 0xac, 0x6e  },
+        { 0x30, 0x9e, 0x99, 0xf9, 0xec, 0x07, 0x5e, 0xc6,
+          0xc6, 0xd4, 0x75, 0xed, 0xa1, 0x18, 0x06, 0x87,
+          0xfc, 0xf1, 0x53, 0x11, 0x95, 0x80, 0x2a, 0x99,
+          0xb5, 0x67, 0x74, 0x49, 0xa8, 0x62, 0x51, 0x82,
+          0x85, 0x1c, 0xb3, 0x32, 0xaf, 0xb6, 0xa8, 0x9c,
+          0x41, 0x13, 0x25, 0xfb, 0xcb, 0xcd, 0x42, 0xaf,
+          0xcb, 0x7b, 0x6e, 0x5a, 0xab, 0x7e, 0xa4, 0x2c,
+          0x66, 0x0f, 0x97, 0xfd, 0x85, 0x84, 0xbf, 0x03  }
+      },
+
+      { "data-50 key-25",  /* Test 4 */
+        /* Test with a combined length of key and data that is larger
+         * than 64 bytes (= block-size of SHA-224 and SHA-256).  */
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+        "\xcd\xcd",
+        "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
+        "\x11\x12\x13\x14\x15\x16\x17\x18\x19",
+
+        { 0xa9, 0xd7, 0x68, 0x5a, 0x19, 0xc4, 0xe0, 0xdb,
+          0xd9, 0xdf, 0x25, 0x56, 0xcc, 0x8a, 0x7d, 0x2a,
+          0x77, 0x33, 0xb6, 0x76, 0x25, 0xce, 0x59, 0x4c,
+          0x78, 0x27, 0x0e, 0xeb   },
+        { 0x57, 0x36, 0x6a, 0x45, 0xe2, 0x30, 0x53, 0x21,
+          0xa4, 0xbc, 0x5a, 0xa5, 0xfe, 0x2e, 0xf8, 0xa9,
+          0x21, 0xf6, 0xaf, 0x82, 0x73, 0xd7, 0xfe, 0x7b,
+          0xe6, 0xcf, 0xed, 0xb3, 0xf0, 0xae, 0xa6, 0xd7  },
+        { 0x3a, 0x5d, 0x7a, 0x87, 0x97, 0x02, 0xc0, 0x86,
+          0xbc, 0x96, 0xd1, 0xdd, 0x8a, 0xa1, 0x5d, 0x9c,
+          0x46, 0x44, 0x6b, 0x95, 0x52, 0x13, 0x11, 0xc6,
+          0x06, 0xfd, 0xc4, 0xe3, 0x08, 0xf4, 0xb9, 0x84,
+          0xda, 0x2d, 0x0f, 0x94, 0x49, 0xb3, 0xba, 0x84,
+          0x25, 0xec, 0x7f, 0xb8, 0xc3, 0x1b, 0xc1, 0x36  },
+        { 0xb2, 0x7e, 0xab, 0x1d, 0x6e, 0x8d, 0x87, 0x46,
+          0x1c, 0x29, 0xf7, 0xf5, 0x73, 0x9d, 0xd5, 0x8e,
+          0x98, 0xaa, 0x35, 0xf8, 0xe8, 0x23, 0xad, 0x38,
+          0xc5, 0x49, 0x2a, 0x20, 0x88, 0xfa, 0x02, 0x81,
+          0x99, 0x3b, 0xbf, 0xff, 0x9a, 0x0e, 0x9c, 0x6b,
+          0xf1, 0x21, 0xae, 0x9e, 0xc9, 0xbb, 0x09, 0xd8,
+          0x4a, 0x5e, 0xba, 0xc8, 0x17, 0x18, 0x2e, 0xa9,
+          0x74, 0x67, 0x3f, 0xb1, 0x33, 0xca, 0x0d, 0x1d  }
+      },
+
+      { "data-20 key-20 trunc",  /* Test 5 */
+        /* Test with a truncation of output to 128 bits.  */
+        "Test With Truncation",
+        "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+        "\x0c\x0c\x0c\x0c",
+
+        { 0x49, 0xfd, 0xd3, 0xab, 0xd0, 0x05, 0xeb, 0xb8,
+          0xae, 0x63, 0xfe, 0xa9, 0x46, 0xd1, 0x88, 0x3c  },
+        { 0x6e, 0x02, 0xc6, 0x45, 0x37, 0xfb, 0x11, 0x80,
+          0x57, 0xab, 0xb7, 0xfb, 0x66, 0xa2, 0x3b, 0x3c  },
+        { 0x47, 0xc5, 0x1a, 0xce, 0x1f, 0xfa, 0xcf, 0xfd,
+          0x74, 0x94, 0x72, 0x46, 0x82, 0x61, 0x57, 0x83  },
+        { 0x0f, 0xa7, 0x47, 0x59, 0x48, 0xf4, 0x3f, 0x48,
+          0xca, 0x05, 0x16, 0x67, 0x1e, 0x18, 0x97, 0x8c  },
+        16
+      },
+
+      { "data-54 key-131",  /* Test 6 */
+        /* Test with a key larger than 128 bytes (= block-size of
+         * SHA-384 and SHA-512).  */
+        "Test Using Larger Than Block-Size Key - Hash Key First",
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+
+        { 0xb4, 0xa1, 0xf0, 0x4c, 0x00, 0x28, 0x7a, 0x9b,
+          0x7f, 0x60, 0x75, 0xb3, 0x13, 0xd2, 0x79, 0xb8,
+          0x33, 0xbc, 0x8f, 0x75, 0x12, 0x43, 0x52, 0xd0,
+          0x5f, 0xb9, 0x99, 0x5f  },
+        { 0xed, 0x73, 0xa3, 0x74, 0xb9, 0x6c, 0x00, 0x52,
+          0x35, 0xf9, 0x48, 0x03, 0x2f, 0x09, 0x67, 0x4a,
+          0x58, 0xc0, 0xce, 0x55, 0x5c, 0xfc, 0x1f, 0x22,
+          0x3b, 0x02, 0x35, 0x65, 0x60, 0x31, 0x2c, 0x3b  },
+        { 0x0f, 0xc1, 0x95, 0x13, 0xbf, 0x6b, 0xd8, 0x78,
+          0x03, 0x70, 0x16, 0x70, 0x6a, 0x0e, 0x57, 0xbc,
+          0x52, 0x81, 0x39, 0x83, 0x6b, 0x9a, 0x42, 0xc3,
+          0xd4, 0x19, 0xe4, 0x98, 0xe0, 0xe1, 0xfb, 0x96,
+          0x16, 0xfd, 0x66, 0x91, 0x38, 0xd3, 0x3a, 0x11,
+          0x05, 0xe0, 0x7c, 0x72, 0xb6, 0x95, 0x3b, 0xcc  },
+        { 0x00, 0xf7, 0x51, 0xa9, 0xe5, 0x06, 0x95, 0xb0,
+          0x90, 0xed, 0x69, 0x11, 0xa4, 0xb6, 0x55, 0x24,
+          0x95, 0x1c, 0xdc, 0x15, 0xa7, 0x3a, 0x5d, 0x58,
+          0xbb, 0x55, 0x21, 0x5e, 0xa2, 0xcd, 0x83, 0x9a,
+          0xc7, 0x9d, 0x2b, 0x44, 0xa3, 0x9b, 0xaf, 0xab,
+          0x27, 0xe8, 0x3f, 0xde, 0x9e, 0x11, 0xf6, 0x34,
+          0x0b, 0x11, 0xd9, 0x91, 0xb1, 0xb9, 0x1b, 0xf2,
+          0xee, 0xe7, 0xfc, 0x87, 0x24, 0x26, 0xc3, 0xa4  }
+      },
+
+      { "data-54 key-147",  /* Test 6a */
+        /* Test with a key larger than 144 bytes (= block-size of
+         * SHA3-224).  */
+        "Test Using Larger Than Block-Size Key - Hash Key First",
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+
+        { 0xb9, 0x6d, 0x73, 0x0c, 0x14, 0x8c, 0x2d, 0xaa,
+          0xd8, 0x64, 0x9d, 0x83, 0xde, 0xfa, 0xa3, 0x71,
+          0x97, 0x38, 0xd3, 0x47, 0x75, 0x39, 0x7b, 0x75,
+          0x71, 0xc3, 0x85, 0x15  },
+        { 0xa6, 0x07, 0x2f, 0x86, 0xde, 0x52, 0xb3, 0x8b,
+          0xb3, 0x49, 0xfe, 0x84, 0xcd, 0x6d, 0x97, 0xfb,
+          0x6a, 0x37, 0xc4, 0xc0, 0xf6, 0x2a, 0xae, 0x93,
+          0x98, 0x11, 0x93, 0xa7, 0x22, 0x9d, 0x34, 0x67  },
+        { 0x71, 0x3d, 0xff, 0x03, 0x02, 0xc8, 0x50, 0x86,
+          0xec, 0x5a, 0xd0, 0x76, 0x8d, 0xd6, 0x5a, 0x13,
+          0xdd, 0xd7, 0x90, 0x68, 0xd8, 0xd4, 0xc6, 0x21,
+          0x2b, 0x71, 0x2e, 0x41, 0x64, 0x94, 0x49, 0x11,
+          0x14, 0x80, 0x23, 0x00, 0x44, 0x18, 0x5a, 0x99,
+          0x10, 0x3e, 0xd8, 0x20, 0x04, 0xdd, 0xbf, 0xcc  },
+        { 0xb1, 0x48, 0x35, 0xc8, 0x19, 0xa2, 0x90, 0xef,
+          0xb0, 0x10, 0xac, 0xe6, 0xd8, 0x56, 0x8d, 0xc6,
+          0xb8, 0x4d, 0xe6, 0x0b, 0xc4, 0x9b, 0x00, 0x4c,
+          0x3b, 0x13, 0xed, 0xa7, 0x63, 0x58, 0x94, 0x51,
+          0xe5, 0xdd, 0x74, 0x29, 0x28, 0x84, 0xd1, 0xbd,
+          0xce, 0x64, 0xe6, 0xb9, 0x19, 0xdd, 0x61, 0xdc,
+          0x9c, 0x56, 0xa2, 0x82, 0xa8, 0x1c, 0x0b, 0xd1,
+          0x4f, 0x1f, 0x36, 0x5b, 0x49, 0xb8, 0x3a, 0x5b  }
+      },
+
+      { "data-152 key-131",  /* Test 7  */
+        /* Test with a key and data that is larger than 128 bytes (=
+         * block-size of SHA-384 and SHA-512).  */
+        "This is a test using a larger than block-size key and a larger "
+        "than block-size data. The key needs to be hashed before being "
+        "used by the HMAC algorithm.",
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+
+        { 0x05, 0xd8, 0xcd, 0x6d, 0x00, 0xfa, 0xea, 0x8d,
+          0x1e, 0xb6, 0x8a, 0xde, 0x28, 0x73, 0x0b, 0xbd,
+          0x3c, 0xba, 0xb6, 0x92, 0x9f, 0x0a, 0x08, 0x6b,
+          0x29, 0xcd, 0x62, 0xa0  },
+        { 0x65, 0xc5, 0xb0, 0x6d, 0x4c, 0x3d, 0xe3, 0x2a,
+          0x7a, 0xef, 0x87, 0x63, 0x26, 0x1e, 0x49, 0xad,
+          0xb6, 0xe2, 0x29, 0x3e, 0xc8, 0xe7, 0xc6, 0x1e,
+          0x8d, 0xe6, 0x17, 0x01, 0xfc, 0x63, 0xe1, 0x23  },
+        { 0x02, 0x6f, 0xdf, 0x6b, 0x50, 0x74, 0x1e, 0x37,
+          0x38, 0x99, 0xc9, 0xf7, 0xd5, 0x40, 0x6d, 0x4e,
+          0xb0, 0x9f, 0xc6, 0x66, 0x56, 0x36, 0xfc, 0x1a,
+          0x53, 0x00, 0x29, 0xdd, 0xf5, 0xcf, 0x3c, 0xa5,
+          0xa9, 0x00, 0xed, 0xce, 0x01, 0xf5, 0xf6, 0x1e,
+          0x2f, 0x40, 0x8c, 0xdf, 0x2f, 0xd3, 0xe7, 0xe8  },
+        { 0x38, 0xa4, 0x56, 0xa0, 0x04, 0xbd, 0x10, 0xd3,
+          0x2c, 0x9a, 0xb8, 0x33, 0x66, 0x84, 0x11, 0x28,
+          0x62, 0xc3, 0xdb, 0x61, 0xad, 0xcc, 0xa3, 0x18,
+          0x29, 0x35, 0x5e, 0xaf, 0x46, 0xfd, 0x5c, 0x73,
+          0xd0, 0x6a, 0x1f, 0x0d, 0x13, 0xfe, 0xc9, 0xa6,
+          0x52, 0xfb, 0x38, 0x11, 0xb5, 0x77, 0xb1, 0xb1,
+          0xd1, 0xb9, 0x78, 0x9f, 0x97, 0xae, 0x5b, 0x83,
+          0xc6, 0xf4, 0x4d, 0xfc, 0xf1, 0xd6, 0x7e, 0xba  }
+      },
+
+      { "data-152 key-147",  /* Test 7a  */
+        /* Test with a key larger than 144 bytes (= block-size of
+         * SHA3-224). */
+        "This is a test using a larger than block-size key and a larger "
+        "than block-size data. The key needs to be hashed before being "
+        "used by the HMAC algorithm.",
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+        "\xaa\xaa\xaa",
+
+        { 0xc7, 0x9c, 0x9b, 0x09, 0x34, 0x24, 0xe5, 0x88,
+          0xa9, 0x87, 0x8b, 0xbc, 0xb0, 0x89, 0xe0, 0x18,
+          0x27, 0x00, 0x96, 0xe9, 0xb4, 0xb1, 0xa9, 0xe8,
+          0x22, 0x0c, 0x86, 0x6a  },
+        { 0xe6, 0xa3, 0x6d, 0x9b, 0x91, 0x5f, 0x86, 0xa0,
+          0x93, 0xca, 0xc7, 0xd1, 0x10, 0xe9, 0xe0, 0x4c,
+          0xf1, 0xd6, 0x10, 0x0d, 0x30, 0x47, 0x55, 0x09,
+          0xc2, 0x47, 0x5f, 0x57, 0x1b, 0x75, 0x8b, 0x5a  },
+        { 0xca, 0xd1, 0x8a, 0x8f, 0xf6, 0xc4, 0xcc, 0x3a,
+          0xd4, 0x87, 0xb9, 0x5f, 0x97, 0x69, 0xe9, 0xb6,
+          0x1c, 0x06, 0x2a, 0xef, 0xd6, 0x95, 0x25, 0x69,
+          0xe6, 0xe6, 0x42, 0x18, 0x97, 0x05, 0x4c, 0xfc,
+          0x70, 0xb5, 0xfd, 0xc6, 0x60, 0x5c, 0x18, 0x45,
+          0x71, 0x12, 0xfc, 0x6a, 0xaa, 0xd4, 0x55, 0x85  },
+        { 0xdc, 0x03, 0x0e, 0xe7, 0x88, 0x70, 0x34, 0xf3,
+          0x2c, 0xf4, 0x02, 0xdf, 0x34, 0x62, 0x2f, 0x31,
+          0x1f, 0x3e, 0x6c, 0xf0, 0x48, 0x60, 0xc6, 0xbb,
+          0xd7, 0xfa, 0x48, 0x86, 0x74, 0x78, 0x2b, 0x46,
+          0x59, 0xfd, 0xbd, 0xf3, 0xfd, 0x87, 0x78, 0x52,
+          0x88, 0x5c, 0xfe, 0x6e, 0x22, 0x18, 0x5f, 0xe7,
+          0xb2, 0xee, 0x95, 0x20, 0x43, 0x62, 0x9b, 0xc9,
+          0xd5, 0xf3, 0x29, 0x8a, 0x41, 0xd0, 0x2c, 0x66  }
+      }/*,*/
+
+      /* Our API does not allow to specify a bit count and thus we
+       * can't use the following test.  */
+      /* { "data-5bit key-4",  /\* Test 8  *\/ */
+      /*   /\* Test with data bit size no multiple of 8, the data bits are */
+      /*    * '11001' from the NIST example using SHA-3 order (= 5 bits */
+      /*    * from LSB hex byte 13 or 5 bits from MSB hex byte c8).  *\/ */
+      /*   "\xc8", */
+      /*   "Jefe", */
+
+      /*   { 0x5f, 0x8c, 0x0e, 0xa7, 0xfa, 0xfe, 0xcd, 0x0c, */
+      /*     0x34, 0x63, 0xaa, 0xd0, 0x97, 0x42, 0xce, 0xce, */
+      /*     0xb1, 0x42, 0xfe, 0x0a, 0xb6, 0xf4, 0x53, 0x94, */
+      /*     0x38, 0xc5, 0x9d, 0xe8  }, */
+      /*   { 0xec, 0x82, 0x22, 0x77, 0x3f, 0xac, 0x68, 0xb3, */
+      /*     0xd3, 0xdc, 0xb1, 0x82, 0xae, 0xc8, 0xb0, 0x50, */
+      /*     0x7a, 0xce, 0x44, 0x48, 0xd2, 0x0a, 0x11, 0x47, */
+      /*     0xe6, 0x82, 0x11, 0x8d, 0xa4, 0xe3, 0xf4, 0x4c  }, */
+      /*   { 0x21, 0xfb, 0xd3, 0xbf, 0x3e, 0xbb, 0xa3, 0xcf, */
+      /*     0xc9, 0xef, 0x64, 0xc0, 0x59, 0x1c, 0x92, 0xc5, */
+      /*     0xac, 0xb2, 0x65, 0xe9, 0x2d, 0x87, 0x61, 0xd1, */
+      /*     0xf9, 0x1a, 0x52, 0xa1, 0x03, 0xa6, 0xc7, 0x96, */
+      /*     0x94, 0xcf, 0xd6, 0x7a, 0x9a, 0x2a, 0xc1, 0x32, */
+      /*     0x4f, 0x02, 0xfe, 0xa6, 0x3b, 0x81, 0xef, 0xfc  }, */
+      /*   { 0x27, 0xf9, 0x38, 0x8c, 0x15, 0x67, 0xef, 0x4e, */
+      /*     0xf2, 0x00, 0x60, 0x2a, 0x6c, 0xf8, 0x71, 0xd6, */
+      /*     0x8a, 0x6f, 0xb0, 0x48, 0xd4, 0x73, 0x7a, 0xc4, */
+      /*     0x41, 0x8a, 0x2f, 0x02, 0x12, 0x89, 0xd1, 0x3d, */
+      /*     0x1f, 0xd1, 0x12, 0x0f, 0xec, 0xb9, 0xcf, 0x96, */
+      /*     0x4c, 0x5b, 0x11, 0x7a, 0xb5, 0xb1, 0x1c, 0x61, */
+      /*     0x4b, 0x2d, 0xa3, 0x9d, 0xad, 0xd5, 0x1f, 0x2f, */
+      /*     0x5e, 0x22, 0xaa, 0xcc, 0xec, 0x7d, 0x57, 0x6e  } */
+      /* } */
+
+    };
+  const char *what;
+  const char *errtxt;
+  int tvidx;
+  const char *expect;
+  int nexpect;
+
+  for (tvidx=0; tvidx < DIM(tv); tvidx++)
+    {
+      what = tv[tvidx].desc;
+      if (hashalgo == GCRY_MD_SHA3_224)
+        {
+          expect = tv[tvidx].expect_224;
+          nexpect = DIM (tv[tvidx].expect_224);
+        }
+      else if (hashalgo == GCRY_MD_SHA3_256)
+        {
+          expect = tv[tvidx].expect_256;
+          nexpect = DIM (tv[tvidx].expect_256);
+        }
+      else if (hashalgo == GCRY_MD_SHA3_384)
+        {
+          expect = tv[tvidx].expect_384;
+          nexpect = DIM (tv[tvidx].expect_384);
+        }
+      else if (hashalgo == GCRY_MD_SHA3_512)
+        {
+          expect = tv[tvidx].expect_512;
+          nexpect = DIM (tv[tvidx].expect_512);
+        }
+      else
+        BUG();
+
+      if (tv[tvidx].trunc && tv[tvidx].trunc < nexpect)
+        nexpect = tv[tvidx].trunc;
+
+      errtxt = check_one (hashalgo,
+                          tv[tvidx].data, strlen (tv[tvidx].data),
+                          tv[tvidx].key, strlen (tv[tvidx].key),
+                          expect, nexpect, !!tv[tvidx].trunc);
+      if (errtxt)
+        goto failed;
+      if (!extended)
+        break;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("hmac", hashalgo, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+static gpg_err_code_t
+hmac_selftest (int algo, int extended, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_MAC_HMAC_SHA1:
+      ec = selftests_sha1 (extended, report);
+      break;
+    case GCRY_MAC_HMAC_SHA224:
+      ec = selftests_sha224 (extended, report);
+      break;
+    case GCRY_MAC_HMAC_SHA256:
+      ec = selftests_sha256 (extended, report);
+      break;
+    case GCRY_MAC_HMAC_SHA384:
+      ec = selftests_sha384 (extended, report);
+      break;
+    case GCRY_MAC_HMAC_SHA512:
+      ec = selftests_sha512 (extended, report);
+      break;
+
+    case GCRY_MAC_HMAC_SHA3_224:
+    case GCRY_MAC_HMAC_SHA3_256:
+    case GCRY_MAC_HMAC_SHA3_384:
+    case GCRY_MAC_HMAC_SHA3_512:
+      {
+        int md_algo = map_mac_algo_to_md (algo);
+        ec = selftests_sha3 (md_algo, extended, report);
+      }
+      break;
+
+    default:
+      ec = GPG_ERR_MAC_ALGO;
+      break;
+    }
+
+  return ec;
+}
+
+
 static const gcry_mac_spec_ops_t hmac_ops = {
   hmac_open,
   hmac_close,
@@ -209,109 +1306,166 @@ static const gcry_mac_spec_ops_t hmac_ops = {
   hmac_read,
   hmac_verify,
   hmac_get_maclen,
-  hmac_get_keylen
+  hmac_get_keylen,
+  NULL,
+  hmac_selftest
 };
 
 
 #if USE_SHA1
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1 = {
   GCRY_MAC_HMAC_SHA1, {0, 1}, "HMAC_SHA1",
   &hmac_ops
 };
 #endif
 #if USE_SHA256
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256 = {
   GCRY_MAC_HMAC_SHA256, {0, 1}, "HMAC_SHA256",
   &hmac_ops
 };
 
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224 = {
   GCRY_MAC_HMAC_SHA224, {0, 1}, "HMAC_SHA224",
   &hmac_ops
 };
 #endif
 #if USE_SHA512
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512 = {
   GCRY_MAC_HMAC_SHA512, {0, 1}, "HMAC_SHA512",
   &hmac_ops
 };
 
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384 = {
   GCRY_MAC_HMAC_SHA384, {0, 1}, "HMAC_SHA384",
   &hmac_ops
 };
+
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256 = {
+  GCRY_MAC_HMAC_SHA512_256, {0, 1}, "HMAC_SHA512_256",
+  &hmac_ops
+};
+
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224 = {
+  GCRY_MAC_HMAC_SHA512_224, {0, 1}, "HMAC_SHA512_224",
+  &hmac_ops
+};
+
 #endif
 #if USE_SHA3
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224 = {
   GCRY_MAC_HMAC_SHA3_224, {0, 1}, "HMAC_SHA3_224",
   &hmac_ops
 };
 
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256 = {
   GCRY_MAC_HMAC_SHA3_256, {0, 1}, "HMAC_SHA3_256",
   &hmac_ops
 };
 
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384 = {
   GCRY_MAC_HMAC_SHA3_384, {0, 1}, "HMAC_SHA3_384",
   &hmac_ops
 };
 
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512 = {
   GCRY_MAC_HMAC_SHA3_512, {0, 1}, "HMAC_SHA3_512",
   &hmac_ops
 };
 #endif
-#ifdef USE_GOST_R_3411_94
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94 = {
+#if USE_GOST_R_3411_94
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94 = {
   GCRY_MAC_HMAC_GOSTR3411_94, {0, 0}, "HMAC_GOSTR3411_94",
   &hmac_ops
 };
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp = {
+  GCRY_MAC_HMAC_GOSTR3411_CP, {0, 0}, "HMAC_GOSTR3411_CP",
+  &hmac_ops
+};
 #endif
-#ifdef USE_GOST_R_3411_12
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256 = {
+#if USE_GOST_R_3411_12
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256 = {
   GCRY_MAC_HMAC_STRIBOG256, {0, 0}, "HMAC_STRIBOG256",
   &hmac_ops
 };
 
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512 = {
   GCRY_MAC_HMAC_STRIBOG512, {0, 0}, "HMAC_STRIBOG512",
   &hmac_ops
 };
 #endif
 #if USE_WHIRLPOOL
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool = {
   GCRY_MAC_HMAC_WHIRLPOOL, {0, 0}, "HMAC_WHIRLPOOL",
   &hmac_ops
 };
 #endif
 #if USE_RMD160
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160 = {
   GCRY_MAC_HMAC_RMD160, {0, 0}, "HMAC_RIPEMD160",
   &hmac_ops
 };
 #endif
 #if USE_TIGER
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1 = {
   GCRY_MAC_HMAC_TIGER1, {0, 0}, "HMAC_TIGER",
   &hmac_ops
 };
 #endif
 #if USE_MD5
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5 = {
   GCRY_MAC_HMAC_MD5, {0, 0}, "HMAC_MD5",
   &hmac_ops
 };
 #endif
 #if USE_MD4
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4 = {
   GCRY_MAC_HMAC_MD4, {0, 0}, "HMAC_MD4",
   &hmac_ops
 };
 #endif
 #if USE_MD2
-gcry_mac_spec_t _gcry_mac_type_spec_hmac_md2 = {
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md2 = {
   GCRY_MAC_HMAC_MD2, {0, 0}, "HMAC_MD2",
   &hmac_ops
 };
 #endif
+#if USE_BLAKE2
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512 = {
+  GCRY_MAC_HMAC_BLAKE2B_512, {0, 0}, "HMAC_BLAKE2B_512",
+  &hmac_ops
+};
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384 = {
+  GCRY_MAC_HMAC_BLAKE2B_384, {0, 0}, "HMAC_BLAKE2B_384",
+  &hmac_ops
+};
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256 = {
+  GCRY_MAC_HMAC_BLAKE2B_256, {0, 0}, "HMAC_BLAKE2B_256",
+  &hmac_ops
+};
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160 = {
+  GCRY_MAC_HMAC_BLAKE2B_160, {0, 0}, "HMAC_BLAKE2B_160",
+  &hmac_ops
+};
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256 = {
+  GCRY_MAC_HMAC_BLAKE2S_256, {0, 0}, "HMAC_BLAKE2S_256",
+  &hmac_ops
+};
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224 = {
+  GCRY_MAC_HMAC_BLAKE2S_224, {0, 0}, "HMAC_BLAKE2S_224",
+  &hmac_ops
+};
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160 = {
+  GCRY_MAC_HMAC_BLAKE2S_160, {0, 0}, "HMAC_BLAKE2S_160",
+  &hmac_ops
+};
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128 = {
+  GCRY_MAC_HMAC_BLAKE2S_128, {0, 0}, "HMAC_BLAKE2S_128",
+  &hmac_ops
+};
+#endif
+#if USE_SM3
+const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3 = {
+  GCRY_MAC_HMAC_SM3, {0, 0}, "HMAC_SM3",
+  &hmac_ops
+};
+#endif
index 2beb284..0199815 100644 (file)
@@ -20,6 +20,8 @@
 #include <config.h>
 
 #include "g10lib.h"
+#include "cipher-proto.h"
+#include "gost.h"
 
 
 /* The data object used to hold a handle to an encryption object.  */
@@ -37,8 +39,8 @@ struct poly1305mac_context_s;
 
 
 /* Magic values for the context structure.  */
-#define CTX_MAGIC_NORMAL 0x59d9b8af
-#define CTX_MAGIC_SECURE 0x12c27cd0
+#define CTX_MAC_MAGIC_NORMAL 0x59d9b8af
+#define CTX_MAC_MAGIC_SECURE 0x12c27cd0
 
 
 /* MAC module functions. */
@@ -63,6 +65,9 @@ typedef gcry_err_code_t (*gcry_mac_verify_func_t)(gcry_mac_hd_t h,
 typedef unsigned int (*gcry_mac_get_maclen_func_t)(int algo);
 typedef unsigned int (*gcry_mac_get_keylen_func_t)(int algo);
 
+/* The type used to convey additional information to a MAC.  */
+typedef gpg_err_code_t (*gcry_mac_set_extra_info_t)
+     (gcry_mac_hd_t h, int what, const void *buffer, size_t buflen);
 
 typedef struct gcry_mac_spec_ops
 {
@@ -76,6 +81,8 @@ typedef struct gcry_mac_spec_ops
   gcry_mac_verify_func_t verify;
   gcry_mac_get_maclen_func_t get_maclen;
   gcry_mac_get_keylen_func_t get_keylen;
+  gcry_mac_set_extra_info_t set_extra_info;
+  selftest_func_t selftest;
 } gcry_mac_spec_ops_t;
 
 
@@ -91,7 +98,6 @@ typedef struct gcry_mac_spec
   const gcry_mac_spec_ops_t *ops;
 } gcry_mac_spec_t;
 
-
 /* The handle structure.  */
 struct gcry_mac_handle
 {
@@ -116,6 +122,13 @@ struct gcry_mac_handle
     struct {
       struct poly1305mac_context_s *ctx;
     } poly1305mac;
+    struct {
+      GOST28147_context ctx;
+      u32 n1, n2;
+      unsigned int unused;
+      unsigned int count;
+      unsigned char lastiv[8]; /* IMIT blocksize */
+    } imit;
   } u;
 };
 
@@ -124,117 +137,139 @@ struct gcry_mac_handle
  * The HMAC algorithm specifications (mac-hmac.c).
  */
 #if USE_SHA1
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1;
 #endif
 #if USE_SHA256
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256;
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224;
 #endif
 #if USE_SHA512
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512;
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256;
 #endif
 #if USE_SHA3
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224;
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256;
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384;
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512;
 #endif
-#ifdef USE_GOST_R_3411_94
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94;
+#if USE_GOST_R_3411_94
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp;
 #endif
-#ifdef USE_GOST_R_3411_12
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256;
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512;
+#if USE_GOST_R_3411_12
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512;
 #endif
 #if USE_WHIRLPOOL
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool;
 #endif
 #if USE_RMD160
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160;
 #endif
 #if USE_TIGER
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1;
 #endif
 #if USE_MD5
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5;
 #endif
 #if USE_MD4
-extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4;
+#endif
+#if USE_BLAKE2
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128;
+#endif
+#if USE_SM3
+extern const gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3;
 #endif
 
 /*
  * The CMAC algorithm specifications (mac-cmac.c).
  */
 #if USE_BLOWFISH
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish;
 #endif
 #if USE_DES
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes;
 #endif
 #if USE_CAST5
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5;
 #endif
 #if USE_AES
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes;
 #endif
 #if USE_TWOFISH
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish;
 #endif
 #if USE_SERPENT
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent;
 #endif
 #if USE_RFC2268
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268;
 #endif
 #if USE_SEED
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed;
 #endif
 #if USE_CAMELLIA
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia;
 #endif
-#ifdef USE_IDEA
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea;
+#if USE_IDEA
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea;
 #endif
 #if USE_GOST28147
-extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147;
+#endif
+#if USE_GOST28147
+extern const gcry_mac_spec_t _gcry_mac_type_spec_gost28147_imit;
+#endif
+#if USE_SM4
+extern const gcry_mac_spec_t _gcry_mac_type_spec_cmac_sm4;
 #endif
 
 /*
  * The GMAC algorithm specifications (mac-gmac.c).
  */
 #if USE_AES
-extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes;
 #endif
 #if USE_TWOFISH
-extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish;
 #endif
 #if USE_SERPENT
-extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent;
 #endif
 #if USE_SEED
-extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed;
 #endif
 #if USE_CAMELLIA
-extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia;
 #endif
 
 /*
  * The Poly1305 MAC algorithm specifications (mac-poly1305.c).
  */
-extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac;
 #if USE_AES
-extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes;
 #endif
 #if USE_CAMELLIA
-extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia;
 #endif
 #if USE_TWOFISH
-extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish;
 #endif
 #if USE_SERPENT
-extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent;
 #endif
 #if USE_SEED
-extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed;
 #endif
index b80f87d..3abc777 100644 (file)
@@ -45,7 +45,7 @@ static gcry_err_code_t
 poly1305mac_open (gcry_mac_hd_t h)
 {
   struct poly1305mac_context_s *mac_ctx;
-  int secure = (h->magic == CTX_MAGIC_SECURE);
+  int secure = (h->magic == CTX_MAC_MAGIC_SECURE);
   unsigned int flags = (secure ? GCRY_CIPHER_SECURE : 0);
   gcry_err_code_t err;
   int cipher_algo;
@@ -322,40 +322,42 @@ static gcry_mac_spec_ops_t poly1305mac_ops = {
   poly1305mac_read,
   poly1305mac_verify,
   poly1305mac_get_maclen,
-  poly1305mac_get_keylen
+  poly1305mac_get_keylen,
+  NULL,
+  NULL,
 };
 
 
-gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac = {
+const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac = {
   GCRY_MAC_POLY1305, {0, 0}, "POLY1305",
   &poly1305mac_ops
 };
 #if USE_AES
-gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes = {
+const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes = {
   GCRY_MAC_POLY1305_AES, {0, 0}, "POLY1305_AES",
   &poly1305mac_ops
 };
 #endif
 #if USE_CAMELLIA
-gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia = {
+const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia = {
   GCRY_MAC_POLY1305_CAMELLIA, {0, 0}, "POLY1305_CAMELLIA",
   &poly1305mac_ops
 };
 #endif
 #if USE_TWOFISH
-gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish = {
+const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish = {
   GCRY_MAC_POLY1305_TWOFISH, {0, 0}, "POLY1305_TWOFISH",
   &poly1305mac_ops
 };
 #endif
 #if USE_SERPENT
-gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent = {
+const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent = {
   GCRY_MAC_POLY1305_SERPENT, {0, 0}, "POLY1305_SERPENT",
   &poly1305mac_ops
 };
 #endif
 #if USE_SEED
-gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed = {
+const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed = {
   GCRY_MAC_POLY1305_SEED, {0, 0}, "POLY1305_SEED",
   &poly1305mac_ops
 };
index 46be7b7..ba1eb30 100644 (file)
@@ -29,7 +29,7 @@
 
 /* This is the list of the digest implementations included in
    libgcrypt.  */
-static gcry_mac_spec_t *mac_list[] = {
+static const gcry_mac_spec_t * const mac_list[] = {
 #if USE_SHA1
   &_gcry_mac_type_spec_hmac_sha1,
 #endif
@@ -40,6 +40,8 @@ static gcry_mac_spec_t *mac_list[] = {
 #if USE_SHA512
   &_gcry_mac_type_spec_hmac_sha512,
   &_gcry_mac_type_spec_hmac_sha384,
+  &_gcry_mac_type_spec_hmac_sha512_256,
+  &_gcry_mac_type_spec_hmac_sha512_224,
 #endif
 #if USE_SHA3
   &_gcry_mac_type_spec_hmac_sha3_224,
@@ -47,10 +49,11 @@ static gcry_mac_spec_t *mac_list[] = {
   &_gcry_mac_type_spec_hmac_sha3_384,
   &_gcry_mac_type_spec_hmac_sha3_512,
 #endif
-#ifdef USE_GOST_R_3411_94
+#if USE_GOST_R_3411_94
   &_gcry_mac_type_spec_hmac_gost3411_94,
+  &_gcry_mac_type_spec_hmac_gost3411_cp,
 #endif
-#ifdef USE_GOST_R_3411_12
+#if USE_GOST_R_3411_12
   &_gcry_mac_type_spec_hmac_stribog256,
   &_gcry_mac_type_spec_hmac_stribog512,
 #endif
@@ -69,6 +72,19 @@ static gcry_mac_spec_t *mac_list[] = {
 #if USE_MD4
   &_gcry_mac_type_spec_hmac_md4,
 #endif
+#if USE_BLAKE2
+  &_gcry_mac_type_spec_hmac_blake2b_512,
+  &_gcry_mac_type_spec_hmac_blake2b_384,
+  &_gcry_mac_type_spec_hmac_blake2b_256,
+  &_gcry_mac_type_spec_hmac_blake2b_160,
+  &_gcry_mac_type_spec_hmac_blake2s_256,
+  &_gcry_mac_type_spec_hmac_blake2s_224,
+  &_gcry_mac_type_spec_hmac_blake2s_160,
+  &_gcry_mac_type_spec_hmac_blake2s_128,
+#endif
+#if USE_SM3
+  &_gcry_mac_type_spec_hmac_sm3,
+#endif
 #if USE_BLOWFISH
   &_gcry_mac_type_spec_cmac_blowfish,
 #endif
@@ -106,55 +122,302 @@ static gcry_mac_spec_t *mac_list[] = {
   &_gcry_mac_type_spec_gmac_camellia,
   &_gcry_mac_type_spec_poly1305mac_camellia,
 #endif
-#ifdef USE_IDEA
+#if USE_IDEA
   &_gcry_mac_type_spec_cmac_idea,
 #endif
 #if USE_GOST28147
   &_gcry_mac_type_spec_cmac_gost28147,
+  &_gcry_mac_type_spec_gost28147_imit,
 #endif
   &_gcry_mac_type_spec_poly1305mac,
+#if USE_SM4
+  &_gcry_mac_type_spec_cmac_sm4,
+#endif
   NULL,
 };
 
+/* HMAC implementations start with index 101 (enum gcry_mac_algos) */
+static const gcry_mac_spec_t * const mac_list_algo101[] =
+  {
+#if USE_SHA256
+    &_gcry_mac_type_spec_hmac_sha256,
+    &_gcry_mac_type_spec_hmac_sha224,
+#else
+    NULL,
+    NULL,
+#endif
+#if USE_SHA512
+    &_gcry_mac_type_spec_hmac_sha512,
+    &_gcry_mac_type_spec_hmac_sha384,
+#else
+    NULL,
+    NULL,
+#endif
+#if USE_SHA1
+    &_gcry_mac_type_spec_hmac_sha1,
+#else
+    NULL,
+#endif
+#if USE_MD5
+    &_gcry_mac_type_spec_hmac_md5,
+#else
+    NULL,
+#endif
+#if USE_MD4
+    &_gcry_mac_type_spec_hmac_md4,
+#else
+    NULL,
+#endif
+#if USE_RMD160
+    &_gcry_mac_type_spec_hmac_rmd160,
+#else
+    NULL,
+#endif
+#if USE_TIGER
+    &_gcry_mac_type_spec_hmac_tiger1,
+#else
+    NULL,
+#endif
+#if USE_WHIRLPOOL
+    &_gcry_mac_type_spec_hmac_whirlpool,
+#else
+    NULL,
+#endif
+#if USE_GOST_R_3411_94
+    &_gcry_mac_type_spec_hmac_gost3411_94,
+#else
+    NULL,
+#endif
+#if USE_GOST_R_3411_12
+    &_gcry_mac_type_spec_hmac_stribog256,
+    &_gcry_mac_type_spec_hmac_stribog512,
+#else
+    NULL,
+    NULL,
+#endif
+#if USE_MD2
+    &_gcry_mac_type_spec_hmac_md2,
+#else
+    NULL,
+#endif
+#if USE_SHA3
+    &_gcry_mac_type_spec_hmac_sha3_224,
+    &_gcry_mac_type_spec_hmac_sha3_256,
+    &_gcry_mac_type_spec_hmac_sha3_384,
+    &_gcry_mac_type_spec_hmac_sha3_512,
+#else
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+#endif
+#if USE_GOST_R_3411_94
+    &_gcry_mac_type_spec_hmac_gost3411_cp,
+#else
+    NULL,
+#endif
+#if USE_BLAKE2
+    &_gcry_mac_type_spec_hmac_blake2b_512,
+    &_gcry_mac_type_spec_hmac_blake2b_384,
+    &_gcry_mac_type_spec_hmac_blake2b_256,
+    &_gcry_mac_type_spec_hmac_blake2b_160,
+    &_gcry_mac_type_spec_hmac_blake2s_256,
+    &_gcry_mac_type_spec_hmac_blake2s_224,
+    &_gcry_mac_type_spec_hmac_blake2s_160,
+    &_gcry_mac_type_spec_hmac_blake2s_128,
+#else
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+#endif
+#if USE_SM3
+    &_gcry_mac_type_spec_hmac_sm3,
+#else
+    NULL,
+#endif
+#if USE_SHA512
+    &_gcry_mac_type_spec_hmac_sha512_256,
+    &_gcry_mac_type_spec_hmac_sha512_224,
+#else
+    NULL,
+    NULL,
+#endif
+  };
+
+/* CMAC implementations start with index 201 (enum gcry_mac_algos) */
+static const gcry_mac_spec_t * const mac_list_algo201[] =
+  {
+#if USE_AES
+    &_gcry_mac_type_spec_cmac_aes,
+#else
+    NULL,
+#endif
+#if USE_DES
+    &_gcry_mac_type_spec_cmac_tripledes,
+#else
+    NULL,
+#endif
+#if USE_CAMELLIA
+    &_gcry_mac_type_spec_cmac_camellia,
+#else
+    NULL,
+#endif
+#if USE_CAST5
+    &_gcry_mac_type_spec_cmac_cast5,
+#else
+    NULL,
+#endif
+#if USE_BLOWFISH
+    &_gcry_mac_type_spec_cmac_blowfish,
+#else
+    NULL,
+#endif
+#if USE_TWOFISH
+    &_gcry_mac_type_spec_cmac_twofish,
+#else
+    NULL,
+#endif
+#if USE_SERPENT
+    &_gcry_mac_type_spec_cmac_serpent,
+#else
+    NULL,
+#endif
+#if USE_SEED
+    &_gcry_mac_type_spec_cmac_seed,
+#else
+    NULL,
+#endif
+#if USE_RFC2268
+    &_gcry_mac_type_spec_cmac_rfc2268,
+#else
+    NULL,
+#endif
+#if USE_IDEA
+    &_gcry_mac_type_spec_cmac_idea,
+#else
+    NULL,
+#endif
+#if USE_GOST28147
+    &_gcry_mac_type_spec_cmac_gost28147,
+#else
+    NULL,
+#endif
+#if USE_SM4
+    &_gcry_mac_type_spec_cmac_sm4
+#else
+    NULL
+#endif
+  };
+
+/* GMAC implementations start with index 401 (enum gcry_mac_algos) */
+static const gcry_mac_spec_t * const mac_list_algo401[] =
+  {
+#if USE_AES
+    &_gcry_mac_type_spec_gmac_aes,
+#else
+    NULL,
+#endif
+#if USE_CAMELLIA
+    &_gcry_mac_type_spec_gmac_camellia,
+#else
+    NULL,
+#endif
+#if USE_TWOFISH
+    &_gcry_mac_type_spec_gmac_twofish,
+#else
+    NULL,
+#endif
+#if USE_SERPENT
+    &_gcry_mac_type_spec_gmac_serpent,
+#else
+    NULL,
+#endif
+#if USE_SEED
+    &_gcry_mac_type_spec_gmac_seed
+#else
+    NULL
+#endif
+  };
+
+/* Poly1305-MAC implementations start with index 501 (enum gcry_mac_algos) */
+static const gcry_mac_spec_t * const mac_list_algo501[] =
+  {
+    &_gcry_mac_type_spec_poly1305mac,
+#if USE_AES
+    &_gcry_mac_type_spec_poly1305mac_aes,
+#else
+    NULL,
+#endif
+#if USE_CAMELLIA
+    &_gcry_mac_type_spec_poly1305mac_camellia,
+#else
+    NULL,
+#endif
+#if USE_TWOFISH
+    &_gcry_mac_type_spec_poly1305mac_twofish,
+#else
+    NULL,
+#endif
+#if USE_SERPENT
+    &_gcry_mac_type_spec_poly1305mac_serpent,
+#else
+    NULL,
+#endif
+#if USE_SEED
+    &_gcry_mac_type_spec_poly1305mac_seed
+#else
+    NULL
+#endif
+  };
+
+
+
+
 /* Explicitly initialize this module.  */
 gcry_err_code_t
 _gcry_mac_init (void)
 {
-  if (fips_mode())
-    {
-      /* disable algorithms that are disallowed in fips */
-      int idx;
-      gcry_mac_spec_t *spec;
-
-      for (idx = 0; (spec = mac_list[idx]); idx++)
-        if (!spec->flags.fips)
-          spec->flags.disabled = 1;
-    }
-
   return 0;
 }
 
 \f
 /* Return the spec structure for the MAC algorithm ALGO.  For an
    unknown algorithm NULL is returned.  */
-static gcry_mac_spec_t *
+static const gcry_mac_spec_t *
 spec_from_algo (int algo)
 {
-  gcry_mac_spec_t *spec;
-  int idx;
+  const gcry_mac_spec_t *spec = NULL;
+
+  if (algo >= 101 && algo < 101 + DIM(mac_list_algo101))
+    spec = mac_list_algo101[algo - 101];
+  else if (algo >= 201 && algo < 201 + DIM(mac_list_algo201))
+    spec = mac_list_algo201[algo - 201];
+  else if (algo >= 401 && algo < 401 + DIM(mac_list_algo401))
+    spec = mac_list_algo401[algo - 401];
+  else if (algo >= 501 && algo < 501 + DIM(mac_list_algo501))
+    spec = mac_list_algo501[algo - 501];
+#if USE_GOST28147
+  else if (algo == GCRY_MAC_GOST28147_IMIT)
+    spec = &_gcry_mac_type_spec_gost28147_imit;
+#endif
 
-  for (idx = 0; (spec = mac_list[idx]); idx++)
-    if (algo == spec->algo)
-      return spec;
-  return NULL;
+  if (spec)
+    gcry_assert (spec->algo == algo);
+
+  return spec;
 }
 
 
 /* Lookup a mac's spec by its name.  */
-static gcry_mac_spec_t *
+static const gcry_mac_spec_t *
 spec_from_name (const char *name)
 {
-  gcry_mac_spec_t *spec;
+  const gcry_mac_spec_t *spec;
   int idx;
 
   for (idx = 0; (spec = mac_list[idx]); idx++)
@@ -171,7 +434,7 @@ spec_from_name (const char *name)
 int
 _gcry_mac_map_name (const char *string)
 {
-  gcry_mac_spec_t *spec;
+  const gcry_mac_spec_t *spec;
 
   if (!string)
     return 0;
@@ -194,7 +457,7 @@ _gcry_mac_map_name (const char *string)
 const char *
 _gcry_mac_algo_name (int algorithm)
 {
-  gcry_mac_spec_t *spec;
+  const gcry_mac_spec_t *spec;
 
   spec = spec_from_algo (algorithm);
   return spec ? spec->name : "?";
@@ -204,10 +467,10 @@ _gcry_mac_algo_name (int algorithm)
 static gcry_err_code_t
 check_mac_algo (int algorithm)
 {
-  gcry_mac_spec_t *spec;
+  const gcry_mac_spec_t *spec;
 
   spec = spec_from_algo (algorithm);
-  if (spec && !spec->flags.disabled)
+  if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()))
     return 0;
 
   return GPG_ERR_MAC_ALGO;
@@ -220,7 +483,7 @@ check_mac_algo (int algorithm)
 static gcry_err_code_t
 mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx)
 {
-  gcry_mac_spec_t *spec;
+  const gcry_mac_spec_t *spec;
   gcry_err_code_t err;
   gcry_mac_hd_t h;
 
@@ -229,6 +492,8 @@ mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx)
     return GPG_ERR_MAC_ALGO;
   else if (spec->flags.disabled)
     return GPG_ERR_MAC_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    return GPG_ERR_MAC_ALGO;
   else if (!spec->ops)
     return GPG_ERR_MAC_ALGO;
   else if (!spec->ops->open || !spec->ops->write || !spec->ops->setkey ||
@@ -243,7 +508,7 @@ mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx)
   if (!h)
     return gpg_err_code_from_syserror ();
 
-  h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
+  h->magic = secure ? CTX_MAC_MAGIC_SECURE : CTX_MAC_MAGIC_NORMAL;
   h->spec = spec;
   h->algo = algo;
   h->gcry_ctx = ctx;
@@ -409,7 +674,7 @@ _gcry_mac_get_algo (gcry_mac_hd_t hd)
 unsigned int
 _gcry_mac_get_algo_maclen (int algo)
 {
-  gcry_mac_spec_t *spec;
+  const gcry_mac_spec_t *spec;
 
   spec = spec_from_algo (algo);
   if (!spec || !spec->ops || !spec->ops->get_maclen)
@@ -422,7 +687,7 @@ _gcry_mac_get_algo_maclen (int algo)
 unsigned int
 _gcry_mac_get_algo_keylen (int algo)
 {
-  gcry_mac_spec_t *spec;
+  const gcry_mac_spec_t *spec;
 
   spec = spec_from_algo (algo);
   if (!spec || !spec->ops || !spec->ops->get_keylen)
@@ -447,6 +712,13 @@ _gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen)
     case GCRYCTL_RESET:
       rc = mac_reset (hd);
       break;
+    case GCRYCTL_SET_SBOX:
+      if (hd->spec->ops->set_extra_info)
+        rc = hd->spec->ops->set_extra_info
+          (hd, GCRYCTL_SET_SBOX, buffer, buflen);
+      else
+        rc = GPG_ERR_NOT_SUPPORTED;
+      break;
     default:
       rc = GPG_ERR_INV_OP;
     }
@@ -500,3 +772,31 @@ _gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes)
 
   return rc;
 }
+
+
+/* Run the self-tests for the MAC.  */
+gpg_error_t
+_gcry_mac_selftest (int algo, int extended, selftest_report_func_t report)
+{
+  gcry_err_code_t ec;
+  const gcry_mac_spec_t *spec;
+
+  spec = spec_from_algo (algo);
+  if (spec && !spec->flags.disabled
+      && (spec->flags.fips || !fips_mode ())
+      && spec->ops && spec->ops->selftest)
+    ec = spec->ops->selftest (algo, extended, report);
+  else
+    {
+      ec = GPG_ERR_MAC_ALGO;
+      if (report)
+        report ("mac", algo, "module",
+                spec && !spec->flags.disabled
+                && (spec->flags.fips || !fips_mode ())?
+                "no selftest available" :
+                spec? "algorithm disabled" :
+                "algorithm not found");
+    }
+
+  return gpg_error (ec);
+}
index c1f585f..4f4fc9b 100644 (file)
@@ -31,7 +31,7 @@
 
 /* This is the list of the digest implementations included in
    libgcrypt.  */
-static gcry_md_spec_t *digest_list[] =
+static const gcry_md_spec_t * const digest_list[] =
   {
 #if USE_CRC
      &_gcry_digest_spec_crc32,
@@ -48,6 +48,8 @@ static gcry_md_spec_t *digest_list[] =
 #if USE_SHA512
      &_gcry_digest_spec_sha512,
      &_gcry_digest_spec_sha384,
+     &_gcry_digest_spec_sha512_256,
+     &_gcry_digest_spec_sha512_224,
 #endif
 #if USE_SHA3
      &_gcry_digest_spec_sha3_224,
@@ -95,16 +97,163 @@ static gcry_md_spec_t *digest_list[] =
      &_gcry_digest_spec_blake2s_160,
      &_gcry_digest_spec_blake2s_128,
 #endif
+#if USE_SM3
+     &_gcry_digest_spec_sm3,
+#endif
      NULL
   };
 
+/* Digest implementations starting with index 0 (enum gcry_md_algos) */
+static const gcry_md_spec_t * const digest_list_algo0[] =
+  {
+    NULL, /* GCRY_MD_NONE */
+#if USE_MD5
+    &_gcry_digest_spec_md5,
+#else
+    NULL,
+#endif
+#if USE_SHA1
+    &_gcry_digest_spec_sha1,
+#else
+    NULL,
+#endif
+#if USE_RMD160
+    &_gcry_digest_spec_rmd160,
+#else
+    NULL,
+#endif
+    NULL, /* Unused index 4 */
+#if USE_MD2
+    &_gcry_digest_spec_md2,
+#else
+    NULL,
+#endif
+#if USE_TIGER
+    &_gcry_digest_spec_tiger,
+#else
+    NULL,
+#endif
+    NULL, /* GCRY_MD_HAVAL */
+#if USE_SHA256
+    &_gcry_digest_spec_sha256,
+#else
+    NULL,
+#endif
+#if USE_SHA512
+    &_gcry_digest_spec_sha384,
+    &_gcry_digest_spec_sha512,
+#else
+    NULL,
+    NULL,
+#endif
+#if USE_SHA256
+    &_gcry_digest_spec_sha224
+#else
+    NULL
+#endif
+  };
+
+/* Digest implementations starting with index 301 (enum gcry_md_algos) */
+static const gcry_md_spec_t * const digest_list_algo301[] =
+  {
+#if USE_MD4
+    &_gcry_digest_spec_md4,
+#else
+    NULL,
+#endif
+#if USE_CRC
+    &_gcry_digest_spec_crc32,
+    &_gcry_digest_spec_crc32_rfc1510,
+    &_gcry_digest_spec_crc24_rfc2440,
+#else
+    NULL,
+    NULL,
+    NULL,
+#endif
+#if USE_WHIRLPOOL
+    &_gcry_digest_spec_whirlpool,
+#else
+    NULL,
+#endif
+#if USE_TIGER
+    &_gcry_digest_spec_tiger1,
+    &_gcry_digest_spec_tiger2,
+#else
+    NULL,
+    NULL,
+#endif
+#if USE_GOST_R_3411_94
+    &_gcry_digest_spec_gost3411_94,
+#else
+    NULL,
+#endif
+#if USE_GOST_R_3411_12
+    &_gcry_digest_spec_stribog_256,
+    &_gcry_digest_spec_stribog_512,
+#else
+    NULL,
+    NULL,
+#endif
+#if USE_GOST_R_3411_94
+    &_gcry_digest_spec_gost3411_cp,
+#else
+    NULL,
+#endif
+#if USE_SHA3
+    &_gcry_digest_spec_sha3_224,
+    &_gcry_digest_spec_sha3_256,
+    &_gcry_digest_spec_sha3_384,
+    &_gcry_digest_spec_sha3_512,
+    &_gcry_digest_spec_shake128,
+    &_gcry_digest_spec_shake256,
+#else
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+#endif
+#if USE_BLAKE2
+    &_gcry_digest_spec_blake2b_512,
+    &_gcry_digest_spec_blake2b_384,
+    &_gcry_digest_spec_blake2b_256,
+    &_gcry_digest_spec_blake2b_160,
+    &_gcry_digest_spec_blake2s_256,
+    &_gcry_digest_spec_blake2s_224,
+    &_gcry_digest_spec_blake2s_160,
+    &_gcry_digest_spec_blake2s_128,
+#else
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+#endif
+#if USE_SM3
+    &_gcry_digest_spec_sm3,
+#else
+    NULL,
+#endif
+#if USE_SHA512
+    &_gcry_digest_spec_sha512_256,
+    &_gcry_digest_spec_sha512_224,
+#else
+    NULL,
+    NULL,
+#endif
+  };
+
 
 typedef struct gcry_md_list
 {
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
   struct gcry_md_list *next;
   size_t actual_struct_size;     /* Allocated size of this structure. */
-  PROPERLY_ALIGNED_TYPE context;
+  PROPERLY_ALIGNED_TYPE context[1];
 } GcryDigestEntry;
 
 /* This structure is put right after the gcry_md_hd_t buffer, so that
@@ -112,14 +261,14 @@ typedef struct gcry_md_list
 struct gcry_md_context
 {
   int  magic;
-  size_t actual_handle_size;     /* Allocated size of this handle. */
-  FILE  *debug;
   struct {
-    unsigned int secure: 1;
+    unsigned int secure:1;
     unsigned int finalized:1;
     unsigned int bugemu1:1;
     unsigned int hmac:1;
   } flags;
+  size_t actual_handle_size;     /* Allocated size of this handle. */
+  FILE  *debug;
   GcryDigestEntry *list;
 };
 
@@ -147,26 +296,30 @@ map_algo (int algo)
 
 /* Return the spec structure for the hash algorithm ALGO.  For an
    unknown algorithm NULL is returned.  */
-static gcry_md_spec_t *
+static const gcry_md_spec_t *
 spec_from_algo (int algo)
 {
-  int idx;
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec = NULL;
 
   algo = map_algo (algo);
 
-  for (idx = 0; (spec = digest_list[idx]); idx++)
-    if (algo == spec->algo)
-      return spec;
-  return NULL;
+  if (algo >= 0 && algo < DIM(digest_list_algo0))
+    spec = digest_list_algo0[algo];
+  else if (algo >= 301 && algo < 301 + DIM(digest_list_algo301))
+    spec = digest_list_algo301[algo - 301];
+
+  if (spec)
+    gcry_assert (spec->algo == algo);
+
+  return spec;
 }
 
 
 /* Lookup a hash's spec by its name.  */
-static gcry_md_spec_t *
+static const gcry_md_spec_t *
 spec_from_name (const char *name)
 {
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
   int idx;
 
   for (idx=0; (spec = digest_list[idx]); idx++)
@@ -180,11 +333,11 @@ spec_from_name (const char *name)
 
 
 /* Lookup a hash's spec by its OID.  */
-static gcry_md_spec_t *
+static const gcry_md_spec_t *
 spec_from_oid (const char *oid)
 {
-  gcry_md_spec_t *spec;
-  gcry_md_oid_spec_t *oid_specs;
+  const gcry_md_spec_t *spec;
+  const gcry_md_oid_spec_t *oid_specs;
   int idx, j;
 
   for (idx=0; (spec = digest_list[idx]); idx++)
@@ -202,10 +355,10 @@ spec_from_oid (const char *oid)
 }
 
 
-static gcry_md_spec_t *
+static const gcry_md_spec_t *
 search_oid (const char *oid, gcry_md_oid_spec_t *oid_spec)
 {
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
   int i;
 
   if (!oid)
@@ -236,7 +389,7 @@ search_oid (const char *oid, gcry_md_oid_spec_t *oid_spec)
 int
 _gcry_md_map_name (const char *string)
 {
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
 
   if (!string)
     return 0;
@@ -266,7 +419,7 @@ _gcry_md_map_name (const char *string)
 const char *
 _gcry_md_algo_name (int algorithm)
 {
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
 
   spec = spec_from_algo (algorithm);
   return spec ? spec->name : "?";
@@ -276,10 +429,10 @@ _gcry_md_algo_name (int algorithm)
 static gcry_err_code_t
 check_digest_algo (int algorithm)
 {
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
 
   spec = spec_from_algo (algorithm);
-  if (spec && !spec->flags.disabled)
+  if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()))
     return 0;
 
   return GPG_ERR_DIGEST_ALGO;
@@ -299,7 +452,6 @@ md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
   int secure = !!(flags & GCRY_MD_FLAG_SECURE);
   int hmac =   !!(flags & GCRY_MD_FLAG_HMAC);
   int bufsize = secure ? 512 : 1024;
-  struct gcry_md_context *ctx;
   gcry_md_hd_t hd;
   size_t n;
 
@@ -317,7 +469,7 @@ md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
    *
    * We have to make sure that private is well aligned.
    */
-  n = sizeof (struct gcry_md_handle) + bufsize;
+  n = offsetof (struct gcry_md_handle, buf) + bufsize;
   n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1)
        / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE);
 
@@ -332,13 +484,16 @@ md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
 
   if (! err)
     {
-      hd->ctx = ctx = (void *) ((char *) hd + n);
+      struct gcry_md_context *ctx;
+
+      ctx = (void *) (hd->buf - offsetof (struct gcry_md_handle, buf) + n);
       /* Setup the globally visible data (bctl in the diagram).*/
-      hd->bufsize = n - sizeof (struct gcry_md_handle) + 1;
+      hd->ctx = ctx;
+      hd->bufsize = n - offsetof (struct gcry_md_handle, buf);
       hd->bufpos = 0;
 
       /* Initialize the private data. */
-      memset (hd->ctx, 0, sizeof *hd->ctx);
+      wipememory2 (ctx, 0, sizeof *ctx);
       ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
       ctx->actual_handle_size = n + sizeof (struct gcry_md_context);
       ctx->flags.secure = secure;
@@ -393,7 +548,7 @@ static gcry_err_code_t
 md_enable (gcry_md_hd_t hd, int algorithm)
 {
   struct gcry_md_context *h = hd->ctx;
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
   GcryDigestEntry *entry;
   gcry_err_code_t err = 0;
 
@@ -408,17 +563,12 @@ md_enable (gcry_md_hd_t hd, int algorithm)
       err = GPG_ERR_DIGEST_ALGO;
     }
 
+  if (!err && spec->flags.disabled)
+    err = GPG_ERR_DIGEST_ALGO;
 
-  if (!err && algorithm == GCRY_MD_MD5 && fips_mode ())
-    {
-      _gcry_inactivate_fips_mode ("MD5 used");
-      if (_gcry_enforced_fips_mode () )
-        {
-          /* We should never get to here because we do not register
-             MD5 in enforced fips mode. But better throw an error.  */
-          err = GPG_ERR_DIGEST_ALGO;
-        }
-    }
+  /* Any non-FIPS algorithm should go this way */
+  if (!err && !spec->flags.fips && fips_mode ())
+    err = GPG_ERR_DIGEST_ALGO;
 
   if (!err && h->flags.hmac && spec->read == NULL)
     {
@@ -448,7 +598,7 @@ md_enable (gcry_md_hd_t hd, int algorithm)
          h->list = entry;
 
          /* And init this instance. */
-         entry->spec->init (&entry->context.c,
+         entry->spec->init (entry->context,
                              h->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
        }
     }
@@ -491,7 +641,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
 
   bhd->ctx = b = (void *) ((char *) bhd + n);
   /* No need to copy the buffer due to the write above. */
-  gcry_assert (ahd->bufsize == (n - sizeof (struct gcry_md_handle) + 1));
+  gcry_assert (ahd->bufsize == (n - offsetof (struct gcry_md_handle, buf)));
   bhd->bufsize = ahd->bufsize;
   bhd->bufpos = 0;
   gcry_assert (! ahd->bufpos);
@@ -557,14 +707,14 @@ _gcry_md_reset (gcry_md_hd_t a)
   if (a->ctx->flags.hmac)
     for (r = a->ctx->list; r; r = r->next)
       {
-        memcpy (r->context.c, r->context.c + r->spec->contextsize,
+        memcpy (r->context, (char *)r->context + r->spec->contextsize,
                 r->spec->contextsize);
       }
   else
     for (r = a->ctx->list; r; r = r->next)
       {
-        memset (r->context.c, 0, r->spec->contextsize);
-        (*r->spec->init) (&r->context.c,
+        memset (r->context, 0, r->spec->contextsize);
+        (*r->spec->init) (r->context,
                           a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
       }
 }
@@ -615,8 +765,8 @@ md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen)
   for (r = a->ctx->list; r; r = r->next)
     {
       if (a->bufpos)
-       (*r->spec->write) (&r->context.c, a->buf, a->bufpos);
-      (*r->spec->write) (&r->context.c, inbuf, inlen);
+       (*r->spec->write) (r->context, a->buf, a->bufpos);
+      (*r->spec->write) (r->context, inbuf, inlen);
     }
   a->bufpos = 0;
 }
@@ -644,7 +794,7 @@ md_final (gcry_md_hd_t a)
     md_write (a, NULL, 0);
 
   for (r = a->ctx->list; r; r = r->next)
-    (*r->spec->final) (&r->context.c);
+    (*r->spec->final) (r->context);
 
   a->ctx->flags.finalized = 1;
 
@@ -661,7 +811,7 @@ md_final (gcry_md_hd_t a)
       if (r->spec->read == NULL)
         continue;
 
-      p = r->spec->read (&r->context.c);
+      p = r->spec->read (r->context);
 
       if (a->ctx->flags.secure)
         hash = xtrymalloc_secure (dlen);
@@ -674,10 +824,10 @@ md_final (gcry_md_hd_t a)
         }
 
       memcpy (hash, p, dlen);
-      memcpy (r->context.c, r->context.c + r->spec->contextsize * 2,
+      memcpy (r->context, (char *)r->context + r->spec->contextsize * 2,
               r->spec->contextsize);
-      (*r->spec->write) (&r->context.c, hash, dlen);
-      (*r->spec->final) (&r->context.c);
+      (*r->spec->write) (r->context, hash, dlen);
+      (*r->spec->final) (r->context);
       xfree (hash);
     }
 }
@@ -700,6 +850,7 @@ md_setkey (gcry_md_hd_t h, const unsigned char *key, size_t keylen)
     {
       switch (r->spec->algo)
        {
+#if USE_BLAKE2
        /* TODO? add spec->init_with_key? */
        case GCRY_MD_BLAKE2B_512:
        case GCRY_MD_BLAKE2B_384:
@@ -710,12 +861,13 @@ md_setkey (gcry_md_hd_t h, const unsigned char *key, size_t keylen)
        case GCRY_MD_BLAKE2S_160:
        case GCRY_MD_BLAKE2S_128:
          algo_had_setkey = 1;
-         memset (r->context.c, 0, r->spec->contextsize);
-         rc = _gcry_blake2_init_with_key (r->context.c,
+         memset (r->context, 0, r->spec->contextsize);
+         rc = _gcry_blake2_init_with_key (r->context,
                                           h->ctx->flags.bugemu1
                                             ? GCRY_MD_FLAG_BUGEMU1:0,
                                           key, keylen, r->spec->algo);
          break;
+#endif
        default:
          rc = GPG_ERR_DIGEST_ALGO;
          break;
@@ -751,6 +903,9 @@ prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen)
 {
   GcryDigestEntry *r;
 
+  if (fips_mode () && keylen < 14)
+    return GPG_ERR_INV_VALUE;
+
   if (!a->ctx->list)
     return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled.  */
 
@@ -782,6 +937,8 @@ prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen)
           break;
         case GCRY_MD_SHA384:
         case GCRY_MD_SHA512:
+        case GCRY_MD_SHA512_256:
+        case GCRY_MD_SHA512_224:
         case GCRY_MD_BLAKE2B_512:
         case GCRY_MD_BLAKE2B_384:
         case GCRY_MD_BLAKE2B_256:
@@ -812,26 +969,26 @@ prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen)
           k_len = keylen;
         }
 
-      (*r->spec->init) (&r->context.c,
+      (*r->spec->init) (r->context,
                         a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
       a->bufpos = 0;
       for (i=0; i < k_len; i++ )
         _gcry_md_putc (a, k[i] ^ 0x36);
       for (; i < macpad_Bsize; i++ )
         _gcry_md_putc (a, 0x36);
-      (*r->spec->write) (&r->context.c, a->buf, a->bufpos);
-      memcpy (r->context.c + r->spec->contextsize, r->context.c,
+      (*r->spec->write) (r->context, a->buf, a->bufpos);
+      memcpy ((char *)r->context + r->spec->contextsize, r->context,
               r->spec->contextsize);
 
-      (*r->spec->init) (&r->context.c,
+      (*r->spec->init) (r->context,
                         a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
       a->bufpos = 0;
       for (i=0; i < k_len; i++ )
         _gcry_md_putc (a, k[i] ^ 0x5c);
       for (; i < macpad_Bsize; i++ )
         _gcry_md_putc (a, 0x5c);
-      (*r->spec->write) (&r->context.c, a->buf, a->bufpos);
-      memcpy (r->context.c + r->spec->contextsize*2, r->context.c,
+      (*r->spec->write) (r->context, a->buf, a->bufpos);
+      memcpy ((char *)r->context + r->spec->contextsize*2, r->context,
               r->spec->contextsize);
 
       xfree (key_allocated);
@@ -917,7 +1074,7 @@ md_read( gcry_md_hd_t a, int algo )
           if (r->next)
             log_debug ("more than one algorithm in md_read(0)\n");
           if (r->spec->read)
-            return r->spec->read (&r->context.c);
+            return r->spec->read (r->context);
         }
     }
   else
@@ -926,7 +1083,7 @@ md_read( gcry_md_hd_t a, int algo )
        if (r->spec->algo == algo)
          {
            if (r->spec->read)
-              return r->spec->read (&r->context.c);
+              return r->spec->read (r->context);
             break;
          }
     }
@@ -971,7 +1128,7 @@ md_extract(gcry_md_hd_t a, int algo, void *out, size_t outlen)
        {
          if (r->next)
            log_debug ("more than one algorithm in md_extract(0)\n");
-         r->spec->extract (&r->context.c, out, outlen);
+         r->spec->extract (r->context, out, outlen);
          return 0;
        }
     }
@@ -980,7 +1137,7 @@ md_extract(gcry_md_hd_t a, int algo, void *out, size_t outlen)
       for (r = a->ctx->list; r; r = r->next)
        if (r->spec->algo == algo && r->spec->extract)
          {
-           r->spec->extract (&r->context.c, out, outlen);
+           r->spec->extract (r->context, out, outlen);
            return 0;
          }
     }
@@ -1028,46 +1185,41 @@ void
 _gcry_md_hash_buffer (int algo, void *digest,
                       const void *buffer, size_t length)
 {
-  if (0)
-    ;
-#if USE_SHA256
-  else if (algo == GCRY_MD_SHA256)
-    _gcry_sha256_hash_buffer (digest, buffer, length);
-#endif
-#if USE_SHA512
-  else if (algo == GCRY_MD_SHA512)
-    _gcry_sha512_hash_buffer (digest, buffer, length);
-#endif
-#if USE_SHA1
-  else if (algo == GCRY_MD_SHA1)
-    _gcry_sha1_hash_buffer (digest, buffer, length);
-#endif
-#if USE_RMD160
-  else if (algo == GCRY_MD_RMD160 && !fips_mode () )
-    _gcry_rmd160_hash_buffer (digest, buffer, length);
-#endif
+  const gcry_md_spec_t *spec;
+
+  spec = spec_from_algo (algo);
+  if (!spec)
+    {
+      log_debug ("md_hash_buffer: algorithm %d not available\n", algo);
+      return;
+    }
+
+  if (spec->hash_buffers != NULL)
+    {
+      gcry_buffer_t iov;
+
+      iov.size = 0;
+      iov.data = (void *)buffer;
+      iov.off = 0;
+      iov.len = length;
+
+      if (spec->flags.disabled || (!spec->flags.fips && fips_mode ()))
+        log_bug ("gcry_md_hash_buffer failed for algo %d: %s",
+                algo, gpg_strerror (gcry_error (GPG_ERR_DIGEST_ALGO)));
+
+      spec->hash_buffers (digest, spec->mdlen, &iov, 1);
+    }
   else
     {
       /* For the others we do not have a fast function, so we use the
-        normal functions. */
+         normal functions. */
       gcry_md_hd_t h;
       gpg_err_code_t err;
 
-      if (algo == GCRY_MD_MD5 && fips_mode ())
-        {
-          _gcry_inactivate_fips_mode ("MD5 used");
-          if (_gcry_enforced_fips_mode () )
-            {
-              /* We should never get to here because we do not register
-                 MD5 in enforced fips mode.  */
-              _gcry_fips_noreturn ();
-            }
-        }
-
       err = md_open (&h, algo, 0);
       if (err)
-       log_bug ("gcry_md_open failed for algo %d: %s",
-                 algo, gpg_strerror (gcry_error(err)));
+        log_bug ("gcry_md_open failed for algo %d: %s",
+                algo, gpg_strerror (gcry_error(err)));
       md_write (h, (byte *) buffer, length);
       md_final (h);
       memcpy (digest, md_read (h, algo), md_digest_length (algo));
@@ -1088,12 +1240,17 @@ _gcry_md_hash_buffer (int algo, void *digest,
    used as the key.
 
    On success 0 is returned and resulting hash or HMAC is stored at
-   DIGEST which must have been provided by the caller with an
-   appropriate length.  */
+   DIGEST. DIGESTLEN may be given as -1, in which case DIGEST must
+   have been provided by the caller with an appropriate length.
+   DIGESTLEN may also be the appropriate length or, in case of XOF
+   algorithms, DIGESTLEN indicates number bytes to extract from XOF
+   to DIGEST.  */
 gpg_err_code_t
-_gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
-                       const gcry_buffer_t *iov, int iovcnt)
+_gcry_md_hash_buffers_extract (int algo, unsigned int flags, void *digest,
+                              int digestlen, const gcry_buffer_t *iov,
+                              int iovcnt)
 {
+  const gcry_md_spec_t *spec;
   int hmac;
 
   if (!iov || iovcnt < 0)
@@ -1105,44 +1262,31 @@ _gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
   if (hmac && iovcnt < 1)
     return GPG_ERR_INV_ARG;
 
-  if (0)
-    ;
-#if USE_SHA256
-  else if (algo == GCRY_MD_SHA256 && !hmac)
-    _gcry_sha256_hash_buffers (digest, iov, iovcnt);
-#endif
-#if USE_SHA512
-  else if (algo == GCRY_MD_SHA512 && !hmac)
-    _gcry_sha512_hash_buffers (digest, iov, iovcnt);
-#endif
-#if USE_SHA1
-  else if (algo == GCRY_MD_SHA1 && !hmac)
-    _gcry_sha1_hash_buffers (digest, iov, iovcnt);
-#endif
+  spec = spec_from_algo (algo);
+  if (!spec)
+    {
+      log_debug ("md_hash_buffers: algorithm %d not available\n", algo);
+      return GPG_ERR_DIGEST_ALGO;
+    }
+
+  if (spec->mdlen > 0 && digestlen != -1 && digestlen != spec->mdlen)
+    return GPG_ERR_DIGEST_ALGO;
+  if (spec->mdlen == 0 && digestlen == -1)
+    return GPG_ERR_DIGEST_ALGO;
+
+  if (!hmac && spec->hash_buffers)
+    {
+      if (spec->flags.disabled || (!spec->flags.fips && fips_mode ()))
+        return GPG_ERR_DIGEST_ALGO;
+
+      spec->hash_buffers (digest, digestlen, iov, iovcnt);
+    }
   else
     {
       /* For the others we do not have a fast function, so we use the
-        normal functions.  */
+         normal functions.  */
       gcry_md_hd_t h;
       gpg_err_code_t rc;
-      int dlen;
-
-      if (algo == GCRY_MD_MD5 && fips_mode ())
-        {
-          _gcry_inactivate_fips_mode ("MD5 used");
-          if (_gcry_enforced_fips_mode () )
-            {
-              /* We should never get to here because we do not register
-                 MD5 in enforced fips mode.  */
-              _gcry_fips_noreturn ();
-            }
-        }
-
-      /* Detect SHAKE128 like algorithms which we can't use because
-       * our API does not allow for a variable length digest.  */
-      dlen = md_digest_length (algo);
-      if (!dlen)
-        return GPG_ERR_DIGEST_ALGO;
 
       rc = md_open (&h, algo, (hmac? GCRY_MD_FLAG_HMAC:0));
       if (rc)
@@ -1163,7 +1307,10 @@ _gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
       for (;iovcnt; iov++, iovcnt--)
         md_write (h, (const char*)iov[0].data + iov[0].off, iov[0].len);
       md_final (h);
-      memcpy (digest, md_read (h, algo), dlen);
+      if (spec->mdlen > 0)
+       memcpy (digest, md_read (h, algo), spec->mdlen);
+      else if (digestlen > 0)
+       md_extract (h, algo, digest, digestlen);
       md_close (h);
     }
 
@@ -1171,6 +1318,28 @@ _gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
 }
 
 
+/* Shortcut function to hash multiple buffers with a given algo.  In
+   contrast to gcry_md_hash_buffer, this function returns an error on
+   invalid arguments or on other problems; disabled algorithms are
+   _not_ ignored but flagged as an error.
+
+   The data to sign is taken from the array IOV which has IOVCNT items.
+
+   The only supported flag in FLAGS is GCRY_MD_FLAG_HMAC which turns
+   this function into a HMAC function; the first item in IOV is then
+   used as the key.
+
+   On success 0 is returned and resulting hash or HMAC is stored at
+   DIGEST which must have been provided by the caller with an
+   appropriate length.  */
+gpg_err_code_t
+_gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
+                      const gcry_buffer_t *iov, int iovcnt)
+{
+  return _gcry_md_hash_buffers_extract(algo, flags, digest, -1, iov, iovcnt);
+}
+
+
 static int
 md_get_algo (gcry_md_hd_t a)
 {
@@ -1198,7 +1367,7 @@ _gcry_md_get_algo (gcry_md_hd_t hd)
 static int
 md_digest_length (int algorithm)
 {
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
 
   spec = spec_from_algo (algorithm);
   return spec? spec->mdlen : 0;
@@ -1221,7 +1390,7 @@ _gcry_md_get_algo_dlen (int algorithm)
 static const byte *
 md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen)
 {
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
   const byte *asnoid = NULL;
 
   spec = spec_from_algo (algorithm);
@@ -1413,17 +1582,6 @@ _gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
 gcry_err_code_t
 _gcry_md_init (void)
 {
-  if (fips_mode())
-    {
-      /* disable algorithms that are disallowed in fips */
-      int idx;
-      gcry_md_spec_t *spec;
-
-      for (idx = 0; (spec = digest_list[idx]); idx++)
-        if (!spec->flags.fips)
-          spec->flags.disabled = 1;
-    }
-
   return 0;
 }
 
@@ -1458,10 +1616,12 @@ gpg_error_t
 _gcry_md_selftest (int algo, int extended, selftest_report_func_t report)
 {
   gcry_err_code_t ec = 0;
-  gcry_md_spec_t *spec;
+  const gcry_md_spec_t *spec;
 
   spec = spec_from_algo (algo);
-  if (spec && !spec->flags.disabled && spec->selftest)
+  if (spec && !spec->flags.disabled
+      && (spec->flags.fips || !fips_mode ())
+      && spec->selftest)
     ec = spec->selftest (algo, extended, report);
   else
     {
@@ -1469,7 +1629,8 @@ _gcry_md_selftest (int algo, int extended, selftest_report_func_t report)
         /* */                       : GPG_ERR_NOT_IMPLEMENTED;
       if (report)
         report ("digest", algo, "module",
-                (spec && !spec->flags.disabled)?
+                spec && !spec->flags.disabled
+                && (spec->flags.fips || !fips_mode ())?
                 "no selftest available" :
                 spec? "algorithm disabled" : "algorithm not found");
     }
diff --git a/cipher/md2.c b/cipher/md2.c
new file mode 100644 (file)
index 0000000..9af9d69
--- /dev/null
@@ -0,0 +1,181 @@
+/* md2.c - MD2 Message-Digest Algorithm
+ * Copyright (C) 2014 Dmitry Eremin-Solenikov
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+
+#include "bithelp.h"
+#include "bufhelp.h"
+#include "hash-common.h"
+
+typedef struct {
+  gcry_md_block_ctx_t bctx;
+  unsigned char C[16];
+  unsigned char L;
+  unsigned char X[48];
+} MD2_CONTEXT;
+
+static const unsigned char S[] =
+  {
+    0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01,
+    0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
+    0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C,
+    0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
+    0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
+    0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
+    0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49,
+    0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
+    0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F,
+    0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
+    0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27,
+    0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
+    0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1,
+    0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
+    0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
+    0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
+    0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,
+    0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
+    0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6,
+    0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
+    0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A,
+    0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
+    0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09,
+    0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
+    0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
+    0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
+    0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D,
+    0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
+    0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4,
+    0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
+    0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A,
+    0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
+};
+
+
+static void
+permute (unsigned char *X, const unsigned char *buf)
+{
+  int i, j;
+  unsigned char t;
+
+  memcpy (X+16, buf, 16);
+  for (i = 0; i < 16; i++)
+    X[32+i] = X[16+i] ^ X[i];
+  t = 0;
+  for (i = 0; i < 18; i++)
+    {
+      for (j = 0; j < 48; j++)
+        {
+          t = X[j] ^ S[t];
+          X[j] = t;
+        }
+      t += i;
+    }
+}
+
+
+static unsigned int
+transform_blk (void *c, const unsigned char *data)
+{
+  MD2_CONTEXT *ctx = c;
+  int j;
+
+  for (j = 0; j < 16; j++)
+    {
+      ctx->C[j] ^= S[data[j] ^ ctx->L];
+      ctx->L = ctx->C[j];
+    }
+
+  permute(ctx->X, data);
+
+  return /* burn stack */ 4 + 5 * sizeof(void*);
+}
+
+
+static unsigned int
+transform ( void *c, const unsigned char *data, size_t nblks )
+{
+  unsigned int burn;
+
+  do
+    {
+      burn = transform_blk (c, data);
+      data += 64;
+    }
+  while (--nblks);
+
+  return burn;
+}
+
+
+static void
+md2_init (void *context, unsigned int flags)
+{
+  MD2_CONTEXT *ctx = context;
+
+  (void)flags;
+
+  memset (ctx, 0, sizeof(*ctx));
+  ctx->bctx.blocksize_shift = _gcry_ctz(16);
+  ctx->bctx.bwrite = transform;
+}
+
+
+static void
+md2_final (void *context)
+{
+  MD2_CONTEXT *hd = context;
+  unsigned int burn;
+
+  /* pad */
+  memset (hd->bctx.buf + hd->bctx.count,
+          16 - hd->bctx.count, 16 - hd->bctx.count);
+  burn = transform_blk (hd, hd->bctx.buf);
+  permute (hd->X, hd->C);
+}
+
+static byte *
+md2_read (void *context)
+{
+  MD2_CONTEXT *hd = (MD2_CONTEXT *) context;
+  return hd->X;
+}
+
+static const byte asn[18] = /* Object ID is 1.2.840.113549.2.2 */
+  { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
+    0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 };
+
+static const gcry_md_oid_spec_t oid_spec_md2[] =
+  {
+    /* iso.member-body.us.rsadsi.digestAlgorithm.md2 */
+    { "1.2.840.113549.2.2" },
+    { NULL },
+  };
+
+const 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,
+    sizeof (MD2_CONTEXT)
+  };
index afa6382..49b2af2 100644 (file)
@@ -83,7 +83,7 @@ md4_init (void *context, unsigned int flags)
   ctx->bctx.nblocks = 0;
   ctx->bctx.nblocks_high = 0;
   ctx->bctx.count = 0;
-  ctx->bctx.blocksize = 64;
+  ctx->bctx.blocksize_shift = _gcry_ctz(64);
   ctx->bctx.bwrite = transform;
 }
 
@@ -213,8 +213,6 @@ md4_final( void *context )
   byte *p;
   unsigned int burn;
 
-  _gcry_md_block_write(hd, NULL, 0); /* flush */;
-
   t = hd->bctx.nblocks;
   if (sizeof t == sizeof hd->bctx.nblocks)
     th = hd->bctx.nblocks_high;
@@ -234,25 +232,28 @@ md4_final( void *context )
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->bctx.count < 56 )  /* enough room */
+  if (hd->bctx.count < 56)  /* enough room */
     {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
-      while( hd->bctx.count < 56 )
-        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
+      if (hd->bctx.count < 56)
+       memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count);
+
+      /* append the 64 bit count */
+      buf_put_le32(hd->bctx.buf + 56, lsb);
+      buf_put_le32(hd->bctx.buf + 60, msb);
+      burn = transform (hd, hd->bctx.buf, 1);
     }
   else /* need one extra block */
     {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
-      while( hd->bctx.count < 64 )
-        hd->bctx.buf[hd->bctx.count++] = 0;
-      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
-      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
+      /* fill pad and next block with zeroes */
+      memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56);
+
+      /* append the 64 bit count */
+      buf_put_le32(hd->bctx.buf + 64 + 56, lsb);
+      buf_put_le32(hd->bctx.buf + 64 + 60, msb);
+      burn = transform (hd, hd->bctx.buf, 2);
     }
-  /* append the 64 bit count */
-  buf_put_le32(hd->bctx.buf + 56, lsb);
-  buf_put_le32(hd->bctx.buf + 60, msb);
-  burn = transform ( hd, hd->bctx.buf, 1 );
-  _gcry_burn_stack (burn);
 
   p = hd->bctx.buf;
 #define X(a) do { buf_put_le32(p, hd->a); p += 4; } while(0)
@@ -262,6 +263,9 @@ md4_final( void *context )
   X(D);
 #undef X
 
+  hd->bctx.count = 0;
+
+  _gcry_burn_stack (burn);
 }
 
 static byte *
@@ -271,21 +275,22 @@ md4_read (void *context)
   return hd->bctx.buf;
 }
 
-static byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */
+static const byte asn[18] = /* Object ID is 1.2.840.113549.2.4 */
   { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
     0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 };
 
-static gcry_md_oid_spec_t oid_spec_md4[] =
+static const gcry_md_oid_spec_t oid_spec_md4[] =
   {
     /* iso.member-body.us.rsadsi.digestAlgorithm.md4 */
     { "1.2.840.113549.2.4" },
     { NULL },
   };
 
-gcry_md_spec_t _gcry_digest_spec_md4 =
+const 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,
     sizeof (MD4_CONTEXT)
   };
index ed942cf..5457fc3 100644 (file)
@@ -67,7 +67,7 @@ md5_init( void *context, unsigned int flags)
   ctx->bctx.nblocks = 0;
   ctx->bctx.nblocks_high = 0;
   ctx->bctx.count = 0;
-  ctx->bctx.blocksize = 64;
+  ctx->bctx.blocksize_shift = _gcry_ctz(64);
   ctx->bctx.bwrite = transform;
 }
 
@@ -237,8 +237,6 @@ md5_final( void *context)
   byte *p;
   unsigned int burn;
 
-  _gcry_md_block_write(hd, NULL, 0); /* flush */;
-
   t = hd->bctx.nblocks;
   if (sizeof t == sizeof hd->bctx.nblocks)
     th = hd->bctx.nblocks_high;
@@ -258,25 +256,28 @@ md5_final( void *context)
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->bctx.count < 56 )  /* enough room */
+  if (hd->bctx.count < 56)  /* enough room */
     {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
-      while( hd->bctx.count < 56 )
-        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
+      if (hd->bctx.count < 56)
+       memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count);
+
+      /* append the 64 bit count */
+      buf_put_le32(hd->bctx.buf + 56, lsb);
+      buf_put_le32(hd->bctx.buf + 60, msb);
+      burn = transform (hd, hd->bctx.buf, 1);
     }
-  else  /* need one extra block */
+  else /* need one extra block */
     {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
-      while( hd->bctx.count < 64 )
-        hd->bctx.buf[hd->bctx.count++] = 0;
-      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
-      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
+      /* fill pad and next block with zeroes */
+      memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56);
+
+      /* append the 64 bit count */
+      buf_put_le32(hd->bctx.buf + 64 + 56, lsb);
+      buf_put_le32(hd->bctx.buf + 64 + 60, msb);
+      burn = transform (hd, hd->bctx.buf, 2);
     }
-  /* append the 64 bit count */
-  buf_put_le32(hd->bctx.buf + 56, lsb);
-  buf_put_le32(hd->bctx.buf + 60, msb);
-  burn = transform ( hd, hd->bctx.buf, 1 );
-  _gcry_burn_stack (burn);
 
   p = hd->bctx.buf;
 #define X(a) do { buf_put_le32(p, hd->a); p += 4; } while(0)
@@ -286,6 +287,9 @@ md5_final( void *context)
   X(D);
 #undef X
 
+  hd->bctx.count = 0;
+
+  _gcry_burn_stack (burn);
 }
 
 static byte *
@@ -295,11 +299,11 @@ md5_read( void *context )
   return hd->bctx.buf;
 }
 
-static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */
+static const byte asn[18] = /* Object ID is 1.2.840.113549.2.5 */
   { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,0x48,
     0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
 
-static gcry_md_oid_spec_t oid_spec_md5[] =
+static const gcry_md_oid_spec_t oid_spec_md5[] =
   {
     /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 (md5WithRSAEncryption) */
     { "1.2.840.113549.1.1.4" },
@@ -308,10 +312,11 @@ static gcry_md_oid_spec_t oid_spec_md5[] =
     { NULL },
   };
 
-gcry_md_spec_t _gcry_digest_spec_md5 =
+const 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,
     sizeof (MD5_CONTEXT)
   };
diff --git a/cipher/poly1305-armv7-neon.S b/cipher/poly1305-armv7-neon.S
deleted file mode 100644 (file)
index 13cb4a5..0000000
+++ /dev/null
@@ -1,744 +0,0 @@
-/* poly1305-armv7-neon.S  -  ARMv7/NEON implementation of Poly1305
- *
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Based on public domain implementation by Andrew Moon at
- *  https://github.com/floodyberry/poly1305-opt
- */
-
-#include <config.h>
-
-#if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) && \
-    defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
-    defined(HAVE_GCC_INLINE_ASM_NEON)
-
-.syntax unified
-.fpu neon
-.arm
-
-#ifdef __PIC__
-#  define GET_DATA_POINTER(reg, name, rtmp) \
-               ldr reg, 1f; \
-               ldr rtmp, 2f; \
-               b 3f; \
-       1:      .word _GLOBAL_OFFSET_TABLE_-(3f+8); \
-       2:      .word name(GOT); \
-       3:      add reg, pc, reg; \
-               ldr reg, [reg, rtmp];
-#else
-#  define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name
-#endif
-
-#define UNALIGNED_LDMIA2(ptr, l0, l1) \
-        tst ptr, #3; \
-        beq 1f; \
-        vpush {d0}; \
-        vld1.32 {d0}, [ptr]!; \
-        vmov l0, s0; \
-        vmov l1, s1; \
-        vpop {d0}; \
-        b 2f; \
-     1: ldmia ptr!, {l0-l1}; \
-     2: ;
-
-#define UNALIGNED_LDMIA4(ptr, l0, l1, l2, l3) \
-        tst ptr, #3; \
-        beq 1f; \
-        vpush {d0-d1}; \
-        vld1.32 {d0-d1}, [ptr]!; \
-        vmov l0, s0; \
-        vmov l1, s1; \
-        vmov l2, s2; \
-        vmov l3, s3; \
-        vpop {d0-d1}; \
-        b 2f; \
-     1: ldmia ptr!, {l0-l3}; \
-     2: ;
-
-.text
-
-.p2align 2
-.Lpoly1305_init_constants_neon:
-.long 0x3ffff03
-.long 0x3ffc0ff
-.long 0x3f03fff
-.long 0x00fffff
-
-.globl _gcry_poly1305_armv7_neon_init_ext
-.type  _gcry_poly1305_armv7_neon_init_ext,%function;
-_gcry_poly1305_armv7_neon_init_ext:
-.Lpoly1305_init_ext_neon_local:
-       stmfd sp!, {r4-r11, lr}
-       sub sp, sp, #32
-       mov r14, r2
-       and r2, r2, r2
-       moveq r14, #-1
-       UNALIGNED_LDMIA4(r1, r2, r3, r4, r5)
-       GET_DATA_POINTER(r7,.Lpoly1305_init_constants_neon,r8)
-       mov r6, r2
-       mov r8, r2, lsr #26
-       mov r9, r3, lsr #20
-       mov r10, r4, lsr #14
-       mov r11, r5, lsr #8
-       orr r8, r8, r3, lsl #6
-       orr r9, r9, r4, lsl #12
-       orr r10, r10, r5, lsl #18
-       ldmia r7, {r2-r5}
-       and r2, r2, r8
-       and r3, r3, r9
-       and r4, r4, r10
-       and r5, r5, r11
-       and r6, r6, 0x3ffffff
-       stmia r0!, {r2-r6}
-       eor r8, r8, r8
-       str r8, [sp, #24]
-.Lpoly1305_init_ext_neon_squareloop:
-       ldr r8, [sp, #24]
-       mov r12, #16
-       cmp r8, #2
-       beq .Lpoly1305_init_ext_neon_donesquaring
-       cmp r8, #1
-       moveq r12, #64
-       cmp r14, r12
-       bls .Lpoly1305_init_ext_neon_donesquaring
-       add r8, #1
-       str r8, [sp, #24]
-       mov r6, r6, lsl #1
-       mov r2, r2, lsl #1
-       umull r7, r8, r3, r3
-       umull r9, r10, r6, r4
-       umlal r7, r8, r6, r5
-       umlal r9, r10, r2, r3
-       add r11, r5, r5, lsl #2
-       umlal r7, r8, r2, r4
-       umlal r9, r10, r5, r11
-       str r7, [sp, #16]
-       str r8, [sp, #20]
-       mov r2, r2, lsr #1
-       mov r5, r5, lsl #1
-       str r9, [sp, #8]
-       str r10, [sp, #12]
-       umull r7, r8, r2, r2
-       umull r9, r10, r6, r2
-       add r11, r3, r3, lsl #2
-       add r12, r4, r4, lsl #2
-       umlal r7, r8, r6, r3
-       umlal r9, r10, r5, r11
-       umlal r7, r8, r5, r12
-       umlal r9, r10, r4, r12
-       mov r6, r6, lsr #1
-       mov r3, r3, lsl #1
-       add r11, r2, r2, lsl #2
-       str r7, [sp, #0]
-       str r8, [sp, #4]
-       umull r7, r8, r6, r6
-       umlal r7, r8, r3, r12
-       umlal r7, r8, r5, r11
-       and r6, r7, 0x3ffffff
-       mov r11, r7, lsr #26
-       orr r11, r11, r8, lsl #6
-       ldr r7, [sp, #0]
-       ldr r8, [sp, #4]
-       adds r9, r9, r11
-       adc r10, r10, #0
-       and r2, r9, 0x3ffffff
-       mov r11, r9, lsr #26
-       orr r11, r11, r10, lsl #6
-       ldr r9, [sp, #8]
-       ldr r10, [sp, #12]
-       adds r7, r7, r11
-       adc r8, r8, #0
-       and r3, r7, 0x3ffffff
-       mov r11, r7, lsr #26
-       orr r11, r11, r8, lsl #6
-       ldr r7, [sp, #16]
-       ldr r8, [sp, #20]
-       adds r9, r9, r11
-       adc r10, r10, #0
-       and r4, r9, 0x3ffffff
-       mov r11, r9, lsr #26
-       orr r11, r11, r10, lsl #6
-       adds r7, r7, r11
-       adc r8, r8, #0
-       and r5, r7, 0x3ffffff
-       mov r11, r7, lsr #26
-       orr r11, r11, r8, lsl #6
-       add r11, r11, r11, lsl #2
-       add r6, r6, r11
-       mov r11, r6, lsr #26
-       and r6, r6, 0x3ffffff
-       add r2, r2, r11
-       stmia r0!, {r2-r6}
-       b .Lpoly1305_init_ext_neon_squareloop
-.Lpoly1305_init_ext_neon_donesquaring:
-       mov r2, #2
-       ldr r14, [sp, #24]
-       sub r14, r2, r14
-       mov r3, r14, lsl #4
-       add r3, r3, r14, lsl #2
-       add r0, r0, r3
-       eor r2, r2, r2
-       eor r3, r3, r3
-       eor r4, r4, r4
-       eor r5, r5, r5
-       eor r6, r6, r6
-       stmia r0!, {r2-r6}
-       stmia r0!, {r2-r6}
-       UNALIGNED_LDMIA4(r1, r2, r3, r4, r5)
-       stmia r0, {r2-r6}
-       add sp, sp, #32
-       ldmfd sp!, {r4-r11, lr}
-       mov r0, #(9*4+32)
-       bx lr
-.ltorg
-.size _gcry_poly1305_armv7_neon_init_ext,.-_gcry_poly1305_armv7_neon_init_ext;
-
-.globl _gcry_poly1305_armv7_neon_blocks
-.type  _gcry_poly1305_armv7_neon_blocks,%function;
-_gcry_poly1305_armv7_neon_blocks:
-.Lpoly1305_blocks_neon_local:
-       vmov.i32 q0, #0xffffffff
-       vmov.i32 d4, #1
-       vsubw.u32 q0, q0, d4
-       vstmdb sp!, {q4,q5,q6,q7}
-       stmfd sp!, {r4-r11, lr}
-       mov r8, sp
-       and sp, sp, #~63
-       sub sp, sp, #192
-       str r0, [sp, #108]
-       str r1, [sp, #112]
-       str r2, [sp, #116]
-       str r8, [sp, #120]
-       mov r3, r0
-       mov r0, r1
-       mov r1, r2
-       mov r2, r3
-       ldr r8, [r2, #116]
-       veor d15, d15, d15
-       vorr.i32 d15, #(1 << 24)
-       tst r8, #2
-       beq .Lpoly1305_blocks_neon_skip_shift8
-       vshr.u64 d15, #32
-.Lpoly1305_blocks_neon_skip_shift8:
-       tst r8, #4
-       beq .Lpoly1305_blocks_neon_skip_shift16
-       veor d15, d15, d15
-.Lpoly1305_blocks_neon_skip_shift16:
-       vst1.64 d15, [sp, :64]
-       tst r8, #1
-       bne .Lpoly1305_blocks_neon_started
-       vld1.64 {q0-q1}, [r0]!
-       vswp d1, d2
-       vmovn.i64 d21, q0
-       vshrn.i64 d22, q0, #26
-       vshrn.u64 d24, q1, #14
-       vext.8 d0, d0, d2, #4
-       vext.8 d1, d1, d3, #4
-       vshr.u64 q1, q1, #32
-       vshrn.i64 d23, q0, #20
-       vshrn.u64 d25, q1, #8
-       vand.i32 d21, #0x03ffffff
-       vand.i32 q11, #0x03ffffff
-       vand.i32 q12, #0x03ffffff
-       orr r8, r8, #1
-       sub r1, r1, #32
-       str r8, [r2, #116]
-       vorr d25, d25, d15
-       b .Lpoly1305_blocks_neon_setupr20
-.Lpoly1305_blocks_neon_started:
-       add r9, r2, #60
-       vldm r9, {d21-d25}
-.Lpoly1305_blocks_neon_setupr20:
-       vmov.i32 d0, #5
-       tst r8, #(8|16)
-       beq .Lpoly1305_blocks_neon_setupr20_simple
-       tst r8, #(8)
-       beq .Lpoly1305_blocks_neon_setupr20_r_1
-       mov r9, r2
-       add r10, r2, #20
-       vld1.64 {q9}, [r9]!
-       vld1.64 {q8}, [r10]!
-       vld1.64 {d2}, [r9]
-       vld1.64 {d20}, [r10]
-       b .Lpoly1305_blocks_neon_setupr20_hard
-.Lpoly1305_blocks_neon_setupr20_r_1:
-       mov r9, r2
-       vmov.i32 d2, #1
-       vld1.64 {q8}, [r9]!
-       veor q9, q9, q9
-       vshr.u64 d2, d2, #32
-       vld1.64 {d20}, [r9]
-.Lpoly1305_blocks_neon_setupr20_hard:
-       vzip.i32 q8, q9
-       vzip.i32 d20, d2
-       b .Lpoly1305_blocks_neon_setups20
-.Lpoly1305_blocks_neon_setupr20_simple:
-       add r9, r2, #20
-       vld1.64 {d2-d4}, [r9]
-       vdup.32 d16, d2[0]
-       vdup.32 d17, d2[1]
-       vdup.32 d18, d3[0]
-       vdup.32 d19, d3[1]
-       vdup.32 d20, d4[0]
-.Lpoly1305_blocks_neon_setups20:
-       vmul.i32 q13, q8, d0[0]
-       vmov.i64 q15, 0x00000000ffffffff
-       vmul.i32 q14, q9, d0[0]
-       vshr.u64 q15, q15, #6
-       cmp r1, #64
-       blo .Lpoly1305_blocks_neon_try32
-       add r9, sp, #16
-       add r10, r2, #40
-       add r11, sp, #64
-       str r1, [sp, #116]
-       vld1.64 {d10-d12}, [r10]
-       vmov d14, d12
-       vmul.i32 q6, q5, d0[0]
-.Lpoly1305_blocks_neon_mainloop:
-       UNALIGNED_LDMIA4(r0, r2, r3, r4, r5)
-       vmull.u32 q0, d25, d12[0]
-       mov r7, r2, lsr #26
-       vmlal.u32 q0, d24, d12[1]
-       mov r8, r3, lsr #20
-       ldr r6, [sp, #0]
-       vmlal.u32 q0, d23, d13[0]
-       mov r9, r4, lsr #14
-       vmlal.u32 q0, d22, d13[1]
-       orr r6, r6, r5, lsr #8
-       vmlal.u32 q0, d21, d14[0]
-       orr r3, r7, r3, lsl #6
-       vmull.u32 q1, d25, d12[1]
-       orr r4, r8, r4, lsl #12
-       orr r5, r9, r5, lsl #18
-       vmlal.u32 q1, d24, d13[0]
-       UNALIGNED_LDMIA4(r0, r7, r8, r9, r10)
-       vmlal.u32 q1, d23, d13[1]
-       mov r1, r7, lsr #26
-       vmlal.u32 q1, d22, d14[0]
-       ldr r11, [sp, #4]
-       mov r12, r8, lsr #20
-       vmlal.u32 q1, d21, d10[0]
-       mov r14, r9, lsr #14
-       vmull.u32 q2, d25, d13[0]
-       orr r11, r11, r10, lsr #8
-       orr r8, r1, r8, lsl #6
-       vmlal.u32 q2, d24, d13[1]
-       orr r9, r12, r9, lsl #12
-       vmlal.u32 q2, d23, d14[0]
-       orr r10, r14, r10, lsl #18
-       vmlal.u32 q2, d22, d10[0]
-       mov r12, r3
-       and r2, r2, #0x3ffffff
-       vmlal.u32 q2, d21, d10[1]
-       mov r14, r5
-       vmull.u32 q3, d25, d13[1]
-       and r3, r7, #0x3ffffff
-       vmlal.u32 q3, d24, d14[0]
-       and r5, r8, #0x3ffffff
-       vmlal.u32 q3, d23, d10[0]
-       and r7, r9, #0x3ffffff
-       vmlal.u32 q3, d22, d10[1]
-       and r8, r14, #0x3ffffff
-       vmlal.u32 q3, d21, d11[0]
-       and r9, r10, #0x3ffffff
-       add r14, sp, #128
-       vmull.u32 q4, d25, d14[0]
-       mov r10, r6
-       vmlal.u32 q4, d24, d10[0]
-       and r6, r4, #0x3ffffff
-       vmlal.u32 q4, d23, d10[1]
-       and r4, r12, #0x3ffffff
-       vmlal.u32 q4, d22, d11[0]
-       stm r14, {r2-r11}
-       vmlal.u32 q4, d21, d11[1]
-       vld1.64 {d21-d24}, [r14, :256]!
-       vld1.64 {d25}, [r14, :64]
-       UNALIGNED_LDMIA4(r0, r2, r3, r4, r5)
-       vmlal.u32 q0, d25, d26
-       mov r7, r2, lsr #26
-       vmlal.u32 q0, d24, d27
-       ldr r6, [sp, #0]
-       mov r8, r3, lsr #20
-       vmlal.u32 q0, d23, d28
-       mov r9, r4, lsr #14
-       vmlal.u32 q0, d22, d29
-       orr r6, r6, r5, lsr #8
-       vmlal.u32 q0, d21, d20
-       orr r3, r7, r3, lsl #6
-       vmlal.u32 q1, d25, d27
-       orr r4, r8, r4, lsl #12
-       orr r5, r9, r5, lsl #18
-       vmlal.u32 q1, d24, d28
-       UNALIGNED_LDMIA4(r0, r7, r8, r9, r10)
-       vmlal.u32 q1, d23, d29
-       mov r1, r7, lsr #26
-       vmlal.u32 q1, d22, d20
-       ldr r11, [sp, #4]
-       mov r12, r8, lsr #20
-       vmlal.u32 q1, d21, d16
-       mov r14, r9, lsr #14
-       vmlal.u32 q2, d25, d28
-       orr r11, r11, r10, lsr #8
-       orr r8, r1, r8, lsl #6
-       orr r9, r12, r9, lsl #12
-       vmlal.u32 q2, d24, d29
-       orr r10, r14, r10, lsl #18
-       and r2, r2, #0x3ffffff
-       mov r12, r3
-       vmlal.u32 q2, d23, d20
-       mov r14, r5
-       vmlal.u32 q2, d22, d16
-       and r3, r7, #0x3ffffff
-       vmlal.u32 q2, d21, d17
-       and r5, r8, #0x3ffffff
-       vmlal.u32 q3, d25, d29
-       and r7, r9, #0x3ffffff
-       vmlal.u32 q3, d24, d20
-       and r8, r14, #0x3ffffff
-       vmlal.u32 q3, d23, d16
-       and r9, r10, #0x3ffffff
-       vmlal.u32 q3, d22, d17
-       add r14, sp, #128
-       vmlal.u32 q3, d21, d18
-       mov r10, r6
-       vmlal.u32 q4, d25, d20
-       vmlal.u32 q4, d24, d16
-       and r6, r4, #0x3ffffff
-       vmlal.u32 q4, d23, d17
-       and r4, r12, #0x3ffffff
-       vmlal.u32 q4, d22, d18
-       stm r14, {r2-r11}
-       vmlal.u32 q4, d21, d19
-       vld1.64 {d21-d24}, [r14, :256]!
-       vld1.64 {d25}, [r14, :64]
-       vaddw.u32 q0, q0, d21
-       vaddw.u32 q1, q1, d22
-       vaddw.u32 q2, q2, d23
-       vaddw.u32 q3, q3, d24
-       vaddw.u32 q4, q4, d25
-       vshr.u64 q11, q0, #26
-       vand q0, q0, q15
-       vadd.i64 q1, q1, q11
-       vshr.u64 q12, q3, #26
-       vand q3, q3, q15
-       vadd.i64 q4, q4, q12
-       vshr.u64 q11, q1, #26
-       vand q1, q1, q15
-       vadd.i64 q2, q2, q11
-       vshr.u64 q12, q4, #26
-       vand q4, q4, q15
-       vadd.i64 q0, q0, q12
-       vshl.i64 q12, q12, #2
-       ldr r1, [sp, #116]
-       vadd.i64 q0, q0, q12
-       vshr.u64 q11, q2, #26
-       vand q2, q2, q15
-       vadd.i64 q3, q3, q11
-       sub r1, #64
-       vshr.u64 q12, q0, #26
-       vand q0, q0, q15
-       vadd.i64 q1, q1, q12
-       cmp r1, #64
-       vshr.u64 q11, q3, #26
-       vand q3, q3, q15
-       vadd.i64 q4, q4, q11
-       vmovn.i64 d21, q0
-       str r1, [sp, #116]
-       vmovn.i64 d22, q1
-       vmovn.i64 d23, q2
-       vmovn.i64 d24, q3
-       vmovn.i64 d25, q4
-       bhs .Lpoly1305_blocks_neon_mainloop
-.Lpoly1305_blocks_neon_try32:
-       cmp r1, #32
-       blo .Lpoly1305_blocks_neon_done
-       tst r0, r0
-       bne .Lpoly1305_blocks_loadm32
-       veor q0, q0, q0
-       veor q1, q1, q1
-       veor q2, q2, q2
-       veor q3, q3, q3
-       veor q4, q4, q4
-       b .Lpoly1305_blocks_continue32
-.Lpoly1305_blocks_loadm32:
-       vld1.64 {q0-q1}, [r0]!
-       veor q4, q4, q4
-       vswp d1, d2
-       veor q3, q3, q3
-       vtrn.32 q0, q4
-       vtrn.32 q1, q3
-       vshl.i64 q2, q1, #12
-       vshl.i64 q3, q3, #18
-       vshl.i64 q1, q4, #6
-       vmovl.u32 q4, d15
-.Lpoly1305_blocks_continue32:
-       vmlal.u32 q0, d25, d26
-       vmlal.u32 q0, d24, d27
-       vmlal.u32 q0, d23, d28
-       vmlal.u32 q0, d22, d29
-       vmlal.u32 q0, d21, d20
-       vmlal.u32 q1, d25, d27
-       vmlal.u32 q1, d24, d28
-       vmlal.u32 q1, d23, d29
-       vmlal.u32 q1, d22, d20
-       vmlal.u32 q1, d21, d16
-       vmlal.u32 q2, d25, d28
-       vmlal.u32 q2, d24, d29
-       vmlal.u32 q2, d23, d20
-       vmlal.u32 q2, d22, d16
-       vmlal.u32 q2, d21, d17
-       vmlal.u32 q3, d25, d29
-       vmlal.u32 q3, d24, d20
-       vmlal.u32 q3, d23, d16
-       vmlal.u32 q3, d22, d17
-       vmlal.u32 q3, d21, d18
-       vmlal.u32 q4, d25, d20
-       vmlal.u32 q4, d24, d16
-       vmlal.u32 q4, d23, d17
-       vmlal.u32 q4, d22, d18
-       vmlal.u32 q4, d21, d19
-       vshr.u64 q11, q0, #26
-       vand q0, q0, q15
-       vadd.i64 q1, q1, q11
-       vshr.u64 q12, q3, #26
-       vand q3, q3, q15
-       vadd.i64 q4, q4, q12
-       vshr.u64 q11, q1, #26
-       vand q1, q1, q15
-       vadd.i64 q2, q2, q11
-       vshr.u64 q12, q4, #26
-       vand q4, q4, q15
-       vadd.i64 q0, q0, q12
-       vshl.i64 q12, q12, #2
-       vadd.i64 q0, q0, q12
-       vshr.u64 q11, q2, #26
-       vand q2, q2, q15
-       vadd.i64 q3, q3, q11
-       vshr.u64 q12, q0, #26
-       vand q0, q0, q15
-       vadd.i64 q1, q1, q12
-       vshr.u64 q11, q3, #26
-       vand q3, q3, q15
-       vadd.i64 q4, q4, q11
-       vmovn.i64 d21, q0
-       vmovn.i64 d22, q1
-       vmovn.i64 d23, q2
-       vmovn.i64 d24, q3
-       vmovn.i64 d25, q4
-.Lpoly1305_blocks_neon_done:
-       tst r0, r0
-       beq .Lpoly1305_blocks_neon_final
-       ldr r2, [sp, #108]
-       add r2, r2, #60
-       vst1.64 {d21}, [r2]!
-       vst1.64 {d22-d25}, [r2]
-       b .Lpoly1305_blocks_neon_leave
-.Lpoly1305_blocks_neon_final:
-       vadd.u32 d10, d0, d1
-       vadd.u32 d13, d2, d3
-       vadd.u32 d11, d4, d5
-       ldr r5, [sp, #108]
-       vadd.u32 d14, d6, d7
-       vadd.u32 d12, d8, d9
-       vtrn.32 d10, d13
-       vtrn.32 d11, d14
-       vst1.64 {d10-d12}, [sp]
-       ldm sp, {r0-r4}
-       mov r12, r0, lsr #26
-       and r0, r0, #0x3ffffff
-       add r1, r1, r12
-       mov r12, r1, lsr #26
-       and r1, r1, #0x3ffffff
-       add r2, r2, r12
-       mov r12, r2, lsr #26
-       and r2, r2, #0x3ffffff
-       add r3, r3, r12
-       mov r12, r3, lsr #26
-       and r3, r3, #0x3ffffff
-       add r4, r4, r12
-       mov r12, r4, lsr #26
-       and r4, r4, #0x3ffffff
-       add r12, r12, r12, lsl #2
-       add r0, r0, r12
-       mov r12, r0, lsr #26
-       and r0, r0, #0x3ffffff
-       add r1, r1, r12
-       mov r12, r1, lsr #26
-       and r1, r1, #0x3ffffff
-       add r2, r2, r12
-       mov r12, r2, lsr #26
-       and r2, r2, #0x3ffffff
-       add r3, r3, r12
-       mov r12, r3, lsr #26
-       and r3, r3, #0x3ffffff
-       add r4, r4, r12
-       mov r12, r4, lsr #26
-       and r4, r4, #0x3ffffff
-       add r12, r12, r12, lsl #2
-       add r0, r0, r12
-       mov r12, r0, lsr #26
-       and r0, r0, #0x3ffffff
-       add r1, r1, r12
-       add r6, r0, #5
-       mov r12, r6, lsr #26
-       and r6, r6, #0x3ffffff
-       add r7, r1, r12
-       mov r12, r7, lsr #26
-       and r7, r7, #0x3ffffff
-       add r10, r2, r12
-       mov r12, r10, lsr #26
-       and r10, r10, #0x3ffffff
-       add r11, r3, r12
-       mov r12, #-(1 << 26)
-       add r12, r12, r11, lsr #26
-       and r11, r11, #0x3ffffff
-       add r14, r4, r12
-       mov r12, r14, lsr #31
-       sub r12, #1
-       and r6, r6, r12
-       and r7, r7, r12
-       and r10, r10, r12
-       and r11, r11, r12
-       and r14, r14, r12
-       mvn r12, r12
-       and r0, r0, r12
-       and r1, r1, r12
-       and r2, r2, r12
-       and r3, r3, r12
-       and r4, r4, r12
-       orr r0, r0, r6
-       orr r1, r1, r7
-       orr r2, r2, r10
-       orr r3, r3, r11
-       orr r4, r4, r14
-       orr r0, r0, r1, lsl #26
-       lsr r1, r1, #6
-       orr r1, r1, r2, lsl #20
-       lsr r2, r2, #12
-       orr r2, r2, r3, lsl #14
-       lsr r3, r3, #18
-       orr r3, r3, r4, lsl #8
-       add r5, r5, #60
-       stm r5, {r0-r3}
-.Lpoly1305_blocks_neon_leave:
-       sub r0, sp, #8
-       ldr sp, [sp, #120]
-       ldmfd sp!, {r4-r11, lr}
-       vldm sp!, {q4-q7}
-       sub r0, sp, r0
-       bx lr
-.size _gcry_poly1305_armv7_neon_blocks,.-_gcry_poly1305_armv7_neon_blocks;
-
-.globl _gcry_poly1305_armv7_neon_finish_ext
-.type  _gcry_poly1305_armv7_neon_finish_ext,%function;
-_gcry_poly1305_armv7_neon_finish_ext:
-.Lpoly1305_finish_ext_neon_local:
-       stmfd sp!, {r4-r11, lr}
-       sub sp, sp, #32
-       mov r5, r0
-       mov r6, r1
-       mov r7, r2
-       mov r8, r3
-       ands r7, r7, r7
-       beq .Lpoly1305_finish_ext_neon_noremaining
-       mov r9, sp
-       veor q0, q0, q0
-       veor q1, q1, q1
-       vst1.64 {q0-q1}, [sp]
-       tst r7, #16
-       beq .Lpoly1305_finish_ext_neon_skip16
-       vld1.u64 {q0}, [r1]!
-       vst1.64 {q0}, [r9]!
-.Lpoly1305_finish_ext_neon_skip16:
-       tst r7, #8
-       beq .Lpoly1305_finish_ext_neon_skip8
-       UNALIGNED_LDMIA2(r1, r10, r11)
-       stmia r9!, {r10-r11}
-.Lpoly1305_finish_ext_neon_skip8:
-       tst r7, #4
-       beq .Lpoly1305_finish_ext_neon_skip4
-       ldr r10, [r1], #4
-       str r10, [r9], #4
-.Lpoly1305_finish_ext_neon_skip4:
-       tst r7, #2
-       beq .Lpoly1305_finish_ext_neon_skip2
-       ldrh r10, [r1], #2
-       strh r10, [r9], #2
-.Lpoly1305_finish_ext_neon_skip2:
-       tst r7, #1
-       beq .Lpoly1305_finish_ext_neon_skip1
-       ldrb r10, [r1], #1
-       strb r10, [r9], #1
-.Lpoly1305_finish_ext_neon_skip1:
-       cmp r7, #16
-       beq .Lpoly1305_finish_ext_neon_skipfinalbit
-       mov r10, #1
-       strb r10, [r9]
-.Lpoly1305_finish_ext_neon_skipfinalbit:
-       ldr r10, [r5, #116]
-       orrhs r10, #2
-       orrlo r10, #4
-       str r10, [r5, #116]
-       mov r0, r5
-       mov r1, sp
-       mov r2, #32
-       bl .Lpoly1305_blocks_neon_local
-.Lpoly1305_finish_ext_neon_noremaining:
-       ldr r10, [r5, #116]
-       tst r10, #1
-       beq .Lpoly1305_finish_ext_neon_notstarted
-       cmp r7, #0
-       beq .Lpoly1305_finish_ext_neon_user2r
-       cmp r7, #16
-       bls .Lpoly1305_finish_ext_neon_user1
-.Lpoly1305_finish_ext_neon_user2r:
-       orr r10, r10, #8
-       b .Lpoly1305_finish_ext_neon_finalblock
-.Lpoly1305_finish_ext_neon_user1:
-       orr r10, r10, #16
-.Lpoly1305_finish_ext_neon_finalblock:
-       str r10, [r5, #116]
-       mov r0, r5
-       eor r1, r1, r1
-       mov r2, #32
-       bl .Lpoly1305_blocks_neon_local
-.Lpoly1305_finish_ext_neon_notstarted:
-       add r0, r5, #60
-       add r9, r5, #100
-       ldm r0, {r0-r3}
-       ldm r9, {r9-r12}
-       adds r0, r0, r9
-       adcs r1, r1, r10
-       adcs r2, r2, r11
-       adcs r3, r3, r12
-       stm r8, {r0-r3}
-       veor q0, q0, q0
-       veor q1, q1, q1
-       veor q2, q2, q2
-       veor q3, q3, q3
-       vstmia r5!, {q0-q3}
-       vstm r5, {q0-q3}
-       add sp, sp, #32
-       ldmfd sp!, {r4-r11, lr}
-       mov r0, #(9*4+32)
-       bx lr
-.size _gcry_poly1305_armv7_neon_finish_ext,.-_gcry_poly1305_armv7_neon_finish_ext;
-
-#endif
diff --git a/cipher/poly1305-avx2-amd64.S b/cipher/poly1305-avx2-amd64.S
deleted file mode 100644 (file)
index 9362a5a..0000000
+++ /dev/null
@@ -1,962 +0,0 @@
-/* poly1305-avx2-amd64.S  -  AMD64/AVX2 implementation of Poly1305
- *
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Based on public domain implementation by Andrew Moon at
- *  https://github.com/floodyberry/poly1305-opt
- */
-
-#include <config.h>
-
-#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
-    defined(ENABLE_AVX2_SUPPORT)
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-
-.text
-
-
-.align 8
-.globl _gcry_poly1305_amd64_avx2_init_ext
-ELF(.type  _gcry_poly1305_amd64_avx2_init_ext,@function;)
-_gcry_poly1305_amd64_avx2_init_ext:
-.Lpoly1305_init_ext_avx2_local:
-       xor %edx, %edx
-       vzeroupper
-       pushq %r12
-       pushq %r13
-       pushq %r14
-       pushq %r15
-       pushq %rbx
-       movq %rdx, %rcx
-       vpxor %ymm0, %ymm0, %ymm0
-       movq $-1, %r8
-       testq %rcx, %rcx
-       vmovdqu %ymm0, (%rdi)
-       vmovdqu %ymm0, 32(%rdi)
-       vmovdqu %ymm0, 64(%rdi)
-       vmovdqu %ymm0, 96(%rdi)
-       vmovdqu %ymm0, 128(%rdi)
-       movq 8(%rsi), %r9
-       cmove %r8, %rcx
-       movq $0xffc0fffffff, %r8
-       movq %r9, %r13
-       movq (%rsi), %r10
-       andq %r10, %r8
-       shrq $44, %r10
-       movq %r8, %r14
-       shlq $20, %r13
-       orq %r13, %r10
-       movq $0xfffffc0ffff, %r13
-       shrq $24, %r9
-       andq %r13, %r10
-       movq $0xffffffc0f, %r13
-       andq %r13, %r9
-       movl %r8d, %r13d
-       andl $67108863, %r13d
-       movl %r13d, 164(%rdi)
-       movq %r10, %r13
-       shrq $26, %r14
-       shlq $18, %r13
-       orq %r13, %r14
-       movq %r10, %r13
-       shrq $8, %r13
-       andl $67108863, %r14d
-       andl $67108863, %r13d
-       movl %r14d, 172(%rdi)
-       movq %r10, %r14
-       movl %r13d, 180(%rdi)
-       movq %r9, %r13
-       shrq $34, %r14
-       shlq $10, %r13
-       orq %r13, %r14
-       movq %r9, %r13
-       shrq $16, %r13
-       andl $67108863, %r14d
-       movl %r14d, 188(%rdi)
-       movl %r13d, 196(%rdi)
-       cmpq $16, %rcx
-       jbe .Lpoly1305_init_ext_avx2_continue
-       lea (%r9,%r9,4), %r11
-       shlq $2, %r11
-       lea (%r10,%r10), %rax
-       mulq %r11
-       movq %rax, %r13
-       movq %r8, %rax
-       movq %rdx, %r14
-       mulq %r8
-       addq %rax, %r13
-       lea (%r8,%r8), %rax
-       movq %r13, %r12
-       adcq %rdx, %r14
-       mulq %r10
-       shlq $20, %r14
-       movq %rax, %r15
-       shrq $44, %r12
-       movq %r11, %rax
-       orq %r12, %r14
-       movq %rdx, %r12
-       mulq %r9
-       addq %rax, %r15
-       movq %r8, %rax
-       adcq %rdx, %r12
-       addq %r15, %r14
-       lea (%r9,%r9), %r15
-       movq %r14, %rbx
-       adcq $0, %r12
-       mulq %r15
-       shlq $20, %r12
-       movq %rdx, %r11
-       shrq $44, %rbx
-       orq %rbx, %r12
-       movq %rax, %rbx
-       movq %r10, %rax
-       mulq %r10
-       addq %rax, %rbx
-       adcq %rdx, %r11
-       addq %rbx, %r12
-       movq $0xfffffffffff, %rbx
-       movq %r12, %r15
-       adcq $0, %r11
-       andq %rbx, %r13
-       shlq $22, %r11
-       andq %rbx, %r14
-       shrq $42, %r15
-       orq %r15, %r11
-       lea (%r11,%r11,4), %r11
-       addq %r11, %r13
-       movq %rbx, %r11
-       andq %r13, %r11
-       shrq $44, %r13
-       movq %r11, %r15
-       addq %r13, %r14
-       movq $0x3ffffffffff, %r13
-       andq %r14, %rbx
-       andq %r13, %r12
-       movq %rbx, %r13
-       shrq $26, %r15
-       shlq $18, %r13
-       orq %r13, %r15
-       movq %rbx, %r13
-       shrq $44, %r14
-       shrq $8, %r13
-       addq %r14, %r12
-       movl %r11d, %r14d
-       andl $67108863, %r15d
-       andl $67108863, %r14d
-       andl $67108863, %r13d
-       movl %r14d, 204(%rdi)
-       movq %rbx, %r14
-       movl %r13d, 220(%rdi)
-       movq %r12, %r13
-       shrq $34, %r14
-       shlq $10, %r13
-       orq %r13, %r14
-       movq %r12, %r13
-       shrq $16, %r13
-       andl $67108863, %r14d
-       movl %r15d, 212(%rdi)
-       movl %r14d, 228(%rdi)
-       movl %r13d, 236(%rdi)
-       cmpq $32, %rcx
-       jbe .Lpoly1305_init_ext_avx2_continue
-       movq %r9, %rax
-       lea (%rbx,%rbx,4), %r14
-       shlq $2, %r14
-       mulq %r14
-       movq %rdi, -32(%rsp)
-       lea (%r12,%r12,4), %rdi
-       shlq $2, %rdi
-       movq %rax, %r14
-       movq %r10, %rax
-       movq %rdx, %r15
-       mulq %rdi
-       movq %rax, %r13
-       movq %r11, %rax
-       movq %rcx, -16(%rsp)
-       movq %rdx, %rcx
-       mulq %r8
-       addq %rax, %r13
-       movq %rdi, %rax
-       movq %rsi, -24(%rsp)
-       adcq %rdx, %rcx
-       addq %r13, %r14
-       adcq %rcx, %r15
-       movq %r14, %rcx
-       mulq %r9
-       shlq $20, %r15
-       movq %rax, %r13
-       shrq $44, %rcx
-       movq %r11, %rax
-       orq %rcx, %r15
-       movq %rdx, %rcx
-       mulq %r10
-       movq %rax, %rsi
-       movq %rbx, %rax
-       movq %rdx, %rdi
-       mulq %r8
-       addq %rax, %rsi
-       movq %r11, %rax
-       adcq %rdx, %rdi
-       addq %rsi, %r13
-       adcq %rdi, %rcx
-       addq %r13, %r15
-       movq %r15, %rdi
-       adcq $0, %rcx
-       mulq %r9
-       shlq $20, %rcx
-       movq %rdx, %rsi
-       shrq $44, %rdi
-       orq %rdi, %rcx
-       movq %rax, %rdi
-       movq %rbx, %rax
-       mulq %r10
-       movq %rax, %r9
-       movq %r8, %rax
-       movq %rdx, %r10
-       movq $0xfffffffffff, %r8
-       mulq %r12
-       addq %rax, %r9
-       adcq %rdx, %r10
-       andq %r8, %r14
-       addq %r9, %rdi
-       adcq %r10, %rsi
-       andq %r8, %r15
-       addq %rdi, %rcx
-       movq $0x3ffffffffff, %rdi
-       movq %rcx, %r10
-       adcq $0, %rsi
-       andq %rdi, %rcx
-       shlq $22, %rsi
-       shrq $42, %r10
-       orq %r10, %rsi
-       movq -32(%rsp), %rdi
-       lea (%rsi,%rsi,4), %r9
-       movq %r8, %rsi
-       addq %r9, %r14
-       andq %r14, %rsi
-       shrq $44, %r14
-       addq %r14, %r15
-       andq %r15, %r8
-       shrq $44, %r15
-       movq %r8, %r14
-       addq %r15, %rcx
-       movl %esi, %r15d
-       movq %rcx, %r10
-       movq %r8, %r9
-       shrq $26, %rsi
-       andl $67108863, %r15d
-       shlq $18, %r14
-       shrq $34, %r8
-       orq %r14, %rsi
-       shlq $10, %r10
-       shrq $8, %r9
-       orq %r10, %r8
-       shrq $16, %rcx
-       andl $67108863, %esi
-       movl %esi, 252(%rdi)
-       andl $67108863, %r9d
-       movl %ecx, 276(%rdi)
-       andl $67108863, %r8d
-       movl %r15d, 244(%rdi)
-       movl %r9d, 260(%rdi)
-       movl %r8d, 268(%rdi)
-       movq -16(%rsp), %rcx
-       movq -24(%rsp), %rsi
-.Lpoly1305_init_ext_avx2_continue:
-       movl 16(%rsi), %r8d
-       movl %r8d, 284(%rdi)
-       movl 20(%rsi), %r9d
-       movl %r9d, 292(%rdi)
-       movl 24(%rsi), %r10d
-       movl %r10d, 300(%rdi)
-       movl 28(%rsi), %esi
-       movl %esi, 308(%rdi)
-       cmpq $48, %rcx
-       jbe .Lpoly1305_init_ext_avx2_done
-       lea (%r12,%r12,4), %r9
-       shlq $2, %r9
-       lea (%rbx,%rbx), %rax
-       mulq %r9
-       movq %rax, %rsi
-       movq %r11, %rax
-       movq %rdx, %r8
-       mulq %r11
-       addq %rax, %rsi
-       lea (%r11,%r11), %rax
-       movq %rsi, %r10
-       adcq %rdx, %r8
-       mulq %rbx
-       movq %rax, %r13
-       movq %r12, %rax
-       movq %rdx, %rcx
-       addq %r12, %r12
-       mulq %r9
-       addq %rax, %r13
-       movq %r11, %rax
-       movq $0xfffffffffff, %r9
-       adcq %rdx, %rcx
-       andq %r9, %rsi
-       mulq %r12
-       shlq $20, %r8
-       movq %rax, %r11
-       shrq $44, %r10
-       movq %rbx, %rax
-       orq %r10, %r8
-       movq %rdx, %r12
-       mulq %rbx
-       addq %r13, %r8
-       movq %r8, %r14
-       adcq $0, %rcx
-       andq %r9, %r8
-       addq %rax, %r11
-       adcq %rdx, %r12
-       shlq $20, %rcx
-       shrq $44, %r14
-       orq %r14, %rcx
-       addq %r11, %rcx
-       movq %rcx, %rbx
-       adcq $0, %r12
-       shlq $22, %r12
-       shrq $42, %rbx
-       orq %rbx, %r12
-       movq %r9, %rbx
-       lea (%r12,%r12,4), %r15
-       addq %r15, %rsi
-       andq %rsi, %rbx
-       shrq $44, %rsi
-       movl %ebx, %r11d
-       addq %rsi, %r8
-       movq $0x3ffffffffff, %rsi
-       andq %r8, %r9
-       andq %rsi, %rcx
-       shrq $44, %r8
-       movq %r9, %rax
-       addq %r8, %rcx
-       movq %r9, %r8
-       movq %rcx, %r10
-       andl $67108863, %r11d
-       shrq $26, %rbx
-       shlq $18, %r8
-       shrq $34, %r9
-       orq %r8, %rbx
-       shlq $10, %r10
-       shrq $8, %rax
-       orq %r10, %r9
-       shrq $16, %rcx
-       andl $67108863, %ebx
-       andl $67108863, %eax
-       andl $67108863, %r9d
-       movl %r11d, 184(%rdi)
-       movl %r11d, 176(%rdi)
-       movl %r11d, 168(%rdi)
-       movl %r11d, 160(%rdi)
-       movl %ebx, 216(%rdi)
-       movl %ebx, 208(%rdi)
-       movl %ebx, 200(%rdi)
-       movl %ebx, 192(%rdi)
-       movl %eax, 248(%rdi)
-       movl %eax, 240(%rdi)
-       movl %eax, 232(%rdi)
-       movl %eax, 224(%rdi)
-       movl %r9d, 280(%rdi)
-       movl %r9d, 272(%rdi)
-       movl %r9d, 264(%rdi)
-       movl %r9d, 256(%rdi)
-       movl %ecx, 312(%rdi)
-       movl %ecx, 304(%rdi)
-       movl %ecx, 296(%rdi)
-       movl %ecx, 288(%rdi)
-.Lpoly1305_init_ext_avx2_done:
-       movq $0, 320(%rdi)
-       vzeroall
-       popq %rbx
-       popq %r15
-       popq %r14
-       popq %r13
-       popq %r12
-       ret
-ELF(.size _gcry_poly1305_amd64_avx2_init_ext,.-_gcry_poly1305_amd64_avx2_init_ext;)
-
-
-.align 8
-.globl _gcry_poly1305_amd64_avx2_blocks
-ELF(.type  _gcry_poly1305_amd64_avx2_blocks,@function;)
-_gcry_poly1305_amd64_avx2_blocks:
-.Lpoly1305_blocks_avx2_local:
-       vzeroupper
-       pushq %rbp
-       movq %rsp, %rbp
-       pushq %rbx
-       andq $-64, %rsp
-       subq $200, %rsp
-       movl $((1<<26)-1), %r8d
-       movl $(5), %r9d
-       movl $((1<<24)), %r10d
-       vmovd %r8d, %xmm0
-       vmovd %r9d, %xmm8
-       vmovd %r10d, %xmm7
-       vpbroadcastq %xmm0, %ymm0
-       vpbroadcastq %xmm8, %ymm8
-       vpbroadcastq %xmm7, %ymm7
-       vmovdqa %ymm7, 168(%rsp)
-       movq 320(%rdi), %rax
-       testb $60, %al
-       je .Lpoly1305_blocks_avx2_9
-       vmovdqa 168(%rsp), %ymm7
-       vpsrldq $8, %ymm7, %ymm1
-       vmovdqa %ymm1, 168(%rsp)
-       testb $4, %al
-       je .Lpoly1305_blocks_avx2_10
-       vpermq $192, %ymm1, %ymm7
-       vmovdqa %ymm7, 168(%rsp)
-.Lpoly1305_blocks_avx2_10:
-       testb $8, %al
-       je .Lpoly1305_blocks_avx2_11
-       vpermq $240, 168(%rsp), %ymm7
-       vmovdqa %ymm7, 168(%rsp)
-.Lpoly1305_blocks_avx2_11:
-       testb $16, %al
-       je .Lpoly1305_blocks_avx2_12
-       vpermq $252, 168(%rsp), %ymm6
-       vmovdqa %ymm6, 168(%rsp)
-.Lpoly1305_blocks_avx2_12:
-       testb $32, %al
-       je .Lpoly1305_blocks_avx2_9
-       vpxor %xmm6, %xmm6, %xmm6
-       vmovdqa %ymm6, 168(%rsp)
-.Lpoly1305_blocks_avx2_9:
-       testb $1, %al
-       jne .Lpoly1305_blocks_avx2_13
-       vmovdqu (%rsi), %ymm3
-       vmovdqu 32(%rsi), %ymm1
-       vpunpcklqdq %ymm1, %ymm3, %ymm2
-       vpunpckhqdq %ymm1, %ymm3, %ymm1
-       vpermq $216, %ymm2, %ymm2
-       vpermq $216, %ymm1, %ymm1
-       vpand %ymm2, %ymm0, %ymm5
-       vpsrlq $26, %ymm2, %ymm4
-       vpand %ymm4, %ymm0, %ymm4
-       vpsllq $12, %ymm1, %ymm3
-       vpsrlq $52, %ymm2, %ymm2
-       vpor %ymm3, %ymm2, %ymm2
-       vpand %ymm2, %ymm0, %ymm3
-       vpsrlq $26, %ymm2, %ymm2
-       vpand %ymm2, %ymm0, %ymm2
-       vpsrlq $40, %ymm1, %ymm1
-       vpor 168(%rsp), %ymm1, %ymm1
-       addq $64, %rsi
-       subq $64, %rdx
-       orq $1, 320(%rdi)
-       jmp .Lpoly1305_blocks_avx2_14
-.Lpoly1305_blocks_avx2_13:
-       vmovdqa (%rdi), %ymm5
-       vmovdqa 32(%rdi), %ymm4
-       vmovdqa 64(%rdi), %ymm3
-       vmovdqa 96(%rdi), %ymm2
-       vmovdqa 128(%rdi), %ymm1
-.Lpoly1305_blocks_avx2_14:
-       cmpq $63, %rdx
-       jbe .Lpoly1305_blocks_avx2_15
-       vmovdqa 160(%rdi), %ymm6
-       vmovdqa %ymm8, 136(%rsp)
-       vmovdqa 192(%rdi), %ymm7
-       vpmuludq %ymm8, %ymm7, %ymm11
-       vmovdqa %ymm11, 104(%rsp)
-       vmovdqa 224(%rdi), %ymm11
-       vmovdqa %ymm11, 72(%rsp)
-       vpmuludq %ymm11, %ymm8, %ymm11
-       vmovdqa %ymm11, 40(%rsp)
-       vmovdqa 256(%rdi), %ymm11
-       vmovdqa %ymm11, 8(%rsp)
-       vpmuludq %ymm11, %ymm8, %ymm11
-       vmovdqa %ymm11, -24(%rsp)
-       vmovdqa 288(%rdi), %ymm13
-       vmovdqa %ymm13, -56(%rsp)
-       vpmuludq %ymm13, %ymm8, %ymm13
-       vmovdqa %ymm13, -88(%rsp)
-.Lpoly1305_blocks_avx2_16:
-       vpmuludq 104(%rsp), %ymm1, %ymm14
-       vmovdqa 40(%rsp), %ymm13
-       vpmuludq %ymm13, %ymm2, %ymm8
-       vpmuludq %ymm13, %ymm1, %ymm13
-       vmovdqa -24(%rsp), %ymm9
-       vpmuludq %ymm9, %ymm2, %ymm10
-       vpmuludq %ymm9, %ymm1, %ymm11
-       vpaddq %ymm8, %ymm14, %ymm14
-       vpmuludq %ymm9, %ymm3, %ymm8
-       vmovdqa -88(%rsp), %ymm12
-       vpmuludq %ymm12, %ymm1, %ymm9
-       vpaddq %ymm10, %ymm13, %ymm13
-       vpmuludq %ymm12, %ymm4, %ymm15
-       vmovdqa %ymm12, %ymm10
-       vpmuludq %ymm12, %ymm3, %ymm12
-       vpaddq %ymm8, %ymm14, %ymm14
-       vpmuludq %ymm10, %ymm2, %ymm10
-       vpmuludq %ymm6, %ymm2, %ymm8
-       vpaddq %ymm15, %ymm14, %ymm14
-       vpmuludq %ymm6, %ymm1, %ymm1
-       vpaddq %ymm12, %ymm13, %ymm13
-       vpmuludq %ymm6, %ymm5, %ymm15
-       vpaddq %ymm10, %ymm11, %ymm11
-       vpmuludq %ymm6, %ymm4, %ymm12
-       vpaddq %ymm8, %ymm9, %ymm9
-       vpmuludq %ymm6, %ymm3, %ymm10
-       vpmuludq %ymm7, %ymm3, %ymm8
-       vpaddq %ymm15, %ymm14, %ymm14
-       vpmuludq %ymm7, %ymm2, %ymm2
-       vpaddq %ymm12, %ymm13, %ymm12
-       vpmuludq %ymm7, %ymm5, %ymm15
-       vpaddq %ymm10, %ymm11, %ymm10
-       vpmuludq %ymm7, %ymm4, %ymm13
-       vpaddq %ymm8, %ymm9, %ymm8
-       vmovdqa 72(%rsp), %ymm9
-       vpmuludq %ymm9, %ymm4, %ymm11
-       vpaddq %ymm2, %ymm1, %ymm1
-       vpmuludq %ymm9, %ymm3, %ymm3
-       vpaddq %ymm15, %ymm12, %ymm12
-       vpmuludq %ymm9, %ymm5, %ymm15
-       vpaddq %ymm13, %ymm10, %ymm10
-       vmovdqa 8(%rsp), %ymm2
-       vpmuludq %ymm2, %ymm5, %ymm9
-       vpaddq %ymm11, %ymm8, %ymm8
-       vpmuludq %ymm2, %ymm4, %ymm4
-       vpaddq %ymm3, %ymm1, %ymm1
-       vpmuludq -56(%rsp), %ymm5, %ymm5
-       vpaddq %ymm15, %ymm10, %ymm10
-       vpaddq %ymm9, %ymm8, %ymm8
-       vpaddq %ymm4, %ymm1, %ymm1
-       vpaddq %ymm5, %ymm1, %ymm5
-       vmovdqu (%rsi), %ymm3
-       vmovdqu 32(%rsi), %ymm2
-       vperm2i128 $32, %ymm2, %ymm3, %ymm1
-       vperm2i128 $49, %ymm2, %ymm3, %ymm2
-       vpunpckldq %ymm2, %ymm1, %ymm15
-       vpunpckhdq %ymm2, %ymm1, %ymm2
-       vpxor %xmm4, %xmm4, %xmm4
-       vpunpckldq %ymm4, %ymm15, %ymm1
-       vpunpckhdq %ymm4, %ymm15, %ymm15
-       vpunpckldq %ymm4, %ymm2, %ymm3
-       vpunpckhdq %ymm4, %ymm2, %ymm2
-       vpsllq $6, %ymm15, %ymm15
-       vpsllq $12, %ymm3, %ymm3
-       vpsllq $18, %ymm2, %ymm2
-       vpaddq %ymm1, %ymm14, %ymm14
-       vpaddq %ymm15, %ymm12, %ymm12
-       vpaddq %ymm3, %ymm10, %ymm10
-       vpaddq %ymm2, %ymm8, %ymm8
-       vpaddq 168(%rsp), %ymm5, %ymm5
-       addq $64, %rsi
-       vpsrlq $26, %ymm14, %ymm4
-       vpsrlq $26, %ymm8, %ymm2
-       vpand %ymm0, %ymm14, %ymm14
-       vpand %ymm0, %ymm8, %ymm8
-       vpaddq %ymm4, %ymm12, %ymm12
-       vpaddq %ymm2, %ymm5, %ymm5
-       vpsrlq $26, %ymm12, %ymm3
-       vpsrlq $26, %ymm5, %ymm9
-       vpand %ymm0, %ymm12, %ymm12
-       vpand %ymm0, %ymm5, %ymm11
-       vpaddq %ymm3, %ymm10, %ymm3
-       vpmuludq 136(%rsp), %ymm9, %ymm9
-       vpaddq %ymm9, %ymm14, %ymm14
-       vpsrlq $26, %ymm3, %ymm2
-       vpsrlq $26, %ymm14, %ymm4
-       vpand %ymm0, %ymm3, %ymm3
-       vpand %ymm0, %ymm14, %ymm5
-       vpaddq %ymm2, %ymm8, %ymm2
-       vpaddq %ymm4, %ymm12, %ymm4
-       vpsrlq $26, %ymm2, %ymm1
-       vpand %ymm0, %ymm2, %ymm2
-       vpaddq %ymm1, %ymm11, %ymm1
-       subq $64, %rdx
-       cmpq $63, %rdx
-       ja .Lpoly1305_blocks_avx2_16
-.Lpoly1305_blocks_avx2_15:
-       testb $64, 320(%rdi)
-       jne .Lpoly1305_blocks_avx2_17
-       vmovdqa %ymm5, (%rdi)
-       vmovdqa %ymm4, 32(%rdi)
-       vmovdqa %ymm3, 64(%rdi)
-       vmovdqa %ymm2, 96(%rdi)
-       vmovdqa %ymm1, 128(%rdi)
-       jmp .Lpoly1305_blocks_avx2_8
-.Lpoly1305_blocks_avx2_17:
-       vpermq $245, %ymm5, %ymm0
-       vpaddq %ymm0, %ymm5, %ymm5
-       vpermq $245, %ymm4, %ymm0
-       vpaddq %ymm0, %ymm4, %ymm4
-       vpermq $245, %ymm3, %ymm0
-       vpaddq %ymm0, %ymm3, %ymm3
-       vpermq $245, %ymm2, %ymm0
-       vpaddq %ymm0, %ymm2, %ymm2
-       vpermq $245, %ymm1, %ymm0
-       vpaddq %ymm0, %ymm1, %ymm1
-       vpermq $170, %ymm5, %ymm0
-       vpaddq %ymm0, %ymm5, %ymm5
-       vpermq $170, %ymm4, %ymm0
-       vpaddq %ymm0, %ymm4, %ymm4
-       vpermq $170, %ymm3, %ymm0
-       vpaddq %ymm0, %ymm3, %ymm3
-       vpermq $170, %ymm2, %ymm0
-       vpaddq %ymm0, %ymm2, %ymm2
-       vpermq $170, %ymm1, %ymm0
-       vpaddq %ymm0, %ymm1, %ymm1
-       vmovd %xmm5, %eax
-       vmovd %xmm4, %edx
-       movl %eax, %ecx
-       shrl $26, %ecx
-       addl %edx, %ecx
-       movl %ecx, %edx
-       andl $67108863, %edx
-       vmovd %xmm3, %esi
-       shrl $26, %ecx
-       movl %ecx, %r11d
-       addl %esi, %r11d
-       vmovd %xmm2, %ecx
-       movl %r11d, %r10d
-       shrl $26, %r10d
-       addl %ecx, %r10d
-       movl %r10d, %r9d
-       andl $67108863, %r9d
-       vmovd %xmm1, %r8d
-       movl %edx, %esi
-       salq $26, %rsi
-       andl $67108863, %eax
-       orq %rax, %rsi
-       movabsq $17592186044415, %rax
-       andq %rax, %rsi
-       andl $67108863, %r11d
-       salq $8, %r11
-       shrl $18, %edx
-       movl %edx, %edx
-       orq %r11, %rdx
-       movq %r9, %rcx
-       salq $34, %rcx
-       orq %rcx, %rdx
-       andq %rax, %rdx
-       shrl $26, %r10d
-       addl %r10d, %r8d
-       salq $16, %r8
-       shrl $10, %r9d
-       movl %r9d, %r9d
-       orq %r9, %r8
-       movabsq $4398046511103, %r10
-       movq %r8, %r9
-       andq %r10, %r9
-       shrq $42, %r8
-       leaq (%r8,%r8,4), %rcx
-       addq %rcx, %rsi
-       movq %rsi, %r8
-       andq %rax, %r8
-       movq %rsi, %rcx
-       shrq $44, %rcx
-       addq %rdx, %rcx
-       movq %rcx, %rsi
-       andq %rax, %rsi
-       shrq $44, %rcx
-       movq %rcx, %rdx
-       addq %r9, %rdx
-       andq %rdx, %r10
-       shrq $42, %rdx
-       leaq (%r8,%rdx,4), %rcx
-       leaq (%rcx,%rdx), %rdx
-       movq %rdx, %rbx
-       andq %rax, %rbx
-       shrq $44, %rdx
-       movq %rdx, %r11
-       addq %rsi, %r11
-       leaq 5(%rbx), %r9
-       movq %r9, %r8
-       shrq $44, %r8
-       addq %r11, %r8
-       movabsq $-4398046511104, %rsi
-       addq %r10, %rsi
-       movq %r8, %rdx
-       shrq $44, %rdx
-       addq %rdx, %rsi
-       movq %rsi, %rdx
-       shrq $63, %rdx
-       subq $1, %rdx
-       movq %rdx, %rcx
-       notq %rcx
-       andq %rcx, %rbx
-       andq %rcx, %r11
-       andq %r10, %rcx
-       andq %rax, %r9
-       andq %rdx, %r9
-       orq %r9, %rbx
-       movq %rbx, (%rdi)
-       andq %r8, %rax
-       andq %rdx, %rax
-       orq %rax, %r11
-       movq %r11, 8(%rdi)
-       andq %rsi, %rdx
-       orq %rcx, %rdx
-       movq %rdx, 16(%rdi)
-.Lpoly1305_blocks_avx2_8:
-       movq -8(%rbp), %rbx
-       vzeroall
-       movq %rbp, %rax
-       subq %rsp, %rax
-       leave
-       addq $8, %rax
-       ret
-ELF(.size _gcry_poly1305_amd64_avx2_blocks,.-_gcry_poly1305_amd64_avx2_blocks;)
-
-
-.align 8
-.globl _gcry_poly1305_amd64_avx2_finish_ext
-ELF(.type  _gcry_poly1305_amd64_avx2_finish_ext,@function;)
-_gcry_poly1305_amd64_avx2_finish_ext:
-.Lpoly1305_finish_ext_avx2_local:
-       vzeroupper
-       pushq %rbp
-       movq %rsp, %rbp
-       pushq %r13
-       pushq %r12
-       pushq %rbx
-       andq $-64, %rsp
-       subq $64, %rsp
-       movq %rdi, %rbx
-       movq %rdx, %r13
-       movq %rcx, %r12
-       testq %rdx, %rdx
-       je .Lpoly1305_finish_ext_avx2_22
-       vpxor %xmm0, %xmm0, %xmm0
-       vmovdqa %ymm0, (%rsp)
-       vmovdqa %ymm0, 32(%rsp)
-       movq %rsp, %rax
-       subq %rsp, %rsi
-       testb $32, %dl
-       je .Lpoly1305_finish_ext_avx2_23
-       vmovdqu (%rsp,%rsi), %ymm0
-       vmovdqa %ymm0, (%rsp)
-       leaq 32(%rsp), %rax
-.Lpoly1305_finish_ext_avx2_23:
-       testb $16, %r13b
-       je .Lpoly1305_finish_ext_avx2_24
-       vmovdqu (%rax,%rsi), %xmm0
-       vmovdqa %xmm0, (%rax)
-       addq $16, %rax
-.Lpoly1305_finish_ext_avx2_24:
-       testb $8, %r13b
-       je .Lpoly1305_finish_ext_avx2_25
-       movq (%rax,%rsi), %rdx
-       movq %rdx, (%rax)
-       addq $8, %rax
-.Lpoly1305_finish_ext_avx2_25:
-       testb $4, %r13b
-       je .Lpoly1305_finish_ext_avx2_26
-       movl (%rax,%rsi), %edx
-       movl %edx, (%rax)
-       addq $4, %rax
-.Lpoly1305_finish_ext_avx2_26:
-       testb $2, %r13b
-       je .Lpoly1305_finish_ext_avx2_27
-       movzwl (%rax,%rsi), %edx
-       movw %dx, (%rax)
-       addq $2, %rax
-.Lpoly1305_finish_ext_avx2_27:
-       testb $1, %r13b
-       je .Lpoly1305_finish_ext_avx2_28
-       movzbl (%rax,%rsi), %edx
-       movb %dl, (%rax)
-.Lpoly1305_finish_ext_avx2_28:
-       testb $15, %r13b
-       je .Lpoly1305_finish_ext_avx2_29
-       movb $1, (%rsp,%r13)
-.Lpoly1305_finish_ext_avx2_29:
-       cmpq $47, %r13
-       jbe .Lpoly1305_finish_ext_avx2_30
-       orq $4, 320(%rbx)
-       jmp .Lpoly1305_finish_ext_avx2_31
-.Lpoly1305_finish_ext_avx2_30:
-       cmpq $31, %r13
-       jbe .Lpoly1305_finish_ext_avx2_32
-       orq $8, 320(%rbx)
-       jmp .Lpoly1305_finish_ext_avx2_31
-.Lpoly1305_finish_ext_avx2_32:
-       cmpq $15, %r13
-       jbe .Lpoly1305_finish_ext_avx2_33
-       orq $16, 320(%rbx)
-       jmp .Lpoly1305_finish_ext_avx2_31
-.Lpoly1305_finish_ext_avx2_33:
-       orq $32, 320(%rbx)
-.Lpoly1305_finish_ext_avx2_31:
-       testb $1, 320(%rbx)
-       je .Lpoly1305_finish_ext_avx2_34
-       cmpq $32, %r13
-       ja .Lpoly1305_finish_ext_avx2_34
-       cmpq $17, %r13
-       sbbq %rsi, %rsi
-       notq %rsi
-       addq $2, %rsi
-       cmpq $17, %r13
-       sbbq %rax, %rax
-       movq %rbx, %rdx
-       addq $23, %rax
-       leaq (%rbx,%rax,8), %rax
-       movl $0, %ecx
-.Lpoly1305_finish_ext_avx2_37:
-       movl 244(%rdx), %edi
-       movl %edi, (%rax)
-       movl 252(%rdx), %edi
-       movl %edi, 32(%rax)
-       movl 260(%rdx), %edi
-       movl %edi, 64(%rax)
-       movl 268(%rdx), %edi
-       movl %edi, 96(%rax)
-       movl 276(%rdx), %edi
-       movl %edi, 128(%rax)
-       addq $1, %rcx
-       subq $40, %rdx
-       addq $8, %rax
-       cmpq %rcx, %rsi
-       ja .Lpoly1305_finish_ext_avx2_37
-.Lpoly1305_finish_ext_avx2_34:
-       movl $64, %edx
-       movq %rsp, %rsi
-       movq %rbx, %rdi
-       call .Lpoly1305_blocks_avx2_local
-.Lpoly1305_finish_ext_avx2_22:
-       movq 320(%rbx), %r8
-       testb $1, %r8b
-       je .Lpoly1305_finish_ext_avx2_38
-       leaq -1(%r13), %rax
-       cmpq $47, %rax
-       ja .Lpoly1305_finish_ext_avx2_46
-       cmpq $32, %r13
-       ja .Lpoly1305_finish_ext_avx2_47
-       cmpq $17, %r13
-       sbbq %r9, %r9
-       addq $2, %r9
-       movl $0, %edi
-       cmpq $17, %r13
-       sbbq %rax, %rax
-       notq %rax
-       andl $5, %eax
-       jmp .Lpoly1305_finish_ext_avx2_39
-.Lpoly1305_finish_ext_avx2_41:
-       movl (%rdx), %esi
-       movl %esi, (%rax)
-       movl 8(%rdx), %esi
-       movl %esi, 32(%rax)
-       movl 16(%rdx), %esi
-       movl %esi, 64(%rax)
-       movl 24(%rdx), %esi
-       movl %esi, 96(%rax)
-       movl 32(%rdx), %esi
-       movl %esi, 128(%rax)
-       addq $1, %rcx
-       subq $40, %rdx
-       addq $8, %rax
-       movq %rcx, %rsi
-       subq %rdi, %rsi
-       cmpq %rsi, %r9
-       ja .Lpoly1305_finish_ext_avx2_41
-       cmpq $3, %rcx
-       ja .Lpoly1305_finish_ext_avx2_42
-       leaq 160(%rbx,%rcx,8), %rax
-.Lpoly1305_finish_ext_avx2_43:
-       movl $1, (%rax)
-       movl $0, 32(%rax)
-       movl $0, 64(%rax)
-       movl $0, 96(%rax)
-       movl $0, 128(%rax)
-       addq $1, %rcx
-       addq $8, %rax
-       cmpq $4, %rcx
-       jne .Lpoly1305_finish_ext_avx2_43
-.Lpoly1305_finish_ext_avx2_42:
-       orq $96, %r8
-       movq %r8, 320(%rbx)
-       vpxor %ymm0, %ymm0, %ymm0
-       vmovdqa %ymm0, (%rsp)
-       vmovdqa %ymm0, 32(%rsp)
-       movl $64, %edx
-       movq %rsp, %rsi
-       movq %rbx, %rdi
-       call .Lpoly1305_blocks_avx2_local
-.Lpoly1305_finish_ext_avx2_38:
-       movq 8(%rbx), %rax
-       movq %rax, %rdx
-       salq $44, %rdx
-       orq (%rbx), %rdx
-       shrq $20, %rax
-       movl $24, %edi
-       shlx %rdi, 16(%rbx), %rcx
-       orq %rcx, %rax
-       movl 292(%rbx), %ecx
-       salq $32, %rcx
-       movl 284(%rbx), %esi
-       orq %rsi, %rcx
-       movl 308(%rbx), %esi
-       salq $32, %rsi
-       movl 300(%rbx), %edi
-       orq %rdi, %rsi
-       addq %rcx, %rdx
-       adcq %rsi, %rax
-       movq %rdx, (%r12)
-       movq %rax, 8(%r12)
-       vpxor %xmm0, %xmm0, %xmm0
-       vmovdqu %ymm0, (%rbx)
-       vmovdqu %ymm0, 32(%rbx)
-       vmovdqu %ymm0, 64(%rbx)
-       vmovdqu %ymm0, 96(%rbx)
-       vmovdqu %ymm0, 128(%rbx)
-       vmovdqu %ymm0, 160(%rbx)
-       vmovdqu %ymm0, 192(%rbx)
-       vmovdqu %ymm0, 224(%rbx)
-       jmp .Lpoly1305_finish_ext_avx2_49
-.Lpoly1305_finish_ext_avx2_46:
-       movl $3, %r9d
-       movl $1, %edi
-       movl $10, %eax
-       jmp .Lpoly1305_finish_ext_avx2_39
-.Lpoly1305_finish_ext_avx2_47:
-       movl $3, %r9d
-       movl $0, %edi
-       movl $10, %eax
-.Lpoly1305_finish_ext_avx2_39:
-       leaq 164(%rbx,%rax,8), %rdx
-       leaq 160(%rbx,%rdi,8), %rax
-       movq %rdi, %rcx
-       jmp .Lpoly1305_finish_ext_avx2_41
-.Lpoly1305_finish_ext_avx2_49:
-       movq %rbp, %rax
-       subq %rsp, %rax
-       leaq -24(%rbp), %rsp
-       vzeroall
-       popq %rbx
-       popq %r12
-       popq %r13
-       popq %rbp
-       addq $(8*5), %rax
-ret
-ELF(.size _gcry_poly1305_amd64_avx2_finish_ext,.-_gcry_poly1305_amd64_avx2_finish_ext;)
-
-#endif
index bcbe5df..19cee5f 100644 (file)
 #include "cipher.h"
 #include "bufhelp.h"
 
-
 #define POLY1305_TAGLEN 16
 #define POLY1305_KEYLEN 32
+#define POLY1305_BLOCKSIZE 16
 
 
-/* Block-size used in default implementation. */
-#define POLY1305_REF_BLOCKSIZE 16
-
-/* State size of default implementation. */
-#define POLY1305_REF_STATESIZE 64
-
-/* State alignment for default implementation. */
-#define POLY1305_REF_ALIGNMENT sizeof(void *)
-
-
-#undef POLY1305_SYSV_FUNC_ABI
-
-/* POLY1305_USE_SSE2 indicates whether to compile with AMD64 SSE2 code. */
-#undef POLY1305_USE_SSE2
-#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
-# define POLY1305_USE_SSE2 1
-# define POLY1305_SSE2_BLOCKSIZE 32
-# define POLY1305_SSE2_STATESIZE 248
-# define POLY1305_SSE2_ALIGNMENT 16
-# define POLY1305_SYSV_FUNC_ABI 1
-#endif
-
-
-/* POLY1305_USE_AVX2 indicates whether to compile with AMD64 AVX2 code. */
-#undef POLY1305_USE_AVX2
-#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
-    defined(ENABLE_AVX2_SUPPORT)
-# define POLY1305_USE_AVX2 1
-# define POLY1305_AVX2_BLOCKSIZE 64
-# define POLY1305_AVX2_STATESIZE 328
-# define POLY1305_AVX2_ALIGNMENT 32
-# define POLY1305_SYSV_FUNC_ABI 1
-#endif
-
-
-/* POLY1305_USE_NEON indicates whether to enable ARM NEON assembly code. */
-#undef POLY1305_USE_NEON
-#if defined(ENABLE_NEON_SUPPORT) && defined(HAVE_ARM_ARCH_V6) && \
-    defined(__ARMEL__) && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
-    defined(HAVE_GCC_INLINE_ASM_NEON)
-# define POLY1305_USE_NEON 1
-# define POLY1305_NEON_BLOCKSIZE 32
-# define POLY1305_NEON_STATESIZE 128
-# define POLY1305_NEON_ALIGNMENT 16
-#endif
-
-
-/* Largest block-size used in any implementation (optimized implementations
- * might use block-size multiple of 16). */
-#ifdef POLY1305_USE_AVX2
-# define POLY1305_LARGEST_BLOCKSIZE POLY1305_AVX2_BLOCKSIZE
-#elif defined(POLY1305_USE_NEON)
-# define POLY1305_LARGEST_BLOCKSIZE POLY1305_NEON_BLOCKSIZE
-#elif defined(POLY1305_USE_SSE2)
-# define POLY1305_LARGEST_BLOCKSIZE POLY1305_SSE2_BLOCKSIZE
-#else
-# define POLY1305_LARGEST_BLOCKSIZE POLY1305_REF_BLOCKSIZE
-#endif
-
-/* Largest state-size used in any implementation. */
-#ifdef POLY1305_USE_AVX2
-# define POLY1305_LARGEST_STATESIZE POLY1305_AVX2_STATESIZE
-#elif defined(POLY1305_USE_NEON)
-# define POLY1305_LARGEST_STATESIZE POLY1305_NEON_STATESIZE
-#elif defined(POLY1305_USE_SSE2)
-# define POLY1305_LARGEST_STATESIZE POLY1305_SSE2_STATESIZE
-#else
-# define POLY1305_LARGEST_STATESIZE POLY1305_REF_STATESIZE
-#endif
-
-/* Minimum alignment for state pointer passed to implementations. */
-#ifdef POLY1305_USE_AVX2
-# define POLY1305_STATE_ALIGNMENT POLY1305_AVX2_ALIGNMENT
-#elif defined(POLY1305_USE_NEON)
-# define POLY1305_STATE_ALIGNMENT POLY1305_NEON_ALIGNMENT
-#elif defined(POLY1305_USE_SSE2)
-# define POLY1305_STATE_ALIGNMENT POLY1305_SSE2_ALIGNMENT
-#else
-# define POLY1305_STATE_ALIGNMENT POLY1305_REF_ALIGNMENT
-#endif
-
-
-/* Assembly implementations use SystemV ABI, ABI conversion and additional
- * stack to store XMM6-XMM15 needed on Win64. */
-#undef OPS_FUNC_ABI
-#if defined(POLY1305_SYSV_FUNC_ABI) && \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)
-# define OPS_FUNC_ABI __attribute__((sysv_abi))
-#else
-# define OPS_FUNC_ABI
-#endif
-
-
-typedef struct poly1305_key_s
+typedef struct
 {
-  byte b[POLY1305_KEYLEN];
-} poly1305_key_t;
-
-
-typedef struct poly1305_ops_s
-{
-  size_t block_size;
-  void (*init_ext) (void *ctx, const poly1305_key_t * key) OPS_FUNC_ABI;
-  unsigned int (*blocks) (void *ctx, const byte * m, size_t bytes) OPS_FUNC_ABI;
-  unsigned int (*finish_ext) (void *ctx, const byte * m, size_t remaining,
-                             byte mac[POLY1305_TAGLEN]) OPS_FUNC_ABI;
-} poly1305_ops_t;
-
+  u32 k[4];
+  u32 r[4];
+  u32 h[5];
+} POLY1305_STATE;
 
 typedef struct poly1305_context_s
 {
-  byte state[POLY1305_LARGEST_STATESIZE + POLY1305_STATE_ALIGNMENT];
-  byte buffer[POLY1305_LARGEST_BLOCKSIZE];
-  const poly1305_ops_t *ops;
+  POLY1305_STATE state;
+  byte buffer[POLY1305_BLOCKSIZE];
   unsigned int leftover;
 } poly1305_context_t;
 
 
-gcry_err_code_t _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key,
+gcry_err_code_t _gcry_poly1305_init (poly1305_context_t *ctx, const byte *key,
                                     size_t keylen);
 
-void _gcry_poly1305_finish (poly1305_context_t * ctx,
-                           byte mac[POLY1305_TAGLEN]);
+void _gcry_poly1305_finish (poly1305_context_t *ctx,
+                            byte mac[POLY1305_TAGLEN]);
 
-void _gcry_poly1305_update (poly1305_context_t * ctx, const byte * buf,
-                           size_t buflen);
+void _gcry_poly1305_update (poly1305_context_t *ctx, const byte *buf,
+                            size_t buflen);
 
+unsigned int _gcry_poly1305_update_burn (poly1305_context_t *ctx,
+                                        const byte *m, size_t bytes);
 
 #endif /* G10_POLY1305_INTERNAL_H */
diff --git a/cipher/poly1305-s390x.S b/cipher/poly1305-s390x.S
new file mode 100644 (file)
index 0000000..28bed56
--- /dev/null
@@ -0,0 +1,87 @@
+/* poly1305-s390x.S  -  zSeries implementation of Poly1305
+ *
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#if defined (__s390x__) && __GNUC__ >= 4 && __ARCH__ >= 9
+#if defined(HAVE_GCC_INLINE_ASM_S390X)
+
+#include "asm-poly1305-s390x.h"
+
+.text
+
+.balign 8
+.globl _gcry_poly1305_s390x_blocks1
+ELF(.type _gcry_poly1305_s390x_blocks1,@function;)
+
+_gcry_poly1305_s390x_blocks1:
+       /* input:
+        *      %r2: poly1305-state
+        *      %r3: src
+        *      %r4: len
+        *      %r5: high_pad
+        */
+       CFI_STARTPROC();
+
+       stmg %r6, %r14, 6 * 8(%r15);
+
+       lgr POLY_RSTATE, %r2;
+       lgr POLY_RSRC, %r3;
+       srlg %r0, %r4, 4;
+
+       cgije %r5, 0, .Lpoly_high0;
+
+       POLY1305_LOAD_STATE();
+
+.balign 4
+.Lpoly_loop_high1:
+       POLY1305_BLOCK_PART1(0 * 16);
+       INC_POLY1305_SRC(1 * 16);
+.Lpoly_block_part2:
+       POLY1305_BLOCK_PART2();
+       POLY1305_BLOCK_PART3();
+       POLY1305_BLOCK_PART4();
+       POLY1305_BLOCK_PART5();
+       POLY1305_BLOCK_PART6();
+       POLY1305_BLOCK_PART7();
+       POLY1305_BLOCK_PART8();
+
+       brctg %r0, .Lpoly_loop_high1;
+
+.balign 4
+.Lpoly_done:
+       POLY1305_STORE_STATE();
+
+       lmg %r6, %r14, 6 * 8(%r15);
+       xgr %r2, %r2;
+       br %r14;
+
+.balign 4
+.Lpoly_high0:
+       lghi %r0, 1;
+       POLY1305_LOAD_STATE();
+       POLY1305_BLOCK_PART1_HB(0 * 16, 0);
+       j .Lpoly_block_part2;
+
+       CFI_ENDPROC();
+ELF(.size _gcry_poly1305_s390x_blocks1,
+    .-_gcry_poly1305_s390x_blocks1;)
+
+#endif /*HAVE_GCC_INLINE_ASM_S390X*/
+#endif /*__s390x__*/
diff --git a/cipher/poly1305-sse2-amd64.S b/cipher/poly1305-sse2-amd64.S
deleted file mode 100644 (file)
index 219eb07..0000000
+++ /dev/null
@@ -1,1043 +0,0 @@
-/* poly1305-sse2-amd64.S  -  AMD64/SSE2 implementation of Poly1305
- *
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-/*
- * Based on public domain implementation by Andrew Moon at
- *  https://github.com/floodyberry/poly1305-opt
- */
-
-#include <config.h>
-
-#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
-    defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-
-.text
-
-
-.align 8
-.globl _gcry_poly1305_amd64_sse2_init_ext
-ELF(.type  _gcry_poly1305_amd64_sse2_init_ext,@function;)
-_gcry_poly1305_amd64_sse2_init_ext:
-.Lpoly1305_init_ext_x86_local:
-       xor %edx, %edx
-       pushq %r12
-       pushq %r13
-       pushq %r14
-       movq %rdx, %r10
-       movq $-1, %rcx
-       testq %r10, %r10
-       pxor %xmm0, %xmm0
-       movq $0xfffffc0ffff, %r9
-       movdqa %xmm0, (%rdi)
-       cmove %rcx, %r10
-       movdqa %xmm0, 16(%rdi)
-       movq $0xffc0fffffff, %rcx
-       movdqa %xmm0, 32(%rdi)
-       movdqa %xmm0, 48(%rdi)
-       movdqa %xmm0, 64(%rdi)
-       movq 8(%rsi), %r11
-       movq %r11, %r8
-       movq (%rsi), %r12
-       andq %r12, %rcx
-       shrq $44, %r12
-       shlq $20, %r8
-       shrq $24, %r11
-       orq %r8, %r12
-       movq $0xffffffc0f, %r8
-       andq %r9, %r12
-       andq %r8, %r11
-       movl %ecx, %r8d
-       andl $67108863, %r8d
-       movq %rcx, %r9
-       movl %r8d, 84(%rdi)
-       movq %r12, %r8
-       shrq $26, %r9
-       shlq $18, %r8
-       orq %r8, %r9
-       movq %r12, %r8
-       shrq $8, %r8
-       andl $67108863, %r9d
-       andl $67108863, %r8d
-       movl %r9d, 92(%rdi)
-       movq %r12, %r9
-       movl %r8d, 100(%rdi)
-       movq %r11, %r8
-       shrq $34, %r9
-       shlq $10, %r8
-       orq %r8, %r9
-       movq %r11, %r8
-       shrq $16, %r8
-       andl $67108863, %r9d
-       movl %r9d, 108(%rdi)
-       cmpq $16, %r10
-       movl %r8d, 116(%rdi)
-       movl 16(%rsi), %r8d
-       movl %r8d, 124(%rdi)
-       movl 20(%rsi), %r8d
-       movl %r8d, 132(%rdi)
-       movl 24(%rsi), %r8d
-       movl %r8d, 140(%rdi)
-       movl 28(%rsi), %esi
-       movl %esi, 148(%rdi)
-       jbe .Lpoly1305_init_ext_sse2_done
-       lea (%r11,%r11,4), %r14
-       shlq $2, %r14
-       lea (%r12,%r12), %rax
-       mulq %r14
-       movq %rax, %r13
-       movq %rcx, %rax
-       movq %rdx, %r8
-       mulq %rcx
-       addq %rax, %r13
-       lea (%rcx,%rcx), %rax
-       movq %r13, %r9
-       adcq %rdx, %r8
-       mulq %r12
-       shlq $20, %r8
-       movq %rax, %rsi
-       shrq $44, %r9
-       movq %r11, %rax
-       orq %r9, %r8
-       movq %rdx, %r9
-       mulq %r14
-       addq %rax, %rsi
-       movq %rcx, %rax
-       adcq %rdx, %r9
-       addq %r11, %r11
-       mulq %r11
-       addq %rsi, %r8
-       movq %rax, %r11
-       movq %r12, %rax
-       movq %rdx, %rcx
-       adcq $0, %r9
-       mulq %r12
-       addq %rax, %r11
-       movq %r8, %rsi
-       adcq %rdx, %rcx
-       shlq $20, %r9
-       shrq $44, %rsi
-       orq %rsi, %r9
-       movq $0xfffffffffff, %rsi
-       addq %r11, %r9
-       movq %r9, %r12
-       adcq $0, %rcx
-       andq %rsi, %r13
-       shlq $22, %rcx
-       andq %rsi, %r8
-       shrq $42, %r12
-       orq %r12, %rcx
-       movq %rsi, %r12
-       lea (%rcx,%rcx,4), %rcx
-       addq %rcx, %r13
-       movq %rsi, %rcx
-       andq %r13, %rcx
-       shrq $44, %r13
-       movq %rcx, %r14
-       addq %r13, %r8
-       movq $0x3ffffffffff, %r13
-       andq %r8, %r12
-       andq %r13, %r9
-       shrq $44, %r8
-       movq %r12, %r11
-       addq %r8, %r9
-       movq %r12, %rax
-       movq %r9, %r13
-       movl %ecx, %r8d
-       shrq $26, %r14
-       andl $67108863, %r8d
-       shlq $18, %r11
-       shrq $34, %rax
-       orq %r11, %r14
-       shlq $10, %r13
-       movq %r12, %r11
-       orq %r13, %rax
-       movq %r9, %r13
-       shrq $8, %r11
-       shrq $16, %r13
-       andl $67108863, %r14d
-       andl $67108863, %r11d
-       andl $67108863, %eax
-       movl %r8d, 88(%rdi)
-       cmpq $64, %r10
-       movl %r8d, 80(%rdi)
-       movl %r14d, 104(%rdi)
-       movl %r14d, 96(%rdi)
-       movl %r11d, 120(%rdi)
-       movl %r11d, 112(%rdi)
-       movl %eax, 136(%rdi)
-       movl %eax, 128(%rdi)
-       movl %r13d, 152(%rdi)
-       movl %r13d, 144(%rdi)
-       jbe .Lpoly1305_init_ext_sse2_done
-       lea (%r9,%r9,4), %r14
-       shlq $2, %r14
-       lea (%r12,%r12), %rax
-       mulq %r14
-       movq %rax, %r8
-       movq %rcx, %rax
-       movq %rdx, %r10
-       mulq %rcx
-       addq %rax, %r8
-       lea (%rcx,%rcx), %rax
-       movq %r8, %r11
-       adcq %rdx, %r10
-       andq %rsi, %r8
-       mulq %r12
-       shlq $20, %r10
-       movq %rax, %r13
-       shrq $44, %r11
-       movq %r9, %rax
-       orq %r11, %r10
-       movq %rdx, %r11
-       mulq %r14
-       addq %rax, %r13
-       movq %rcx, %rax
-       adcq %rdx, %r11
-       addq %r9, %r9
-       mulq %r9
-       addq %r13, %r10
-       movq %rax, %r9
-       movq %r12, %rax
-       movq %rdx, %rcx
-       adcq $0, %r11
-       mulq %r12
-       addq %rax, %r9
-       movq %r10, %r13
-       adcq %rdx, %rcx
-       andq %rsi, %r10
-       shlq $20, %r11
-       shrq $44, %r13
-       orq %r13, %r11
-       addq %r9, %r11
-       movq %rsi, %r9
-       movq %r11, %r12
-       adcq $0, %rcx
-       shlq $22, %rcx
-       shrq $42, %r12
-       orq %r12, %rcx
-       lea (%rcx,%rcx,4), %rcx
-       addq %rcx, %r8
-       andq %r8, %r9
-       shrq $44, %r8
-       movl %r9d, %eax
-       addq %r8, %r10
-       movq $0x3ffffffffff, %r8
-       andq %r10, %rsi
-       andq %r8, %r11
-       shrq $44, %r10
-       movq %rsi, %r8
-       addq %r10, %r11
-       andl $67108863, %eax
-       shrq $26, %r9
-       movq %r11, %r10
-       shlq $18, %r8
-       shlq $10, %r10
-       orq %r8, %r9
-       movq %rsi, %r8
-       shrq $34, %rsi
-       andl $67108863, %r9d
-       shrq $8, %r8
-       orq %r10, %rsi
-       shrq $16, %r11
-       andl $67108863, %r8d
-       andl $67108863, %esi
-       movl %eax, 168(%rdi)
-       movl %eax, 160(%rdi)
-       movl %r9d, 184(%rdi)
-       movl %r9d, 176(%rdi)
-       movl %r8d, 200(%rdi)
-       movl %r8d, 192(%rdi)
-       movl %esi, 216(%rdi)
-       movl %esi, 208(%rdi)
-       movl %r11d, 232(%rdi)
-       movl %r11d, 224(%rdi)
-.Lpoly1305_init_ext_sse2_done:
-       movq $0, 240(%rdi)
-       popq %r14
-       popq %r13
-       popq %r12
-       ret
-ELF(.size _gcry_poly1305_amd64_sse2_init_ext,.-_gcry_poly1305_amd64_sse2_init_ext;)
-
-
-.align 8
-.globl _gcry_poly1305_amd64_sse2_finish_ext
-ELF(.type  _gcry_poly1305_amd64_sse2_finish_ext,@function;)
-_gcry_poly1305_amd64_sse2_finish_ext:
-.Lpoly1305_finish_ext_x86_local:
-       pushq %rbp
-       movq %rsp, %rbp
-       subq $64, %rsp
-       andq $~63, %rsp
-       movq %rdx, 32(%rsp)
-       movq %rcx, 40(%rsp)
-       andq %rdx, %rdx
-       jz .Lpoly1305_finish_x86_no_leftover
-       pxor %xmm0, %xmm0
-       movdqa %xmm0, 0+0(%rsp)
-       movdqa %xmm0, 16+0(%rsp)
-       leaq 0(%rsp), %r8
-       testq $16, %rdx
-       jz .Lpoly1305_finish_x86_skip16
-       movdqu 0(%rsi), %xmm0
-       movdqa %xmm0, 0(%r8)
-       addq $16, %rsi
-       addq $16, %r8
-.Lpoly1305_finish_x86_skip16:
-       testq $8, %rdx
-       jz .Lpoly1305_finish_x86_skip8
-       movq 0(%rsi), %rax
-       movq %rax, 0(%r8)
-       addq $8, %rsi
-       addq $8, %r8
-.Lpoly1305_finish_x86_skip8:
-       testq $4, %rdx
-       jz .Lpoly1305_finish_x86_skip4
-       movl 0(%rsi), %eax
-       movl %eax, 0(%r8)
-       addq $4, %rsi
-       addq $4, %r8
-.Lpoly1305_finish_x86_skip4:
-       testq $2, %rdx
-       jz .Lpoly1305_finish_x86_skip2
-       movw 0(%rsi), %ax
-       movw %ax, 0(%r8)
-       addq $2, %rsi
-       addq $2, %r8
-.Lpoly1305_finish_x86_skip2:
-       testq $1, %rdx
-       jz .Lpoly1305_finish_x86_skip1
-       movb 0(%rsi), %al
-       movb %al, 0(%r8)
-       addq $1, %r8
-.Lpoly1305_finish_x86_skip1:
-       cmpq $16, %rdx
-       je .Lpoly1305_finish_x86_is16
-       movb $1, 0(%r8)
-.Lpoly1305_finish_x86_is16:
-       movq $4, %rax
-       jae .Lpoly1305_finish_x86_16andover
-       movq $8, %rax
-.Lpoly1305_finish_x86_16andover:
-       orq %rax, 240(%rdi)
-       leaq 0(%rsp), %rsi
-       movq $32, %rdx
-       callq .Lpoly1305_blocks_x86_local
-.Lpoly1305_finish_x86_no_leftover:
-       testq $1, 240(%rdi)
-       jz .Lpoly1305_finish_x86_not_started
-       movq 32(%rsp), %rdx
-       andq %rdx, %rdx
-       jz .Lpoly1305_finish_x86_r2r
-       cmpq $16, %rdx
-       jg .Lpoly1305_finish_x86_r2r
-       xorl %r10d, %r10d
-       movl 84(%rdi), %eax
-       movl 92(%rdi), %ecx
-       movl 100(%rdi), %edx
-       movl 108(%rdi), %r8d
-       movl 116(%rdi), %r9d
-       movl %eax, 80(%rdi)
-       movl $1, 8+80(%rdi)
-       movl %ecx, 96(%rdi)
-       movl %r10d, 8+96(%rdi)
-       movl %edx, 112(%rdi)
-       movl %r10d, 8+112(%rdi)
-       movl %r8d, 128(%rdi)
-       movl %r10d, 8+128(%rdi)
-       movl %r9d, 144(%rdi)
-       movl %r10d, 8+144(%rdi)
-       jmp .Lpoly1305_finish_x86_combine
-.Lpoly1305_finish_x86_r2r:
-       movl 84(%rdi), %eax
-       movl 92(%rdi), %ecx
-       movl 100(%rdi), %edx
-       movl 108(%rdi), %r8d
-       movl 116(%rdi), %r9d
-       movl %eax, 8+80(%rdi)
-       movl %ecx, 8+96(%rdi)
-       movl %edx, 8+112(%rdi)
-       movl %r8d, 8+128(%rdi)
-       movl %r9d, 8+144(%rdi)
-.Lpoly1305_finish_x86_combine:
-       xorq %rsi, %rsi
-       movq $32, %rdx
-       callq .Lpoly1305_blocks_x86_local
-.Lpoly1305_finish_x86_not_started:
-       movq 0(%rdi), %r8
-       movq 8(%rdi), %r9
-       movq %r9, %r10
-       movq 16(%rdi), %r11
-       shlq $44, %r9
-       shrq $20, %r10
-       shlq $24, %r11
-       orq %r9, %r8
-       orq %r11, %r10
-       pxor %xmm0, %xmm0
-       movl 124(%rdi), %eax
-       movl 132(%rdi), %ecx
-       movl 140(%rdi), %edx
-       movl 148(%rdi), %esi
-       movq 40(%rsp), %r11
-       shlq $32, %rcx
-       shlq $32, %rsi
-       orq %rcx, %rax
-       orq %rsi, %rdx
-       addq %r8, %rax
-       adcq %r10, %rdx
-       movq %rax, 0(%r11)
-       movq %rdx, 8(%r11)
-       movq %rbp, %rax
-       subq %rsp, %rax
-       movq %rbp, %rsp
-       movdqa %xmm0, 0(%rdi)
-       movdqa %xmm0, 16(%rdi)
-       movdqa %xmm0, 32(%rdi)
-       movdqa %xmm0, 48(%rdi)
-       movdqa %xmm0, 64(%rdi)
-       movdqa %xmm0, 80(%rdi)
-       movdqa %xmm0, 96(%rdi)
-       movdqa %xmm0, 112(%rdi)
-       movdqa %xmm0, 128(%rdi)
-       movdqa %xmm0, 144(%rdi)
-       movdqa %xmm0, 160(%rdi)
-       movdqa %xmm0, 176(%rdi)
-       movdqa %xmm0, 192(%rdi)
-       movdqa %xmm0, 208(%rdi)
-       movdqa %xmm0, 224(%rdi)
-       popq %rbp
-       addq $8, %rax
-       ret
-ELF(.size _gcry_poly1305_amd64_sse2_finish_ext,.-_gcry_poly1305_amd64_sse2_finish_ext;)
-
-
-.align 8
-.globl _gcry_poly1305_amd64_sse2_blocks
-ELF(.type  _gcry_poly1305_amd64_sse2_blocks,@function;)
-_gcry_poly1305_amd64_sse2_blocks:
-.Lpoly1305_blocks_x86_local:
-       pushq %rbp
-       movq %rsp, %rbp
-       pushq %rbx
-       andq $-64, %rsp
-       subq $328, %rsp
-       movq 240(%rdi), %rax
-       movl $(1<<24), %r8d
-       movl $((1<<26)-1), %r9d
-       movd %r8, %xmm0
-       movd %r9, %xmm5
-       pshufd $0x44, %xmm0, %xmm0
-       pshufd $0x44, %xmm5, %xmm5
-       testb $4, %al
-       je .Lpoly1305_blocks_x86_3
-       psrldq $8, %xmm0
-.Lpoly1305_blocks_x86_3:
-       testb $8, %al
-       je .Lpoly1305_blocks_x86_4
-       pxor %xmm0, %xmm0
-.Lpoly1305_blocks_x86_4:
-       movdqa %xmm0, 168(%rsp)
-       testb $1, %al
-       jne .Lpoly1305_blocks_x86_5
-       movq 16(%rsi), %xmm0
-       movdqa %xmm5, %xmm7
-       movdqa %xmm5, %xmm10
-       movq (%rsi), %xmm6
-       orq $1, %rax
-       subq $32, %rdx
-       movq 8(%rsi), %xmm1
-       punpcklqdq %xmm0, %xmm6
-       movq 24(%rsi), %xmm0
-       pand %xmm6, %xmm7
-       movdqa %xmm6, %xmm9
-       psrlq $52, %xmm6
-       addq $32, %rsi
-       punpcklqdq %xmm0, %xmm1
-       movdqa %xmm1, %xmm0
-       psrlq $26, %xmm9
-       psllq $12, %xmm0
-       movq %rax, 240(%rdi)
-       pand %xmm5, %xmm9
-       por %xmm0, %xmm6
-       psrlq $40, %xmm1
-       pand %xmm6, %xmm10
-       por 168(%rsp), %xmm1
-       psrlq $26, %xmm6
-       pand %xmm5, %xmm6
-.Lpoly1305_blocks_x86_6:
-       movdqa 80(%rdi), %xmm13
-       cmpq $63, %rdx
-       movl $(5), %r8d
-       movd %r8, %xmm14
-       pshufd $0x44, %xmm14, %xmm14
-       movdqa 96(%rdi), %xmm15
-       movdqa %xmm13, -8(%rsp)
-       movdqa 112(%rdi), %xmm0
-       movdqa %xmm14, 136(%rsp)
-       movdqa 128(%rdi), %xmm3
-       movdqa %xmm15, 312(%rsp)
-       pmuludq %xmm14, %xmm15
-       movdqa 144(%rdi), %xmm13
-       movdqa %xmm0, 232(%rsp)
-       pmuludq %xmm14, %xmm0
-       movdqa %xmm3, 152(%rsp)
-       pmuludq %xmm14, %xmm3
-       movdqa %xmm13, 56(%rsp)
-       pmuludq %xmm14, %xmm13
-       movdqa %xmm15, 40(%rsp)
-       movdqa %xmm0, -24(%rsp)
-       movdqa %xmm3, -40(%rsp)
-       movdqa %xmm13, -56(%rsp)
-       jbe .Lpoly1305_blocks_x86_7
-       movdqa 192(%rdi), %xmm15
-       leaq 32(%rsi), %rax
-       movq %rdx, %rcx
-       movdqa 176(%rdi), %xmm14
-       movdqa %xmm15, %xmm2
-       movdqa 208(%rdi), %xmm0
-       movdqa %xmm15, 216(%rsp)
-       movdqa %xmm14, 296(%rsp)
-       movdqa 224(%rdi), %xmm3
-       pmuludq 136(%rsp), %xmm14
-       movdqa -24(%rsp), %xmm13
-       movdqa %xmm14, 8(%rsp)
-       pmuludq 136(%rsp), %xmm2
-       movdqa -40(%rsp), %xmm14
-       movdqa %xmm0, 120(%rsp)
-       pmuludq 136(%rsp), %xmm0
-       movdqa %xmm3, 24(%rsp)
-       movdqa 160(%rdi), %xmm12
-       movdqa %xmm0, %xmm8
-       movdqa -56(%rsp), %xmm15
-       movdqa %xmm13, 88(%rsp)
-       pmuludq 136(%rsp), %xmm3
-       movdqa %xmm2, 104(%rsp)
-       movdqa %xmm0, %xmm13
-       movdqa -8(%rsp), %xmm11
-       movdqa %xmm3, 280(%rsp)
-       movdqa %xmm2, %xmm3
-       movdqa %xmm0, 200(%rsp)
-       movdqa %xmm14, 184(%rsp)
-       movdqa %xmm15, 264(%rsp)
-       jmp .Lpoly1305_blocks_x86_8
-.p2align 6,,63
-.Lpoly1305_blocks_x86_13:
-       movdqa 200(%rsp), %xmm13
-       movdqa %xmm3, %xmm6
-       movdqa 200(%rsp), %xmm8
-       movdqa 104(%rsp), %xmm3
-.Lpoly1305_blocks_x86_8:
-       movdqa 8(%rsp), %xmm4
-       pmuludq %xmm6, %xmm3
-       subq $64, %rcx
-       pmuludq %xmm10, %xmm8
-       movdqa 104(%rsp), %xmm2
-       movdqa 200(%rsp), %xmm0
-       pmuludq %xmm1, %xmm4
-       movdqa 280(%rsp), %xmm15
-       pmuludq %xmm6, %xmm13
-       movdqa 280(%rsp), %xmm14
-       pmuludq %xmm1, %xmm0
-       paddq %xmm3, %xmm4
-       pmuludq %xmm1, %xmm2
-       movdqa 280(%rsp), %xmm3
-       paddq %xmm8, %xmm4
-       pmuludq %xmm9, %xmm15
-       movdqa 280(%rsp), %xmm8
-       pmuludq %xmm10, %xmm14
-       pmuludq %xmm6, %xmm8
-       paddq %xmm13, %xmm2
-       movdqa %xmm6, %xmm13
-       pmuludq %xmm1, %xmm3
-       paddq %xmm15, %xmm4
-       movdqa 296(%rsp), %xmm15
-       pmuludq %xmm12, %xmm13
-       paddq %xmm14, %xmm2
-       movdqa %xmm7, %xmm14
-       paddq %xmm8, %xmm0
-       pmuludq %xmm12, %xmm14
-       movdqa %xmm9, %xmm8
-       pmuludq 296(%rsp), %xmm6
-       pmuludq %xmm12, %xmm8
-       movdqa %xmm6, 248(%rsp)
-       pmuludq %xmm10, %xmm15
-       movq -16(%rax), %xmm6
-       paddq %xmm13, %xmm3
-       movdqa %xmm10, %xmm13
-       paddq %xmm14, %xmm4
-       movq -8(%rax), %xmm14
-       paddq %xmm8, %xmm2
-       movq -32(%rax), %xmm8
-       pmuludq %xmm12, %xmm13
-       paddq %xmm15, %xmm3
-       pmuludq %xmm12, %xmm1
-       movdqa 216(%rsp), %xmm15
-       pmuludq 216(%rsp), %xmm10
-       punpcklqdq %xmm6, %xmm8
-       movq -24(%rax), %xmm6
-       pmuludq %xmm9, %xmm15
-       paddq %xmm13, %xmm0
-       movdqa 296(%rsp), %xmm13
-       paddq 248(%rsp), %xmm1
-       punpcklqdq %xmm14, %xmm6
-       movdqa 296(%rsp), %xmm14
-       pmuludq %xmm9, %xmm13
-       pmuludq 120(%rsp), %xmm9
-       movdqa %xmm15, 72(%rsp)
-       paddq %xmm10, %xmm1
-       movdqa 216(%rsp), %xmm15
-       pmuludq %xmm7, %xmm14
-       movdqa %xmm6, %xmm10
-       paddq %xmm9, %xmm1
-       pmuludq %xmm7, %xmm15
-       paddq %xmm13, %xmm0
-       paddq 72(%rsp), %xmm3
-       movdqa 120(%rsp), %xmm13
-       psllq $12, %xmm10
-       paddq %xmm14, %xmm2
-       movdqa %xmm5, %xmm14
-       pand %xmm8, %xmm14
-       pmuludq %xmm7, %xmm13
-       paddq %xmm15, %xmm0
-       movdqa %xmm14, 248(%rsp)
-       movdqa %xmm8, %xmm14
-       psrlq $52, %xmm8
-       movdqu (%rax), %xmm9
-       por %xmm10, %xmm8
-       pmuludq 24(%rsp), %xmm7
-       movdqu 16(%rax), %xmm10
-       paddq %xmm13, %xmm3
-       pxor %xmm13, %xmm13
-       movdqa %xmm9, %xmm15
-       paddq %xmm7, %xmm1
-       movdqa %xmm6, %xmm7
-       movdqa %xmm10, -72(%rsp)
-       punpckldq %xmm10, %xmm15
-       movdqa %xmm15, %xmm10
-       punpckldq %xmm13, %xmm10
-       punpckhdq -72(%rsp), %xmm9
-       psrlq $40, %xmm6
-       movdqa %xmm10, 72(%rsp)
-       movdqa %xmm9, %xmm10
-       punpckhdq %xmm13, %xmm9
-       psllq $18, %xmm9
-       paddq 72(%rsp), %xmm4
-       addq $64, %rax
-       paddq %xmm9, %xmm3
-       movdqa 40(%rsp), %xmm9
-       cmpq $63, %rcx
-       punpckhdq %xmm13, %xmm15
-       psllq $6, %xmm15
-       punpckldq %xmm13, %xmm10
-       paddq %xmm15, %xmm2
-       psllq $12, %xmm10
-       por 168(%rsp), %xmm6
-       pmuludq %xmm6, %xmm9
-       movdqa 88(%rsp), %xmm15
-       paddq %xmm10, %xmm0
-       movdqa 88(%rsp), %xmm13
-       psrlq $14, %xmm7
-       pand %xmm5, %xmm8
-       movdqa 184(%rsp), %xmm10
-       pand %xmm5, %xmm7
-       pmuludq %xmm7, %xmm15
-       paddq %xmm9, %xmm4
-       pmuludq %xmm6, %xmm13
-       movdqa 184(%rsp), %xmm9
-       paddq 168(%rsp), %xmm1
-       pmuludq %xmm7, %xmm10
-       pmuludq %xmm6, %xmm9
-       paddq %xmm15, %xmm4
-       movdqa 184(%rsp), %xmm15
-       paddq %xmm13, %xmm2
-       psrlq $26, %xmm14
-       movdqa 264(%rsp), %xmm13
-       paddq %xmm10, %xmm2
-       pmuludq %xmm8, %xmm15
-       pand %xmm5, %xmm14
-       paddq %xmm9, %xmm0
-       pmuludq %xmm6, %xmm13
-       movdqa 264(%rsp), %xmm9
-       movdqa 264(%rsp), %xmm10
-       pmuludq %xmm11, %xmm6
-       pmuludq %xmm8, %xmm9
-       paddq %xmm15, %xmm4
-       movdqa 264(%rsp), %xmm15
-       pmuludq %xmm14, %xmm10
-       paddq %xmm13, %xmm3
-       movdqa %xmm7, %xmm13
-       pmuludq %xmm7, %xmm15
-       paddq %xmm6, %xmm1
-       movdqa 312(%rsp), %xmm6
-       paddq %xmm9, %xmm2
-       pmuludq %xmm11, %xmm13
-       movdqa 248(%rsp), %xmm9
-       paddq %xmm10, %xmm4
-       pmuludq %xmm8, %xmm6
-       pmuludq 312(%rsp), %xmm7
-       paddq %xmm15, %xmm0
-       movdqa %xmm9, %xmm10
-       movdqa %xmm14, %xmm15
-       pmuludq %xmm11, %xmm10
-       paddq %xmm13, %xmm3
-       movdqa %xmm8, %xmm13
-       pmuludq %xmm11, %xmm13
-       paddq %xmm6, %xmm3
-       paddq %xmm7, %xmm1
-       movdqa 232(%rsp), %xmm6
-       pmuludq %xmm11, %xmm15
-       pmuludq 232(%rsp), %xmm8
-       paddq %xmm10, %xmm4
-       paddq %xmm8, %xmm1
-       movdqa 312(%rsp), %xmm10
-       paddq %xmm13, %xmm0
-       pmuludq %xmm14, %xmm6
-       movdqa 312(%rsp), %xmm13
-       pmuludq %xmm9, %xmm10
-       paddq %xmm15, %xmm2
-       movdqa 232(%rsp), %xmm7
-       pmuludq %xmm14, %xmm13
-       pmuludq 152(%rsp), %xmm14
-       paddq %xmm14, %xmm1
-       pmuludq %xmm9, %xmm7
-       paddq %xmm6, %xmm3
-       paddq %xmm10, %xmm2
-       movdqa 152(%rsp), %xmm10
-       paddq %xmm13, %xmm0
-       pmuludq %xmm9, %xmm10
-       paddq %xmm7, %xmm0
-       movdqa %xmm4, %xmm7
-       psrlq $26, %xmm7
-       pmuludq 56(%rsp), %xmm9
-       pand %xmm5, %xmm4
-       paddq %xmm7, %xmm2
-       paddq %xmm9, %xmm1
-       paddq %xmm10, %xmm3
-       movdqa %xmm2, %xmm7
-       movdqa %xmm2, %xmm9
-       movdqa %xmm3, %xmm6
-       psrlq $26, %xmm7
-       pand %xmm5, %xmm3
-       psrlq $26, %xmm6
-       paddq %xmm7, %xmm0
-       pand %xmm5, %xmm9
-       paddq %xmm6, %xmm1
-       movdqa %xmm0, %xmm10
-       movdqa %xmm1, %xmm6
-       pand %xmm5, %xmm10
-       pand %xmm5, %xmm1
-       psrlq $26, %xmm6
-       pmuludq 136(%rsp), %xmm6
-       paddq %xmm6, %xmm4
-       movdqa %xmm0, %xmm6
-       psrlq $26, %xmm6
-       movdqa %xmm4, %xmm2
-       movdqa %xmm4, %xmm7
-       paddq %xmm6, %xmm3
-       psrlq $26, %xmm2
-       pand %xmm5, %xmm7
-       movdqa %xmm3, %xmm0
-       paddq %xmm2, %xmm9
-       pand %xmm5, %xmm3
-       psrlq $26, %xmm0
-       paddq %xmm0, %xmm1
-       ja .Lpoly1305_blocks_x86_13
-       leaq -64(%rdx), %rax
-       movdqa %xmm3, %xmm6
-       andl $63, %edx
-       andq $-64, %rax
-       leaq 64(%rsi,%rax), %rsi
-.Lpoly1305_blocks_x86_7:
-       cmpq $31, %rdx
-       jbe .Lpoly1305_blocks_x86_9
-       movdqa -24(%rsp), %xmm13
-       movdqa %xmm6, %xmm0
-       movdqa %xmm6, %xmm3
-       movdqa 40(%rsp), %xmm11
-       movdqa %xmm1, %xmm12
-       testq %rsi, %rsi
-       movdqa -40(%rsp), %xmm2
-       pmuludq %xmm13, %xmm0
-       movdqa %xmm1, %xmm8
-       pmuludq %xmm1, %xmm11
-       movdqa %xmm10, %xmm4
-       movdqa %xmm1, %xmm14
-       pmuludq %xmm2, %xmm3
-       movdqa %xmm6, %xmm15
-       pmuludq %xmm1, %xmm13
-       movdqa %xmm7, %xmm1
-       pmuludq %xmm2, %xmm12
-       paddq %xmm0, %xmm11
-       movdqa -56(%rsp), %xmm0
-       pmuludq %xmm10, %xmm2
-       paddq %xmm3, %xmm13
-       pmuludq %xmm0, %xmm4
-       movdqa %xmm9, %xmm3
-       pmuludq %xmm0, %xmm3
-       paddq %xmm2, %xmm11
-       pmuludq %xmm0, %xmm8
-       movdqa %xmm6, %xmm2
-       pmuludq %xmm0, %xmm2
-       movdqa -8(%rsp), %xmm0
-       paddq %xmm4, %xmm13
-       movdqa 312(%rsp), %xmm4
-       paddq %xmm3, %xmm11
-       pmuludq 312(%rsp), %xmm6
-       movdqa 312(%rsp), %xmm3
-       pmuludq %xmm0, %xmm1
-       paddq %xmm2, %xmm12
-       pmuludq %xmm0, %xmm15
-       movdqa %xmm9, %xmm2
-       pmuludq %xmm0, %xmm2
-       pmuludq %xmm7, %xmm3
-       paddq %xmm1, %xmm11
-       movdqa 232(%rsp), %xmm1
-       pmuludq %xmm0, %xmm14
-       paddq %xmm15, %xmm8
-       pmuludq %xmm10, %xmm0
-       paddq %xmm2, %xmm13
-       movdqa 312(%rsp), %xmm2
-       pmuludq %xmm10, %xmm4
-       paddq %xmm3, %xmm13
-       movdqa 152(%rsp), %xmm3
-       pmuludq %xmm9, %xmm2
-       paddq %xmm6, %xmm14
-       pmuludq 232(%rsp), %xmm10
-       paddq %xmm0, %xmm12
-       pmuludq %xmm9, %xmm1
-       paddq %xmm10, %xmm14
-       movdqa 232(%rsp), %xmm0
-       pmuludq %xmm7, %xmm3
-       paddq %xmm4, %xmm8
-       pmuludq 152(%rsp), %xmm9
-       paddq %xmm2, %xmm12
-       paddq %xmm9, %xmm14
-       pmuludq %xmm7, %xmm0
-       paddq %xmm1, %xmm8
-       pmuludq 56(%rsp), %xmm7
-       paddq %xmm3, %xmm8
-       paddq %xmm7, %xmm14
-       paddq %xmm0, %xmm12
-       je .Lpoly1305_blocks_x86_10
-       movdqu (%rsi), %xmm1
-       pxor %xmm0, %xmm0
-       paddq 168(%rsp), %xmm14
-       movdqu 16(%rsi), %xmm2
-       movdqa %xmm1, %xmm3
-       punpckldq %xmm2, %xmm3
-       punpckhdq %xmm2, %xmm1
-       movdqa %xmm3, %xmm4
-       movdqa %xmm1, %xmm2
-       punpckldq %xmm0, %xmm4
-       punpckhdq %xmm0, %xmm3
-       punpckhdq %xmm0, %xmm1
-       punpckldq %xmm0, %xmm2
-       movdqa %xmm2, %xmm0
-       psllq $6, %xmm3
-       paddq %xmm4, %xmm11
-       psllq $12, %xmm0
-       paddq %xmm3, %xmm13
-       psllq $18, %xmm1
-       paddq %xmm0, %xmm12
-       paddq %xmm1, %xmm8
-.Lpoly1305_blocks_x86_10:
-       movdqa %xmm11, %xmm9
-       movdqa %xmm8, %xmm1
-       movdqa %xmm11, %xmm7
-       psrlq $26, %xmm9
-       movdqa %xmm8, %xmm6
-       pand %xmm5, %xmm7
-       paddq %xmm13, %xmm9
-       psrlq $26, %xmm1
-       pand %xmm5, %xmm6
-       movdqa %xmm9, %xmm10
-       paddq %xmm14, %xmm1
-       pand %xmm5, %xmm9
-       psrlq $26, %xmm10
-       movdqa %xmm1, %xmm0
-       pand %xmm5, %xmm1
-       paddq %xmm12, %xmm10
-       psrlq $26, %xmm0
-       pmuludq 136(%rsp), %xmm0
-       movdqa %xmm10, %xmm2
-       paddq %xmm0, %xmm7
-       psrlq $26, %xmm2
-       movdqa %xmm7, %xmm0
-       pand %xmm5, %xmm10
-       paddq %xmm2, %xmm6
-       psrlq $26, %xmm0
-       pand %xmm5, %xmm7
-       movdqa %xmm6, %xmm2
-       paddq %xmm0, %xmm9
-       pand %xmm5, %xmm6
-       psrlq $26, %xmm2
-       paddq %xmm2, %xmm1
-.Lpoly1305_blocks_x86_9:
-       testq %rsi, %rsi
-       je .Lpoly1305_blocks_x86_11
-       movdqa %xmm7, 0(%rdi)
-       movdqa %xmm9, 16(%rdi)
-       movdqa %xmm10, 32(%rdi)
-       movdqa %xmm6, 48(%rdi)
-       movdqa %xmm1, 64(%rdi)
-       movq -8(%rbp), %rbx
-       leave
-       ret
-.Lpoly1305_blocks_x86_5:
-       movdqa 0(%rdi), %xmm7
-       movdqa 16(%rdi), %xmm9
-       movdqa 32(%rdi), %xmm10
-       movdqa 48(%rdi), %xmm6
-       movdqa 64(%rdi), %xmm1
-       jmp .Lpoly1305_blocks_x86_6
-.Lpoly1305_blocks_x86_11:
-       movdqa %xmm7, %xmm0
-       movdqa %xmm9, %xmm2
-       movdqa %xmm6, %xmm3
-       psrldq $8, %xmm0
-       movabsq $4398046511103, %rbx
-       paddq %xmm0, %xmm7
-       psrldq $8, %xmm2
-       movdqa %xmm10, %xmm0
-       movd %xmm7, %edx
-       paddq %xmm2, %xmm9
-       psrldq $8, %xmm0
-       movl %edx, %ecx
-       movd %xmm9, %eax
-       paddq %xmm0, %xmm10
-       shrl $26, %ecx
-       psrldq $8, %xmm3
-       movdqa %xmm1, %xmm0
-       addl %ecx, %eax
-       movd %xmm10, %ecx
-       paddq %xmm3, %xmm6
-       movl %eax, %r9d
-       shrl $26, %eax
-       psrldq $8, %xmm0
-       addl %ecx, %eax
-       movd %xmm6, %ecx
-       paddq %xmm0, %xmm1
-       movl %eax, %esi
-       andl $67108863, %r9d
-       movd %xmm1, %r10d
-       shrl $26, %esi
-       andl $67108863, %eax
-       andl $67108863, %edx
-       addl %ecx, %esi
-       salq $8, %rax
-       movl %r9d, %ecx
-       shrl $18, %r9d
-       movl %esi, %r8d
-       shrl $26, %esi
-       andl $67108863, %r8d
-       addl %r10d, %esi
-       orq %r9, %rax
-       salq $16, %rsi
-       movq %r8, %r9
-       shrl $10, %r8d
-       salq $26, %rcx
-       orq %r8, %rsi
-       salq $34, %r9
-       orq %rdx, %rcx
-       movq %rsi, %r8
-       shrq $42, %rsi
-       movabsq $17592186044415, %rdx
-       orq %r9, %rax
-       andq %rbx, %r8
-       leaq (%rsi,%rsi,4), %rsi
-       andq %rdx, %rcx
-       andq %rdx, %rax
-       movabsq $-4398046511104, %r10
-       addq %rsi, %rcx
-       movq %rcx, %rsi
-       shrq $44, %rcx
-       addq %rcx, %rax
-       andq %rdx, %rsi
-       movq %rax, %rcx
-       shrq $44, %rax
-       addq %r8, %rax
-       andq %rdx, %rcx
-       andq %rax, %rbx
-       shrq $42, %rax
-       leaq (%rsi,%rax,4), %rsi
-       addq %rbx, %r10
-       addq %rax, %rsi
-       movq %rsi, %r8
-       shrq $44, %rsi
-       andq %rdx, %r8
-       addq %rcx, %rsi
-       leaq 5(%r8), %r9
-       movq %r9, %r11
-       andq %rdx, %r9
-       shrq $44, %r11
-       addq %rsi, %r11
-       movq %r11, %rax
-       andq %r11, %rdx
-       shrq $44, %rax
-       addq %rax, %r10
-       movq %r10, %rax
-       shrq $63, %rax
-       subq $1, %rax
-       movq %rax, %rcx
-       andq %rax, %r9
-       andq %rax, %rdx
-       notq %rcx
-       andq %r10, %rax
-       andq %rcx, %r8
-       andq %rcx, %rsi
-       andq %rbx, %rcx
-       orq %r9, %r8
-       orq %rdx, %rsi
-       orq %rax, %rcx
-       movq %r8, 0(%rdi)
-       movq %rsi, 8(%rdi)
-       movq %rcx, 16(%rdi)
-       movq -8(%rbp), %rbx
-       movq %rbp, %rax
-       subq %rsp, %rax
-       pxor %xmm15, %xmm15
-       pxor %xmm7, %xmm7
-       pxor %xmm14, %xmm14
-       pxor %xmm6, %xmm6
-       pxor %xmm13, %xmm13
-       pxor %xmm5, %xmm5
-       pxor %xmm12, %xmm12
-       pxor %xmm4, %xmm4
-       leave
-       addq $8, %rax
-       pxor %xmm11, %xmm11
-       pxor %xmm3, %xmm3
-       pxor %xmm10, %xmm10
-       pxor %xmm2, %xmm2
-       pxor %xmm9, %xmm9
-       pxor %xmm1, %xmm1
-       pxor %xmm8, %xmm8
-       pxor %xmm0, %xmm0
-       ret
-ELF(.size _gcry_poly1305_amd64_sse2_blocks,.-_gcry_poly1305_amd64_sse2_blocks;)
-
-#endif
index 22255fb..e57e64f 100644 (file)
@@ -1,5 +1,5 @@
 /* poly1305.c  -  Poly1305 internals and generic implementation
- * Copyright (C) 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2014,2017,2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-/* The code is based on public-domain Poly1305 implementation by
- * Andrew Moon at
- *  https://github.com/floodyberry/poly1305-opt
- */
-
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "bufhelp.h"
 #include "poly1305-internal.h"
 
+#include "mpi-internal.h"
+#include "longlong.h"
+
 
 static const char *selftest (void);
-\f
-
-
-#ifdef POLY1305_USE_SSE2
-
-void _gcry_poly1305_amd64_sse2_init_ext(void *state, const poly1305_key_t *key)
-                                       OPS_FUNC_ABI;
-unsigned int _gcry_poly1305_amd64_sse2_finish_ext(void *state, const byte *m,
-                                                 size_t remaining,
-                                                 byte mac[16]) OPS_FUNC_ABI;
-unsigned int _gcry_poly1305_amd64_sse2_blocks(void *ctx, const byte *m,
-                                             size_t bytes) OPS_FUNC_ABI;
-
-static const poly1305_ops_t poly1305_amd64_sse2_ops = {
-  POLY1305_SSE2_BLOCKSIZE,
-  _gcry_poly1305_amd64_sse2_init_ext,
-  _gcry_poly1305_amd64_sse2_blocks,
-  _gcry_poly1305_amd64_sse2_finish_ext
-};
-
-#else  /* !POLY1305_USE_SSE2 */
-
-static OPS_FUNC_ABI void poly1305_init_ext_ref32
-/**/                (void *state, const poly1305_key_t *key);
-static OPS_FUNC_ABI unsigned int poly1305_blocks_ref32
-/**/                (void *state, const byte *m, size_t bytes);
-static OPS_FUNC_ABI unsigned int poly1305_finish_ext_ref32
-/**/                (void *state, const byte * m,
-                     size_t remaining, byte mac[POLY1305_TAGLEN]);
-
-static const poly1305_ops_t poly1305_default_ops = {
-  POLY1305_REF_BLOCKSIZE,
-  poly1305_init_ext_ref32,
-  poly1305_blocks_ref32,
-  poly1305_finish_ext_ref32
-};
-
-#endif /* !POLY1305_USE_SSE2 */
-
-
-#ifdef POLY1305_USE_AVX2
-
-void _gcry_poly1305_amd64_avx2_init_ext(void *state, const poly1305_key_t *key)
-                                       OPS_FUNC_ABI;
-unsigned int _gcry_poly1305_amd64_avx2_finish_ext(void *state, const byte *m,
-                                                 size_t remaining,
-                                                 byte mac[16]) OPS_FUNC_ABI;
-unsigned int _gcry_poly1305_amd64_avx2_blocks(void *ctx, const byte *m,
-                                             size_t bytes) OPS_FUNC_ABI;
-
-static const poly1305_ops_t poly1305_amd64_avx2_ops = {
-  POLY1305_AVX2_BLOCKSIZE,
-  _gcry_poly1305_amd64_avx2_init_ext,
-  _gcry_poly1305_amd64_avx2_blocks,
-  _gcry_poly1305_amd64_avx2_finish_ext
-};
 
-#endif
 
+#undef HAVE_ASM_POLY1305_BLOCKS
 
-#ifdef POLY1305_USE_NEON
 
-void _gcry_poly1305_armv7_neon_init_ext(void *state, const poly1305_key_t *key)
-                                       OPS_FUNC_ABI;
-unsigned int _gcry_poly1305_armv7_neon_finish_ext(void *state, const byte *m,
-                                                 size_t remaining,
-                                                 byte mac[16]) OPS_FUNC_ABI;
-unsigned int _gcry_poly1305_armv7_neon_blocks(void *ctx, const byte *m,
-                                             size_t bytes) OPS_FUNC_ABI;
+#undef USE_MPI_64BIT
+#undef USE_MPI_32BIT
+#if BYTES_PER_MPI_LIMB == 8 && defined(HAVE_TYPE_U64)
+# define USE_MPI_64BIT 1
+#elif BYTES_PER_MPI_LIMB == 4
+# define USE_MPI_32BIT 1
+#else
+# error please implement for this limb size.
+#endif
 
-static const poly1305_ops_t poly1305_armv7_neon_ops = {
-  POLY1305_NEON_BLOCKSIZE,
-  _gcry_poly1305_armv7_neon_init_ext,
-  _gcry_poly1305_armv7_neon_blocks,
-  _gcry_poly1305_armv7_neon_finish_ext
-};
 
+/* USE_S390X_ASM indicates whether to enable zSeries code. */
+#undef USE_S390X_ASM
+#if BYTES_PER_MPI_LIMB == 8
+# if defined (__s390x__) && __GNUC__ >= 4 && __ARCH__ >= 9
+#  if defined(HAVE_GCC_INLINE_ASM_S390X)
+#   define USE_S390X_ASM 1
+#  endif /* USE_S390X_ASM */
+# endif
 #endif
 
 
-/* Reference unoptimized poly1305 implementation using 32 bit * 32 bit = 64 bit
- * multiplication and 64 bit addition.
- */
+#ifdef USE_S390X_ASM
 
-typedef struct poly1305_state_ref32_s
-{
-  u32 r[5];
-  u32 h[5];
-  u32 pad[4];
-  byte final;
-} poly1305_state_ref32_t;
+#define HAVE_ASM_POLY1305_BLOCKS 1
 
+extern unsigned int _gcry_poly1305_s390x_blocks1(void *state,
+                                                const byte *buf, size_t len,
+                                                byte high_pad);
 
-#ifndef POLY1305_USE_SSE2
-static OPS_FUNC_ABI void
-poly1305_init_ext_ref32 (void *state, const poly1305_key_t * key)
+static unsigned int
+poly1305_blocks (poly1305_context_t *ctx, const byte *buf, size_t len,
+                byte high_pad)
 {
-  poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
+  return _gcry_poly1305_s390x_blocks1(&ctx->state, buf, len, high_pad);
+}
 
-  gcry_assert (sizeof (*st) + POLY1305_STATE_ALIGNMENT <=
-              sizeof (((poly1305_context_t *) 0)->state));
+#endif /* USE_S390X_ASM */
 
-  /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-  st->r[0] = (buf_get_le32 (&key->b[0])) & 0x3ffffff;
-  st->r[1] = (buf_get_le32 (&key->b[3]) >> 2) & 0x3ffff03;
-  st->r[2] = (buf_get_le32 (&key->b[6]) >> 4) & 0x3ffc0ff;
-  st->r[3] = (buf_get_le32 (&key->b[9]) >> 6) & 0x3f03fff;
-  st->r[4] = (buf_get_le32 (&key->b[12]) >> 8) & 0x00fffff;
 
-  /* h = 0 */
+static void poly1305_init (poly1305_context_t *ctx,
+                          const byte key[POLY1305_KEYLEN])
+{
+  POLY1305_STATE *st = &ctx->state;
+
+  ctx->leftover = 0;
+
   st->h[0] = 0;
   st->h[1] = 0;
   st->h[2] = 0;
   st->h[3] = 0;
   st->h[4] = 0;
 
-  /* save pad for later */
-  st->pad[0] = buf_get_le32 (&key->b[16]);
-  st->pad[1] = buf_get_le32 (&key->b[20]);
-  st->pad[2] = buf_get_le32 (&key->b[24]);
-  st->pad[3] = buf_get_le32 (&key->b[28]);
+  st->r[0] = buf_get_le32(key + 0)  & 0x0fffffff;
+  st->r[1] = buf_get_le32(key + 4)  & 0x0ffffffc;
+  st->r[2] = buf_get_le32(key + 8)  & 0x0ffffffc;
+  st->r[3] = buf_get_le32(key + 12) & 0x0ffffffc;
 
-  st->final = 0;
+  st->k[0] = buf_get_le32(key + 16);
+  st->k[1] = buf_get_le32(key + 20);
+  st->k[2] = buf_get_le32(key + 24);
+  st->k[3] = buf_get_le32(key + 28);
 }
-#endif /* !POLY1305_USE_SSE2 */
 
 
-#ifndef POLY1305_USE_SSE2
-static OPS_FUNC_ABI unsigned int
-poly1305_blocks_ref32 (void *state, const byte * m, size_t bytes)
+#ifdef USE_MPI_64BIT
+
+#if defined (__aarch64__) && defined(HAVE_CPU_ARCH_ARM) && __GNUC__ >= 4
+
+/* A += B (armv8/aarch64) */
+#define ADD_1305_64(A2, A1, A0, B2, B1, B0) \
+      __asm__ ("adds %0, %3, %0\n" \
+              "adcs %1, %4, %1\n" \
+              "adc  %2, %5, %2\n" \
+              : "+r" (A0), "+r" (A1), "+r" (A2) \
+              : "r" (B0), "r" (B1), "r" (B2) \
+              : "cc" )
+
+#endif /* __aarch64__ */
+
+#if defined (__x86_64__) && defined(HAVE_CPU_ARCH_X86) && __GNUC__ >= 4
+
+/* A += B (x86-64) */
+#define ADD_1305_64(A2, A1, A0, B2, B1, B0) \
+      __asm__ ("addq %3, %0\n" \
+              "adcq %4, %1\n" \
+              "adcq %5, %2\n" \
+              : "+r" (A0), "+r" (A1), "+r" (A2) \
+              : "g" (B0), "g" (B1), "g" (B2) \
+              : "cc" )
+
+#endif /* __x86_64__ */
+
+#if defined (__powerpc__) && defined(HAVE_CPU_ARCH_PPC) && __GNUC__ >= 4
+
+/* A += B (ppc64) */
+#define ADD_1305_64(A2, A1, A0, B2, B1, B0) \
+      __asm__ ("addc %0, %3, %0\n" \
+              "adde %1, %4, %1\n" \
+              "adde %2, %5, %2\n" \
+              : "+r" (A0), "+r" (A1), "+r" (A2) \
+              : "r" (B0), "r" (B1), "r" (B2) \
+              : "cc" )
+
+#endif /* __powerpc__ */
+
+#ifndef ADD_1305_64
+/* A += B (generic, mpi) */
+#  define ADD_1305_64(A2, A1, A0, B2, B1, B0) do { \
+    u64 carry; \
+    add_ssaaaa(carry, A0, 0, A0, 0, B0); \
+    add_ssaaaa(A2, A1, A2, A1, B2, B1); \
+    add_ssaaaa(A2, A1, A2, A1, 0, carry); \
+  } while (0)
+#endif
+
+/* H = H * R mod 2¹³⁰-5 */
+#define MUL_MOD_1305_64(H2, H1, H0, R1, R0, R1_MULT5) do { \
+    u64 x0_lo, x0_hi, x1_lo, x1_hi; \
+    u64 t0_lo, t0_hi, t1_lo, t1_hi; \
+    \
+    /* x = a * r (partial mod 2^130-5) */ \
+    umul_ppmm(x0_hi, x0_lo, H0, R0);  /* h0 * r0 */ \
+    umul_ppmm(x1_hi, x1_lo, H0, R1);  /* h0 * r1 */ \
+    \
+    umul_ppmm(t0_hi, t0_lo, H1, R1_MULT5); /* h1 * r1 mod 2^130-5 */ \
+    add_ssaaaa(x0_hi, x0_lo, x0_hi, x0_lo, t0_hi, t0_lo); \
+    umul_ppmm(t1_hi, t1_lo, H1, R0);       /* h1 * r0 */ \
+    add_ssaaaa(x1_hi, x1_lo, x1_hi, x1_lo, t1_hi, t1_lo); \
+    \
+    t1_lo = H2 * R1_MULT5; /* h2 * r1 mod 2^130-5 */ \
+    t1_hi = H2 * R0;       /* h2 * r0 */ \
+    add_ssaaaa(H0, H1, x1_hi, x1_lo, t1_hi, t1_lo); \
+    \
+    /* carry propagation */ \
+    H2 = H0 & 3; \
+    H0 = (H0 >> 2) * 5; /* msb mod 2^130-5 */ \
+    ADD_1305_64(H2, H1, H0, (u64)0, x0_hi, x0_lo); \
+  } while (0)
+
+#ifndef HAVE_ASM_POLY1305_BLOCKS
+
+static unsigned int
+poly1305_blocks (poly1305_context_t *ctx, const byte *buf, size_t len,
+                byte high_pad)
 {
-  poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
-  const u32 hibit = (st->final) ? 0 : (1 << 24);       /* 1 << 128 */
-  u32 r0, r1, r2, r3, r4;
-  u32 s1, s2, s3, s4;
-  u32 h0, h1, h2, h3, h4;
-  u64 d0, d1, d2, d3, d4;
-  u32 c;
+  POLY1305_STATE *st = &ctx->state;
+  u64 r0, r1, r1_mult5;
+  u64 h0, h1, h2;
+  u64 m0, m1, m2;
+
+  m2 = high_pad;
+
+  h0 = st->h[0] + ((u64)st->h[1] << 32);
+  h1 = st->h[2] + ((u64)st->h[3] << 32);
+  h2 = st->h[4];
+
+  r0 = st->r[0] + ((u64)st->r[1] << 32);
+  r1 = st->r[2] + ((u64)st->r[3] << 32);
+
+  r1_mult5 = (r1 >> 2) + r1;
+
+  m0 = buf_get_le64(buf + 0);
+  m1 = buf_get_le64(buf + 8);
+  buf += POLY1305_BLOCKSIZE;
+  len -= POLY1305_BLOCKSIZE;
+
+  while (len >= POLY1305_BLOCKSIZE)
+    {
+      /* a = h + m */
+      ADD_1305_64(h2, h1, h0, m2, m1, m0);
+
+      m0 = buf_get_le64(buf + 0);
+      m1 = buf_get_le64(buf + 8);
+
+      /* h = a * r (partial mod 2^130-5) */
+      MUL_MOD_1305_64(h2, h1, h0, r1, r0, r1_mult5);
+
+      buf += POLY1305_BLOCKSIZE;
+      len -= POLY1305_BLOCKSIZE;
+    }
+
+  /* a = h + m */
+  ADD_1305_64(h2, h1, h0, m2, m1, m0);
+
+  /* h = a * r (partial mod 2^130-5) */
+  MUL_MOD_1305_64(h2, h1, h0, r1, r0, r1_mult5);
+
+  st->h[0] = h0;
+  st->h[1] = h0 >> 32;
+  st->h[2] = h1;
+  st->h[3] = h1 >> 32;
+  st->h[4] = h2;
+
+  return 6 * sizeof (void *) + 18 * sizeof (u64);
+}
+
+#endif /* !HAVE_ASM_POLY1305_BLOCKS */
+
+static unsigned int poly1305_final (poly1305_context_t *ctx,
+                                   byte mac[POLY1305_TAGLEN])
+{
+  POLY1305_STATE *st = &ctx->state;
+  unsigned int burn = 0;
+  u64 u, carry;
+  u64 k0, k1;
+  u64 h0, h1;
+  u64 h2;
+
+  /* process the remaining block */
+  if (ctx->leftover)
+    {
+      ctx->buffer[ctx->leftover++] = 1;
+      if (ctx->leftover < POLY1305_BLOCKSIZE)
+       {
+         memset (&ctx->buffer[ctx->leftover], 0,
+                 POLY1305_BLOCKSIZE - ctx->leftover);
+         ctx->leftover = POLY1305_BLOCKSIZE;
+       }
+      burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 0);
+    }
+
+  h0 = st->h[0] + ((u64)st->h[1] << 32);
+  h1 = st->h[2] + ((u64)st->h[3] << 32);
+  h2 = st->h[4];
+
+  k0 = st->k[0] + ((u64)st->k[1] << 32);
+  k1 = st->k[2] + ((u64)st->k[3] << 32);
+
+  /* check if h is more than 2^130-5, by adding 5. */
+  add_ssaaaa(carry, u, 0, h0, 0, 5);
+  add_ssaaaa(carry, u, 0, carry, 0, h1);
+  u = (carry + h2) >> 2; /* u == 0 or 1 */
 
-  r0 = st->r[0];
-  r1 = st->r[1];
-  r2 = st->r[2];
-  r3 = st->r[3];
-  r4 = st->r[4];
+  /* minus 2^130-5 ... (+5) */
+  u = (-u) & 5;
+  add_ssaaaa(h1, h0, h1, h0, 0, u);
 
-  s1 = r1 * 5;
-  s2 = r2 * 5;
-  s3 = r3 * 5;
-  s4 = r4 * 5;
+  /* add high part of key + h */
+  add_ssaaaa(h1, h0, h1, h0, k1, k0);
+  buf_put_le64(mac + 0, h0);
+  buf_put_le64(mac + 8, h1);
+
+  /* burn_stack */
+  return 4 * sizeof (void *) + 7 * sizeof (u64) + burn;
+}
+
+#endif /* USE_MPI_64BIT */
+
+#ifdef USE_MPI_32BIT
+
+#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
+
+/* HI:LO += A * B (arm) */
+#define UMUL_ADD_32(HI, LO, A, B) \
+      __asm__ ("umlal %1, %0, %4, %5" \
+              : "=r" (HI), "=r" (LO) \
+              : "0" (HI), "1" (LO), "r" (A), "r" (B) )
+
+/* A += B (arm) */
+#ifdef __GCC_ASM_FLAG_OUTPUTS__
+#  define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) do { \
+      u32 __carry; \
+      __asm__ ("adds %0, %0, %5\n" \
+              "adcs %1, %1, %6\n" \
+              "adcs %2, %2, %7\n" \
+              "adcs %3, %3, %8\n" \
+              : "+r" (A0), "+r" (A1), "+r" (A2), "+r" (A3), \
+                "=@cccs" (__carry) \
+              : "r" (B0), "r" (B1), "r" (B2), "r" (B3) \
+              : ); \
+      (A4) += (B4) + __carry; \
+    } while (0)
+#else
+#  define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) do { \
+      u32 __carry = (B0); \
+      __asm__ ("adds %0, %0, %2\n" \
+              "adcs %1, %1, %3\n" \
+              "rrx %2, %2\n" /* carry to 31th bit */ \
+              : "+r" (A0), "+r" (A1), "+r" (__carry) \
+              : "r" (B1), "r" (0) \
+              : "cc" ); \
+      __asm__ ("lsls %0, %0, #1\n" /* carry from 31th bit */ \
+              "adcs %1, %1, %4\n" \
+              "adcs %2, %2, %5\n" \
+              "adc  %3, %3, %6\n" \
+              : "+r" (__carry), "+r" (A2), "+r" (A3), "+r" (A4) \
+              : "r" (B2), "r" (B3), "r" (B4) \
+              : "cc" ); \
+    } while (0)
+#endif
+
+#endif /* HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS */
+
+#if defined (__i386__) && defined(HAVE_CPU_ARCH_X86) && __GNUC__ >= 5
+/* Note: ADD_1305_32 below does not compile on GCC-4.7 */
+
+/* A += B (i386) */
+#define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) \
+      __asm__ ("addl %5, %0\n" \
+              "adcl %6, %1\n" \
+              "adcl %7, %2\n" \
+              "adcl %8, %3\n" \
+              "adcl %9, %4\n" \
+              : "+r" (A0), "+r" (A1), "+r" (A2), "+r" (A3), "+r" (A4) \
+              : "g" (B0), "g" (B1), "g" (B2), "g" (B3), "g" (B4) \
+              : "cc" )
+
+#endif /* __i386__ */
+
+#ifndef UMUL_ADD_32
+/* HI:LO += A * B (generic, mpi) */
+#  define UMUL_ADD_32(HI, LO, A, B) do { \
+    u32 t_lo, t_hi; \
+    umul_ppmm(t_hi, t_lo, A, B); \
+    add_ssaaaa(HI, LO, HI, LO, t_hi, t_lo); \
+  } while (0)
+#endif
+
+#ifndef ADD_1305_32
+/* A += B (generic, mpi) */
+#  define ADD_1305_32(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0) do { \
+    u32 carry0, carry1, carry2; \
+    add_ssaaaa(carry0, A0, 0, A0, 0, B0); \
+    add_ssaaaa(carry1, A1, 0, A1, 0, B1); \
+    add_ssaaaa(carry1, A1, carry1, A1, 0, carry0); \
+    add_ssaaaa(carry2, A2, 0, A2, 0, B2); \
+    add_ssaaaa(carry2, A2, carry2, A2, 0, carry1); \
+    add_ssaaaa(A4, A3, A4, A3, B4, B3); \
+    add_ssaaaa(A4, A3, A4, A3, 0, carry2); \
+  } while (0)
+#endif
+
+/* H = H * R mod 2¹³⁰-5 */
+#define MUL_MOD_1305_32(H4, H3, H2, H1, H0, R3, R2, R1, R0, \
+                        R3_MULT5, R2_MULT5, R1_MULT5) do { \
+    u32 x0_lo, x0_hi, x1_lo, x1_hi, x2_lo, x2_hi, x3_lo, x3_hi; \
+    u32 t0_lo, t0_hi; \
+    \
+    /* x = a * r (partial mod 2^130-5) */ \
+    umul_ppmm(x0_hi, x0_lo, H0, R0);  /* h0 * r0 */ \
+    umul_ppmm(x1_hi, x1_lo, H0, R1);  /* h0 * r1 */ \
+    umul_ppmm(x2_hi, x2_lo, H0, R2);  /* h0 * r2 */ \
+    umul_ppmm(x3_hi, x3_lo, H0, R3);  /* h0 * r3 */ \
+    \
+    UMUL_ADD_32(x0_hi, x0_lo, H1, R3_MULT5); /* h1 * r3 mod 2^130-5 */ \
+    UMUL_ADD_32(x1_hi, x1_lo, H1, R0);       /* h1 * r0 */ \
+    UMUL_ADD_32(x2_hi, x2_lo, H1, R1);       /* h1 * r1 */ \
+    UMUL_ADD_32(x3_hi, x3_lo, H1, R2);       /* h1 * r2 */ \
+    \
+    UMUL_ADD_32(x0_hi, x0_lo, H2, R2_MULT5); /* h2 * r2 mod 2^130-5 */ \
+    UMUL_ADD_32(x1_hi, x1_lo, H2, R3_MULT5); /* h2 * r3 mod 2^130-5 */ \
+    UMUL_ADD_32(x2_hi, x2_lo, H2, R0);       /* h2 * r0 */ \
+    UMUL_ADD_32(x3_hi, x3_lo, H2, R1);       /* h2 * r1 */ \
+    \
+    UMUL_ADD_32(x0_hi, x0_lo, H3, R1_MULT5); /* h3 * r1 mod 2^130-5 */ \
+    H1 = x0_hi; \
+    UMUL_ADD_32(x1_hi, x1_lo, H3, R2_MULT5); /* h3 * r2 mod 2^130-5 */ \
+    UMUL_ADD_32(x2_hi, x2_lo, H3, R3_MULT5); /* h3 * r3 mod 2^130-5 */ \
+    UMUL_ADD_32(x3_hi, x3_lo, H3, R0);       /* h3 * r0 */ \
+    \
+    t0_lo = H4 * R1_MULT5; /* h4 * r1 mod 2^130-5 */ \
+    t0_hi = H4 * R2_MULT5; /* h4 * r2 mod 2^130-5 */ \
+    add_ssaaaa(H2, x1_lo, x1_hi, x1_lo, 0, t0_lo); \
+    add_ssaaaa(H3, x2_lo, x2_hi, x2_lo, 0, t0_hi); \
+    t0_lo = H4 * R3_MULT5; /* h4 * r3 mod 2^130-5 */ \
+    t0_hi = H4 * R0;       /* h4 * r0 */ \
+    add_ssaaaa(H4, x3_lo, x3_hi, x3_lo, t0_hi, t0_lo); \
+    \
+    /* carry propagation */ \
+    H0 = (H4 >> 2) * 5; /* msb mod 2^130-5 */ \
+    H4 = H4 & 3; \
+    ADD_1305_32(H4, H3, H2, H1, H0, 0, x3_lo, x2_lo, x1_lo, x0_lo); \
+  } while (0)
+
+#ifndef HAVE_ASM_POLY1305_BLOCKS
+
+static unsigned int
+poly1305_blocks (poly1305_context_t *ctx, const byte *buf, size_t len,
+                byte high_pad)
+{
+  POLY1305_STATE *st = &ctx->state;
+  u32 r1_mult5, r2_mult5, r3_mult5;
+  u32 h0, h1, h2, h3, h4;
+  u32 m0, m1, m2, m3, m4;
+
+  m4 = high_pad;
 
   h0 = st->h[0];
   h1 = st->h[1];
@@ -191,54 +432,27 @@ poly1305_blocks_ref32 (void *state, const byte * m, size_t bytes)
   h3 = st->h[3];
   h4 = st->h[4];
 
-  while (bytes >= POLY1305_REF_BLOCKSIZE)
+  r1_mult5 = (st->r[1] >> 2) + st->r[1];
+  r2_mult5 = (st->r[2] >> 2) + st->r[2];
+  r3_mult5 = (st->r[3] >> 2) + st->r[3];
+
+  while (len >= POLY1305_BLOCKSIZE)
     {
-      /* h += m[i] */
-      h0 += (buf_get_le32 (m + 0)) & 0x3ffffff;
-      h1 += (buf_get_le32 (m + 3) >> 2) & 0x3ffffff;
-      h2 += (buf_get_le32 (m + 6) >> 4) & 0x3ffffff;
-      h3 += (buf_get_le32 (m + 9) >> 6) & 0x3ffffff;
-      h4 += (buf_get_le32 (m + 12) >> 8) | hibit;
-
-      /* h *= r */
-      d0 =
-       ((u64) h0 * r0) + ((u64) h1 * s4) +
-       ((u64) h2 * s3) + ((u64) h3 * s2) + ((u64) h4 * s1);
-      d1 =
-       ((u64) h0 * r1) + ((u64) h1 * r0) +
-       ((u64) h2 * s4) + ((u64) h3 * s3) + ((u64) h4 * s2);
-      d2 =
-       ((u64) h0 * r2) + ((u64) h1 * r1) +
-       ((u64) h2 * r0) + ((u64) h3 * s4) + ((u64) h4 * s3);
-      d3 =
-       ((u64) h0 * r3) + ((u64) h1 * r2) +
-       ((u64) h2 * r1) + ((u64) h3 * r0) + ((u64) h4 * s4);
-      d4 =
-       ((u64) h0 * r4) + ((u64) h1 * r3) +
-       ((u64) h2 * r2) + ((u64) h3 * r1) + ((u64) h4 * r0);
-
-      /* (partial) h %= p */
-      c = (u32) (d0 >> 26);
-      h0 = (u32) d0 & 0x3ffffff;
-      d1 += c;
-      c = (u32) (d1 >> 26);
-      h1 = (u32) d1 & 0x3ffffff;
-      d2 += c;
-      c = (u32) (d2 >> 26);
-      h2 = (u32) d2 & 0x3ffffff;
-      d3 += c;
-      c = (u32) (d3 >> 26);
-      h3 = (u32) d3 & 0x3ffffff;
-      d4 += c;
-      c = (u32) (d4 >> 26);
-      h4 = (u32) d4 & 0x3ffffff;
-      h0 += c * 5;
-      c = (h0 >> 26);
-      h0 = h0 & 0x3ffffff;
-      h1 += c;
-
-      m += POLY1305_REF_BLOCKSIZE;
-      bytes -= POLY1305_REF_BLOCKSIZE;
+      m0 = buf_get_le32(buf + 0);
+      m1 = buf_get_le32(buf + 4);
+      m2 = buf_get_le32(buf + 8);
+      m3 = buf_get_le32(buf + 12);
+
+      /* a = h + m */
+      ADD_1305_32(h4, h3, h2, h1, h0, m4, m3, m2, m1, m0);
+
+      /* h = a * r (partial mod 2^130-5) */
+      MUL_MOD_1305_32(h4, h3, h2, h1, h0,
+                     st->r[3], st->r[2], st->r[1], st->r[0],
+                     r3_mult5, r2_mult5, r1_mult5);
+
+      buf += POLY1305_BLOCKSIZE;
+      len -= POLY1305_BLOCKSIZE;
     }
 
   st->h[0] = h0;
@@ -247,185 +461,102 @@ poly1305_blocks_ref32 (void *state, const byte * m, size_t bytes)
   st->h[3] = h3;
   st->h[4] = h4;
 
-  return (16 * sizeof (u32) + 5 * sizeof (u64) + 5 * sizeof (void *));
+  return 6 * sizeof (void *) + 28 * sizeof (u32);
 }
-#endif /* !POLY1305_USE_SSE2 */
 
+#endif /* !HAVE_ASM_POLY1305_BLOCKS */
 
-#ifndef POLY1305_USE_SSE2
-static OPS_FUNC_ABI unsigned int
-poly1305_finish_ext_ref32 (void *state, const byte * m,
-                          size_t remaining, byte mac[POLY1305_TAGLEN])
+static unsigned int poly1305_final (poly1305_context_t *ctx,
+                                   byte mac[POLY1305_TAGLEN])
 {
-  poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state;
-  u32 h0, h1, h2, h3, h4, c;
-  u32 g0, g1, g2, g3, g4;
-  u64 f;
-  u32 mask;
+  POLY1305_STATE *st = &ctx->state;
   unsigned int burn = 0;
+  u32 carry, tmp0, tmp1, tmp2, u;
+  u32 h4, h3, h2, h1, h0;
 
   /* process the remaining block */
-  if (remaining)
+  if (ctx->leftover)
     {
-      byte final[POLY1305_REF_BLOCKSIZE] = { 0 };
-      size_t i;
-      for (i = 0; i < remaining; i++)
-       final[i] = m[i];
-      final[remaining] = 1;
-      st->final = 1;
-      burn = poly1305_blocks_ref32 (st, final, POLY1305_REF_BLOCKSIZE);
+      ctx->buffer[ctx->leftover++] = 1;
+      if (ctx->leftover < POLY1305_BLOCKSIZE)
+       {
+         memset (&ctx->buffer[ctx->leftover], 0,
+                 POLY1305_BLOCKSIZE - ctx->leftover);
+         ctx->leftover = POLY1305_BLOCKSIZE;
+       }
+      burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 0);
     }
 
-  /* fully carry h */
   h0 = st->h[0];
   h1 = st->h[1];
   h2 = st->h[2];
   h3 = st->h[3];
   h4 = st->h[4];
 
-  c = h1 >> 26;
-  h1 = h1 & 0x3ffffff;
-  h2 += c;
-  c = h2 >> 26;
-  h2 = h2 & 0x3ffffff;
-  h3 += c;
-  c = h3 >> 26;
-  h3 = h3 & 0x3ffffff;
-  h4 += c;
-  c = h4 >> 26;
-  h4 = h4 & 0x3ffffff;
-  h0 += c * 5;
-  c = h0 >> 26;
-  h0 = h0 & 0x3ffffff;
-  h1 += c;
-
-  /* compute h + -p */
-  g0 = h0 + 5;
-  c = g0 >> 26;
-  g0 &= 0x3ffffff;
-  g1 = h1 + c;
-  c = g1 >> 26;
-  g1 &= 0x3ffffff;
-  g2 = h2 + c;
-  c = g2 >> 26;
-  g2 &= 0x3ffffff;
-  g3 = h3 + c;
-  c = g3 >> 26;
-  g3 &= 0x3ffffff;
-  g4 = h4 + c - (1 << 26);
-
-  /* select h if h < p, or h + -p if h >= p */
-  mask = (g4 >> ((sizeof (u32) * 8) - 1)) - 1;
-  g0 &= mask;
-  g1 &= mask;
-  g2 &= mask;
-  g3 &= mask;
-  g4 &= mask;
-  mask = ~mask;
-  h0 = (h0 & mask) | g0;
-  h1 = (h1 & mask) | g1;
-  h2 = (h2 & mask) | g2;
-  h3 = (h3 & mask) | g3;
-  h4 = (h4 & mask) | g4;
-
-  /* h = h % (2^128) */
-  h0 = ((h0) | (h1 << 26)) & 0xffffffff;
-  h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
-  h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
-  h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
-
-  /* mac = (h + pad) % (2^128) */
-  f = (u64) h0 + st->pad[0];
-  h0 = (u32) f;
-  f = (u64) h1 + st->pad[1] + (f >> 32);
-  h1 = (u32) f;
-  f = (u64) h2 + st->pad[2] + (f >> 32);
-  h2 = (u32) f;
-  f = (u64) h3 + st->pad[3] + (f >> 32);
-  h3 = (u32) f;
-
-  buf_put_le32 (mac + 0, h0);
-  buf_put_le32 (mac + 4, h1);
-  buf_put_le32 (mac + 8, h2);
-  buf_put_le32 (mac + 12, h3);
-
-  /* zero out the state */
-  st->h[0] = 0;
-  st->h[1] = 0;
-  st->h[2] = 0;
-  st->h[3] = 0;
-  st->h[4] = 0;
-  st->r[0] = 0;
-  st->r[1] = 0;
-  st->r[2] = 0;
-  st->r[3] = 0;
-  st->r[4] = 0;
-  st->pad[0] = 0;
-  st->pad[1] = 0;
-  st->pad[2] = 0;
-  st->pad[3] = 0;
+  /* check if h is more than 2^130-5, by adding 5. */
+  add_ssaaaa(carry, tmp0, 0, h0, 0, 5);
+  add_ssaaaa(carry, tmp0, 0, carry, 0, h1);
+  add_ssaaaa(carry, tmp0, 0, carry, 0, h2);
+  add_ssaaaa(carry, tmp0, 0, carry, 0, h3);
+  u = (carry + h4) >> 2; /* u == 0 or 1 */
+
+  /* minus 2^130-5 ... (+5) */
+  u = (-u) & 5;
+  add_ssaaaa(carry, h0, 0, h0, 0, u);
+  add_ssaaaa(carry, h1, 0, h1, 0, carry);
+  add_ssaaaa(carry, h2, 0, h2, 0, carry);
+  add_ssaaaa(carry, h3, 0, h3, 0, carry);
+
+  /* add high part of key + h */
+  add_ssaaaa(tmp0, h0, 0, h0, 0, st->k[0]);
+  add_ssaaaa(tmp1, h1, 0, h1, 0, st->k[1]);
+  add_ssaaaa(tmp1, h1, tmp1, h1, 0, tmp0);
+  add_ssaaaa(tmp2, h2, 0, h2, 0, st->k[2]);
+  add_ssaaaa(tmp2, h2, tmp2, h2, 0, tmp1);
+  add_ssaaaa(carry, h3, 0, h3, 0, st->k[3]);
+  h3 += tmp2;
+
+  buf_put_le32(mac + 0, h0);
+  buf_put_le32(mac + 4, h1);
+  buf_put_le32(mac + 8, h2);
+  buf_put_le32(mac + 12, h3);
 
   /* burn_stack */
-  return (13 * sizeof (u32) + sizeof (u64) +
-         POLY1305_REF_BLOCKSIZE + 6 * sizeof (void *)) + burn;
+  return 4 * sizeof (void *) + 10 * sizeof (u32) + burn;
 }
-#endif /* !POLY1305_USE_SSE2*/
-
 
-\f
+#endif /* USE_MPI_32BIT */
 
 
-static inline void *
-poly1305_get_state (poly1305_context_t * ctx)
+unsigned int
+_gcry_poly1305_update_burn (poly1305_context_t *ctx, const byte *m,
+                           size_t bytes)
 {
-  byte *c = ctx->state;
-  c += POLY1305_STATE_ALIGNMENT - 1;
-  c -= (uintptr_t) c & (POLY1305_STATE_ALIGNMENT - 1);
-  return c;
-}
-
-
-static void
-poly1305_init (poly1305_context_t * ctx, const poly1305_key_t * key)
-{
-  void *state = poly1305_get_state (ctx);
-
-  ctx->leftover = 0;
-
-  ctx->ops->init_ext (state, key);
-}
-
-
-void
-_gcry_poly1305_update (poly1305_context_t * ctx, const byte * m, size_t bytes)
-{
-  void *state = poly1305_get_state (ctx);
   unsigned int burn = 0;
-  size_t block_size = ctx->ops->block_size;
 
   /* handle leftover */
   if (ctx->leftover)
     {
-      size_t want = (block_size - ctx->leftover);
+      size_t want = (POLY1305_BLOCKSIZE - ctx->leftover);
       if (want > bytes)
        want = bytes;
       buf_cpy (ctx->buffer + ctx->leftover, m, want);
       bytes -= want;
       m += want;
       ctx->leftover += want;
-      if (ctx->leftover < block_size)
-       return;
-      burn = ctx->ops->blocks (state, ctx->buffer, block_size);
+      if (ctx->leftover < POLY1305_BLOCKSIZE)
+       return 0;
+      burn = poly1305_blocks (ctx, ctx->buffer, POLY1305_BLOCKSIZE, 1);
       ctx->leftover = 0;
     }
 
   /* process full blocks */
-  if (bytes >= block_size)
+  if (bytes >= POLY1305_BLOCKSIZE)
     {
-      size_t want = (bytes & ~(block_size - 1));
-      burn = ctx->ops->blocks (state, m, want);
-      m += want;
-      bytes -= want;
+      size_t nblks = bytes / POLY1305_BLOCKSIZE;
+      burn = poly1305_blocks (ctx, m, nblks * POLY1305_BLOCKSIZE, 1);
+      m += nblks * POLY1305_BLOCKSIZE;
+      bytes -= nblks * POLY1305_BLOCKSIZE;
     }
 
   /* store leftover */
@@ -435,18 +566,28 @@ _gcry_poly1305_update (poly1305_context_t * ctx, const byte * m, size_t bytes)
       ctx->leftover += bytes;
     }
 
+  return burn;
+}
+
+
+void
+_gcry_poly1305_update (poly1305_context_t *ctx, const byte *m, size_t bytes)
+{
+  unsigned int burn;
+
+  burn = _gcry_poly1305_update_burn (ctx, m, bytes);
+
   if (burn)
     _gcry_burn_stack (burn);
 }
 
 
 void
-_gcry_poly1305_finish (poly1305_context_t * ctx, byte mac[POLY1305_TAGLEN])
+_gcry_poly1305_finish (poly1305_context_t *ctx, byte mac[POLY1305_TAGLEN])
 {
-  void *state = poly1305_get_state (ctx);
   unsigned int burn;
 
-  burn = ctx->ops->finish_ext (state, ctx->buffer, ctx->leftover, mac);
+  burn = poly1305_final (ctx, mac);
 
   _gcry_burn_stack (burn);
 }
@@ -458,8 +599,6 @@ _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key,
 {
   static int initialized;
   static const char *selftest_failed;
-  poly1305_key_t keytmp;
-  unsigned int features = _gcry_get_hw_features ();
 
   if (!initialized)
     {
@@ -475,26 +614,7 @@ _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key,
   if (selftest_failed)
     return GPG_ERR_SELFTEST_FAILED;
 
-#ifdef POLY1305_USE_SSE2
-  ctx->ops = &poly1305_amd64_sse2_ops;
-#else
-  ctx->ops = &poly1305_default_ops;
-#endif
-
-#ifdef POLY1305_USE_AVX2
-  if (features & HWF_INTEL_AVX2)
-    ctx->ops = &poly1305_amd64_avx2_ops;
-#endif
-#ifdef POLY1305_USE_NEON
-  if (features & HWF_ARM_NEON)
-    ctx->ops = &poly1305_armv7_neon_ops;
-#endif
-  (void)features;
-
-  buf_cpy (keytmp.b, key, POLY1305_KEYLEN);
-  poly1305_init (ctx, &keytmp);
-
-  wipememory (&keytmp, sizeof (keytmp));
+  poly1305_init (ctx, key);
 
   return 0;
 }
index b8167c7..0ca7709 100644 (file)
@@ -75,15 +75,17 @@ _gcry_rsa_oaep_decode (unsigned char **r_result, size_t *r_resultlen,
                        const unsigned char *label, size_t labellen);
 gpg_err_code_t
 _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
-                      const unsigned char *value, size_t valuelen, int saltlen,
-                      const void *random_override, size_t random_override_len);
+                      int hashed_already, int saltlen,
+                      const unsigned char *value, size_t valuelen,
+                      const void *random_override);
 gpg_err_code_t
-_gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
+_gcry_rsa_pss_verify (gcry_mpi_t value, int hashed_already, gcry_mpi_t encoded,
                       unsigned int nbits, int algo, size_t saltlen);
 
 
 
 /*-- dsa-common.c --*/
+void _gcry_dsa_modify_k (gcry_mpi_t k, gcry_mpi_t q, int qbits);
 gcry_mpi_t _gcry_dsa_gen_k (gcry_mpi_t q, int security_level);
 gpg_err_code_t _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
                                         gcry_mpi_t dsa_q, gcry_mpi_t dsa_x,
@@ -91,7 +93,8 @@ gpg_err_code_t _gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
                                         unsigned int h1len,
                                         int halgo,
                                         unsigned int extraloops);
-
+gpg_err_code_t _gcry_dsa_compute_hash (gcry_mpi_t *r_hash, gcry_mpi_t input,
+                                       int hashalgo);
 gpg_err_code_t _gcry_dsa_normalize_hash (gcry_mpi_t input,
                                          gcry_mpi_t *out,
                                          unsigned int qbits);
index c40ef97..68defea 100644 (file)
@@ -39,9 +39,10 @@ static int
 pss_verify_cmp (void *opaque, gcry_mpi_t tmp)
 {
   struct pk_encoding_ctx *ctx = opaque;
-  gcry_mpi_t hash = ctx->verify_arg;
+  gcry_mpi_t value = ctx->verify_arg;
 
-  return _gcry_rsa_pss_verify (hash, tmp, ctx->nbits - 1,
+  return _gcry_rsa_pss_verify (value, !(ctx->flags & PUBKEY_FLAG_PREHASH),
+                               tmp, ctx->nbits - 1,
                                ctx->hash_algo, ctx->saltlen);
 }
 
@@ -81,6 +82,11 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list,
               encoding = PUBKEY_ENC_RAW;
               flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given.  */
             }
+          else if (!memcmp (s, "sm2", 3))
+            {
+                encoding = PUBKEY_ENC_RAW;
+                flags |= PUBKEY_FLAG_SM2 | PUBKEY_FLAG_RAW_FLAG;
+            }
           else if (!igninvflag)
             rc = GPG_ERR_INV_FLAG;
           break;
@@ -132,6 +138,8 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list,
             flags |= PUBKEY_FLAG_RFC6979;
           else if (!memcmp (s, "noparam", 7))
             ; /* Ignore - it is the default.  */
+          else if (!memcmp (s, "prehash", 7))
+            flags |= PUBKEY_FLAG_PREHASH;
           else if (!igninvflag)
             rc = GPG_ERR_INV_FLAG;
           break;
@@ -221,6 +229,11 @@ get_hash_algo (const char *s, size_t n)
     { "sha3-256", GCRY_MD_SHA3_256 },
     { "sha3-384", GCRY_MD_SHA3_384 },
     { "sha3-512", GCRY_MD_SHA3_512 },
+    { "sm3", GCRY_MD_SM3 },
+    { "shake128", GCRY_MD_SHAKE128 },
+    { "shake256", GCRY_MD_SHAKE256 },
+    { "sha512-224", GCRY_MD_SHA512_224 },
+    { "sha512-256", GCRY_MD_SHA512_256 },
     { NULL, 0 }
   };
   int algo;
@@ -428,6 +441,8 @@ _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
         *r_eccflags = PUBKEY_FLAG_EDDSA;
       if (!strcmp (name, "gost"))
         *r_eccflags = PUBKEY_FLAG_GOST;
+      if (!strcmp (name, "sm2"))
+        *r_eccflags = PUBKEY_FLAG_SM2;
     }
 
   *r_parms = l2;
@@ -649,7 +664,8 @@ _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx)
    (<mpi>)
    or
    (data
-    [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979, eddsa])]
+    [(flags [raw, direct, pkcs1, oaep, pss,
+             no-blinding, rfc6979, eddsa, prehash])]
     [(hash <algo> <value>)]
     [(value <text>)]
     [(hash-algo <algo>)]
@@ -661,11 +677,11 @@ _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx)
    Either the VALUE or the HASH element must be present for use
    with signatures.  VALUE is used for encryption.
 
-   HASH-ALGO is specific to OAEP and EDDSA.
+   HASH-ALGO is specific to OAEP, PSS and EDDSA.
 
    LABEL is specific to OAEP.
 
-   SALT-LENGTH is for PSS it is limited to 16384 bytes.
+   SALT-LENGTH is for PSS, it is limited to 16384 bytes.
 
    RANDOM-OVERRIDE is used to replace random nonces for regression
    testing.  */
@@ -684,7 +700,10 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
   ldata = sexp_find_token (input, "data", 0);
   if (!ldata)
     { /* assume old style */
-      *ret_mpi = sexp_nth_mpi (input, 0, 0);
+      int mpifmt = (ctx->flags & PUBKEY_FLAG_RAW_FLAG) ?
+        GCRYMPI_FMT_OPAQUE : GCRYMPI_FMT_STD;
+
+      *ret_mpi = sexp_nth_mpi (input, 0, mpifmt);
       return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
     }
 
@@ -712,7 +731,8 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
   else if (unknown_flag)
     rc = GPG_ERR_INV_FLAG;
   else if (ctx->encoding == PUBKEY_ENC_RAW
-           && (parsed_flags & PUBKEY_FLAG_EDDSA))
+           && ((parsed_flags & PUBKEY_FLAG_EDDSA)
+               || (ctx->flags & PUBKEY_FLAG_EDDSA)))
     {
       /* Prepare for EdDSA.  */
       gcry_sexp_t list;
@@ -724,6 +744,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
           rc = GPG_ERR_INV_OBJ;
           goto leave;
         }
+      /* Hash algo is determined by curve.  No hash-algo is OK.  */
       /* Get HASH-ALGO. */
       list = sexp_find_token (ldata, "hash-algo", 0);
       if (list)
@@ -739,11 +760,32 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
             }
           sexp_release (list);
         }
-      else
-        rc = GPG_ERR_INV_OBJ;
       if (rc)
         goto leave;
 
+      /* Get LABEL. */
+      list = sexp_find_token (ldata, "label", 0);
+      if (list)
+        {
+          s = sexp_nth_data (list, 1, &n);
+          if (!s)
+            rc = GPG_ERR_NO_OBJ;
+          else if (n > 0)
+            {
+              ctx->label = xtrymalloc (n);
+              if (!ctx->label)
+                rc = gpg_err_code_from_syserror ();
+              else
+                {
+                  memcpy (ctx->label, s, n);
+                  ctx->labellen = n;
+                }
+            }
+          sexp_release (list);
+          if (rc)
+            goto leave;
+        }
+
       /* Get VALUE.  */
       value = sexp_nth_buffer (lvalue, 1, &valuelen);
       if (!value)
@@ -767,27 +809,66 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
       /* Note that mpi_set_opaque takes ownership of VALUE.  */
       *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
     }
-  else if (ctx->encoding == PUBKEY_ENC_RAW && lhash
+  else if (ctx->encoding == PUBKEY_ENC_RAW
+           && (lhash || (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH)))
            && ((parsed_flags & PUBKEY_FLAG_RAW_FLAG)
                || (parsed_flags & PUBKEY_FLAG_RFC6979)))
     {
+      void * value;
+      size_t valuelen;
+      gcry_sexp_t list;
+
       /* Raw encoding along with a hash element.  This is commonly
          used for DSA.  For better backward error compatibility we
          allow this only if either the rfc6979 flag has been given or
          the raw flags was explicitly given.  */
-      if (sexp_length (lhash) != 3)
-        rc = GPG_ERR_INV_OBJ;
-      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
-        rc = GPG_ERR_INV_OBJ;
-      else
+
+      if (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH))
         {
-          void *value;
-          size_t valuelen;
+          /* Get HASH-ALGO. */
+          list = sexp_find_token (ldata, "hash-algo", 0);
+          if (list)
+            {
+              s = sexp_nth_data (list, 1, &n);
+              if (!s)
+                rc = GPG_ERR_NO_OBJ;
+              else
+                {
+                  ctx->hash_algo = get_hash_algo (s, n);
+                  if (!ctx->hash_algo)
+                    rc = GPG_ERR_DIGEST_ALGO;
+                }
+              sexp_release (list);
+              if (rc)
+                goto leave;
+            }
+
+          /* Get optional LABEL.  */
+          list = sexp_find_token (ldata, "label", 0);
+          if (list)
+            {
+              s = sexp_nth_data (list, 1, &n);
+              if (!s)
+                rc = GPG_ERR_NO_OBJ;
+              else if (n > 0)
+                {
+                  ctx->label = xtrymalloc (n);
+                  if (!ctx->label)
+                    rc = gpg_err_code_from_syserror ();
+                  else
+                    {
+                      memcpy (ctx->label, s, n);
+                      ctx->labellen = n;
+                    }
+                }
+              else
+                rc = GPG_ERR_INV_ARG;
+              sexp_release (list);
+              if (rc)
+                goto leave;
+            }
 
-         ctx->hash_algo = get_hash_algo (s, n);
-          if (!ctx->hash_algo)
-            rc = GPG_ERR_DIGEST_ALGO;
-          else if (!(value=sexp_nth_buffer (lhash, 2, &valuelen)))
+          if ( !(value=sexp_nth_buffer (lvalue, 1, &valuelen)) || !valuelen )
             rc = GPG_ERR_INV_OBJ;
           else if ((valuelen * 8) < valuelen)
             {
@@ -797,10 +878,64 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
           else
             *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
         }
+      else if (lhash)
+        {
+          /* Get optional LABEL.  */
+          list = sexp_find_token (ldata, "label", 0);
+          if (list)
+            {
+              s = sexp_nth_data (list, 1, &n);
+              if (!s)
+                rc = GPG_ERR_NO_OBJ;
+              else if (n > 0)
+                {
+                  ctx->label = xtrymalloc (n);
+                  if (!ctx->label)
+                    rc = gpg_err_code_from_syserror ();
+                  else
+                    {
+                      memcpy (ctx->label, s, n);
+                      ctx->labellen = n;
+                    }
+                }
+              else
+                rc = GPG_ERR_INV_ARG;
+              sexp_release (list);
+              if (rc)
+                goto leave;
+            }
+
+          if (sexp_length (lhash) != 3)
+            rc = GPG_ERR_INV_OBJ;
+          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
+            rc = GPG_ERR_INV_OBJ;
+          else
+            {
+              ctx->hash_algo = get_hash_algo (s, n);
+
+              if (!ctx->hash_algo)
+                rc = GPG_ERR_DIGEST_ALGO;
+              else if ( !(value=sexp_nth_buffer (lhash, 2, &valuelen))
+                        || !valuelen )
+                rc = GPG_ERR_INV_OBJ;
+              else if ((valuelen * 8) < valuelen)
+                {
+                  xfree (value);
+                  rc = GPG_ERR_TOO_LARGE;
+                }
+              else
+                *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
+            }
+        }
+      else
+        rc = GPG_ERR_CONFLICT;
+
+      if (rc)
+        goto leave;
     }
   else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
     {
-      /* RFC6969 may only be used with the a hash value and not the
+      /* RFC6979 may only be used with the a hash value and not the
          MPI based value.  */
       if (parsed_flags & PUBKEY_FLAG_RFC6979)
         {
@@ -856,29 +991,81 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
           xfree (random_override);
         }
     }
-  else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash
+  else if (ctx->encoding == PUBKEY_ENC_PKCS1
+           && (lhash || (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH)))
           && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
     {
-      if (sexp_length (lhash) != 3)
-        rc = GPG_ERR_INV_OBJ;
-      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
-        rc = GPG_ERR_INV_OBJ;
-      else
+      if (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH))
         {
-          const void * value;
+          void * value;
           size_t valuelen;
+          gcry_sexp_t list;
 
-         ctx->hash_algo = get_hash_algo (s, n);
+          /* Get HASH-ALGO. */
+          list = sexp_find_token (ldata, "hash-algo", 0);
+          if (list)
+            {
+              s = sexp_nth_data (list, 1, &n);
+              if (!s)
+                rc = GPG_ERR_NO_OBJ;
+              else
+                {
+                  ctx->hash_algo = get_hash_algo (s, n);
+                  if (!ctx->hash_algo)
+                    rc = GPG_ERR_DIGEST_ALGO;
+                }
+              sexp_release (list);
+              if (rc)
+                goto leave;
+            }
 
-          if (!ctx->hash_algo)
-            rc = GPG_ERR_DIGEST_ALGO;
-          else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
-                    || !valuelen )
+          if ( !(value=sexp_nth_buffer (lvalue, 1, &valuelen)) || !valuelen )
             rc = GPG_ERR_INV_OBJ;
+          else if ((valuelen * 8) < valuelen)
+            {
+              xfree (value);
+              rc = GPG_ERR_TOO_LARGE;
+            }
           else
-           rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
-                                                 value, valuelen,
-                                                 ctx->hash_algo);
+            {
+              void *hash;
+
+              n = _gcry_md_get_algo_dlen (ctx->hash_algo);
+              hash = xtrymalloc (n);
+              if (!hash)
+                rc = gpg_err_code_from_syserror ();
+              else
+                {
+                  _gcry_md_hash_buffer (ctx->hash_algo, hash, value, valuelen);
+                  rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
+                                                       hash, n, ctx->hash_algo);
+                  xfree (hash);
+                }
+            }
+        }
+      else if (lhash)
+        {
+          if (sexp_length (lhash) != 3)
+            rc = GPG_ERR_INV_OBJ;
+          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
+            rc = GPG_ERR_INV_OBJ;
+          else
+            {
+              const void * value;
+              size_t valuelen;
+
+              ctx->hash_algo = get_hash_algo (s, n);
+
+              if (!ctx->hash_algo)
+                rc = GPG_ERR_DIGEST_ALGO;
+              else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
+                        || !valuelen )
+                rc = GPG_ERR_INV_OBJ;
+              else
+                rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
+                                                     value, valuelen,
+                                                     ctx->hash_algo);
+            }
         }
     }
   else if (ctx->encoding == PUBKEY_ENC_PKCS1_RAW && lvalue
@@ -981,125 +1168,180 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
           xfree (random_override);
        }
     }
-  else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
-          && ctx->op == PUBKEY_OP_SIGN)
+  else if (ctx->encoding == PUBKEY_ENC_PSS && ctx->op == PUBKEY_OP_SIGN)
     {
-      if (sexp_length (lhash) != 3)
-        rc = GPG_ERR_INV_OBJ;
-      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
-        rc = GPG_ERR_INV_OBJ;
-      else
-        {
-          const void * value;
-          size_t valuelen;
-          void *random_override = NULL;
-          size_t random_override_len = 0;
+      const void * value;
+      size_t valuelen;
+      gcry_sexp_t list;
+      void *random_override = NULL;
 
-         ctx->hash_algo = get_hash_algo (s, n);
+      if (lvalue)
+        {
+          /* Get HASH-ALGO. */
+          list = sexp_find_token (ldata, "hash-algo", 0);
+          if (list)
+            {
+              s = sexp_nth_data (list, 1, &n);
+              if (!s)
+                rc = GPG_ERR_NO_OBJ;
+              else
+                {
+                  ctx->hash_algo = get_hash_algo (s, n);
+                  if (!ctx->hash_algo)
+                    rc = GPG_ERR_DIGEST_ALGO;
+                }
+              sexp_release (list);
+              if (rc)
+                goto leave;
+            }
 
-          if (!ctx->hash_algo)
-            rc = GPG_ERR_DIGEST_ALGO;
-          else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
-                    || !valuelen )
+          if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
+            rc = GPG_ERR_INV_OBJ;
+          ctx->flags |= PUBKEY_FLAG_PREHASH;
+        }
+      else if (lhash)
+        {
+          if (sexp_length (lhash) != 3)
+            rc = GPG_ERR_INV_OBJ;
+          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
             rc = GPG_ERR_INV_OBJ;
           else
-           {
-             gcry_sexp_t list;
+            {
+              ctx->hash_algo = get_hash_algo (s, n);
 
-             /* Get SALT-LENGTH. */
-             list = sexp_find_token (ldata, "salt-length", 0);
-             if (list)
-               {
-                 s = sexp_nth_data (list, 1, &n);
-                 if (!s)
-                   {
-                     rc = GPG_ERR_NO_OBJ;
-                     goto leave;
-                   }
-                 ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
-                 sexp_release (list);
-               }
+              if (!ctx->hash_algo)
+                rc = GPG_ERR_DIGEST_ALGO;
+              else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
+                        || !valuelen )
+                rc = GPG_ERR_INV_OBJ;
+            }
+        }
+      else
+        rc = GPG_ERR_CONFLICT;
 
-              /* Get optional RANDOM-OVERRIDE.  */
-              list = sexp_find_token (ldata, "random-override", 0);
-              if (list)
-                {
-                  s = sexp_nth_data (list, 1, &n);
-                  if (!s)
-                    rc = GPG_ERR_NO_OBJ;
-                  else if (n > 0)
-                    {
-                      random_override = xtrymalloc (n);
-                      if (!random_override)
-                        rc = gpg_err_code_from_syserror ();
-                      else
-                        {
-                          memcpy (random_override, s, n);
-                          random_override_len = n;
-                        }
-                    }
-                  sexp_release (list);
-                  if (rc)
-                    goto leave;
-                }
+      if (rc)
+        goto leave;
 
-              /* Encode the data.  (NBITS-1 is due to 8.1.1, step 1.) */
-             rc = _gcry_rsa_pss_encode (ret_mpi, ctx->nbits - 1,
-                                         ctx->hash_algo,
-                                         value, valuelen, ctx->saltlen,
-                                         random_override, random_override_len);
+      /* Get SALT-LENGTH. */
+      list = sexp_find_token (ldata, "salt-length", 0);
+      if (list)
+        {
+          s = sexp_nth_data (list, 1, &n);
+          if (!s)
+            {
+              rc = GPG_ERR_NO_OBJ;
+              goto leave;
+            }
+          ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
+          sexp_release (list);
+        }
 
-              xfree (random_override);
-           }
+      /* Get optional RANDOM-OVERRIDE.  */
+      list = sexp_find_token (ldata, "random-override", 0);
+      if (list)
+        {
+          s = sexp_nth_data (list, 1, &n);
+          if (!s)
+            rc = GPG_ERR_NO_OBJ;
+          else if (n == ctx->saltlen)
+            {
+              random_override = xtrymalloc (n);
+              if (!random_override)
+                rc = gpg_err_code_from_syserror ();
+              else
+                memcpy (random_override, s, n);
+            }
+          else
+            rc = GPG_ERR_INV_ARG;
+          sexp_release (list);
+          if (rc)
+            goto leave;
         }
+
+      /* Encode the data.  (NBITS-1 is due to 8.1.1, step 1.) */
+      rc = _gcry_rsa_pss_encode (ret_mpi, ctx->nbits - 1,
+                                 ctx->hash_algo, ctx->saltlen,
+                                 !(ctx->flags & PUBKEY_FLAG_PREHASH),
+                                 value, valuelen,
+                                 random_override);
+      xfree (random_override);
     }
-  else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
-          && ctx->op == PUBKEY_OP_VERIFY)
+  else if (ctx->encoding == PUBKEY_ENC_PSS && ctx->op == PUBKEY_OP_VERIFY)
     {
-      if (sexp_length (lhash) != 3)
-        rc = GPG_ERR_INV_OBJ;
-      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
-        rc = GPG_ERR_INV_OBJ;
-      else
+      gcry_sexp_t list;
+
+      if (lvalue)
         {
-         ctx->hash_algo = get_hash_algo (s, n);
+          /* Get HASH-ALGO. */
+          list = sexp_find_token (ldata, "hash-algo", 0);
+          if (list)
+            {
+              s = sexp_nth_data (list, 1, &n);
+              if (!s)
+                rc = GPG_ERR_NO_OBJ;
+              else
+                {
+                  ctx->hash_algo = get_hash_algo (s, n);
+                  if (!ctx->hash_algo)
+                    rc = GPG_ERR_DIGEST_ALGO;
+                }
+              sexp_release (list);
+              if (rc)
+                goto leave;
+            }
 
-          if (!ctx->hash_algo)
-            rc = GPG_ERR_DIGEST_ALGO;
-         else
-           {
-             gcry_sexp_t list;
-             /* Get SALT-LENGTH. */
-             list = sexp_find_token (ldata, "salt-length", 0);
-             if (list)
-               {
-                  unsigned long ul;
+          *ret_mpi = sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_OPAQUE);
+          if (!*ret_mpi)
+            rc = GPG_ERR_INV_OBJ;
 
-                 s = sexp_nth_data (list, 1, &n);
-                 if (!s)
-                   {
-                     rc = GPG_ERR_NO_OBJ;
-                      sexp_release (list);
-                     goto leave;
-                   }
-                 ul = strtoul (s, NULL, 10);
-                  if (ul > 16384)
-                    {
-                      rc = GPG_ERR_TOO_LARGE;
-                      sexp_release (list);
-                      goto leave;
-                    }
-                  ctx->saltlen = ul;
-                 sexp_release (list);
-               }
+          ctx->flags |= PUBKEY_FLAG_PREHASH;
+        }
+      else if (lhash)
+        {
+          if (sexp_length (lhash) != 3)
+            rc = GPG_ERR_INV_OBJ;
+          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
+            rc = GPG_ERR_INV_OBJ;
+          else
+            {
+              ctx->hash_algo = get_hash_algo (s, n);
 
-             *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
-             if (!*ret_mpi)
-               rc = GPG_ERR_INV_OBJ;
-             ctx->verify_cmp = pss_verify_cmp;
-             ctx->verify_arg = *ret_mpi;
-           }
-       }
+              if (!ctx->hash_algo)
+                rc = GPG_ERR_DIGEST_ALGO;
+              else
+                {
+                  *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_OPAQUE);
+                  if (!*ret_mpi)
+                    rc = GPG_ERR_INV_OBJ;
+                }
+            }
+        }
+      else
+        rc = GPG_ERR_CONFLICT;
+
+      if (rc)
+        goto leave;
+
+      /* Get SALT-LENGTH. */
+      list = sexp_find_token (ldata, "salt-length", 0);
+      if (list)
+        {
+          s = sexp_nth_data (list, 1, &n);
+          if (!s)
+            {
+              rc = GPG_ERR_NO_OBJ;
+              goto leave;
+            }
+          ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
+          if (ctx->saltlen > 16384)
+            rc = GPG_ERR_TOO_LARGE;
+          sexp_release (list);
+          if (rc)
+            goto leave;
+        }
+
+      ctx->verify_cmp = pss_verify_cmp;
+      ctx->verify_arg = *ret_mpi;
     }
   else
     rc = GPG_ERR_CONFLICT;
@@ -1110,7 +1352,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
   sexp_release (lvalue);
 
   if (!rc)
-    ctx->flags = parsed_flags;
+    ctx->flags |= parsed_flags;
   else
     {
       xfree (ctx->label);
index 8ec15fd..8deeced 100644 (file)
@@ -34,7 +34,7 @@
 
 /* This is the list of the public-key algorithms included in
    Libgcrypt.  */
-static gcry_pk_spec_t *pubkey_list[] =
+static gcry_pk_spec_t * const pubkey_list[] =
   {
 #if USE_ECC
     &_gcry_pubkey_spec_ecc,
@@ -61,6 +61,7 @@ map_algo (int algo)
    case GCRY_PK_RSA_S: return GCRY_PK_RSA;
    case GCRY_PK_ELG_E: return GCRY_PK_ELG;
    case GCRY_PK_ECDSA: return GCRY_PK_ECC;
+   case GCRY_PK_EDDSA: return GCRY_PK_ECC;
    case GCRY_PK_ECDH:  return GCRY_PK_ECC;
    default:            return algo;
    }
@@ -194,6 +195,8 @@ _gcry_pk_map_name (const char *string)
     return 0;
   if (spec->flags.disabled)
     return 0;
+  if (!spec->flags.fips && fips_mode ())
+    return 0;
   return spec->algo;
 }
 
@@ -223,7 +226,7 @@ check_pubkey_algo (int algo, unsigned use)
   gcry_pk_spec_t *spec;
 
   spec = spec_from_algo (algo);
-  if (spec)
+  if (spec && !spec->flags.disabled && (spec->flags.fips || !fips_mode ()))
     {
       if (((use & GCRY_PK_USAGE_SIGN)
           && (! (spec->use & GCRY_PK_USAGE_SIGN)))
@@ -321,7 +324,11 @@ _gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
   if (rc)
     goto leave;
 
-  if (spec->encrypt)
+  if (spec->flags.disabled)
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (spec->encrypt)
     rc = spec->encrypt (r_ciph, s_data, keyparms);
   else
     rc = GPG_ERR_NOT_IMPLEMENTED;
@@ -373,7 +380,11 @@ _gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
   if (rc)
     goto leave;
 
-  if (spec->decrypt)
+  if (spec->flags.disabled)
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (spec->decrypt)
     rc = spec->decrypt (r_plain, s_data, keyparms);
   else
     rc = GPG_ERR_NOT_IMPLEMENTED;
@@ -426,7 +437,11 @@ _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
   if (rc)
     goto leave;
 
-  if (spec->sign)
+  if (spec->flags.disabled)
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (spec->sign)
     rc = spec->sign (r_sig, s_hash, keyparms);
   else
     rc = GPG_ERR_NOT_IMPLEMENTED;
@@ -437,6 +452,147 @@ _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
 }
 
 
+gcry_err_code_t
+_gcry_pk_sign_md (gcry_sexp_t *r_sig, const char *tmpl, gcry_md_hd_t hd_orig,
+                  gcry_sexp_t s_skey, gcry_ctx_t ctx)
+{
+  gcry_err_code_t rc;
+  gcry_pk_spec_t *spec;
+  gcry_sexp_t keyparms = NULL;
+  gcry_sexp_t s_hash = NULL;
+  int algo;
+  const unsigned char *digest;
+  gcry_error_t err;
+  gcry_md_hd_t hd;
+  char *s;
+  char *hash_name;
+
+  *r_sig = NULL;
+
+  /* Check if it has fixed hash name or %s */
+  s = strstr (tmpl, "(hash ");
+  if (s == NULL)
+    return GPG_ERR_DIGEST_ALGO;
+
+  s += 6;
+  if (!strncmp (s, "%s", 2))
+    hash_name = NULL;
+  else
+    {
+      char *p;
+
+      for (p = s; *p && *p != ' '; p++)
+       ;
+
+      hash_name = xtrymalloc (p - s + 1);
+      if (!hash_name)
+       return gpg_error_from_syserror ();
+      memcpy (hash_name, s, p - s);
+      hash_name[p - s] = 0;
+    }
+
+  err = _gcry_md_copy (&hd, hd_orig);
+  if (err)
+    {
+      xfree (hash_name);
+      return gpg_err_code (err);
+    }
+
+  if (hash_name)
+    {
+      algo = _gcry_md_map_name (hash_name);
+      if (algo == 0
+          || (fips_mode () && algo == GCRY_MD_SHA1))
+       {
+         xfree (hash_name);
+         _gcry_md_close (hd);
+         return GPG_ERR_DIGEST_ALGO;
+       }
+
+      digest = _gcry_md_read (hd, algo);
+    }
+  else
+    {
+      algo = _gcry_md_get_algo (hd);
+
+      if (fips_mode () && algo == GCRY_MD_SHA1)
+        {
+          _gcry_md_close (hd);
+          return GPG_ERR_DIGEST_ALGO;
+        }
+
+      digest = _gcry_md_read (hd, 0);
+    }
+
+  if (!digest)
+    {
+      xfree (hash_name);
+      _gcry_md_close (hd);
+      return GPG_ERR_NOT_IMPLEMENTED;
+    }
+
+  if (!ctx)
+    {
+      if (hash_name)
+       rc = _gcry_sexp_build (&s_hash, NULL, tmpl,
+                              (int) _gcry_md_get_algo_dlen (algo),
+                              digest);
+      else
+       rc = _gcry_sexp_build (&s_hash, NULL, tmpl,
+                              _gcry_md_algo_name (algo),
+                              (int) _gcry_md_get_algo_dlen (algo),
+                              digest);
+    }
+  else
+    {
+      const unsigned char *p;
+      size_t len;
+
+      rc = _gcry_pk_get_random_override (ctx, &p, &len);
+      if (rc)
+        {
+          _gcry_md_close (hd);
+          return rc;
+        }
+
+      if (hash_name)
+       rc = _gcry_sexp_build (&s_hash, NULL, tmpl,
+                              (int) _gcry_md_get_algo_dlen (algo),
+                              digest,
+                              (int) len, p);
+      else
+       rc = _gcry_sexp_build (&s_hash, NULL, tmpl,
+                              _gcry_md_algo_name (algo),
+                              (int) _gcry_md_get_algo_dlen (algo),
+                              digest,
+                              (int) len, p);
+    }
+
+  xfree (hash_name);
+  _gcry_md_close (hd);
+  if (rc)
+    return rc;
+
+  rc = spec_from_sexp (s_skey, 1, &spec, &keyparms);
+  if (rc)
+    goto leave;
+
+  if (spec->flags.disabled)
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (spec->sign)
+    rc = spec->sign (r_sig, s_hash, keyparms);
+  else
+    rc = GPG_ERR_NOT_IMPLEMENTED;
+
+ leave:
+  sexp_release (s_hash);
+  sexp_release (keyparms);
+  return rc;
+}
+
+
 /*
    Verify a signature.
 
@@ -455,12 +611,93 @@ _gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
   if (rc)
     goto leave;
 
-  if (spec->verify)
+  if (spec->flags.disabled)
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (spec->verify)
+    rc = spec->verify (s_sig, s_hash, keyparms);
+  else
+    rc = GPG_ERR_NOT_IMPLEMENTED;
+
+ leave:
+  sexp_release (keyparms);
+  return rc;
+}
+
+
+gcry_err_code_t
+_gcry_pk_verify_md (gcry_sexp_t s_sig, const char *tmpl, gcry_md_hd_t hd_orig,
+                    gcry_sexp_t s_pkey, gcry_ctx_t ctx)
+{
+  gcry_err_code_t rc;
+  gcry_pk_spec_t *spec;
+  gcry_sexp_t keyparms = NULL;
+  gcry_sexp_t s_hash = NULL;
+  int algo;
+  const unsigned char *digest;
+  gcry_error_t err;
+  gcry_md_hd_t hd;
+
+  err = _gcry_md_copy (&hd, hd_orig);
+  if (err)
+    return gpg_err_code (err);
+
+  algo = _gcry_md_get_algo (hd);
+
+  if (fips_mode () && algo == GCRY_MD_SHA1)
+    return GPG_ERR_DIGEST_ALGO;
+
+  digest = _gcry_md_read (hd, 0);
+  if (!digest)
+    {
+      _gcry_md_close (hd);
+      return GPG_ERR_DIGEST_ALGO;
+    }
+
+  if (!ctx)
+    rc = _gcry_sexp_build (&s_hash, NULL, tmpl,
+                           _gcry_md_algo_name (algo),
+                           (int) _gcry_md_get_algo_dlen (algo),
+                           digest);
+  else
+    {
+      const unsigned char *p;
+      size_t len;
+
+      rc = _gcry_pk_get_random_override (ctx, &p, &len);
+      if (rc)
+        {
+          _gcry_md_close (hd);
+          return rc;
+        }
+
+      rc = _gcry_sexp_build (&s_hash, NULL, tmpl,
+                             _gcry_md_algo_name (algo),
+                             (int) _gcry_md_get_algo_dlen (algo),
+                             digest,
+                             (int) len, p);
+    }
+
+  _gcry_md_close (hd);
+  if (rc)
+    return rc;
+
+  rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms);
+  if (rc)
+    goto leave;
+
+  if (spec->flags.disabled)
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (spec->verify)
     rc = spec->verify (s_sig, s_hash, keyparms);
   else
     rc = GPG_ERR_NOT_IMPLEMENTED;
 
  leave:
+  sexp_release (s_hash);
   sexp_release (keyparms);
   return rc;
 }
@@ -486,7 +723,11 @@ _gcry_pk_testkey (gcry_sexp_t s_key)
   if (rc)
     goto leave;
 
-  if (spec->check_secret_key)
+  if (spec->flags.disabled)
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (!spec->flags.fips && fips_mode ())
+    rc = GPG_ERR_PUBKEY_ALGO;
+  else if (spec->check_secret_key)
     rc = spec->check_secret_key (keyparms);
   else
     rc = GPG_ERR_NOT_IMPLEMENTED;
@@ -568,7 +809,7 @@ _gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
   spec = spec_from_name (name);
   xfree (name);
   name = NULL;
-  if (!spec)
+  if (!spec || spec->flags.disabled || (!spec->flags.fips && fips_mode ()))
     {
       rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm.  */
       goto leave;
@@ -608,6 +849,10 @@ _gcry_pk_get_nbits (gcry_sexp_t key)
 
   if (spec_from_sexp (key, 0, &spec, &parms))
     return 0; /* Error - 0 is a suitable indication for that.  */
+  if (spec->flags.disabled)
+    return 0;
+  if (!spec->flags.fips && fips_mode ())
+    return 0;
 
   nbits = spec->get_nbits (parms);
   sexp_release (parms);
@@ -741,6 +986,10 @@ _gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits)
         return NULL;
     }
 
+  if (spec->flags.disabled)
+    return NULL;
+  if (!spec->flags.fips && fips_mode ())
+    return NULL;
   if (spec->get_curve)
     result = spec->get_curve (keyparms, iterator, r_nbits);
 
@@ -926,17 +1175,6 @@ _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
 gcry_err_code_t
 _gcry_pk_init (void)
 {
-  if (fips_mode())
-    {
-      /* disable algorithms that are disallowed in fips */
-      int idx;
-      gcry_pk_spec_t *spec;
-
-      for (idx = 0; (spec = pubkey_list[idx]); idx++)
-        if (!spec->flags.fips)
-          spec->flags.disabled = 1;
-    }
-
   return 0;
 }
 
@@ -951,7 +1189,9 @@ _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
 
   algo = map_algo (algo);
   spec = spec_from_algo (algo);
-  if (spec && !spec->flags.disabled && spec->selftest)
+  if (spec && !spec->flags.disabled
+      && (spec->flags.fips || !fips_mode ())
+      && spec->selftest)
     ec = spec->selftest (algo, extended, report);
   else
     {
@@ -960,7 +1200,8 @@ _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
          of an encryption mode (e.g. pkcs1, ecdsa, or ecdh).  */
       if (report)
         report ("pubkey", algo, "module",
-                spec && !spec->flags.disabled?
+                spec && !spec->flags.disabled
+                && (spec->flags.fips || !fips_mode ())?
                 "no selftest available" :
                 spec? "algorithm disabled" :
                 "algorithm not found");
@@ -968,3 +1209,48 @@ _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report)
 
   return gpg_error (ec);
 }
+
+
+struct pk_random_override {
+  size_t len;
+  unsigned char area[];
+};
+
+gpg_err_code_t
+_gcry_pk_random_override_new (gcry_ctx_t *r_ctx,
+                              const unsigned char *p, size_t len)
+{
+  gcry_ctx_t ctx;
+  struct pk_random_override *pro;
+
+  *r_ctx = NULL;
+  if (!p)
+    return GPG_ERR_EINVAL;
+
+  ctx = _gcry_ctx_alloc (CONTEXT_TYPE_RANDOM_OVERRIDE,
+                         sizeof (size_t) + len, NULL);
+  if (!ctx)
+    return gpg_err_code_from_syserror ();
+  pro = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_RANDOM_OVERRIDE);
+  pro->len = len;
+  memcpy (pro->area, p, len);
+
+  *r_ctx = ctx;
+  return 0;
+}
+
+gpg_err_code_t
+_gcry_pk_get_random_override (gcry_ctx_t ctx,
+                              const unsigned char **r_p, size_t *r_len)
+{
+  struct pk_random_override *pro;
+
+  pro = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_RANDOM_OVERRIDE);
+  if (!pro)
+    return GPG_ERR_EINVAL;
+
+  *r_p = pro->area;
+  *r_len = pro->len;
+
+  return 0;
+}
index aed8cad..c270ce9 100644 (file)
@@ -35,6 +35,7 @@
 #include "g10lib.h"
 #include "types.h"
 #include "cipher.h"
+#include "cipher-internal.h"
 
 #define RFC2268_BLOCKSIZE 8
 
@@ -227,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++)
@@ -262,8 +266,10 @@ setkey_core (void *context, const unsigned char *key, unsigned int keylen, int w
 }
 
 static gpg_err_code_t
-do_setkey (void *context, const unsigned char *key, unsigned int keylen)
+do_setkey (void *context, const unsigned char *key, unsigned int keylen,
+           cipher_bulk_ops_t *bulk_ops)
 {
+  (void)bulk_ops;
   return setkey_core (context, key, keylen, 1);
 }
 
@@ -343,7 +349,7 @@ selftest (void)
 
 
 
-static gcry_cipher_oid_spec_t oids_rfc2268_40[] =
+static const gcry_cipher_oid_spec_t oids_rfc2268_40[] =
   {
     /*{ "1.2.840.113549.3.2", GCRY_CIPHER_MODE_CBC },*/
     /* pbeWithSHAAnd40BitRC2_CBC */
@@ -351,7 +357,7 @@ static gcry_cipher_oid_spec_t oids_rfc2268_40[] =
     { NULL }
   };
 
-static gcry_cipher_oid_spec_t oids_rfc2268_128[] =
+static const gcry_cipher_oid_spec_t oids_rfc2268_128[] =
   {
     /* pbeWithSHAAnd128BitRC2_CBC */
     { "1.2.840.113549.1.12.1.5", GCRY_CIPHER_MODE_CBC },
index e533bbe..184fcd2 100644 (file)
@@ -18,7 +18,7 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "asm-common-aarch64.h"
 
 #if defined(__AARCH64EL__)
 #ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
        addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
 
 .globl _gcry_aes_arm_encrypt_block
-.type   _gcry_aes_arm_encrypt_block,%function;
+ELF(.type   _gcry_aes_arm_encrypt_block,%function;)
 
 _gcry_aes_arm_encrypt_block:
        /* input:
@@ -216,6 +216,7 @@ _gcry_aes_arm_encrypt_block:
         *      %w3: number of rounds.. 10, 12 or 14
         *      %x4: encryption table
         */
+       CFI_STARTPROC();
 
        /* read input block */
 
@@ -262,7 +263,7 @@ _gcry_aes_arm_encrypt_block:
        stp     RC, RD, [RDST, #8];
 
        mov     x0, #(0);
-       ret;
+       ret_spec_stop;
 
 .ltorg
 .Lenc_not_128:
@@ -285,7 +286,8 @@ _gcry_aes_arm_encrypt_block:
        lastencround(11, RNA, RNB, RNC, RND, RA, RB, RC, RD);
 
        b .Lenc_done;
-.size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;
+       CFI_ENDPROC();
+ELF(.size _gcry_aes_arm_encrypt_block,.-_gcry_aes_arm_encrypt_block;)
 
 #define addroundkey_dec(round, ra, rb, rc, rd, rna, rnb, rnc, rnd) \
        ldr rna, [CTX, #(((round) * 16) + 0 * 4)]; \
@@ -429,7 +431,7 @@ _gcry_aes_arm_encrypt_block:
        addroundkey(rna, rnb, rnc, rnd, ra, rb, rc, rd, dummy);
 
 .globl _gcry_aes_arm_decrypt_block
-.type   _gcry_aes_arm_decrypt_block,%function;
+ELF(.type   _gcry_aes_arm_decrypt_block,%function;)
 
 _gcry_aes_arm_decrypt_block:
        /* input:
@@ -439,6 +441,7 @@ _gcry_aes_arm_decrypt_block:
         *      %w3: number of rounds.. 10, 12 or 14
         *      %x4: decryption table
         */
+       CFI_STARTPROC();
 
        /* read input block */
 
@@ -483,7 +486,7 @@ _gcry_aes_arm_decrypt_block:
        stp     RC, RD, [RDST, #8];
 
        mov     x0, #(0);
-       ret;
+       ret_spec_stop;
 
 .ltorg
 .Ldec_256:
@@ -504,7 +507,8 @@ _gcry_aes_arm_decrypt_block:
        decround(9, RA, RB, RC, RD, RNA, RNB, RNC, RND, preload_first_key);
 
        b .Ldec_tail;
-.size _gcry_aes_arm_decrypt_block,.-_gcry_aes_arm_decrypt_block;
+       CFI_ENDPROC();
+ELF(.size _gcry_aes_arm_decrypt_block,.-_gcry_aes_arm_decrypt_block;)
 
 #endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
 #endif /*__AARCH64EL__ */
index 735e5cd..ff6b0b2 100644 (file)
 /* Prevent compiler from issuing SSE instructions between asm blocks. */
 #  pragma GCC target("no-sse")
 #endif
+#if __clang__
+#  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
+#endif
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR          NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE   ASM_FUNC_ATTR ALWAYS_INLINE
+#define ASM_FUNC_ATTR_NOINLINE ASM_FUNC_ATTR NO_INLINE
 
 
 typedef struct u128_s
@@ -47,6 +59,23 @@ typedef struct u128_s
 } __attribute__((packed, aligned(1), may_alias)) u128_t;
 
 
+/* Copy of ocb_get_l needed here as GCC is unable to inline ocb_get_l
+   because of 'pragma target'. */
+static ASM_FUNC_ATTR_INLINE const unsigned char *
+aes_ocb_get_l (gcry_cipher_hd_t c, u64 n)
+{
+  unsigned long ntz;
+
+  /* Assumes that N != 0. */
+  asm ("rep;bsfl %k[low], %k[ntz]\n\t"
+        : [ntz] "=r" (ntz)
+        : [low] "r" ((unsigned long)n)
+        : "cc");
+
+  return c->u_mode.ocb.L[ntz];
+}
+
+
 /* Two macros to be called prior and after the use of AESNI
    instructions.  There should be no external function calls between
    the use of these macros.  There purpose is to make sure that the
@@ -54,52 +83,96 @@ typedef struct u128_s
    the key or the data.  */
 #ifdef __WIN64__
 /* XMM6-XMM15 are callee-saved registers on WIN64. */
-# define aesni_prepare_2_6_variable char win64tmp[16]
+# define aesni_prepare_2_7_variable char win64tmp[16 * 2]
+# define aesni_prepare_8_15_variable char win64tmp8_15[16 * 8]
 # define aesni_prepare() do { } while (0)
-# define aesni_prepare_2_6()                                            \
+# define aesni_prepare_2_7()                                            \
    do { asm volatile ("movdqu %%xmm6, %0\n\t"                           \
-                      : "=m" (*win64tmp)                                \
+                     "movdqu %%xmm7, %1\n\t"                           \
+                      : "=m" (*win64tmp), "=m" (*(win64tmp+16))         \
+                      :                                                 \
+                      : "memory");                                      \
+   } while (0)
+# define aesni_prepare_8_15()                                           \
+   do { asm volatile ("movdqu %%xmm8,  0*16(%0)\n\t"                    \
+                      "movdqu %%xmm9,  1*16(%0)\n\t"                    \
+                      "movdqu %%xmm10, 2*16(%0)\n\t"                    \
+                      "movdqu %%xmm11, 3*16(%0)\n\t"                    \
+                      "movdqu %%xmm12, 4*16(%0)\n\t"                    \
+                      "movdqu %%xmm13, 5*16(%0)\n\t"                    \
+                      "movdqu %%xmm14, 6*16(%0)\n\t"                    \
+                      "movdqu %%xmm15, 7*16(%0)\n\t"                    \
                       :                                                 \
+                      : "r" (win64tmp8_15)                              \
                       : "memory");                                      \
    } while (0)
 # define aesni_cleanup()                                                \
    do { asm volatile ("pxor %%xmm0, %%xmm0\n\t"                         \
                       "pxor %%xmm1, %%xmm1\n" :: );                     \
    } while (0)
-# define aesni_cleanup_2_6()                                            \
+# define aesni_cleanup_2_7()                                            \
    do { asm volatile ("movdqu %0,   %%xmm6\n\t"                         \
+                     "movdqu %1,   %%xmm7\n\t"                         \
                       "pxor %%xmm2, %%xmm2\n"                           \
                       "pxor %%xmm3, %%xmm3\n"                           \
                       "pxor %%xmm4, %%xmm4\n"                           \
                       "pxor %%xmm5, %%xmm5\n"                           \
                       :                                                 \
-                      : "m" (*win64tmp)                                 \
+                      : "m" (*win64tmp), "m" (*(win64tmp+16))           \
+                      : "memory");                                      \
+   } while (0)
+# define aesni_cleanup_8_15()                                           \
+   do { asm volatile ("movdqu 0*16(%0), %%xmm8\n\t"                     \
+                      "movdqu 1*16(%0), %%xmm9\n\t"                     \
+                      "movdqu 2*16(%0), %%xmm10\n\t"                    \
+                      "movdqu 3*16(%0), %%xmm11\n\t"                    \
+                      "movdqu 4*16(%0), %%xmm12\n\t"                    \
+                      "movdqu 5*16(%0), %%xmm13\n\t"                    \
+                      "movdqu 6*16(%0), %%xmm14\n\t"                    \
+                      "movdqu 7*16(%0), %%xmm15\n\t"                    \
+                      :                                                 \
+                      : "r" (win64tmp8_15)                              \
                       : "memory");                                      \
    } while (0)
 #else
-# define aesni_prepare_2_6_variable
+# define aesni_prepare_2_7_variable
 # define aesni_prepare() do { } while (0)
-# define aesni_prepare_2_6() do { } while (0)
+# define aesni_prepare_2_7() do { } while (0)
 # define aesni_cleanup()                                                \
    do { asm volatile ("pxor %%xmm0, %%xmm0\n\t"                         \
                       "pxor %%xmm1, %%xmm1\n" :: );                     \
    } while (0)
-# define aesni_cleanup_2_6()                                            \
-   do { asm volatile ("pxor %%xmm2, %%xmm2\n\t"                         \
+# define aesni_cleanup_2_7()                                            \
+   do { asm volatile ("pxor %%xmm7, %%xmm7\n\t"                         \
+                      "pxor %%xmm2, %%xmm2\n\t"                         \
                       "pxor %%xmm3, %%xmm3\n"                           \
                       "pxor %%xmm4, %%xmm4\n"                           \
                       "pxor %%xmm5, %%xmm5\n"                           \
                       "pxor %%xmm6, %%xmm6\n":: );                      \
    } while (0)
+# ifdef __x86_64__
+#  define aesni_prepare_8_15_variable
+#  define aesni_prepare_8_15() do { } while (0)
+#  define aesni_cleanup_8_15()                                          \
+   do { asm volatile ("pxor %%xmm8, %%xmm8\n"                           \
+                      "pxor %%xmm9, %%xmm9\n"                           \
+                      "pxor %%xmm10, %%xmm10\n"                         \
+                      "pxor %%xmm11, %%xmm11\n"                         \
+                      "pxor %%xmm12, %%xmm12\n"                         \
+                      "pxor %%xmm13, %%xmm13\n"                         \
+                      "pxor %%xmm14, %%xmm14\n"                         \
+                      "pxor %%xmm15, %%xmm15\n":: );                    \
+   } while (0)
+# endif
 #endif
 
-void
+void ASM_FUNC_ATTR
 _gcry_aes_aesni_do_setkey (RIJNDAEL_context *ctx, const byte *key)
 {
-  aesni_prepare_2_6_variable;
+  aesni_prepare_2_7_variable;
 
   aesni_prepare();
-  aesni_prepare_2_6();
+  aesni_prepare_2_7();
 
   if (ctx->rounds < 12)
     {
@@ -322,13 +395,13 @@ _gcry_aes_aesni_do_setkey (RIJNDAEL_context *ctx, const byte *key)
     }
 
   aesni_cleanup();
-  aesni_cleanup_2_6();
+  aesni_cleanup_2_7();
 }
 
 
 /* Make a decryption key from an encryption key. */
-void
-_gcry_aes_aesni_prepare_decryption (RIJNDAEL_context *ctx)
+static ASM_FUNC_ATTR_INLINE void
+do_aesni_prepare_decryption (RIJNDAEL_context *ctx)
 {
   /* The AES-NI decrypt instructions use the Equivalent Inverse
      Cipher, thus we can't use the the standard decrypt key
@@ -338,8 +411,6 @@ _gcry_aes_aesni_prepare_decryption (RIJNDAEL_context *ctx)
   int rr;
   int r;
 
-  aesni_prepare();
-
 #define DO_AESNI_AESIMC() \
   asm volatile ("movdqa %[ekey], %%xmm1\n\t" \
                 /*"aesimc %%xmm1, %%xmm1\n\t"*/ \
@@ -375,14 +446,20 @@ _gcry_aes_aesni_prepare_decryption (RIJNDAEL_context *ctx)
   dkey[r] = ekey[0];
 
 #undef DO_AESNI_AESIMC
+}
 
+void ASM_FUNC_ATTR
+_gcry_aes_aesni_prepare_decryption (RIJNDAEL_context *ctx)
+{
+  aesni_prepare();
+  do_aesni_prepare_decryption (ctx);
   aesni_cleanup();
 }
 
 
 /* Encrypt one block using the Intel AES-NI instructions.  Block is input
  * and output through SSE register xmm0. */
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 do_aesni_enc (const RIJNDAEL_context *ctx)
 {
 #define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
@@ -435,7 +512,7 @@ do_aesni_enc (const RIJNDAEL_context *ctx)
 
 /* Decrypt one block using the Intel AES-NI instructions.  Block is input
  * and output through SSE register xmm0. */
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 do_aesni_dec (const RIJNDAEL_context *ctx)
 {
 #define aesdec_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t"
@@ -488,7 +565,7 @@ do_aesni_dec (const RIJNDAEL_context *ctx)
 
 /* Encrypt four blocks using the Intel AES-NI instructions.  Blocks are input
  * and output through SSE registers xmm1 to xmm4.  */
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 do_aesni_enc_vec4 (const RIJNDAEL_context *ctx)
 {
 #define aesenc_xmm0_xmm1      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc8\n\t"
@@ -597,7 +674,7 @@ do_aesni_enc_vec4 (const RIJNDAEL_context *ctx)
 
 /* Decrypt four blocks using the Intel AES-NI instructions.  Blocks are input
  * and output through SSE registers xmm1 to xmm4.  */
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 do_aesni_dec_vec4 (const RIJNDAEL_context *ctx)
 {
 #define aesdec_xmm0_xmm1 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc8\n\t"
@@ -704,10 +781,284 @@ do_aesni_dec_vec4 (const RIJNDAEL_context *ctx)
 }
 
 
+#ifdef __x86_64__
+
+/* Encrypt eight blocks using the Intel AES-NI instructions.  Blocks are input
+ * and output through SSE registers xmm1 to xmm4 and xmm8 to xmm11.  */
+static ASM_FUNC_ATTR_INLINE void
+do_aesni_enc_vec8 (const RIJNDAEL_context *ctx)
+{
+  asm volatile ("movdqa 0x10(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0x20(%[key]), %%xmm0\n\t"
+                "cmpl $12, %[rounds]\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0x30(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0x40(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0x50(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0x60(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0x70(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0x80(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0x90(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0xa0(%[key]), %%xmm0\n\t"
+                "jb .Ldeclast%=\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0xb0(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0xc0(%[key]), %%xmm0\n\t"
+                "je .Ldeclast%=\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0xd0(%[key]), %%xmm0\n\t"
+                "aesenc %%xmm0, %%xmm1\n\t"
+                "aesenc %%xmm0, %%xmm2\n\t"
+                "aesenc %%xmm0, %%xmm3\n\t"
+                "aesenc %%xmm0, %%xmm4\n\t"
+                "aesenc %%xmm0, %%xmm8\n\t"
+                "aesenc %%xmm0, %%xmm9\n\t"
+                "aesenc %%xmm0, %%xmm10\n\t"
+                "aesenc %%xmm0, %%xmm11\n\t"
+                "movdqa 0xe0(%[key]), %%xmm0\n"
+
+                ".Ldeclast%=:\n\t"
+                : /* no output */
+                : [key] "r" (ctx->keyschenc),
+                  [rounds] "r" (ctx->rounds)
+                : "cc", "memory");
+}
+
+
+/* Decrypt eight blocks using the Intel AES-NI instructions.  Blocks are input
+ * and output through SSE registers xmm1 to xmm4 and xmm8 to xmm11.  */
+static ASM_FUNC_ATTR_INLINE void
+do_aesni_dec_vec8 (const RIJNDAEL_context *ctx)
+{
+  asm volatile ("movdqa 0x10(%[key]), %%xmm0\n\t"
+                "cmpl $12, %[rounds]\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0x20(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0x30(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0x40(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0x50(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0x60(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0x70(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0x80(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0x90(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0xa0(%[key]), %%xmm0\n\t"
+                "jb .Ldeclast%=\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0xb0(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0xc0(%[key]), %%xmm0\n\t"
+                "je .Ldeclast%=\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0xd0(%[key]), %%xmm0\n\t"
+                "aesdec %%xmm0, %%xmm1\n\t"
+                "aesdec %%xmm0, %%xmm2\n\t"
+                "aesdec %%xmm0, %%xmm3\n\t"
+                "aesdec %%xmm0, %%xmm4\n\t"
+                "aesdec %%xmm0, %%xmm8\n\t"
+                "aesdec %%xmm0, %%xmm9\n\t"
+                "aesdec %%xmm0, %%xmm10\n\t"
+                "aesdec %%xmm0, %%xmm11\n\t"
+                "movdqa 0xe0(%[key]), %%xmm0\n"
+
+                ".Ldeclast%=:\n\t"
+                : /* no output */
+                : [key] "r" (ctx->keyschdec),
+                  [rounds] "r" (ctx->rounds)
+                : "cc", "memory");
+}
+
+#endif /* __x86_64__ */
+
+
 /* Perform a CTR encryption round using the counter CTR and the input
    block A.  Write the result to the output block B and update CTR.
    CTR needs to be a 16 byte aligned little-endian value.  */
-static void
+static ASM_FUNC_ATTR_INLINE void
 do_aesni_ctr (const RIJNDAEL_context *ctx,
               unsigned char *ctr, unsigned char *b, const unsigned char *a)
 {
@@ -786,7 +1137,7 @@ do_aesni_ctr (const RIJNDAEL_context *ctx,
 
 
 /* Four blocks at a time variant of do_aesni_ctr.  */
-static void
+static ASM_FUNC_ATTR_INLINE void
 do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
                 unsigned char *ctr, unsigned char *b, const unsigned char *a)
 {
@@ -808,7 +1159,7 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
 #define aesenclast_xmm1_xmm4  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t"
 
   /* Register usage:
-      esi   keyschedule
+      [key] keyschedule
       xmm0  CTR-0
       xmm1  temp / round key
       xmm2  CTR-1
@@ -819,8 +1170,8 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
    */
 
   asm volatile (/* detect if 8-bit carry handling is needed */
-                "cmpb   $0xfb, 15(%[ctr])\n\t"
-                "ja     .Ladd32bit%=\n\t"
+                "addb   $4, 15(%[ctr])\n\t"
+                "jc     .Ladd32bit%=\n\t"
 
                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5) */
                 "movdqa 0*16(%[addb]), %%xmm2\n\t"  /* xmm2 := be(1) */
@@ -832,9 +1183,10 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
                 "paddb  %%xmm0, %%xmm4\n\t"     /* xmm4 := be(3) + CTR (xmm0) */
                 "paddb  %%xmm0, %%xmm5\n\t"     /* xmm5 := be(4) + CTR (xmm0) */
                 "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0] */
-                "jmp    .Lstore_ctr%=\n\t"
+                "jmp    .Ldone_ctr%=\n\t"
 
                 ".Ladd32bit%=:\n\t"
+                "movdqa %%xmm5, (%[ctr])\n\t"   /* Restore CTR.  */
                 "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0, xmm2 := CTR (xmm5) */
                 "movdqa %%xmm0, %%xmm2\n\t"
                 "pcmpeqd %%xmm1, %%xmm1\n\t"
@@ -880,8 +1232,9 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
                 "pshufb %%xmm6, %%xmm4\n\t"     /* xmm4 := be(xmm4) */
                 "pshufb %%xmm6, %%xmm5\n\t"     /* xmm5 := be(xmm5) */
 
-                ".Lstore_ctr%=:\n\t"
                 "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).  */
+
+                ".Ldone_ctr%=:\n\t"
                 :
                 : [ctr] "r" (ctr),
                   [key] "r" (ctx->keyschenc),
@@ -1003,7 +1356,350 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx,
 }
 
 
-unsigned int
+#ifdef __x86_64__
+
+/* Eight blocks at a time variant of do_aesni_ctr.  */
+static ASM_FUNC_ATTR_INLINE void
+do_aesni_ctr_8 (const RIJNDAEL_context *ctx,
+                unsigned char *ctr, unsigned char *b, const unsigned char *a)
+{
+  static const byte bige_addb_const[8][16] __attribute__ ((aligned (16))) =
+    {
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 },
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 },
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 },
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 },
+      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 }
+    };
+  const void *bige_addb = bige_addb_const;
+
+  /* Register usage:
+      [key] keyschedule
+      xmm0  CTR-0
+      xmm1  temp / round key
+      xmm2  CTR-1
+      xmm3  CTR-2
+      xmm4  CTR-3
+      xmm5  copy of *ctr
+      xmm6  endian swapping mask
+      xmm8  CTR-4
+      xmm9  CTR-5
+      xmm10 CTR-6
+      xmm11 CTR-7
+      xmm12 temp
+      xmm13 temp
+      xmm14 temp
+      xmm15 temp
+   */
+
+  asm volatile (/* detect if 8-bit carry handling is needed */
+                "addb   $8, 15(%[ctr])\n\t"
+                "jc     .Ladd32bit%=\n\t"
+
+                "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0] */
+                "movdqa 16(%[key]), %%xmm7\n\t" /* xmm7 := key[1] */
+
+                "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0 := CTR (xmm5) */
+                "movdqa %%xmm5, %%xmm2\n\t"     /* xmm2 := CTR (xmm5) */
+                "movdqa %%xmm5, %%xmm3\n\t"     /* xmm3 := CTR (xmm5) */
+                "movdqa %%xmm5, %%xmm4\n\t"     /* xmm4 := CTR (xmm5) */
+                "paddb  0*16(%[addb]), %%xmm2\n\t" /* xmm2 := be(1) + CTR */
+                "paddb  1*16(%[addb]), %%xmm3\n\t" /* xmm3 := be(2) + CTR */
+                "paddb  2*16(%[addb]), %%xmm4\n\t" /* xmm4 := be(3) + CTR */
+                "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm2\n\t"     /* xmm2 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm3\n\t"     /* xmm3 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm4\n\t"     /* xmm4 ^= key[0]    */
+                "aesenc %%xmm7, %%xmm0\n\t"
+                "aesenc %%xmm7, %%xmm2\n\t"
+                "aesenc %%xmm7, %%xmm3\n\t"
+                "aesenc %%xmm7, %%xmm4\n\t"
+                "movdqa %%xmm5, %%xmm8\n\t"     /* xmm8 := CTR (xmm5) */
+                "movdqa %%xmm5, %%xmm9\n\t"     /* xmm9 := CTR (xmm5) */
+                "movdqa %%xmm5, %%xmm10\n\t"    /* xmm10 := CTR (xmm5) */
+                "movdqa %%xmm5, %%xmm11\n\t"    /* xmm11 := CTR (xmm5) */
+                "paddb  3*16(%[addb]), %%xmm8\n\t"  /* xmm8 := be(4) + CTR */
+                "paddb  4*16(%[addb]), %%xmm9\n\t"  /* xmm9 := be(5) + CTR */
+                "paddb  5*16(%[addb]), %%xmm10\n\t" /* xmm10 := be(6) + CTR */
+                "paddb  6*16(%[addb]), %%xmm11\n\t" /* xmm11 := be(7) + CTR */
+                "pxor   %%xmm1, %%xmm8\n\t"     /* xmm8 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm9\n\t"     /* xmm9 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm10\n\t"    /* xmm10 ^= key[0]   */
+                "pxor   %%xmm1, %%xmm11\n\t"    /* xmm11 ^= key[0]   */
+                "aesenc %%xmm7, %%xmm8\n\t"
+                "aesenc %%xmm7, %%xmm9\n\t"
+                "aesenc %%xmm7, %%xmm10\n\t"
+                "aesenc %%xmm7, %%xmm11\n\t"
+
+                "paddb  7*16(%[addb]), %%xmm5\n\t" /* xmm5 := be(8) + CTR */
+
+                "jmp    .Ldone_ctr%=\n\t"
+
+                ".Ladd32bit%=:\n\t"
+                "movdqa %%xmm5, (%[ctr])\n\t"   /* Restore CTR. */
+                "movdqa %%xmm5, %%xmm0\n\t"     /* xmm0, xmm2 := CTR (xmm5) */
+                "movdqa %%xmm0, %%xmm2\n\t"
+                "pcmpeqd %%xmm1, %%xmm1\n\t"
+                "psrldq $8, %%xmm1\n\t"         /* xmm1 = -1 */
+
+                "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := le(xmm2) */
+                "psubq  %%xmm1, %%xmm2\n\t"     /* xmm2++           */
+                "movdqa %%xmm2, %%xmm3\n\t"     /* xmm3 := xmm2     */
+                "psubq  %%xmm1, %%xmm3\n\t"     /* xmm3++           */
+                "movdqa %%xmm3, %%xmm4\n\t"     /* xmm4 := xmm3     */
+                "psubq  %%xmm1, %%xmm4\n\t"     /* xmm4++           */
+                "movdqa %%xmm4, %%xmm8\n\t"     /* xmm8 := xmm4     */
+                "psubq  %%xmm1, %%xmm8\n\t"     /* xmm8++           */
+                "movdqa %%xmm8, %%xmm9\n\t"     /* xmm9 := xmm8     */
+                "psubq  %%xmm1, %%xmm9\n\t"     /* xmm9++           */
+                "movdqa %%xmm9, %%xmm10\n\t"    /* xmm10 := xmm9    */
+                "psubq  %%xmm1, %%xmm10\n\t"    /* xmm10++          */
+                "movdqa %%xmm10, %%xmm11\n\t"   /* xmm11 := xmm10   */
+                "psubq  %%xmm1, %%xmm11\n\t"    /* xmm11++          */
+                "movdqa %%xmm11, %%xmm5\n\t"    /* xmm5 := xmm11    */
+                "psubq  %%xmm1, %%xmm5\n\t"     /* xmm5++           */
+
+                /* detect if 64-bit carry handling is needed */
+                "cmpl   $0xffffffff, 8(%[ctr])\n\t"
+                "jne    .Lno_carry%=\n\t"
+                "movl   12(%[ctr]), %%esi\n\t"
+                "bswapl %%esi\n\t"
+                "cmpl   $0xfffffff8, %%esi\n\t"
+                "jb     .Lno_carry%=\n\t"       /* no carry */
+
+                "pslldq $8, %%xmm1\n\t"         /* move lower 64-bit to high */
+                "je     .Lcarry_xmm5%=\n\t"     /* esi == 0xfffffff8 */
+                "cmpl   $0xfffffffa, %%esi\n\t"
+                "jb     .Lcarry_xmm11%=\n\t"     /* esi == 0xfffffff9 */
+                "je     .Lcarry_xmm10%=\n\t"     /* esi == 0xfffffffa */
+                "cmpl   $0xfffffffc, %%esi\n\t"
+                "jb     .Lcarry_xmm9%=\n\t"     /* esi == 0xfffffffb */
+                "je     .Lcarry_xmm8%=\n\t"     /* esi == 0xfffffffc */
+                "cmpl   $0xfffffffe, %%esi\n\t"
+                "jb     .Lcarry_xmm4%=\n\t"     /* esi == 0xfffffffd */
+                "je     .Lcarry_xmm3%=\n\t"     /* esi == 0xfffffffe */
+                /* esi == 0xffffffff */
+
+                "psubq   %%xmm1, %%xmm2\n\t"
+                ".Lcarry_xmm3%=:\n\t"
+                "psubq   %%xmm1, %%xmm3\n\t"
+                ".Lcarry_xmm4%=:\n\t"
+                "psubq   %%xmm1, %%xmm4\n\t"
+                ".Lcarry_xmm8%=:\n\t"
+                "psubq   %%xmm1, %%xmm8\n\t"
+                ".Lcarry_xmm9%=:\n\t"
+                "psubq   %%xmm1, %%xmm9\n\t"
+                ".Lcarry_xmm10%=:\n\t"
+                "psubq   %%xmm1, %%xmm10\n\t"
+                ".Lcarry_xmm11%=:\n\t"
+                "psubq   %%xmm1, %%xmm11\n\t"
+                ".Lcarry_xmm5%=:\n\t"
+                "psubq   %%xmm1, %%xmm5\n\t"
+
+                ".Lno_carry%=:\n\t"
+                "movdqa (%[key]), %%xmm1\n\t"   /* xmm1 := key[0] */
+                "movdqa 16(%[key]), %%xmm7\n\t" /* xmm7 := key[1] */
+
+                "pshufb %%xmm6, %%xmm2\n\t"     /* xmm2 := be(xmm2) */
+                "pshufb %%xmm6, %%xmm3\n\t"     /* xmm3 := be(xmm3) */
+                "pshufb %%xmm6, %%xmm4\n\t"     /* xmm4 := be(xmm4) */
+                "pxor   %%xmm1, %%xmm0\n\t"     /* xmm0 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm2\n\t"     /* xmm2 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm3\n\t"     /* xmm3 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm4\n\t"     /* xmm4 ^= key[0]    */
+                "aesenc %%xmm7, %%xmm0\n\t"
+                "aesenc %%xmm7, %%xmm2\n\t"
+                "aesenc %%xmm7, %%xmm3\n\t"
+                "aesenc %%xmm7, %%xmm4\n\t"
+                "pshufb %%xmm6, %%xmm8\n\t"     /* xmm8 := be(xmm8) */
+                "pshufb %%xmm6, %%xmm9\n\t"     /* xmm9 := be(xmm9) */
+                "pshufb %%xmm6, %%xmm10\n\t"    /* xmm10 := be(xmm10) */
+                "pshufb %%xmm6, %%xmm11\n\t"    /* xmm11 := be(xmm11) */
+                "pxor   %%xmm1, %%xmm8\n\t"     /* xmm8 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm9\n\t"     /* xmm9 ^= key[0]    */
+                "pxor   %%xmm1, %%xmm10\n\t"    /* xmm10 ^= key[0]   */
+                "pxor   %%xmm1, %%xmm11\n\t"    /* xmm11 ^= key[0]   */
+                "aesenc %%xmm7, %%xmm8\n\t"
+                "aesenc %%xmm7, %%xmm9\n\t"
+                "aesenc %%xmm7, %%xmm10\n\t"
+                "aesenc %%xmm7, %%xmm11\n\t"
+
+                "pshufb %%xmm6, %%xmm5\n\t"     /* xmm5 := be(xmm5) */
+                "movdqa %%xmm5, (%[ctr])\n\t"   /* Update CTR (mem).  */
+
+                ".align 16\n\t"
+                ".Ldone_ctr%=:\n\t"
+                :
+                : [ctr] "r" (ctr),
+                  [key] "r" (ctx->keyschenc),
+                  [addb] "r" (bige_addb)
+                : "%esi", "cc", "memory");
+
+  asm volatile ("movdqa 0x20(%[key]), %%xmm1\n\t"
+                "movdqu 0*16(%[src]), %%xmm12\n\t" /* Get block 1.      */
+                "movdqu 1*16(%[src]), %%xmm13\n\t" /* Get block 2.      */
+                "movdqu 2*16(%[src]), %%xmm14\n\t" /* Get block 3.      */
+                "movdqu 3*16(%[src]), %%xmm15\n\t" /* Get block 4.      */
+                "movdqu 4*16(%[src]), %%xmm7\n\t"  /* Get block 5.      */
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "cmpl $12, %[rounds]\n\t"
+                "movdqa 0x30(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0x40(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0x50(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0x60(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0x70(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0x80(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0x90(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0xa0(%[key]), %%xmm1\n\t"
+                "jb .Lenclast%=\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0xb0(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0xc0(%[key]), %%xmm1\n\t"
+                "je .Lenclast%=\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0xd0(%[key]), %%xmm1\n\t"
+                "aesenc %%xmm1, %%xmm0\n\t"
+                "aesenc %%xmm1, %%xmm2\n\t"
+                "aesenc %%xmm1, %%xmm3\n\t"
+                "aesenc %%xmm1, %%xmm4\n\t"
+                "aesenc %%xmm1, %%xmm8\n\t"
+                "aesenc %%xmm1, %%xmm9\n\t"
+                "aesenc %%xmm1, %%xmm10\n\t"
+                "aesenc %%xmm1, %%xmm11\n\t"
+                "movdqa 0xe0(%[key]), %%xmm1\n"
+
+                ".Lenclast%=:\n\t"
+                :
+                : [key] "r" (ctx->keyschenc),
+                  [rounds] "r" (ctx->rounds),
+                  [src] "r" (a)
+                : "cc", "memory");
+
+  asm volatile ("pxor %%xmm1, %%xmm12\n\t"         /* block1 ^= lastkey */
+                "pxor %%xmm1, %%xmm13\n\t"         /* block2 ^= lastkey */
+                "pxor %%xmm1, %%xmm14\n\t"         /* block3 ^= lastkey */
+                "pxor %%xmm1, %%xmm15\n\t"         /* block4 ^= lastkey */
+                "aesenclast %%xmm12, %%xmm0\n\t"
+                "aesenclast %%xmm13, %%xmm2\n\t"
+                "aesenclast %%xmm14, %%xmm3\n\t"
+                "aesenclast %%xmm15, %%xmm4\n\t"
+                "movdqu 5*16(%[src]), %%xmm12\n\t" /* Get block 6.      */
+                "movdqu 6*16(%[src]), %%xmm13\n\t" /* Get block 7.      */
+                "movdqu 7*16(%[src]), %%xmm14\n\t" /* Get block 8.      */
+                "movdqu %%xmm0, 0*16(%[dst])\n\t"  /* Store block 1.    */
+                "movdqu %%xmm2, 1*16(%[dst])\n\t"  /* Store block 2.    */
+                "movdqu %%xmm3, 2*16(%[dst])\n\t"  /* Store block 3.    */
+                "movdqu %%xmm4, 3*16(%[dst])\n\t"  /* Store block 4.    */
+                "pxor %%xmm1, %%xmm7\n\t"          /* block5 ^= lastkey */
+                "pxor %%xmm1, %%xmm12\n\t"         /* block6 ^= lastkey */
+                "pxor %%xmm1, %%xmm13\n\t"         /* block7 ^= lastkey */
+                "pxor %%xmm1, %%xmm14\n\t"         /* block8 ^= lastkey */
+                "aesenclast %%xmm7, %%xmm8\n\t"
+                "aesenclast %%xmm12, %%xmm9\n\t"
+                "aesenclast %%xmm13, %%xmm10\n\t"
+                "aesenclast %%xmm14, %%xmm11\n\t"
+                "movdqu %%xmm8, 4*16(%[dst])\n\t"  /* Store block 8.    */
+                "movdqu %%xmm9, 5*16(%[dst])\n\t"  /* Store block 9.    */
+                "movdqu %%xmm10, 6*16(%[dst])\n\t" /* Store block 10.   */
+                "movdqu %%xmm11, 7*16(%[dst])\n\t" /* Store block 11.   */
+                :
+                : [src] "r" (a),
+                  [dst] "r" (b)
+                : "memory");
+}
+
+#endif /* __x86_64__ */
+
+
+unsigned int ASM_FUNC_ATTR
 _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
                          const unsigned char *src)
 {
@@ -1022,99 +1718,228 @@ _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
 }
 
 
-void
-_gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                         const unsigned char *inbuf, unsigned char *iv,
+void ASM_FUNC_ATTR
+_gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx, unsigned char *iv,
+                         unsigned char *outbuf, const unsigned char *inbuf,
                          size_t nblocks)
 {
+  unsigned int rounds = ctx->rounds;
+  aesni_prepare_2_7_variable;
+
   aesni_prepare ();
+  aesni_prepare_2_7();
 
   asm volatile ("movdqu %[iv], %%xmm0\n\t"
-                : /* No output */
-                : [iv] "m" (*iv)
-                : "memory" );
+               : /* No output */
+               : [iv] "m" (*iv)
+               : "memory" );
+
+  asm volatile ("movdqa %[key0], %%xmm2\n\t"     /* xmm2 = key[0] */
+               "movdqa %[keylast], %%xmm4\n\t"  /* xmm4 = key[last] */
+               "movdqa %%xmm0, %%xmm3\n"
+               "pxor %%xmm2, %%xmm4\n\t"        /* xmm4 = key[0] ^ key[last] */
+               "pxor %%xmm2, %%xmm0\n\t"        /* xmm0 = IV ^ key[0] */
+               : /* No output */
+               : [key0] "m" (ctx->keyschenc[0][0][0]),
+                 [keylast] "m" (ctx->keyschenc[rounds][0][0])
+               : "memory" );
 
   for ( ;nblocks; nblocks-- )
     {
-      do_aesni_enc (ctx);
+      asm volatile ("movdqu %[inbuf], %%xmm5\n\t"
+                   "movdqa %%xmm2, %%xmm3\n\t"
+                   "pxor %%xmm4, %%xmm5\n\t"  /* xmm5 = input ^ key[last] ^ key[0] */
+                   :
+                   : [inbuf] "m" (*inbuf)
+                   : "memory" );
 
-      asm volatile ("movdqu %[inbuf], %%xmm1\n\t"
-                    "pxor %%xmm1, %%xmm0\n\t"
-                    "movdqu %%xmm0, %[outbuf]\n\t"
-                    : [outbuf] "=m" (*outbuf)
-                    : [inbuf] "m" (*inbuf)
-                    : "memory" );
+#define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
+#define aesenclast_xmm1_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t"
+#define aesenclast_xmm5_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc5\n\t"
+      asm volatile ("movdqa 0x10(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x20(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x30(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x40(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x50(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x60(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x70(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x80(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x90(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "cmpl $10, %[rounds]\n\t"
+                   "jz .Lenclast%=\n\t"
+                   "movdqa 0xa0(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0xb0(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "cmpl $12, %[rounds]\n\t"
+                   "jz .Lenclast%=\n\t"
+                   "movdqa 0xc0(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0xd0(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+
+                   ".Lenclast%=:\n\t"
+                   aesenclast_xmm5_xmm0
+                   :
+                   : [key] "r" (ctx->keyschenc),
+                     [rounds] "r" (rounds)
+                   : "cc", "memory");
+#undef aesenc_xmm1_xmm0
+#undef aesenclast_xmm1_xmm0
+#undef aesenclast_xmm5_xmm0
+
+      asm volatile ("pxor %%xmm0, %%xmm3\n\t"
+                   "movdqu %%xmm3, %[outbuf]\n\t"
+                   : [outbuf] "=m" (*outbuf)
+                   : [inbuf] "m" (*inbuf)
+                   : "memory" );
 
       outbuf += BLOCKSIZE;
       inbuf  += BLOCKSIZE;
     }
 
-  asm volatile ("movdqu %%xmm0, %[iv]\n\t"
-                : [iv] "=m" (*iv)
-                :
-                : "memory" );
+  asm volatile ("movdqu %%xmm3, %[iv]\n\t"
+               : [iv] "=m" (*iv)
+               :
+               : "memory" );
 
   aesni_cleanup ();
+  aesni_cleanup_2_7 ();
 }
 
 
-void
-_gcry_aes_aesni_cbc_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                         const unsigned char *inbuf, unsigned char *iv,
+void ASM_FUNC_ATTR
+_gcry_aes_aesni_cbc_enc (RIJNDAEL_context *ctx, unsigned char *iv,
+                         unsigned char *outbuf, const unsigned char *inbuf,
                          size_t nblocks, int cbc_mac)
 {
-  aesni_prepare_2_6_variable;
+  unsigned int rounds = ctx->rounds;
+  aesni_prepare_2_7_variable;
 
-  aesni_prepare ();
-  aesni_prepare_2_6();
+  if (nblocks == 0) /* CMAC may call with nblocks 0. */
+    return;
 
-  asm volatile ("movdqu %[iv], %%xmm5\n\t"
-                : /* No output */
-                : [iv] "m" (*iv)
-                : "memory" );
+  aesni_prepare ();
+  aesni_prepare_2_7();
 
-  for ( ;nblocks; nblocks-- )
+  asm volatile ("movdqu %[iv], %%xmm0\n\t"
+               : /* No output */
+               : [iv] "m" (*iv)
+               : "memory" );
+
+  asm volatile ("movdqa %[key0], %%xmm2\n\t"     /* xmm2 = key[0] */
+               "movdqa %[keylast], %%xmm3\n\t"  /* xmm3 = key[last] */
+               "pxor %%xmm2, %%xmm0\n\t"        /* xmm0 = IV ^ key[0] */
+               "pxor %%xmm3, %%xmm2\n\t"        /* xmm2 = key[0] ^ key[last] */
+               : /* No output */
+               : [key0] "m" (ctx->keyschenc[0][0][0]),
+                 [keylast] "m" (ctx->keyschenc[rounds][0][0])
+               : "memory" );
+
+  asm volatile ("movdqu %[inbuf], %%xmm4\n\t"
+               "pxor %%xmm4, %%xmm0\n\t"  /* xmm0 = IV ^ key[0] ^ input */
+               :
+               : [inbuf] "m" (*inbuf)
+               : "memory" );
+  inbuf += BLOCKSIZE;
+
+  for ( ;nblocks; )
     {
-      asm volatile ("movdqu %[inbuf], %%xmm0\n\t"
-                    "pxor %%xmm5, %%xmm0\n\t"
-                    : /* No output */
-                    : [inbuf] "m" (*inbuf)
-                    : "memory" );
+      if (--nblocks)
+       {
+         asm volatile ("movdqu %[inbuf], %%xmm4\n\t"
+                       /* xmm4 = IV ^ key[0] ^ key[last] ^ input: */
+                       "pxor %%xmm2, %%xmm4\n\t"
+                       :
+                       : [inbuf] "m" (*inbuf)
+                       : "memory" );
+         inbuf += BLOCKSIZE;
+       }
 
-      do_aesni_enc (ctx);
+#define aesenc_xmm1_xmm0      ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t"
+#define aesenclast_xmm4_xmm0  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc4\n\t"
+#define aesenclast_xmm3_xmm5  ".byte 0x66, 0x0f, 0x38, 0xdd, 0xeb\n\t"
+      asm volatile ("movdqa 0x10(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x20(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x30(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x40(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x50(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x60(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x70(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x80(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0x90(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "cmpl $10, %[rounds]\n\t"
+                   "jz .Lenclast%=\n\t"
+                   "movdqa 0xa0(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0xb0(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "cmpl $12, %[rounds]\n\t"
+                   "jz .Lenclast%=\n\t"
+                   "movdqa 0xc0(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+                   "movdqa 0xd0(%[key]), %%xmm1\n\t"
+                   aesenc_xmm1_xmm0
+
+                   ".Lenclast%=:\n\t"
+                   "movdqa %%xmm0, %%xmm5\n"
+                   aesenclast_xmm4_xmm0  /* xmm0 = IV ^ key[0] */
+                   aesenclast_xmm3_xmm5  /* xmm5 = IV */
+                   :
+                   : [key] "r" (ctx->keyschenc),
+                     [rounds] "r" (rounds)
+                   : "cc", "memory");
+#undef aesenc_xmm1_xmm0
+#undef aesenclast_xmm4_xmm0
+#undef aesenclast_xmm3_xmm5
 
-      asm volatile ("movdqa %%xmm0, %%xmm5\n\t"
-                    "movdqu %%xmm0, %[outbuf]\n\t"
-                    : [outbuf] "=m" (*outbuf)
-                    :
-                    : "memory" );
+      asm volatile ("movdqu %%xmm5, %[outbuf]\n\t"
+                   : [outbuf] "=m" (*outbuf)
+                   :
+                   : "memory" );
 
-      inbuf += BLOCKSIZE;
-      if (!cbc_mac)
-        outbuf += BLOCKSIZE;
+      outbuf += -(!cbc_mac) & BLOCKSIZE;
     }
 
   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
-                : [iv] "=m" (*iv)
-                :
-                : "memory" );
+               : [iv] "=m" (*iv)
+               :
+               : "memory" );
 
   aesni_cleanup ();
-  aesni_cleanup_2_6 ();
+  aesni_cleanup_2_7 ();
 }
 
 
-void
-_gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                         const unsigned char *inbuf, unsigned char *ctr,
+void ASM_FUNC_ATTR
+_gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *ctr,
+                         unsigned char *outbuf, const unsigned char *inbuf,
                          size_t nblocks)
 {
   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
-  aesni_prepare_2_6_variable;
+  aesni_prepare_2_7_variable;
 
   aesni_prepare ();
-  aesni_prepare_2_6();
+  aesni_prepare_2_7();
 
   asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */
                 "movdqa %[ctr], %%xmm5\n\t"  /* Preload CTR */
@@ -1123,7 +1948,25 @@ _gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
                   [ctr] "m" (*ctr)
                 : "memory");
 
-  for ( ;nblocks > 3 ; nblocks -= 4 )
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      aesni_prepare_8_15_variable;
+
+      aesni_prepare_8_15();
+
+      for ( ;nblocks >= 8 ; nblocks -= 8 )
+       {
+         do_aesni_ctr_8 (ctx, ctr, outbuf, inbuf);
+         outbuf += 8*BLOCKSIZE;
+         inbuf  += 8*BLOCKSIZE;
+       }
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
+  for ( ;nblocks >= 4 ; nblocks -= 4 )
     {
       do_aesni_ctr_4 (ctx, ctr, outbuf, inbuf);
       outbuf += 4*BLOCKSIZE;
@@ -1136,38 +1979,230 @@ _gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
       inbuf  += BLOCKSIZE;
     }
   aesni_cleanup ();
-  aesni_cleanup_2_6 ();
+  aesni_cleanup_2_7 ();
 }
 
 
-unsigned int
-_gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
-                         const unsigned char *src)
+void ASM_FUNC_ATTR
+_gcry_aes_aesni_ctr32le_enc (RIJNDAEL_context *ctx, unsigned char *ctr,
+                            unsigned char *outbuf, const unsigned char *inbuf,
+                            size_t nblocks)
 {
+  static const byte le_addd_const[8][16] __attribute__ ((aligned (16))) =
+    {
+      { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+      { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+      { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+      { 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+      { 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+      { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+      { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+      { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+    };
+  aesni_prepare_2_7_variable;
+
   aesni_prepare ();
-  asm volatile ("movdqu %[src], %%xmm0\n\t"
-                :
-                : [src] "m" (*src)
-                : "memory" );
-  do_aesni_dec (ctx);
-  asm volatile ("movdqu %%xmm0, %[dst]\n\t"
-                : [dst] "=m" (*dst)
-                :
-                : "memory" );
-  aesni_cleanup ();
-  return 0;
-}
+  aesni_prepare_2_7();
 
+  asm volatile ("movdqa %[ctr], %%xmm5\n\t"  /* Preload CTR */
+               : /* No output */
+               : [ctr] "m" (*ctr)
+               : "memory");
 
-void
-_gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                         const unsigned char *inbuf, unsigned char *iv,
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      aesni_prepare_8_15_variable;
+
+      aesni_prepare_8_15();
+
+      for ( ;nblocks >= 8 ; nblocks -= 8 )
+       {
+         asm volatile
+           ("movdqa (%[key]), %%xmm0\n\t"
+
+            "movdqa %%xmm5,         %%xmm1\n\t" /* load input blocks */
+            "movdqa %%xmm5,         %%xmm2\n\t"
+            "movdqa %%xmm5,         %%xmm3\n\t"
+            "movdqa %%xmm5,         %%xmm4\n\t"
+            "movdqa %%xmm5,         %%xmm8\n\t"
+            "movdqa %%xmm5,         %%xmm9\n\t"
+            "movdqa %%xmm5,         %%xmm10\n\t"
+            "movdqa %%xmm5,         %%xmm11\n\t"
+
+            "paddd 0*16(%[addd]),   %%xmm2\n\t"
+            "paddd 1*16(%[addd]),   %%xmm3\n\t"
+            "paddd 2*16(%[addd]),   %%xmm4\n\t"
+            "paddd 3*16(%[addd]),   %%xmm8\n\t"
+            "paddd 4*16(%[addd]),   %%xmm9\n\t"
+            "paddd 5*16(%[addd]),   %%xmm10\n\t"
+            "paddd 6*16(%[addd]),   %%xmm11\n\t"
+
+            "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
+            "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
+            "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
+            "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
+            "pxor   %%xmm0, %%xmm8\n\t"     /* xmm8 ^= key[0] */
+            "pxor   %%xmm0, %%xmm9\n\t"     /* xmm9 ^= key[0] */
+            "pxor   %%xmm0, %%xmm10\n\t"    /* xmm10 ^= key[0] */
+            "pxor   %%xmm0, %%xmm11\n\t"    /* xmm11 ^= key[0] */
+
+            "movdqu 0*16(%[inbuf]), %%xmm6\n\t"
+            "movdqu 1*16(%[inbuf]), %%xmm7\n\t"
+            "movdqu 2*16(%[inbuf]), %%xmm12\n\t"
+            "movdqu 3*16(%[inbuf]), %%xmm13\n\t"
+            "movdqu 4*16(%[inbuf]), %%xmm14\n\t"
+            "movdqu 5*16(%[inbuf]), %%xmm15\n\t"
+
+            "paddd 7*16(%[addd]),   %%xmm5\n\t"
+            : /* No output */
+            : [addd] "r" (&le_addd_const[0][0]),
+              [inbuf] "r" (inbuf),
+              [key] "r" (ctx->keyschenc)
+            : "memory");
+
+         do_aesni_enc_vec8 (ctx);
+
+         asm volatile
+           ("pxor %%xmm0, %%xmm6\n\t"
+            "pxor %%xmm0, %%xmm7\n\t"
+            "pxor %%xmm0, %%xmm12\n\t"
+            "pxor %%xmm0, %%xmm13\n\t"
+            "pxor %%xmm0, %%xmm14\n\t"
+            "pxor %%xmm0, %%xmm15\n\t"
+            "aesenclast %%xmm6, %%xmm1\n\t"
+            "aesenclast %%xmm7, %%xmm2\n\t"
+            "movdqu 6*16(%[inbuf]), %%xmm6\n\t"
+            "movdqu 7*16(%[inbuf]), %%xmm7\n\t"
+            "aesenclast %%xmm12, %%xmm3\n\t"
+            "aesenclast %%xmm13, %%xmm4\n\t"
+            "pxor %%xmm0, %%xmm6\n\t"
+            "pxor %%xmm0, %%xmm7\n\t"
+            "aesenclast %%xmm14, %%xmm8\n\t"
+            "aesenclast %%xmm15, %%xmm9\n\t"
+            "aesenclast %%xmm6, %%xmm10\n\t"
+            "aesenclast %%xmm7, %%xmm11\n\t"
+            "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
+            "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
+            "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
+            "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
+            "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
+            "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
+            "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
+            "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
+            : /* No output */
+            : [inbuf] "r" (inbuf),
+              [outbuf] "r" (outbuf)
+            : "memory");
+
+         outbuf += 8*BLOCKSIZE;
+         inbuf  += 8*BLOCKSIZE;
+       }
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
+  for ( ;nblocks >= 4 ; nblocks -= 4 )
+    {
+      asm volatile
+       ("movdqa %%xmm5,         %%xmm1\n\t" /* load input blocks */
+        "movdqa %%xmm5,         %%xmm2\n\t"
+        "movdqa %%xmm5,         %%xmm3\n\t"
+        "movdqa %%xmm5,         %%xmm4\n\t"
+        "paddd 0*16(%[addd]),   %%xmm2\n\t"
+        "paddd 1*16(%[addd]),   %%xmm3\n\t"
+        "paddd 2*16(%[addd]),   %%xmm4\n\t"
+        "paddd 3*16(%[addd]),   %%xmm5\n\t"
+        "movdqu 0*16(%[inbuf]), %%xmm6\n\t"
+        "movdqu 1*16(%[inbuf]), %%xmm7\n\t"
+        : /* No output */
+        : [addd] "r" (&le_addd_const[0][0]),
+          [inbuf] "r" (inbuf)
+        : "memory");
+
+      do_aesni_enc_vec4 (ctx);
+
+      asm volatile
+       ("pxor %%xmm6, %%xmm1\n\t"
+        "pxor %%xmm7, %%xmm2\n\t"
+        "movdqu 2*16(%[inbuf]), %%xmm6\n\t"
+        "movdqu 3*16(%[inbuf]), %%xmm7\n\t"
+        "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
+        "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
+        "pxor %%xmm6, %%xmm3\n\t"
+        "pxor %%xmm7, %%xmm4\n\t"
+        "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
+        "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
+        : /* No output */
+        : [inbuf] "r" (inbuf),
+          [outbuf] "r" (outbuf)
+        : "memory");
+
+      outbuf += 4*BLOCKSIZE;
+      inbuf  += 4*BLOCKSIZE;
+    }
+
+  for ( ;nblocks; nblocks-- )
+    {
+      asm volatile ("movdqa %%xmm5, %%xmm0\n\t"
+                   "paddd %[add_one], %%xmm5\n\t"
+                   "movdqu %[inbuf], %%xmm6\n\t"
+                   :
+                   : [add_one] "m" (*le_addd_const[0]),
+                     [inbuf] "m" (*inbuf)
+                   : "memory" );
+
+      do_aesni_enc (ctx);
+
+      asm volatile ("pxor %%xmm0, %%xmm6\n\t"
+                   "movdqu %%xmm6, %[outbuf]\n\t"
+                   : [outbuf] "=m" (*outbuf)
+                   :
+                   : "memory" );
+
+      outbuf += BLOCKSIZE;
+      inbuf  += BLOCKSIZE;
+    }
+
+  asm volatile ("movdqa %%xmm5, %[ctr]\n\t"
+                : [ctr] "=m" (*ctr)
+                :
+                : "memory" );
+
+  aesni_cleanup ();
+  aesni_cleanup_2_7 ();
+}
+
+
+unsigned int ASM_FUNC_ATTR
+_gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
+                         const unsigned char *src)
+{
+  aesni_prepare ();
+  asm volatile ("movdqu %[src], %%xmm0\n\t"
+                :
+                : [src] "m" (*src)
+                : "memory" );
+  do_aesni_dec (ctx);
+  asm volatile ("movdqu %%xmm0, %[dst]\n\t"
+                : [dst] "=m" (*dst)
+                :
+                : "memory" );
+  aesni_cleanup ();
+  return 0;
+}
+
+
+void ASM_FUNC_ATTR
+_gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *iv,
+                         unsigned char *outbuf, const unsigned char *inbuf,
                          size_t nblocks)
 {
-  aesni_prepare_2_6_variable;
+  aesni_prepare_2_7_variable;
 
   aesni_prepare ();
-  aesni_prepare_2_6();
+  aesni_prepare_2_7();
 
   asm volatile ("movdqu %[iv], %%xmm6\n\t"
                 : /* No output */
@@ -1175,6 +2210,98 @@ _gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
                 : "memory" );
 
   /* CFB decryption can be parallelized */
+
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      aesni_prepare_8_15_variable;
+
+      aesni_prepare_8_15();
+
+      for ( ;nblocks >= 8; nblocks -= 8)
+       {
+         asm volatile
+           ("movdqa (%[key]), %%xmm0\n\t"
+
+            "movdqu %%xmm6,         %%xmm1\n\t" /* load input blocks */
+            "movdqu 0*16(%[inbuf]), %%xmm2\n\t"
+            "movdqu 1*16(%[inbuf]), %%xmm3\n\t"
+            "movdqu 2*16(%[inbuf]), %%xmm4\n\t"
+            "movdqu 3*16(%[inbuf]), %%xmm8\n\t"
+            "movdqu 4*16(%[inbuf]), %%xmm9\n\t"
+            "movdqu 5*16(%[inbuf]), %%xmm10\n\t"
+            "movdqu 6*16(%[inbuf]), %%xmm11\n\t"
+
+            "movdqu 7*16(%[inbuf]), %%xmm6\n\t" /* update IV */
+
+            "movdqa %%xmm2, %%xmm12\n\t"
+            "movdqa %%xmm3, %%xmm13\n\t"
+            "movdqa %%xmm4, %%xmm14\n\t"
+            "movdqa %%xmm8, %%xmm15\n\t"
+
+             "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
+             "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
+             "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
+             "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
+             "pxor   %%xmm0, %%xmm8\n\t"     /* xmm8 ^= key[0] */
+             "pxor   %%xmm0, %%xmm9\n\t"     /* xmm9 ^= key[0] */
+             "pxor   %%xmm0, %%xmm10\n\t"     /* xmm10 ^= key[0] */
+             "pxor   %%xmm0, %%xmm11\n\t"     /* xmm11 ^= key[0] */
+            : /* No output */
+            : [inbuf] "r" (inbuf),
+              [key] "r" (ctx->keyschenc)
+            : "memory");
+
+         do_aesni_enc_vec8 (ctx);
+
+         asm volatile
+           (
+            "pxor %%xmm0, %%xmm12\n\t"
+            "pxor %%xmm0, %%xmm13\n\t"
+            "pxor %%xmm0, %%xmm14\n\t"
+            "pxor %%xmm0, %%xmm15\n\t"
+            "aesenclast %%xmm12, %%xmm1\n\t"
+            "aesenclast %%xmm13, %%xmm2\n\t"
+            "aesenclast %%xmm14, %%xmm3\n\t"
+            "aesenclast %%xmm15, %%xmm4\n\t"
+
+            "movdqu 4*16(%[inbuf]), %%xmm12\n\t"
+            "movdqu 5*16(%[inbuf]), %%xmm13\n\t"
+            "movdqu 6*16(%[inbuf]), %%xmm14\n\t"
+            "movdqu 7*16(%[inbuf]), %%xmm15\n\t"
+            "pxor %%xmm0, %%xmm12\n\t"
+            "pxor %%xmm0, %%xmm13\n\t"
+            "pxor %%xmm0, %%xmm14\n\t"
+            "pxor %%xmm0, %%xmm15\n\t"
+
+            "aesenclast %%xmm12, %%xmm8\n\t"
+            "aesenclast %%xmm13, %%xmm9\n\t"
+            "aesenclast %%xmm14, %%xmm10\n\t"
+            "aesenclast %%xmm15, %%xmm11\n\t"
+
+            "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
+            "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
+            "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
+            "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
+
+            "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
+            "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
+            "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
+            "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
+
+            : /* No output */
+            : [inbuf] "r" (inbuf),
+              [outbuf] "r" (outbuf)
+            : "memory");
+
+         outbuf += 8*BLOCKSIZE;
+         inbuf  += 8*BLOCKSIZE;
+       }
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
   for ( ;nblocks >= 4; nblocks -= 4)
     {
       asm volatile
@@ -1240,19 +2367,25 @@ _gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
                 : "memory" );
 
   aesni_cleanup ();
-  aesni_cleanup_2_6 ();
+  aesni_cleanup_2_7 ();
 }
 
 
-void
-_gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                        const unsigned char *inbuf, unsigned char *iv,
-                        size_t nblocks)
+void ASM_FUNC_ATTR
+_gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *iv,
+                         unsigned char *outbuf, const unsigned char *inbuf,
+                         size_t nblocks)
 {
-  aesni_prepare_2_6_variable;
+  aesni_prepare_2_7_variable;
 
   aesni_prepare ();
-  aesni_prepare_2_6();
+  aesni_prepare_2_7();
+
+  if ( !ctx->decryption_prepared )
+    {
+      do_aesni_prepare_decryption ( ctx );
+      ctx->decryption_prepared = 1;
+    }
 
   asm volatile
     ("movdqu %[iv], %%xmm5\n\t"        /* use xmm5 as fast IV storage */
@@ -1260,7 +2393,97 @@ _gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
      : [iv] "m" (*iv)
      : "memory");
 
-  for ( ;nblocks > 3 ; nblocks -= 4 )
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      aesni_prepare_8_15_variable;
+
+      aesni_prepare_8_15();
+
+      for ( ;nblocks >= 8 ; nblocks -= 8 )
+       {
+         asm volatile
+           ("movdqa (%[key]), %%xmm0\n\t"
+
+            "movdqu 0*16(%[inbuf]), %%xmm1\n\t"        /* load input blocks */
+            "movdqu 1*16(%[inbuf]), %%xmm2\n\t"
+            "movdqu 2*16(%[inbuf]), %%xmm3\n\t"
+            "movdqu 3*16(%[inbuf]), %%xmm4\n\t"
+            "movdqu 4*16(%[inbuf]), %%xmm8\n\t"
+            "movdqu 5*16(%[inbuf]), %%xmm9\n\t"
+            "movdqu 6*16(%[inbuf]), %%xmm10\n\t"
+            "movdqu 7*16(%[inbuf]), %%xmm11\n\t"
+
+            "movdqa %%xmm1, %%xmm12\n\t"
+            "movdqa %%xmm2, %%xmm13\n\t"
+            "movdqa %%xmm3, %%xmm14\n\t"
+            "movdqa %%xmm4, %%xmm15\n\t"
+
+            "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
+            "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
+            "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
+            "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
+            "pxor   %%xmm0, %%xmm8\n\t"     /* xmm8 ^= key[0] */
+            "pxor   %%xmm0, %%xmm9\n\t"     /* xmm9 ^= key[0] */
+            "pxor   %%xmm0, %%xmm10\n\t"    /* xmm10 ^= key[0] */
+            "pxor   %%xmm0, %%xmm11\n\t"    /* xmm11 ^= key[0] */
+
+            : /* No output */
+            : [inbuf] "r" (inbuf),
+              [key] "r" (ctx->keyschdec)
+            : "memory");
+
+         do_aesni_dec_vec8 (ctx);
+
+         asm volatile
+           (
+            "pxor %%xmm0, %%xmm5\n\t"                  /* xor IV with key */
+            "pxor %%xmm0, %%xmm12\n\t"                 /* xor IV with key */
+            "pxor %%xmm0, %%xmm13\n\t"                 /* xor IV with key */
+            "pxor %%xmm0, %%xmm14\n\t"                 /* xor IV with key */
+            "pxor %%xmm0, %%xmm15\n\t"                 /* xor IV with key */
+
+            "aesdeclast %%xmm5, %%xmm1\n\t"
+            "aesdeclast %%xmm12, %%xmm2\n\t"
+            "aesdeclast %%xmm13, %%xmm3\n\t"
+            "aesdeclast %%xmm14, %%xmm4\n\t"
+
+            "movdqu 4*16(%[inbuf]), %%xmm12\n\t"
+            "movdqu 5*16(%[inbuf]), %%xmm13\n\t"
+            "movdqu 6*16(%[inbuf]), %%xmm14\n\t"
+            "movdqu 7*16(%[inbuf]), %%xmm5\n\t"
+            "pxor %%xmm0, %%xmm12\n\t"                 /* xor IV with key */
+            "pxor %%xmm0, %%xmm13\n\t"                 /* xor IV with key */
+            "pxor %%xmm0, %%xmm14\n\t"                 /* xor IV with key */
+
+            "aesdeclast %%xmm15, %%xmm8\n\t"
+            "aesdeclast %%xmm12, %%xmm9\n\t"
+            "aesdeclast %%xmm13, %%xmm10\n\t"
+            "aesdeclast %%xmm14, %%xmm11\n\t"
+
+            "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
+            "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
+            "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
+            "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
+            "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
+            "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
+            "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
+            "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
+
+            : /* No output */
+            : [inbuf] "r" (inbuf),
+              [outbuf] "r" (outbuf)
+            : "memory");
+
+         outbuf += 8*BLOCKSIZE;
+         inbuf  += 8*BLOCKSIZE;
+       }
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
+  for ( ;nblocks >= 4 ; nblocks -= 4 )
     {
       asm volatile
         ("movdqu 0*16(%[inbuf]), %%xmm1\n\t"   /* load input blocks */
@@ -1330,11 +2553,179 @@ _gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
      : "memory");
 
   aesni_cleanup ();
-  aesni_cleanup_2_6 ();
+  aesni_cleanup_2_7 ();
+}
+
+
+static ASM_FUNC_ATTR_INLINE void
+aesni_ocb_checksum (gcry_cipher_hd_t c, const unsigned char *plaintext,
+                   size_t nblocks)
+{
+  RIJNDAEL_context *ctx = (void *)&c->context.c;
+
+  /* Calculate checksum */
+  asm volatile ("movdqu %[checksum], %%xmm6\n\t"
+                "pxor %%xmm1, %%xmm1\n\t"
+                "pxor %%xmm2, %%xmm2\n\t"
+                "pxor %%xmm3, %%xmm3\n\t"
+                :
+                :[checksum] "m" (*c->u_ctr.ctr)
+                : "memory" );
+
+  if (0) {}
+#if defined(HAVE_GCC_INLINE_ASM_AVX2)
+  else if (nblocks >= 16 && ctx->use_avx2)
+    {
+      /* Use wider 256-bit registers for fast xoring of plaintext. */
+      asm volatile ("vzeroupper\n\t"
+                   "vpxor %%xmm0, %%xmm0, %%xmm0\n\t"
+                   "vpxor %%xmm4, %%xmm4, %%xmm4\n\t"
+                   "vpxor %%xmm5, %%xmm5, %%xmm5\n\t"
+                   "vpxor %%xmm7, %%xmm7, %%xmm7\n\t"
+                    :
+                    :
+                    : "memory");
+
+      for (;nblocks >= 16; nblocks -= 16)
+       {
+         asm volatile ("vpxor %[ptr0], %%ymm6, %%ymm6\n\t"
+                       "vpxor %[ptr1], %%ymm1, %%ymm1\n\t"
+                       "vpxor %[ptr2], %%ymm2, %%ymm2\n\t"
+                       "vpxor %[ptr3], %%ymm3, %%ymm3\n\t"
+                       :
+                       : [ptr0] "m" (*(plaintext + 0 * BLOCKSIZE * 2)),
+                         [ptr1] "m" (*(plaintext + 1 * BLOCKSIZE * 2)),
+                         [ptr2] "m" (*(plaintext + 2 * BLOCKSIZE * 2)),
+                         [ptr3] "m" (*(plaintext + 3 * BLOCKSIZE * 2))
+                       : "memory" );
+         asm volatile ("vpxor %[ptr4], %%ymm0, %%ymm0\n\t"
+                       "vpxor %[ptr5], %%ymm4, %%ymm4\n\t"
+                       "vpxor %[ptr6], %%ymm5, %%ymm5\n\t"
+                       "vpxor %[ptr7], %%ymm7, %%ymm7\n\t"
+                       :
+                       : [ptr4] "m" (*(plaintext + 4 * BLOCKSIZE * 2)),
+                         [ptr5] "m" (*(plaintext + 5 * BLOCKSIZE * 2)),
+                         [ptr6] "m" (*(plaintext + 6 * BLOCKSIZE * 2)),
+                         [ptr7] "m" (*(plaintext + 7 * BLOCKSIZE * 2))
+                       : "memory" );
+         plaintext += BLOCKSIZE * 16;
+       }
+
+      asm volatile ("vpxor %%ymm0, %%ymm6, %%ymm6\n\t"
+                   "vpxor %%ymm4, %%ymm1, %%ymm1\n\t"
+                   "vpxor %%ymm5, %%ymm2, %%ymm2\n\t"
+                   "vpxor %%ymm7, %%ymm3, %%ymm3\n\t"
+                   "vextracti128 $1, %%ymm6, %%xmm0\n\t"
+                   "vextracti128 $1, %%ymm1, %%xmm4\n\t"
+                   "vextracti128 $1, %%ymm2, %%xmm5\n\t"
+                   "vextracti128 $1, %%ymm3, %%xmm7\n\t"
+                   "vpxor %%xmm0, %%xmm6, %%xmm6\n\t"
+                   "vpxor %%xmm4, %%xmm1, %%xmm1\n\t"
+                   "vpxor %%xmm5, %%xmm2, %%xmm2\n\t"
+                   "vpxor %%xmm7, %%xmm3, %%xmm3\n\t"
+                   "vzeroupper\n\t"
+                   :
+                   :
+                   : "memory" );
+    }
+#endif
+#if defined(HAVE_GCC_INLINE_ASM_AVX)
+  else if (nblocks >= 16 && ctx->use_avx)
+    {
+      /* Same as AVX2, except using 256-bit floating point instructions. */
+      asm volatile ("vzeroupper\n\t"
+                   "vxorpd %%xmm0, %%xmm0, %%xmm0\n\t"
+                   "vxorpd %%xmm4, %%xmm4, %%xmm4\n\t"
+                   "vxorpd %%xmm5, %%xmm5, %%xmm5\n\t"
+                   "vxorpd %%xmm7, %%xmm7, %%xmm7\n\t"
+                    :
+                    :
+                    : "memory");
+
+      for (;nblocks >= 16; nblocks -= 16)
+       {
+         asm volatile ("vxorpd %[ptr0], %%ymm6, %%ymm6\n\t"
+                       "vxorpd %[ptr1], %%ymm1, %%ymm1\n\t"
+                       "vxorpd %[ptr2], %%ymm2, %%ymm2\n\t"
+                       "vxorpd %[ptr3], %%ymm3, %%ymm3\n\t"
+                       :
+                       : [ptr0] "m" (*(plaintext + 0 * BLOCKSIZE * 2)),
+                         [ptr1] "m" (*(plaintext + 1 * BLOCKSIZE * 2)),
+                         [ptr2] "m" (*(plaintext + 2 * BLOCKSIZE * 2)),
+                         [ptr3] "m" (*(plaintext + 3 * BLOCKSIZE * 2))
+                       : "memory" );
+         asm volatile ("vxorpd %[ptr4], %%ymm0, %%ymm0\n\t"
+                       "vxorpd %[ptr5], %%ymm4, %%ymm4\n\t"
+                       "vxorpd %[ptr6], %%ymm5, %%ymm5\n\t"
+                       "vxorpd %[ptr7], %%ymm7, %%ymm7\n\t"
+                       :
+                       : [ptr4] "m" (*(plaintext + 4 * BLOCKSIZE * 2)),
+                         [ptr5] "m" (*(plaintext + 5 * BLOCKSIZE * 2)),
+                         [ptr6] "m" (*(plaintext + 6 * BLOCKSIZE * 2)),
+                         [ptr7] "m" (*(plaintext + 7 * BLOCKSIZE * 2))
+                       : "memory" );
+         plaintext += BLOCKSIZE * 16;
+       }
+
+      asm volatile ("vxorpd %%ymm0, %%ymm6, %%ymm6\n\t"
+                   "vxorpd %%ymm4, %%ymm1, %%ymm1\n\t"
+                   "vxorpd %%ymm5, %%ymm2, %%ymm2\n\t"
+                   "vxorpd %%ymm7, %%ymm3, %%ymm3\n\t"
+                   "vextractf128 $1, %%ymm6, %%xmm0\n\t"
+                   "vextractf128 $1, %%ymm1, %%xmm4\n\t"
+                   "vextractf128 $1, %%ymm2, %%xmm5\n\t"
+                   "vextractf128 $1, %%ymm3, %%xmm7\n\t"
+                   "vxorpd %%xmm0, %%xmm6, %%xmm6\n\t"
+                   "vxorpd %%xmm4, %%xmm1, %%xmm1\n\t"
+                   "vxorpd %%xmm5, %%xmm2, %%xmm2\n\t"
+                   "vxorpd %%xmm7, %%xmm3, %%xmm3\n\t"
+                   "vzeroupper\n\t"
+                   :
+                   :
+                   : "memory" );
+    }
+#endif
+
+  for (;nblocks >= 4; nblocks -= 4)
+    {
+      asm volatile ("movdqu %[ptr0], %%xmm0\n\t"
+                   "movdqu %[ptr1], %%xmm4\n\t"
+                   "movdqu %[ptr2], %%xmm5\n\t"
+                   "movdqu %[ptr3], %%xmm7\n\t"
+                   "pxor %%xmm0, %%xmm6\n\t"
+                   "pxor %%xmm4, %%xmm1\n\t"
+                   "pxor %%xmm5, %%xmm2\n\t"
+                   "pxor %%xmm7, %%xmm3\n\t"
+                   :
+                   : [ptr0] "m" (*(plaintext + 0 * BLOCKSIZE)),
+                     [ptr1] "m" (*(plaintext + 1 * BLOCKSIZE)),
+                     [ptr2] "m" (*(plaintext + 2 * BLOCKSIZE)),
+                     [ptr3] "m" (*(plaintext + 3 * BLOCKSIZE))
+                   : "memory" );
+      plaintext += BLOCKSIZE * 4;
+    }
+
+  for (;nblocks >= 1; nblocks -= 1)
+    {
+      asm volatile ("movdqu %[ptr0], %%xmm0\n\t"
+                   "pxor %%xmm0, %%xmm6\n\t"
+                   :
+                   : [ptr0] "m" (*(plaintext + 0 * BLOCKSIZE))
+                   : "memory" );
+      plaintext += BLOCKSIZE;
+    }
+
+  asm volatile ("pxor %%xmm1, %%xmm6\n\t"
+               "pxor %%xmm2, %%xmm6\n\t"
+               "pxor %%xmm3, %%xmm6\n\t"
+               "movdqu %%xmm6, %[checksum]\n\t"
+               : [checksum] "=m" (*c->u_ctr.ctr)
+               :
+               : "memory" );
 }
 
 
-static void
+static unsigned int ASM_FUNC_ATTR_NOINLINE
 aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
                const void *inbuf_arg, size_t nblocks)
 {
@@ -1343,31 +2734,35 @@ aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
   const unsigned char *inbuf = inbuf_arg;
   u64 n = c->u_mode.ocb.data_nblocks;
   const unsigned char *l;
-  aesni_prepare_2_6_variable;
+  byte tmpbuf_store[3 * 16 + 15];
+  byte *tmpbuf;
+  aesni_prepare_2_7_variable;
+
+  asm volatile ("" : "=r" (tmpbuf) : "0" (tmpbuf_store) : "memory");
+  tmpbuf = tmpbuf + (-(uintptr_t)tmpbuf & 15);
 
   aesni_prepare ();
-  aesni_prepare_2_6 ();
+  aesni_prepare_2_7 ();
 
-  /* Preload Offset and Checksum */
+  /* Preload Offset */
   asm volatile ("movdqu %[iv], %%xmm5\n\t"
-                "movdqu %[ctr], %%xmm6\n\t"
-                : /* No output */
-                : [iv] "m" (*c->u_iv.iv),
-                  [ctr] "m" (*c->u_ctr.ctr)
-                : "memory" );
-
+               "movdqu %[ctr], %%xmm7\n\t"
+               : /* No output */
+               : [iv] "m" (*c->u_iv.iv),
+                 [ctr] "m" (*c->u_ctr.ctr)
+               : "memory" );
 
   for ( ;nblocks && n % 4; nblocks-- )
     {
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
-      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* Checksum_i = Checksum_{i-1} xor P_i  */
+      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
       asm volatile ("movdqu %[l],     %%xmm1\n\t"
                     "movdqu %[inbuf], %%xmm0\n\t"
                     "pxor   %%xmm1,   %%xmm5\n\t"
-                    "pxor   %%xmm0,   %%xmm6\n\t"
+                    "pxor   %%xmm0,   %%xmm7\n\t"
                     "pxor   %%xmm5,   %%xmm0\n\t"
                     :
                     : [l] "m" (*l),
@@ -1386,72 +2781,385 @@ aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
       outbuf += BLOCKSIZE;
     }
 
-  for ( ;nblocks > 3 ; nblocks -= 4 )
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      unsigned char last_xor_first_key_store[16 + 15];
+      unsigned char *lxf_key;
+      aesni_prepare_8_15_variable;
+
+      asm volatile (""
+                    : "=r" (lxf_key)
+                   : "0" (last_xor_first_key_store)
+                   : "memory");
+      lxf_key = lxf_key + (-(uintptr_t)lxf_key & 15);
+
+      aesni_prepare_8_15();
+
+      asm volatile ("movdqu %[l0], %%xmm6\n\t"
+                   "movdqa %[last_key], %%xmm0\n\t"
+                   "pxor %[first_key], %%xmm5\n\t"
+                   "pxor %[first_key], %%xmm0\n\t"
+                   "movdqa %%xmm0, %[lxfkey]\n\t"
+                   : [lxfkey] "=m" (*lxf_key)
+                   : [l0] "m" (*c->u_mode.ocb.L[0]),
+                     [last_key] "m" (ctx->keyschenc[ctx->rounds][0][0]),
+                     [first_key] "m" (ctx->keyschenc[0][0][0])
+                   : "memory" );
+
+      for ( ;nblocks >= 8 ; nblocks -= 8 )
+       {
+         n += 4;
+         l = aes_ocb_get_l(c, n);
+
+         asm volatile ("movdqu %[l0l1],   %%xmm10\n\t"
+                       "movdqu %[l1],     %%xmm11\n\t"
+                       "movdqu %[l3],     %%xmm15\n\t"
+                       :
+                       : [l0l1] "m" (*c->u_mode.ocb.L0L1),
+                         [l1] "m" (*c->u_mode.ocb.L[1]),
+                         [l3] "m" (*l)
+                       : "memory" );
+
+         n += 4;
+         l = aes_ocb_get_l(c, n);
+
+          /* Checksum_i = Checksum_{i-1} xor P_i  */
+         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+         /* P_i = Offset_i xor ENCIPHER(K, C_i xor Offset_i)  */
+         asm volatile ("movdqu %[inbuf0], %%xmm1\n\t"
+                       "movdqu %[inbuf1], %%xmm2\n\t"
+                       "movdqu %[inbuf2], %%xmm3\n\t"
+                       :
+                       : [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE)),
+                         [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE)),
+                         [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
+                       : "memory" );
+         asm volatile ("movdqu %[inbuf3], %%xmm4\n\t"
+                       "movdqu %[inbuf4], %%xmm8\n\t"
+                       "movdqu %[inbuf5], %%xmm9\n\t"
+                       :
+                       : [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE)),
+                         [inbuf4] "m" (*(inbuf + 4 * BLOCKSIZE)),
+                         [inbuf5] "m" (*(inbuf + 5 * BLOCKSIZE))
+                       : "memory" );
+         asm volatile ("movdqa %[lxfkey], %%xmm0\n\t"
+                       "movdqa %%xmm6,    %%xmm12\n\t"
+                       "pxor   %%xmm5,    %%xmm12\n\t"
+                       "pxor   %%xmm1,    %%xmm7\n\t"
+                       "pxor   %%xmm12,   %%xmm1\n\t"
+                       "pxor   %%xmm0,    %%xmm12\n\t"
+
+                       "movdqa %%xmm10,   %%xmm13\n\t"
+                       "pxor   %%xmm5,    %%xmm13\n\t"
+                       "pxor   %%xmm2,    %%xmm7\n\t"
+                       "pxor   %%xmm13,   %%xmm2\n\t"
+                       "pxor   %%xmm0,    %%xmm13\n\t"
+
+                       "movdqa %%xmm11,   %%xmm14\n\t"
+                       "pxor   %%xmm5,    %%xmm14\n\t"
+                       "pxor   %%xmm3,    %%xmm7\n\t"
+                       "pxor   %%xmm14,   %%xmm3\n\t"
+                       "pxor   %%xmm0,    %%xmm14\n\t"
+
+                       "pxor   %%xmm11,   %%xmm5\n\t"
+                       "pxor   %%xmm15,   %%xmm5\n\t"
+                       "pxor   %%xmm4,    %%xmm7\n\t"
+                       "pxor   %%xmm5,    %%xmm4\n\t"
+                       "movdqa %%xmm5,    %%xmm15\n\t"
+                       "pxor   %%xmm0,    %%xmm15\n\t"
+
+                       "movdqa %%xmm5,    %%xmm0\n\t"
+                       "pxor   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm8,    %%xmm7\n\t"
+                       "pxor   %%xmm0,    %%xmm8\n\t"
+                       "pxor   %[lxfkey], %%xmm0\n\t"
+                       "movdqa %%xmm0,    %[tmpbuf0]\n\t"
+
+                       "movdqa %%xmm10,   %%xmm0\n\t"
+                       "pxor   %%xmm5,    %%xmm0\n\t"
+                       "pxor   %%xmm9,    %%xmm7\n\t"
+                       "pxor   %%xmm0,    %%xmm9\n\t"
+                       "pxor   %[lxfkey], %%xmm0\n"
+                       "movdqa %%xmm0,    %[tmpbuf1]\n\t"
+                       : [tmpbuf0] "=m" (*(tmpbuf + 0 * BLOCKSIZE)),
+                         [tmpbuf1] "=m" (*(tmpbuf + 1 * BLOCKSIZE))
+                       : [lxfkey] "m" (*lxf_key)
+                       : "memory" );
+         asm volatile ("movdqu %[inbuf6], %%xmm10\n\t"
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "pxor   %%xmm5,    %%xmm0\n\t"
+                       "pxor   %%xmm10,   %%xmm7\n\t"
+                       "pxor   %%xmm0,    %%xmm10\n\t"
+                       "pxor   %[lxfkey], %%xmm0\n\t"
+                       "movdqa %%xmm0,    %[tmpbuf2]\n\t"
+                       : [tmpbuf2] "=m" (*(tmpbuf + 2 * BLOCKSIZE))
+                       : [inbuf6] "m" (*(inbuf + 6 * BLOCKSIZE)),
+                         [lxfkey] "m" (*lxf_key)
+                       : "memory" );
+         asm volatile ("movdqu %[l7],     %%xmm0\n\t"
+                       "pxor   %%xmm11,   %%xmm5\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       "movdqa 0x10(%[key]), %%xmm0\n\t"
+                       "movdqu %[inbuf7], %%xmm11\n\t"
+                       "pxor   %%xmm11,   %%xmm7\n\t"
+                       "pxor   %%xmm5,    %%xmm11\n\t"
+                       :
+                       : [l7] "m" (*l),
+                         [inbuf7] "m" (*(inbuf + 7 * BLOCKSIZE)),
+                         [key] "r" (ctx->keyschenc)
+                       : "memory" );
+
+         asm volatile ("cmpl $12, %[rounds]\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x20(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x30(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x40(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x50(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x60(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x70(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x80(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x90(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "jb .Ldeclast%=\n\t"
+                       "movdqa 0xa0(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xb0(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "je .Ldeclast%=\n\t"
+                       "movdqa 0xc0(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xd0(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+
+                       ".Ldeclast%=:\n\t"
+                       :
+                       : [key] "r" (ctx->keyschenc),
+                         [rounds] "r" (ctx->rounds)
+                       : "cc", "memory");
+
+         asm volatile ("aesenclast %%xmm12,   %%xmm1\n\t"
+                       "aesenclast %%xmm13,   %%xmm2\n\t"
+                       "aesenclast %%xmm14,   %%xmm3\n\t"
+                       "aesenclast %%xmm15,   %%xmm4\n\t"
+                       "aesenclast %[tmpbuf0],%%xmm8\n\t"
+                       "aesenclast %[tmpbuf1],%%xmm9\n\t"
+                       "aesenclast %[tmpbuf2],%%xmm10\n\t"
+                       :
+                       : [tmpbuf0] "m" (*(tmpbuf + 0 * BLOCKSIZE)),
+                         [tmpbuf1] "m" (*(tmpbuf + 1 * BLOCKSIZE)),
+                         [tmpbuf2] "m" (*(tmpbuf + 2 * BLOCKSIZE)),
+                         [lxfkey] "m" (*lxf_key)
+                       : "memory" );
+         asm volatile ("aesenclast %%xmm5,    %%xmm11\n\t"
+                       "pxor   %[lxfkey], %%xmm11\n\t"
+                       "movdqu %%xmm1,    %[outbuf0]\n\t"
+                       "movdqu %%xmm2,    %[outbuf1]\n\t"
+                       : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
+                         [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
+                       : [lxfkey] "m" (*lxf_key)
+                       : "memory" );
+         asm volatile ("movdqu %%xmm3,    %[outbuf2]\n\t"
+                       "movdqu %%xmm4,    %[outbuf3]\n\t"
+                       "movdqu %%xmm8,    %[outbuf4]\n\t"
+                       : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
+                         [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE)),
+                         [outbuf4] "=m" (*(outbuf + 4 * BLOCKSIZE))
+                       :
+                       : "memory" );
+         asm volatile ("movdqu %%xmm9,    %[outbuf5]\n\t"
+                       "movdqu %%xmm10,   %[outbuf6]\n\t"
+                       "movdqu %%xmm11,   %[outbuf7]\n\t"
+                       : [outbuf5] "=m" (*(outbuf + 5 * BLOCKSIZE)),
+                         [outbuf6] "=m" (*(outbuf + 6 * BLOCKSIZE)),
+                         [outbuf7] "=m" (*(outbuf + 7 * BLOCKSIZE))
+                       :
+                       : "memory" );
+
+         outbuf += 8*BLOCKSIZE;
+         inbuf  += 8*BLOCKSIZE;
+       }
+
+      asm volatile ("pxor %[first_key], %%xmm5\n\t"
+                   "pxor %%xmm0, %%xmm0\n\t"
+                   "movdqu %%xmm0, %[lxfkey]\n\t"
+                   : [lxfkey] "=m" (*lxf_key)
+                   : [first_key] "m" (ctx->keyschenc[0][0][0])
+                   : "memory" );
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
+  for ( ;nblocks >= 4 ; nblocks -= 4 )
     {
       n += 4;
-      l = ocb_get_l(c, n);
+      l = aes_ocb_get_l(c, n);
 
-      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* Checksum_i = Checksum_{i-1} xor P_i  */
+      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
                    "movdqu %[inbuf0], %%xmm1\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
-                   "pxor   %%xmm1,    %%xmm6\n\t"
-                   "pxor   %%xmm5,    %%xmm1\n\t"
-                   "movdqu %%xmm5,    %[outbuf0]\n\t"
-                   : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
+                   "movdqu %[l0l1],   %%xmm3\n\t"
+                   :
                    : [l0] "m" (*c->u_mode.ocb.L[0]),
+                     [l0l1] "m" (*c->u_mode.ocb.L0L1),
                      [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
                    : "memory" );
-      asm volatile ("movdqu %[l1],     %%xmm0\n\t"
-                   "movdqu %[inbuf1], %%xmm2\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
-                   "pxor   %%xmm2,    %%xmm6\n\t"
-                   "pxor   %%xmm5,    %%xmm2\n\t"
-                   "movdqu %%xmm5,    %[outbuf1]\n\t"
-                   : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
+      asm volatile ("movdqu %[l1],     %%xmm4\n\t"
+                   "movdqu %[l3],     %%xmm6\n\t"
+                   "pxor   %%xmm5,    %%xmm0\n\t"
+                   "pxor   %%xmm1,    %%xmm7\n\t"
+                   "pxor   %%xmm0,    %%xmm1\n\t"
+                   "movdqa %%xmm0,    %[tmpbuf0]\n\t"
+                   : [tmpbuf0] "=m" (*(tmpbuf + 0 * BLOCKSIZE))
                    : [l1] "m" (*c->u_mode.ocb.L[1]),
-                     [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
+                     [l3] "m" (*l)
                    : "memory" );
-      asm volatile ("movdqu %[l2],     %%xmm0\n\t"
-                   "movdqu %[inbuf2], %%xmm3\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
-                   "pxor   %%xmm3,    %%xmm6\n\t"
+      asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
                    "pxor   %%xmm5,    %%xmm3\n\t"
-                   "movdqu %%xmm5,    %[outbuf2]\n\t"
-                   : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
-                   : [l2] "m" (*c->u_mode.ocb.L[0]),
+                   "pxor   %%xmm2,    %%xmm7\n\t"
+                   "pxor   %%xmm3,    %%xmm2\n\t"
+                   "movdqa %%xmm3,    %[tmpbuf1]\n\t"
+                   : [tmpbuf1] "=m" (*(tmpbuf + 1 * BLOCKSIZE))
+                   : [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
+                   : "memory" );
+      asm volatile ("movdqa %%xmm4,    %%xmm0\n\t"
+                   "movdqu %[inbuf2], %%xmm3\n\t"
+                   "pxor   %%xmm5,    %%xmm0\n\t"
+                   "pxor   %%xmm3,    %%xmm7\n\t"
+                   "pxor   %%xmm0,    %%xmm3\n\t"
+                   "movdqa %%xmm0,    %[tmpbuf2]\n\t"
+                   : [tmpbuf2] "=m" (*(tmpbuf + 2 * BLOCKSIZE))
+                   :
                      [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
                    : "memory" );
-      asm volatile ("movdqu %[l3],     %%xmm0\n\t"
+      asm volatile ("pxor   %%xmm6,    %%xmm5\n\t"
+                   "pxor   %%xmm4,    %%xmm5\n\t"
                    "movdqu %[inbuf3], %%xmm4\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
-                   "pxor   %%xmm4,    %%xmm6\n\t"
+                   "pxor   %%xmm4,    %%xmm7\n\t"
                    "pxor   %%xmm5,    %%xmm4\n\t"
                    :
-                   : [l3] "m" (*l),
-                     [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
+                   : [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
                    : "memory" );
 
       do_aesni_enc_vec4 (ctx);
 
-      asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
-                   "pxor   %%xmm0,    %%xmm1\n\t"
+      asm volatile ("pxor   %[tmpbuf0],%%xmm1\n\t"
                    "movdqu %%xmm1,    %[outbuf0]\n\t"
-                   "movdqu %[outbuf1],%%xmm0\n\t"
-                   "pxor   %%xmm0,    %%xmm2\n\t"
+                   "pxor   %[tmpbuf1],%%xmm2\n\t"
                    "movdqu %%xmm2,    %[outbuf1]\n\t"
-                   "movdqu %[outbuf2],%%xmm0\n\t"
-                   "pxor   %%xmm0,    %%xmm3\n\t"
+                   : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
+                     [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
+                   : [tmpbuf0] "m" (*(tmpbuf + 0 * BLOCKSIZE)),
+                     [tmpbuf1] "m" (*(tmpbuf + 1 * BLOCKSIZE))
+                   : "memory" );
+      asm volatile ("pxor   %[tmpbuf2],%%xmm3\n\t"
                    "movdqu %%xmm3,    %[outbuf2]\n\t"
                    "pxor   %%xmm5,    %%xmm4\n\t"
                    "movdqu %%xmm4,    %[outbuf3]\n\t"
-                   : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
-                     [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
-                     [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
+                   : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
                      [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
-                   :
+                   : [tmpbuf2] "m" (*(tmpbuf + 2 * BLOCKSIZE))
                    : "memory" );
 
       outbuf += 4*BLOCKSIZE;
@@ -1460,15 +3168,15 @@ aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
 
   for ( ;nblocks; nblocks-- )
     {
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
-      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* Checksum_i = Checksum_{i-1} xor P_i  */
+      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
       asm volatile ("movdqu %[l],     %%xmm1\n\t"
                     "movdqu %[inbuf], %%xmm0\n\t"
                     "pxor   %%xmm1,   %%xmm5\n\t"
-                    "pxor   %%xmm0,   %%xmm6\n\t"
+                   "pxor   %%xmm0,   %%xmm7\n\t"
                     "pxor   %%xmm5,   %%xmm0\n\t"
                     :
                     : [l] "m" (*l),
@@ -1489,46 +3197,67 @@ aesni_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
 
   c->u_mode.ocb.data_nblocks = n;
   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
-                "movdqu %%xmm6, %[ctr]\n\t"
-                : [iv] "=m" (*c->u_iv.iv),
-                  [ctr] "=m" (*c->u_ctr.ctr)
+                "movdqu %%xmm7, %[ctr]\n\t"
+               : [iv] "=m" (*c->u_iv.iv),
+                 [ctr] "=m" (*c->u_ctr.ctr)
+                :
+                : "memory" );
+
+  asm volatile ("pxor   %%xmm0, %%xmm0\n\t"
+                "movdqa %%xmm0, %[tmpbuf0]\n\t"
+                "movdqa %%xmm0, %[tmpbuf1]\n\t"
+                "movdqa %%xmm0, %[tmpbuf2]\n\t"
+               : [tmpbuf0] "=m" (*(tmpbuf + 0 * BLOCKSIZE)),
+                 [tmpbuf1] "=m" (*(tmpbuf + 1 * BLOCKSIZE)),
+                 [tmpbuf2] "=m" (*(tmpbuf + 2 * BLOCKSIZE))
                 :
                 : "memory" );
 
   aesni_cleanup ();
-  aesni_cleanup_2_6 ();
+  aesni_cleanup_2_7 ();
+
+  return 0;
 }
 
 
-static void
+static unsigned int ASM_FUNC_ATTR_NOINLINE
 aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
-               const void *inbuf_arg, size_t nblocks)
+               const void *inbuf_arg, size_t nblocks_arg)
 {
   RIJNDAEL_context *ctx = (void *)&c->context.c;
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
   u64 n = c->u_mode.ocb.data_nblocks;
   const unsigned char *l;
-  aesni_prepare_2_6_variable;
+  size_t nblocks = nblocks_arg;
+  byte tmpbuf_store[3 * 16 + 15];
+  byte *tmpbuf;
+  aesni_prepare_2_7_variable;
+
+  asm volatile ("" : "=r" (tmpbuf) : "0" (tmpbuf_store) : "memory");
+  tmpbuf = tmpbuf + (-(uintptr_t)tmpbuf & 15);
 
   aesni_prepare ();
-  aesni_prepare_2_6 ();
+  aesni_prepare_2_7 ();
 
-  /* Preload Offset and Checksum */
+  if ( !ctx->decryption_prepared )
+    {
+      do_aesni_prepare_decryption ( ctx );
+      ctx->decryption_prepared = 1;
+    }
+
+  /* Preload Offset */
   asm volatile ("movdqu %[iv], %%xmm5\n\t"
-                "movdqu %[ctr], %%xmm6\n\t"
                 : /* No output */
-                : [iv] "m" (*c->u_iv.iv),
-                  [ctr] "m" (*c->u_ctr.ctr)
+                : [iv] "m" (*c->u_iv.iv)
                 : "memory" );
 
   for ( ;nblocks && n % 4; nblocks-- )
     {
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
-      /* Checksum_i = Checksum_{i-1} xor P_i  */
       asm volatile ("movdqu %[l],     %%xmm1\n\t"
                     "movdqu %[inbuf], %%xmm0\n\t"
                     "pxor   %%xmm1,   %%xmm5\n\t"
@@ -1541,7 +3270,6 @@ aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
       do_aesni_dec (ctx);
 
       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
-                    "pxor   %%xmm0, %%xmm6\n\t"
                     "movdqu %%xmm0, %[outbuf]\n\t"
                     : [outbuf] "=m" (*outbuf)
                     :
@@ -1551,72 +3279,370 @@ aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
       outbuf += BLOCKSIZE;
     }
 
-  for ( ;nblocks > 3 ; nblocks -= 4 )
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      unsigned char last_xor_first_key_store[16 + 15];
+      unsigned char *lxf_key;
+      aesni_prepare_8_15_variable;
+
+      asm volatile (""
+                    : "=r" (lxf_key)
+                   : "0" (last_xor_first_key_store)
+                   : "memory");
+      lxf_key = lxf_key + (-(uintptr_t)lxf_key & 15);
+
+      aesni_prepare_8_15();
+
+      asm volatile ("movdqu %[l0], %%xmm6\n\t"
+                   "movdqa %[last_key], %%xmm0\n\t"
+                   "pxor %[first_key], %%xmm5\n\t"
+                   "pxor %[first_key], %%xmm0\n\t"
+                   "movdqa %%xmm0, %[lxfkey]\n\t"
+                   : [lxfkey] "=m" (*lxf_key)
+                   : [l0] "m" (*c->u_mode.ocb.L[0]),
+                     [last_key] "m" (ctx->keyschdec[ctx->rounds][0][0]),
+                     [first_key] "m" (ctx->keyschdec[0][0][0])
+                   : "memory" );
+
+      for ( ;nblocks >= 8 ; nblocks -= 8 )
+       {
+         n += 4;
+         l = aes_ocb_get_l(c, n);
+
+         asm volatile ("movdqu %[l0l1],   %%xmm10\n\t"
+                       "movdqu %[l1],     %%xmm11\n\t"
+                       "movdqu %[l3],     %%xmm15\n\t"
+                       :
+                       : [l0l1] "m" (*c->u_mode.ocb.L0L1),
+                         [l1] "m" (*c->u_mode.ocb.L[1]),
+                         [l3] "m" (*l)
+                       : "memory" );
+
+         n += 4;
+         l = aes_ocb_get_l(c, n);
+
+         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+         /* P_i = Offset_i xor ENCIPHER(K, C_i xor Offset_i)  */
+         asm volatile ("movdqu %[inbuf0], %%xmm1\n\t"
+                       "movdqu %[inbuf1], %%xmm2\n\t"
+                       "movdqu %[inbuf2], %%xmm3\n\t"
+                       :
+                       : [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE)),
+                         [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE)),
+                         [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
+                       : "memory" );
+         asm volatile ("movdqu %[inbuf3], %%xmm4\n\t"
+                       "movdqu %[inbuf4], %%xmm8\n\t"
+                       "movdqu %[inbuf5], %%xmm9\n\t"
+                       :
+                       : [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE)),
+                         [inbuf4] "m" (*(inbuf + 4 * BLOCKSIZE)),
+                         [inbuf5] "m" (*(inbuf + 5 * BLOCKSIZE))
+                       : "memory" );
+         asm volatile ("movdqa %[lxfkey], %%xmm0\n\t"
+                       "movdqa %%xmm6,    %%xmm12\n\t"
+                       "pxor   %%xmm5,    %%xmm12\n\t"
+                       "pxor   %%xmm12,   %%xmm1\n\t"
+                       "pxor   %%xmm0,    %%xmm12\n\t"
+
+                       "movdqa %%xmm10,   %%xmm13\n\t"
+                       "pxor   %%xmm5,    %%xmm13\n\t"
+                       "pxor   %%xmm13,   %%xmm2\n\t"
+                       "pxor   %%xmm0,    %%xmm13\n\t"
+
+                       "movdqa %%xmm11,   %%xmm14\n\t"
+                       "pxor   %%xmm5,    %%xmm14\n\t"
+                       "pxor   %%xmm14,   %%xmm3\n\t"
+                       "pxor   %%xmm0,    %%xmm14\n\t"
+
+                       "pxor   %%xmm11,   %%xmm5\n\t"
+                       "pxor   %%xmm15,   %%xmm5\n\t"
+                       "pxor   %%xmm5,    %%xmm4\n\t"
+                       "movdqa %%xmm5,    %%xmm15\n\t"
+                       "pxor   %%xmm0,    %%xmm15\n\t"
+
+                       "movdqa %%xmm5,    %%xmm0\n\t"
+                       "pxor   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm8\n\t"
+                       "pxor   %[lxfkey], %%xmm0\n\t"
+                       "movdqa %%xmm0,    %[tmpbuf0]\n\t"
+
+                       "movdqa %%xmm10,   %%xmm0\n\t"
+                       "pxor   %%xmm5,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm9\n\t"
+                       "pxor   %[lxfkey], %%xmm0\n"
+                       "movdqa %%xmm0,    %[tmpbuf1]\n\t"
+                       : [tmpbuf0] "=m" (*(tmpbuf + 0 * BLOCKSIZE)),
+                         [tmpbuf1] "=m" (*(tmpbuf + 1 * BLOCKSIZE))
+                       : [lxfkey] "m" (*lxf_key)
+                       : "memory" );
+         asm volatile ("movdqu %[inbuf6], %%xmm10\n\t"
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "pxor   %%xmm5,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm10\n\t"
+                       "pxor   %[lxfkey], %%xmm0\n\t"
+                       "movdqa %%xmm0,    %[tmpbuf2]\n\t"
+                       : [tmpbuf2] "=m" (*(tmpbuf + 2 * BLOCKSIZE))
+                       : [inbuf6] "m" (*(inbuf + 6 * BLOCKSIZE)),
+                         [lxfkey] "m" (*lxf_key)
+                       : "memory" );
+         asm volatile ("movdqu %[l7],     %%xmm0\n\t"
+                       "pxor   %%xmm11,   %%xmm5\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       "movdqa 0x10(%[key]), %%xmm0\n\t"
+                       "movdqu %[inbuf7], %%xmm11\n\t"
+                       "pxor   %%xmm5,    %%xmm11\n\t"
+                       :
+                       : [l7] "m" (*l),
+                         [inbuf7] "m" (*(inbuf + 7 * BLOCKSIZE)),
+                         [key] "r" (ctx->keyschdec)
+                       : "memory" );
+
+         asm volatile ("cmpl $12, %[rounds]\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x20(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x30(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x40(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x50(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x60(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x70(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x80(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x90(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "jb .Ldeclast%=\n\t"
+                       "movdqa 0xa0(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xb0(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "je .Ldeclast%=\n\t"
+                       "movdqa 0xc0(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xd0(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+
+                       ".Ldeclast%=:\n\t"
+                       :
+                       : [key] "r" (ctx->keyschdec),
+                         [rounds] "r" (ctx->rounds)
+                       : "cc", "memory");
+
+         asm volatile ("aesdeclast %%xmm12,   %%xmm1\n\t"
+                       "aesdeclast %%xmm13,   %%xmm2\n\t"
+                       "aesdeclast %%xmm14,   %%xmm3\n\t"
+                       "aesdeclast %%xmm15,   %%xmm4\n\t"
+                       "aesdeclast %[tmpbuf0],%%xmm8\n\t"
+                       "aesdeclast %[tmpbuf1],%%xmm9\n\t"
+                       "aesdeclast %[tmpbuf2],%%xmm10\n\t"
+                       :
+                       : [tmpbuf0] "m" (*(tmpbuf + 0 * BLOCKSIZE)),
+                         [tmpbuf1] "m" (*(tmpbuf + 1 * BLOCKSIZE)),
+                         [tmpbuf2] "m" (*(tmpbuf + 2 * BLOCKSIZE))
+                       : "memory" );
+         asm volatile ("aesdeclast %%xmm5,    %%xmm11\n\t"
+                       "pxor   %[lxfkey], %%xmm11\n\t"
+                       "movdqu %%xmm1,    %[outbuf0]\n\t"
+                       "movdqu %%xmm2,    %[outbuf1]\n\t"
+                       : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
+                         [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
+                       : [lxfkey] "m" (*lxf_key)
+                       : "memory" );
+         asm volatile ("movdqu %%xmm3,    %[outbuf2]\n\t"
+                       "movdqu %%xmm4,    %[outbuf3]\n\t"
+                       "movdqu %%xmm8,    %[outbuf4]\n\t"
+                       : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
+                         [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE)),
+                         [outbuf4] "=m" (*(outbuf + 4 * BLOCKSIZE))
+                       :
+                       : "memory" );
+         asm volatile ("movdqu %%xmm9,    %[outbuf5]\n\t"
+                       "movdqu %%xmm10,   %[outbuf6]\n\t"
+                       "movdqu %%xmm11,   %[outbuf7]\n\t"
+                       : [outbuf5] "=m" (*(outbuf + 5 * BLOCKSIZE)),
+                         [outbuf6] "=m" (*(outbuf + 6 * BLOCKSIZE)),
+                         [outbuf7] "=m" (*(outbuf + 7 * BLOCKSIZE))
+                       :
+                       : "memory" );
+
+         outbuf += 8*BLOCKSIZE;
+         inbuf  += 8*BLOCKSIZE;
+       }
+
+      asm volatile ("pxor %[first_key], %%xmm5\n\t"
+                   "pxor %%xmm0, %%xmm0\n\t"
+                   "movdqu %%xmm0, %[lxfkey]\n\t"
+                   : [lxfkey] "=m" (*lxf_key)
+                   : [first_key] "m" (ctx->keyschdec[0][0][0])
+                   : "memory" );
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
+  for ( ;nblocks >= 4 ; nblocks -= 4 )
     {
       n += 4;
-      l = ocb_get_l(c, n);
+      l = aes_ocb_get_l(c, n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-      /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
-      /* Checksum_i = Checksum_{i-1} xor P_i  */
+      /* C_i = Offset_i xor DECIPHER(K, P_i xor Offset_i)  */
       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
                    "movdqu %[inbuf0], %%xmm1\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
-                   "pxor   %%xmm5,    %%xmm1\n\t"
-                   "movdqu %%xmm5,    %[outbuf0]\n\t"
-                   : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE))
+                   "movdqu %[l0l1],   %%xmm3\n\t"
+                   :
                    : [l0] "m" (*c->u_mode.ocb.L[0]),
+                     [l0l1] "m" (*c->u_mode.ocb.L0L1),
                      [inbuf0] "m" (*(inbuf + 0 * BLOCKSIZE))
                    : "memory" );
-      asm volatile ("movdqu %[l1],     %%xmm0\n\t"
-                   "movdqu %[inbuf1], %%xmm2\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
-                   "pxor   %%xmm5,    %%xmm2\n\t"
-                   "movdqu %%xmm5,    %[outbuf1]\n\t"
-                   : [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
+      asm volatile ("movdqu %[l1],     %%xmm4\n\t"
+                   "movdqu %[l3],     %%xmm6\n\t"
+                   "pxor   %%xmm5,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm1\n\t"
+                   "movdqa %%xmm0,    %[tmpbuf0]\n\t"
+                   : [tmpbuf0] "=m" (*(tmpbuf + 0 * BLOCKSIZE))
                    : [l1] "m" (*c->u_mode.ocb.L[1]),
-                     [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
+                     [l3] "m" (*l)
                    : "memory" );
-      asm volatile ("movdqu %[l2],     %%xmm0\n\t"
-                   "movdqu %[inbuf2], %%xmm3\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
+      asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
                    "pxor   %%xmm5,    %%xmm3\n\t"
-                   "movdqu %%xmm5,    %[outbuf2]\n\t"
-                   : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE))
-                   : [l2] "m" (*c->u_mode.ocb.L[0]),
+                   "pxor   %%xmm3,    %%xmm2\n\t"
+                   "movdqa %%xmm3,    %[tmpbuf1]\n\t"
+                   : [tmpbuf1] "=m" (*(tmpbuf + 1 * BLOCKSIZE))
+                   : [inbuf1] "m" (*(inbuf + 1 * BLOCKSIZE))
+                   : "memory" );
+      asm volatile ("movdqa %%xmm4,    %%xmm0\n\t"
+                   "movdqu %[inbuf2], %%xmm3\n\t"
+                   "pxor   %%xmm5,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm3\n\t"
+                   "movdqa %%xmm0,    %[tmpbuf2]\n\t"
+                   : [tmpbuf2] "=m" (*(tmpbuf + 2 * BLOCKSIZE))
+                   :
                      [inbuf2] "m" (*(inbuf + 2 * BLOCKSIZE))
                    : "memory" );
-      asm volatile ("movdqu %[l3],     %%xmm0\n\t"
+      asm volatile ("pxor   %%xmm6,    %%xmm5\n\t"
+                   "pxor   %%xmm4,    %%xmm5\n\t"
                    "movdqu %[inbuf3], %%xmm4\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
                    "pxor   %%xmm5,    %%xmm4\n\t"
                    :
-                   : [l3] "m" (*l),
-                     [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
+                   : [inbuf3] "m" (*(inbuf + 3 * BLOCKSIZE))
                    : "memory" );
 
       do_aesni_dec_vec4 (ctx);
 
-      asm volatile ("movdqu %[outbuf0],%%xmm0\n\t"
-                   "pxor   %%xmm0,    %%xmm1\n\t"
+      asm volatile ("pxor   %[tmpbuf0],%%xmm1\n\t"
                    "movdqu %%xmm1,    %[outbuf0]\n\t"
-                   "movdqu %[outbuf1],%%xmm0\n\t"
-                   "pxor   %%xmm0,    %%xmm2\n\t"
+                   "pxor   %[tmpbuf1],%%xmm2\n\t"
                    "movdqu %%xmm2,    %[outbuf1]\n\t"
-                   "movdqu %[outbuf2],%%xmm0\n\t"
-                   "pxor   %%xmm0,    %%xmm3\n\t"
+                   : [outbuf0] "=m" (*(outbuf + 0 * BLOCKSIZE)),
+                     [outbuf1] "=m" (*(outbuf + 1 * BLOCKSIZE))
+                   : [tmpbuf0] "m" (*(tmpbuf + 0 * BLOCKSIZE)),
+                     [tmpbuf1] "m" (*(tmpbuf + 1 * BLOCKSIZE))
+                   : "memory" );
+      asm volatile ("pxor   %[tmpbuf2],%%xmm3\n\t"
                    "movdqu %%xmm3,    %[outbuf2]\n\t"
                    "pxor   %%xmm5,    %%xmm4\n\t"
                    "movdqu %%xmm4,    %[outbuf3]\n\t"
-                   "pxor   %%xmm1,    %%xmm6\n\t"
-                   "pxor   %%xmm2,    %%xmm6\n\t"
-                   "pxor   %%xmm3,    %%xmm6\n\t"
-                   "pxor   %%xmm4,    %%xmm6\n\t"
-                   : [outbuf0] "+m" (*(outbuf + 0 * BLOCKSIZE)),
-                     [outbuf1] "+m" (*(outbuf + 1 * BLOCKSIZE)),
-                     [outbuf2] "+m" (*(outbuf + 2 * BLOCKSIZE)),
+                   : [outbuf2] "=m" (*(outbuf + 2 * BLOCKSIZE)),
                      [outbuf3] "=m" (*(outbuf + 3 * BLOCKSIZE))
-                   :
+                   : [tmpbuf2] "m" (*(tmpbuf + 2 * BLOCKSIZE))
                    : "memory" );
 
       outbuf += 4*BLOCKSIZE;
@@ -1625,7 +3651,7 @@ aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
 
   for ( ;nblocks; nblocks-- )
     {
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
@@ -1642,7 +3668,6 @@ aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
       do_aesni_dec (ctx);
 
       asm volatile ("pxor   %%xmm5, %%xmm0\n\t"
-                    "pxor   %%xmm0, %%xmm6\n\t"
                     "movdqu %%xmm0, %[outbuf]\n\t"
                     : [outbuf] "=m" (*outbuf)
                     :
@@ -1654,29 +3679,41 @@ aesni_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
 
   c->u_mode.ocb.data_nblocks = n;
   asm volatile ("movdqu %%xmm5, %[iv]\n\t"
-                "movdqu %%xmm6, %[ctr]\n\t"
-                : [iv] "=m" (*c->u_iv.iv),
-                  [ctr] "=m" (*c->u_ctr.ctr)
+                : [iv] "=m" (*c->u_iv.iv)
                 :
                 : "memory" );
 
+  asm volatile ("pxor   %%xmm0, %%xmm0\n\t"
+                "movdqa %%xmm0, %[tmpbuf0]\n\t"
+                "movdqa %%xmm0, %[tmpbuf1]\n\t"
+                "movdqa %%xmm0, %[tmpbuf2]\n\t"
+               : [tmpbuf0] "=m" (*(tmpbuf + 0 * BLOCKSIZE)),
+                 [tmpbuf1] "=m" (*(tmpbuf + 1 * BLOCKSIZE)),
+                 [tmpbuf2] "=m" (*(tmpbuf + 2 * BLOCKSIZE))
+                :
+                : "memory" );
+
+  aesni_ocb_checksum (c, outbuf_arg, nblocks_arg);
+
   aesni_cleanup ();
-  aesni_cleanup_2_6 ();
+  aesni_cleanup_2_7 ();
+
+  return 0;
 }
 
 
-void
+size_t ASM_FUNC_ATTR
 _gcry_aes_aesni_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
                           const void *inbuf_arg, size_t nblocks, int encrypt)
 {
   if (encrypt)
-    aesni_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
+    return aesni_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
   else
-    aesni_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
+    return aesni_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
 }
 
 
-void
+size_t ASM_FUNC_ATTR
 _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
                           size_t nblocks)
 {
@@ -1684,10 +3721,10 @@ _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
   const unsigned char *abuf = abuf_arg;
   u64 n = c->u_mode.ocb.aad_nblocks;
   const unsigned char *l;
-  aesni_prepare_2_6_variable;
+  aesni_prepare_2_7_variable;
 
   aesni_prepare ();
-  aesni_prepare_2_6 ();
+  aesni_prepare_2_7 ();
 
   /* Preload Offset and Sum */
   asm volatile ("movdqu %[iv], %%xmm5\n\t"
@@ -1699,7 +3736,7 @@ _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
 
   for ( ;nblocks && n % 4; nblocks-- )
     {
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
@@ -1722,44 +3759,174 @@ _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
       abuf += BLOCKSIZE;
     }
 
-  for ( ;nblocks > 3 ; nblocks -= 4 )
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      aesni_prepare_8_15_variable;
+
+      aesni_prepare_8_15();
+
+      asm volatile ("movdqu %[l0],     %%xmm7\n\t"
+                   "movdqu %[l0l1],   %%xmm12\n\t"
+                   "movdqu %[l1],     %%xmm13\n\t"
+                   :
+                   : [l0] "m" (*c->u_mode.ocb.L[0]),
+                     [l0l1] "m" (*c->u_mode.ocb.L0L1),
+                     [l1] "m" (*c->u_mode.ocb.L[1])
+                   : "memory" );
+
+      for ( ;nblocks >= 8 ; nblocks -= 8 )
+       {
+         n += 4;
+         l = aes_ocb_get_l(c, n);
+
+         asm volatile ("movdqu %[l3],   %%xmm0\n\t"
+                       "pxor   %%xmm13, %%xmm0\n\t"
+                       :
+                       : [l3] "m" (*l)
+                       : "memory" );
+
+         n += 4;
+         l = aes_ocb_get_l(c, n);
+
+         asm volatile ("movdqu %[l7],   %%xmm14\n\t"
+                       "pxor   %%xmm13, %%xmm14\n\t"
+                       :
+                       : [l7] "m" (*l)
+                       : "memory" );
+
+         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+         /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
+         asm volatile ("movdqu %[abuf0],  %%xmm1\n\t"
+                       "movdqu %[abuf1],  %%xmm2\n\t"
+                       "movdqu %[abuf2],  %%xmm3\n\t"
+                       "movdqu %[abuf3],  %%xmm4\n\t"
+                       :
+                       : [abuf0] "m" (*(abuf + 0 * BLOCKSIZE)),
+                         [abuf1] "m" (*(abuf + 1 * BLOCKSIZE)),
+                         [abuf2] "m" (*(abuf + 2 * BLOCKSIZE)),
+                         [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
+                       : "memory" );
+         asm volatile ("movdqu %[abuf4],  %%xmm8\n\t"
+                       "movdqu %[abuf5],  %%xmm9\n\t"
+                       "movdqu %[abuf6],  %%xmm10\n\t"
+                       "movdqu %[abuf7],  %%xmm11\n\t"
+                       :
+                       : [abuf4] "m" (*(abuf + 4 * BLOCKSIZE)),
+                         [abuf5] "m" (*(abuf + 5 * BLOCKSIZE)),
+                         [abuf6] "m" (*(abuf + 6 * BLOCKSIZE)),
+                         [abuf7] "m" (*(abuf + 7 * BLOCKSIZE))
+                       : "memory" );
+         asm volatile ("pxor   %%xmm7,    %%xmm1\n\t"
+                       "pxor   %%xmm5,    %%xmm1\n\t"
+
+                       "pxor   %%xmm12,   %%xmm2\n\t"
+                       "pxor   %%xmm5,    %%xmm2\n\t"
+
+                       "pxor   %%xmm13,   %%xmm3\n\t"
+                       "pxor   %%xmm5,    %%xmm3\n\t"
+
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       "movdqa (%[key]),  %%xmm0\n\t"
+                       "pxor   %%xmm5,    %%xmm4\n\t"
+
+                       "pxor   %%xmm0, %%xmm1\n\t"     /* xmm1 ^= key[0] */
+                       "pxor   %%xmm0, %%xmm2\n\t"     /* xmm2 ^= key[0] */
+                       "pxor   %%xmm0, %%xmm3\n\t"     /* xmm3 ^= key[0] */
+                       "pxor   %%xmm0, %%xmm4\n\t"     /* xmm4 ^= key[0] */
+
+                       "pxor   %%xmm7,    %%xmm8\n\t"
+                       "pxor   %%xmm5,    %%xmm8\n\t"
+
+                       "pxor   %%xmm12,   %%xmm9\n\t"
+                       "pxor   %%xmm5,    %%xmm9\n\t"
+
+                       "pxor   %%xmm13,   %%xmm10\n\t"
+                       "pxor   %%xmm5,    %%xmm10\n\t"
+
+                       "pxor   %%xmm14,   %%xmm5\n\t"
+                       "pxor   %%xmm5,    %%xmm11\n\t"
+
+                       "pxor   %%xmm0, %%xmm8\n\t"     /* xmm8 ^= key[0] */
+                       "pxor   %%xmm0, %%xmm9\n\t"     /* xmm9 ^= key[0] */
+                       "pxor   %%xmm0, %%xmm10\n\t"    /* xmm10 ^= key[0] */
+                       "pxor   %%xmm0, %%xmm11\n\t"    /* xmm11 ^= key[0] */
+                       :
+                       : [key] "r" (ctx->keyschenc)
+                       : "memory" );
+
+         do_aesni_enc_vec8 (ctx);
+
+         asm volatile (
+                       "aesenclast %%xmm0, %%xmm1\n\t"
+                       "aesenclast %%xmm0, %%xmm2\n\t"
+                       "aesenclast %%xmm0, %%xmm3\n\t"
+                       "aesenclast %%xmm0, %%xmm4\n\t"
+                       "aesenclast %%xmm0, %%xmm8\n\t"
+                       "aesenclast %%xmm0, %%xmm9\n\t"
+                       "aesenclast %%xmm0, %%xmm10\n\t"
+                       "aesenclast %%xmm0, %%xmm11\n\t"
+                       "pxor   %%xmm2,   %%xmm1\n\t"
+                       "pxor   %%xmm3,   %%xmm1\n\t"
+                       "pxor   %%xmm4,   %%xmm1\n\t"
+                       "pxor   %%xmm8,   %%xmm1\n\t"
+                       "pxor   %%xmm9,   %%xmm6\n\t"
+                       "pxor   %%xmm10,  %%xmm6\n\t"
+                       "pxor   %%xmm11,  %%xmm6\n\t"
+                       "pxor   %%xmm1,   %%xmm6\n\t"
+                       :
+                       :
+                       : "memory" );
+
+         abuf += 8*BLOCKSIZE;
+       }
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
+  for ( ;nblocks >= 4 ; nblocks -= 4 )
     {
       n += 4;
-      l = ocb_get_l(c, n);
+      l = aes_ocb_get_l(c, n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
       asm volatile ("movdqu %[l0],     %%xmm0\n\t"
                    "movdqu %[abuf0],  %%xmm1\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
-                   "pxor   %%xmm5,    %%xmm1\n\t"
+                   "movdqu %[l0l1],   %%xmm3\n\t"
                    :
                    : [l0] "m" (*c->u_mode.ocb.L[0]),
+                     [l0l1] "m" (*c->u_mode.ocb.L0L1),
                      [abuf0] "m" (*(abuf + 0 * BLOCKSIZE))
                    : "memory" );
-      asm volatile ("movdqu %[l1],     %%xmm0\n\t"
-                   "movdqu %[abuf1],  %%xmm2\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
-                   "pxor   %%xmm5,    %%xmm2\n\t"
+      asm volatile ("movdqu %[l1],     %%xmm4\n\t"
+                   "movdqu %[l3],     %%xmm7\n\t"
+                   "pxor   %%xmm5,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm1\n\t"
                    :
                    : [l1] "m" (*c->u_mode.ocb.L[1]),
-                     [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
+                     [l3] "m" (*l)
                    : "memory" );
-      asm volatile ("movdqu %[l2],     %%xmm0\n\t"
-                   "movdqu %[abuf2],  %%xmm3\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
+      asm volatile ("movdqu %[abuf1],  %%xmm2\n\t"
                    "pxor   %%xmm5,    %%xmm3\n\t"
+                   "pxor   %%xmm3,    %%xmm2\n\t"
                    :
-                   : [l2] "m" (*c->u_mode.ocb.L[0]),
-                     [abuf2] "m" (*(abuf + 2 * BLOCKSIZE))
+                   : [abuf1] "m" (*(abuf + 1 * BLOCKSIZE))
                    : "memory" );
-      asm volatile ("movdqu %[l3],     %%xmm0\n\t"
+      asm volatile ("movdqa %%xmm4,    %%xmm0\n\t"
+                   "movdqu %[abuf2],  %%xmm3\n\t"
+                   "pxor   %%xmm5,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm3\n\t"
+                   :
+                   : [abuf2] "m" (*(abuf + 2 * BLOCKSIZE))
+                   : "memory" );
+      asm volatile ("pxor   %%xmm7,    %%xmm5\n\t"
+                   "pxor   %%xmm4,    %%xmm5\n\t"
                    "movdqu %[abuf3],  %%xmm4\n\t"
-                   "pxor   %%xmm0,    %%xmm5\n\t"
                    "pxor   %%xmm5,    %%xmm4\n\t"
                    :
-                   : [l3] "m" (*l),
-                     [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
+                   : [abuf3] "m" (*(abuf + 3 * BLOCKSIZE))
                    : "memory" );
 
       do_aesni_enc_vec4 (ctx);
@@ -1777,7 +3944,7 @@ _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
 
   for ( ;nblocks; nblocks-- )
     {
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
@@ -1809,8 +3976,905 @@ _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
                 : "memory" );
 
   aesni_cleanup ();
-  aesni_cleanup_2_6 ();
+  aesni_cleanup_2_7 ();
+
+  return 0;
 }
 
 
+static const u64 xts_gfmul_const[2] __attribute__ ((aligned (16))) =
+  { 0x87, 0x01 };
+
+
+static void ASM_FUNC_ATTR
+_gcry_aes_aesni_xts_enc (RIJNDAEL_context *ctx, unsigned char *tweak,
+                        unsigned char *outbuf, const unsigned char *inbuf,
+                        size_t nblocks)
+{
+  aesni_prepare_2_7_variable;
+
+  aesni_prepare ();
+  aesni_prepare_2_7 ();
+
+  /* Preload Tweak */
+  asm volatile ("movdqu %[tweak], %%xmm5\n\t"
+               "movdqa %[gfmul], %%xmm6\n\t"
+               :
+               : [tweak] "m" (*tweak),
+                 [gfmul] "m" (*xts_gfmul_const)
+               : "memory" );
+
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      aesni_prepare_8_15_variable;
+
+      aesni_prepare_8_15();
+
+      for ( ;nblocks >= 8 ; nblocks -= 8 )
+       {
+         asm volatile ("pshufd $0x13,     %%xmm5,  %%xmm11\n\t"
+                       "movdqu %[inbuf0], %%xmm1\n\t"
+                       "pxor   %%xmm5,    %%xmm1\n\t"
+                       "movdqa %%xmm5,    %%xmm7\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf0] "m" (*(inbuf + 0 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
+                       "pxor   %%xmm5,    %%xmm2\n\t"
+                       "movdqa %%xmm5,    %%xmm12\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf1] "m" (*(inbuf + 1 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
+                       "pxor   %%xmm5,    %%xmm3\n\t"
+                       "movdqa %%xmm5,    %%xmm13\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf2] "m" (*(inbuf + 2 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf3], %%xmm4\n\t"
+                       "pxor   %%xmm5,    %%xmm4\n\t"
+                       "movdqa %%xmm5,    %%xmm14\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf3] "m" (*(inbuf + 3 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf4], %%xmm8\n\t"
+                       "pxor   %%xmm5,    %%xmm8\n\t"
+                       "movdqa %%xmm5,    %%xmm15\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf4] "m" (*(inbuf + 4 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf5], %%xmm9\n\t"
+                       "pxor   %%xmm5,    %%xmm9\n\t"
+                       "movdqu %%xmm5,    %[outbuf5]\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       : [outbuf5] "=m" (*(outbuf + 5 * 16))
+                       : [inbuf5] "m" (*(inbuf + 5 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf6], %%xmm10\n\t"
+                       "pxor   %%xmm5,    %%xmm10\n\t"
+                       "movdqu %%xmm5,    %[outbuf6]\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       : [outbuf6] "=m" (*(outbuf + 6 * 16))
+                       : [inbuf6] "m" (*(inbuf + 6 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqa %%xmm11,   %%xmm0\n\t"
+                       "movdqu %[inbuf7], %%xmm11\n\t"
+                       "pxor   %%xmm5,    %%xmm11\n\t"
+                       "movdqu %%xmm5,    %[outbuf7]\n\t"
+
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       : [outbuf7] "=m" (*(outbuf + 7 * 16))
+                       : [inbuf7] "m" (*(inbuf + 7 * 16))
+                       : "memory" );
+
+         asm volatile ("cmpl $12, %[rounds]\n\t"
+                       "movdqa (%[key]), %%xmm0\n\t"
+                       "pxor %%xmm0, %%xmm1\n\t"
+                       "pxor %%xmm0, %%xmm2\n\t"
+                       "pxor %%xmm0, %%xmm3\n\t"
+                       "pxor %%xmm0, %%xmm4\n\t"
+                       "pxor %%xmm0, %%xmm8\n\t"
+                       "pxor %%xmm0, %%xmm9\n\t"
+                       "pxor %%xmm0, %%xmm10\n\t"
+                       "pxor %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x10(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x20(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x30(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x40(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x50(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x60(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x70(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x80(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x90(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xa0(%[key]), %%xmm0\n\t"
+                       "jb .Lenclast%=\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xb0(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xc0(%[key]), %%xmm0\n\t"
+                       "je .Lenclast%=\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xd0(%[key]), %%xmm0\n\t"
+                       "aesenc %%xmm0, %%xmm1\n\t"
+                       "aesenc %%xmm0, %%xmm2\n\t"
+                       "aesenc %%xmm0, %%xmm3\n\t"
+                       "aesenc %%xmm0, %%xmm4\n\t"
+                       "aesenc %%xmm0, %%xmm8\n\t"
+                       "aesenc %%xmm0, %%xmm9\n\t"
+                       "aesenc %%xmm0, %%xmm10\n\t"
+                       "aesenc %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xe0(%[key]), %%xmm0\n\t"
+
+                       ".Lenclast%=:\n\t"
+                       :
+                       : [key] "r" (ctx->keyschenc),
+                         [rounds] "rm" (ctx->rounds)
+                       : "cc", "memory");
+
+         asm volatile ("pxor %%xmm0, %%xmm7\n\t"
+                       "pxor %%xmm0, %%xmm12\n\t"
+                       "pxor %%xmm0, %%xmm13\n\t"
+                       "pxor %%xmm0, %%xmm14\n\t"
+                       "aesenclast %%xmm7, %%xmm1\n\t"
+                       "aesenclast %%xmm12, %%xmm2\n\t"
+                       "aesenclast %%xmm13, %%xmm3\n\t"
+                       "aesenclast %%xmm14, %%xmm4\n\t"
+                       "movdqu 5*16(%[outbuf]), %%xmm12\n\t"
+                       "movdqu 6*16(%[outbuf]), %%xmm13\n\t"
+                       "movdqu 7*16(%[outbuf]), %%xmm14\n\t"
+                       "pxor %%xmm0, %%xmm15\n\t"
+                       "pxor %%xmm0, %%xmm12\n\t"
+                       "pxor %%xmm0, %%xmm13\n\t"
+                       "pxor %%xmm0, %%xmm14\n\t"
+                       "aesenclast %%xmm15, %%xmm8\n\t"
+                       "aesenclast %%xmm12, %%xmm9\n\t"
+                       "aesenclast %%xmm13, %%xmm10\n\t"
+                       "aesenclast %%xmm14, %%xmm11\n\t"
+                       "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
+                       "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
+                       "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
+                       "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
+                       "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
+                       "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
+                       "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
+                       "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
+                       :
+                       : [outbuf] "r" (outbuf)
+                       : "memory" );
+
+         outbuf += 8*BLOCKSIZE;
+         inbuf  += 8*BLOCKSIZE;
+       }
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
+  for ( ;nblocks >= 4; nblocks -= 4 )
+    {
+      asm volatile ("pshufd $0x13,     %%xmm5,  %%xmm4\n\t"
+                   "movdqu %[inbuf0], %%xmm1\n\t"
+                   "pxor   %%xmm5,    %%xmm1\n\t"
+                   "movdqu %%xmm5,    %[outbuf0]\n\t"
+
+                   "movdqa %%xmm4,    %%xmm0\n\t"
+                   "paddd  %%xmm4,    %%xmm4\n\t"
+                   "psrad  $31,       %%xmm0\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm5\n\t"
+                   : [outbuf0] "=m" (*(outbuf + 0 * 16))
+                   : [inbuf0] "m" (*(inbuf + 0 * 16))
+                   : "memory" );
+
+      asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
+                   "pxor   %%xmm5,    %%xmm2\n\t"
+                   "movdqu %%xmm5,    %[outbuf1]\n\t"
+
+                   "movdqa %%xmm4,    %%xmm0\n\t"
+                   "paddd  %%xmm4,    %%xmm4\n\t"
+                   "psrad  $31,       %%xmm0\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm5\n\t"
+                   : [outbuf1] "=m" (*(outbuf + 1 * 16))
+                   : [inbuf1] "m" (*(inbuf + 1 * 16))
+                   : "memory" );
+
+      asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
+                   "pxor   %%xmm5,    %%xmm3\n\t"
+                   "movdqu %%xmm5,    %[outbuf2]\n\t"
+
+                   "movdqa %%xmm4,    %%xmm0\n\t"
+                   "paddd  %%xmm4,    %%xmm4\n\t"
+                   "psrad  $31,       %%xmm0\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm5\n\t"
+                   : [outbuf2] "=m" (*(outbuf + 2 * 16))
+                   : [inbuf2] "m" (*(inbuf + 2 * 16))
+                   : "memory" );
+
+      asm volatile ("movdqa %%xmm4,    %%xmm0\n\t"
+                   "movdqu %[inbuf3], %%xmm4\n\t"
+                   "pxor   %%xmm5,    %%xmm4\n\t"
+                   "movdqu %%xmm5,    %[outbuf3]\n\t"
+
+                   "psrad  $31,       %%xmm0\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm5\n\t"
+                   : [outbuf3] "=m" (*(outbuf + 3 * 16))
+                   : [inbuf3] "m" (*(inbuf + 3 * 16))
+                   : "memory" );
+
+      do_aesni_enc_vec4 (ctx);
+
+      asm volatile ("movdqu %[outbuf0], %%xmm0\n\t"
+                    "pxor   %%xmm0,     %%xmm1\n\t"
+                   "movdqu %[outbuf1], %%xmm0\n\t"
+                   "movdqu %%xmm1,     %[outbuf0]\n\t"
+                   "movdqu %[outbuf2], %%xmm1\n\t"
+                    "pxor   %%xmm0,     %%xmm2\n\t"
+                   "movdqu %[outbuf3], %%xmm0\n\t"
+                    "pxor   %%xmm1,     %%xmm3\n\t"
+                    "pxor   %%xmm0,     %%xmm4\n\t"
+                   "movdqu %%xmm2,     %[outbuf1]\n\t"
+                   "movdqu %%xmm3,     %[outbuf2]\n\t"
+                   "movdqu %%xmm4,     %[outbuf3]\n\t"
+                   : [outbuf0] "+m" (*(outbuf + 0 * 16)),
+                     [outbuf1] "+m" (*(outbuf + 1 * 16)),
+                     [outbuf2] "+m" (*(outbuf + 2 * 16)),
+                     [outbuf3] "+m" (*(outbuf + 3 * 16))
+                   :
+                   : "memory" );
+
+      outbuf += BLOCKSIZE * 4;
+      inbuf += BLOCKSIZE * 4;
+    }
+
+  for ( ;nblocks; nblocks-- )
+    {
+      asm volatile ("movdqu %[inbuf],  %%xmm0\n\t"
+                   "pxor   %%xmm5,    %%xmm0\n\t"
+                   "movdqa %%xmm5,    %%xmm4\n\t"
+
+                   "pshufd $0x13,     %%xmm5,  %%xmm1\n\t"
+                   "psrad  $31,       %%xmm1\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm1\n\t"
+                   "pxor   %%xmm1,    %%xmm5\n\t"
+                   :
+                   : [inbuf] "m" (*inbuf)
+                   : "memory" );
+
+      do_aesni_enc (ctx);
+
+      asm volatile ("pxor   %%xmm4,    %%xmm0\n\t"
+                   "movdqu %%xmm0,    %[outbuf]\n\t"
+                   : [outbuf] "=m" (*outbuf)
+                   :
+                   : "memory" );
+
+      outbuf += BLOCKSIZE;
+      inbuf += BLOCKSIZE;
+    }
+
+  asm volatile ("movdqu %%xmm5, %[tweak]\n\t"
+               : [tweak] "=m" (*tweak)
+               :
+               : "memory" );
+
+  aesni_cleanup ();
+  aesni_cleanup_2_7 ();
+}
+
+
+static void ASM_FUNC_ATTR
+_gcry_aes_aesni_xts_dec (RIJNDAEL_context *ctx, unsigned char *tweak,
+                        unsigned char *outbuf, const unsigned char *inbuf,
+                        size_t nblocks)
+{
+  aesni_prepare_2_7_variable;
+
+  aesni_prepare ();
+  aesni_prepare_2_7 ();
+
+  if ( !ctx->decryption_prepared )
+    {
+      do_aesni_prepare_decryption ( ctx );
+      ctx->decryption_prepared = 1;
+    }
+
+  /* Preload Tweak */
+  asm volatile ("movdqu %[tweak], %%xmm5\n\t"
+               "movdqa %[gfmul], %%xmm6\n\t"
+               :
+               : [tweak] "m" (*tweak),
+                 [gfmul] "m" (*xts_gfmul_const)
+               : "memory" );
+
+#ifdef __x86_64__
+  if (nblocks >= 8)
+    {
+      aesni_prepare_8_15_variable;
+
+      aesni_prepare_8_15();
+
+      for ( ;nblocks >= 8 ; nblocks -= 8 )
+       {
+         asm volatile ("pshufd $0x13,     %%xmm5,  %%xmm11\n\t"
+                       "movdqu %[inbuf0], %%xmm1\n\t"
+                       "pxor   %%xmm5,    %%xmm1\n\t"
+                       "movdqa %%xmm5,    %%xmm7\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf0] "m" (*(inbuf + 0 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
+                       "pxor   %%xmm5,    %%xmm2\n\t"
+                       "movdqa %%xmm5,    %%xmm12\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf1] "m" (*(inbuf + 1 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
+                       "pxor   %%xmm5,    %%xmm3\n\t"
+                       "movdqa %%xmm5,    %%xmm13\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf2] "m" (*(inbuf + 2 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf3], %%xmm4\n\t"
+                       "pxor   %%xmm5,    %%xmm4\n\t"
+                       "movdqa %%xmm5,    %%xmm14\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf3] "m" (*(inbuf + 3 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf4], %%xmm8\n\t"
+                       "pxor   %%xmm5,    %%xmm8\n\t"
+                       "movdqa %%xmm5,    %%xmm15\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       :
+                       : [inbuf4] "m" (*(inbuf + 4 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf5], %%xmm9\n\t"
+                       "pxor   %%xmm5,    %%xmm9\n\t"
+                       "movdqu %%xmm5,    %[outbuf5]\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       : [outbuf5] "=m" (*(outbuf + 5 * 16))
+                       : [inbuf5] "m" (*(inbuf + 5 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqu %[inbuf6], %%xmm10\n\t"
+                       "pxor   %%xmm5,    %%xmm10\n\t"
+                       "movdqu %%xmm5,    %[outbuf6]\n\t"
+
+                       "movdqa %%xmm11,   %%xmm0\n\t"
+                       "paddd  %%xmm11,   %%xmm11\n\t"
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       : [outbuf6] "=m" (*(outbuf + 6 * 16))
+                       : [inbuf6] "m" (*(inbuf + 6 * 16))
+                       : "memory" );
+
+         asm volatile ("movdqa %%xmm11,   %%xmm0\n\t"
+                       "movdqu %[inbuf7], %%xmm11\n\t"
+                       "pxor   %%xmm5,    %%xmm11\n\t"
+                       "movdqu %%xmm5,    %[outbuf7]\n\t"
+
+                       "psrad  $31,       %%xmm0\n\t"
+                       "paddq  %%xmm5,    %%xmm5\n\t"
+                       "pand   %%xmm6,    %%xmm0\n\t"
+                       "pxor   %%xmm0,    %%xmm5\n\t"
+                       : [outbuf7] "=m" (*(outbuf + 7 * 16))
+                       : [inbuf7] "m" (*(inbuf + 7 * 16))
+                       : "memory" );
+
+         asm volatile ("cmpl $12, %[rounds]\n\t"
+                       "movdqa (%[key]), %%xmm0\n\t"
+                       "pxor %%xmm0, %%xmm1\n\t"
+                       "pxor %%xmm0, %%xmm2\n\t"
+                       "pxor %%xmm0, %%xmm3\n\t"
+                       "pxor %%xmm0, %%xmm4\n\t"
+                       "pxor %%xmm0, %%xmm8\n\t"
+                       "pxor %%xmm0, %%xmm9\n\t"
+                       "pxor %%xmm0, %%xmm10\n\t"
+                       "pxor %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x10(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x20(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x30(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x40(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x50(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x60(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x70(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x80(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0x90(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xa0(%[key]), %%xmm0\n\t"
+                       "jb .Ldeclast%=\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xb0(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xc0(%[key]), %%xmm0\n\t"
+                       "je .Ldeclast%=\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xd0(%[key]), %%xmm0\n\t"
+                       "aesdec %%xmm0, %%xmm1\n\t"
+                       "aesdec %%xmm0, %%xmm2\n\t"
+                       "aesdec %%xmm0, %%xmm3\n\t"
+                       "aesdec %%xmm0, %%xmm4\n\t"
+                       "aesdec %%xmm0, %%xmm8\n\t"
+                       "aesdec %%xmm0, %%xmm9\n\t"
+                       "aesdec %%xmm0, %%xmm10\n\t"
+                       "aesdec %%xmm0, %%xmm11\n\t"
+                       "movdqa 0xe0(%[key]), %%xmm0\n\t"
+
+                       ".Ldeclast%=:\n\t"
+                       :
+                       : [key] "r" (ctx->keyschdec),
+                         [rounds] "rm" (ctx->rounds)
+                       : "cc", "memory");
+
+         asm volatile ("pxor %%xmm0, %%xmm7\n\t"
+                       "pxor %%xmm0, %%xmm12\n\t"
+                       "pxor %%xmm0, %%xmm13\n\t"
+                       "pxor %%xmm0, %%xmm14\n\t"
+                       "aesdeclast %%xmm7, %%xmm1\n\t"
+                       "aesdeclast %%xmm12, %%xmm2\n\t"
+                       "aesdeclast %%xmm13, %%xmm3\n\t"
+                       "aesdeclast %%xmm14, %%xmm4\n\t"
+                       "movdqu 5*16(%[outbuf]), %%xmm12\n\t"
+                       "movdqu 6*16(%[outbuf]), %%xmm13\n\t"
+                       "movdqu 7*16(%[outbuf]), %%xmm14\n\t"
+                       "pxor %%xmm0, %%xmm15\n\t"
+                       "pxor %%xmm0, %%xmm12\n\t"
+                       "pxor %%xmm0, %%xmm13\n\t"
+                       "pxor %%xmm0, %%xmm14\n\t"
+                       "aesdeclast %%xmm15, %%xmm8\n\t"
+                       "aesdeclast %%xmm12, %%xmm9\n\t"
+                       "aesdeclast %%xmm13, %%xmm10\n\t"
+                       "aesdeclast %%xmm14, %%xmm11\n\t"
+                       "movdqu %%xmm1, 0*16(%[outbuf])\n\t"
+                       "movdqu %%xmm2, 1*16(%[outbuf])\n\t"
+                       "movdqu %%xmm3, 2*16(%[outbuf])\n\t"
+                       "movdqu %%xmm4, 3*16(%[outbuf])\n\t"
+                       "movdqu %%xmm8, 4*16(%[outbuf])\n\t"
+                       "movdqu %%xmm9, 5*16(%[outbuf])\n\t"
+                       "movdqu %%xmm10, 6*16(%[outbuf])\n\t"
+                       "movdqu %%xmm11, 7*16(%[outbuf])\n\t"
+                       :
+                       : [outbuf] "r" (outbuf)
+                       : "memory" );
+
+         outbuf += 8*BLOCKSIZE;
+         inbuf  += 8*BLOCKSIZE;
+       }
+
+      aesni_cleanup_8_15();
+    }
+#endif
+
+  for ( ;nblocks >= 4; nblocks -= 4 )
+    {
+      asm volatile ("pshufd $0x13,     %%xmm5,  %%xmm4\n\t"
+                   "movdqu %[inbuf0], %%xmm1\n\t"
+                   "pxor   %%xmm5,    %%xmm1\n\t"
+                   "movdqu %%xmm5,    %[outbuf0]\n\t"
+
+                   "movdqa %%xmm4,    %%xmm0\n\t"
+                   "paddd  %%xmm4,    %%xmm4\n\t"
+                   "psrad  $31,       %%xmm0\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm5\n\t"
+                   : [outbuf0] "=m" (*(outbuf + 0 * 16))
+                   : [inbuf0] "m" (*(inbuf + 0 * 16))
+                   : "memory" );
+
+      asm volatile ("movdqu %[inbuf1], %%xmm2\n\t"
+                   "pxor   %%xmm5,    %%xmm2\n\t"
+                   "movdqu %%xmm5,    %[outbuf1]\n\t"
+
+                   "movdqa %%xmm4,    %%xmm0\n\t"
+                   "paddd  %%xmm4,    %%xmm4\n\t"
+                   "psrad  $31,       %%xmm0\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm5\n\t"
+                   : [outbuf1] "=m" (*(outbuf + 1 * 16))
+                   : [inbuf1] "m" (*(inbuf + 1 * 16))
+                   : "memory" );
+
+      asm volatile ("movdqu %[inbuf2], %%xmm3\n\t"
+                   "pxor   %%xmm5,    %%xmm3\n\t"
+                   "movdqu %%xmm5,    %[outbuf2]\n\t"
+
+                   "movdqa %%xmm4,    %%xmm0\n\t"
+                   "paddd  %%xmm4,    %%xmm4\n\t"
+                   "psrad  $31,       %%xmm0\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm5\n\t"
+                   : [outbuf2] "=m" (*(outbuf + 2 * 16))
+                   : [inbuf2] "m" (*(inbuf + 2 * 16))
+                   : "memory" );
+
+      asm volatile ("movdqa %%xmm4,    %%xmm0\n\t"
+                   "movdqu %[inbuf3], %%xmm4\n\t"
+                   "pxor   %%xmm5,    %%xmm4\n\t"
+                   "movdqu %%xmm5,    %[outbuf3]\n\t"
+
+                   "psrad  $31,       %%xmm0\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm0\n\t"
+                   "pxor   %%xmm0,    %%xmm5\n\t"
+                   : [outbuf3] "=m" (*(outbuf + 3 * 16))
+                   : [inbuf3] "m" (*(inbuf + 3 * 16))
+                   : "memory" );
+
+      do_aesni_dec_vec4 (ctx);
+
+      asm volatile ("movdqu %[outbuf0], %%xmm0\n\t"
+                    "pxor   %%xmm0,     %%xmm1\n\t"
+                   "movdqu %[outbuf1], %%xmm0\n\t"
+                   "movdqu %%xmm1,     %[outbuf0]\n\t"
+                   "movdqu %[outbuf2], %%xmm1\n\t"
+                    "pxor   %%xmm0,     %%xmm2\n\t"
+                   "movdqu %[outbuf3], %%xmm0\n\t"
+                    "pxor   %%xmm1,     %%xmm3\n\t"
+                    "pxor   %%xmm0,     %%xmm4\n\t"
+                   "movdqu %%xmm2,     %[outbuf1]\n\t"
+                   "movdqu %%xmm3,     %[outbuf2]\n\t"
+                   "movdqu %%xmm4,     %[outbuf3]\n\t"
+                   : [outbuf0] "+m" (*(outbuf + 0 * 16)),
+                     [outbuf1] "+m" (*(outbuf + 1 * 16)),
+                     [outbuf2] "+m" (*(outbuf + 2 * 16)),
+                     [outbuf3] "+m" (*(outbuf + 3 * 16))
+                   :
+                   : "memory" );
+
+      outbuf += BLOCKSIZE * 4;
+      inbuf += BLOCKSIZE * 4;
+    }
+
+  for ( ;nblocks; nblocks-- )
+    {
+      asm volatile ("movdqu %[inbuf],  %%xmm0\n\t"
+                   "pxor   %%xmm5,    %%xmm0\n\t"
+                   "movdqa %%xmm5,    %%xmm4\n\t"
+
+                   "pshufd $0x13,     %%xmm5,  %%xmm1\n\t"
+                   "psrad  $31,       %%xmm1\n\t"
+                   "paddq  %%xmm5,    %%xmm5\n\t"
+                   "pand   %%xmm6,    %%xmm1\n\t"
+                   "pxor   %%xmm1,    %%xmm5\n\t"
+                   :
+                   : [inbuf] "m" (*inbuf)
+                   : "memory" );
+
+      do_aesni_dec (ctx);
+
+      asm volatile ("pxor   %%xmm4,    %%xmm0\n\t"
+                   "movdqu %%xmm0,    %[outbuf]\n\t"
+                   : [outbuf] "=m" (*outbuf)
+                   :
+                   : "memory" );
+
+      outbuf += BLOCKSIZE;
+      inbuf += BLOCKSIZE;
+    }
+
+  asm volatile ("movdqu %%xmm5, %[tweak]\n\t"
+                : [tweak] "=m" (*tweak)
+                :
+                : "memory" );
+
+  aesni_cleanup ();
+  aesni_cleanup_2_7 ();
+}
+
+
+void ASM_FUNC_ATTR
+_gcry_aes_aesni_xts_crypt (RIJNDAEL_context *ctx, unsigned char *tweak,
+                          unsigned char *outbuf, const unsigned char *inbuf,
+                          size_t nblocks, int encrypt)
+{
+  if (encrypt)
+    _gcry_aes_aesni_xts_enc(ctx, tweak, outbuf, inbuf, nblocks);
+  else
+    _gcry_aes_aesni_xts_dec(ctx, tweak, outbuf, inbuf, nblocks);
+}
+
+#if __clang__
+#  pragma clang attribute pop
+#endif
+
 #endif /* USE_AESNI */
index b149e94..6e3cc81 100644 (file)
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_AES)
 
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -222,12 +212,19 @@ _gcry_aes_amd64_encrypt_block:
         *      %ecx: number of rounds.. 10, 12 or 14
         *      %r8:  encryption tables
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_5
+
        subq $(5 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(5 * 8);
        movq %rsi, (0 * 8)(%rsp);
        movl %ecx, (1 * 8)(%rsp);
        movq %rbp, (2 * 8)(%rsp);
        movq %rbx, (3 * 8)(%rsp);
        movq %r12, (4 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 2 * 8);
+       CFI_REL_OFFSET(%rbx, 3 * 8);
+       CFI_REL_OFFSET(%r12, 4 * 8);
 
        leaq (%r8), RTAB;
 
@@ -259,14 +256,23 @@ _gcry_aes_amd64_encrypt_block:
        movl RCd, 2 * 4(%rsi);
        movl RDd, 3 * 4(%rsi);
 
+       CFI_REMEMBER_STATE();
+
        movq (4 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %rbx;
        movq (2 * 8)(%rsp), %rbp;
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%rbp);
        addq $(5 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-5 * 8);
 
        movl $(6 * 8), %eax;
-       ret;
 
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+
+       CFI_RESTORE_STATE();
 .align 4
 .Lenc_not_128:
        je .Lenc_192
@@ -286,6 +292,7 @@ _gcry_aes_amd64_encrypt_block:
        lastencround(11);
 
        jmp .Lenc_done;
+       CFI_ENDPROC();
 ELF(.size _gcry_aes_amd64_encrypt_block,.-_gcry_aes_amd64_encrypt_block;)
 
 #define do_decround(next_r) \
@@ -382,12 +389,19 @@ _gcry_aes_amd64_decrypt_block:
         *      %ecx: number of rounds.. 10, 12 or 14
         *      %r8:  decryption tables
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_5
+
        subq $(5 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(5 * 8);
        movq %rsi, (0 * 8)(%rsp);
        movl %ecx, (1 * 8)(%rsp);
        movq %rbp, (2 * 8)(%rsp);
        movq %rbx, (3 * 8)(%rsp);
        movq %r12, (4 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 2 * 8);
+       CFI_REL_OFFSET(%rbx, 3 * 8);
+       CFI_REL_OFFSET(%r12, 4 * 8);
 
        leaq (%r8), RTAB;
 
@@ -420,14 +434,23 @@ _gcry_aes_amd64_decrypt_block:
        movl RCd, 2 * 4(%rsi);
        movl RDd, 3 * 4(%rsi);
 
+       CFI_REMEMBER_STATE();
+
        movq (4 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %rbx;
        movq (2 * 8)(%rsp), %rbp;
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%rbp);
        addq $(5 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-5 * 8);
 
        movl $(6 * 8), %eax;
-       ret;
 
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+
+       CFI_RESTORE_STATE();
 .align 4
 .Ldec_256:
        je .Ldec_192;
@@ -447,6 +470,7 @@ _gcry_aes_amd64_decrypt_block:
        decround(9);
 
        jmp .Ldec_tail;
+       CFI_ENDPROC();
 ELF(.size _gcry_aes_amd64_decrypt_block,.-_gcry_aes_amd64_decrypt_block;)
 
 #endif /*USE_AES*/
index 5c8fa3c..1eafa93 100644 (file)
 
 /* Other functional macros */
 
-#define CLEAR_REG(reg) veor reg, reg;
+#define CLEAR_REG(reg) vmov.i8 reg, #0;
 
 
 /*
@@ -1017,6 +1017,127 @@ _gcry_aes_ctr_enc_armv8_ce:
 
 
 /*
+ * void _gcry_aes_ctr32le_enc_armv8_ce (const void *keysched,
+ *                                      unsigned char *outbuf,
+ *                                      const unsigned char *inbuf,
+ *                                      unsigned char *iv,
+ *                                      unsigned int nrounds);
+ */
+
+.align 3
+.globl _gcry_aes_ctr32le_enc_armv8_ce
+.type  _gcry_aes_ctr32le_enc_armv8_ce,%function;
+_gcry_aes_ctr32le_enc_armv8_ce:
+  /* input:
+   *    r0: keysched
+   *    r1: outbuf
+   *    r2: inbuf
+   *    r3: iv
+   *    %st+0: nblocks => r4
+   *    %st+4: nrounds => r5
+   */
+
+  vpush {q4-q7}
+  push {r4-r12,lr} /* 4*16 + 4*10 = 104b */
+  ldr r4, [sp, #(104+0)]
+  ldr r5, [sp, #(104+4)]
+  cmp r4, #0
+  beq .Lctr32le_enc_skip
+
+  cmp r5, #12
+  vld1.8 {q0}, [r3] /* load IV */
+
+  aes_preload_keys(r0, r6);
+
+  beq .Lctr32le_enc_entry_192
+  bhi .Lctr32le_enc_entry_256
+
+#define CTR_ENC(bits, ...) \
+  .Lctr32le_enc_entry_##bits: \
+    cmp r4, #4; \
+    blo .Lctr32le_enc_loop_##bits; \
+    \
+  .Lctr32le_enc_loop4_##bits: \
+    veor q2, q2; \
+    sub r4, r4, #4; \
+    vmov.i64 d4, #0xffffffff; /* q2 <= -1:0:0:0 */ \
+    vmov q1, q0; \
+    vadd.u32 q3, q2, q2; /* q3 <= -2:0:0:0 */ \
+    vadd.u32 q0, q3, q3; /* q0 <= -4:0:0:0 */ \
+    vadd.u32 q4, q3, q2; /* q4 <= -3:0:0:0 */ \
+    vsub.u32 q0, q1, q0; \
+    vsub.u32 q2, q1, q2; \
+    vst1.8 {q0}, [r3]; \
+    vsub.u32 q3, q1, q3; \
+    vsub.u32 q4, q1, q4; \
+    \
+    cmp r4, #4; \
+    vld1.8 {q0}, [r2]!; /* load ciphertext */ \
+    \
+    do_aes_4_##bits(e, mc, q1, q2, q3, q4, ##__VA_ARGS__); \
+    \
+    veor q1, q1, q0; \
+    vld1.8 {q0}, [r2]!; /* load ciphertext */ \
+    vst1.8 {q1}, [r1]!; /* store plaintext */ \
+    vld1.8 {q1}, [r2]!; /* load ciphertext */ \
+    veor q2, q2, q0; \
+    veor q3, q3, q1; \
+    vld1.8 {q0}, [r2]!; /* load ciphertext */ \
+    vst1.8 {q2}, [r1]!; /* store plaintext */ \
+    veor q4, q4, q0; \
+    vld1.8 {q0}, [r3]; /* reload IV */ \
+    vst1.8 {q3-q4}, [r1]!; /* store plaintext */ \
+    \
+    bhs .Lctr32le_enc_loop4_##bits; \
+    cmp r4, #0; \
+    beq .Lctr32le_enc_done; \
+    \
+  .Lctr32le_enc_loop_##bits: \
+    \
+    veor q2, q2; \
+    vmov q1, q0; \
+    vmov.i64 d4, #0xffffffff; /* q2 <= -1:0:0:0 */ \
+    subs r4, r4, #1; \
+    vsub.u32 q0, q0, q2; \
+    vld1.8 {q2}, [r2]!; /* load ciphertext */ \
+    \
+    do_aes_one##bits(e, mc, q1, q1, ##__VA_ARGS__); \
+    \
+    veor q1, q2, q1; \
+    vst1.8 {q1}, [r1]!; /* store plaintext */ \
+    \
+    bne .Lctr32le_enc_loop_##bits; \
+    b .Lctr32le_enc_done;
+
+  CTR_ENC(128)
+  CTR_ENC(192, r0, r6)
+  CTR_ENC(256, r0, r6)
+
+#undef CTR_ENC
+
+.Lctr32le_enc_done:
+  vst1.8 {q0}, [r3] /* store IV */
+
+  CLEAR_REG(q0)
+  CLEAR_REG(q1)
+  CLEAR_REG(q2)
+  CLEAR_REG(q3)
+  CLEAR_REG(q8)
+  CLEAR_REG(q9)
+  CLEAR_REG(q10)
+  CLEAR_REG(q11)
+  CLEAR_REG(q12)
+  CLEAR_REG(q13)
+  CLEAR_REG(q14)
+
+.Lctr32le_enc_skip:
+  pop {r4-r12,lr}
+  vpop {q4-q7}
+  bx lr
+.size _gcry_aes_ctr32le_enc_armv8_ce,.-_gcry_aes_ctr32le_enc_armv8_ce;
+
+
+/*
  * void _gcry_aes_ocb_enc_armv8_ce (const void *keysched,
  *                                  unsigned char *outbuf,
  *                                  const unsigned char *inbuf,
@@ -1517,6 +1638,317 @@ _gcry_aes_ocb_auth_armv8_ce:
 .size _gcry_aes_ocb_auth_armv8_ce,.-_gcry_aes_ocb_auth_armv8_ce;
 
 
+
+/*
+ * void _gcry_aes_xts_enc_armv8_ce (const void *keysched,
+ *                                  unsigned char *outbuf,
+ *                                  const unsigned char *inbuf,
+ *                                  unsigned char *iv, unsigned int nrounds);
+ */
+
+.align 3
+.globl _gcry_aes_xts_enc_armv8_ce
+.type  _gcry_aes_xts_enc_armv8_ce,%function;
+_gcry_aes_xts_enc_armv8_ce:
+  /* input:
+   *    r0: keysched
+   *    r1: outbuf
+   *    r2: inbuf
+   *    r3: iv
+   *    %st+0: nblocks => r4
+   *    %st+4: nrounds => r5
+   */
+
+  vpush {q4-q7}
+  push {r4-r12,lr} /* 4*16 + 4*10 = 104b */
+  ldr r4, [sp, #(104+0)]
+  ldr r5, [sp, #(104+4)]
+  cmp r4, #0
+  beq .Lxts_enc_skip
+
+  cmp r5, #12
+
+  vld1.8 {q0}, [r3] /* load tweak */
+  mov r7, #0x87;
+
+  aes_preload_keys(r0, r6);
+
+  beq .Lxts_enc_entry_192
+  bhi .Lxts_enc_entry_256
+
+#define CTR_XTS(bits, ...) \
+  .Lxts_enc_entry_##bits: \
+    cmp r4, #4; \
+    blo .Lxts_enc_loop_##bits; \
+    \
+  .Lxts_enc_loop4_##bits: \
+    sub r4, r4, #4; \
+    veor q9, q9, q9; \
+    \
+    vld1.8 {q1-q2}, [r2]!; /* load plaintext */ \
+    veor q1, q1, q0; \
+    cmp r4, #4; \
+    vmov.u32 d18[0], r7; \
+    vst1.8 {q0}, [r1]!; /* store tweak0 to temp */ \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    \
+    vld1.8 {q3-q4}, [r2]!; /* load plaintext */ \
+    veor q2, q2, q0; \
+    vst1.8 {q0}, [r1]!; /* store tweak1 to temp */ \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    \
+    veor q3, q3, q0; \
+    vst1.8 {q0}, [r1]!; /* store tweak2 to temp */ \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    \
+    veor q4, q4, q0; \
+    vst1.8 {q0}, [r1]; /* store tweak3 to temp */ \
+    sub r1, r1, #48; \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    \
+    do_aes_4_##bits(e, mc, q1, q2, q3, q4, ##__VA_ARGS__); \
+    \
+    vld1.8 {q8-q9}, [r1]!; /* load tweak from temp */ \
+    veor q1, q1, q8; \
+    veor q2, q2, q9; \
+    vld1.8 {q8-q9}, [r1]; /* load tweak from temp */ \
+    sub r1, r1, #32; \
+    veor q3, q3, q8; \
+    veor q4, q4, q9; \
+    vst1.8 {q1-q2}, [r1]!; /* store plaintext */ \
+    vst1.8 {q3-q4}, [r1]!; /* store plaintext */ \
+    \
+    bhs .Lxts_enc_loop4_##bits; \
+    cmp r4, #0; \
+    beq .Lxts_enc_done; \
+    \
+  .Lxts_enc_loop_##bits: \
+    \
+    vld1.8 {q1}, [r2]!; /* load ciphertext */ \
+    \
+    veor q9, q9, q9; \
+    veor q1, q1, q0; \
+    vmov.u32 d18[0], r7; \
+    vmov q2, q0; \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    subs r4, r4, #1; \
+    \
+    do_aes_one##bits(e, mc, q1, q1, ##__VA_ARGS__); \
+    \
+    veor q1, q1, q2; \
+    vst1.8 {q1}, [r1]!; /* store plaintext */ \
+    \
+    bne .Lxts_enc_loop_##bits; \
+    b .Lxts_enc_done;
+
+  CTR_XTS(128re, r0, r6)
+  CTR_XTS(192, r0, r6)
+  CTR_XTS(256, r0, r6)
+
+#undef CTR_XTS
+
+.Lxts_enc_done:
+  vst1.8 {q0}, [r3] /* store tweak */
+
+  CLEAR_REG(q0)
+  CLEAR_REG(q1)
+  CLEAR_REG(q2)
+  CLEAR_REG(q3)
+  CLEAR_REG(q8)
+  CLEAR_REG(q9)
+  CLEAR_REG(q10)
+  CLEAR_REG(q11)
+  CLEAR_REG(q12)
+  CLEAR_REG(q13)
+  CLEAR_REG(q14)
+
+.Lxts_enc_skip:
+  pop {r4-r12,lr}
+  vpop {q4-q7}
+  bx lr
+.size _gcry_aes_xts_enc_armv8_ce,.-_gcry_aes_xts_enc_armv8_ce;
+
+
+/*
+ * void _gcry_aes_xts_dec_armv8_ce (const void *keysched,
+ *                                  unsigned char *outbuf,
+ *                                  const unsigned char *inbuf,
+ *                                  unsigned char *iv, unsigned int nrounds);
+ */
+
+.align 3
+.globl _gcry_aes_xts_dec_armv8_ce
+.type  _gcry_aes_xts_dec_armv8_ce,%function;
+_gcry_aes_xts_dec_armv8_ce:
+  /* input:
+   *    r0: keysched
+   *    r1: outbuf
+   *    r2: inbuf
+   *    r3: iv
+   *    %st+0: nblocks => r4
+   *    %st+4: nrounds => r5
+   */
+
+  vpush {q4-q7}
+  push {r4-r12,lr} /* 4*16 + 4*10 = 104b */
+  ldr r4, [sp, #(104+0)]
+  ldr r5, [sp, #(104+4)]
+  cmp r4, #0
+  beq .Lxts_dec_skip
+
+  cmp r5, #12
+
+  vld1.8 {q0}, [r3] /* load tweak */
+  mov r7, #0x87;
+
+  aes_preload_keys(r0, r6);
+
+  beq .Lxts_dec_entry_192
+  bhi .Lxts_dec_entry_256
+
+#define CTR_XTS(bits, ...) \
+  .Lxts_dec_entry_##bits: \
+    cmp r4, #4; \
+    blo .Lxts_dec_loop_##bits; \
+    \
+  .Lxts_dec_loop4_##bits: \
+    sub r4, r4, #4; \
+    veor q9, q9, q9; \
+    \
+    vld1.8 {q1-q2}, [r2]!; /* load plaintext */ \
+    veor q1, q1, q0; \
+    cmp r4, #4; \
+    vmov.u32 d18[0], r7; \
+    vst1.8 {q0}, [r1]!; /* store tweak0 to temp */ \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    \
+    vld1.8 {q3-q4}, [r2]!; /* load plaintext */ \
+    veor q2, q2, q0; \
+    vst1.8 {q0}, [r1]!; /* store tweak1 to temp */ \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    \
+    veor q3, q3, q0; \
+    vst1.8 {q0}, [r1]!; /* store tweak2 to temp */ \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    \
+    veor q4, q4, q0; \
+    vst1.8 {q0}, [r1]; /* store tweak3 to temp */ \
+    sub r1, r1, #48; \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    \
+    do_aes_4_##bits(d, imc, q1, q2, q3, q4, ##__VA_ARGS__); \
+    \
+    vld1.8 {q8-q9}, [r1]!; /* load tweak from temp */ \
+    veor q1, q1, q8; \
+    veor q2, q2, q9; \
+    vld1.8 {q8-q9}, [r1]; /* load tweak from temp */ \
+    sub r1, r1, #32; \
+    veor q3, q3, q8; \
+    veor q4, q4, q9; \
+    vst1.8 {q1-q2}, [r1]!; /* store plaintext */ \
+    vst1.8 {q3-q4}, [r1]!; /* store plaintext */ \
+    \
+    bhs .Lxts_dec_loop4_##bits; \
+    cmp r4, #0; \
+    beq .Lxts_dec_done; \
+    \
+  .Lxts_dec_loop_##bits: \
+    \
+    vld1.8 {q1}, [r2]!; /* load ciphertext */ \
+    \
+    veor q9, q9, q9; \
+    veor q1, q1, q0; \
+    vmov.u32 d18[0], r7; \
+    vmov q2, q0; \
+    \
+    vshr.s64 d16, d1, #63; \
+    vshr.u64 d17, d0, #63; \
+    vadd.u64 q0, q0, q0; \
+    vand d16, d16, d18; \
+    veor q0, q0, q8; \
+    subs r4, r4, #1; \
+    \
+    do_aes_one##bits(d, imc, q1, q1, ##__VA_ARGS__); \
+    \
+    veor q1, q1, q2; \
+    vst1.8 {q1}, [r1]!; /* store plaintext */ \
+    \
+    bne .Lxts_dec_loop_##bits; \
+    b .Lxts_dec_done;
+
+  CTR_XTS(128re, r0, r6)
+  CTR_XTS(192, r0, r6)
+  CTR_XTS(256, r0, r6)
+
+#undef CTR_XTS
+
+.Lxts_dec_done:
+  vst1.8 {q0}, [r3] /* store tweak */
+
+  CLEAR_REG(q0)
+  CLEAR_REG(q1)
+  CLEAR_REG(q2)
+  CLEAR_REG(q3)
+  CLEAR_REG(q8)
+  CLEAR_REG(q9)
+  CLEAR_REG(q10)
+  CLEAR_REG(q11)
+  CLEAR_REG(q12)
+  CLEAR_REG(q13)
+  CLEAR_REG(q14)
+
+.Lxts_dec_skip:
+  pop {r4-r12,lr}
+  vpop {q4-q7}
+  bx lr
+.size _gcry_aes_xts_dec_armv8_ce,.-_gcry_aes_xts_dec_armv8_ce;
+
+
 /*
  * u32 _gcry_aes_sbox4_armv8_ce(u32 in4b);
  */
index 708ef34..4fef034 100644 (file)
@@ -17,7 +17,7 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "asm-common-aarch64.h"
 
 #if defined(__AARCH64EL__) && \
     defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
 .text
 
 
-#define GET_DATA_POINTER(reg, name) \
-       adrp    reg, :got:name ; \
-       ldr     reg, [reg, #:got_lo12:name] ;
-
-
 /* Register macros */
 
 #define vk0 v17
 #define vk11 v28
 #define vk12 v29
 #define vk13 v30
-#define vk14 v31
+#define vklast v31
+
+
+/* Helper macros */
+
+#define __ /*_*/
+#define _(...) __VA_ARGS__
 
 
 /* AES macros */
        ld1 {vk0.16b-vk3.16b}, [keysched], #64; \
        ld1 {vk4.16b-vk7.16b}, [keysched], #64; \
        ld1 {vk8.16b-vk10.16b}, [keysched], #48; \
+       mov vklast.16b, vk10.16b; \
        b.lo 1f; \
        ld1 {vk11.16b-vk12.16b}, [keysched], #32; \
+       mov vklast.16b, vk12.16b; \
        b.eq 1f; \
-       ld1 {vk13.16b-vk14.16b}, [keysched]; \
+       ld1 {vk13.16b-vklast.16b}, [keysched]; \
 1:     ;
 
-#define do_aes_one128(ed, mcimc, vo, vb) \
-       aes##ed    vb.16b, vk0.16b; \
+#define do_aes_one_part1(ed, mcimc, vb, vkfirst) \
+       aes##ed    vb.16b, vkfirst.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk1.16b; \
-       aes##mcimc vb.16b, vb.16b; \
+       aes##mcimc vb.16b, vb.16b;
+
+#define do_aes_one_part2_128(ed, mcimc, vb, iop1, iop2) \
        aes##ed    vb.16b, vk2.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk3.16b; \
        aes##mcimc vb.16b, vb.16b; \
+       iop1; \
        aes##ed    vb.16b, vk4.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk5.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk6.16b; \
        aes##mcimc vb.16b, vb.16b; \
+       iop2; \
        aes##ed    vb.16b, vk7.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk8.16b; \
        aes##mcimc vb.16b, vb.16b; \
-       aes##ed    vb.16b, vk9.16b; \
-       eor        vo.16b, vb.16b, vk10.16b;
+       aes##ed    vb.16b, vk9.16b;
 
-#define do_aes_one192(ed, mcimc, vo, vb) \
-       aes##ed    vb.16b, vk0.16b; \
-       aes##mcimc vb.16b, vb.16b; \
-       aes##ed    vb.16b, vk1.16b; \
-       aes##mcimc vb.16b, vb.16b; \
+#define do_aes_one_part2_192(ed, mcimc, vb, iop1, iop2) \
        aes##ed    vb.16b, vk2.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk3.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk5.16b; \
        aes##mcimc vb.16b, vb.16b; \
+       iop1; \
        aes##ed    vb.16b, vk6.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk7.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk8.16b; \
        aes##mcimc vb.16b, vb.16b; \
+       iop2; \
        aes##ed    vb.16b, vk9.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk10.16b; \
        aes##mcimc vb.16b, vb.16b; \
-       aes##ed    vb.16b, vk11.16b; \
-       eor        vo.16b, vb.16b, vk12.16b;
+       aes##ed    vb.16b, vk11.16b;
 
-#define do_aes_one256(ed, mcimc, vo, vb) \
-       aes##ed    vb.16b, vk0.16b; \
-       aes##mcimc vb.16b, vb.16b; \
-       aes##ed    vb.16b, vk1.16b; \
-       aes##mcimc vb.16b, vb.16b; \
+#define do_aes_one_part2_256(ed, mcimc, vb, iop1, iop2) \
        aes##ed    vb.16b, vk2.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk3.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk7.16b; \
        aes##mcimc vb.16b, vb.16b; \
+       iop1; \
        aes##ed    vb.16b, vk8.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk9.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk10.16b; \
        aes##mcimc vb.16b, vb.16b; \
+       iop2; \
        aes##ed    vb.16b, vk11.16b; \
        aes##mcimc vb.16b, vb.16b; \
        aes##ed    vb.16b, vk12.16b; \
        aes##mcimc vb.16b, vb.16b; \
-       aes##ed    vb.16b, vk13.16b; \
-       eor        vo.16b, vb.16b, vk14.16b;
+       aes##ed    vb.16b, vk13.16b;
 
-#define aes_round_4(ed, mcimc, b0, b1, b2, b3, key) \
-       aes##ed    b0.16b, key.16b; \
+#define do_aes_one128(ed, mcimc, vo, vb, vkfirst) \
+       do_aes_one_part1(ed, mcimc, vb, vkfirst); \
+       do_aes_one_part2_128(ed, mcimc, vb, __, __); \
+       eor vo.16b, vb.16b, vklast.16b;
+
+#define do_aes_one192(ed, mcimc, vo, vb, vkfirst) \
+       do_aes_one_part1(ed, mcimc, vb, vkfirst); \
+       do_aes_one_part2_192(ed, mcimc, vb, __, __); \
+       eor vo.16b, vb.16b, vklast.16b;
+
+#define do_aes_one256(ed, mcimc, vo, vb, vkfirst) \
+       do_aes_one_part1(ed, mcimc, vb, vkfirst); \
+       do_aes_one_part2_256(ed, mcimc, vb, __, __); \
+       eor vo.16b, vb.16b, vklast.16b;
+
+#define aes_round_4_multikey(ed, mcimc, b0, b1, b2, b3, key0, key1, key2, key3) \
+       aes##ed    b0.16b, key0.16b; \
        aes##mcimc b0.16b, b0.16b; \
-         aes##ed    b1.16b, key.16b; \
+         aes##ed    b1.16b, key1.16b; \
          aes##mcimc b1.16b, b1.16b; \
-           aes##ed    b2.16b, key.16b; \
+           aes##ed    b2.16b, key2.16b; \
            aes##mcimc b2.16b, b2.16b; \
-             aes##ed    b3.16b, key.16b; \
+             aes##ed    b3.16b, key3.16b; \
              aes##mcimc b3.16b, b3.16b;
 
-#define aes_lastround_4(ed, b0, b1, b2, b3, key1, key2) \
+#define aes_round_4(ed, mcimc, b0, b1, b2, b3, key) \
+       aes_round_4_multikey(ed, mcimc, b0, b1, b2, b3, key, key, key, key);
+
+#define aes_lastround_4(ed, o0, o1, o2, o3, b0, b1, b2, b3, key1, b0_key2, b1_key2, b2_key2, b3_key2) \
        aes##ed    b0.16b, key1.16b; \
-       eor        b0.16b, b0.16b, key2.16b; \
          aes##ed    b1.16b, key1.16b; \
-         eor        b1.16b, b1.16b, key2.16b; \
            aes##ed    b2.16b, key1.16b; \
-           eor        b2.16b, b2.16b, key2.16b; \
              aes##ed    b3.16b, key1.16b; \
-             eor        b3.16b, b3.16b, key2.16b;
+       eor        o0.16b, b0.16b, b0_key2.16b; \
+         eor        o1.16b, b1.16b, b1_key2.16b; \
+           eor        o2.16b, b2.16b, b2_key2.16b; \
+             eor        o3.16b, b3.16b, b3_key2.16b;
 
-#define do_aes_4_128(ed, mcimc, b0, b1, b2, b3) \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk0); \
+#define do_aes_4_part1_multikey(ed, mcimc, b0, b1, b2, b3, key0, key1, key2, key3) \
+       aes_round_4_multikey(ed, mcimc, b0, b1, b2, b3, key0, key1, key2, key3); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk1); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk2); \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk3); \
+       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk3);
+
+#define do_aes_4_part1(ed, mcimc, b0, b1, b2, b3, vkfirst) \
+       do_aes_4_part1_multikey(ed, mcimc, b0, b1, b2, b3, vkfirst, vkfirst, vkfirst, vkfirst);
+
+#define do_aes_4_part2_128(ed, mcimc, o0, o1, o2, o3, b0, b1, b2, b3, \
+                          b0_key, b1_key, b2_key, b3_key) \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk4); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk5); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk6); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk7); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk8); \
-       aes_lastround_4(ed, b0, b1, b2, b3, vk9, vk10);
+       aes_lastround_4(ed, o0, o1, o2, o3, b0, b1, b2, b3, vk9, b0_key, b1_key, b2_key, b3_key);
 
-#define do_aes_4_192(ed, mcimc, b0, b1, b2, b3) \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk0); \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk1); \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk2); \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk3); \
+#define do_aes_4_part2_192(ed, mcimc, o0, o1, o2, o3, b0, b1, b2, b3, \
+                          b0_key, b1_key, b2_key, b3_key) \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk4); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk5); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk6); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk8); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk9); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk10); \
-       aes_lastround_4(ed, b0, b1, b2, b3, vk11, vk12);
+       aes_lastround_4(ed, o0, o1, o2, o3, b0, b1, b2, b3, vk11, b0_key, b1_key, b2_key, b3_key);
 
-#define do_aes_4_256(ed, mcimc, b0, b1, b2, b3) \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk0); \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk1); \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk2); \
-       aes_round_4(ed, mcimc, b0, b1, b2, b3, vk3); \
+#define do_aes_4_part2_256(ed, mcimc, o0, o1, o2, o3, b0, b1, b2, b3, \
+                          b0_key, b1_key, b2_key, b3_key) \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk4); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk5); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk6); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk10); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk11); \
        aes_round_4(ed, mcimc, b0, b1, b2, b3, vk12); \
-       aes_lastround_4(ed, b0, b1, b2, b3, vk13, vk14);
+       aes_lastround_4(ed, o0, o1, o2, o3, b0, b1, b2, b3, vk13, b0_key, b1_key, b2_key, b3_key);
+
+#define do_aes_4_128(ed, mcimc, b0, b1, b2, b3) \
+       do_aes_4_part1(ed, mcimc, b0, b1, b2, b3, vk0); \
+       do_aes_4_part2_128(ed, mcimc, b0, b1, b2, b3, b0, b1, b2, b3, vklast, vklast, vklast, vklast);
+
+#define do_aes_4_192(ed, mcimc, b0, b1, b2, b3) \
+       do_aes_4_part1(ed, mcimc, b0, b1, b2, b3, vk0); \
+       do_aes_4_part2_192(ed, mcimc, b0, b1, b2, b3, b0, b1, b2, b3, vklast, vklast, vklast, vklast);
 
+#define do_aes_4_256(ed, mcimc, b0, b1, b2, b3) \
+       do_aes_4_part1(ed, mcimc, b0, b1, b2, b3, vk0); \
+       do_aes_4_part2_256(ed, mcimc, b0, b1, b2, b3, b0, b1, b2, b3, vklast, vklast, vklast, vklast);
 
 /* Other functional macros */
 
-#define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
+#define CLEAR_REG(reg) movi reg.16b, #0;
 
 #define aes_clear_keys(nrounds) \
-       cmp nrounds, #12; \
        CLEAR_REG(vk0); \
        CLEAR_REG(vk1); \
        CLEAR_REG(vk2); \
        CLEAR_REG(vk9); \
        CLEAR_REG(vk8); \
        CLEAR_REG(vk10); \
-       b.lo 1f; \
        CLEAR_REG(vk11); \
        CLEAR_REG(vk12); \
-       b.eq 1f; \
        CLEAR_REG(vk13); \
-       CLEAR_REG(vk14); \
-1:     ;
+       CLEAR_REG(vklast);
 
 
 /*
  */
 .align 3
 .globl _gcry_aes_enc_armv8_ce
-.type  _gcry_aes_enc_armv8_ce,%function;
+ELF(.type  _gcry_aes_enc_armv8_ce,%function;)
 _gcry_aes_enc_armv8_ce:
   /* input:
    *    x0: keysched
@@ -247,6 +272,7 @@ _gcry_aes_enc_armv8_ce:
    *    x2: src
    *    w3: nrounds
    */
+  CFI_STARTPROC();
 
   aes_preload_keys(x0, w3);
 
@@ -256,7 +282,7 @@ _gcry_aes_enc_armv8_ce:
   b.eq .Lenc1_192
 
 .Lenc1_128:
-  do_aes_one128(e, mc, v0, v0);
+  do_aes_one128(e, mc, v0, v0, vk0);
 
 .Lenc1_tail:
   CLEAR_REG(vk0)
@@ -270,28 +296,29 @@ _gcry_aes_enc_armv8_ce:
   CLEAR_REG(vk8)
   CLEAR_REG(vk9)
   CLEAR_REG(vk10)
+  CLEAR_REG(vklast)
   st1 {v0.16b}, [x1]
   CLEAR_REG(v0)
 
   mov x0, #0
-  ret
+  ret_spec_stop
 
 .Lenc1_192:
-  do_aes_one192(e, mc, v0, v0);
+  do_aes_one192(e, mc, v0, v0, vk0);
 
   CLEAR_REG(vk11)
   CLEAR_REG(vk12)
   b .Lenc1_tail
 
 .Lenc1_256:
-  do_aes_one256(e, mc, v0, v0);
+  do_aes_one256(e, mc, v0, v0, vk0);
 
   CLEAR_REG(vk11)
   CLEAR_REG(vk12)
   CLEAR_REG(vk13)
-  CLEAR_REG(vk14)
   b .Lenc1_tail
-.size _gcry_aes_enc_armv8_ce,.-_gcry_aes_enc_armv8_ce;
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_enc_armv8_ce,.-_gcry_aes_enc_armv8_ce;)
 
 
 /*
@@ -301,7 +328,7 @@ _gcry_aes_enc_armv8_ce:
  */
 .align 3
 .globl _gcry_aes_dec_armv8_ce
-.type  _gcry_aes_dec_armv8_ce,%function;
+ELF(.type  _gcry_aes_dec_armv8_ce,%function;)
 _gcry_aes_dec_armv8_ce:
   /* input:
    *    x0: keysched
@@ -309,6 +336,7 @@ _gcry_aes_dec_armv8_ce:
    *    x2: src
    *    w3: nrounds
    */
+  CFI_STARTPROC();
 
   aes_preload_keys(x0, w3);
 
@@ -318,7 +346,7 @@ _gcry_aes_dec_armv8_ce:
   b.eq .Ldec1_192
 
 .Ldec1_128:
-  do_aes_one128(d, imc, v0, v0);
+  do_aes_one128(d, imc, v0, v0, vk0);
 
 .Ldec1_tail:
   CLEAR_REG(vk0)
@@ -332,28 +360,29 @@ _gcry_aes_dec_armv8_ce:
   CLEAR_REG(vk8)
   CLEAR_REG(vk9)
   CLEAR_REG(vk10)
+  CLEAR_REG(vklast)
   st1 {v0.16b}, [x1]
   CLEAR_REG(v0)
 
   mov x0, #0
-  ret
+  ret_spec_stop
 
 .Ldec1_192:
-  do_aes_one192(d, imc, v0, v0);
+  do_aes_one192(d, imc, v0, v0, vk0);
 
   CLEAR_REG(vk11)
   CLEAR_REG(vk12)
   b .Ldec1_tail
 
 .Ldec1_256:
-  do_aes_one256(d, imc, v0, v0);
+  do_aes_one256(d, imc, v0, v0, vk0);
 
   CLEAR_REG(vk11)
   CLEAR_REG(vk12)
   CLEAR_REG(vk13)
-  CLEAR_REG(vk14)
   b .Ldec1_tail
-.size _gcry_aes_dec_armv8_ce,.-_gcry_aes_dec_armv8_ce;
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_dec_armv8_ce,.-_gcry_aes_dec_armv8_ce;)
 
 
 /*
@@ -366,7 +395,7 @@ _gcry_aes_dec_armv8_ce:
 
 .align 3
 .globl _gcry_aes_cbc_enc_armv8_ce
-.type  _gcry_aes_cbc_enc_armv8_ce,%function;
+ELF(.type  _gcry_aes_cbc_enc_armv8_ce,%function;)
 _gcry_aes_cbc_enc_armv8_ce:
   /* input:
    *    x0: keysched
@@ -377,30 +406,43 @@ _gcry_aes_cbc_enc_armv8_ce:
    *    w5: cbc_mac
    *    w6: nrounds
    */
+  CFI_STARTPROC();
 
   cbz x4, .Lcbc_enc_skip
 
   cmp w5, #0
-  ld1 {v1.16b}, [x3] /* load IV */
-  cset x5, eq
+  ld1 {v4.16b}, [x3] /* load IV */
+  csetm x5, eq
 
   aes_preload_keys(x0, w6);
-  lsl x5, x5, #4
+  and x5, x5, #16
+
+  ld1 {v3.16b}, [x2], #16; /* load plaintext */
+  mov v0.16b, vk0.16b;
+  sub x4, x4, #1;
+  eor v16.16b, vk0.16b, vklast.16b;
+  eor v4.16b, v4.16b, v3.16b;
+  do_aes_one_part1(e, mc, v4, v0);
 
-  b.eq .Lcbc_enc_loop192
-  b.hi .Lcbc_enc_loop256
+  b.eq .Lcbc_enc_entry_192
+  b.hi .Lcbc_enc_entry_256
 
 #define CBC_ENC(bits) \
-  .Lcbc_enc_loop##bits: \
-    ld1 {v0.16b}, [x2], #16; /* load plaintext */ \
-    eor v1.16b, v0.16b, v1.16b; \
-    sub x4, x4, #1; \
+  .Lcbc_enc_entry_##bits: \
+    cbz x4, .Lcbc_enc_done_##bits; \
     \
-    do_aes_one##bits(e, mc, v1, v1); \
-    \
-    st1 {v1.16b}, [x1], x5; /* store ciphertext */ \
+  .Lcbc_enc_loop_##bits: \
+    do_aes_one_part2_##bits(e, mc, v4, \
+                            _(ld1 {v0.16b}, [x2], #16 /* load plaintext */), \
+                            _(eor v0.16b, v0.16b, v16.16b)); \
+    sub x4, x4, #1; \
+    eor v3.16b, v4.16b, vklast.16b; \
+    do_aes_one_part1(e, mc, v4, v0); \
+    st1 {v3.16b}, [x1], x5; /* store ciphertext */ \
+    cbnz x4, .Lcbc_enc_loop_##bits; \
     \
-    cbnz x4, .Lcbc_enc_loop##bits; \
+  .Lcbc_enc_done_##bits: \
+    do_aes_one_part2_##bits(e, mc, v4, __, __); \
     b .Lcbc_enc_done;
 
   CBC_ENC(128)
@@ -410,16 +452,20 @@ _gcry_aes_cbc_enc_armv8_ce:
 #undef CBC_ENC
 
 .Lcbc_enc_done:
+  eor v3.16b, v4.16b, vklast.16b;
+  st1 {v3.16b}, [x1]; /* store ciphertext */
   aes_clear_keys(w6)
+  st1 {v3.16b}, [x3] /* store IV */
 
-  st1 {v1.16b}, [x3] /* store IV */
-
-  CLEAR_REG(v1)
+  CLEAR_REG(v16)
+  CLEAR_REG(v4)
+  CLEAR_REG(v3)
   CLEAR_REG(v0)
 
 .Lcbc_enc_skip:
-  ret
-.size _gcry_aes_cbc_enc_armv8_ce,.-_gcry_aes_cbc_enc_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_cbc_enc_armv8_ce,.-_gcry_aes_cbc_enc_armv8_ce;)
 
 /*
  * void _gcry_aes_cbc_dec_armv8_ce (const void *keysched,
@@ -430,7 +476,7 @@ _gcry_aes_cbc_enc_armv8_ce:
 
 .align 3
 .globl _gcry_aes_cbc_dec_armv8_ce
-.type  _gcry_aes_cbc_dec_armv8_ce,%function;
+ELF(.type  _gcry_aes_cbc_dec_armv8_ce,%function;)
 _gcry_aes_cbc_dec_armv8_ce:
   /* input:
    *    x0: keysched
@@ -440,10 +486,14 @@ _gcry_aes_cbc_dec_armv8_ce:
    *    x4: nblocks
    *    w5: nrounds
    */
+  CFI_STARTPROC();
 
   cbz x4, .Lcbc_dec_skip
 
-  ld1 {v0.16b}, [x3] /* load IV */
+  add sp, sp, #-64;
+  CFI_ADJUST_CFA_OFFSET(64);
+
+  ld1 {v16.16b}, [x3] /* load IV */
 
   aes_preload_keys(x0, w5);
 
@@ -455,44 +505,61 @@ _gcry_aes_cbc_dec_armv8_ce:
     cmp x4, #4; \
     b.lo .Lcbc_dec_loop_##bits; \
     \
-  .Lcbc_dec_loop4_##bits: \
-    \
-    ld1 {v1.16b-v4.16b}, [x2], #64; /* load ciphertext */ \
+    ld1 {v0.16b-v3.16b}, [x2], #64; /* load ciphertext */ \
+    cmp x4, #8; \
     sub x4, x4, #4; \
-    mov v5.16b, v1.16b; \
-    mov v6.16b, v2.16b; \
-    mov v7.16b, v3.16b; \
-    mov v16.16b, v4.16b; \
-    cmp x4, #4; \
+    eor v4.16b, v16.16b, vklast.16b; \
+    eor v5.16b, v0.16b, vklast.16b; \
+    eor v6.16b, v1.16b, vklast.16b; \
+    eor v7.16b, v2.16b, vklast.16b; \
+    mov v16.16b, v3.16b; /* next IV */ \
     \
-    do_aes_4_##bits(d, imc, v1, v2, v3, v4); \
+    do_aes_4_part1(d, imc, v0, v1, v2, v3, vk0); \
+    b.lo .Lcbc_dec_done4_##bits; \
     \
-    eor v1.16b, v1.16b, v0.16b; \
-    eor v2.16b, v2.16b, v5.16b; \
-    st1 {v1.16b-v2.16b}, [x1], #32; /* store plaintext */ \
-    eor v3.16b, v3.16b, v6.16b; \
-    eor v4.16b, v4.16b, v7.16b; \
-    mov v0.16b, v16.16b; /* next IV */ \
-    st1 {v3.16b-v4.16b}, [x1], #32; /* store plaintext */ \
+    st1 {v8.16b-v11.16b}, [sp]; /* store callee saved registers */ \
+    \
+  .Lcbc_dec_loop4_##bits: \
+    do_aes_4_part2_##bits(d, imc, v8, v9, v10, v11, v0, v1, v2, v3, v4, v5, v6, v7); \
+    ld1 {v0.16b-v3.16b}, [x2], #64; /* load ciphertext */ \
+    cmp x4, #8; \
+    sub x4, x4, #4; \
+    eor v4.16b, v16.16b, vklast.16b; \
+    eor v5.16b, v0.16b, vklast.16b; \
+    eor v6.16b, v1.16b, vklast.16b; \
+    eor v7.16b, v2.16b, vklast.16b; \
+    mov v16.16b, v3.16b; /* next IV */ \
+    \
+    do_aes_4_part1(d, imc, v0, v1, v2, v3, vk0); \
+    st1 {v8.16b-v11.16b}, [x1], #64; /* store plaintext */ \
     \
     b.hs .Lcbc_dec_loop4_##bits; \
-    CLEAR_REG(v3); \
+    \
+    ld1 {v8.16b-v11.16b}, [sp]; /* restore callee saved registers */ \
+    \
+  .Lcbc_dec_done4_##bits: \
+    do_aes_4_part2_##bits(d, imc, v0, v1, v2, v3, v0, v1, v2, v3, v4, v5, v6, v7); \
+    \
     CLEAR_REG(v4); \
     CLEAR_REG(v5); \
     CLEAR_REG(v6); \
     CLEAR_REG(v7); \
-    CLEAR_REG(v16); \
+    st1 {v0.16b-v3.16b}, [x1], #64; /* store plaintext */ \
+    CLEAR_REG(v0); \
+    CLEAR_REG(v3); \
     cbz x4, .Lcbc_dec_done; \
     \
   .Lcbc_dec_loop_##bits: \
     ld1 {v1.16b}, [x2], #16; /* load ciphertext */ \
     sub x4, x4, #1; \
+    eor v16.16b, v16.16b, vklast.16b; \
     mov v2.16b, v1.16b; \
     \
-    do_aes_one##bits(d, imc, v1, v1); \
+    do_aes_one_part1(d, imc, v1, vk0); \
+    do_aes_one_part2_##bits(d, imc, v1, __, __); \
+    eor v1.16b, v1.16b, v16.16b; \
     \
-    eor v1.16b, v1.16b, v0.16b; \
-    mov v0.16b, v2.16b; \
+    mov v16.16b, v2.16b; \
     st1 {v1.16b}, [x1], #16; /* store plaintext */ \
     \
     cbnz x4, .Lcbc_dec_loop_##bits; \
@@ -507,15 +574,19 @@ _gcry_aes_cbc_dec_armv8_ce:
 .Lcbc_dec_done:
   aes_clear_keys(w5)
 
-  st1 {v0.16b}, [x3] /* store IV */
+  st1 {v16.16b}, [x3] /* store IV */
 
-  CLEAR_REG(v0)
+  CLEAR_REG(v16)
   CLEAR_REG(v1)
   CLEAR_REG(v2)
 
+  add sp, sp, #64;
+  CFI_ADJUST_CFA_OFFSET(-64);
+
 .Lcbc_dec_skip:
-  ret
-.size _gcry_aes_cbc_dec_armv8_ce,.-_gcry_aes_cbc_dec_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_cbc_dec_armv8_ce,.-_gcry_aes_cbc_dec_armv8_ce;)
 
 
 /*
@@ -527,7 +598,7 @@ _gcry_aes_cbc_dec_armv8_ce:
 
 .align 3
 .globl _gcry_aes_ctr_enc_armv8_ce
-.type  _gcry_aes_ctr_enc_armv8_ce,%function;
+ELF(.type  _gcry_aes_ctr_enc_armv8_ce,%function;)
 _gcry_aes_ctr_enc_armv8_ce:
   /* input:
    *    r0: keysched
@@ -537,12 +608,17 @@ _gcry_aes_ctr_enc_armv8_ce:
    *    x4: nblocks
    *    w5: nrounds
    */
+  CFI_STARTPROC();
 
   cbz x4, .Lctr_enc_skip
 
-  mov x6, #1
+  add x8, sp, #-64
+  add sp, sp, #-128;
+  CFI_ADJUST_CFA_OFFSET(128);
+
+  mov w6, #(1 << 24)
   movi v16.16b, #0
-  mov v16.D[1], x6
+  mov v16.S[3], w6 /* 1 */
 
   /* load IV */
   ldp x9, x10, [x3]
@@ -550,6 +626,9 @@ _gcry_aes_ctr_enc_armv8_ce:
   rev x9, x9
   rev x10, x10
 
+  mov x12, #(4 << 56)
+  lsl x11, x10, #56
+
   aes_preload_keys(x0, w5);
 
   b.eq .Lctr_enc_entry_192
@@ -560,73 +639,71 @@ _gcry_aes_ctr_enc_armv8_ce:
     cmp x4, #4; \
     b.lo .Lctr_enc_loop_##bits; \
     \
-  .Lctr_enc_loop4_##bits: \
-    cmp x10, #0xfffffffffffffffc; \
+    st1 {v8.16b-v11.16b}, [sp]; /* store callee saved registers */ \
+    \
+    adds x11, x11, x12; \
+    add v9.4s, v16.4s, v16.4s; /* 2 */ \
+    add v10.4s, v16.4s, v9.4s; /* 3 */ \
+    add v11.4s, v9.4s, v9.4s; /* 4 */ \
+    mov x7, #1; \
     sub x4, x4, #4; \
-    b.lo .Lctr_enc_loop4_##bits##_nocarry; \
+    ld1 {v5.16b-v8.16b}, [x2], #64; /* preload ciphertext */ \
+    b.cs .Lctr_enc_carry4_##bits; \
     \
-    adds x10, x10, #1; \
     mov v1.16b, v0.16b; \
-    adc x9, x9, xzr; \
-    mov v2.D[1], x10; \
-    mov v2.D[0], x9; \
-    \
-    adds x10, x10, #1; \
-    rev64 v2.16b, v2.16b; \
-    adc x9, x9, xzr; \
-    mov v3.D[1], x10; \
-    mov v3.D[0], x9; \
-    \
-    adds x10, x10, #1; \
-    rev64 v3.16b, v3.16b; \
-    adc x9, x9, xzr; \
-    mov v4.D[1], x10; \
-    mov v4.D[0], x9; \
+    add x10, x10, #4; \
+    add v2.16b, v0.16b, v16.16b; \
+    add v3.8h, v0.8h, v9.8h; \
+    add v4.4s, v0.4s, v10.4s; \
+    add v0.2d, v0.2d, v11.2d; \
     \
-    adds x10, x10, #1; \
-    rev64 v4.16b, v4.16b; \
-    adc x9, x9, xzr; \
-    mov v0.D[1], x10; \
-    mov v0.D[0], x9; \
-    rev64 v0.16b, v0.16b; \
+  .Lctr_enc_entry4_##bits##_carry_done: \
+    mov x7, #0; \
+    cmp x4, #4; \
+    do_aes_4_part1(e, mc, v1, v2, v3, v4, vk0); \
+    b.lo .Lctr_enc_done4_##bits; \
     \
-    b .Lctr_enc_loop4_##bits##_store_ctr; \
+    st1 {v12.16b-v15.16b}, [x8]; /* store callee saved registers */ \
     \
-  .Lctr_enc_loop4_##bits##_nocarry: \
+  .Lctr_enc_loop4_##bits: \
+    eor v5.16b, v5.16b, vklast.16b; \
+    eor v6.16b, v6.16b, vklast.16b; \
+    eor v7.16b, v7.16b, vklast.16b; \
+    eor v8.16b, v8.16b, vklast.16b; \
+    do_aes_4_part2_##bits(e, mc, v12, v13, v14, v15, v1, v2, v3, v4, v5, v6, v7, v8); \
+    ld1 {v5.16b-v8.16b}, [x2], #64; /* preload ciphertext */ \
+    adds x11, x11, x12; \
+    sub x4, x4, #4; \
+    b.cs .Lctr_enc_carry4_##bits; \
     \
-    add v3.2d, v16.2d, v16.2d; /* 2 */ \
-    rev64 v6.16b, v0.16b; \
+    mov v1.16b, v0.16b; \
     add x10, x10, #4; \
-    add v4.2d, v3.2d, v16.2d;  /* 3 */ \
-    add v0.2d, v3.2d, v3.2d;   /* 4 */ \
-    rev64 v1.16b, v6.16b; \
-    add v2.2d, v6.2d, v16.2d; \
-    add v3.2d, v6.2d, v3.2d; \
-    add v4.2d, v6.2d, v4.2d; \
-    add v0.2d, v6.2d, v0.2d; \
-    rev64 v2.16b, v2.16b; \
-    rev64 v3.16b, v3.16b; \
-    rev64 v0.16b, v0.16b; \
-    rev64 v4.16b, v4.16b; \
-    \
-  .Lctr_enc_loop4_##bits##_store_ctr: \
+    add v2.16b, v0.16b, v16.16b; \
+    add v3.8h, v0.8h, v9.8h; \
+    add v4.4s, v0.4s, v10.4s; \
+    add v0.2d, v0.2d, v11.2d; \
     \
-    st1 {v0.16b}, [x3]; \
+  .Lctr_enc_loop4_##bits##_carry_done: \
     cmp x4, #4; \
-    ld1 {v5.16b-v7.16b}, [x2], #48; /* preload ciphertext */ \
+    do_aes_4_part1(e, mc, v1, v2, v3, v4, vk0); \
+    st1 {v12.16b-v15.16b}, [x1], #64; /* store plaintext */ \
     \
-    do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
+    b.hs .Lctr_enc_loop4_##bits; \
     \
-    eor v1.16b, v1.16b, v5.16b; \
-    ld1 {v5.16b}, [x2], #16; /* load ciphertext */ \
-    eor v2.16b, v2.16b, v6.16b; \
-    eor v3.16b, v3.16b, v7.16b; \
-    eor v4.16b, v4.16b, v5.16b; \
-    st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
+    ld1 {v12.16b-v15.16b}, [x8]; /* restore callee saved registers */ \
+    \
+  .Lctr_enc_done4_##bits: \
+    eor v5.16b, v5.16b, vklast.16b; \
+    eor v6.16b, v6.16b, vklast.16b; \
+    eor v7.16b, v7.16b, vklast.16b; \
+    eor v8.16b, v8.16b, vklast.16b; \
+    do_aes_4_part2_##bits(e, mc, v5, v6, v7, v8, v1, v2, v3, v4, v5, v6, v7, v8); \
+    \
+    st1 {v5.16b-v8.16b}, [x1], #64; /* store plaintext */ \
     \
-    b.hs .Lctr_enc_loop4_##bits; \
     CLEAR_REG(v3); \
     CLEAR_REG(v4); \
+    ld1 {v8.16b-v11.16b}, [sp]; /* restore callee saved registers */ \
     CLEAR_REG(v5); \
     CLEAR_REG(v6); \
     CLEAR_REG(v7); \
@@ -637,19 +714,48 @@ _gcry_aes_ctr_enc_armv8_ce:
     adds x10, x10, #1; \
     mov v1.16b, v0.16b; \
     adc x9, x9, xzr; \
-    mov v0.D[1], x10; \
-    mov v0.D[0], x9; \
+    dup v0.2d, x10; \
     sub x4, x4, #1; \
+    ins v0.D[0], x9; \
     ld1 {v2.16b}, [x2], #16; /* load ciphertext */ \
     rev64 v0.16b, v0.16b; \
     \
-    do_aes_one##bits(e, mc, v1, v1); \
+    do_aes_one_part1(e, mc, v1, vk0); \
+    eor v2.16b, v2.16b, vklast.16b; \
+    do_aes_one_part2_##bits(e, mc, v1, __, __); \
     \
-    eor v1.16b, v2.16b, v1.16b; \
+    eor v1.16b, v1.16b, v2.16b; \
     st1 {v1.16b}, [x1], #16; /* store plaintext */ \
     \
     cbnz x4, .Lctr_enc_loop_##bits; \
-    b .Lctr_enc_done;
+    b .Lctr_enc_done; \
+    \
+  .Lctr_enc_carry4_##bits: \
+    \
+    adds x13, x10, #1; \
+    mov v1.16b, v0.16b; \
+    adc x14, x9, xzr; \
+    dup v2.2d, x13; \
+      adds x13, x10, #2; \
+    ins v2.D[0], x14; \
+      adc x14, x9, xzr; \
+    rev64 v2.16b, v2.16b; \
+      dup v3.2d, x13; \
+       adds x13, x10, #3; \
+      ins v3.D[0], x14; \
+       adc x14, x9, xzr; \
+      rev64 v3.16b, v3.16b; \
+       dup v4.2d, x13; \
+         adds x10, x10, #4; \
+       ins v4.D[0], x14; \
+         adc x9, x9, xzr; \
+       rev64 v4.16b, v4.16b; \
+         dup v0.2d, x10; \
+         ins v0.D[0], x9; \
+         rev64 v0.16b, v0.16b; \
+    \
+    cbz x7, .Lctr_enc_loop4_##bits##_carry_done; \
+    b .Lctr_enc_entry4_##bits##_carry_done;
 
   CTR_ENC(128)
   CTR_ENC(192)
@@ -665,11 +771,162 @@ _gcry_aes_ctr_enc_armv8_ce:
   CLEAR_REG(v0)
   CLEAR_REG(v1)
   CLEAR_REG(v2)
+  CLEAR_REG(v16)
+
+  add sp, sp, #128;
+  CFI_ADJUST_CFA_OFFSET(-128);
 
 .Lctr_enc_skip:
-  ret
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_ctr_enc_armv8_ce,.-_gcry_aes_ctr_enc_armv8_ce;)
+
+
+/*
+ * void _gcry_aes_ctr32le_enc_armv8_ce (const void *keysched,
+ *                                      unsigned char *outbuf,
+ *                                      const unsigned char *inbuf,
+ *                                      unsigned char *iv,
+ *                                      unsigned int nrounds);
+ */
+
+.align 3
+.globl _gcry_aes_ctr32le_enc_armv8_ce
+ELF(.type  _gcry_aes_ctr32le_enc_armv8_ce,%function;)
+_gcry_aes_ctr32le_enc_armv8_ce:
+  /* input:
+   *    r0: keysched
+   *    r1: outbuf
+   *    r2: inbuf
+   *    r3: iv
+   *    x4: nblocks
+   *    w5: nrounds
+   */
+  CFI_STARTPROC();
+
+  cbz x4, .Lctr32le_enc_skip
+
+  add x8, sp, #-64
+  add sp, sp, #-128;
+  CFI_ADJUST_CFA_OFFSET(128);
+
+  mov w6, #1
+  movi v16.16b, #0
+  mov v16.S[0], w6
+
+  /* load IV */
+  ld1 {v0.16b}, [x3]
+
+  aes_preload_keys(x0, w5);
+
+  b.eq .Lctr32le_enc_entry_192
+  b.hi .Lctr32le_enc_entry_256
+
+#define CTR32LE_ENC(bits) \
+  .Lctr32le_enc_entry_##bits: \
+    cmp x4, #4; \
+    b.lo .Lctr32le_enc_loop_##bits; \
+    \
+    st1 {v8.16b-v11.16b}, [sp]; /* store callee saved registers */ \
+    add v9.4s, v16.4s, v16.4s; /* 2 */ \
+    cmp x4, #8; \
+    add v10.4s, v9.4s, v16.4s; /* 3 */ \
+    sub x4, x4, #4; \
+    add v11.4s, v9.4s, v9.4s;  /* 4 */ \
+    \
+    ld1 {v5.16b-v8.16b}, [x2], #64; /* preload ciphertext */ \
+    \
+    mov v1.16b, v0.16b; \
+    add v2.4s, v0.4s, v16.4s; \
+    add v3.4s, v0.4s, v9.4s; \
+    add v4.4s, v0.4s, v10.4s; \
+    add v0.4s, v0.4s, v11.4s; \
+    \
+    do_aes_4_part1(e, mc, v1, v2, v3, v4, vk0); \
+    b.lo .Lctr32le_enc_done4_##bits; \
+    \
+    st1 {v12.16b-v15.16b}, [x8]; /* store callee saved registers */ \
+    \
+  .Lctr32le_enc_loop4_##bits: \
+    eor v5.16b, v5.16b, vklast.16b; \
+    eor v6.16b, v6.16b, vklast.16b; \
+    eor v7.16b, v7.16b, vklast.16b; \
+    eor v8.16b, v8.16b, vklast.16b; \
+    do_aes_4_part2_##bits(e, mc, v12, v13, v14, v15, v1, v2, v3, v4, v5, v6, v7, v8); \
+    ld1 {v5.16b-v8.16b}, [x2], #64; /* preload ciphertext */ \
+    \
+    cmp x4, #8; \
+    sub x4, x4, #4; \
+    \
+    mov v1.16b, v0.16b; \
+    add v2.4s, v0.4s, v16.4s; \
+    add v3.4s, v0.4s, v9.4s; \
+    add v4.4s, v0.4s, v10.4s; \
+    add v0.4s, v0.4s, v11.4s; \
+    \
+    do_aes_4_part1(e, mc, v1, v2, v3, v4, vk0); \
+    st1 {v12.16b-v15.16b}, [x1], #64; /* store plaintext */ \
+    \
+    b.hs .Lctr32le_enc_loop4_##bits; \
+    \
+    ld1 {v12.16b-v15.16b}, [x8]; /* restore callee saved registers */ \
+    \
+  .Lctr32le_enc_done4_##bits: \
+    eor v5.16b, v5.16b, vklast.16b; \
+    eor v6.16b, v6.16b, vklast.16b; \
+    eor v7.16b, v7.16b, vklast.16b; \
+    eor v8.16b, v8.16b, vklast.16b; \
+    do_aes_4_part2_##bits(e, mc, v5, v6, v7, v8, v1, v2, v3, v4, v5, v6, v7, v8); \
+    \
+    st1 {v5.16b-v8.16b}, [x1], #64; /* store plaintext */ \
+    CLEAR_REG(v3); \
+    CLEAR_REG(v4); \
+    ld1 {v8.16b-v11.16b}, [sp]; /* restore callee saved registers */ \
+    CLEAR_REG(v5); \
+    CLEAR_REG(v6); \
+    CLEAR_REG(v7); \
+    cbz x4, .Lctr32le_enc_done; \
+    \
+  .Lctr32le_enc_loop_##bits: \
+    \
+    mov v1.16b, v0.16b; \
+    ld1 {v2.16b}, [x2], #16; /* load ciphertext */ \
+    sub x4, x4, #1; \
+    add v0.4s, v0.4s, v16.4s; \
+    \
+    do_aes_one_part1(e, mc, v1, vk0); \
+    eor v2.16b, v2.16b, vklast.16b; \
+    do_aes_one_part2_##bits(e, mc, v1, __, __); \
+    \
+    eor v1.16b, v1.16b, v2.16b; \
+    st1 {v1.16b}, [x1], #16; /* store plaintext */ \
+    \
+    cbnz x4, .Lctr32le_enc_loop_##bits; \
+    b .Lctr32le_enc_done;
+
+  CTR32LE_ENC(128)
+  CTR32LE_ENC(192)
+  CTR32LE_ENC(256)
+
+#undef CTR32LE_ENC
+
+.Lctr32le_enc_done:
+  aes_clear_keys(w5)
+
+  st1 {v0.16b}, [x3] /* store IV */
+
+  CLEAR_REG(v0)
+  CLEAR_REG(v1)
+  CLEAR_REG(v2)
+  CLEAR_REG(v16)
 
-.size _gcry_aes_ctr_enc_armv8_ce,.-_gcry_aes_ctr_enc_armv8_ce;
+  add sp, sp, #128;
+  CFI_ADJUST_CFA_OFFSET(-128);
+
+.Lctr32le_enc_skip:
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_ctr32le_enc_armv8_ce,.-_gcry_aes_ctr32le_enc_armv8_ce;)
 
 
 /*
@@ -681,7 +938,7 @@ _gcry_aes_ctr_enc_armv8_ce:
 
 .align 3
 .globl _gcry_aes_cfb_enc_armv8_ce
-.type  _gcry_aes_cfb_enc_armv8_ce,%function;
+ELF(.type  _gcry_aes_cfb_enc_armv8_ce,%function;)
 _gcry_aes_cfb_enc_armv8_ce:
   /* input:
    *    r0: keysched
@@ -691,6 +948,7 @@ _gcry_aes_cfb_enc_armv8_ce:
    *    x4: nblocks
    *    w5: nrounds
    */
+  CFI_STARTPROC();
 
   cbz x4, .Lcfb_enc_skip
 
@@ -699,21 +957,34 @@ _gcry_aes_cfb_enc_armv8_ce:
 
   aes_preload_keys(x0, w5);
 
+  ld1 {v1.16b}, [x2], #16; /* load plaintext */
+  eor v3.16b, vk0.16b, vklast.16b;
+  eor v0.16b, v0.16b, vklast.16b;
+  sub x4, x4, #1;
+  mov v4.16b, v3.16b;
+  do_aes_one_part1(e, mc, v0, v4);
+
   b.eq .Lcfb_enc_entry_192
   b.hi .Lcfb_enc_entry_256
 
 #define CFB_ENC(bits) \
   .Lcfb_enc_entry_##bits: \
+    cbz x4, .Lcfb_enc_done_##bits; \
+    \
   .Lcfb_enc_loop_##bits: \
-    ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
+    eor v2.16b, v1.16b, vklast.16b; \
+    do_aes_one_part2_##bits(e, mc, v0, \
+                           _(eor v4.16b, v3.16b, v1.16b), \
+                           _(ld1 {v1.16b}, [x2], #16 /* load plaintext */)); \
     sub x4, x4, #1; \
-    \
-    do_aes_one##bits(e, mc, v0, v0); \
-    \
-    eor v0.16b, v1.16b, v0.16b; \
-    st1 {v0.16b}, [x1], #16; /* store ciphertext */ \
-    \
+    eor v2.16b, v2.16b, v0.16b; \
+    do_aes_one_part1(e, mc, v0, v4); \
+    st1 {v2.16b}, [x1], #16; /* store ciphertext */ \
     cbnz x4, .Lcfb_enc_loop_##bits; \
+    \
+  .Lcfb_enc_done_##bits: \
+    eor v2.16b, v1.16b, vklast.16b; \
+    do_aes_one_part2_##bits(e, mc, v0, __, __); \
     b .Lcfb_enc_done;
 
   CFB_ENC(128)
@@ -723,16 +994,21 @@ _gcry_aes_cfb_enc_armv8_ce:
 #undef CFB_ENC
 
 .Lcfb_enc_done:
+  eor v2.16b, v2.16b, v0.16b;
+  st1 {v2.16b}, [x1]; /* store ciphertext */
   aes_clear_keys(w5)
-
-  st1 {v0.16b}, [x3] /* store IV */
+  st1 {v2.16b}, [x3] /* store IV */
 
   CLEAR_REG(v0)
   CLEAR_REG(v1)
+  CLEAR_REG(v2)
+  CLEAR_REG(v3)
+  CLEAR_REG(v4)
 
 .Lcfb_enc_skip:
-  ret
-.size _gcry_aes_cfb_enc_armv8_ce,.-_gcry_aes_cfb_enc_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_cfb_enc_armv8_ce,.-_gcry_aes_cfb_enc_armv8_ce;)
 
 
 /*
@@ -744,7 +1020,7 @@ _gcry_aes_cfb_enc_armv8_ce:
 
 .align 3
 .globl _gcry_aes_cfb_dec_armv8_ce
-.type  _gcry_aes_cfb_dec_armv8_ce,%function;
+ELF(.type  _gcry_aes_cfb_dec_armv8_ce,%function;)
 _gcry_aes_cfb_dec_armv8_ce:
   /* input:
    *    r0: keysched
@@ -754,9 +1030,13 @@ _gcry_aes_cfb_dec_armv8_ce:
    *    x4: nblocks
    *    w5: nrounds
    */
+  CFI_STARTPROC();
 
   cbz x4, .Lcfb_dec_skip
 
+  add sp, sp, #-64;
+  CFI_ADJUST_CFA_OFFSET(64);
+
   /* load IV */
   ld1 {v0.16b}, [x3]
 
@@ -770,42 +1050,60 @@ _gcry_aes_cfb_dec_armv8_ce:
     cmp x4, #4; \
     b.lo .Lcfb_dec_loop_##bits; \
     \
-  .Lcfb_dec_loop4_##bits: \
-    \
-    ld1 {v2.16b-v4.16b}, [x2], #48; /* load ciphertext */ \
+    ld1 {v2.16b-v5.16b}, [x2], #64; /* load ciphertext */ \
+    cmp x4, #8; \
     mov v1.16b, v0.16b; \
     sub x4, x4, #4; \
-    cmp x4, #4; \
-    mov v5.16b, v2.16b; \
-    mov v6.16b, v3.16b; \
-    mov v7.16b, v4.16b; \
-    ld1 {v0.16b}, [x2], #16; /* load next IV / ciphertext */ \
+    eor v6.16b, v2.16b, vklast.16b; \
+    eor v7.16b, v3.16b, vklast.16b; \
+    eor v16.16b, v4.16b, vklast.16b; \
+    mov v0.16b, v5.16b; /* next IV */ \
+    eor v5.16b, v5.16b, vklast.16b; \
     \
-    do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
+    do_aes_4_part1(e, mc, v1, v2, v3, v4, vk0); \
+    b.lo .Lcfb_dec_done4_##bits; \
     \
-    eor v1.16b, v1.16b, v5.16b; \
-    eor v2.16b, v2.16b, v6.16b; \
-    eor v3.16b, v3.16b, v7.16b; \
-    eor v4.16b, v4.16b, v0.16b; \
-    st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
+    st1 {v8.16b-v11.16b}, [sp]; /* store callee saved registers */ \
+    \
+  .Lcfb_dec_loop4_##bits: \
+    do_aes_4_part2_##bits(e, mc, v8, v9, v10, v11, v1, v2, v3, v4, v6, v7, v16, v5); \
+    ld1 {v2.16b-v5.16b}, [x2], #64; /* load ciphertext */ \
+    cmp x4, #8; \
+    mov v1.16b, v0.16b; \
+    sub x4, x4, #4; \
+    eor v6.16b, v2.16b, vklast.16b; \
+    eor v7.16b, v3.16b, vklast.16b; \
+    eor v16.16b, v4.16b, vklast.16b; \
+    mov v0.16b, v5.16b; /* next IV */ \
+    eor v5.16b, v5.16b, vklast.16b; \
+    \
+    do_aes_4_part1(e, mc, v1, v2, v3, v4, vk0); \
+    st1 {v8.16b-v11.16b}, [x1], #64; /* store plaintext */ \
     \
     b.hs .Lcfb_dec_loop4_##bits; \
-    CLEAR_REG(v3); \
-    CLEAR_REG(v4); \
+    \
+    ld1 {v8.16b-v11.16b}, [sp]; /* restore callee saved registers */ \
+    \
+  .Lcfb_dec_done4_##bits: \
+    do_aes_4_part2_##bits(e, mc, v1, v2, v3, v4, v1, v2, v3, v4, v6, v7, v16, v5); \
+    \
     CLEAR_REG(v5); \
     CLEAR_REG(v6); \
     CLEAR_REG(v7); \
+    st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
+    CLEAR_REG(v3); \
+    CLEAR_REG(v4); \
     cbz x4, .Lcfb_dec_done; \
     \
   .Lcfb_dec_loop_##bits: \
-    \
     ld1 {v1.16b}, [x2], #16; /* load ciphertext */ \
-    \
     sub x4, x4, #1; \
     \
-    do_aes_one##bits(e, mc, v0, v0); \
+    do_aes_one_part1(e, mc, v0, vk0); \
+    eor v2.16b, v1.16b, vklast.16b; \
+    do_aes_one_part2_##bits(e, mc, v0, __, __); \
+    eor v2.16b, v2.16b, v0.16b; \
     \
-    eor v2.16b, v1.16b, v0.16b; \
     mov v0.16b, v1.16b; \
     st1 {v2.16b}, [x1], #16; /* store plaintext */ \
     \
@@ -826,10 +1124,15 @@ _gcry_aes_cfb_dec_armv8_ce:
   CLEAR_REG(v0)
   CLEAR_REG(v1)
   CLEAR_REG(v2)
+  CLEAR_REG(v16)
+
+  add sp, sp, #64;
+  CFI_ADJUST_CFA_OFFSET(-64);
 
 .Lcfb_dec_skip:
-  ret
-.size _gcry_aes_cfb_dec_armv8_ce,.-_gcry_aes_cfb_dec_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_cfb_dec_armv8_ce,.-_gcry_aes_cfb_dec_armv8_ce;)
 
 
 /*
@@ -846,7 +1149,7 @@ _gcry_aes_cfb_dec_armv8_ce:
 
 .align 3
 .globl _gcry_aes_ocb_enc_armv8_ce
-.type  _gcry_aes_ocb_enc_armv8_ce,%function;
+ELF(.type  _gcry_aes_ocb_enc_armv8_ce,%function;)
 _gcry_aes_ocb_enc_armv8_ce:
   /* input:
    *    x0: keysched
@@ -855,119 +1158,213 @@ _gcry_aes_ocb_enc_armv8_ce:
    *    x3: offset
    *    x4: checksum
    *    x5: Ltable
-   *    x6: nblocks (0 < nblocks <= 32)
+   *    x6: nblocks (0 < nblocks)
    *    w7: nrounds
    *    %st+0: blkn => w12
    */
+  CFI_STARTPROC();
 
   ldr w12, [sp]
   ld1 {v0.16b}, [x3] /* load offset */
   ld1 {v16.16b}, [x4] /* load checksum */
 
+  add x16, sp, #-64;
+  add sp, sp, #-128;
+  CFI_ADJUST_CFA_OFFSET(128);
+
   aes_preload_keys(x0, w7);
 
-  b.eq .Locb_enc_entry_192
-  b.hi .Locb_enc_entry_256
+  st1 {v8.16b-v11.16b}, [sp]; /* store callee saved registers */
 
-#define OCB_ENC(bits, ...) \
-  .Locb_enc_entry_##bits: \
-    cmp x6, #4; \
-    add x12, x12, #1; \
-    b.lo .Locb_enc_loop_##bits; \
+  eor v0.16b, v0.16b, vk0.16b; /* offset ^ first key */
+  eor v9.16b, vk0.16b, vklast.16b; /* first key ^ last key */
+
+  b.eq .Locb_ecry_entry_192
+  b.hi .Locb_ecry_entry_256
+
+#define OCB_CRYPT(bits, ed, mcimc) \
+  .Locb_##ed##cry_entry_##bits: \
+    /* Get number of blocks to align nblk to 4. */ \
+    neg x13, x12; \
+    add x12, x12, #1; /* Pre-increment nblk for ntz calculation */ \
+    and x13, x13, #(4-1); \
+    cmp x13, x6; \
+    csel x13, x6, x13, hi; \
+    cbz x13, .Locb_##ed##cry_alignment_ok_##bits; \
+    \
+    /* Number of blocks after alignment. */ \
+    sub x14, x6, x13; \
+    \
+    /* If number after alignment is less than 4, skip aligned handling \
+     * completely. */ \
+    cmp x14, #4; \
+    csel x13, x6, x13, lo; \
+    \
+  .Locb_##ed##cry_unaligned_entry_##bits: \
+    cmp x13, #4; \
     \
-  .Locb_enc_loop4_##bits: \
+  .Locb_##ed##cry_loop1_##bits: \
     \
     /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
     /* Checksum_i = Checksum_{i-1} xor P_i  */ \
     /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */ \
     \
-    add w9, w12, #1; \
-    add w10, w12, #2; \
-    add w11, w12, #3; \
-    rbit w8, w12; \
-    add w12, w12, #4; \
-    rbit w9, w9; \
-    rbit w10, w10; \
-    rbit w11, w11; \
-    clz w8, w8; /* ntz(i+0) */ \
-    clz w9, w9; /* ntz(i+1) */ \
-    clz w10, w10; /* ntz(i+2) */ \
-    clz w11, w11; /* ntz(i+3) */ \
+    rbit x8, x12; \
+    add x12, x12, #1; \
+    clz x8, x8; /* ntz(i) */ \
     add x8, x5, x8, lsl #4; \
-    ld1 {v1.16b-v4.16b}, [x2], #64;   /* load P_i+<0-3> */ \
-    add x9, x5, x9, lsl #4; \
-    add x10, x5, x10, lsl #4; \
-    add x11, x5, x11, lsl #4; \
     \
-    sub x6, x6, #4; \
+    ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
+    ld1 {v2.16b}, [x8]; /* load L_{ntz(i)} */ \
+    eor v0.16b, v0.16b, v2.16b; \
+    sub x13, x13, #1; \
+    ENC(eor v16.16b, v16.16b, v1.16b); \
+    sub x6, x6, #1; \
     \
-    ld1 {v5.16b}, [x8];               /* load L_{ntz(i+0)} */ \
-    eor v16.16b, v16.16b, v1.16b;     /* Checksum_i+0 */ \
-    ld1 {v6.16b}, [x9];               /* load L_{ntz(i+1)} */ \
-    eor v16.16b, v16.16b, v2.16b;     /* Checksum_i+1 */ \
-    ld1 {v7.16b}, [x10];              /* load L_{ntz(i+2)} */ \
-    eor v16.16b, v16.16b, v3.16b;     /* Checksum_i+2 */ \
-    eor v5.16b, v5.16b, v0.16b;       /* Offset_i+0 */ \
-    ld1 {v0.16b}, [x11];              /* load L_{ntz(i+3)} */ \
-    eor v16.16b, v16.16b, v4.16b;     /* Checksum_i+3 */ \
-    eor v6.16b, v6.16b, v5.16b;       /* Offset_i+1 */ \
-    eor v1.16b, v1.16b, v5.16b;       /* P_i+0 xor Offset_i+0 */ \
-    eor v7.16b, v7.16b, v6.16b;       /* Offset_i+2 */ \
-    eor v2.16b, v2.16b, v6.16b;       /* P_i+1 xor Offset_i+1 */ \
-    eor v0.16b, v0.16b, v7.16b;       /* Offset_i+3 */ \
-    cmp x6, #4; \
-    eor v3.16b, v3.16b, v7.16b;       /* P_i+2 xor Offset_i+2 */ \
-    eor v4.16b, v4.16b, v0.16b;       /* P_i+3 xor Offset_i+3 */ \
+    do_aes_one_part1(ed, mcimc, v1, v0); \
+    eor v2.16b, v0.16b, v9.16b; \
+    do_aes_one_part2_##bits(ed, mcimc, v1, __, __); \
+    eor v1.16b, v1.16b, v2.16b; \
+    st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
+    DEC(eor v16.16b, v16.16b, v1.16b); \
     \
-    do_aes_4_##bits(e, mc, v1, v2, v3, v4); \
+    cbnz x13, .Locb_##ed##cry_loop1_##bits; \
     \
-    eor v1.16b, v1.16b, v5.16b;       /* xor Offset_i+0 */ \
-    eor v2.16b, v2.16b, v6.16b;       /* xor Offset_i+1 */ \
-    eor v3.16b, v3.16b, v7.16b;       /* xor Offset_i+2 */ \
-    eor v4.16b, v4.16b, v0.16b;       /* xor Offset_i+3 */ \
-    st1 {v1.16b-v4.16b}, [x1], #64; \
+    cbz x6, .Locb_##ed##cry_done; \
     \
-    b.hs .Locb_enc_loop4_##bits; \
-    CLEAR_REG(v3); \
-    CLEAR_REG(v4); \
-    CLEAR_REG(v5); \
-    CLEAR_REG(v6); \
-    CLEAR_REG(v7); \
-    cbz x6, .Locb_enc_done; \
+    /* nblk is now aligned and we have 4 or more blocks. So jump directly to \
+     * aligned processing. */ \
+    b .Locb_##ed##cry_aligned_entry_##bits; \
     \
-  .Locb_enc_loop_##bits: \
+  .Locb_##ed##cry_alignment_ok_##bits: \
+    cbz x6, .Locb_##ed##cry_done; \
+    \
+    /* Short buffers do not benefit from L-array optimization. */ \
+    cmp x6, #4; \
+    mov x13, x6; \
+    b.lo .Locb_##ed##cry_unaligned_entry_##bits; \
+    \
+  .Locb_##ed##cry_aligned_entry_##bits: \
+    /* Prepare L-array optimization. \
+     * Since nblk is aligned to 4, offsets will have following construction: \
+     *  - block1 = ntz{0} = offset ^ L[0] \
+     *  - block2 = ntz{1} = offset ^ L[0] ^ L[1] \
+     *  - block3 = ntz{0} = offset ^ L[1] \
+     *  - block4 = ntz{x} = offset ^ L[1] ^ L[ntz{x}] \
+     */ \
+    ld1 {v10.16b-v11.16b}, [x5];        /* preload L[0] && L[1] */ \
+    mov x15, #4; \
+    \
+    st1 {v12.16b-v15.16b}, [x16]; /* store callee saved registers */ \
     \
     /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
     /* Checksum_i = Checksum_{i-1} xor P_i  */ \
     /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */ \
     \
-    rbit x8, x12; \
-    add x12, x12, #1; \
-    clz x8, x8; /* ntz(i) */ \
-    add x8, x5, x8, lsl #4; \
+    add x11, x12, #3; \
+    ld1 {v1.16b-v4.16b}, [x2], #64;     /* load P_i+<0-3> */ \
+    rbit x11, x11; \
+    eor v6.16b, v10.16b, v11.16b;       /* L[0] ^ L[1] */ \
+    ENC(eor v16.16b, v16.16b, v1.16b);  /* Checksum_i+0 */ \
+    add x12, x12, #4; \
+    clz x11, x11; /* ntz(i+3) */ \
+    add x15, x15, #4; \
+    add x11, x5, x11, lsl #4; \
     \
-    ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
-    ld1 {v2.16b}, [x8]; /* load L_{ntz(i)} */ \
-    sub x6, x6, #1; \
-    eor v0.16b, v0.16b, v2.16b; \
-    eor v16.16b, v16.16b, v1.16b; \
-    eor v1.16b, v1.16b, v0.16b; \
+    eor v5.16b, v0.16b, v10.16b;        /* Offset_i+0 */ \
+    ENC(eor v16.16b, v16.16b, v2.16b);  /* Checksum_i+1 */ \
+    ld1 {v8.16b}, [x11];                /* load L_{ntz(i+3)} */ \
+    ENC(eor v16.16b, v16.16b, v3.16b);  /* Checksum_i+2 */ \
+    eor v6.16b, v0.16b, v6.16b;         /* Offset_i+1 */ \
+    ENC(eor v16.16b, v16.16b, v4.16b);  /* Checksum_i+3 */ \
+    eor v7.16b, v0.16b, v11.16b;        /* Offset_i+2 */ \
+    eor v8.16b, v8.16b, v11.16b;        /* L[1] ^ L[ntz{x}] */ \
+    cmp x15, x13; \
+    eor v0.16b, v0.16b, v8.16b;         /* Offset_i+3 */ \
+    \
+    do_aes_4_part1_multikey(ed, mcimc, v1, v2, v3, v4, v5, v6, v7, v0); /* P_i+j xor Offset_i+j */ \
+    b.hi .Locb_##ed##cry_aligned_done4_##bits; \
+    \
+  .Locb_##ed##cry_aligned_loop4_##bits: \
+    add x11, x12, #3; \
+    eor v5.16b, v5.16b, v9.16b; \
+    eor v6.16b, v6.16b, v9.16b; \
+    rbit x11, x11; \
+    eor v7.16b, v7.16b, v9.16b; \
+    eor v8.16b, v0.16b, v9.16b; \
+    clz x11, x11; /* ntz(i+3) */ \
+    do_aes_4_part2_##bits(ed, mcimc, v12, v13, v14, v15, v1, v2, v3, v4, v5, v6, v7, v8); /* xor Offset_i+j */ \
     \
-    do_aes_one##bits(e, mc, v1, v1); \
+    /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
+    /* Checksum_i = Checksum_{i-1} xor P_i  */ \
+    /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */ \
     \
-    eor v1.16b, v1.16b, v0.16b; \
-    st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
+    add x12, x12, #4; \
+    ld1 {v1.16b-v4.16b}, [x2], #64;     /* load P_i+<0-3> */ \
+    eor v6.16b, v10.16b, v11.16b;       /* L[0] ^ L[1] */ \
+    add x15, x15, #4; \
+    DEC(eor v16.16b, v16.16b, v12.16b); /* Checksum_i+0 */ \
+    ENC(eor v16.16b, v16.16b, v1.16b);  /* Checksum_i+0 */ \
+    add x11, x5, x11, lsl #4; \
+    \
+    eor v5.16b, v0.16b, v10.16b;        /* Offset_i+0 */ \
+    ENC(eor v16.16b, v16.16b, v2.16b);  /* Checksum_i+1 */ \
+    DEC(eor v16.16b, v16.16b, v13.16b); /* Checksum_1+2 */ \
+    ld1 {v8.16b}, [x11];                /* load L_{ntz(i+3)} */ \
+    ENC(eor v16.16b, v16.16b, v3.16b);  /* Checksum_i+2 */ \
+    DEC(eor v16.16b, v16.16b, v14.16b); /* Checksum_i+0+3 */ \
+    eor v6.16b, v0.16b, v6.16b;         /* Offset_i+1 */ \
+    ENC(eor v16.16b, v16.16b, v4.16b);  /* Checksum_i+3 */ \
+    DEC(eor v16.16b, v16.16b, v15.16b); /* Checksum_i+0+1+2 */ \
+    eor v7.16b, v0.16b, v11.16b;        /* Offset_i+2 */ \
+    eor v8.16b, v8.16b, v11.16b;        /* L[1] ^ L[ntz{x}] */ \
+    cmp x15, x13; \
+    eor v0.16b, v0.16b, v8.16b;         /* Offset_i+3 */ \
+    \
+    do_aes_4_part1_multikey(ed, mcimc, v1, v2, v3, v4, v5, v6, v7, v0); /* P_i+j xor Offset_i+j */ \
+    st1 {v12.16b-v15.16b}, [x1], #64; \
+    \
+    b.ls .Locb_##ed##cry_aligned_loop4_##bits; \
+    \
+  .Locb_##ed##cry_aligned_done4_##bits: \
+    eor v5.16b, v5.16b, v9.16b; \
+    eor v6.16b, v6.16b, v9.16b; \
+    eor v7.16b, v7.16b, v9.16b; \
+    eor v8.16b, v0.16b, v9.16b; \
+    do_aes_4_part2_##bits(ed, mcimc, v1, v2, v3, v4, v1, v2, v3, v4, v5, v6, v7, v8); /* xor Offset_i+j */ \
+    DEC(eor v16.16b, v16.16b, v1.16b);  /* Checksum_i+0 */ \
+    DEC(eor v5.16b, v2.16b, v3.16b);    /* Checksum_1+2 */ \
+    DEC(eor v16.16b, v16.16b, v4.16b);  /* Checksum_i+0+3 */ \
+    st1 {v1.16b-v4.16b}, [x1], #64; \
+    DEC(eor v16.16b, v16.16b, v5.16b);  /* Checksum_i+0+1+2 */ \
+    \
+    sub x15, x15, #4; \
+    CLEAR_REG(v3); \
+    CLEAR_REG(v4); \
+    ld1 {v12.16b-v15.16b}, [x16]; /* restore callee saved registers */ \
+    sub x13, x13, x15; \
+    sub x6, x6, x15; \
+    CLEAR_REG(v5); \
+    CLEAR_REG(v6); \
+    \
+    /* Handle tailing 1…3 blocks in unaligned loop. */ \
+    mov x13, x6; \
+    cbnz x6, .Locb_##ed##cry_unaligned_entry_##bits; \
     \
-    cbnz x6, .Locb_enc_loop_##bits; \
-    b .Locb_enc_done;
+    b .Locb_##ed##cry_done;
 
-  OCB_ENC(128)
-  OCB_ENC(192)
-  OCB_ENC(256)
+#define ENC(...) __VA_ARGS__
+#define DEC(...) /*_*/
+  OCB_CRYPT(128, e, mc)
+  OCB_CRYPT(192, e, mc)
+  OCB_CRYPT(256, e, mc)
+#undef ENC
+#undef DEC
 
-#undef OCB_ENC
+.Locb_ecry_done:
+  eor v0.16b, v0.16b, vk0.16b; /* restore offset */
 
-.Locb_enc_done:
+  ld1 {v8.16b-v11.16b}, [sp]; /* restore callee saved registers */
   aes_clear_keys(w7)
 
   st1 {v16.16b}, [x4] /* store checksum */
@@ -976,10 +1373,15 @@ _gcry_aes_ocb_enc_armv8_ce:
   CLEAR_REG(v0)
   CLEAR_REG(v1)
   CLEAR_REG(v2)
+  CLEAR_REG(v7)
   CLEAR_REG(v16)
 
-  ret
-.size _gcry_aes_ocb_enc_armv8_ce,.-_gcry_aes_ocb_enc_armv8_ce;
+  add sp, sp, #128;
+  CFI_ADJUST_CFA_OFFSET(-128);
+
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_ocb_enc_armv8_ce,.-_gcry_aes_ocb_enc_armv8_ce;)
 
 
 /*
@@ -996,7 +1398,7 @@ _gcry_aes_ocb_enc_armv8_ce:
 
 .align 3
 .globl _gcry_aes_ocb_dec_armv8_ce
-.type  _gcry_aes_ocb_dec_armv8_ce,%function;
+ELF(.type  _gcry_aes_ocb_dec_armv8_ce,%function;)
 _gcry_aes_ocb_dec_armv8_ce:
   /* input:
    *    x0: keysched
@@ -1005,119 +1407,44 @@ _gcry_aes_ocb_dec_armv8_ce:
    *    x3: offset
    *    x4: checksum
    *    x5: Ltable
-   *    x6: nblocks (0 < nblocks <= 32)
+   *    x6: nblocks (0 < nblocks)
    *    w7: nrounds
    *    %st+0: blkn => w12
    */
+  CFI_STARTPROC();
 
   ldr w12, [sp]
   ld1 {v0.16b}, [x3] /* load offset */
   ld1 {v16.16b}, [x4] /* load checksum */
 
+  add x16, sp, #-64;
+  add sp, sp, #-128;
+  CFI_ADJUST_CFA_OFFSET(128);
+
   aes_preload_keys(x0, w7);
 
-  b.eq .Locb_dec_entry_192
-  b.hi .Locb_dec_entry_256
+  st1 {v8.16b-v11.16b}, [sp]; /* store callee saved registers */
 
-#define OCB_DEC(bits) \
-  .Locb_dec_entry_##bits: \
-    cmp x6, #4; \
-    add w12, w12, #1; \
-    b.lo .Locb_dec_loop_##bits; \
-    \
-  .Locb_dec_loop4_##bits: \
-    \
-    /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
-    /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */ \
-    /* Checksum_i = Checksum_{i-1} xor P_i  */ \
-    \
-    add w9, w12, #1; \
-    add w10, w12, #2; \
-    add w11, w12, #3; \
-    rbit w8, w12; \
-    add w12, w12, #4; \
-    rbit w9, w9; \
-    rbit w10, w10; \
-    rbit w11, w11; \
-    clz w8, w8; /* ntz(i+0) */ \
-    clz w9, w9; /* ntz(i+1) */ \
-    clz w10, w10; /* ntz(i+2) */ \
-    clz w11, w11; /* ntz(i+3) */ \
-    add x8, x5, x8, lsl #4; \
-    ld1 {v1.16b-v4.16b}, [x2], #64;   /* load C_i+<0-3> */ \
-    add x9, x5, x9, lsl #4; \
-    add x10, x5, x10, lsl #4; \
-    add x11, x5, x11, lsl #4; \
-    \
-    sub x6, x6, #4; \
-    \
-    ld1 {v5.16b}, [x8];               /* load L_{ntz(i+0)} */ \
-    ld1 {v6.16b}, [x9];               /* load L_{ntz(i+1)} */ \
-    ld1 {v7.16b}, [x10];              /* load L_{ntz(i+2)} */ \
-    eor v5.16b, v5.16b, v0.16b;       /* Offset_i+0 */ \
-    ld1 {v0.16b}, [x11];              /* load L_{ntz(i+3)} */ \
-    eor v6.16b, v6.16b, v5.16b;       /* Offset_i+1 */ \
-    eor v1.16b, v1.16b, v5.16b;       /* C_i+0 xor Offset_i+0 */ \
-    eor v7.16b, v7.16b, v6.16b;       /* Offset_i+2 */ \
-    eor v2.16b, v2.16b, v6.16b;       /* C_i+1 xor Offset_i+1 */ \
-    eor v0.16b, v0.16b, v7.16b;       /* Offset_i+3 */ \
-    cmp x6, #4; \
-    eor v3.16b, v3.16b, v7.16b;       /* C_i+2 xor Offset_i+2 */ \
-    eor v4.16b, v4.16b, v0.16b;       /* C_i+3 xor Offset_i+3 */ \
-    \
-    do_aes_4_##bits(d, imc, v1, v2, v3, v4); \
-    \
-    eor v1.16b, v1.16b, v5.16b;       /* xor Offset_i+0 */ \
-    eor v2.16b, v2.16b, v6.16b;       /* xor Offset_i+1 */ \
-    eor v16.16b, v16.16b, v1.16b;     /* Checksum_i+0 */ \
-    eor v3.16b, v3.16b, v7.16b;       /* xor Offset_i+2 */ \
-    eor v16.16b, v16.16b, v2.16b;     /* Checksum_i+1 */ \
-    eor v4.16b, v4.16b, v0.16b;       /* xor Offset_i+3 */ \
-    eor v16.16b, v16.16b, v3.16b;     /* Checksum_i+2 */ \
-    eor v16.16b, v16.16b, v4.16b;     /* Checksum_i+3 */ \
-    st1 {v1.16b-v4.16b}, [x1], #64; \
-    \
-    b.hs .Locb_dec_loop4_##bits; \
-    CLEAR_REG(v3); \
-    CLEAR_REG(v4); \
-    CLEAR_REG(v5); \
-    CLEAR_REG(v6); \
-    CLEAR_REG(v7); \
-    cbz x6, .Locb_dec_done; \
-    \
-  .Locb_dec_loop_##bits: \
-    \
-    /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ \
-    /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */ \
-    /* Checksum_i = Checksum_{i-1} xor P_i  */ \
-    \
-    rbit w8, w12; \
-    add w12, w12, #1; \
-    clz w8, w8; /* ntz(i) */ \
-    add x8, x5, x8, lsl #4; \
-    \
-    ld1 {v1.16b}, [x2], #16; /* load ciphertext */ \
-    ld1 {v2.16b}, [x8]; /* load L_{ntz(i)} */ \
-    sub x6, x6, #1; \
-    eor v0.16b, v0.16b, v2.16b; \
-    eor v1.16b, v1.16b, v0.16b; \
-    \
-    do_aes_one##bits(d, imc, v1, v1) \
-    \
-    eor v1.16b, v1.16b, v0.16b; \
-    st1 {v1.16b}, [x1], #16; /* store plaintext */ \
-    eor v16.16b, v16.16b, v1.16b; \
-    \
-    cbnz x6, .Locb_dec_loop_##bits; \
-    b .Locb_dec_done;
+  eor v0.16b, v0.16b, vk0.16b; /* offset ^ first key */
+  eor v9.16b, vk0.16b, vklast.16b; /* first key ^ last key */
 
-  OCB_DEC(128)
-  OCB_DEC(192)
-  OCB_DEC(256)
+  b.eq .Locb_dcry_entry_192
+  b.hi .Locb_dcry_entry_256
 
-#undef OCB_DEC
+#define ENC(...) /*_*/
+#define DEC(...) __VA_ARGS__
+  OCB_CRYPT(128, d, imc)
+  OCB_CRYPT(192, d, imc)
+  OCB_CRYPT(256, d, imc)
+#undef ENC
+#undef DEC
 
-.Locb_dec_done:
+#undef OCB_CRYPT
+
+.Locb_dcry_done:
+  eor v0.16b, v0.16b, vk0.16b; /* restore offset */
+
+  ld1 {v8.16b-v11.16b}, [sp]; /* restore callee saved registers */
   aes_clear_keys(w7)
 
   st1 {v16.16b}, [x4] /* store checksum */
@@ -1128,8 +1455,12 @@ _gcry_aes_ocb_dec_armv8_ce:
   CLEAR_REG(v2)
   CLEAR_REG(v16)
 
-  ret
-.size _gcry_aes_ocb_dec_armv8_ce,.-_gcry_aes_ocb_dec_armv8_ce;
+  add sp, sp, #128;
+  CFI_ADJUST_CFA_OFFSET(-128);
+
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_ocb_dec_armv8_ce,.-_gcry_aes_ocb_dec_armv8_ce;)
 
 
 /*
@@ -1145,7 +1476,7 @@ _gcry_aes_ocb_dec_armv8_ce:
 
 .align 3
 .globl _gcry_aes_ocb_auth_armv8_ce
-.type  _gcry_aes_ocb_auth_armv8_ce,%function;
+ELF(.type  _gcry_aes_ocb_auth_armv8_ce,%function;)
 _gcry_aes_ocb_auth_armv8_ce:
   /* input:
    *    x0: keysched
@@ -1157,8 +1488,10 @@ _gcry_aes_ocb_auth_armv8_ce:
    *    w6: nrounds => w7
    *    w7: blkn => w12
    */
-  mov x12, x7
-  mov x7, x6
+  CFI_STARTPROC();
+
+  mov w12, w7
+  mov w7, w6
   mov x6, x5
   mov x5, x4
   mov x4, x3
@@ -1248,7 +1581,7 @@ _gcry_aes_ocb_auth_armv8_ce:
     eor v0.16b, v0.16b, v2.16b; \
     eor v1.16b, v1.16b, v0.16b; \
     \
-    do_aes_one##bits(e, mc, v1, v1) \
+    do_aes_one##bits(e, mc, v1, v1, vk0) \
     \
     eor v16.16b, v16.16b, v1.16b; \
     \
@@ -1272,8 +1605,278 @@ _gcry_aes_ocb_auth_armv8_ce:
   CLEAR_REG(v2)
   CLEAR_REG(v16)
 
-  ret
-.size _gcry_aes_ocb_auth_armv8_ce,.-_gcry_aes_ocb_auth_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_ocb_auth_armv8_ce,.-_gcry_aes_ocb_auth_armv8_ce;)
+
+
+/*
+ * void _gcry_aes_xts_enc_armv8_ce (const void *keysched,
+ *                                  unsigned char *outbuf,
+ *                                  const unsigned char *inbuf,
+ *                                  unsigned char *tweak,
+ *                                  size_t nblocks,
+ *                                  unsigned int nrounds);
+ */
+
+.align 3
+.globl _gcry_aes_xts_enc_armv8_ce
+ELF(.type  _gcry_aes_xts_enc_armv8_ce,%function;)
+_gcry_aes_xts_enc_armv8_ce:
+  /* input:
+   *    r0: keysched
+   *    r1: outbuf
+   *    r2: inbuf
+   *    r3: tweak
+   *    x4: nblocks
+   *    w5: nrounds
+   */
+  CFI_STARTPROC();
+
+  cbz x4, .Lxts_enc_skip
+
+  add x16, sp, #-64;
+  add sp, sp, #-128;
+  CFI_ADJUST_CFA_OFFSET(128);
+
+  /* load tweak */
+  ld1 {v0.16b}, [x3]
+
+  /* load gfmul mask */
+  mov x6, #0x87
+  mov x7, #0x01
+  mov v16.D[0], x6
+  mov v16.D[1], x7
+
+  aes_preload_keys(x0, w5);
+  eor vklast.16b, vklast.16b, vk0.16b;
+
+  b.eq .Lxts_ecry_entry_192
+  b.hi .Lxts_ecry_entry_256
+
+#define XTS_CRYPT(bits, ed, mcimc) \
+  .Lxts_##ed##cry_entry_##bits: \
+    cmp x4, #4; \
+    b.lo .Lxts_##ed##cry_loop_##bits; \
+    \
+    st1 {v8.16b}, [sp]; /* store callee saved registers */ \
+    ext v4.16b, v0.16b, v0.16b, #8; \
+    mov v8.16b, v0.16b; \
+    \
+    sshr v2.2d, v4.2d, #63; \
+    add v5.2d, v0.2d, v0.2d; \
+    and v2.16b, v2.16b, v16.16b; \
+    add v4.2d, v4.2d, v4.2d; \
+    eor v5.16b, v5.16b, v2.16b; \
+    \
+    sshr v2.2d, v4.2d, #63; \
+    add v6.2d, v5.2d, v5.2d; \
+    and v2.16b, v2.16b, v16.16b; \
+    add v4.2d, v4.2d, v4.2d; \
+    eor v6.16b, v6.16b, v2.16b; \
+    \
+    sshr v2.2d, v4.2d, #63; \
+    add v7.2d, v6.2d, v6.2d; \
+    and v2.16b, v2.16b, v16.16b; \
+    add v4.2d, v4.2d, v4.2d; \
+    eor v7.16b, v7.16b, v2.16b; \
+    \
+    sshr v2.2d, v4.2d, #63; \
+    add v3.2d, v7.2d, v7.2d; \
+    and v2.16b, v2.16b, v16.16b; \
+    add v4.2d, v4.2d, v4.2d; \
+    eor v0.16b, v3.16b, v2.16b; \
+    ld1 {v1.16b-v4.16b}, [x2], #64; /* load plaintext */ \
+    cmp x4, #8; \
+    sub x4, x4, #4; \
+    \
+    eor v8.16b, v8.16b, vk0.16b; \
+    eor v5.16b, v5.16b, vk0.16b; \
+    eor v6.16b, v6.16b, vk0.16b; \
+    eor v7.16b, v7.16b, vk0.16b; \
+    \
+    do_aes_4_part1_multikey(ed, mcimc, v1, v2, v3, v4, v8, v5, v6, v7); \
+    b.lo .Lxts_##ed##cry_done4_##bits; \
+    \
+    st1 {v9.16b-v12.16b}, [x16]; /* store callee saved registers */ \
+    \
+  .Lxts_##ed##cry_loop4_##bits: \
+    eor v8.16b, v8.16b, vklast.16b; \
+    eor v5.16b, v5.16b, vklast.16b; \
+    eor v6.16b, v6.16b, vklast.16b; \
+    eor v7.16b, v7.16b, vklast.16b; \
+    do_aes_4_part2_##bits(ed, mcimc, v9, v10, v11, v12, v1, v2, v3, v4, v8, v5, v6, v7); \
+    \
+    ext v4.16b, v0.16b, v0.16b, #8; \
+    mov v8.16b, v0.16b; \
+    \
+    sshr v2.2d, v4.2d, #63; \
+    add v5.2d, v0.2d, v0.2d; \
+    and v2.16b, v2.16b, v16.16b; \
+    add v4.2d, v4.2d, v4.2d; \
+    eor v5.16b, v5.16b, v2.16b; \
+    \
+    sshr v2.2d, v4.2d, #63; \
+    add v6.2d, v5.2d, v5.2d; \
+    and v2.16b, v2.16b, v16.16b; \
+    add v4.2d, v4.2d, v4.2d; \
+    eor v6.16b, v6.16b, v2.16b; \
+    \
+    sshr v2.2d, v4.2d, #63; \
+    add v7.2d, v6.2d, v6.2d; \
+    and v2.16b, v2.16b, v16.16b; \
+    add v4.2d, v4.2d, v4.2d; \
+    eor v7.16b, v7.16b, v2.16b; \
+    \
+    sshr v2.2d, v4.2d, #63; \
+    add v3.2d, v7.2d, v7.2d; \
+    and v2.16b, v2.16b, v16.16b; \
+    add v4.2d, v4.2d, v4.2d; \
+    eor v0.16b, v3.16b, v2.16b; \
+    ld1 {v1.16b-v4.16b}, [x2], #64; /* load plaintext */ \
+    cmp x4, #8; \
+    sub x4, x4, #4; \
+    \
+    eor v8.16b, v8.16b, vk0.16b; \
+    eor v5.16b, v5.16b, vk0.16b; \
+    eor v6.16b, v6.16b, vk0.16b; \
+    eor v7.16b, v7.16b, vk0.16b; \
+    \
+    do_aes_4_part1_multikey(ed, mcimc, v1, v2, v3, v4, v8, v5, v6, v7); \
+    \
+    st1 {v9.16b-v12.16b}, [x1], #64; /* store plaintext */ \
+    \
+    b.hs .Lxts_##ed##cry_loop4_##bits; \
+    \
+    ld1 {v9.16b-v12.16b}, [x16]; /* restore callee saved registers */ \
+    \
+  .Lxts_##ed##cry_done4_##bits: \
+    eor v8.16b, v8.16b, vklast.16b; \
+    eor v5.16b, v5.16b, vklast.16b; \
+    eor v6.16b, v6.16b, vklast.16b; \
+    eor v7.16b, v7.16b, vklast.16b; \
+    do_aes_4_part2_##bits(ed, mcimc, v1, v2, v3, v4, v1, v2, v3, v4, v8, v5, v6, v7); \
+    \
+    st1 {v1.16b-v4.16b}, [x1], #64; /* store plaintext */ \
+    \
+    CLEAR_REG(v4); \
+    ld1 {v8.16b}, [sp]; /* restore callee saved registers */ \
+    CLEAR_REG(v5); \
+    CLEAR_REG(v6); \
+    CLEAR_REG(v7); \
+    cbz x4, .Lxts_##ed##cry_done; \
+    \
+  .Lxts_##ed##cry_loop_##bits: \
+    \
+    ld1 {v1.16b}, [x2], #16; /* load plaintext */ \
+    ext v3.16b, v0.16b, v0.16b, #8; \
+    eor v2.16b, v0.16b, vk0.16b; \
+    sshr v3.2d, v3.2d, #63; \
+    add v0.2d, v0.2d, v0.2d; \
+    and v3.16b, v3.16b, v16.16b; \
+    sub x4, x4, #1; \
+    eor v0.16b, v0.16b, v3.16b; \
+    \
+    do_aes_one_part1(ed, mcimc, v1, v2); \
+    eor v2.16b, v2.16b, vklast.16b; \
+    do_aes_one_part2_##bits(ed, mcimc, v1, __, __); \
+    eor v1.16b, v1.16b, v2.16b; \
+    \
+    st1 {v1.16b}, [x1], #16; /* store ciphertext */ \
+    \
+    cbnz x4, .Lxts_##ed##cry_loop_##bits; \
+    b .Lxts_##ed##cry_done;
+
+  XTS_CRYPT(128, e, mc)
+  XTS_CRYPT(192, e, mc)
+  XTS_CRYPT(256, e, mc)
+
+.Lxts_ecry_done:
+  aes_clear_keys(w5)
+
+  st1 {v0.16b}, [x3] /* store tweak */
+
+  CLEAR_REG(v0)
+  CLEAR_REG(v1)
+  CLEAR_REG(v2)
+  CLEAR_REG(v3)
+  CLEAR_REG(v16)
+
+  add sp, sp, 128;
+  CFI_ADJUST_CFA_OFFSET(-128);
+
+.Lxts_enc_skip:
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_xts_enc_armv8_ce,.-_gcry_aes_xts_enc_armv8_ce;)
+
+
+/*
+ * void _gcry_aes_xts_dec_armv8_ce (const void *keysched,
+ *                                  unsigned char *outbuf,
+ *                                  const unsigned char *inbuf,
+ *                                  unsigned char *tweak,
+ *                                  size_t nblocks,
+ *                                  unsigned int nrounds);
+ */
+
+.align 3
+.globl _gcry_aes_xts_dec_armv8_ce
+ELF(.type  _gcry_aes_xts_dec_armv8_ce,%function;)
+_gcry_aes_xts_dec_armv8_ce:
+  /* input:
+   *    r0: keysched
+   *    r1: outbuf
+   *    r2: inbuf
+   *    r3: tweak
+   *    x4: nblocks
+   *    w5: nrounds
+   */
+  CFI_STARTPROC();
+
+  cbz x4, .Lxts_dec_skip
+
+  add x16, sp, #-64;
+  add sp, sp, #-128;
+  CFI_ADJUST_CFA_OFFSET(128);
+
+  /* load tweak */
+  ld1 {v0.16b}, [x3]
+
+  /* load gfmul mask */
+  mov x6, #0x87
+  mov x7, #0x01
+  mov v16.D[0], x6
+  mov v16.D[1], x7
+
+  aes_preload_keys(x0, w5);
+  eor vklast.16b, vklast.16b, vk0.16b;
+
+  b.eq .Lxts_dcry_entry_192
+  b.hi .Lxts_dcry_entry_256
+
+  XTS_CRYPT(128, d, imc)
+  XTS_CRYPT(192, d, imc)
+  XTS_CRYPT(256, d, imc)
+
+#undef XTS_CRYPT
+
+.Lxts_dcry_done:
+  aes_clear_keys(w5)
+
+  st1 {v0.16b}, [x3] /* store tweak */
+
+  CLEAR_REG(v0)
+  CLEAR_REG(v1)
+  CLEAR_REG(v2)
+
+  add sp, sp, 128;
+  CFI_ADJUST_CFA_OFFSET(-128);
+
+.Lxts_dec_skip:
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_xts_dec_armv8_ce,.-_gcry_aes_xts_dec_armv8_ce;)
 
 
 /*
@@ -1281,11 +1884,12 @@ _gcry_aes_ocb_auth_armv8_ce:
  */
 .align 3
 .globl _gcry_aes_sbox4_armv8_ce
-.type  _gcry_aes_sbox4_armv8_ce,%function;
+ELF(.type  _gcry_aes_sbox4_armv8_ce,%function;)
 _gcry_aes_sbox4_armv8_ce:
   /* See "Gouvêa, C. P. L. & López, J. Implementing GCM on ARMv8. Topics in
    * Cryptology — CT-RSA 2015" for details.
    */
+  CFI_STARTPROC();
   movi v0.16b, #0x52
   movi v1.16b, #0
   mov v0.S[0], w0
@@ -1293,8 +1897,9 @@ _gcry_aes_sbox4_armv8_ce:
   addv s0, v0.4s
   mov w0, v0.S[0]
   CLEAR_REG(v0)
-  ret
-.size _gcry_aes_sbox4_armv8_ce,.-_gcry_aes_sbox4_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_sbox4_armv8_ce,.-_gcry_aes_sbox4_armv8_ce;)
 
 
 /*
@@ -1302,13 +1907,15 @@ _gcry_aes_sbox4_armv8_ce:
  */
 .align 3
 .globl _gcry_aes_invmixcol_armv8_ce
-.type  _gcry_aes_invmixcol_armv8_ce,%function;
+ELF(.type  _gcry_aes_invmixcol_armv8_ce,%function;)
 _gcry_aes_invmixcol_armv8_ce:
+  CFI_STARTPROC();
   ld1 {v0.16b}, [x1]
   aesimc v0.16b, v0.16b
   st1 {v0.16b}, [x0]
   CLEAR_REG(v0)
-  ret
-.size _gcry_aes_invmixcol_armv8_ce,.-_gcry_aes_invmixcol_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_aes_invmixcol_armv8_ce,.-_gcry_aes_invmixcol_armv8_ce;)
 
 #endif
index 334cf68..b24ae3e 100644 (file)
@@ -75,6 +75,12 @@ extern void _gcry_aes_ctr_enc_armv8_ce (const void *keysched,
                                         unsigned char *iv, size_t nblocks,
                                         unsigned int nrounds);
 
+extern void _gcry_aes_ctr32le_enc_armv8_ce (const void *keysched,
+                                            unsigned char *outbuf,
+                                            const unsigned char *inbuf,
+                                            unsigned char *iv, size_t nblocks,
+                                            unsigned int nrounds);
+
 extern void _gcry_aes_ocb_enc_armv8_ce (const void *keysched,
                                         unsigned char *outbuf,
                                         const unsigned char *inbuf,
@@ -101,6 +107,16 @@ extern void _gcry_aes_ocb_auth_armv8_ce (const void *keysched,
                                          size_t nblocks,
                                          unsigned int nrounds,
                                          unsigned int blkn);
+extern void _gcry_aes_xts_enc_armv8_ce (const void *keysched,
+                                        unsigned char *outbuf,
+                                        const unsigned char *inbuf,
+                                        unsigned char *tweak,
+                                        size_t nblocks, unsigned int nrounds);
+extern void _gcry_aes_xts_dec_armv8_ce (const void *keysched,
+                                        unsigned char *outbuf,
+                                        const unsigned char *inbuf,
+                                        unsigned char *tweak,
+                                        size_t nblocks, unsigned int nrounds);
 
 typedef void (*ocb_crypt_fn_t) (const void *keysched, unsigned char *outbuf,
                                 const unsigned char *inbuf,
@@ -108,6 +124,11 @@ typedef void (*ocb_crypt_fn_t) (const void *keysched, unsigned char *outbuf,
                                 unsigned char *L_table, size_t nblocks,
                                 unsigned int nrounds, unsigned int blkn);
 
+typedef void (*xts_crypt_fn_t) (const void *keysched, unsigned char *outbuf,
+                                const unsigned char *inbuf,
+                                unsigned char *tweak, size_t nblocks,
+                                unsigned int nrounds);
+
 void
 _gcry_aes_armv8_ce_setkey (RIJNDAEL_context *ctx, const byte *key)
 {
@@ -269,8 +290,8 @@ _gcry_aes_armv8_ce_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
 }
 
 void
-_gcry_aes_armv8_ce_cbc_enc (const RIJNDAEL_context *ctx, unsigned char *outbuf,
-                            const unsigned char *inbuf, unsigned char *iv,
+_gcry_aes_armv8_ce_cbc_enc (const RIJNDAEL_context *ctx, unsigned char *iv,
+                            unsigned char *outbuf, const unsigned char *inbuf,
                             size_t nblocks, int cbc_mac)
 {
   const void *keysched = ctx->keyschenc32;
@@ -281,19 +302,25 @@ _gcry_aes_armv8_ce_cbc_enc (const RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 void
-_gcry_aes_armv8_ce_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                            const unsigned char *inbuf, unsigned char *iv,
+_gcry_aes_armv8_ce_cbc_dec (RIJNDAEL_context *ctx, unsigned char *iv,
+                            unsigned char *outbuf, const unsigned char *inbuf,
                             size_t nblocks)
 {
   const void *keysched = ctx->keyschdec32;
   unsigned int nrounds = ctx->rounds;
 
+  if ( !ctx->decryption_prepared )
+    {
+      _gcry_aes_armv8_ce_prepare_decryption ( ctx );
+      ctx->decryption_prepared = 1;
+    }
+
   _gcry_aes_cbc_dec_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, nrounds);
 }
 
 void
-_gcry_aes_armv8_ce_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                            const unsigned char *inbuf, unsigned char *iv,
+_gcry_aes_armv8_ce_cfb_enc (RIJNDAEL_context *ctx, unsigned char *iv,
+                            unsigned char *outbuf, const unsigned char *inbuf,
                             size_t nblocks)
 {
   const void *keysched = ctx->keyschenc32;
@@ -303,8 +330,8 @@ _gcry_aes_armv8_ce_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 void
-_gcry_aes_armv8_ce_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                            const unsigned char *inbuf, unsigned char *iv,
+_gcry_aes_armv8_ce_cfb_dec (RIJNDAEL_context *ctx, unsigned char *iv,
+                            unsigned char *outbuf, const unsigned char *inbuf,
                             size_t nblocks)
 {
   const void *keysched = ctx->keyschenc32;
@@ -314,8 +341,8 @@ _gcry_aes_armv8_ce_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 void
-_gcry_aes_armv8_ce_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                            const unsigned char *inbuf, unsigned char *iv,
+_gcry_aes_armv8_ce_ctr_enc (RIJNDAEL_context *ctx, unsigned char *iv,
+                            unsigned char *outbuf, const unsigned char *inbuf,
                             size_t nblocks)
 {
   const void *keysched = ctx->keyschenc32;
@@ -325,6 +352,17 @@ _gcry_aes_armv8_ce_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 void
+_gcry_aes_armv8_ce_ctr32le_enc (RIJNDAEL_context *ctx, unsigned char *iv,
+                                unsigned char *outbuf,
+                                const unsigned char *inbuf, size_t nblocks)
+{
+  const void *keysched = ctx->keyschenc32;
+  unsigned int nrounds = ctx->rounds;
+
+  _gcry_aes_ctr32le_enc_armv8_ce(keysched, outbuf, inbuf, iv, nblocks, nrounds);
+}
+
+size_t
 _gcry_aes_armv8_ce_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
                               const void *inbuf_arg, size_t nblocks,
                               int encrypt)
@@ -338,13 +376,21 @@ _gcry_aes_armv8_ce_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
   unsigned int nrounds = ctx->rounds;
   u64 blkn = c->u_mode.ocb.data_nblocks;
 
+  if ( !encrypt && !ctx->decryption_prepared )
+    {
+      _gcry_aes_armv8_ce_prepare_decryption ( ctx );
+      ctx->decryption_prepared = 1;
+    }
+
   c->u_mode.ocb.data_nblocks = blkn + nblocks;
 
   crypt_fn(keysched, outbuf, inbuf, c->u_iv.iv, c->u_ctr.ctr,
            c->u_mode.ocb.L[0], nblocks, nrounds, (unsigned int)blkn);
+
+  return 0;
 }
 
-void
+size_t
 _gcry_aes_armv8_ce_ocb_auth (gcry_cipher_hd_t c, void *abuf_arg,
                              size_t nblocks)
 {
@@ -359,6 +405,27 @@ _gcry_aes_armv8_ce_ocb_auth (gcry_cipher_hd_t c, void *abuf_arg,
   _gcry_aes_ocb_auth_armv8_ce(keysched, abuf, c->u_mode.ocb.aad_offset,
                              c->u_mode.ocb.aad_sum, c->u_mode.ocb.L[0],
                              nblocks, nrounds, (unsigned int)blkn);
+
+  return 0;
+}
+
+void
+_gcry_aes_armv8_ce_xts_crypt (RIJNDAEL_context *ctx, unsigned char *tweak,
+                             unsigned char *outbuf, const unsigned char *inbuf,
+                             size_t nblocks, int encrypt)
+{
+  const void *keysched = encrypt ? ctx->keyschenc32 : ctx->keyschdec32;
+  xts_crypt_fn_t crypt_fn = encrypt ? _gcry_aes_xts_enc_armv8_ce
+                                    : _gcry_aes_xts_dec_armv8_ce;
+  unsigned int nrounds = ctx->rounds;
+
+  if ( !encrypt && !ctx->decryption_prepared )
+    {
+      _gcry_aes_armv8_ce_prepare_decryption ( ctx );
+      ctx->decryption_prepared = 1;
+    }
+
+  crypt_fn(keysched, outbuf, inbuf, tweak, nblocks, nrounds);
 }
 
 #endif /* USE_ARM_CE */
diff --git a/cipher/rijndael-gcm-p10le.s b/cipher/rijndael-gcm-p10le.s
new file mode 100644 (file)
index 0000000..81fec2a
--- /dev/null
@@ -0,0 +1,1401 @@
+# Copyright 2021- IBM Inc. All rights reserved
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+#===================================================================================
+# Written by Danny Tsen <dtsen@us.ibm.com>
+#
+# GHASH is based on the Karatsuba multiplication method.
+#
+#    Xi xor X1
+#
+#    X1 * H^4 + X2 * H^3 + x3 * H^2 + X4 * H =
+#      (X1.h * H4.h + xX.l * H4.l + X1 * H4) +
+#      (X2.h * H3.h + X2.l * H3.l + X2 * H3) +
+#      (X3.h * H2.h + X3.l * H2.l + X3 * H2) +
+#      (X4.h * H.h + X4.l * H.l + X4 * H)
+#
+# Xi = v0
+# H Poly = v2
+# Hash keys = v3 - v14
+#     ( H.l, H, H.h)
+#     ( H^2.l, H^2, H^2.h)
+#     ( H^3.l, H^3, H^3.h)
+#     ( H^4.l, H^4, H^4.h)
+#
+# v30 is IV
+# v31 - counter 1
+#
+# AES used,
+#     vs0 - vs14 for round keys
+#     v15, v16, v17, v18, v19, v20, v21, v22 for 8 blocks (encrypted)
+#
+# This implementation uses stitched AES-GCM approach to improve overall performance.
+# AES is implemented with 8x blocks and GHASH is using 2 4x blocks.
+#
+# Current performance with 128 bit key using bench-slope on Power10[le] (3.89GHz):
+#
+# AES            |  nanosecs/byte   mebibytes/sec   cycles/byte
+#        GCM enc |     0.169 ns/B      5643 MiB/s         - c/B
+#        GCM dec |     0.171 ns/B      5585 MiB/s         - c/B
+#
+# ===================================================================================
+#
+
+.machine        "any"
+.abiversion     2
+.text
+
+# 4x loops
+# v15 - v18 - input states
+# vs1 - vs9 - round keys
+#
+.macro Loop_aes_middle4x
+       xxlor   19+32, 1, 1
+       xxlor   20+32, 2, 2
+       xxlor   21+32, 3, 3
+       xxlor   22+32, 4, 4
+
+       vcipher 15, 15, 19
+       vcipher 16, 16, 19
+       vcipher 17, 17, 19
+       vcipher 18, 18, 19
+
+       vcipher 15, 15, 20
+       vcipher 16, 16, 20
+       vcipher 17, 17, 20
+       vcipher 18, 18, 20
+
+       vcipher 15, 15, 21
+       vcipher 16, 16, 21
+       vcipher 17, 17, 21
+       vcipher 18, 18, 21
+
+       vcipher 15, 15, 22
+       vcipher 16, 16, 22
+       vcipher 17, 17, 22
+       vcipher 18, 18, 22
+
+       xxlor   19+32, 5, 5
+       xxlor   20+32, 6, 6
+       xxlor   21+32, 7, 7
+       xxlor   22+32, 8, 8
+
+       vcipher 15, 15, 19
+       vcipher 16, 16, 19
+       vcipher 17, 17, 19
+       vcipher 18, 18, 19
+
+       vcipher 15, 15, 20
+       vcipher 16, 16, 20
+       vcipher 17, 17, 20
+       vcipher 18, 18, 20
+
+       vcipher 15, 15, 21
+       vcipher 16, 16, 21
+       vcipher 17, 17, 21
+       vcipher 18, 18, 21
+
+       vcipher 15, 15, 22
+       vcipher 16, 16, 22
+       vcipher 17, 17, 22
+       vcipher 18, 18, 22
+
+       xxlor   23+32, 9, 9
+       vcipher 15, 15, 23
+       vcipher 16, 16, 23
+       vcipher 17, 17, 23
+       vcipher 18, 18, 23
+.endm
+
+# 8x loops
+# v15 - v22 - input states
+# vs1 - vs9 - round keys
+#
+.macro Loop_aes_middle8x
+       xxlor   23+32, 1, 1
+       xxlor   24+32, 2, 2
+       xxlor   25+32, 3, 3
+       xxlor   26+32, 4, 4
+
+       vcipher 15, 15, 23
+       vcipher 16, 16, 23
+       vcipher 17, 17, 23
+       vcipher 18, 18, 23
+       vcipher 19, 19, 23
+       vcipher 20, 20, 23
+       vcipher 21, 21, 23
+       vcipher 22, 22, 23
+
+       vcipher 15, 15, 24
+       vcipher 16, 16, 24
+       vcipher 17, 17, 24
+       vcipher 18, 18, 24
+       vcipher 19, 19, 24
+       vcipher 20, 20, 24
+       vcipher 21, 21, 24
+       vcipher 22, 22, 24
+
+       vcipher 15, 15, 25
+       vcipher 16, 16, 25
+       vcipher 17, 17, 25
+       vcipher 18, 18, 25
+       vcipher 19, 19, 25
+       vcipher 20, 20, 25
+       vcipher 21, 21, 25
+       vcipher 22, 22, 25
+
+       vcipher 15, 15, 26
+       vcipher 16, 16, 26
+       vcipher 17, 17, 26
+       vcipher 18, 18, 26
+       vcipher 19, 19, 26
+       vcipher 20, 20, 26
+       vcipher 21, 21, 26
+       vcipher 22, 22, 26
+
+       xxlor   23+32, 5, 5
+       xxlor   24+32, 6, 6
+       xxlor   25+32, 7, 7
+       xxlor   26+32, 8, 8
+
+       vcipher 15, 15, 23
+       vcipher 16, 16, 23
+       vcipher 17, 17, 23
+       vcipher 18, 18, 23
+       vcipher 19, 19, 23
+       vcipher 20, 20, 23
+       vcipher 21, 21, 23
+       vcipher 22, 22, 23
+
+       vcipher 15, 15, 24
+       vcipher 16, 16, 24
+       vcipher 17, 17, 24
+       vcipher 18, 18, 24
+       vcipher 19, 19, 24
+       vcipher 20, 20, 24
+       vcipher 21, 21, 24
+       vcipher 22, 22, 24
+
+       vcipher 15, 15, 25
+       vcipher 16, 16, 25
+       vcipher 17, 17, 25
+       vcipher 18, 18, 25
+       vcipher 19, 19, 25
+       vcipher 20, 20, 25
+       vcipher 21, 21, 25
+       vcipher 22, 22, 25
+
+       vcipher 15, 15, 26
+       vcipher 16, 16, 26
+       vcipher 17, 17, 26
+       vcipher 18, 18, 26
+       vcipher 19, 19, 26
+       vcipher 20, 20, 26
+       vcipher 21, 21, 26
+       vcipher 22, 22, 26
+
+       xxlor   23+32, 9, 9
+       vcipher 15, 15, 23
+       vcipher 16, 16, 23
+       vcipher 17, 17, 23
+       vcipher 18, 18, 23
+       vcipher 19, 19, 23
+       vcipher 20, 20, 23
+       vcipher 21, 21, 23
+       vcipher 22, 22, 23
+.endm
+
+#
+# Compute 4x hash values based on Karatsuba method.
+#
+ppc_aes_gcm_ghash:
+       vxor            15, 15, 0
+
+       xxlxor          29, 29, 29
+
+       vpmsumd         23, 12, 15              # H4.L * X.L
+       vpmsumd         24, 9, 16
+       vpmsumd         25, 6, 17
+       vpmsumd         26, 3, 18
+
+       vxor            23, 23, 24
+       vxor            23, 23, 25
+       vxor            23, 23, 26              # L
+
+       vpmsumd         24, 13, 15              # H4.L * X.H + H4.H * X.L
+       vpmsumd         25, 10, 16              # H3.L * X1.H + H3.H * X1.L
+       vpmsumd         26, 7, 17
+       vpmsumd         27, 4, 18
+
+       vxor            24, 24, 25
+       vxor            24, 24, 26
+       vxor            24, 24, 27              # M
+
+       # sum hash and reduction with H Poly
+       vpmsumd         28, 23, 2               # reduction
+
+       xxlor           29+32, 29, 29
+       vsldoi          26, 24, 29, 8           # mL
+       vsldoi          29, 29, 24, 8           # mH
+       vxor            23, 23, 26              # mL + L
+
+       vsldoi          23, 23, 23, 8           # swap
+       vxor            23, 23, 28
+
+       vpmsumd         24, 14, 15              # H4.H * X.H
+       vpmsumd         25, 11, 16
+       vpmsumd         26, 8, 17
+       vpmsumd         27, 5, 18
+
+       vxor            24, 24, 25
+       vxor            24, 24, 26
+       vxor            24, 24, 27
+
+       vxor            24, 24, 29
+
+       # sum hash and reduction with H Poly
+       vsldoi          27, 23, 23, 8           # swap
+       vpmsumd         23, 23, 2
+       vxor            27, 27, 24
+       vxor            23, 23, 27
+
+       xxlor           32, 23+32, 23+32                # update hash
+
+       blr
+
+#
+# Combine two 4x ghash
+# v15 - v22 - input blocks
+#
+.macro ppc_aes_gcm_ghash2_4x
+       # first 4x hash
+       vxor            15, 15, 0               # Xi + X
+
+       xxlxor          29, 29, 29
+
+       vpmsumd         23, 12, 15              # H4.L * X.L
+       vpmsumd         24, 9, 16
+       vpmsumd         25, 6, 17
+       vpmsumd         26, 3, 18
+
+       vxor            23, 23, 24
+       vxor            23, 23, 25
+       vxor            23, 23, 26              # L
+
+       vpmsumd         24, 13, 15              # H4.L * X.H + H4.H * X.L
+       vpmsumd         25, 10, 16              # H3.L * X1.H + H3.H * X1.L
+       vpmsumd         26, 7, 17
+       vpmsumd         27, 4, 18
+
+       vxor            24, 24, 25
+       vxor            24, 24, 26
+
+       # sum hash and reduction with H Poly
+       vpmsumd         28, 23, 2               # reduction
+
+       xxlor           29+32, 29, 29
+
+       vxor            24, 24, 27              # M
+       vsldoi          26, 24, 29, 8           # mL
+       vsldoi          29, 29, 24, 8           # mH
+       vxor            23, 23, 26              # mL + L
+
+       vsldoi          23, 23, 23, 8           # swap
+       vxor            23, 23, 28
+
+       vpmsumd         24, 14, 15              # H4.H * X.H
+       vpmsumd         25, 11, 16
+       vpmsumd         26, 8, 17
+       vpmsumd         27, 5, 18
+
+       vxor            24, 24, 25
+       vxor            24, 24, 26
+       vxor            24, 24, 27              # H
+
+       vxor            24, 24, 29              # H + mH
+
+       # sum hash and reduction with H Poly
+       vsldoi          27, 23, 23, 8           # swap
+       vpmsumd         23, 23, 2
+       vxor            27, 27, 24
+       vxor            27, 23, 27              # 1st Xi
+
+       # 2nd 4x hash
+       vpmsumd         24, 9, 20
+       vpmsumd         25, 6, 21
+       vpmsumd         26, 3, 22
+       vxor            19, 19, 27              # Xi + X
+       vpmsumd         23, 12, 19              # H4.L * X.L
+
+       vxor            23, 23, 24
+       vxor            23, 23, 25
+       vxor            23, 23, 26              # L
+
+       vpmsumd         24, 13, 19              # H4.L * X.H + H4.H * X.L
+       vpmsumd         25, 10, 20              # H3.L * X1.H + H3.H * X1.L
+       vpmsumd         26, 7, 21
+       vpmsumd         27, 4, 22
+
+       vxor            24, 24, 25
+       vxor            24, 24, 26
+
+       # sum hash and reduction with H Poly
+       vpmsumd         28, 23, 2               # reduction
+
+       xxlor           29+32, 29, 29
+
+       vxor            24, 24, 27              # M
+       vsldoi          26, 24, 29, 8           # mL
+       vsldoi          29, 29, 24, 8           # mH
+       vxor            23, 23, 26              # mL + L
+
+       vsldoi          23, 23, 23, 8           # swap
+       vxor            23, 23, 28
+
+       vpmsumd         24, 14, 19              # H4.H * X.H
+       vpmsumd         25, 11, 20
+       vpmsumd         26, 8, 21
+       vpmsumd         27, 5, 22
+
+       vxor            24, 24, 25
+       vxor            24, 24, 26
+       vxor            24, 24, 27              # H
+
+       vxor            24, 24, 29              # H + mH
+
+       # sum hash and reduction with H Poly
+       vsldoi          27, 23, 23, 8           # swap
+       vpmsumd         23, 23, 2
+       vxor            27, 27, 24
+       vxor            23, 23, 27
+
+       xxlor           32, 23+32, 23+32                # update hash
+
+.endm
+
+#
+# Compute update single hash
+#
+.macro ppc_update_hash_1x
+       vxor            28, 28, 0
+
+       vxor            19, 19, 19
+
+       vpmsumd         22, 3, 28               # L
+       vpmsumd         23, 4, 28               # M
+       vpmsumd         24, 5, 28               # H
+
+       vpmsumd         27, 22, 2               # reduction
+
+       vsldoi          25, 23, 19, 8           # mL
+       vsldoi          26, 19, 23, 8           # mH
+       vxor            22, 22, 25              # LL + LL
+       vxor            24, 24, 26              # HH + HH
+
+       vsldoi          22, 22, 22, 8           # swap
+       vxor            22, 22, 27
+
+       vsldoi          20, 22, 22, 8           # swap
+       vpmsumd         22, 22, 2               # reduction
+       vxor            20, 20, 24
+       vxor            22, 22, 20
+
+       vmr             0, 22                   # update hash
+
+.endm
+
+#
+# libgcrypt:
+# _gcry_ppc10_aes_gcm_encrypt (const void *inp, void *out, size_t len,
+#               const char *rk, unsigned char iv[16], void *Xip);
+#
+#    r3 - inp
+#    r4 - out
+#    r5 - len
+#    r6 - AES round keys
+#    r7 - iv
+#    r8 - HPoli, hash keys, Xi
+#
+#    rounds is at offset 480 in rk
+#    Xi is at 256 in gcm_table (Xip).
+#
+.global _gcry_ppc10_aes_gcm_encrypt
+.align 5
+_gcry_ppc10_aes_gcm_encrypt:
+_gcry_ppc_aes_gcm_encrypt:
+
+       stdu 1,-512(1)
+       mflr 0
+
+       std     14,112(1)
+       std     15,120(1)
+       std     16,128(1)
+       std     17,136(1)
+       std     18,144(1)
+       std     19,152(1)
+       std     20,160(1)
+       std     21,168(1)
+       li      9, 256
+       stvx    20, 9, 1
+       addi    9, 9, 16
+       stvx    21, 9, 1
+       addi    9, 9, 16
+       stvx    22, 9, 1
+       addi    9, 9, 16
+       stvx    23, 9, 1
+       addi    9, 9, 16
+       stvx    24, 9, 1
+       addi    9, 9, 16
+       stvx    25, 9, 1
+       addi    9, 9, 16
+       stvx    26, 9, 1
+       addi    9, 9, 16
+       stvx    27, 9, 1
+       addi    9, 9, 16
+       stvx    28, 9, 1
+       addi    9, 9, 16
+       stvx    29, 9, 1
+       addi    9, 9, 16
+       stvx    30, 9, 1
+       addi    9, 9, 16
+       stvx    31, 9, 1
+       std     0, 528(1)
+
+       # Load Xi
+       li      10, 256
+       lxvb16x 32, 10, 8       # load Xi
+
+       # load Hash - h^4, h^3, h^2, h
+       lxvd2x  2+32, 0, 8      # H Poli
+       li      10, 16
+       lxvd2x  3+32, 10, 8     # Hl
+       li      10, 32
+       lxvd2x  4+32, 10, 8     # H
+       li      10, 48
+       lxvd2x  5+32, 10, 8     # Hh
+
+       li      10, 64
+       lxvd2x  6+32, 10, 8     # H^2l
+       li      10, 80
+       lxvd2x  7+32, 10, 8     # H^2
+       li      10, 96
+       lxvd2x  8+32, 10, 8     # H^2h
+
+       li      10, 112
+       lxvd2x  9+32, 10, 8     # H^3l
+       li      10, 128
+       lxvd2x  10+32, 10, 8    # H^3
+       li      10, 144
+       lxvd2x  11+32, 10, 8    # H^3h
+
+       li      10, 160
+       lxvd2x  12+32, 10, 8    # H^4l
+       li      10, 176
+       lxvd2x  13+32, 10, 8    # H^4
+       li      10, 192
+       lxvd2x  14+32, 10, 8    # H^4h
+
+       # initialize ICB: GHASH( IV ), IV - r7
+       lxvb16x 30+32, 0, 7     # load IV  - v30
+
+       mr      12, 5           # length
+       li      11, 0           # block index
+
+       # counter 1
+       vxor    31, 31, 31
+       vspltisb 22, 1
+       vsldoi  31, 31, 22,1    # counter 1
+
+       # load round key to VSR
+       lxv     0, 0(6)
+       lxv     1, 0x10(6)
+       lxv     2, 0x20(6)
+       lxv     3, 0x30(6)
+       lxv     4, 0x40(6)
+       lxv     5, 0x50(6)
+       lxv     6, 0x60(6)
+       lxv     7, 0x70(6)
+       lxv     8, 0x80(6)
+       lxv     9, 0x90(6)
+       lxv     10, 0xa0(6)
+
+       # load rounds - 10 (128), 12 (192), 14 (256)
+       lwz     9,480(6)
+
+       #
+       # vxor  state, state, w # addroundkey
+       xxlor   32+29, 0, 0
+       vxor    15, 30, 29      # IV + round key - add round key 0
+
+       cmpdi   9, 10
+       beq     Loop_aes_gcm_8x
+
+       # load 2 more round keys (v11, v12)
+       lxv     11, 0xb0(6)
+       lxv     12, 0xc0(6)
+
+       cmpdi   9, 12
+       beq     Loop_aes_gcm_8x
+
+       # load 2 more round keys (v11, v12, v13, v14)
+       lxv     13, 0xd0(6)
+       lxv     14, 0xe0(6)
+       cmpdi   9, 14
+       beq     Loop_aes_gcm_8x
+
+       b       aes_gcm_out
+
+.align 5
+Loop_aes_gcm_8x:
+       mr      14, 3
+       mr      9, 4
+
+       # n blcoks
+       li      10, 128
+       divdu   10, 5, 10       # n 128 bytes-blocks
+       cmpdi   10, 0
+       beq     Loop_last_block
+
+       vaddudm 30, 30, 31      # IV + counter
+       vxor    16, 30, 29
+       vaddudm 30, 30, 31
+       vxor    17, 30, 29
+       vaddudm 30, 30, 31
+       vxor    18, 30, 29
+       vaddudm 30, 30, 31
+       vxor    19, 30, 29
+       vaddudm 30, 30, 31
+       vxor    20, 30, 29
+       vaddudm 30, 30, 31
+       vxor    21, 30, 29
+       vaddudm 30, 30, 31
+       vxor    22, 30, 29
+
+       mtctr   10
+
+       li      15, 16
+       li      16, 32
+       li      17, 48
+       li      18, 64
+       li      19, 80
+       li      20, 96
+       li      21, 112
+
+       lwz     10, 480(6)
+
+Loop_8x_block:
+
+       lxvb16x         15, 0, 14       # load block
+       lxvb16x         16, 15, 14      # load block
+       lxvb16x         17, 16, 14      # load block
+       lxvb16x         18, 17, 14      # load block
+       lxvb16x         19, 18, 14      # load block
+       lxvb16x         20, 19, 14      # load block
+       lxvb16x         21, 20, 14      # load block
+       lxvb16x         22, 21, 14      # load block
+       addi            14, 14, 128
+
+       Loop_aes_middle8x
+
+       xxlor   23+32, 10, 10
+
+       cmpdi   10, 10
+       beq     Do_next_ghash
+
+       # 192 bits
+       xxlor   24+32, 11, 11
+
+       vcipher 15, 15, 23
+       vcipher 16, 16, 23
+       vcipher 17, 17, 23
+       vcipher 18, 18, 23
+       vcipher 19, 19, 23
+       vcipher 20, 20, 23
+       vcipher 21, 21, 23
+       vcipher 22, 22, 23
+
+       vcipher 15, 15, 24
+       vcipher 16, 16, 24
+       vcipher 17, 17, 24
+       vcipher 18, 18, 24
+       vcipher 19, 19, 24
+       vcipher 20, 20, 24
+       vcipher 21, 21, 24
+       vcipher 22, 22, 24
+
+       xxlor   23+32, 12, 12
+
+       cmpdi   10, 12
+       beq     Do_next_ghash
+
+       # 256 bits
+       xxlor   24+32, 13, 13
+
+       vcipher 15, 15, 23
+       vcipher 16, 16, 23
+       vcipher 17, 17, 23
+       vcipher 18, 18, 23
+       vcipher 19, 19, 23
+       vcipher 20, 20, 23
+       vcipher 21, 21, 23
+       vcipher 22, 22, 23
+
+       vcipher 15, 15, 24
+       vcipher 16, 16, 24
+       vcipher 17, 17, 24
+       vcipher 18, 18, 24
+       vcipher 19, 19, 24
+       vcipher 20, 20, 24
+       vcipher 21, 21, 24
+       vcipher 22, 22, 24
+
+       xxlor   23+32, 14, 14
+
+       cmpdi   10, 14
+       beq     Do_next_ghash
+       b       aes_gcm_out
+
+Do_next_ghash:
+
+       #
+       # last round
+       vcipherlast     15, 15, 23
+       vcipherlast     16, 16, 23
+
+       xxlxor          47, 47, 15
+       stxvb16x        47, 0, 9        # store output
+       xxlxor          48, 48, 16
+       stxvb16x        48, 15, 9       # store output
+
+       vcipherlast     17, 17, 23
+       vcipherlast     18, 18, 23
+
+       xxlxor          49, 49, 17
+       stxvb16x        49, 16, 9       # store output
+       xxlxor          50, 50, 18
+       stxvb16x        50, 17, 9       # store output
+
+       vcipherlast     19, 19, 23
+       vcipherlast     20, 20, 23
+
+       xxlxor          51, 51, 19
+       stxvb16x        51, 18, 9       # store output
+       xxlxor          52, 52, 20
+       stxvb16x        52, 19, 9       # store output
+
+       vcipherlast     21, 21, 23
+       vcipherlast     22, 22, 23
+
+       xxlxor          53, 53, 21
+       stxvb16x        53, 20, 9       # store output
+       xxlxor          54, 54, 22
+       stxvb16x        54, 21, 9       # store output
+
+       addi            9, 9, 128
+
+       # ghash here
+       ppc_aes_gcm_ghash2_4x
+
+       xxlor   27+32, 0, 0
+       vaddudm 30, 30, 31              # IV + counter
+       vmr     29, 30
+       vxor    15, 30, 27              # add round key
+       vaddudm 30, 30, 31
+       vxor    16, 30, 27
+       vaddudm 30, 30, 31
+       vxor    17, 30, 27
+       vaddudm 30, 30, 31
+       vxor    18, 30, 27
+       vaddudm 30, 30, 31
+       vxor    19, 30, 27
+       vaddudm 30, 30, 31
+       vxor    20, 30, 27
+       vaddudm 30, 30, 31
+       vxor    21, 30, 27
+       vaddudm 30, 30, 31
+       vxor    22, 30, 27
+
+       addi    12, 12, -128
+       addi    11, 11, 128
+
+       bdnz    Loop_8x_block
+
+       vmr     30, 29
+
+Loop_last_block:
+       cmpdi   12, 0
+       beq     aes_gcm_out
+
+       # loop last few blocks
+       li      10, 16
+       divdu   10, 12, 10
+
+       mtctr   10
+
+       lwz     10, 480(6)
+
+       cmpdi   12, 16
+       blt     Final_block
+
+.macro Loop_aes_middle_1x
+       xxlor   19+32, 1, 1
+       xxlor   20+32, 2, 2
+       xxlor   21+32, 3, 3
+       xxlor   22+32, 4, 4
+
+       vcipher 15, 15, 19
+       vcipher 15, 15, 20
+       vcipher 15, 15, 21
+       vcipher 15, 15, 22
+
+       xxlor   19+32, 5, 5
+       xxlor   20+32, 6, 6
+       xxlor   21+32, 7, 7
+       xxlor   22+32, 8, 8
+
+       vcipher 15, 15, 19
+       vcipher 15, 15, 20
+       vcipher 15, 15, 21
+       vcipher 15, 15, 22
+
+       xxlor   19+32, 9, 9
+       vcipher 15, 15, 19
+.endm
+
+Next_rem_block:
+       lxvb16x 15, 0, 14               # load block
+
+       Loop_aes_middle_1x
+
+       xxlor   23+32, 10, 10
+
+       cmpdi   10, 10
+       beq     Do_next_1x
+
+       # 192 bits
+       xxlor   24+32, 11, 11
+
+       vcipher 15, 15, 23
+       vcipher 15, 15, 24
+
+       xxlor   23+32, 12, 12
+
+       cmpdi   10, 12
+       beq     Do_next_1x
+
+       # 256 bits
+       xxlor   24+32, 13, 13
+
+       vcipher 15, 15, 23
+       vcipher 15, 15, 24
+
+       xxlor   23+32, 14, 14
+
+       cmpdi   10, 14
+       beq     Do_next_1x
+
+Do_next_1x:
+       vcipherlast     15, 15, 23
+
+       xxlxor          47, 47, 15
+       stxvb16x        47, 0, 9        # store output
+       addi            14, 14, 16
+       addi            9, 9, 16
+
+       vmr             28, 15
+       ppc_update_hash_1x
+
+       addi            12, 12, -16
+       addi            11, 11, 16
+       xxlor           19+32, 0, 0
+       vaddudm         30, 30, 31              # IV + counter
+       vxor            15, 30, 19              # add round key
+
+       bdnz    Next_rem_block
+
+       cmpdi   12, 0
+       beq     aes_gcm_out
+
+Final_block:
+       Loop_aes_middle_1x
+
+       xxlor   23+32, 10, 10
+
+       cmpdi   10, 10
+       beq     Do_final_1x
+
+       # 192 bits
+       xxlor   24+32, 11, 11
+
+       vcipher 15, 15, 23
+       vcipher 15, 15, 24
+
+       xxlor   23+32, 12, 12
+
+       cmpdi   10, 12
+       beq     Do_final_1x
+
+       # 256 bits
+       xxlor   24+32, 13, 13
+
+       vcipher 15, 15, 23
+       vcipher 15, 15, 24
+
+       xxlor   23+32, 14, 14
+
+       cmpdi   10, 14
+       beq     Do_final_1x
+
+Do_final_1x:
+       vcipherlast     15, 15, 23
+
+       lxvb16x 15, 0, 14               # load last block
+       xxlxor  47, 47, 15
+
+       # create partial block mask
+       li      15, 16
+       sub     15, 15, 12              # index to the mask
+
+       vspltisb        16, -1          # first 16 bytes - 0xffff...ff
+       vspltisb        17, 0           # second 16 bytes - 0x0000...00
+       li      10, 192
+       stvx    16, 10, 1
+       addi    10, 10, 16
+       stvx    17, 10, 1
+
+       addi    10, 1, 192
+       lxvb16x 16, 15, 10              # load partial block mask
+       xxland  47, 47, 16
+
+       vmr     28, 15
+       ppc_update_hash_1x
+
+       # * should store only the remaining bytes.
+       bl      Write_partial_block
+
+       b aes_gcm_out
+
+#
+# Write partial block
+# r9 - output
+# r12 - remaining bytes
+# v15 - partial input data
+#
+Write_partial_block:
+       li              10, 192
+       stxvb16x        15+32, 10, 1            # last block
+
+       #add            10, 9, 11               # Output
+       addi            10, 9, -1
+       addi            16, 1, 191
+
+        mtctr          12                      # remaining bytes
+       li              15, 0
+
+Write_last_byte:
+        lbzu           14, 1(16)
+       stbu            14, 1(10)
+        bdnz           Write_last_byte
+       blr
+
+aes_gcm_out:
+       # out = state
+       li      10, 256
+       stxvb16x        32, 10, 8               # write out Xi
+       add     3, 11, 12               # return count
+
+       li      9, 256
+       lvx     20, 9, 1
+       addi    9, 9, 16
+       lvx     21, 9, 1
+       addi    9, 9, 16
+       lvx     22, 9, 1
+       addi    9, 9, 16
+       lvx     23, 9, 1
+       addi    9, 9, 16
+       lvx     24, 9, 1
+       addi    9, 9, 16
+       lvx     25, 9, 1
+       addi    9, 9, 16
+       lvx     26, 9, 1
+       addi    9, 9, 16
+       lvx     27, 9, 1
+       addi    9, 9, 16
+       lvx     28, 9, 1
+       addi    9, 9, 16
+       lvx     29, 9, 1
+       addi    9, 9, 16
+       lvx     30, 9, 1
+       addi    9, 9, 16
+       lvx     31, 9, 1
+
+       ld      0, 528(1)
+       ld      14,112(1)
+       ld      15,120(1)
+       ld      16,128(1)
+       ld      17,136(1)
+       ld      18,144(1)
+       ld      19,152(1)
+       ld      20,160(1)
+       ld      21,168(1)
+
+       mtlr    0
+       addi    1, 1, 512
+       blr
+
+#
+# 8x Decrypt
+#
+.global _gcry_ppc10_aes_gcm_decrypt
+.align 5
+_gcry_ppc10_aes_gcm_decrypt:
+_gcry_ppc_aes_gcm_decrypt:
+
+       stdu 1,-512(1)
+       mflr 0
+
+       std     14,112(1)
+       std     15,120(1)
+       std     16,128(1)
+       std     17,136(1)
+       std     18,144(1)
+       std     19,152(1)
+       std     20,160(1)
+       std     21,168(1)
+       li      9, 256
+       stvx    20, 9, 1
+       addi    9, 9, 16
+       stvx    21, 9, 1
+       addi    9, 9, 16
+       stvx    22, 9, 1
+       addi    9, 9, 16
+       stvx    23, 9, 1
+       addi    9, 9, 16
+       stvx    24, 9, 1
+       addi    9, 9, 16
+       stvx    25, 9, 1
+       addi    9, 9, 16
+       stvx    26, 9, 1
+       addi    9, 9, 16
+       stvx    27, 9, 1
+       addi    9, 9, 16
+       stvx    28, 9, 1
+       addi    9, 9, 16
+       stvx    29, 9, 1
+       addi    9, 9, 16
+       stvx    30, 9, 1
+       addi    9, 9, 16
+       stvx    31, 9, 1
+       std     0, 528(1)
+
+       # Load Xi
+       li      10, 256
+       lxvb16x 32, 10, 8       # load Xi
+
+       # load Hash - h^4, h^3, h^2, h
+       lxvd2x  2+32, 0, 8      # H Poli
+       li      10, 16
+       lxvd2x  3+32, 10, 8     # Hl
+       li      10, 32
+       lxvd2x  4+32, 10, 8     # H
+       li      10, 48
+       lxvd2x  5+32, 10, 8     # Hh
+
+       li      10, 64
+       lxvd2x  6+32, 10, 8     # H^2l
+       li      10, 80
+       lxvd2x  7+32, 10, 8     # H^2
+       li      10, 96
+       lxvd2x  8+32, 10, 8     # H^2h
+
+       li      10, 112
+       lxvd2x  9+32, 10, 8     # H^3l
+       li      10, 128
+       lxvd2x  10+32, 10, 8    # H^3
+       li      10, 144
+       lxvd2x  11+32, 10, 8    # H^3h
+
+       li      10, 160
+       lxvd2x  12+32, 10, 8    # H^4l
+       li      10, 176
+       lxvd2x  13+32, 10, 8    # H^4
+       li      10, 192
+       lxvd2x  14+32, 10, 8    # H^4h
+
+       # initialize ICB: GHASH( IV ), IV - r7
+       lxvb16x 30+32, 0, 7     # load IV  - v30
+
+       mr      12, 5           # length
+       li      11, 0           # block index
+
+       # counter 1
+       vxor    31, 31, 31
+       vspltisb 22, 1
+       vsldoi  31, 31, 22,1    # counter 1
+
+       # load round key to VSR
+       lxv     0, 0(6)
+       lxv     1, 0x10(6)
+       lxv     2, 0x20(6)
+       lxv     3, 0x30(6)
+       lxv     4, 0x40(6)
+       lxv     5, 0x50(6)
+       lxv     6, 0x60(6)
+       lxv     7, 0x70(6)
+       lxv     8, 0x80(6)
+       lxv     9, 0x90(6)
+       lxv     10, 0xa0(6)
+
+       # load rounds - 10 (128), 12 (192), 14 (256)
+       lwz     9,480(6)
+
+       #
+       # vxor  state, state, w # addroundkey
+       xxlor   32+29, 0, 0
+       vxor    15, 30, 29      # IV + round key - add round key 0
+
+       cmpdi   9, 10
+       beq     Loop_aes_gcm_8x_dec
+
+       # load 2 more round keys (v11, v12)
+       lxv     11, 0xb0(6)
+       lxv     12, 0xc0(6)
+
+       cmpdi   9, 12
+       beq     Loop_aes_gcm_8x_dec
+
+       # load 2 more round keys (v11, v12, v13, v14)
+       lxv     13, 0xd0(6)
+       lxv     14, 0xe0(6)
+       cmpdi   9, 14
+       beq     Loop_aes_gcm_8x_dec
+
+       b       aes_gcm_out
+
+.align 5
+Loop_aes_gcm_8x_dec:
+       mr      14, 3
+       mr      9, 4
+
+       # n blcoks
+       li      10, 128
+       divdu   10, 5, 10       # n 128 bytes-blocks
+       cmpdi   10, 0
+       beq     Loop_last_block_dec
+
+       vaddudm 30, 30, 31      # IV + counter
+       vxor    16, 30, 29
+       vaddudm 30, 30, 31
+       vxor    17, 30, 29
+       vaddudm 30, 30, 31
+       vxor    18, 30, 29
+       vaddudm 30, 30, 31
+       vxor    19, 30, 29
+       vaddudm 30, 30, 31
+       vxor    20, 30, 29
+       vaddudm 30, 30, 31
+       vxor    21, 30, 29
+       vaddudm 30, 30, 31
+       vxor    22, 30, 29
+
+       mtctr   10
+
+       li      15, 16
+       li      16, 32
+       li      17, 48
+       li      18, 64
+       li      19, 80
+       li      20, 96
+       li      21, 112
+
+       lwz     10, 480(6)
+
+Loop_8x_block_dec:
+
+       lxvb16x         15, 0, 14       # load block
+       lxvb16x         16, 15, 14      # load block
+       lxvb16x         17, 16, 14      # load block
+       lxvb16x         18, 17, 14      # load block
+       lxvb16x         19, 18, 14      # load block
+       lxvb16x         20, 19, 14      # load block
+       lxvb16x         21, 20, 14      # load block
+       lxvb16x         22, 21, 14      # load block
+       addi            14, 14, 128
+
+       Loop_aes_middle8x
+
+       xxlor   23+32, 10, 10
+
+       cmpdi   10, 10
+       beq     Do_last_aes_dec
+
+       # 192 bits
+       xxlor   24+32, 11, 11
+
+       vcipher 15, 15, 23
+       vcipher 16, 16, 23
+       vcipher 17, 17, 23
+       vcipher 18, 18, 23
+       vcipher 19, 19, 23
+       vcipher 20, 20, 23
+       vcipher 21, 21, 23
+       vcipher 22, 22, 23
+
+       vcipher 15, 15, 24
+       vcipher 16, 16, 24
+       vcipher 17, 17, 24
+       vcipher 18, 18, 24
+       vcipher 19, 19, 24
+       vcipher 20, 20, 24
+       vcipher 21, 21, 24
+       vcipher 22, 22, 24
+
+       xxlor   23+32, 12, 12
+
+       cmpdi   10, 12
+       beq     Do_last_aes_dec
+
+       # 256 bits
+       xxlor   24+32, 13, 13
+
+       vcipher 15, 15, 23
+       vcipher 16, 16, 23
+       vcipher 17, 17, 23
+       vcipher 18, 18, 23
+       vcipher 19, 19, 23
+       vcipher 20, 20, 23
+       vcipher 21, 21, 23
+       vcipher 22, 22, 23
+
+       vcipher 15, 15, 24
+       vcipher 16, 16, 24
+       vcipher 17, 17, 24
+       vcipher 18, 18, 24
+       vcipher 19, 19, 24
+       vcipher 20, 20, 24
+       vcipher 21, 21, 24
+       vcipher 22, 22, 24
+
+       xxlor   23+32, 14, 14
+
+       cmpdi   10, 14
+       beq     Do_last_aes_dec
+       b       aes_gcm_out
+
+Do_last_aes_dec:
+
+       #
+       # last round
+       vcipherlast     15, 15, 23
+       vcipherlast     16, 16, 23
+
+       xxlxor          47, 47, 15
+       stxvb16x        47, 0, 9        # store output
+       xxlxor          48, 48, 16
+       stxvb16x        48, 15, 9       # store output
+
+       vcipherlast     17, 17, 23
+       vcipherlast     18, 18, 23
+
+       xxlxor          49, 49, 17
+       stxvb16x        49, 16, 9       # store output
+       xxlxor          50, 50, 18
+       stxvb16x        50, 17, 9       # store output
+
+       vcipherlast     19, 19, 23
+       vcipherlast     20, 20, 23
+
+       xxlxor          51, 51, 19
+       stxvb16x        51, 18, 9       # store output
+       xxlxor          52, 52, 20
+       stxvb16x        52, 19, 9       # store output
+
+       vcipherlast     21, 21, 23
+       vcipherlast     22, 22, 23
+
+       xxlxor          53, 53, 21
+       stxvb16x        53, 20, 9       # store output
+       xxlxor          54, 54, 22
+       stxvb16x        54, 21, 9       # store output
+
+       addi            9, 9, 128
+
+       xxlor           15+32, 15, 15
+       xxlor           16+32, 16, 16
+       xxlor           17+32, 17, 17
+       xxlor           18+32, 18, 18
+       xxlor           19+32, 19, 19
+       xxlor           20+32, 20, 20
+       xxlor           21+32, 21, 21
+       xxlor           22+32, 22, 22
+
+       # ghash here
+       ppc_aes_gcm_ghash2_4x
+
+       xxlor   27+32, 0, 0
+       vaddudm 30, 30, 31              # IV + counter
+       vmr     29, 30
+       vxor    15, 30, 27              # add round key
+       vaddudm 30, 30, 31
+       vxor    16, 30, 27
+       vaddudm 30, 30, 31
+       vxor    17, 30, 27
+       vaddudm 30, 30, 31
+       vxor    18, 30, 27
+       vaddudm 30, 30, 31
+       vxor    19, 30, 27
+       vaddudm 30, 30, 31
+       vxor    20, 30, 27
+       vaddudm 30, 30, 31
+       vxor    21, 30, 27
+       vaddudm 30, 30, 31
+       vxor    22, 30, 27
+       addi    12, 12, -128
+       addi    11, 11, 128
+
+       bdnz    Loop_8x_block_dec
+
+       vmr     30, 29
+
+Loop_last_block_dec:
+       cmpdi   12, 0
+       beq     aes_gcm_out
+
+       # loop last few blocks
+       li      10, 16
+       divdu   10, 12, 10
+
+       mtctr   10
+
+       lwz     10,480(6)
+
+       cmpdi   12, 16
+       blt     Final_block_dec
+
+Next_rem_block_dec:
+       lxvb16x 15, 0, 14               # load block
+
+       Loop_aes_middle_1x
+
+       xxlor   23+32, 10, 10
+
+       cmpdi   10, 10
+       beq     Do_next_1x_dec
+
+       # 192 bits
+       xxlor   24+32, 11, 11
+
+       vcipher 15, 15, 23
+       vcipher 15, 15, 24
+
+       xxlor   23+32, 12, 12
+
+       cmpdi   10, 12
+       beq     Do_next_1x_dec
+
+       # 256 bits
+       xxlor   24+32, 13, 13
+
+       vcipher 15, 15, 23
+       vcipher 15, 15, 24
+
+       xxlor   23+32, 14, 14
+
+       cmpdi   10, 14
+       beq     Do_next_1x_dec
+
+Do_next_1x_dec:
+       vcipherlast     15, 15, 23
+
+       xxlxor  47, 47, 15
+       stxvb16x        47, 0, 9        # store output
+       addi    14, 14, 16
+       addi    9, 9, 16
+
+       xxlor   28+32, 15, 15
+       ppc_update_hash_1x
+
+       addi    12, 12, -16
+       addi    11, 11, 16
+       xxlor   19+32, 0, 0
+       vaddudm 30, 30, 31              # IV + counter
+       vxor    15, 30, 19              # add round key
+
+       bdnz    Next_rem_block_dec
+
+       cmpdi   12, 0
+       beq     aes_gcm_out
+
+Final_block_dec:
+       Loop_aes_middle_1x
+
+       xxlor   23+32, 10, 10
+
+       cmpdi   10, 10
+       beq     Do_final_1x_dec
+
+       # 192 bits
+       xxlor   24+32, 11, 11
+
+       vcipher 15, 15, 23
+       vcipher 15, 15, 24
+
+       xxlor   23+32, 12, 12
+
+       cmpdi   10, 12
+       beq     Do_final_1x_dec
+
+       # 256 bits
+       xxlor   24+32, 13, 13
+
+       vcipher 15, 15, 23
+       vcipher 15, 15, 24
+
+       xxlor   23+32, 14, 14
+
+       cmpdi   10, 14
+       beq     Do_final_1x_dec
+
+Do_final_1x_dec:
+       vcipherlast     15, 15, 23
+
+       lxvb16x 15, 0, 14               # load block
+       xxlxor  47, 47, 15
+
+       # create partial block mask
+       li      15, 16
+       sub     15, 15, 12              # index to the mask
+
+       vspltisb        16, -1          # first 16 bytes - 0xffff...ff
+       vspltisb        17, 0           # second 16 bytes - 0x0000...00
+       li      10, 192
+       stvx    16, 10, 1
+       addi    10, 10, 16
+       stvx    17, 10, 1
+
+       addi    10, 1, 192
+       lxvb16x 16, 15, 10              # load block mask
+       xxland  47, 47, 16
+
+       xxlor   28+32, 15, 15
+       ppc_update_hash_1x
+
+       # * should store only the remaining bytes.
+       bl      Write_partial_block
+
+       b aes_gcm_out
+#
index 160fb8c..3060408 100644 (file)
 #define BLOCKSIZE               (128/8)
 
 
-/* Helper macro to force alignment to 16 bytes.  */
+/* Helper macro to force alignment to 16 or 64 bytes.  */
 #ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
 # define ATTR_ALIGNED_16  __attribute__ ((aligned (16)))
+# define ATTR_ALIGNED_64  __attribute__ ((aligned (64)))
 #else
 # define ATTR_ALIGNED_16
+# define ATTR_ALIGNED_64
 #endif
 
 
@@ -73,7 +75,7 @@
 #   define USE_PADLOCK 1
 #  endif
 # endif
-#endif /*ENABLE_PADLOCK_SUPPORT*/
+#endif /* ENABLE_PADLOCK_SUPPORT */
 
 /* USE_AESNI inidicates whether to compile with Intel AES-NI code.  We
    need the vector-size attribute which seems to be available since
 # endif
 #endif /* ENABLE_AESNI_SUPPORT */
 
+/* USE_VAES inidicates whether to compile with Intel VAES code.  */
+#undef USE_VAES
+#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
+     defined(__x86_64__) && defined(ENABLE_AVX2_SUPPORT) && \
+     defined(HAVE_GCC_INLINE_ASM_VAES_VPCLMUL) && \
+     defined(USE_AESNI)
+# define USE_VAES 1
+#endif
+
 /* USE_ARM_CE indicates whether to enable ARMv8 Crypto Extension assembly
  * code. */
 #undef USE_ARM_CE
 # endif
 #endif /* ENABLE_ARM_CRYPTO_SUPPORT */
 
+/* USE_PPC_CRYPTO indicates whether to enable PowerPC vector crypto
+ * accelerated code.  USE_PPC_CRYPTO_WITH_PPC9LE indicates whether to
+ * enable POWER9 optimized variant.  */
+#undef USE_PPC_CRYPTO
+#undef USE_PPC_CRYPTO_WITH_PPC9LE
+#ifdef ENABLE_PPC_CRYPTO_SUPPORT
+# if defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+     defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC)
+#  if __GNUC__ >= 4
+#   define USE_PPC_CRYPTO 1
+#   if !defined(WORDS_BIGENDIAN) && defined(HAVE_GCC_INLINE_ASM_PPC_ARCH_3_00)
+#    define USE_PPC_CRYPTO_WITH_PPC9LE 1
+#   endif
+#  endif
+# endif
+#endif /* ENABLE_PPC_CRYPTO_SUPPORT */
+
+/* USE_S390X_CRYPTO indicates whether to enable zSeries code. */
+#undef USE_S390X_CRYPTO
+#if defined(HAVE_GCC_INLINE_ASM_S390X)
+# define USE_S390X_CRYPTO 1
+#endif /* USE_S390X_CRYPTO */
+
 struct RIJNDAEL_context_s;
 
 typedef unsigned int (*rijndael_cryptfn_t)(const struct RIJNDAEL_context_s *ctx,
                                            unsigned char *bx,
                                            const unsigned char *ax);
 typedef void (*rijndael_prefetchfn_t)(void);
+typedef void (*rijndael_prepare_decfn_t)(struct RIJNDAEL_context_s *ctx);
 
 /* Our context object.  */
 typedef struct RIJNDAEL_context_s
@@ -138,22 +174,24 @@ typedef struct RIJNDAEL_context_s
   } u2;
   int rounds;                         /* Key-length-dependent number of rounds.  */
   unsigned int decryption_prepared:1; /* The decryption key schedule is available.  */
-#ifdef USE_PADLOCK
-  unsigned int use_padlock:1;         /* Padlock shall be used.  */
-#endif /*USE_PADLOCK*/
 #ifdef USE_AESNI
-  unsigned int use_aesni:1;           /* AES-NI shall be used.  */
+  unsigned int use_avx:1;             /* AVX shall be used by AES-NI implementation. */
+  unsigned int use_avx2:1;            /* AVX2 shall be used by AES-NI implementation. */
 #endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  unsigned int use_ssse3:1;           /* SSSE3 shall be used.  */
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  unsigned int use_arm_ce:1;          /* ARMv8 CE shall be used.  */
-#endif /*USE_ARM_CE*/
+#ifdef USE_S390X_CRYPTO
+  byte km_func;
+  byte km_func_xts;
+  byte kmc_func;
+  byte kmac_func;
+  byte kmf_func;
+  byte kmo_func;
+  byte kma_func;
+#endif /*USE_S390X_CRYPTO*/
   rijndael_cryptfn_t encrypt_fn;
   rijndael_cryptfn_t decrypt_fn;
   rijndael_prefetchfn_t prefetch_enc_fn;
   rijndael_prefetchfn_t prefetch_dec_fn;
+  rijndael_prepare_decfn_t prepare_decryption;
 } RIJNDAEL_context ATTR_ALIGNED_16;
 
 /* Macros defining alias for the keyschedules.  */
diff --git a/cipher/rijndael-p10le.c b/cipher/rijndael-p10le.c
new file mode 100644 (file)
index 0000000..b16ebe1
--- /dev/null
@@ -0,0 +1,119 @@
+/* Rijndael (AES) for GnuPG - PowerPC Vector Crypto AES implementation
+ * Copyright 2021- IBM Inc. All rights reserved
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Alternatively, this code may be used in OpenSSL from The OpenSSL Project,
+ * and Cryptogams by Andy Polyakov, and if made part of a release of either
+ * or both projects, is thereafter dual-licensed under the license said project
+ * is released under.
+ */
+
+#include <config.h>
+
+#include "rijndael-internal.h"
+#include "cipher-internal.h"
+#include "bufhelp.h"
+
+#ifdef USE_PPC_CRYPTO_WITH_PPC9LE
+
+
+extern size_t _gcry_ppc10_aes_gcm_encrypt (const void *inp, void *out,
+                                           size_t len,
+                                           const unsigned char *key,
+                                           unsigned char iv[16], void *Xip);
+extern size_t _gcry_ppc10_aes_gcm_decrypt (const void *inp, void *out,
+                                           size_t len,
+                                           const unsigned char *key,
+                                           unsigned char iv[16], void *Xip);
+
+size_t
+_gcry_aes_p10le_gcm_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
+                          const void *inbuf_arg, size_t nblocks, int encrypt)
+{
+  RIJNDAEL_context *ctx = (RIJNDAEL_context *) &c->context.c;
+  unsigned char *rk = (unsigned char *) ctx->u1.keyschedule;
+  unsigned char *gcm_table = (unsigned char *) c->u_mode.gcm.gcm_table;
+  unsigned char *iv = c->u_ctr.ctr;
+  unsigned char *Xi = c->u_mode.gcm.u_tag.tag;
+  int s = 0;
+  int ndone = 0;
+  int ctr_reset = 0;
+  size_t len = nblocks * GCRY_GCM_BLOCK_LEN;
+  u64 blocks_unused;
+  u64 nb = nblocks;
+  u64 next_ctr = 0;
+  unsigned char ctr_saved[12];
+  unsigned char *inp = (unsigned char *) inbuf_arg;
+  unsigned char *out = (unsigned char *) outbuf_arg;
+
+  /*
+   * This is what the aes-gcm asembly code expects some input parameters.
+   *
+   *   - Number of rounds is at 480 offset from rk (rk->rounds)
+   *   - Xi at 256 offset from gcm_table
+   */
+  gcry_assert (sizeof(c->u_mode.gcm.gcm_table) >= 256 + 16);
+  buf_cpy (gcm_table+256, Xi, 16);
+  buf_cpy (ctr_saved, c->u_ctr.ctr, 12);
+
+  while (nb)
+    {
+      blocks_unused = (u64) 0xffffffffU + 1 - (u64) buf_get_be32 (iv + 12);
+      if (nb > blocks_unused)
+        {
+          len = blocks_unused * GCRY_GCM_BLOCK_LEN;
+          nb -= blocks_unused;
+          next_ctr = blocks_unused;
+          ctr_reset = 1;
+        }
+      else
+        {
+          len = nb * GCRY_GCM_BLOCK_LEN;
+          next_ctr = nb;
+          nb = 0;
+        }
+
+      if (encrypt)
+        s = _gcry_ppc10_aes_gcm_encrypt((const void *) inp, (void *) out, len,
+                                        (const unsigned char *) rk, iv,
+                                        (void *) gcm_table);
+      else
+        s = _gcry_ppc10_aes_gcm_decrypt((const void *) inp, (void *) out, len,
+                                        (const unsigned char *) rk, iv,
+                                        (void *) gcm_table);
+
+      cipher_block_add(c->u_ctr.ctr, next_ctr, GCRY_GCM_BLOCK_LEN);
+      if (ctr_reset)
+        {
+          ctr_reset = 0;
+          inp += len;
+          out += len;
+        }
+      buf_cpy (c->u_ctr.ctr, ctr_saved, 12);
+      ndone += s;
+    }
+  buf_cpy (Xi, gcm_table+256, 16);
+
+  /*
+   * Return number of blocks done.
+   */
+  s = ndone / GCRY_GCM_BLOCK_LEN;
+  s = nblocks - s;
+  return ( s );
+}
+
+#endif /* USE_PPC_CRYPTO_WITH_PPC9LE */
index 234751b..3af214d 100644 (file)
@@ -101,4 +101,10 @@ _gcry_aes_padlock_decrypt (const RIJNDAEL_context *ctx,
   return do_padlock(ctx, bx, ax, 1);
 }
 
+void
+_gcry_aes_padlock_prepare_decryption (RIJNDAEL_context *ctx)
+{
+  /* Padlock does not need decryption subkeys. */
+  (void)ctx;
+}
 #endif /* USE_PADLOCK */
diff --git a/cipher/rijndael-ppc-common.h b/cipher/rijndael-ppc-common.h
new file mode 100644 (file)
index 0000000..bbbeaac
--- /dev/null
@@ -0,0 +1,342 @@
+/* Rijndael (AES) for GnuPG - PowerPC Vector Crypto AES implementation
+ * Copyright (C) 2019 Shawn Landden <shawn@git.icu>
+ * Copyright (C) 2019-2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Alternatively, this code may be used in OpenSSL from The OpenSSL Project,
+ * and Cryptogams by Andy Polyakov, and if made part of a release of either
+ * or both projects, is thereafter dual-licensed under the license said project
+ * is released under.
+ */
+
+#ifndef G10_RIJNDAEL_PPC_COMMON_H
+#define G10_RIJNDAEL_PPC_COMMON_H
+
+#include <altivec.h>
+
+
+typedef vector unsigned char block;
+
+typedef union
+{
+  u32 data32[4];
+} __attribute__((packed, aligned(1), may_alias)) u128_t;
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR          NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE   ASM_FUNC_ATTR ALWAYS_INLINE
+#define ASM_FUNC_ATTR_NOINLINE ASM_FUNC_ATTR NO_INLINE
+
+
+#define ALIGNED_LOAD(in_ptr, offs) \
+  (asm_aligned_ld ((offs) * 16, (const void *)(in_ptr)))
+
+#define ALIGNED_STORE(out_ptr, offs, vec) \
+  (asm_aligned_st ((vec), (offs) * 16, (void *)(out_ptr)))
+
+#define VEC_BE_SWAP(vec, bige_const) (asm_be_swap ((vec), (bige_const)))
+
+#define VEC_LOAD_BE(in_ptr, offs, bige_const) \
+  (asm_be_swap (asm_load_be_noswap ((offs) * 16, (const void *)(in_ptr)), \
+               bige_const))
+
+#define VEC_LOAD_BE_NOSWAP(in_ptr, offs) \
+  (asm_load_be_noswap ((offs) * 16, (const unsigned char *)(in_ptr)))
+
+#define VEC_STORE_BE(out_ptr, offs, vec, bige_const) \
+  (asm_store_be_noswap (asm_be_swap ((vec), (bige_const)), (offs) * 16, \
+                       (void *)(out_ptr)))
+
+#define VEC_STORE_BE_NOSWAP(out_ptr, offs, vec) \
+  (asm_store_be_noswap ((vec), (offs) * 16, (void *)(out_ptr)))
+
+
+#define ROUND_KEY_VARIABLES \
+  block rkey0, rkeylast
+
+#define PRELOAD_ROUND_KEYS(nrounds) \
+  do { \
+    rkey0 = ALIGNED_LOAD (rk, 0); \
+    rkeylast = ALIGNED_LOAD (rk, nrounds); \
+  } while (0)
+
+#define AES_ENCRYPT(blk, nrounds) \
+  do { \
+    blk ^= rkey0; \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 1)); \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 2)); \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 3)); \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 4)); \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 5)); \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 6)); \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 7)); \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 8)); \
+    blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 9)); \
+    if (nrounds >= 12) \
+      { \
+       blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 10)); \
+       blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 11)); \
+       if (rounds > 12) \
+         { \
+           blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 12)); \
+           blk = asm_cipher_be (blk, ALIGNED_LOAD (rk, 13)); \
+         } \
+      } \
+    blk = asm_cipherlast_be (blk, rkeylast); \
+  } while (0)
+
+#define AES_DECRYPT(blk, nrounds) \
+  do { \
+    blk ^= rkey0; \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 1)); \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 2)); \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 3)); \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 4)); \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 5)); \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 6)); \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 7)); \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 8)); \
+    blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 9)); \
+    if (nrounds >= 12) \
+      { \
+       blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 10)); \
+       blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 11)); \
+       if (rounds > 12) \
+         { \
+           blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 12)); \
+           blk = asm_ncipher_be (blk, ALIGNED_LOAD (rk, 13)); \
+         } \
+      } \
+    blk = asm_ncipherlast_be (blk, rkeylast); \
+  } while (0)
+
+
+#define ROUND_KEY_VARIABLES_ALL \
+  block rkey0, rkey1, rkey2, rkey3, rkey4, rkey5, rkey6, rkey7, rkey8, \
+        rkey9, rkey10, rkey11, rkey12, rkey13, rkeylast
+
+#define PRELOAD_ROUND_KEYS_ALL(nrounds) \
+  do { \
+    rkey0 = ALIGNED_LOAD (rk, 0); \
+    rkey1 = ALIGNED_LOAD (rk, 1); \
+    rkey2 = ALIGNED_LOAD (rk, 2); \
+    rkey3 = ALIGNED_LOAD (rk, 3); \
+    rkey4 = ALIGNED_LOAD (rk, 4); \
+    rkey5 = ALIGNED_LOAD (rk, 5); \
+    rkey6 = ALIGNED_LOAD (rk, 6); \
+    rkey7 = ALIGNED_LOAD (rk, 7); \
+    rkey8 = ALIGNED_LOAD (rk, 8); \
+    rkey9 = ALIGNED_LOAD (rk, 9); \
+    if (nrounds >= 12) \
+      { \
+       rkey10 = ALIGNED_LOAD (rk, 10); \
+       rkey11 = ALIGNED_LOAD (rk, 11); \
+       if (rounds > 12) \
+         { \
+           rkey12 = ALIGNED_LOAD (rk, 12); \
+           rkey13 = ALIGNED_LOAD (rk, 13); \
+         } \
+      } \
+    rkeylast = ALIGNED_LOAD (rk, nrounds); \
+  } while (0)
+
+#define AES_ENCRYPT_ALL(blk, nrounds) \
+  do { \
+    blk ^= rkey0; \
+    blk = asm_cipher_be (blk, rkey1); \
+    blk = asm_cipher_be (blk, rkey2); \
+    blk = asm_cipher_be (blk, rkey3); \
+    blk = asm_cipher_be (blk, rkey4); \
+    blk = asm_cipher_be (blk, rkey5); \
+    blk = asm_cipher_be (blk, rkey6); \
+    blk = asm_cipher_be (blk, rkey7); \
+    blk = asm_cipher_be (blk, rkey8); \
+    blk = asm_cipher_be (blk, rkey9); \
+    if (nrounds >= 12) \
+      { \
+       blk = asm_cipher_be (blk, rkey10); \
+       blk = asm_cipher_be (blk, rkey11); \
+       if (rounds > 12) \
+         { \
+           blk = asm_cipher_be (blk, rkey12); \
+           blk = asm_cipher_be (blk, rkey13); \
+         } \
+      } \
+    blk = asm_cipherlast_be (blk, rkeylast); \
+  } while (0)
+
+
+static ASM_FUNC_ATTR_INLINE block
+asm_aligned_ld(unsigned long offset, const void *ptr)
+{
+  block vec;
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("lvx %0,0,%1\n\t"
+                     : "=v" (vec)
+                     : "r" ((uintptr_t)ptr)
+                     : "memory");
+  else
+#endif
+    __asm__ volatile ("lvx %0,%1,%2\n\t"
+                     : "=v" (vec)
+                     : "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+  return vec;
+}
+
+static ASM_FUNC_ATTR_INLINE void
+asm_aligned_st(block vec, unsigned long offset, void *ptr)
+{
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("stvx %0,0,%1\n\t"
+                     :
+                     : "v" (vec), "r" ((uintptr_t)ptr)
+                     : "memory");
+  else
+#endif
+    __asm__ volatile ("stvx %0,%1,%2\n\t"
+                     :
+                     : "v" (vec), "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_vperm1(block vec, block mask)
+{
+  block o;
+  __asm__ volatile ("vperm %0,%1,%1,%2\n\t"
+                   : "=v" (o)
+                   : "v" (vec), "v" (mask));
+  return o;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_add_uint128(block a, block b)
+{
+  block res;
+  __asm__ volatile ("vadduqm %0,%1,%2\n\t"
+                   : "=v" (res)
+                   : "v" (a), "v" (b));
+  return res;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_add_uint64(block a, block b)
+{
+  block res;
+  __asm__ volatile ("vaddudm %0,%1,%2\n\t"
+                   : "=v" (res)
+                   : "v" (a), "v" (b));
+  return res;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_sra_int64(block a, block b)
+{
+  block res;
+  __asm__ volatile ("vsrad %0,%1,%2\n\t"
+                   : "=v" (res)
+                   : "v" (a), "v" (b));
+  return res;
+}
+
+static block
+asm_swap_uint64_halfs(block a)
+{
+  block res;
+  __asm__ volatile ("xxswapd %x0, %x1"
+                   : "=wa" (res)
+                   : "wa" (a));
+  return res;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_xor(block a, block b)
+{
+  block res;
+  __asm__ volatile ("vxor %0,%1,%2\n\t"
+                   : "=v" (res)
+                   : "v" (a), "v" (b));
+  return res;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_cipher_be(block b, block rk)
+{
+  block o;
+  __asm__ volatile ("vcipher %0, %1, %2\n\t"
+                   : "=v" (o)
+                   : "v" (b), "v" (rk));
+  return o;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_cipherlast_be(block b, block rk)
+{
+  block o;
+  __asm__ volatile ("vcipherlast %0, %1, %2\n\t"
+                   : "=v" (o)
+                   : "v" (b), "v" (rk));
+  return o;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_ncipher_be(block b, block rk)
+{
+  block o;
+  __asm__ volatile ("vncipher %0, %1, %2\n\t"
+                   : "=v" (o)
+                   : "v" (b), "v" (rk));
+  return o;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_ncipherlast_be(block b, block rk)
+{
+  block o;
+  __asm__ volatile ("vncipherlast %0, %1, %2\n\t"
+                   : "=v" (o)
+                   : "v" (b), "v" (rk));
+  return o;
+}
+
+
+/* Make a decryption key from an encryption key. */
+static ASM_FUNC_ATTR_INLINE void
+internal_aes_ppc_prepare_decryption (RIJNDAEL_context *ctx)
+{
+  u128_t *ekey = (u128_t *)(void *)ctx->keyschenc;
+  u128_t *dkey = (u128_t *)(void *)ctx->keyschdec;
+  int rounds = ctx->rounds;
+  int rr;
+  int r;
+
+  r = 0;
+  rr = rounds;
+  for (r = 0, rr = rounds; r <= rounds; r++, rr--)
+    {
+      ALIGNED_STORE (dkey, r, ALIGNED_LOAD (ekey, rr));
+    }
+}
+
+#endif /* G10_RIJNDAEL_PPC_COMMON_H */
diff --git a/cipher/rijndael-ppc-functions.h b/cipher/rijndael-ppc-functions.h
new file mode 100644 (file)
index 0000000..72f3185
--- /dev/null
@@ -0,0 +1,2020 @@
+/* Rijndael (AES) for GnuPG - PowerPC Vector Crypto AES implementation
+ * Copyright (C) 2019 Shawn Landden <shawn@git.icu>
+ * Copyright (C) 2019-2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Alternatively, this code may be used in OpenSSL from The OpenSSL Project,
+ * and Cryptogams by Andy Polyakov, and if made part of a release of either
+ * or both projects, is thereafter dual-licensed under the license said project
+ * is released under.
+ */
+
+unsigned int ENCRYPT_BLOCK_FUNC (const RIJNDAEL_context *ctx,
+                                unsigned char *out,
+                                const unsigned char *in)
+{
+  const block bige_const = asm_load_be_const();
+  const u128_t *rk = (u128_t *)&ctx->keyschenc;
+  int rounds = ctx->rounds;
+  ROUND_KEY_VARIABLES;
+  block b;
+
+  b = VEC_LOAD_BE (in, 0, bige_const);
+
+  PRELOAD_ROUND_KEYS (rounds);
+
+  AES_ENCRYPT (b, rounds);
+  VEC_STORE_BE (out, 0, b, bige_const);
+
+  return 0; /* does not use stack */
+}
+
+
+unsigned int DECRYPT_BLOCK_FUNC (const RIJNDAEL_context *ctx,
+                                unsigned char *out,
+                                const unsigned char *in)
+{
+  const block bige_const = asm_load_be_const();
+  const u128_t *rk = (u128_t *)&ctx->keyschdec;
+  int rounds = ctx->rounds;
+  ROUND_KEY_VARIABLES;
+  block b;
+
+  b = VEC_LOAD_BE (in, 0, bige_const);
+
+  PRELOAD_ROUND_KEYS (rounds);
+
+  AES_DECRYPT (b, rounds);
+  VEC_STORE_BE (out, 0, b, bige_const);
+
+  return 0; /* does not use stack */
+}
+
+
+void CFB_ENC_FUNC (void *context, unsigned char *iv_arg,
+                  void *outbuf_arg, const void *inbuf_arg,
+                  size_t nblocks)
+{
+  const block bige_const = asm_load_be_const();
+  RIJNDAEL_context *ctx = context;
+  const u128_t *rk = (u128_t *)&ctx->keyschenc;
+  const u128_t *in = (const u128_t *)inbuf_arg;
+  u128_t *out = (u128_t *)outbuf_arg;
+  int rounds = ctx->rounds;
+  ROUND_KEY_VARIABLES_ALL;
+  block rkeylast_orig;
+  block iv;
+
+  iv = VEC_LOAD_BE (iv_arg, 0, bige_const);
+
+  PRELOAD_ROUND_KEYS_ALL (rounds);
+  rkeylast_orig = rkeylast;
+
+  for (; nblocks >= 2; nblocks -= 2)
+    {
+      block in2, iv1;
+
+      rkeylast = rkeylast_orig ^ VEC_LOAD_BE (in, 0, bige_const);
+      in2 = VEC_LOAD_BE (in + 1, 0, bige_const);
+      in += 2;
+
+      AES_ENCRYPT_ALL (iv, rounds);
+
+      iv1 = iv;
+      rkeylast = rkeylast_orig ^ in2;
+
+      AES_ENCRYPT_ALL (iv, rounds);
+
+      VEC_STORE_BE (out++, 0, iv1, bige_const);
+      VEC_STORE_BE (out++, 0, iv, bige_const);
+    }
+
+  for (; nblocks; nblocks--)
+    {
+      rkeylast = rkeylast_orig ^ VEC_LOAD_BE (in++, 0, bige_const);
+
+      AES_ENCRYPT_ALL (iv, rounds);
+
+      VEC_STORE_BE (out++, 0, iv, bige_const);
+    }
+
+  VEC_STORE_BE (iv_arg, 0, iv, bige_const);
+}
+
+void CFB_DEC_FUNC (void *context, unsigned char *iv_arg,
+                  void *outbuf_arg, const void *inbuf_arg,
+                  size_t nblocks)
+{
+  const block bige_const = asm_load_be_const();
+  RIJNDAEL_context *ctx = context;
+  const u128_t *rk = (u128_t *)&ctx->keyschenc;
+  const u128_t *in = (const u128_t *)inbuf_arg;
+  u128_t *out = (u128_t *)outbuf_arg;
+  int rounds = ctx->rounds;
+  ROUND_KEY_VARIABLES;
+  block rkeylast_orig;
+  block iv, b, bin;
+  block in0, in1, in2, in3, in4, in5, in6, in7;
+  block b0, b1, b2, b3, b4, b5, b6, b7;
+  block rkey;
+
+  iv = VEC_LOAD_BE (iv_arg, 0, bige_const);
+
+  PRELOAD_ROUND_KEYS (rounds);
+  rkeylast_orig = rkeylast;
+
+  for (; nblocks >= 8; nblocks -= 8)
+    {
+      in0 = iv;
+      in1 = VEC_LOAD_BE_NOSWAP (in, 0);
+      in2 = VEC_LOAD_BE_NOSWAP (in, 1);
+      in3 = VEC_LOAD_BE_NOSWAP (in, 2);
+      in4 = VEC_LOAD_BE_NOSWAP (in, 3);
+      in1 = VEC_BE_SWAP (in1, bige_const);
+      in2 = VEC_BE_SWAP (in2, bige_const);
+      in5 = VEC_LOAD_BE_NOSWAP (in, 4);
+      in6 = VEC_LOAD_BE_NOSWAP (in, 5);
+      in3 = VEC_BE_SWAP (in3, bige_const);
+      in4 = VEC_BE_SWAP (in4, bige_const);
+      in7 = VEC_LOAD_BE_NOSWAP (in, 6);
+      iv = VEC_LOAD_BE_NOSWAP (in, 7);
+      in += 8;
+      in5 = VEC_BE_SWAP (in5, bige_const);
+      in6 = VEC_BE_SWAP (in6, bige_const);
+      b0 = asm_xor (rkey0, in0);
+      b1 = asm_xor (rkey0, in1);
+      in7 = VEC_BE_SWAP (in7, bige_const);
+      iv = VEC_BE_SWAP (iv, bige_const);
+      b2 = asm_xor (rkey0, in2);
+      b3 = asm_xor (rkey0, in3);
+      b4 = asm_xor (rkey0, in4);
+      b5 = asm_xor (rkey0, in5);
+      b6 = asm_xor (rkey0, in6);
+      b7 = asm_xor (rkey0, in7);
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey); \
+             b4 = asm_cipher_be (b4, rkey); \
+             b5 = asm_cipher_be (b5, rkey); \
+             b6 = asm_cipher_be (b6, rkey); \
+             b7 = asm_cipher_be (b7, rkey);
+
+      DO_ROUND(1);
+      DO_ROUND(2);
+      DO_ROUND(3);
+      DO_ROUND(4);
+      DO_ROUND(5);
+      DO_ROUND(6);
+      DO_ROUND(7);
+      DO_ROUND(8);
+      DO_ROUND(9);
+      if (rounds >= 12)
+       {
+         DO_ROUND(10);
+         DO_ROUND(11);
+         if (rounds > 12)
+           {
+             DO_ROUND(12);
+             DO_ROUND(13);
+           }
+       }
+
+#undef DO_ROUND
+
+      in1 = asm_xor (rkeylast, in1);
+      in2 = asm_xor (rkeylast, in2);
+      in3 = asm_xor (rkeylast, in3);
+      in4 = asm_xor (rkeylast, in4);
+      b0 = asm_cipherlast_be (b0, in1);
+      b1 = asm_cipherlast_be (b1, in2);
+      in5 = asm_xor (rkeylast, in5);
+      in6 = asm_xor (rkeylast, in6);
+      b2 = asm_cipherlast_be (b2, in3);
+      b3 = asm_cipherlast_be (b3, in4);
+      in7 = asm_xor (rkeylast, in7);
+      in0 = asm_xor (rkeylast, iv);
+      b0 = VEC_BE_SWAP (b0, bige_const);
+      b1 = VEC_BE_SWAP (b1, bige_const);
+      b4 = asm_cipherlast_be (b4, in5);
+      b5 = asm_cipherlast_be (b5, in6);
+      b2 = VEC_BE_SWAP (b2, bige_const);
+      b3 = VEC_BE_SWAP (b3, bige_const);
+      b6 = asm_cipherlast_be (b6, in7);
+      b7 = asm_cipherlast_be (b7, in0);
+      b4 = VEC_BE_SWAP (b4, bige_const);
+      b5 = VEC_BE_SWAP (b5, bige_const);
+      b6 = VEC_BE_SWAP (b6, bige_const);
+      b7 = VEC_BE_SWAP (b7, bige_const);
+      VEC_STORE_BE_NOSWAP (out, 0, b0);
+      VEC_STORE_BE_NOSWAP (out, 1, b1);
+      VEC_STORE_BE_NOSWAP (out, 2, b2);
+      VEC_STORE_BE_NOSWAP (out, 3, b3);
+      VEC_STORE_BE_NOSWAP (out, 4, b4);
+      VEC_STORE_BE_NOSWAP (out, 5, b5);
+      VEC_STORE_BE_NOSWAP (out, 6, b6);
+      VEC_STORE_BE_NOSWAP (out, 7, b7);
+      out += 8;
+    }
+
+  if (nblocks >= 4)
+    {
+      in0 = iv;
+      in1 = VEC_LOAD_BE (in, 0, bige_const);
+      in2 = VEC_LOAD_BE (in, 1, bige_const);
+      in3 = VEC_LOAD_BE (in, 2, bige_const);
+      iv = VEC_LOAD_BE (in, 3, bige_const);
+
+      b0 = asm_xor (rkey0, in0);
+      b1 = asm_xor (rkey0, in1);
+      b2 = asm_xor (rkey0, in2);
+      b3 = asm_xor (rkey0, in3);
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey);
+
+      DO_ROUND(1);
+      DO_ROUND(2);
+      DO_ROUND(3);
+      DO_ROUND(4);
+      DO_ROUND(5);
+      DO_ROUND(6);
+      DO_ROUND(7);
+      DO_ROUND(8);
+      DO_ROUND(9);
+      if (rounds >= 12)
+       {
+         DO_ROUND(10);
+         DO_ROUND(11);
+         if (rounds > 12)
+           {
+             DO_ROUND(12);
+             DO_ROUND(13);
+           }
+       }
+
+#undef DO_ROUND
+
+      in1 = asm_xor (rkeylast, in1);
+      in2 = asm_xor (rkeylast, in2);
+      in3 = asm_xor (rkeylast, in3);
+      in0 = asm_xor (rkeylast, iv);
+      b0 = asm_cipherlast_be (b0, in1);
+      b1 = asm_cipherlast_be (b1, in2);
+      b2 = asm_cipherlast_be (b2, in3);
+      b3 = asm_cipherlast_be (b3, in0);
+      VEC_STORE_BE (out, 0, b0, bige_const);
+      VEC_STORE_BE (out, 1, b1, bige_const);
+      VEC_STORE_BE (out, 2, b2, bige_const);
+      VEC_STORE_BE (out, 3, b3, bige_const);
+
+      in += 4;
+      out += 4;
+      nblocks -= 4;
+    }
+
+  for (; nblocks; nblocks--)
+    {
+      bin = VEC_LOAD_BE (in, 0, bige_const);
+      rkeylast = rkeylast_orig ^ bin;
+      b = iv;
+      iv = bin;
+
+      AES_ENCRYPT (b, rounds);
+
+      VEC_STORE_BE (out, 0, b, bige_const);
+
+      out++;
+      in++;
+    }
+
+  VEC_STORE_BE (iv_arg, 0, iv, bige_const);
+}
+
+
+void CBC_ENC_FUNC (void *context, unsigned char *iv_arg,
+                  void *outbuf_arg, const void *inbuf_arg,
+                  size_t nblocks, int cbc_mac)
+{
+  const block bige_const = asm_load_be_const();
+  RIJNDAEL_context *ctx = context;
+  const u128_t *rk = (u128_t *)&ctx->keyschenc;
+  const u128_t *in = (const u128_t *)inbuf_arg;
+  byte *out = (byte *)outbuf_arg;
+  int rounds = ctx->rounds;
+  ROUND_KEY_VARIABLES_ALL;
+  block lastiv, b;
+  unsigned int outadd = -(!cbc_mac) & 16;
+
+  lastiv = VEC_LOAD_BE (iv_arg, 0, bige_const);
+
+  PRELOAD_ROUND_KEYS_ALL (rounds);
+
+  for (; nblocks >= 2; nblocks -= 2)
+    {
+      block in2, lastiv1;
+
+      b = lastiv ^ VEC_LOAD_BE (in, 0, bige_const);
+      in2 = VEC_LOAD_BE (in + 1, 0, bige_const);
+      in += 2;
+
+      AES_ENCRYPT_ALL (b, rounds);
+
+      lastiv1 = b;
+      b = lastiv1 ^ in2;
+
+      AES_ENCRYPT_ALL (b, rounds);
+
+      lastiv = b;
+      VEC_STORE_BE ((u128_t *)out, 0, lastiv1, bige_const);
+      out += outadd;
+      VEC_STORE_BE ((u128_t *)out, 0, lastiv, bige_const);
+      out += outadd;
+    }
+
+  for (; nblocks; nblocks--)
+    {
+      b = lastiv ^ VEC_LOAD_BE (in++, 0, bige_const);
+
+      AES_ENCRYPT_ALL (b, rounds);
+
+      lastiv = b;
+      VEC_STORE_BE ((u128_t *)out, 0, b, bige_const);
+      out += outadd;
+    }
+
+  VEC_STORE_BE (iv_arg, 0, lastiv, bige_const);
+}
+
+void CBC_DEC_FUNC (void *context, unsigned char *iv_arg,
+                  void *outbuf_arg, const void *inbuf_arg,
+                  size_t nblocks)
+{
+  const block bige_const = asm_load_be_const();
+  RIJNDAEL_context *ctx = context;
+  const u128_t *rk = (u128_t *)&ctx->keyschdec;
+  const u128_t *in = (const u128_t *)inbuf_arg;
+  u128_t *out = (u128_t *)outbuf_arg;
+  int rounds = ctx->rounds;
+  ROUND_KEY_VARIABLES;
+  block rkeylast_orig;
+  block in0, in1, in2, in3, in4, in5, in6, in7;
+  block b0, b1, b2, b3, b4, b5, b6, b7;
+  block rkey;
+  block iv, b;
+
+  if (!ctx->decryption_prepared)
+    {
+      internal_aes_ppc_prepare_decryption (ctx);
+      ctx->decryption_prepared = 1;
+    }
+
+  iv = VEC_LOAD_BE (iv_arg, 0, bige_const);
+
+  PRELOAD_ROUND_KEYS (rounds);
+  rkeylast_orig = rkeylast;
+
+  for (; nblocks >= 8; nblocks -= 8)
+    {
+      in0 = VEC_LOAD_BE_NOSWAP (in, 0);
+      in1 = VEC_LOAD_BE_NOSWAP (in, 1);
+      in2 = VEC_LOAD_BE_NOSWAP (in, 2);
+      in3 = VEC_LOAD_BE_NOSWAP (in, 3);
+      in0 = VEC_BE_SWAP (in0, bige_const);
+      in1 = VEC_BE_SWAP (in1, bige_const);
+      in4 = VEC_LOAD_BE_NOSWAP (in, 4);
+      in5 = VEC_LOAD_BE_NOSWAP (in, 5);
+      in2 = VEC_BE_SWAP (in2, bige_const);
+      in3 = VEC_BE_SWAP (in3, bige_const);
+      in6 = VEC_LOAD_BE_NOSWAP (in, 6);
+      in7 = VEC_LOAD_BE_NOSWAP (in, 7);
+      in += 8;
+      b0 = asm_xor (rkey0, in0);
+      b1 = asm_xor (rkey0, in1);
+      in4 = VEC_BE_SWAP (in4, bige_const);
+      in5 = VEC_BE_SWAP (in5, bige_const);
+      b2 = asm_xor (rkey0, in2);
+      b3 = asm_xor (rkey0, in3);
+      in6 = VEC_BE_SWAP (in6, bige_const);
+      in7 = VEC_BE_SWAP (in7, bige_const);
+      b4 = asm_xor (rkey0, in4);
+      b5 = asm_xor (rkey0, in5);
+      b6 = asm_xor (rkey0, in6);
+      b7 = asm_xor (rkey0, in7);
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_ncipher_be (b0, rkey); \
+             b1 = asm_ncipher_be (b1, rkey); \
+             b2 = asm_ncipher_be (b2, rkey); \
+             b3 = asm_ncipher_be (b3, rkey); \
+             b4 = asm_ncipher_be (b4, rkey); \
+             b5 = asm_ncipher_be (b5, rkey); \
+             b6 = asm_ncipher_be (b6, rkey); \
+             b7 = asm_ncipher_be (b7, rkey);
+
+      DO_ROUND(1);
+      DO_ROUND(2);
+      DO_ROUND(3);
+      DO_ROUND(4);
+      DO_ROUND(5);
+      DO_ROUND(6);
+      DO_ROUND(7);
+      DO_ROUND(8);
+      DO_ROUND(9);
+      if (rounds >= 12)
+       {
+         DO_ROUND(10);
+         DO_ROUND(11);
+         if (rounds > 12)
+           {
+             DO_ROUND(12);
+             DO_ROUND(13);
+           }
+       }
+
+#undef DO_ROUND
+
+      iv = asm_xor (rkeylast, iv);
+      in0 = asm_xor (rkeylast, in0);
+      in1 = asm_xor (rkeylast, in1);
+      in2 = asm_xor (rkeylast, in2);
+      b0 = asm_ncipherlast_be (b0, iv);
+      iv = in7;
+      b1 = asm_ncipherlast_be (b1, in0);
+      in3 = asm_xor (rkeylast, in3);
+      in4 = asm_xor (rkeylast, in4);
+      b2 = asm_ncipherlast_be (b2, in1);
+      b3 = asm_ncipherlast_be (b3, in2);
+      in5 = asm_xor (rkeylast, in5);
+      in6 = asm_xor (rkeylast, in6);
+      b0 = VEC_BE_SWAP (b0, bige_const);
+      b1 = VEC_BE_SWAP (b1, bige_const);
+      b4 = asm_ncipherlast_be (b4, in3);
+      b5 = asm_ncipherlast_be (b5, in4);
+      b2 = VEC_BE_SWAP (b2, bige_const);
+      b3 = VEC_BE_SWAP (b3, bige_const);
+      b6 = asm_ncipherlast_be (b6, in5);
+      b7 = asm_ncipherlast_be (b7, in6);
+      b4 = VEC_BE_SWAP (b4, bige_const);
+      b5 = VEC_BE_SWAP (b5, bige_const);
+      b6 = VEC_BE_SWAP (b6, bige_const);
+      b7 = VEC_BE_SWAP (b7, bige_const);
+      VEC_STORE_BE_NOSWAP (out, 0, b0);
+      VEC_STORE_BE_NOSWAP (out, 1, b1);
+      VEC_STORE_BE_NOSWAP (out, 2, b2);
+      VEC_STORE_BE_NOSWAP (out, 3, b3);
+      VEC_STORE_BE_NOSWAP (out, 4, b4);
+      VEC_STORE_BE_NOSWAP (out, 5, b5);
+      VEC_STORE_BE_NOSWAP (out, 6, b6);
+      VEC_STORE_BE_NOSWAP (out, 7, b7);
+      out += 8;
+    }
+
+  if (nblocks >= 4)
+    {
+      in0 = VEC_LOAD_BE (in, 0, bige_const);
+      in1 = VEC_LOAD_BE (in, 1, bige_const);
+      in2 = VEC_LOAD_BE (in, 2, bige_const);
+      in3 = VEC_LOAD_BE (in, 3, bige_const);
+
+      b0 = asm_xor (rkey0, in0);
+      b1 = asm_xor (rkey0, in1);
+      b2 = asm_xor (rkey0, in2);
+      b3 = asm_xor (rkey0, in3);
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_ncipher_be (b0, rkey); \
+             b1 = asm_ncipher_be (b1, rkey); \
+             b2 = asm_ncipher_be (b2, rkey); \
+             b3 = asm_ncipher_be (b3, rkey);
+
+      DO_ROUND(1);
+      DO_ROUND(2);
+      DO_ROUND(3);
+      DO_ROUND(4);
+      DO_ROUND(5);
+      DO_ROUND(6);
+      DO_ROUND(7);
+      DO_ROUND(8);
+      DO_ROUND(9);
+      if (rounds >= 12)
+       {
+         DO_ROUND(10);
+         DO_ROUND(11);
+         if (rounds > 12)
+           {
+             DO_ROUND(12);
+             DO_ROUND(13);
+           }
+       }
+
+#undef DO_ROUND
+
+      iv = asm_xor (rkeylast, iv);
+      in0 = asm_xor (rkeylast, in0);
+      in1 = asm_xor (rkeylast, in1);
+      in2 = asm_xor (rkeylast, in2);
+
+      b0 = asm_ncipherlast_be (b0, iv);
+      iv = in3;
+      b1 = asm_ncipherlast_be (b1, in0);
+      b2 = asm_ncipherlast_be (b2, in1);
+      b3 = asm_ncipherlast_be (b3, in2);
+
+      VEC_STORE_BE (out, 0, b0, bige_const);
+      VEC_STORE_BE (out, 1, b1, bige_const);
+      VEC_STORE_BE (out, 2, b2, bige_const);
+      VEC_STORE_BE (out, 3, b3, bige_const);
+
+      in += 4;
+      out += 4;
+      nblocks -= 4;
+    }
+
+  for (; nblocks; nblocks--)
+    {
+      rkeylast = rkeylast_orig ^ iv;
+
+      iv = VEC_LOAD_BE (in, 0, bige_const);
+      b = iv;
+      AES_DECRYPT (b, rounds);
+
+      VEC_STORE_BE (out, 0, b, bige_const);
+
+      in++;
+      out++;
+    }
+
+  VEC_STORE_BE (iv_arg, 0, iv, bige_const);
+}
+
+
+void CTR_ENC_FUNC (void *context, unsigned char *ctr_arg,
+                  void *outbuf_arg, const void *inbuf_arg,
+                  size_t nblocks)
+{
+  static const unsigned char vec_one_const[16] =
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+  const block bige_const = asm_load_be_const();
+  RIJNDAEL_context *ctx = context;
+  const u128_t *rk = (u128_t *)&ctx->keyschenc;
+  const u128_t *in = (const u128_t *)inbuf_arg;
+  u128_t *out = (u128_t *)outbuf_arg;
+  int rounds = ctx->rounds;
+  ROUND_KEY_VARIABLES;
+  block rkeylast_orig;
+  block ctr, b, one;
+
+  ctr = VEC_LOAD_BE (ctr_arg, 0, bige_const);
+  one = VEC_LOAD_BE (&vec_one_const, 0, bige_const);
+
+  PRELOAD_ROUND_KEYS (rounds);
+  rkeylast_orig = rkeylast;
+
+  if (nblocks >= 4)
+    {
+      block in0, in1, in2, in3, in4, in5, in6, in7;
+      block b0, b1, b2, b3, b4, b5, b6, b7;
+      block two, three, four;
+      block rkey;
+
+      two   = asm_add_uint128 (one, one);
+      three = asm_add_uint128 (two, one);
+      four  = asm_add_uint128 (two, two);
+
+      for (; nblocks >= 8; nblocks -= 8)
+       {
+         b1 = asm_add_uint128 (ctr, one);
+         b2 = asm_add_uint128 (ctr, two);
+         b3 = asm_add_uint128 (ctr, three);
+         b4 = asm_add_uint128 (ctr, four);
+         b5 = asm_add_uint128 (b1, four);
+         b6 = asm_add_uint128 (b2, four);
+         b7 = asm_add_uint128 (b3, four);
+         b0 = asm_xor (rkey0, ctr);
+         rkey = ALIGNED_LOAD (rk, 1);
+         ctr = asm_add_uint128 (b4, four);
+         b1 = asm_xor (rkey0, b1);
+         b2 = asm_xor (rkey0, b2);
+         b3 = asm_xor (rkey0, b3);
+         b0 = asm_cipher_be (b0, rkey);
+         b1 = asm_cipher_be (b1, rkey);
+         b2 = asm_cipher_be (b2, rkey);
+         b3 = asm_cipher_be (b3, rkey);
+         b4 = asm_xor (rkey0, b4);
+         b5 = asm_xor (rkey0, b5);
+         b6 = asm_xor (rkey0, b6);
+         b7 = asm_xor (rkey0, b7);
+         b4 = asm_cipher_be (b4, rkey);
+         b5 = asm_cipher_be (b5, rkey);
+         b6 = asm_cipher_be (b6, rkey);
+         b7 = asm_cipher_be (b7, rkey);
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey); \
+             b4 = asm_cipher_be (b4, rkey); \
+             b5 = asm_cipher_be (b5, rkey); \
+             b6 = asm_cipher_be (b6, rkey); \
+             b7 = asm_cipher_be (b7, rkey);
+
+         in0 = VEC_LOAD_BE_NOSWAP (in, 0);
+         DO_ROUND(2);
+         in1 = VEC_LOAD_BE_NOSWAP (in, 1);
+         DO_ROUND(3);
+         in2 = VEC_LOAD_BE_NOSWAP (in, 2);
+         DO_ROUND(4);
+         in3 = VEC_LOAD_BE_NOSWAP (in, 3);
+         DO_ROUND(5);
+         in4 = VEC_LOAD_BE_NOSWAP (in, 4);
+         DO_ROUND(6);
+         in5 = VEC_LOAD_BE_NOSWAP (in, 5);
+         DO_ROUND(7);
+         in6 = VEC_LOAD_BE_NOSWAP (in, 6);
+         DO_ROUND(8);
+         in7 = VEC_LOAD_BE_NOSWAP (in, 7);
+         in += 8;
+         DO_ROUND(9);
+
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         in0 = VEC_BE_SWAP (in0, bige_const);
+         in1 = VEC_BE_SWAP (in1, bige_const);
+         in2 = VEC_BE_SWAP (in2, bige_const);
+         in3 = VEC_BE_SWAP (in3, bige_const);
+         in4 = VEC_BE_SWAP (in4, bige_const);
+         in5 = VEC_BE_SWAP (in5, bige_const);
+         in6 = VEC_BE_SWAP (in6, bige_const);
+         in7 = VEC_BE_SWAP (in7, bige_const);
+
+         in0 = asm_xor (rkeylast, in0);
+         in1 = asm_xor (rkeylast, in1);
+         in2 = asm_xor (rkeylast, in2);
+         in3 = asm_xor (rkeylast, in3);
+         b0 = asm_cipherlast_be (b0, in0);
+         b1 = asm_cipherlast_be (b1, in1);
+         in4 = asm_xor (rkeylast, in4);
+         in5 = asm_xor (rkeylast, in5);
+         b2 = asm_cipherlast_be (b2, in2);
+         b3 = asm_cipherlast_be (b3, in3);
+         in6 = asm_xor (rkeylast, in6);
+         in7 = asm_xor (rkeylast, in7);
+         b4 = asm_cipherlast_be (b4, in4);
+         b5 = asm_cipherlast_be (b5, in5);
+         b6 = asm_cipherlast_be (b6, in6);
+         b7 = asm_cipherlast_be (b7, in7);
+
+         b0 = VEC_BE_SWAP (b0, bige_const);
+         b1 = VEC_BE_SWAP (b1, bige_const);
+         b2 = VEC_BE_SWAP (b2, bige_const);
+         b3 = VEC_BE_SWAP (b3, bige_const);
+         b4 = VEC_BE_SWAP (b4, bige_const);
+         b5 = VEC_BE_SWAP (b5, bige_const);
+         b6 = VEC_BE_SWAP (b6, bige_const);
+         b7 = VEC_BE_SWAP (b7, bige_const);
+         VEC_STORE_BE_NOSWAP (out, 0, b0);
+         VEC_STORE_BE_NOSWAP (out, 1, b1);
+         VEC_STORE_BE_NOSWAP (out, 2, b2);
+         VEC_STORE_BE_NOSWAP (out, 3, b3);
+         VEC_STORE_BE_NOSWAP (out, 4, b4);
+         VEC_STORE_BE_NOSWAP (out, 5, b5);
+         VEC_STORE_BE_NOSWAP (out, 6, b6);
+         VEC_STORE_BE_NOSWAP (out, 7, b7);
+         out += 8;
+       }
+
+      if (nblocks >= 4)
+       {
+         b1 = asm_add_uint128 (ctr, one);
+         b2 = asm_add_uint128 (ctr, two);
+         b3 = asm_add_uint128 (ctr, three);
+         b0 = asm_xor (rkey0, ctr);
+         ctr = asm_add_uint128 (ctr, four);
+         b1 = asm_xor (rkey0, b1);
+         b2 = asm_xor (rkey0, b2);
+         b3 = asm_xor (rkey0, b3);
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+         DO_ROUND(8);
+
+         in0 = VEC_LOAD_BE (in, 0, bige_const);
+         in1 = VEC_LOAD_BE (in, 1, bige_const);
+         in2 = VEC_LOAD_BE (in, 2, bige_const);
+         in3 = VEC_LOAD_BE (in, 3, bige_const);
+
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         in0 = asm_xor (rkeylast, in0);
+         in1 = asm_xor (rkeylast, in1);
+         in2 = asm_xor (rkeylast, in2);
+         in3 = asm_xor (rkeylast, in3);
+
+         b0 = asm_cipherlast_be (b0, in0);
+         b1 = asm_cipherlast_be (b1, in1);
+         b2 = asm_cipherlast_be (b2, in2);
+         b3 = asm_cipherlast_be (b3, in3);
+
+         VEC_STORE_BE (out, 0, b0, bige_const);
+         VEC_STORE_BE (out, 1, b1, bige_const);
+         VEC_STORE_BE (out, 2, b2, bige_const);
+         VEC_STORE_BE (out, 3, b3, bige_const);
+
+         in += 4;
+         out += 4;
+         nblocks -= 4;
+       }
+    }
+
+  for (; nblocks; nblocks--)
+    {
+      b = ctr;
+      ctr = asm_add_uint128 (ctr, one);
+      rkeylast = rkeylast_orig ^ VEC_LOAD_BE (in, 0, bige_const);
+
+      AES_ENCRYPT (b, rounds);
+
+      VEC_STORE_BE (out, 0, b, bige_const);
+
+      out++;
+      in++;
+    }
+
+  VEC_STORE_BE (ctr_arg, 0, ctr, bige_const);
+}
+
+
+size_t OCB_CRYPT_FUNC (gcry_cipher_hd_t c, void *outbuf_arg,
+                      const void *inbuf_arg, size_t nblocks,
+                      int encrypt)
+{
+  const block bige_const = asm_load_be_const();
+  RIJNDAEL_context *ctx = (void *)&c->context.c;
+  const u128_t *in = (const u128_t *)inbuf_arg;
+  u128_t *out = (u128_t *)outbuf_arg;
+  int rounds = ctx->rounds;
+  u64 data_nblocks = c->u_mode.ocb.data_nblocks;
+  block l0, l1, l2, l;
+  block b0, b1, b2, b3, b4, b5, b6, b7, b;
+  block iv0, iv1, iv2, iv3, iv4, iv5, iv6, iv7;
+  block rkey, rkeylf;
+  block ctr, iv;
+  ROUND_KEY_VARIABLES;
+
+  iv = VEC_LOAD_BE (c->u_iv.iv, 0, bige_const);
+  ctr = VEC_LOAD_BE (c->u_ctr.ctr, 0, bige_const);
+
+  l0 = VEC_LOAD_BE (c->u_mode.ocb.L[0], 0, bige_const);
+  l1 = VEC_LOAD_BE (c->u_mode.ocb.L[1], 0, bige_const);
+  l2 = VEC_LOAD_BE (c->u_mode.ocb.L[2], 0, bige_const);
+
+  if (encrypt)
+    {
+      const u128_t *rk = (u128_t *)&ctx->keyschenc;
+
+      PRELOAD_ROUND_KEYS (rounds);
+
+      for (; nblocks >= 8 && data_nblocks % 8; nblocks--)
+       {
+         l = VEC_LOAD_BE (ocb_get_l (c, ++data_nblocks), 0, bige_const);
+         b = VEC_LOAD_BE (in, 0, bige_const);
+
+         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+         iv ^= l;
+         /* Checksum_i = Checksum_{i-1} xor P_i  */
+         ctr ^= b;
+         /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+         b ^= iv;
+         AES_ENCRYPT (b, rounds);
+         b ^= iv;
+
+         VEC_STORE_BE (out, 0, b, bige_const);
+
+         in += 1;
+         out += 1;
+       }
+
+      for (; nblocks >= 8; nblocks -= 8)
+       {
+         b0 = VEC_LOAD_BE_NOSWAP (in, 0);
+         b1 = VEC_LOAD_BE_NOSWAP (in, 1);
+         b2 = VEC_LOAD_BE_NOSWAP (in, 2);
+         b3 = VEC_LOAD_BE_NOSWAP (in, 3);
+         b4 = VEC_LOAD_BE_NOSWAP (in, 4);
+         b5 = VEC_LOAD_BE_NOSWAP (in, 5);
+         b6 = VEC_LOAD_BE_NOSWAP (in, 6);
+         b7 = VEC_LOAD_BE_NOSWAP (in, 7);
+         in += 8;
+         l = VEC_LOAD_BE_NOSWAP (ocb_get_l (c, data_nblocks += 8), 0);
+         b0 = VEC_BE_SWAP(b0, bige_const);
+         b1 = VEC_BE_SWAP(b1, bige_const);
+         b2 = VEC_BE_SWAP(b2, bige_const);
+         b3 = VEC_BE_SWAP(b3, bige_const);
+         b4 = VEC_BE_SWAP(b4, bige_const);
+         b5 = VEC_BE_SWAP(b5, bige_const);
+         b6 = VEC_BE_SWAP(b6, bige_const);
+         b7 = VEC_BE_SWAP(b7, bige_const);
+         l = VEC_BE_SWAP(l, bige_const);
+
+         ctr ^= b0 ^ b1 ^ b2 ^ b3 ^ b4 ^ b5 ^ b6 ^ b7;
+
+         iv ^= rkey0;
+
+         iv0 = iv ^ l0;
+         iv1 = iv ^ l0 ^ l1;
+         iv2 = iv ^ l1;
+         iv3 = iv ^ l1 ^ l2;
+         iv4 = iv ^ l1 ^ l2 ^ l0;
+         iv5 = iv ^ l2 ^ l0;
+         iv6 = iv ^ l2;
+         iv7 = iv ^ l2 ^ l;
+
+         b0 ^= iv0;
+         b1 ^= iv1;
+         b2 ^= iv2;
+         b3 ^= iv3;
+         b4 ^= iv4;
+         b5 ^= iv5;
+         b6 ^= iv6;
+         b7 ^= iv7;
+         iv = iv7 ^ rkey0;
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey); \
+             b4 = asm_cipher_be (b4, rkey); \
+             b5 = asm_cipher_be (b5, rkey); \
+             b6 = asm_cipher_be (b6, rkey); \
+             b7 = asm_cipher_be (b7, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+
+         rkeylf = asm_xor (rkeylast, rkey0);
+
+         DO_ROUND(8);
+
+         iv0 = asm_xor (rkeylf, iv0);
+         iv1 = asm_xor (rkeylf, iv1);
+         iv2 = asm_xor (rkeylf, iv2);
+         iv3 = asm_xor (rkeylf, iv3);
+         iv4 = asm_xor (rkeylf, iv4);
+         iv5 = asm_xor (rkeylf, iv5);
+         iv6 = asm_xor (rkeylf, iv6);
+         iv7 = asm_xor (rkeylf, iv7);
+
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         b0 = asm_cipherlast_be (b0, iv0);
+         b1 = asm_cipherlast_be (b1, iv1);
+         b2 = asm_cipherlast_be (b2, iv2);
+         b3 = asm_cipherlast_be (b3, iv3);
+         b4 = asm_cipherlast_be (b4, iv4);
+         b5 = asm_cipherlast_be (b5, iv5);
+         b6 = asm_cipherlast_be (b6, iv6);
+         b7 = asm_cipherlast_be (b7, iv7);
+
+         b0 = VEC_BE_SWAP (b0, bige_const);
+         b1 = VEC_BE_SWAP (b1, bige_const);
+         b2 = VEC_BE_SWAP (b2, bige_const);
+         b3 = VEC_BE_SWAP (b3, bige_const);
+         b4 = VEC_BE_SWAP (b4, bige_const);
+         b5 = VEC_BE_SWAP (b5, bige_const);
+         b6 = VEC_BE_SWAP (b6, bige_const);
+         b7 = VEC_BE_SWAP (b7, bige_const);
+         VEC_STORE_BE_NOSWAP (out, 0, b0);
+         VEC_STORE_BE_NOSWAP (out, 1, b1);
+         VEC_STORE_BE_NOSWAP (out, 2, b2);
+         VEC_STORE_BE_NOSWAP (out, 3, b3);
+         VEC_STORE_BE_NOSWAP (out, 4, b4);
+         VEC_STORE_BE_NOSWAP (out, 5, b5);
+         VEC_STORE_BE_NOSWAP (out, 6, b6);
+         VEC_STORE_BE_NOSWAP (out, 7, b7);
+         out += 8;
+       }
+
+      if (nblocks >= 4 && (data_nblocks % 4) == 0)
+       {
+         b0 = VEC_LOAD_BE (in, 0, bige_const);
+         b1 = VEC_LOAD_BE (in, 1, bige_const);
+         b2 = VEC_LOAD_BE (in, 2, bige_const);
+         b3 = VEC_LOAD_BE (in, 3, bige_const);
+
+         l = VEC_LOAD_BE (ocb_get_l (c, data_nblocks += 4), 0, bige_const);
+
+         ctr ^= b0 ^ b1 ^ b2 ^ b3;
+
+         iv ^= rkey0;
+
+         iv0 = iv ^ l0;
+         iv1 = iv ^ l0 ^ l1;
+         iv2 = iv ^ l1;
+         iv3 = iv ^ l1 ^ l;
+
+         b0 ^= iv0;
+         b1 ^= iv1;
+         b2 ^= iv2;
+         b3 ^= iv3;
+         iv = iv3 ^ rkey0;
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+         DO_ROUND(8);
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         rkey = rkeylast ^ rkey0;
+         b0 = asm_cipherlast_be (b0, rkey ^ iv0);
+         b1 = asm_cipherlast_be (b1, rkey ^ iv1);
+         b2 = asm_cipherlast_be (b2, rkey ^ iv2);
+         b3 = asm_cipherlast_be (b3, rkey ^ iv3);
+
+         VEC_STORE_BE (out, 0, b0, bige_const);
+         VEC_STORE_BE (out, 1, b1, bige_const);
+         VEC_STORE_BE (out, 2, b2, bige_const);
+         VEC_STORE_BE (out, 3, b3, bige_const);
+
+         in += 4;
+         out += 4;
+         nblocks -= 4;
+       }
+
+      for (; nblocks; nblocks--)
+       {
+         l = VEC_LOAD_BE (ocb_get_l (c, ++data_nblocks), 0, bige_const);
+         b = VEC_LOAD_BE (in, 0, bige_const);
+
+         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+         iv ^= l;
+         /* Checksum_i = Checksum_{i-1} xor P_i  */
+         ctr ^= b;
+         /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+         b ^= iv;
+         AES_ENCRYPT (b, rounds);
+         b ^= iv;
+
+         VEC_STORE_BE (out, 0, b, bige_const);
+
+         in += 1;
+         out += 1;
+       }
+    }
+  else
+    {
+      const u128_t *rk = (u128_t *)&ctx->keyschdec;
+
+      if (!ctx->decryption_prepared)
+       {
+         internal_aes_ppc_prepare_decryption (ctx);
+         ctx->decryption_prepared = 1;
+       }
+
+      PRELOAD_ROUND_KEYS (rounds);
+
+      for (; nblocks >= 8 && data_nblocks % 8; nblocks--)
+       {
+         l = VEC_LOAD_BE (ocb_get_l (c, ++data_nblocks), 0, bige_const);
+         b = VEC_LOAD_BE (in, 0, bige_const);
+
+         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+         iv ^= l;
+         /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
+         b ^= iv;
+         AES_DECRYPT (b, rounds);
+         b ^= iv;
+         /* Checksum_i = Checksum_{i-1} xor P_i  */
+         ctr ^= b;
+
+         VEC_STORE_BE (out, 0, b, bige_const);
+
+         in += 1;
+         out += 1;
+       }
+
+      for (; nblocks >= 8; nblocks -= 8)
+       {
+         b0 = VEC_LOAD_BE_NOSWAP (in, 0);
+         b1 = VEC_LOAD_BE_NOSWAP (in, 1);
+         b2 = VEC_LOAD_BE_NOSWAP (in, 2);
+         b3 = VEC_LOAD_BE_NOSWAP (in, 3);
+         b4 = VEC_LOAD_BE_NOSWAP (in, 4);
+         b5 = VEC_LOAD_BE_NOSWAP (in, 5);
+         b6 = VEC_LOAD_BE_NOSWAP (in, 6);
+         b7 = VEC_LOAD_BE_NOSWAP (in, 7);
+         in += 8;
+         l = VEC_LOAD_BE_NOSWAP (ocb_get_l (c, data_nblocks += 8), 0);
+         b0 = VEC_BE_SWAP(b0, bige_const);
+         b1 = VEC_BE_SWAP(b1, bige_const);
+         b2 = VEC_BE_SWAP(b2, bige_const);
+         b3 = VEC_BE_SWAP(b3, bige_const);
+         b4 = VEC_BE_SWAP(b4, bige_const);
+         b5 = VEC_BE_SWAP(b5, bige_const);
+         b6 = VEC_BE_SWAP(b6, bige_const);
+         b7 = VEC_BE_SWAP(b7, bige_const);
+         l = VEC_BE_SWAP(l, bige_const);
+
+         iv ^= rkey0;
+
+         iv0 = iv ^ l0;
+         iv1 = iv ^ l0 ^ l1;
+         iv2 = iv ^ l1;
+         iv3 = iv ^ l1 ^ l2;
+         iv4 = iv ^ l1 ^ l2 ^ l0;
+         iv5 = iv ^ l2 ^ l0;
+         iv6 = iv ^ l2;
+         iv7 = iv ^ l2 ^ l;
+
+         b0 ^= iv0;
+         b1 ^= iv1;
+         b2 ^= iv2;
+         b3 ^= iv3;
+         b4 ^= iv4;
+         b5 ^= iv5;
+         b6 ^= iv6;
+         b7 ^= iv7;
+         iv = iv7 ^ rkey0;
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_ncipher_be (b0, rkey); \
+             b1 = asm_ncipher_be (b1, rkey); \
+             b2 = asm_ncipher_be (b2, rkey); \
+             b3 = asm_ncipher_be (b3, rkey); \
+             b4 = asm_ncipher_be (b4, rkey); \
+             b5 = asm_ncipher_be (b5, rkey); \
+             b6 = asm_ncipher_be (b6, rkey); \
+             b7 = asm_ncipher_be (b7, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+
+         rkeylf = asm_xor (rkeylast, rkey0);
+
+         DO_ROUND(8);
+
+         iv0 = asm_xor (rkeylf, iv0);
+         iv1 = asm_xor (rkeylf, iv1);
+         iv2 = asm_xor (rkeylf, iv2);
+         iv3 = asm_xor (rkeylf, iv3);
+         iv4 = asm_xor (rkeylf, iv4);
+         iv5 = asm_xor (rkeylf, iv5);
+         iv6 = asm_xor (rkeylf, iv6);
+         iv7 = asm_xor (rkeylf, iv7);
+
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         b0 = asm_ncipherlast_be (b0, iv0);
+         b1 = asm_ncipherlast_be (b1, iv1);
+         b2 = asm_ncipherlast_be (b2, iv2);
+         b3 = asm_ncipherlast_be (b3, iv3);
+         b4 = asm_ncipherlast_be (b4, iv4);
+         b5 = asm_ncipherlast_be (b5, iv5);
+         b6 = asm_ncipherlast_be (b6, iv6);
+         b7 = asm_ncipherlast_be (b7, iv7);
+
+         ctr ^= b0 ^ b1 ^ b2 ^ b3 ^ b4 ^ b5 ^ b6 ^ b7;
+
+         b0 = VEC_BE_SWAP (b0, bige_const);
+         b1 = VEC_BE_SWAP (b1, bige_const);
+         b2 = VEC_BE_SWAP (b2, bige_const);
+         b3 = VEC_BE_SWAP (b3, bige_const);
+         b4 = VEC_BE_SWAP (b4, bige_const);
+         b5 = VEC_BE_SWAP (b5, bige_const);
+         b6 = VEC_BE_SWAP (b6, bige_const);
+         b7 = VEC_BE_SWAP (b7, bige_const);
+         VEC_STORE_BE_NOSWAP (out, 0, b0);
+         VEC_STORE_BE_NOSWAP (out, 1, b1);
+         VEC_STORE_BE_NOSWAP (out, 2, b2);
+         VEC_STORE_BE_NOSWAP (out, 3, b3);
+         VEC_STORE_BE_NOSWAP (out, 4, b4);
+         VEC_STORE_BE_NOSWAP (out, 5, b5);
+         VEC_STORE_BE_NOSWAP (out, 6, b6);
+         VEC_STORE_BE_NOSWAP (out, 7, b7);
+         out += 8;
+       }
+
+      if (nblocks >= 4 && (data_nblocks % 4) == 0)
+       {
+         b0 = VEC_LOAD_BE (in, 0, bige_const);
+         b1 = VEC_LOAD_BE (in, 1, bige_const);
+         b2 = VEC_LOAD_BE (in, 2, bige_const);
+         b3 = VEC_LOAD_BE (in, 3, bige_const);
+
+         l = VEC_LOAD_BE (ocb_get_l (c, data_nblocks += 4), 0, bige_const);
+
+         iv ^= rkey0;
+
+         iv0 = iv ^ l0;
+         iv1 = iv ^ l0 ^ l1;
+         iv2 = iv ^ l1;
+         iv3 = iv ^ l1 ^ l;
+
+         b0 ^= iv0;
+         b1 ^= iv1;
+         b2 ^= iv2;
+         b3 ^= iv3;
+         iv = iv3 ^ rkey0;
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_ncipher_be (b0, rkey); \
+             b1 = asm_ncipher_be (b1, rkey); \
+             b2 = asm_ncipher_be (b2, rkey); \
+             b3 = asm_ncipher_be (b3, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+         DO_ROUND(8);
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         rkey = rkeylast ^ rkey0;
+         b0 = asm_ncipherlast_be (b0, rkey ^ iv0);
+         b1 = asm_ncipherlast_be (b1, rkey ^ iv1);
+         b2 = asm_ncipherlast_be (b2, rkey ^ iv2);
+         b3 = asm_ncipherlast_be (b3, rkey ^ iv3);
+
+         VEC_STORE_BE (out, 0, b0, bige_const);
+         VEC_STORE_BE (out, 1, b1, bige_const);
+         VEC_STORE_BE (out, 2, b2, bige_const);
+         VEC_STORE_BE (out, 3, b3, bige_const);
+
+         ctr ^= b0 ^ b1 ^ b2 ^ b3;
+
+         in += 4;
+         out += 4;
+         nblocks -= 4;
+       }
+
+      for (; nblocks; nblocks--)
+       {
+         l = VEC_LOAD_BE (ocb_get_l (c, ++data_nblocks), 0, bige_const);
+         b = VEC_LOAD_BE (in, 0, bige_const);
+
+         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+         iv ^= l;
+         /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
+         b ^= iv;
+         AES_DECRYPT (b, rounds);
+         b ^= iv;
+         /* Checksum_i = Checksum_{i-1} xor P_i  */
+         ctr ^= b;
+
+         VEC_STORE_BE (out, 0, b, bige_const);
+
+         in += 1;
+         out += 1;
+       }
+    }
+
+  VEC_STORE_BE (c->u_iv.iv, 0, iv, bige_const);
+  VEC_STORE_BE (c->u_ctr.ctr, 0, ctr, bige_const);
+  c->u_mode.ocb.data_nblocks = data_nblocks;
+
+  return 0;
+}
+
+size_t OCB_AUTH_FUNC (gcry_cipher_hd_t c, void *abuf_arg, size_t nblocks)
+{
+  const block bige_const = asm_load_be_const();
+  RIJNDAEL_context *ctx = (void *)&c->context.c;
+  const u128_t *rk = (u128_t *)&ctx->keyschenc;
+  const u128_t *abuf = (const u128_t *)abuf_arg;
+  int rounds = ctx->rounds;
+  u64 data_nblocks = c->u_mode.ocb.aad_nblocks;
+  block l0, l1, l2, l;
+  block b0, b1, b2, b3, b4, b5, b6, b7, b;
+  block iv0, iv1, iv2, iv3, iv4, iv5, iv6, iv7;
+  block rkey, frkey;
+  block ctr, iv;
+  ROUND_KEY_VARIABLES;
+
+  iv = VEC_LOAD_BE (c->u_mode.ocb.aad_offset, 0, bige_const);
+  ctr = VEC_LOAD_BE (c->u_mode.ocb.aad_sum, 0, bige_const);
+
+  l0 = VEC_LOAD_BE (c->u_mode.ocb.L[0], 0, bige_const);
+  l1 = VEC_LOAD_BE (c->u_mode.ocb.L[1], 0, bige_const);
+  l2 = VEC_LOAD_BE (c->u_mode.ocb.L[2], 0, bige_const);
+
+  PRELOAD_ROUND_KEYS (rounds);
+
+  for (; nblocks >= 8 && data_nblocks % 8; nblocks--)
+    {
+      l = VEC_LOAD_BE (ocb_get_l (c, ++data_nblocks), 0, bige_const);
+      b = VEC_LOAD_BE (abuf, 0, bige_const);
+
+      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+      iv ^= l;
+      /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
+      b ^= iv;
+      AES_ENCRYPT (b, rounds);
+      ctr ^= b;
+
+      abuf += 1;
+    }
+
+  for (; nblocks >= 8; nblocks -= 8)
+    {
+      b0 = VEC_LOAD_BE (abuf, 0, bige_const);
+      b1 = VEC_LOAD_BE (abuf, 1, bige_const);
+      b2 = VEC_LOAD_BE (abuf, 2, bige_const);
+      b3 = VEC_LOAD_BE (abuf, 3, bige_const);
+      b4 = VEC_LOAD_BE (abuf, 4, bige_const);
+      b5 = VEC_LOAD_BE (abuf, 5, bige_const);
+      b6 = VEC_LOAD_BE (abuf, 6, bige_const);
+      b7 = VEC_LOAD_BE (abuf, 7, bige_const);
+
+      l = VEC_LOAD_BE (ocb_get_l (c, data_nblocks += 8), 0, bige_const);
+
+      frkey = rkey0;
+      iv ^= frkey;
+
+      iv0 = iv ^ l0;
+      iv1 = iv ^ l0 ^ l1;
+      iv2 = iv ^ l1;
+      iv3 = iv ^ l1 ^ l2;
+      iv4 = iv ^ l1 ^ l2 ^ l0;
+      iv5 = iv ^ l2 ^ l0;
+      iv6 = iv ^ l2;
+      iv7 = iv ^ l2 ^ l;
+
+      b0 ^= iv0;
+      b1 ^= iv1;
+      b2 ^= iv2;
+      b3 ^= iv3;
+      b4 ^= iv4;
+      b5 ^= iv5;
+      b6 ^= iv6;
+      b7 ^= iv7;
+      iv = iv7 ^ frkey;
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey); \
+             b4 = asm_cipher_be (b4, rkey); \
+             b5 = asm_cipher_be (b5, rkey); \
+             b6 = asm_cipher_be (b6, rkey); \
+             b7 = asm_cipher_be (b7, rkey);
+
+      DO_ROUND(1);
+      DO_ROUND(2);
+      DO_ROUND(3);
+      DO_ROUND(4);
+      DO_ROUND(5);
+      DO_ROUND(6);
+      DO_ROUND(7);
+      DO_ROUND(8);
+      DO_ROUND(9);
+      if (rounds >= 12)
+       {
+         DO_ROUND(10);
+         DO_ROUND(11);
+         if (rounds > 12)
+           {
+             DO_ROUND(12);
+             DO_ROUND(13);
+           }
+       }
+
+#undef DO_ROUND
+
+      rkey = rkeylast;
+      b0 = asm_cipherlast_be (b0, rkey);
+      b1 = asm_cipherlast_be (b1, rkey);
+      b2 = asm_cipherlast_be (b2, rkey);
+      b3 = asm_cipherlast_be (b3, rkey);
+      b4 = asm_cipherlast_be (b4, rkey);
+      b5 = asm_cipherlast_be (b5, rkey);
+      b6 = asm_cipherlast_be (b6, rkey);
+      b7 = asm_cipherlast_be (b7, rkey);
+
+      ctr ^= b0 ^ b1 ^ b2 ^ b3 ^ b4 ^ b5 ^ b6 ^ b7;
+
+      abuf += 8;
+    }
+
+  if (nblocks >= 4 && (data_nblocks % 4) == 0)
+    {
+      b0 = VEC_LOAD_BE (abuf, 0, bige_const);
+      b1 = VEC_LOAD_BE (abuf, 1, bige_const);
+      b2 = VEC_LOAD_BE (abuf, 2, bige_const);
+      b3 = VEC_LOAD_BE (abuf, 3, bige_const);
+
+      l = VEC_LOAD_BE (ocb_get_l (c, data_nblocks += 4), 0, bige_const);
+
+      frkey = rkey0;
+      iv ^= frkey;
+
+      iv0 = iv ^ l0;
+      iv1 = iv ^ l0 ^ l1;
+      iv2 = iv ^ l1;
+      iv3 = iv ^ l1 ^ l;
+
+      b0 ^= iv0;
+      b1 ^= iv1;
+      b2 ^= iv2;
+      b3 ^= iv3;
+      iv = iv3 ^ frkey;
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey);
+
+      DO_ROUND(1);
+      DO_ROUND(2);
+      DO_ROUND(3);
+      DO_ROUND(4);
+      DO_ROUND(5);
+      DO_ROUND(6);
+      DO_ROUND(7);
+      DO_ROUND(8);
+      DO_ROUND(9);
+      if (rounds >= 12)
+       {
+         DO_ROUND(10);
+         DO_ROUND(11);
+         if (rounds > 12)
+           {
+             DO_ROUND(12);
+             DO_ROUND(13);
+           }
+       }
+
+#undef DO_ROUND
+
+      rkey = rkeylast;
+      b0 = asm_cipherlast_be (b0, rkey);
+      b1 = asm_cipherlast_be (b1, rkey);
+      b2 = asm_cipherlast_be (b2, rkey);
+      b3 = asm_cipherlast_be (b3, rkey);
+
+      ctr ^= b0 ^ b1 ^ b2 ^ b3;
+
+      abuf += 4;
+      nblocks -= 4;
+    }
+
+  for (; nblocks; nblocks--)
+    {
+      l = VEC_LOAD_BE (ocb_get_l (c, ++data_nblocks), 0, bige_const);
+      b = VEC_LOAD_BE (abuf, 0, bige_const);
+
+      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+      iv ^= l;
+      /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
+      b ^= iv;
+      AES_ENCRYPT (b, rounds);
+      ctr ^= b;
+
+      abuf += 1;
+    }
+
+  VEC_STORE_BE (c->u_mode.ocb.aad_offset, 0, iv, bige_const);
+  VEC_STORE_BE (c->u_mode.ocb.aad_sum, 0, ctr, bige_const);
+  c->u_mode.ocb.aad_nblocks = data_nblocks;
+
+  return 0;
+}
+
+
+void XTS_CRYPT_FUNC (void *context, unsigned char *tweak_arg,
+                    void *outbuf_arg, const void *inbuf_arg,
+                    size_t nblocks, int encrypt)
+{
+#ifdef WORDS_BIGENDIAN
+  static const block vec_bswap128_const =
+    { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+#else
+  static const block vec_bswap128_const =
+    { ~15, ~14, ~13, ~12, ~11, ~10, ~9, ~8, ~7, ~6, ~5, ~4, ~3, ~2, ~1, ~0 };
+#endif
+  static const unsigned char vec_tweak_const[16] =
+    { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0x87 };
+  static const vector unsigned long long vec_shift63_const =
+    { 63, 63 };
+  const block bige_const = asm_load_be_const();
+  RIJNDAEL_context *ctx = context;
+  const u128_t *in = (const u128_t *)inbuf_arg;
+  u128_t *out = (u128_t *)outbuf_arg;
+  int rounds = ctx->rounds;
+  block tweak;
+  block b0, b1, b2, b3, b4, b5, b6, b7, b, rkey, rkeylf;
+  block tweak0, tweak1, tweak2, tweak3, tweak4, tweak5, tweak6, tweak7;
+  block tweak_const, bswap128_const, shift63_const;
+  ROUND_KEY_VARIABLES;
+
+  tweak_const = VEC_LOAD_BE (&vec_tweak_const, 0, bige_const);
+  bswap128_const = ALIGNED_LOAD (&vec_bswap128_const, 0);
+  shift63_const = ALIGNED_LOAD (&vec_shift63_const, 0);
+
+  tweak = VEC_LOAD_BE (tweak_arg, 0, bige_const);
+  tweak = asm_vperm1 (tweak, bswap128_const);
+
+#define GEN_TWEAK(tout, tin) /* Generate next tweak. */ \
+    do { \
+      block tmp1, tmp2; \
+      tmp1 = asm_swap_uint64_halfs(tin); \
+      tmp2 = asm_add_uint64(tin, tin); \
+      tmp1 = asm_sra_int64(tmp1, shift63_const) & tweak_const; \
+      tout = asm_xor(tmp1, tmp2); \
+    } while (0)
+
+  if (encrypt)
+    {
+      const u128_t *rk = (u128_t *)&ctx->keyschenc;
+
+      PRELOAD_ROUND_KEYS (rounds);
+
+      for (; nblocks >= 8; nblocks -= 8)
+       {
+         b0 = VEC_LOAD_BE_NOSWAP (in, 0);
+         b1 = VEC_LOAD_BE_NOSWAP (in, 1);
+         b2 = VEC_LOAD_BE_NOSWAP (in, 2);
+         b3 = VEC_LOAD_BE_NOSWAP (in, 3);
+         tweak0 = tweak;
+         GEN_TWEAK (tweak1, tweak0);
+         tweak0 = asm_vperm1 (tweak0, bswap128_const);
+         b4 = VEC_LOAD_BE_NOSWAP (in, 4);
+         b5 = VEC_LOAD_BE_NOSWAP (in, 5);
+         GEN_TWEAK (tweak2, tweak1);
+         tweak1 = asm_vperm1 (tweak1, bswap128_const);
+         b6 = VEC_LOAD_BE_NOSWAP (in, 6);
+         b7 = VEC_LOAD_BE_NOSWAP (in, 7);
+         in += 8;
+
+         b0 = VEC_BE_SWAP(b0, bige_const);
+         b1 = VEC_BE_SWAP(b1, bige_const);
+         GEN_TWEAK (tweak3, tweak2);
+         tweak2 = asm_vperm1 (tweak2, bswap128_const);
+         GEN_TWEAK (tweak4, tweak3);
+         tweak3 = asm_vperm1 (tweak3, bswap128_const);
+         b2 = VEC_BE_SWAP(b2, bige_const);
+         b3 = VEC_BE_SWAP(b3, bige_const);
+         GEN_TWEAK (tweak5, tweak4);
+         tweak4 = asm_vperm1 (tweak4, bswap128_const);
+         GEN_TWEAK (tweak6, tweak5);
+         tweak5 = asm_vperm1 (tweak5, bswap128_const);
+         b4 = VEC_BE_SWAP(b4, bige_const);
+         b5 = VEC_BE_SWAP(b5, bige_const);
+         GEN_TWEAK (tweak7, tweak6);
+         tweak6 = asm_vperm1 (tweak6, bswap128_const);
+         GEN_TWEAK (tweak, tweak7);
+         tweak7 = asm_vperm1 (tweak7, bswap128_const);
+         b6 = VEC_BE_SWAP(b6, bige_const);
+         b7 = VEC_BE_SWAP(b7, bige_const);
+
+         tweak0 = asm_xor (tweak0, rkey0);
+         tweak1 = asm_xor (tweak1, rkey0);
+         tweak2 = asm_xor (tweak2, rkey0);
+         tweak3 = asm_xor (tweak3, rkey0);
+         tweak4 = asm_xor (tweak4, rkey0);
+         tweak5 = asm_xor (tweak5, rkey0);
+         tweak6 = asm_xor (tweak6, rkey0);
+         tweak7 = asm_xor (tweak7, rkey0);
+
+         b0 = asm_xor (b0, tweak0);
+         b1 = asm_xor (b1, tweak1);
+         b2 = asm_xor (b2, tweak2);
+         b3 = asm_xor (b3, tweak3);
+         b4 = asm_xor (b4, tweak4);
+         b5 = asm_xor (b5, tweak5);
+         b6 = asm_xor (b6, tweak6);
+         b7 = asm_xor (b7, tweak7);
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey); \
+             b4 = asm_cipher_be (b4, rkey); \
+             b5 = asm_cipher_be (b5, rkey); \
+             b6 = asm_cipher_be (b6, rkey); \
+             b7 = asm_cipher_be (b7, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+
+         rkeylf = asm_xor (rkeylast, rkey0);
+
+         DO_ROUND(8);
+
+         tweak0 = asm_xor (tweak0, rkeylf);
+         tweak1 = asm_xor (tweak1, rkeylf);
+         tweak2 = asm_xor (tweak2, rkeylf);
+         tweak3 = asm_xor (tweak3, rkeylf);
+         tweak4 = asm_xor (tweak4, rkeylf);
+         tweak5 = asm_xor (tweak5, rkeylf);
+         tweak6 = asm_xor (tweak6, rkeylf);
+         tweak7 = asm_xor (tweak7, rkeylf);
+
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         b0 = asm_cipherlast_be (b0, tweak0);
+         b1 = asm_cipherlast_be (b1, tweak1);
+         b2 = asm_cipherlast_be (b2, tweak2);
+         b3 = asm_cipherlast_be (b3, tweak3);
+         b0 = VEC_BE_SWAP (b0, bige_const);
+         b1 = VEC_BE_SWAP (b1, bige_const);
+         b4 = asm_cipherlast_be (b4, tweak4);
+         b5 = asm_cipherlast_be (b5, tweak5);
+         b2 = VEC_BE_SWAP (b2, bige_const);
+         b3 = VEC_BE_SWAP (b3, bige_const);
+         b6 = asm_cipherlast_be (b6, tweak6);
+         b7 = asm_cipherlast_be (b7, tweak7);
+         VEC_STORE_BE_NOSWAP (out, 0, b0);
+         VEC_STORE_BE_NOSWAP (out, 1, b1);
+         b4 = VEC_BE_SWAP (b4, bige_const);
+         b5 = VEC_BE_SWAP (b5, bige_const);
+         VEC_STORE_BE_NOSWAP (out, 2, b2);
+         VEC_STORE_BE_NOSWAP (out, 3, b3);
+         b6 = VEC_BE_SWAP (b6, bige_const);
+         b7 = VEC_BE_SWAP (b7, bige_const);
+         VEC_STORE_BE_NOSWAP (out, 4, b4);
+         VEC_STORE_BE_NOSWAP (out, 5, b5);
+         VEC_STORE_BE_NOSWAP (out, 6, b6);
+         VEC_STORE_BE_NOSWAP (out, 7, b7);
+         out += 8;
+       }
+
+      if (nblocks >= 4)
+       {
+         tweak0 = tweak;
+         GEN_TWEAK (tweak1, tweak0);
+         GEN_TWEAK (tweak2, tweak1);
+         GEN_TWEAK (tweak3, tweak2);
+         GEN_TWEAK (tweak, tweak3);
+
+         b0 = VEC_LOAD_BE (in, 0, bige_const);
+         b1 = VEC_LOAD_BE (in, 1, bige_const);
+         b2 = VEC_LOAD_BE (in, 2, bige_const);
+         b3 = VEC_LOAD_BE (in, 3, bige_const);
+
+         tweak0 = asm_vperm1 (tweak0, bswap128_const);
+         tweak1 = asm_vperm1 (tweak1, bswap128_const);
+         tweak2 = asm_vperm1 (tweak2, bswap128_const);
+         tweak3 = asm_vperm1 (tweak3, bswap128_const);
+
+         b0 ^= tweak0 ^ rkey0;
+         b1 ^= tweak1 ^ rkey0;
+         b2 ^= tweak2 ^ rkey0;
+         b3 ^= tweak3 ^ rkey0;
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_cipher_be (b0, rkey); \
+             b1 = asm_cipher_be (b1, rkey); \
+             b2 = asm_cipher_be (b2, rkey); \
+             b3 = asm_cipher_be (b3, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+         DO_ROUND(8);
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         rkey = rkeylast;
+         b0 = asm_cipherlast_be (b0, rkey ^ tweak0);
+         b1 = asm_cipherlast_be (b1, rkey ^ tweak1);
+         b2 = asm_cipherlast_be (b2, rkey ^ tweak2);
+         b3 = asm_cipherlast_be (b3, rkey ^ tweak3);
+
+         VEC_STORE_BE (out, 0, b0, bige_const);
+         VEC_STORE_BE (out, 1, b1, bige_const);
+         VEC_STORE_BE (out, 2, b2, bige_const);
+         VEC_STORE_BE (out, 3, b3, bige_const);
+
+         in += 4;
+         out += 4;
+         nblocks -= 4;
+       }
+
+      for (; nblocks; nblocks--)
+       {
+         tweak0 = asm_vperm1 (tweak, bswap128_const);
+
+         /* Xor-Encrypt/Decrypt-Xor block. */
+         b = VEC_LOAD_BE (in, 0, bige_const) ^ tweak0;
+
+         /* Generate next tweak. */
+         GEN_TWEAK (tweak, tweak);
+
+         AES_ENCRYPT (b, rounds);
+
+         b ^= tweak0;
+         VEC_STORE_BE (out, 0, b, bige_const);
+
+         in++;
+         out++;
+       }
+    }
+  else
+    {
+      const u128_t *rk = (u128_t *)&ctx->keyschdec;
+
+      if (!ctx->decryption_prepared)
+       {
+         internal_aes_ppc_prepare_decryption (ctx);
+         ctx->decryption_prepared = 1;
+       }
+
+      PRELOAD_ROUND_KEYS (rounds);
+
+      for (; nblocks >= 8; nblocks -= 8)
+       {
+         b0 = VEC_LOAD_BE_NOSWAP (in, 0);
+         b1 = VEC_LOAD_BE_NOSWAP (in, 1);
+         b2 = VEC_LOAD_BE_NOSWAP (in, 2);
+         b3 = VEC_LOAD_BE_NOSWAP (in, 3);
+         tweak0 = tweak;
+         GEN_TWEAK (tweak1, tweak0);
+         tweak0 = asm_vperm1 (tweak0, bswap128_const);
+         b4 = VEC_LOAD_BE_NOSWAP (in, 4);
+         b5 = VEC_LOAD_BE_NOSWAP (in, 5);
+         GEN_TWEAK (tweak2, tweak1);
+         tweak1 = asm_vperm1 (tweak1, bswap128_const);
+         b6 = VEC_LOAD_BE_NOSWAP (in, 6);
+         b7 = VEC_LOAD_BE_NOSWAP (in, 7);
+         in += 8;
+
+         b0 = VEC_BE_SWAP(b0, bige_const);
+         b1 = VEC_BE_SWAP(b1, bige_const);
+         GEN_TWEAK (tweak3, tweak2);
+         tweak2 = asm_vperm1 (tweak2, bswap128_const);
+         GEN_TWEAK (tweak4, tweak3);
+         tweak3 = asm_vperm1 (tweak3, bswap128_const);
+         b2 = VEC_BE_SWAP(b2, bige_const);
+         b3 = VEC_BE_SWAP(b3, bige_const);
+         GEN_TWEAK (tweak5, tweak4);
+         tweak4 = asm_vperm1 (tweak4, bswap128_const);
+         GEN_TWEAK (tweak6, tweak5);
+         tweak5 = asm_vperm1 (tweak5, bswap128_const);
+         b4 = VEC_BE_SWAP(b4, bige_const);
+         b5 = VEC_BE_SWAP(b5, bige_const);
+         GEN_TWEAK (tweak7, tweak6);
+         tweak6 = asm_vperm1 (tweak6, bswap128_const);
+         GEN_TWEAK (tweak, tweak7);
+         tweak7 = asm_vperm1 (tweak7, bswap128_const);
+         b6 = VEC_BE_SWAP(b6, bige_const);
+         b7 = VEC_BE_SWAP(b7, bige_const);
+
+         tweak0 = asm_xor (tweak0, rkey0);
+         tweak1 = asm_xor (tweak1, rkey0);
+         tweak2 = asm_xor (tweak2, rkey0);
+         tweak3 = asm_xor (tweak3, rkey0);
+         tweak4 = asm_xor (tweak4, rkey0);
+         tweak5 = asm_xor (tweak5, rkey0);
+         tweak6 = asm_xor (tweak6, rkey0);
+         tweak7 = asm_xor (tweak7, rkey0);
+
+         b0 = asm_xor (b0, tweak0);
+         b1 = asm_xor (b1, tweak1);
+         b2 = asm_xor (b2, tweak2);
+         b3 = asm_xor (b3, tweak3);
+         b4 = asm_xor (b4, tweak4);
+         b5 = asm_xor (b5, tweak5);
+         b6 = asm_xor (b6, tweak6);
+         b7 = asm_xor (b7, tweak7);
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_ncipher_be (b0, rkey); \
+             b1 = asm_ncipher_be (b1, rkey); \
+             b2 = asm_ncipher_be (b2, rkey); \
+             b3 = asm_ncipher_be (b3, rkey); \
+             b4 = asm_ncipher_be (b4, rkey); \
+             b5 = asm_ncipher_be (b5, rkey); \
+             b6 = asm_ncipher_be (b6, rkey); \
+             b7 = asm_ncipher_be (b7, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+
+         rkeylf = asm_xor (rkeylast, rkey0);
+
+         DO_ROUND(8);
+
+         tweak0 = asm_xor (tweak0, rkeylf);
+         tweak1 = asm_xor (tweak1, rkeylf);
+         tweak2 = asm_xor (tweak2, rkeylf);
+         tweak3 = asm_xor (tweak3, rkeylf);
+         tweak4 = asm_xor (tweak4, rkeylf);
+         tweak5 = asm_xor (tweak5, rkeylf);
+         tweak6 = asm_xor (tweak6, rkeylf);
+         tweak7 = asm_xor (tweak7, rkeylf);
+
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         b0 = asm_ncipherlast_be (b0, tweak0);
+         b1 = asm_ncipherlast_be (b1, tweak1);
+         b2 = asm_ncipherlast_be (b2, tweak2);
+         b3 = asm_ncipherlast_be (b3, tweak3);
+         b0 = VEC_BE_SWAP (b0, bige_const);
+         b1 = VEC_BE_SWAP (b1, bige_const);
+         b4 = asm_ncipherlast_be (b4, tweak4);
+         b5 = asm_ncipherlast_be (b5, tweak5);
+         b2 = VEC_BE_SWAP (b2, bige_const);
+         b3 = VEC_BE_SWAP (b3, bige_const);
+         b6 = asm_ncipherlast_be (b6, tweak6);
+         b7 = asm_ncipherlast_be (b7, tweak7);
+         VEC_STORE_BE_NOSWAP (out, 0, b0);
+         VEC_STORE_BE_NOSWAP (out, 1, b1);
+         b4 = VEC_BE_SWAP (b4, bige_const);
+         b5 = VEC_BE_SWAP (b5, bige_const);
+         VEC_STORE_BE_NOSWAP (out, 2, b2);
+         VEC_STORE_BE_NOSWAP (out, 3, b3);
+         b6 = VEC_BE_SWAP (b6, bige_const);
+         b7 = VEC_BE_SWAP (b7, bige_const);
+         VEC_STORE_BE_NOSWAP (out, 4, b4);
+         VEC_STORE_BE_NOSWAP (out, 5, b5);
+         VEC_STORE_BE_NOSWAP (out, 6, b6);
+         VEC_STORE_BE_NOSWAP (out, 7, b7);
+         out += 8;
+       }
+
+      if (nblocks >= 4)
+       {
+         tweak0 = tweak;
+         GEN_TWEAK (tweak1, tweak0);
+         GEN_TWEAK (tweak2, tweak1);
+         GEN_TWEAK (tweak3, tweak2);
+         GEN_TWEAK (tweak, tweak3);
+
+         b0 = VEC_LOAD_BE (in, 0, bige_const);
+         b1 = VEC_LOAD_BE (in, 1, bige_const);
+         b2 = VEC_LOAD_BE (in, 2, bige_const);
+         b3 = VEC_LOAD_BE (in, 3, bige_const);
+
+         tweak0 = asm_vperm1 (tweak0, bswap128_const);
+         tweak1 = asm_vperm1 (tweak1, bswap128_const);
+         tweak2 = asm_vperm1 (tweak2, bswap128_const);
+         tweak3 = asm_vperm1 (tweak3, bswap128_const);
+
+         b0 ^= tweak0 ^ rkey0;
+         b1 ^= tweak1 ^ rkey0;
+         b2 ^= tweak2 ^ rkey0;
+         b3 ^= tweak3 ^ rkey0;
+
+#define DO_ROUND(r) \
+             rkey = ALIGNED_LOAD (rk, r); \
+             b0 = asm_ncipher_be (b0, rkey); \
+             b1 = asm_ncipher_be (b1, rkey); \
+             b2 = asm_ncipher_be (b2, rkey); \
+             b3 = asm_ncipher_be (b3, rkey);
+
+         DO_ROUND(1);
+         DO_ROUND(2);
+         DO_ROUND(3);
+         DO_ROUND(4);
+         DO_ROUND(5);
+         DO_ROUND(6);
+         DO_ROUND(7);
+         DO_ROUND(8);
+         DO_ROUND(9);
+         if (rounds >= 12)
+           {
+             DO_ROUND(10);
+             DO_ROUND(11);
+             if (rounds > 12)
+               {
+                 DO_ROUND(12);
+                 DO_ROUND(13);
+               }
+           }
+
+#undef DO_ROUND
+
+         rkey = rkeylast;
+         b0 = asm_ncipherlast_be (b0, rkey ^ tweak0);
+         b1 = asm_ncipherlast_be (b1, rkey ^ tweak1);
+         b2 = asm_ncipherlast_be (b2, rkey ^ tweak2);
+         b3 = asm_ncipherlast_be (b3, rkey ^ tweak3);
+
+         VEC_STORE_BE (out, 0, b0, bige_const);
+         VEC_STORE_BE (out, 1, b1, bige_const);
+         VEC_STORE_BE (out, 2, b2, bige_const);
+         VEC_STORE_BE (out, 3, b3, bige_const);
+
+         in += 4;
+         out += 4;
+         nblocks -= 4;
+       }
+
+      for (; nblocks; nblocks--)
+       {
+         tweak0 = asm_vperm1 (tweak, bswap128_const);
+
+         /* Xor-Encrypt/Decrypt-Xor block. */
+         b = VEC_LOAD_BE (in, 0, bige_const) ^ tweak0;
+
+         /* Generate next tweak. */
+         GEN_TWEAK (tweak, tweak);
+
+         AES_DECRYPT (b, rounds);
+
+         b ^= tweak0;
+         VEC_STORE_BE (out, 0, b, bige_const);
+
+         in++;
+         out++;
+       }
+    }
+
+  tweak = asm_vperm1 (tweak, bswap128_const);
+  VEC_STORE_BE (tweak_arg, 0, tweak, bige_const);
+
+#undef GEN_TWEAK
+}
diff --git a/cipher/rijndael-ppc.c b/cipher/rijndael-ppc.c
new file mode 100644 (file)
index 0000000..f5c3236
--- /dev/null
@@ -0,0 +1,259 @@
+/* Rijndael (AES) for GnuPG - PowerPC Vector Crypto AES implementation
+ * Copyright (C) 2019 Shawn Landden <shawn@git.icu>
+ * Copyright (C) 2019-2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Alternatively, this code may be used in OpenSSL from The OpenSSL Project,
+ * and Cryptogams by Andy Polyakov, and if made part of a release of either
+ * or both projects, is thereafter dual-licensed under the license said project
+ * is released under.
+ */
+
+#include <config.h>
+
+#include "rijndael-internal.h"
+#include "cipher-internal.h"
+#include "bufhelp.h"
+
+#ifdef USE_PPC_CRYPTO
+
+#include "rijndael-ppc-common.h"
+
+
+#ifdef WORDS_BIGENDIAN
+static const block vec_bswap32_const =
+  { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 };
+#else
+static const block vec_bswap32_const_neg =
+  { ~3, ~2, ~1, ~0, ~7, ~6, ~5, ~4, ~11, ~10, ~9, ~8, ~15, ~14, ~13, ~12 };
+#endif
+
+
+static ASM_FUNC_ATTR_INLINE block
+asm_load_be_const(void)
+{
+#ifndef WORDS_BIGENDIAN
+  return ALIGNED_LOAD (&vec_bswap32_const_neg, 0);
+#else
+  static const block vec_dummy = { 0 };
+  return vec_dummy;
+#endif
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_be_swap(block vec, block be_bswap_const)
+{
+  (void)be_bswap_const;
+#ifndef WORDS_BIGENDIAN
+  return asm_vperm1 (vec, be_bswap_const);
+#else
+  return vec;
+#endif
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_load_be_noswap(unsigned long offset, const void *ptr)
+{
+  block vec;
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("lxvw4x %x0,0,%1\n\t"
+                     : "=wa" (vec)
+                     : "r" ((uintptr_t)ptr)
+                     : "memory");
+  else
+#endif
+    __asm__ volatile ("lxvw4x %x0,%1,%2\n\t"
+                     : "=wa" (vec)
+                     : "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+  /* NOTE: vec needs to be be-swapped using 'asm_be_swap' by caller */
+  return vec;
+}
+
+static ASM_FUNC_ATTR_INLINE void
+asm_store_be_noswap(block vec, unsigned long offset, void *ptr)
+{
+  /* NOTE: vec be-swapped using 'asm_be_swap' by caller */
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("stxvw4x %x0,0,%1\n\t"
+                     :
+                     : "wa" (vec), "r" ((uintptr_t)ptr)
+                     : "memory");
+  else
+#endif
+    __asm__ volatile ("stxvw4x %x0,%1,%2\n\t"
+                     :
+                     : "wa" (vec), "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+}
+
+
+static ASM_FUNC_ATTR_INLINE u32
+_gcry_aes_sbox4_ppc8(u32 fourbytes)
+{
+  union
+    {
+      PROPERLY_ALIGNED_TYPE dummy;
+      block data_vec;
+      u32 data32[4];
+    } u;
+
+  u.data32[0] = fourbytes;
+  u.data_vec = vec_sbox_be(u.data_vec);
+  return u.data32[0];
+}
+
+void
+_gcry_aes_ppc8_setkey (RIJNDAEL_context *ctx, const byte *key)
+{
+  const block bige_const = asm_load_be_const();
+  union
+    {
+      PROPERLY_ALIGNED_TYPE dummy;
+      byte data[MAXKC][4];
+      u32 data32[MAXKC];
+    } tkk[2];
+  unsigned int rounds = ctx->rounds;
+  int KC = rounds - 6;
+  unsigned int keylen = KC * 4;
+  u128_t *ekey = (u128_t *)(void *)ctx->keyschenc;
+  unsigned int i, r, t;
+  byte rcon = 1;
+  int j;
+#define k      tkk[0].data
+#define k_u32  tkk[0].data32
+#define tk     tkk[1].data
+#define tk_u32 tkk[1].data32
+#define W      (ctx->keyschenc)
+#define W_u32  (ctx->keyschenc32)
+
+  for (i = 0; i < keylen; i++)
+    {
+      k[i >> 2][i & 3] = key[i];
+    }
+
+  for (j = KC-1; j >= 0; j--)
+    {
+      tk_u32[j] = k_u32[j];
+    }
+  r = 0;
+  t = 0;
+  /* Copy values into round key array.  */
+  for (j = 0; (j < KC) && (r < rounds + 1); )
+    {
+      for (; (j < KC) && (t < 4); j++, t++)
+        {
+          W_u32[r][t] = le_bswap32(tk_u32[j]);
+        }
+      if (t == 4)
+        {
+          r++;
+          t = 0;
+        }
+    }
+  while (r < rounds + 1)
+    {
+      tk_u32[0] ^=
+       le_bswap32(
+         _gcry_aes_sbox4_ppc8(rol(le_bswap32(tk_u32[KC - 1]), 24)) ^ rcon);
+
+      if (KC != 8)
+        {
+          for (j = 1; j < KC; j++)
+            {
+              tk_u32[j] ^= tk_u32[j-1];
+            }
+        }
+      else
+        {
+          for (j = 1; j < KC/2; j++)
+            {
+              tk_u32[j] ^= tk_u32[j-1];
+            }
+
+          tk_u32[KC/2] ^=
+           le_bswap32(_gcry_aes_sbox4_ppc8(le_bswap32(tk_u32[KC/2 - 1])));
+
+          for (j = KC/2 + 1; j < KC; j++)
+            {
+              tk_u32[j] ^= tk_u32[j-1];
+            }
+        }
+
+      /* Copy values into round key array.  */
+      for (j = 0; (j < KC) && (r < rounds + 1); )
+        {
+          for (; (j < KC) && (t < 4); j++, t++)
+            {
+              W_u32[r][t] = le_bswap32(tk_u32[j]);
+            }
+          if (t == 4)
+            {
+              r++;
+              t = 0;
+            }
+        }
+
+      rcon = (rcon << 1) ^ (-(rcon >> 7) & 0x1b);
+    }
+
+  /* Store in big-endian order. */
+  for (r = 0; r <= rounds; r++)
+    {
+#ifndef WORDS_BIGENDIAN
+      VEC_STORE_BE(ekey, r, ALIGNED_LOAD (ekey, r), bige_const);
+#else
+      block rvec = ALIGNED_LOAD (ekey, r);
+      ALIGNED_STORE (ekey, r,
+                     vec_perm(rvec, rvec, vec_bswap32_const));
+      (void)bige_const;
+#endif
+    }
+
+#undef W
+#undef tk
+#undef k
+#undef W_u32
+#undef tk_u32
+#undef k_u32
+  wipememory(&tkk, sizeof(tkk));
+}
+
+void
+_gcry_aes_ppc8_prepare_decryption (RIJNDAEL_context *ctx)
+{
+  internal_aes_ppc_prepare_decryption (ctx);
+}
+
+
+#define GCRY_AES_PPC8 1
+#define ENCRYPT_BLOCK_FUNC     _gcry_aes_ppc8_encrypt
+#define DECRYPT_BLOCK_FUNC     _gcry_aes_ppc8_decrypt
+#define CFB_ENC_FUNC           _gcry_aes_ppc8_cfb_enc
+#define CFB_DEC_FUNC           _gcry_aes_ppc8_cfb_dec
+#define CBC_ENC_FUNC           _gcry_aes_ppc8_cbc_enc
+#define CBC_DEC_FUNC           _gcry_aes_ppc8_cbc_dec
+#define CTR_ENC_FUNC           _gcry_aes_ppc8_ctr_enc
+#define OCB_CRYPT_FUNC         _gcry_aes_ppc8_ocb_crypt
+#define OCB_AUTH_FUNC          _gcry_aes_ppc8_ocb_auth
+#define XTS_CRYPT_FUNC         _gcry_aes_ppc8_xts_crypt
+
+#include <rijndael-ppc-functions.h>
+
+#endif /* USE_PPC_CRYPTO */
diff --git a/cipher/rijndael-ppc9le.c b/cipher/rijndael-ppc9le.c
new file mode 100644 (file)
index 0000000..facdedd
--- /dev/null
@@ -0,0 +1,102 @@
+/* Rijndael (AES) for GnuPG - PowerPC Vector Crypto AES implementation
+ * Copyright (C) 2019 Shawn Landden <shawn@git.icu>
+ * Copyright (C) 2019-2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Alternatively, this code may be used in OpenSSL from The OpenSSL Project,
+ * and Cryptogams by Andy Polyakov, and if made part of a release of either
+ * or both projects, is thereafter dual-licensed under the license said project
+ * is released under.
+ */
+
+#include <config.h>
+
+#include "rijndael-internal.h"
+#include "cipher-internal.h"
+#include "bufhelp.h"
+
+#ifdef USE_PPC_CRYPTO_WITH_PPC9LE
+
+#include "rijndael-ppc-common.h"
+
+
+static ASM_FUNC_ATTR_INLINE block
+asm_load_be_const(void)
+{
+  static const block vec_dummy = { 0 };
+  return vec_dummy;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_be_swap(block vec, block be_bswap_const)
+{
+  (void)be_bswap_const;
+  return vec;
+}
+
+static ASM_FUNC_ATTR_INLINE block
+asm_load_be_noswap(unsigned long offset, const void *ptr)
+{
+  block vec;
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("lxvb16x %x0,0,%1\n\t"
+                     : "=wa" (vec)
+                     : "r" ((uintptr_t)ptr)
+                     : "memory");
+  else
+#endif
+    __asm__ volatile ("lxvb16x %x0,%1,%2\n\t"
+                     : "=wa" (vec)
+                     : "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+  return vec;
+}
+
+static ASM_FUNC_ATTR_INLINE void
+asm_store_be_noswap(block vec, unsigned long offset, void *ptr)
+{
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ volatile ("stxvb16x %x0,0,%1\n\t"
+                     :
+                     : "wa" (vec), "r" ((uintptr_t)ptr)
+                     : "memory");
+  else
+#endif
+    __asm__ volatile ("stxvb16x %x0,%1,%2\n\t"
+                     :
+                     : "wa" (vec), "r" (offset), "r" ((uintptr_t)ptr)
+                     : "memory", "r0");
+}
+
+
+#define GCRY_AES_PPC9LE 1
+#define ENCRYPT_BLOCK_FUNC     _gcry_aes_ppc9le_encrypt
+#define DECRYPT_BLOCK_FUNC     _gcry_aes_ppc9le_decrypt
+#define CFB_ENC_FUNC           _gcry_aes_ppc9le_cfb_enc
+#define CFB_DEC_FUNC           _gcry_aes_ppc9le_cfb_dec
+#define CBC_ENC_FUNC           _gcry_aes_ppc9le_cbc_enc
+#define CBC_DEC_FUNC           _gcry_aes_ppc9le_cbc_dec
+#define CTR_ENC_FUNC           _gcry_aes_ppc9le_ctr_enc
+#define OCB_CRYPT_FUNC         _gcry_aes_ppc9le_ocb_crypt
+#define OCB_AUTH_FUNC          _gcry_aes_ppc9le_ocb_auth
+#define XTS_CRYPT_FUNC         _gcry_aes_ppc9le_xts_crypt
+
+#include <rijndael-ppc-functions.h>
+
+#endif /* USE_PPC_CRYPTO */
diff --git a/cipher/rijndael-s390x.c b/cipher/rijndael-s390x.c
new file mode 100644 (file)
index 0000000..e50537e
--- /dev/null
@@ -0,0 +1,1166 @@
+/* Rijndael (AES) for GnuPG - s390x/zSeries AES implementation
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "rijndael-internal.h"
+#include "cipher-internal.h"
+#include "bufhelp.h"
+
+#ifdef USE_S390X_CRYPTO
+
+#include "asm-inline-s390x.h"
+
+#define NO_INLINE __attribute__((noinline))
+
+struct aes_s390x_gcm_params_s
+{
+  u32 reserved[3];
+  u32 counter_value;
+  u64 tag[2];
+  u64 hash_subkey[2];
+  u64 total_aad_length;
+  u64 total_cipher_length;
+  u32 initial_counter_value[4];
+  u64 key[4];
+};
+
+#define DECL_QUERY_FUNC(instruction, opcode) \
+  static u128_t instruction ##_query(void) \
+  { \
+    static u128_t function_codes = 0; \
+    static int initialized = 0; \
+    register unsigned long reg0 asm("0") = 0; \
+    register void *reg1 asm("1") = &function_codes; \
+    u128_t r1, r2; \
+    \
+    if (initialized) \
+      return function_codes; \
+    \
+    asm volatile ("0: .insn rre," #opcode " << 16, %[r1], %[r2]\n\t" \
+                 "   brc 1,0b\n\t" \
+                 : [r1] "=a" (r1), [r2] "=a" (r2) \
+                 : [reg0] "r" (reg0), [reg1] "r" (reg1) \
+                 : "cc", "memory"); \
+    \
+    initialized = 1; \
+    return function_codes; \
+  }
+
+#define DECL_EXECUTE_FUNC(instruction, opcode, param_const) \
+  static ALWAYS_INLINE size_t \
+  instruction ##_execute(unsigned int func, param_const void *param_block, \
+                        void *dst, const void *src, size_t src_len) \
+  { \
+    register unsigned long reg0 asm("0") = func; \
+    register param_const byte *reg1 asm("1") = param_block; \
+    u128_t r1 = ((u128_t)(uintptr_t)dst << 64); \
+    u128_t r2 = ((u128_t)(uintptr_t)src << 64) | (u64)src_len; \
+    \
+    asm volatile ("0: .insn rre," #opcode " << 16, %[r1], %[r2]\n\t" \
+                 "   brc 1,0b\n\t" \
+                 : [r1] "+a" (r1), [r2] "+a" (r2) \
+                 : [func] "r" (reg0), [param_ptr] "r" (reg1) \
+                 : "cc", "memory"); \
+    \
+    return (u64)r2; \
+  }
+
+DECL_QUERY_FUNC(km, 0xb92e);
+DECL_QUERY_FUNC(kmc, 0xb92f);
+DECL_QUERY_FUNC(kmac, 0xb91e);
+DECL_QUERY_FUNC(kmf, 0xb92a);
+DECL_QUERY_FUNC(kmo, 0xb92b);
+
+DECL_EXECUTE_FUNC(km, 0xb92e, const);
+DECL_EXECUTE_FUNC(kmc, 0xb92f, );
+DECL_EXECUTE_FUNC(kmac, 0xb91e, );
+DECL_EXECUTE_FUNC(kmf, 0xb92a, );
+DECL_EXECUTE_FUNC(kmo, 0xb92b, );
+
+static u128_t kma_query(void)
+{
+  static u128_t function_codes = 0;
+  static int initialized = 0;
+  register unsigned long reg0 asm("0") = 0;
+  register void *reg1 asm("1") = &function_codes;
+  u128_t r1, r2, r3;
+
+  if (initialized)
+    return function_codes;
+
+  asm volatile ("0: .insn rrf,0xb929 << 16, %[r1], %[r2], %[r3], 0\n\t"
+               "   brc 1,0b\n\t"
+               : [r1] "=a" (r1), [r2] "=a" (r2), [r3] "=a" (r3)
+               : [reg0] "r" (reg0), [reg1] "r" (reg1)
+               : "cc", "memory");
+
+  initialized = 1;
+  return function_codes;
+}
+
+static ALWAYS_INLINE void
+kma_execute(unsigned int func, void *param_block, byte *dst, const byte *src,
+           size_t src_len, const byte *aad, size_t aad_len)
+{
+  register unsigned long reg0 asm("0") = func;
+  register byte *reg1 asm("1") = param_block;
+  u128_t r1 = ((u128_t)(uintptr_t)dst << 64);
+  u128_t r2 = ((u128_t)(uintptr_t)src << 64) | (u64)src_len;
+  u128_t r3 = ((u128_t)(uintptr_t)aad << 64) | (u64)aad_len;
+
+  asm volatile ("0: .insn rrf,0xb929 << 16, %[r1], %[r2], %[r3], 0\n\t"
+               "   brc 1,0b\n\t"
+               : [r1] "+a" (r1), [r2] "+a" (r2), [r3] "+a" (r3),
+                 [func] "+r" (reg0)
+               : [param_ptr] "r" (reg1)
+               : "cc", "memory");
+}
+
+unsigned int _gcry_aes_s390x_encrypt(const RIJNDAEL_context *ctx,
+                                    unsigned char *dst,
+                                    const unsigned char *src)
+{
+  km_execute (ctx->km_func | KM_ENCRYPT, ctx->keyschenc, dst, src,
+             BLOCKSIZE);
+  return 0;
+}
+
+unsigned int _gcry_aes_s390x_decrypt(const RIJNDAEL_context *ctx,
+                                    unsigned char *dst,
+                                    const unsigned char *src)
+{
+  km_execute (ctx->km_func | KM_DECRYPT, ctx->keyschenc, dst, src,
+             BLOCKSIZE);
+  return 0;
+}
+
+static void aes_s390x_cbc_enc(void *context, unsigned char *iv,
+                             void *outbuf_arg, const void *inbuf_arg,
+                             size_t nblocks, int cbc_mac)
+{
+  RIJNDAEL_context *ctx = context;
+  byte *out = outbuf_arg;
+  const byte *in = inbuf_arg;
+  u128_t params[3];
+
+  /* Prepare parameter block. */
+  memcpy (&params[0], iv, BLOCKSIZE);
+  memcpy (&params[1], ctx->keyschenc, 32);
+
+  if (cbc_mac)
+    {
+      kmac_execute (ctx->kmac_func | KM_ENCRYPT, &params, NULL, in,
+                   nblocks * BLOCKSIZE);
+      memcpy (out, &params[0], BLOCKSIZE);
+    }
+  else
+    {
+      kmc_execute (ctx->kmc_func | KM_ENCRYPT, &params, out, in,
+                  nblocks * BLOCKSIZE);
+    }
+
+  /* Update IV with OCV. */
+  memcpy (iv, &params[0], BLOCKSIZE);
+
+  wipememory (&params, sizeof(params));
+}
+
+static void aes_s390x_cbc_dec(void *context, unsigned char *iv,
+                             void *outbuf_arg, const void *inbuf_arg,
+                             size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  byte *out = outbuf_arg;
+  const byte *in = inbuf_arg;
+  u128_t params[3];
+
+  /* Prepare parameter block (ICV & key). */
+  memcpy (&params[0], iv, BLOCKSIZE);
+  memcpy (&params[1], ctx->keyschenc, 32);
+
+  kmc_execute (ctx->kmc_func | KM_DECRYPT, &params, out, in,
+              nblocks * BLOCKSIZE);
+
+  /* Update IV with OCV. */
+  memcpy (iv, &params[0], BLOCKSIZE);
+
+  wipememory (&params, sizeof(params));
+}
+
+static void aes_s390x_cfb128_enc(void *context, unsigned char *iv,
+                                void *outbuf_arg, const void *inbuf_arg,
+                                size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  byte *out = outbuf_arg;
+  const byte *in = inbuf_arg;
+  unsigned int function;
+  u128_t params[3];
+
+  /* Prepare parameter block. */
+  memcpy (&params[0], iv, BLOCKSIZE);
+  memcpy (&params[1], ctx->keyschenc, 32);
+
+  function = ctx->kmf_func | KM_ENCRYPT | KMF_LCFB_16;
+  kmf_execute (function, &params, out, in, nblocks * BLOCKSIZE);
+
+  /* Update IV with OCV. */
+  memcpy (iv, &params[0], BLOCKSIZE);
+
+  wipememory (&params, sizeof(params));
+}
+
+static void aes_s390x_cfb128_dec(void *context, unsigned char *iv,
+                                void *outbuf_arg, const void *inbuf_arg,
+                                size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  u128_t blocks[64];
+  byte *out = outbuf_arg;
+  const byte *in = inbuf_arg;
+  size_t max_blocks_used = 0;
+
+  /* AES128-CFB128 decryption speed using KMF was observed to be the same as
+   * the KMF encryption, ~1.03 cpb. Expection was to see similar performance
+   * as for AES128-CBC decryption as decryption for both modes should be
+   * parallalizeble (CBC shows ~0.22 cpb). Therefore there is quite a bit
+   * of room for improvement and implementation below using KM instruction
+   * shows ~0.70 cpb speed, ~30% improvement over KMF instruction.
+   */
+
+  while (nblocks >= 64)
+    {
+      /* Copy IV to encrypt buffer, copy (nblocks - 1) input blocks to
+       * encrypt buffer and update IV. */
+      asm volatile ("mvc 0(16, %[blocks]), 0(%[iv])\n\t"
+                   "mvc  16(240, %[blocks]),   0(%[in])\n\t"
+                   "mvc 256(256, %[blocks]), 240(%[in])\n\t"
+                   "mvc 512(256, %[blocks]), 496(%[in])\n\t"
+                   "mvc 768(256, %[blocks]), 752(%[in])\n\t"
+                   "mvc 0(16, %[iv]), 1008(%[in])\n\t"
+                   :
+                   : [in] "a" (in), [out] "a" (out), [blocks] "a" (blocks),
+                     [iv] "a" (iv)
+                   : "memory");
+
+      /* Perform encryption of temporary buffer. */
+      km_execute (ctx->km_func | KM_ENCRYPT, ctx->keyschenc, blocks, blocks,
+                 64 * BLOCKSIZE);
+
+      /* Xor encrypt buffer with input blocks and store to output blocks. */
+      asm volatile ("xc   0(256, %[blocks]),   0(%[in])\n\t"
+                   "xc 256(256, %[blocks]), 256(%[in])\n\t"
+                   "xc 512(256, %[blocks]), 512(%[in])\n\t"
+                   "xc 768(256, %[blocks]), 768(%[in])\n\t"
+                   "mvc   0(256, %[out]),   0(%[blocks])\n\t"
+                   "mvc 256(256, %[out]), 256(%[blocks])\n\t"
+                   "mvc 512(256, %[out]), 512(%[blocks])\n\t"
+                   "mvc 768(256, %[out]), 768(%[blocks])\n\t"
+                   :
+                   : [in] "a" (in), [out] "a" (out), [blocks] "a" (blocks)
+                   : "memory");
+
+      max_blocks_used = 64;
+      in += 64 * BLOCKSIZE;
+      out += 64 * BLOCKSIZE;
+      nblocks -= 64;
+    }
+
+  if (nblocks)
+    {
+      unsigned int pos = 0;
+      size_t in_nblocks = nblocks;
+      size_t num_in = 0;
+
+      max_blocks_used = max_blocks_used < nblocks ? nblocks : max_blocks_used;
+
+      /* Copy IV to encrypt buffer. */
+      asm volatile ("mvc 0(16, %[blocks]), 0(%[iv])\n\t"
+                   :
+                   : [blocks] "a" (blocks), [iv] "a" (iv)
+                   : "memory");
+      pos += 1;
+
+#define CFB_MOVE_BLOCKS(block_oper, move_nbytes) \
+      block_oper (in_nblocks - 1 >= move_nbytes / BLOCKSIZE) \
+       { \
+         unsigned int move_nblocks = move_nbytes / BLOCKSIZE; \
+         asm volatile ("mvc 0(" #move_nbytes ", %[blocks_x]), 0(%[in])\n\t" \
+                       : \
+                       : [blocks_x] "a" (&blocks[pos]), [in] "a" (in) \
+                       : "memory"); \
+         num_in += move_nblocks; \
+         in += move_nblocks * BLOCKSIZE; \
+         pos += move_nblocks; \
+          in_nblocks -= move_nblocks; \
+       }
+
+      /* Copy (nblocks - 1) input blocks to encrypt buffer. */
+      CFB_MOVE_BLOCKS(while, 256);
+      CFB_MOVE_BLOCKS(if, 128);
+      CFB_MOVE_BLOCKS(if, 64);
+      CFB_MOVE_BLOCKS(if, 32);
+      CFB_MOVE_BLOCKS(if, 16);
+
+#undef CFB_MOVE_BLOCKS
+
+      /* Update IV. */
+      asm volatile ("mvc 0(16, %[iv]), 0(%[in])\n\t"
+                   :
+                   : [iv] "a" (iv), [in] "a" (in)
+                   : "memory");
+      num_in += 1;
+      in += BLOCKSIZE;
+
+      /* Perform encryption of temporary buffer. */
+      km_execute (ctx->km_func | KM_ENCRYPT, ctx->keyschenc, blocks, blocks,
+                 nblocks * BLOCKSIZE);
+
+      /* Xor encrypt buffer with input blocks and store to output blocks. */
+      pos = 0;
+      in -= nblocks * BLOCKSIZE;
+
+#define CFB_XOR_BLOCKS(block_oper, xor_nbytes) \
+      block_oper (nblocks >= xor_nbytes / BLOCKSIZE) \
+       { \
+         unsigned int xor_nblocks = xor_nbytes / BLOCKSIZE; \
+         asm volatile ("xc 0(" #xor_nbytes ", %[blocks_x]), 0(%[in])\n\t" \
+                       "mvc 0(" #xor_nbytes ", %[out]), 0(%[blocks_x])\n\t" \
+                       : \
+                       : [blocks_x] "a" (&blocks[pos]), [out] "a" (out), \
+                         [in] "a" (in) \
+                       : "memory"); \
+         out += xor_nblocks * BLOCKSIZE; \
+         in += xor_nblocks * BLOCKSIZE; \
+         nblocks -= xor_nblocks; \
+         pos += xor_nblocks; \
+       }
+
+      CFB_XOR_BLOCKS(while, 256);
+      CFB_XOR_BLOCKS(if, 128);
+      CFB_XOR_BLOCKS(if, 64);
+      CFB_XOR_BLOCKS(if, 32);
+      CFB_XOR_BLOCKS(if, 16);
+
+#undef CFB_XOR_BLOCKS
+    }
+
+  if (max_blocks_used)
+    wipememory (&blocks, max_blocks_used * BLOCKSIZE);
+}
+
+static void aes_s390x_ofb_enc(void *context, unsigned char *iv,
+                             void *outbuf_arg, const void *inbuf_arg,
+                             size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  byte *out = outbuf_arg;
+  const byte *in = inbuf_arg;
+  unsigned int function;
+  u128_t params[3];
+
+  /* Prepare parameter block. */
+  memcpy (&params[0], iv, BLOCKSIZE);
+  memcpy (&params[1], ctx->keyschenc, 32);
+
+  function = ctx->kmo_func | KM_ENCRYPT;
+  kmo_execute (function, &params, out, in, nblocks * BLOCKSIZE);
+
+  /* Update IV with OCV. */
+  memcpy (iv, &params[0], BLOCKSIZE);
+
+  wipememory (&params, sizeof(params));
+}
+
+static void aes_s390x_ctr128_enc(void *context, unsigned char *ctr,
+                                void *outbuf_arg, const void *inbuf_arg,
+                                size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  byte *out = outbuf_arg;
+  const byte *in = inbuf_arg;
+  unsigned int function;
+  struct aes_s390x_gcm_params_s params;
+
+  memset (&params.hash_subkey, 0, sizeof(params.hash_subkey));
+  memcpy (&params.key, ctx->keyschenc, 32);
+
+  function = ctx->kma_func | KM_DECRYPT | KMA_HS | KMA_LAAD;
+
+  while (nblocks)
+    {
+      u64 to_overflow = (u64)0xFFFFFFFFU + 1 - buf_get_be32 (ctr + 12);
+      u64 ncurr = nblocks > to_overflow ? to_overflow : nblocks;
+
+      /* Prepare parameter block. */
+      memset (&params.reserved, 0, sizeof(params.reserved));
+      buf_put_be32 (&params.counter_value, buf_get_be32(ctr + 12) - 1);
+      memcpy (&params.initial_counter_value, ctr, 16);
+      params.initial_counter_value[3] = params.counter_value;
+      memset (&params.tag, 0, sizeof(params.tag));
+      params.total_aad_length = 0;
+      params.total_cipher_length = 0;
+
+      /* Update counter. */
+      cipher_block_add (ctr, ncurr, BLOCKSIZE);
+      if (ncurr == (u64)0xFFFFFFFFU + 1)
+       cipher_block_add (ctr, 1, BLOCKSIZE);
+
+      /* Perform CTR using KMA-GCM. */
+      kma_execute (function, &params, out, in, ncurr * BLOCKSIZE, NULL, 0);
+
+      out += ncurr * BLOCKSIZE;
+      in += ncurr * BLOCKSIZE;
+      nblocks -= ncurr;
+    }
+
+  wipememory (&params, sizeof(params));
+}
+
+static size_t aes_s390x_gcm_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
+                                 const void *inbuf_arg, size_t nblocks,
+                                 int encrypt)
+{
+  RIJNDAEL_context *ctx = (void *)&c->context.c;
+  byte *out = outbuf_arg;
+  const byte *in = inbuf_arg;
+  byte *ctr = c->u_ctr.ctr;
+  unsigned int function;
+  struct aes_s390x_gcm_params_s params;
+
+  function = ctx->kma_func | (encrypt ? KM_ENCRYPT : KM_DECRYPT)
+             | KMA_HS | KMA_LAAD;
+
+  /* Prepare parameter block. */
+  memset (&params.reserved, 0, sizeof(params.reserved));
+  buf_put_be32 (&params.counter_value, buf_get_be32(ctr + 12) - 1);
+  memcpy (&params.tag, c->u_mode.gcm.u_tag.tag, 16);
+  memcpy (&params.hash_subkey, c->u_mode.gcm.u_ghash_key.key, 16);
+  params.total_aad_length = 0;
+  params.total_cipher_length = 0;
+  memcpy (&params.initial_counter_value, ctr, 12);
+  params.initial_counter_value[3] = params.counter_value;
+  memcpy (&params.key, ctx->keyschenc, 32);
+
+  /* Update counter (CTR32). */
+  buf_put_be32(ctr + 12, buf_get_be32(ctr + 12) + nblocks);
+
+  /* Perform KMA-GCM. */
+  kma_execute (function, &params, out, in, nblocks * BLOCKSIZE, NULL, 0);
+
+  /* Update tag. */
+  memcpy (c->u_mode.gcm.u_tag.tag, &params.tag, 16);
+
+  wipememory (&params, sizeof(params));
+
+  return 0;
+}
+
+static void aes_s390x_xts_crypt(void *context, unsigned char *tweak,
+                               void *outbuf_arg, const void *inbuf_arg,
+                               size_t nblocks, int encrypt)
+{
+  RIJNDAEL_context *ctx = context;
+  byte *out = outbuf_arg;
+  const byte *in = inbuf_arg;
+  unsigned int function;
+  u128_t params[3];
+  u128_t *params_tweak;
+
+  if (ctx->rounds < 12)
+    {
+      memcpy (&params[0], ctx->keyschenc, 16);
+      params_tweak = &params[1];
+      memcpy (params_tweak, tweak, BLOCKSIZE);
+    }
+  else if (ctx->rounds == 12)
+    {
+      BUG(); /* KM-XTS-AES-192 not defined. */
+    }
+  else
+    {
+      memcpy (&params[0], ctx->keyschenc, 32);
+      params_tweak = &params[2];
+      memcpy (params_tweak, tweak, BLOCKSIZE);
+    }
+
+  function = ctx->km_func_xts | (encrypt ? KM_ENCRYPT : KM_DECRYPT);
+  km_execute (function, &params, out, in, nblocks * BLOCKSIZE);
+
+  /* Update tweak with XTSP. */
+  memcpy (tweak, params_tweak, BLOCKSIZE);
+
+  wipememory (&params, sizeof(params));
+}
+
+static NO_INLINE void
+aes_s390x_ocb_prepare_Ls (gcry_cipher_hd_t c, u64 blkn, const void *Ls[64],
+                         const void ***pl)
+{
+  unsigned int n = 64 - (blkn % 64);
+  int i;
+
+  /* Prepare L pointers. */
+  *pl = &Ls[(63 + n) % 64];
+  for (i = 0; i < 64; i += 8, n = (n + 8) % 64)
+    {
+      static const int lastL[8] = { 3, 4, 3, 5, 3, 4, 3, 0 };
+
+      Ls[(0 + n) % 64] = c->u_mode.ocb.L[0];
+      Ls[(1 + n) % 64] = c->u_mode.ocb.L[1];
+      Ls[(2 + n) % 64] = c->u_mode.ocb.L[0];
+      Ls[(3 + n) % 64] = c->u_mode.ocb.L[2];
+      Ls[(4 + n) % 64] = c->u_mode.ocb.L[0];
+      Ls[(5 + n) % 64] = c->u_mode.ocb.L[1];
+      Ls[(6 + n) % 64] = c->u_mode.ocb.L[0];
+      Ls[(7 + n) % 64] = c->u_mode.ocb.L[lastL[i / 8]];
+    }
+}
+
+static ALWAYS_INLINE const unsigned char *
+aes_s390x_ocb_get_l (gcry_cipher_hd_t c, u64 n)
+{
+  unsigned long ntz = _gcry_ctz (n);
+  if (ntz >= OCB_L_TABLE_SIZE)
+    {
+      return NULL; /* Not accessed. */
+    }
+  return c->u_mode.ocb.L[ntz];
+}
+
+static NO_INLINE void
+aes_s390x_ocb_checksum (unsigned char *checksum, const void *plainbuf_arg,
+                       size_t nblks)
+{
+  const char *plainbuf = plainbuf_arg;
+  u64 tmp0[2];
+  u64 tmp1[2] = { 0, 0 };
+  u64 tmp2[2] = { 0, 0 };
+  u64 tmp3[2] = { 0, 0 };
+
+  cipher_block_cpy (tmp0, checksum, BLOCKSIZE);
+
+  if (nblks >= 4)
+    {
+      while (nblks >= 4)
+       {
+         /* Checksum_i = Checksum_{i-1} xor P_i  */
+         cipher_block_xor_1 (tmp0, plainbuf + 0 * BLOCKSIZE, BLOCKSIZE);
+         cipher_block_xor_1 (tmp1, plainbuf + 1 * BLOCKSIZE, BLOCKSIZE);
+         cipher_block_xor_1 (tmp2, plainbuf + 2 * BLOCKSIZE, BLOCKSIZE);
+         cipher_block_xor_1 (tmp3, plainbuf + 3 * BLOCKSIZE, BLOCKSIZE);
+
+         plainbuf += 4 * BLOCKSIZE;
+         nblks -= 4;
+       }
+
+      cipher_block_xor_1 (tmp0, tmp1, BLOCKSIZE);
+      cipher_block_xor_1 (tmp2, tmp3, BLOCKSIZE);
+      cipher_block_xor_1 (tmp0, tmp2, BLOCKSIZE);
+
+      wipememory (tmp1, sizeof(tmp1));
+      wipememory (tmp2, sizeof(tmp2));
+      wipememory (tmp3, sizeof(tmp3));
+    }
+
+  while (nblks > 0)
+    {
+      /* Checksum_i = Checksum_{i-1} xor P_i  */
+      cipher_block_xor_1 (tmp0, plainbuf, BLOCKSIZE);
+
+      plainbuf += BLOCKSIZE;
+      nblks--;
+    }
+
+  cipher_block_cpy (checksum, tmp0, BLOCKSIZE);
+
+  wipememory (tmp0, sizeof(tmp0));
+}
+
+static NO_INLINE size_t
+aes_s390x_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
+                  const void *inbuf_arg, size_t nblocks_arg)
+{
+  RIJNDAEL_context *ctx = (void *)&c->context.c;
+  unsigned char *outbuf = outbuf_arg;
+  const unsigned char *inbuf = inbuf_arg;
+  size_t nblocks = nblocks_arg;
+  u128_t blocks[64];
+  u128_t offset;
+  size_t max_blocks_used = 0;
+  u64 blkn = c->u_mode.ocb.data_nblocks;
+  unsigned int function = ctx->km_func | KM_ENCRYPT;
+  const void *Ls[64];
+  const void **pl;
+
+  aes_s390x_ocb_prepare_Ls (c, blkn, Ls, &pl);
+
+  /* Checksumming could be done inline in OCB_INPUT macros, but register
+   * pressure becomes too heavy and performance would end up being worse.
+   * For decryption, checksumming is part of OCB_OUTPUT macros as
+   * output handling is less demanding and can handle the additional
+   * computation. */
+  aes_s390x_ocb_checksum (c->u_ctr.ctr, inbuf_arg, nblocks_arg);
+
+  cipher_block_cpy (&offset, &c->u_iv.iv, BLOCKSIZE);
+
+#define OCB_INPUT(n) \
+      cipher_block_xor_2dst (&blocks[n], &offset, Ls[n], BLOCKSIZE); \
+      cipher_block_xor (outbuf + (n) * BLOCKSIZE, inbuf + (n) * BLOCKSIZE, \
+                       &offset, BLOCKSIZE)
+
+#define OCB_INPUT_4(n) \
+      OCB_INPUT((n) + 0); OCB_INPUT((n) + 1); OCB_INPUT((n) + 2); \
+      OCB_INPUT((n) + 3)
+
+#define OCB_INPUT_16(n) \
+      OCB_INPUT_4((n) + 0); OCB_INPUT_4((n) + 4); OCB_INPUT_4((n) + 8); \
+      OCB_INPUT_4((n) + 12);
+
+#define OCB_OUTPUT(n) \
+      cipher_block_xor_1 (outbuf + (n) * BLOCKSIZE, &blocks[n], BLOCKSIZE)
+
+#define OCB_OUTPUT_4(n) \
+      OCB_OUTPUT((n) + 0); OCB_OUTPUT((n) + 1); OCB_OUTPUT((n) + 2); \
+      OCB_OUTPUT((n) + 3)
+
+#define OCB_OUTPUT_16(n) \
+      OCB_OUTPUT_4((n) + 0); OCB_OUTPUT_4((n) + 4); OCB_OUTPUT_4((n) + 8); \
+      OCB_OUTPUT_4((n) + 12);
+
+  while (nblocks >= 64)
+    {
+      blkn += 64;
+      *pl = aes_s390x_ocb_get_l(c, blkn - blkn % 64);
+
+      OCB_INPUT_16(0);
+      OCB_INPUT_16(16);
+      OCB_INPUT_16(32);
+      OCB_INPUT_16(48);
+
+      km_execute (function, ctx->keyschenc, outbuf, outbuf, 64 * BLOCKSIZE);
+
+      asm volatile ("xc   0(256, %[out]),   0(%[blocks])\n\t"
+                   "xc 256(256, %[out]), 256(%[blocks])\n\t"
+                   "xc 512(256, %[out]), 512(%[blocks])\n\t"
+                   "xc 768(256, %[out]), 768(%[blocks])\n\t"
+                   :
+                   : [out] "a" (outbuf), [blocks] "a" (blocks)
+                   : "memory");
+
+      max_blocks_used = 64;
+      inbuf += 64 * BLOCKSIZE;
+      outbuf += 64 * BLOCKSIZE;
+      nblocks -= 64;
+    }
+
+  if (nblocks)
+    {
+      unsigned int pos = 0;
+
+      max_blocks_used = max_blocks_used < nblocks ? nblocks : max_blocks_used;
+
+      blkn += nblocks;
+      *pl = aes_s390x_ocb_get_l(c, blkn - blkn % 64);
+
+      while (nblocks >= 16)
+       {
+         OCB_INPUT_16(pos + 0);
+         pos += 16;
+         nblocks -= 16;
+       }
+      while (nblocks >= 4)
+       {
+         OCB_INPUT_4(pos + 0);
+         pos += 4;
+         nblocks -= 4;
+       }
+      if (nblocks >= 2)
+       {
+         OCB_INPUT(pos + 0);
+         OCB_INPUT(pos + 1);
+         pos += 2;
+         nblocks -= 2;
+       }
+      if (nblocks >= 1)
+       {
+         OCB_INPUT(pos + 0);
+         pos += 1;
+         nblocks -= 1;
+       }
+
+      nblocks = pos;
+      pos = 0;
+      km_execute (function, ctx->keyschenc, outbuf, outbuf,
+                 nblocks * BLOCKSIZE);
+
+      while (nblocks >= 16)
+       {
+         OCB_OUTPUT_16(pos + 0);
+         pos += 16;
+         nblocks -= 16;
+       }
+      while (nblocks >= 4)
+       {
+         OCB_OUTPUT_4(pos + 0);
+         pos += 4;
+         nblocks -= 4;
+       }
+      if (nblocks >= 2)
+       {
+         OCB_OUTPUT(pos + 0);
+         OCB_OUTPUT(pos + 1);
+         pos += 2;
+         nblocks -= 2;
+       }
+      if (nblocks >= 1)
+       {
+         OCB_OUTPUT(pos + 0);
+         pos += 1;
+         nblocks -= 1;
+       }
+    }
+
+#undef OCB_INPUT
+#undef OCB_INPUT_4
+#undef OCB_INPUT_16
+#undef OCB_OUTPUT
+#undef OCB_OUTPUT_4
+#undef OCB_OUTPUT_16
+
+  c->u_mode.ocb.data_nblocks = blkn;
+  cipher_block_cpy (&c->u_iv.iv, &offset, BLOCKSIZE);
+
+  if (max_blocks_used)
+    wipememory (&blocks, max_blocks_used * BLOCKSIZE);
+
+  return 0;
+}
+
+static NO_INLINE size_t
+aes_s390x_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
+                  const void *inbuf_arg, size_t nblocks_arg)
+{
+  RIJNDAEL_context *ctx = (void *)&c->context.c;
+  unsigned char *outbuf = outbuf_arg;
+  const unsigned char *inbuf = inbuf_arg;
+  size_t nblocks = nblocks_arg;
+  u128_t blocks[64];
+  u128_t offset;
+  size_t max_blocks_used = 0;
+  u64 blkn = c->u_mode.ocb.data_nblocks;
+  unsigned int function = ctx->km_func | KM_DECRYPT;
+  const void *Ls[64];
+  const void **pl;
+
+  aes_s390x_ocb_prepare_Ls (c, blkn, Ls, &pl);
+
+  cipher_block_cpy (&offset, &c->u_iv.iv, BLOCKSIZE);
+
+#define OCB_INPUT(n) \
+      cipher_block_xor_2dst (&blocks[n], &offset, Ls[n], BLOCKSIZE); \
+      cipher_block_xor (outbuf + (n) * BLOCKSIZE, inbuf + (n) * BLOCKSIZE, \
+                       &offset, BLOCKSIZE)
+
+#define OCB_INPUT_4(n) \
+      OCB_INPUT((n) + 0); OCB_INPUT((n) + 1); OCB_INPUT((n) + 2); \
+      OCB_INPUT((n) + 3)
+
+#define OCB_INPUT_16(n) \
+      OCB_INPUT_4((n) + 0); OCB_INPUT_4((n) + 4); OCB_INPUT_4((n) + 8); \
+      OCB_INPUT_4((n) + 12);
+
+#define OCB_OUTPUT(n) \
+      cipher_block_xor_1 (outbuf + (n) * BLOCKSIZE, &blocks[n], BLOCKSIZE);
+
+#define OCB_OUTPUT_4(n) \
+      OCB_OUTPUT((n) + 0); OCB_OUTPUT((n) + 1); OCB_OUTPUT((n) + 2); \
+      OCB_OUTPUT((n) + 3)
+
+#define OCB_OUTPUT_16(n) \
+      OCB_OUTPUT_4((n) + 0); OCB_OUTPUT_4((n) + 4); OCB_OUTPUT_4((n) + 8); \
+      OCB_OUTPUT_4((n) + 12);
+
+  while (nblocks >= 64)
+    {
+      blkn += 64;
+      *pl = aes_s390x_ocb_get_l(c, blkn - blkn % 64);
+
+      OCB_INPUT_16(0);
+      OCB_INPUT_16(16);
+      OCB_INPUT_16(32);
+      OCB_INPUT_16(48);
+
+      km_execute (function, ctx->keyschenc, outbuf, outbuf, 64 * BLOCKSIZE);
+
+      asm volatile ("xc   0(256, %[out]),   0(%[blocks])\n\t"
+                   "xc 256(256, %[out]), 256(%[blocks])\n\t"
+                   "xc 512(256, %[out]), 512(%[blocks])\n\t"
+                   "xc 768(256, %[out]), 768(%[blocks])\n\t"
+                   :
+                   : [out] "a" (outbuf), [blocks] "a" (blocks)
+                   : "memory");
+
+      max_blocks_used = 64;
+      inbuf += 64 * BLOCKSIZE;
+      outbuf += 64 * BLOCKSIZE;
+      nblocks -= 64;
+    }
+
+  if (nblocks)
+    {
+      unsigned int pos = 0;
+
+      max_blocks_used = max_blocks_used < nblocks ? nblocks : max_blocks_used;
+
+      blkn += nblocks;
+      *pl = aes_s390x_ocb_get_l(c, blkn - blkn % 64);
+
+      while (nblocks >= 16)
+       {
+         OCB_INPUT_16(pos + 0);
+         pos += 16;
+         nblocks -= 16;
+       }
+      while (nblocks >= 4)
+       {
+         OCB_INPUT_4(pos + 0);
+         pos += 4;
+         nblocks -= 4;
+       }
+      if (nblocks >= 2)
+       {
+         OCB_INPUT(pos + 0);
+         OCB_INPUT(pos + 1);
+         pos += 2;
+         nblocks -= 2;
+       }
+      if (nblocks >= 1)
+       {
+         OCB_INPUT(pos + 0);
+         pos += 1;
+         nblocks -= 1;
+       }
+
+      nblocks = pos;
+      pos = 0;
+      km_execute (function, ctx->keyschenc, outbuf, outbuf,
+                 nblocks * BLOCKSIZE);
+
+      while (nblocks >= 16)
+       {
+         OCB_OUTPUT_16(pos + 0);
+         pos += 16;
+         nblocks -= 16;
+       }
+      while (nblocks >= 4)
+       {
+         OCB_OUTPUT_4(pos + 0);
+         pos += 4;
+         nblocks -= 4;
+       }
+      if (nblocks >= 2)
+       {
+         OCB_OUTPUT(pos + 0);
+         OCB_OUTPUT(pos + 1);
+         pos += 2;
+         nblocks -= 2;
+       }
+      if (nblocks >= 1)
+       {
+         OCB_OUTPUT(pos + 0);
+         pos += 1;
+         nblocks -= 1;
+       }
+    }
+
+#undef OCB_INPUT
+#undef OCB_INPUT_4
+#undef OCB_INPUT_16
+#undef OCB_OUTPUT
+#undef OCB_OUTPUT_4
+#undef OCB_OUTPUT_16
+
+  c->u_mode.ocb.data_nblocks = blkn;
+  cipher_block_cpy (&c->u_iv.iv, &offset, BLOCKSIZE);
+
+  if (max_blocks_used)
+    wipememory (&blocks, max_blocks_used * BLOCKSIZE);
+
+  aes_s390x_ocb_checksum (c->u_ctr.ctr, outbuf_arg, nblocks_arg);
+
+  return 0;
+}
+
+static size_t
+aes_s390x_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                    const void *inbuf_arg, size_t nblocks_arg, int encrypt)
+{
+  if (encrypt)
+    return aes_s390x_ocb_enc (c, outbuf_arg, inbuf_arg, nblocks_arg);
+  else
+    return aes_s390x_ocb_dec (c, outbuf_arg, inbuf_arg, nblocks_arg);
+}
+
+static size_t
+aes_s390x_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
+                   size_t nblocks_arg)
+{
+  RIJNDAEL_context *ctx = (void *)&c->context.c;
+  const unsigned char *abuf = abuf_arg;
+  u128_t blocks[64];
+  u128_t offset;
+  size_t max_blocks_used = 0;
+  u64 blkn = c->u_mode.ocb.aad_nblocks;
+  unsigned int function = ctx->km_func | KM_ENCRYPT;
+  const void *Ls[64];
+  const void **pl;
+
+  aes_s390x_ocb_prepare_Ls (c, blkn, Ls, &pl);
+
+  cipher_block_cpy (&offset, c->u_mode.ocb.aad_offset, BLOCKSIZE);
+
+#define OCB_INPUT(n) \
+      cipher_block_xor_2dst (&blocks[n], &offset, Ls[n], BLOCKSIZE); \
+      cipher_block_xor_1 (&blocks[n], abuf + (n) * BLOCKSIZE, BLOCKSIZE)
+
+#define OCB_INPUT_4(n) \
+      OCB_INPUT((n) + 0); OCB_INPUT((n) + 1); OCB_INPUT((n) + 2); \
+      OCB_INPUT((n) + 3)
+
+#define OCB_INPUT_16(n) \
+      OCB_INPUT_4((n) + 0); OCB_INPUT_4((n) + 4); OCB_INPUT_4((n) + 8); \
+      OCB_INPUT_4((n) + 12);
+
+  while (nblocks_arg >= 64)
+    {
+      blkn += 64;
+      *pl = aes_s390x_ocb_get_l(c, blkn - blkn % 64);
+
+      OCB_INPUT_16(0);
+      OCB_INPUT_16(16);
+      OCB_INPUT_16(32);
+      OCB_INPUT_16(48);
+
+      km_execute (function, ctx->keyschenc, blocks, blocks, 64 * BLOCKSIZE);
+
+      aes_s390x_ocb_checksum (c->u_mode.ocb.aad_sum, blocks, 64);
+
+      max_blocks_used = 64;
+      abuf += 64 * BLOCKSIZE;
+      nblocks_arg -= 64;
+    }
+
+  if (nblocks_arg > 0)
+    {
+      size_t nblocks = nblocks_arg;
+      unsigned int pos = 0;
+
+      max_blocks_used = max_blocks_used < nblocks ? nblocks : max_blocks_used;
+
+      blkn += nblocks;
+      *pl = aes_s390x_ocb_get_l(c, blkn - blkn % 64);
+
+      while (nblocks >= 16)
+       {
+         OCB_INPUT_16(pos + 0);
+         pos += 16;
+         nblocks -= 16;
+       }
+      while (nblocks >= 4)
+       {
+         OCB_INPUT_4(pos + 0);
+         pos += 4;
+         nblocks -= 4;
+       }
+      if (nblocks >= 2)
+       {
+         OCB_INPUT(pos + 0);
+         OCB_INPUT(pos + 1);
+         pos += 2;
+         nblocks -= 2;
+       }
+      if (nblocks >= 1)
+       {
+         OCB_INPUT(pos + 0);
+         pos += 1;
+         nblocks -= 1;
+       }
+
+      nblocks = pos;
+      nblocks_arg -= pos;
+      pos = 0;
+      km_execute (function, ctx->keyschenc, blocks, blocks,
+                 nblocks * BLOCKSIZE);
+
+      aes_s390x_ocb_checksum (c->u_mode.ocb.aad_sum, blocks, nblocks);
+    }
+
+#undef OCB_INPUT
+#undef OCB_INPUT_4
+#undef OCB_INPUT_16
+
+  c->u_mode.ocb.aad_nblocks = blkn;
+  cipher_block_cpy (c->u_mode.ocb.aad_offset, &offset, BLOCKSIZE);
+
+  if (max_blocks_used)
+    wipememory (&blocks, max_blocks_used * BLOCKSIZE);
+
+  return 0;
+}
+
+int _gcry_aes_s390x_setup_acceleration(RIJNDAEL_context *ctx,
+                                      unsigned int keylen,
+                                      unsigned int hwfeatures,
+                                      cipher_bulk_ops_t *bulk_ops)
+{
+  unsigned int func;
+  unsigned int func_xts;
+  u128_t func_mask;
+  u128_t func_xts_mask;
+
+  if (!(hwfeatures & HWF_S390X_MSA))
+    return 0;
+
+  switch (keylen)
+    {
+    default:
+    case 16:
+      func = KM_FUNCTION_AES_128;
+      func_xts = KM_FUNCTION_XTS_AES_128;
+      func_mask = km_function_to_mask(KM_FUNCTION_AES_128);
+      func_xts_mask = km_function_to_mask(KM_FUNCTION_XTS_AES_128);
+      break;
+    case 24:
+      func = KM_FUNCTION_AES_192;
+      func_xts = 0;
+      func_mask = km_function_to_mask(KM_FUNCTION_AES_192);
+      func_xts_mask = 0; /* XTS-AES192 not available. */
+      break;
+    case 32:
+      func = KM_FUNCTION_AES_256;
+      func_xts = KM_FUNCTION_XTS_AES_256;
+      func_mask = km_function_to_mask(KM_FUNCTION_AES_256);
+      func_xts_mask = km_function_to_mask(KM_FUNCTION_AES_256);
+      break;
+    }
+
+  /* Query KM for supported algorithms and check if acceleration for
+   * requested key-length is available. */
+  if (!(km_query () & func_mask))
+    return 0;
+
+  ctx->km_func = func;
+
+  /* Query KM for supported XTS algorithms. */
+  if (km_query () & func_xts_mask)
+    ctx->km_func_xts = func_xts;
+
+  /* Query KMC for supported algorithms. */
+  if (kmc_query () & func_mask)
+    ctx->kmc_func = func;
+
+  /* Query KMAC for supported algorithms. */
+  if (kmac_query () & func_mask)
+    ctx->kmac_func = func;
+
+  if (hwfeatures & HWF_S390X_MSA_4)
+    {
+      /* Query KMF for supported algorithms. */
+      if (kmf_query () & func_mask)
+       ctx->kmf_func = func;
+
+      /* Query KMO for supported algorithms. */
+      if (kmo_query () & func_mask)
+       ctx->kmo_func = func;
+    }
+
+  if (hwfeatures & HWF_S390X_MSA_8)
+    {
+      /* Query KMA for supported algorithms. */
+      if (kma_query () & func_mask)
+       ctx->kma_func = func;
+    }
+
+  /* Setup zSeries bulk encryption/decryption routines. */
+
+  if (ctx->km_func)
+    {
+      bulk_ops->ocb_crypt = aes_s390x_ocb_crypt;
+      bulk_ops->ocb_auth = aes_s390x_ocb_auth;
+
+      /* CFB128 decryption uses KM instruction, instead of KMF. */
+      bulk_ops->cfb_dec = aes_s390x_cfb128_dec;
+    }
+
+  if (ctx->km_func_xts)
+    {
+      bulk_ops->xts_crypt = aes_s390x_xts_crypt;
+    }
+
+  if (ctx->kmc_func)
+    {
+      if(ctx->kmac_func)
+       {
+         /* Either KMC or KMAC used depending on 'cbc_mac' parameter. */
+         bulk_ops->cbc_enc = aes_s390x_cbc_enc;
+       }
+
+      bulk_ops->cbc_dec = aes_s390x_cbc_dec;
+    }
+
+  if (ctx->kmf_func)
+    {
+      bulk_ops->cfb_enc = aes_s390x_cfb128_enc;
+    }
+
+  if (ctx->kmo_func)
+    {
+      bulk_ops->ofb_enc = aes_s390x_ofb_enc;
+    }
+
+  if (ctx->kma_func)
+    {
+      bulk_ops->ctr_enc = aes_s390x_ctr128_enc;
+
+      if (kimd_query () & km_function_to_mask (KMID_FUNCTION_GHASH))
+       {
+         /* KIMD based GHASH implementation is required with AES-GCM
+          * acceleration. */
+         bulk_ops->gcm_crypt = aes_s390x_gcm_crypt;
+       }
+    }
+
+  return 1;
+}
+
+void _gcry_aes_s390x_setkey(RIJNDAEL_context *ctx, const byte *key)
+{
+  unsigned int keylen = 16 + (ctx->rounds - 10) * 4;
+  memcpy (ctx->keyschenc, key, keylen);
+}
+
+void _gcry_aes_s390x_prepare_decryption(RIJNDAEL_context *ctx)
+{
+  /* Do nothing. */
+  (void)ctx;
+}
+
+#endif /* USE_S390X_CRYPTO */
index 3ae55e8..b98dca2 100644 (file)
     (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
 
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-# define ELF(...)
-#else
-# define ELF(...) __VA_ARGS__
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -54,6 +50,8 @@
 ELF(.type _gcry_aes_ssse3_enc_preload,@function)
 .globl _gcry_aes_ssse3_enc_preload
 _gcry_aes_ssse3_enc_preload:
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
        lea     .Laes_consts(%rip), %rax
        movdqa            (%rax), %xmm9  # 0F
        movdqa  .Lk_inv   (%rax), %xmm10 # inv
@@ -62,7 +60,9 @@ _gcry_aes_ssse3_enc_preload:
        movdqa  .Lk_sb1+16(%rax), %xmm12 # sb1t
        movdqa  .Lk_sb2   (%rax), %xmm15 # sb2u
        movdqa  .Lk_sb2+16(%rax), %xmm14 # sb2t
-       ret
+       EXIT_SYSV_FUNC
+       ret_spec_stop
+       CFI_ENDPROC();
 ELF(.size _gcry_aes_ssse3_enc_preload,.-_gcry_aes_ssse3_enc_preload)
 
 ##
@@ -71,6 +71,8 @@ ELF(.size _gcry_aes_ssse3_enc_preload,.-_gcry_aes_ssse3_enc_preload)
 ELF(.type _gcry_aes_ssse3_dec_preload,@function)
 .globl _gcry_aes_ssse3_dec_preload
 _gcry_aes_ssse3_dec_preload:
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
        lea     .Laes_consts(%rip), %rax
        movdqa            (%rax), %xmm9   # 0F
        movdqa  .Lk_inv   (%rax), %xmm10  # inv
@@ -80,7 +82,9 @@ _gcry_aes_ssse3_dec_preload:
        movdqa  .Lk_dsbd   (%rax), %xmm15 # sbdu
        movdqa  .Lk_dsbb   (%rax), %xmm14 # sbbu
        movdqa  .Lk_dsbe   (%rax), %xmm8  # sbeu
-       ret
+       EXIT_SYSV_FUNC
+       ret_spec_stop
+       CFI_ENDPROC();
 ELF(.size _gcry_aes_ssse3_dec_preload,.-_gcry_aes_ssse3_dec_preload)
 
 ##
@@ -98,11 +102,11 @@ ELF(.size _gcry_aes_ssse3_dec_preload,.-_gcry_aes_ssse3_dec_preload)
 ##  Inputs:
 ##     %xmm0 = input
 ##     %xmm9-%xmm15 as in .Laes_preheat
-##    (%rdx) = scheduled keys
-##     %rax  = nrounds - 1
+##    (%rdi) = scheduled keys
+##     %rsi  = nrounds
 ##
 ##  Output in %xmm0
-##  Clobbers  %xmm1-%xmm4, %r9, %r11, %rax, %rcx
+##  Clobbers  %xmm1-%xmm4, %r9, %r11, %rax, %rcx, %rdx
 ##  Preserves %xmm6 - %xmm7 so you get some local vectors
 ##
 ##
@@ -111,6 +115,10 @@ ELF(.type _gcry_aes_ssse3_encrypt_core,@function)
 .globl _gcry_aes_ssse3_encrypt_core
 _gcry_aes_ssse3_encrypt_core:
 _aes_encrypt_core:
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+       mov     %rdi,   %rdx
+       leaq    -1(%rsi), %rax
        lea     .Laes_consts(%rip), %rcx
        leaq    .Lk_mc_backward(%rcx), %rdi
        mov     $16,    %rsi
@@ -185,7 +193,9 @@ _aes_encrypt_core:
        pshufb  %xmm3,  %xmm0   # 0 = sb1t
        pxor    %xmm4,  %xmm0   # 0 = A
        pshufb  .Lk_sr(%rsi,%rcx), %xmm0
-       ret
+       EXIT_SYSV_FUNC
+       ret_spec_stop
+       CFI_ENDPROC();
 ELF(.size _aes_encrypt_core,.-_aes_encrypt_core)
 
 ##
@@ -198,8 +208,12 @@ ELF(.size _aes_encrypt_core,.-_aes_encrypt_core)
 ELF(.type _gcry_aes_ssse3_decrypt_core,@function)
 _gcry_aes_ssse3_decrypt_core:
 _aes_decrypt_core:
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+       mov     %rdi,   %rdx
        lea     .Laes_consts(%rip), %rcx
-       movl    %eax,   %esi
+       subl    $1,     %esi
+       movl    %esi,   %eax
        shll    $4,     %esi
        xorl    $48,    %esi
        andl    $48,    %esi
@@ -288,7 +302,9 @@ _aes_decrypt_core:
        pshufb  %xmm3,  %xmm0   # 0 = sb1t
        pxor    %xmm4,  %xmm0   # 0 = A
        pshufb  .Lk_sr(%rsi,%rcx), %xmm0
-       ret
+       EXIT_SYSV_FUNC
+       ret_spec_stop
+       CFI_ENDPROC();
 ELF(.size _aes_decrypt_core,.-_aes_decrypt_core)
 
 ########################################################
@@ -306,6 +322,9 @@ _aes_schedule_core:
        # rsi = size in bits
        # rdx = buffer
        # rcx = direction.  0=encrypt, 1=decrypt
+       # r8 = rotoffs
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_5
 
        # load the tables
        lea     .Laes_consts(%rip), %r10
@@ -420,7 +439,7 @@ _aes_schedule_core:
        pxor    %xmm6,  %xmm0           # -> b+c+d b+c b a
        pshufd  $0x0E,  %xmm0,  %xmm6
        pslldq  $8,     %xmm6           # clobber low side with zeros
-       ret
+       ret_spec_stop
 
 ##
 ##  .Laes_schedule_256
@@ -527,7 +546,7 @@ _aes_schedule_core:
        # add in smeared stuff
        pxor    %xmm7,  %xmm0
        movdqa  %xmm0,  %xmm7
-       ret
+       ret_spec_stop
 
 ##
 ##  .Laes_schedule_transform
@@ -548,7 +567,7 @@ _aes_schedule_core:
        movdqa  16(%r11), %xmm0 # hi
        pshufb  %xmm1,  %xmm0
        pxor    %xmm2,  %xmm0
-       ret
+       ret_spec_stop
 
 ##
 ##  .Laes_schedule_mangle
@@ -620,7 +639,7 @@ _aes_schedule_core:
        add     $-16,   %r8
        and     $48,    %r8
        movdqa  %xmm3,  (%rdx)
-       ret
+       ret_spec_stop
 
 ##
 ##  .Laes_schedule_mangle_last
@@ -659,8 +678,10 @@ _aes_schedule_core:
        pxor    %xmm6,  %xmm6
        pxor    %xmm7,  %xmm7
        pxor    %xmm8,  %xmm8
-       ret
-ELF(.size _aes_schedule_core,.-_aes_schedule_core)
+       EXIT_SYSV_FUNC
+       ret_spec_stop
+       CFI_ENDPROC();
+ELF(.size _gcry_aes_ssse3_schedule_core,.-_gcry_aes_ssse3_schedule_core)
 
 ########################################################
 ##                                                    ##
index da5339e..b072385 100644 (file)
 /* Prevent compiler from issuing SSE instructions between asm blocks. */
 #  pragma GCC target("no-sse")
 #endif
+#if __clang__
+#  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
+#endif
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR        NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE ASM_FUNC_ATTR ALWAYS_INLINE
+
+
+/* Copy of ocb_get_l needed here as GCC is unable to inline ocb_get_l
+   because of 'pragma target'. */
+static ASM_FUNC_ATTR_INLINE const unsigned char *
+aes_ocb_get_l (gcry_cipher_hd_t c, u64 n)
+{
+  unsigned long ntz;
+
+  /* Assumes that N != 0. */
+  asm ("rep;bsfl %k[low], %k[ntz]\n\t"
+        : [ntz] "=r" (ntz)
+        : [low] "r" ((unsigned long)n)
+        : "cc");
+
+  return c->u_mode.ocb.L[ntz];
+}
 
 
 /* Assembly functions in rijndael-ssse3-amd64-asm.S. Note that these
-   have custom calling convention and need to be called from assembly
-   blocks, not directly. */
+   have custom calling convention (additional XMM parameters). */
 extern void _gcry_aes_ssse3_enc_preload(void);
 extern void _gcry_aes_ssse3_dec_preload(void);
-extern void _gcry_aes_ssse3_schedule_core(void);
-extern void _gcry_aes_ssse3_encrypt_core(void);
-extern void _gcry_aes_ssse3_decrypt_core(void);
+extern void _gcry_aes_ssse3_schedule_core(const void *key, u64 keybits,
+                                         void *buffer, u64 decrypt,
+                                         u64 rotoffs);
+extern void _gcry_aes_ssse3_encrypt_core(const void *key, u64 nrounds);
+extern void _gcry_aes_ssse3_decrypt_core(const void *key, u64 nrounds);
 
 
 
@@ -110,8 +138,6 @@ extern void _gcry_aes_ssse3_decrypt_core(void);
                   : \
                   : "r" (ssse3_state) \
                   : "memory" )
-# define PUSH_STACK_PTR
-# define POP_STACK_PTR
 #else
 # define SSSE3_STATE_SIZE 1
 # define vpaes_ssse3_prepare() (void)ssse3_state
@@ -126,34 +152,18 @@ extern void _gcry_aes_ssse3_decrypt_core(void);
                   "pxor        %%xmm7,  %%xmm7 \n\t" \
                   "pxor        %%xmm8,  %%xmm8 \n\t" \
                   ::: "memory" )
-/* Old GCC versions use red-zone of AMD64 SYSV ABI and stack pointer is
- * not properly adjusted for assembly block. Therefore stack pointer
- * needs to be manually corrected. */
-# define PUSH_STACK_PTR "subq $128, %%rsp;\n\t"
-# define POP_STACK_PTR  "addq $128, %%rsp;\n\t"
 #endif
 
 #define vpaes_ssse3_prepare_enc() \
     vpaes_ssse3_prepare(); \
-    asm volatile (PUSH_STACK_PTR \
-                  "callq *%q[core] \n\t" \
-                  POP_STACK_PTR \
-                  : \
-                  : [core] "r" (_gcry_aes_ssse3_enc_preload) \
-                  : "rax", "cc", "memory" )
+    _gcry_aes_ssse3_enc_preload();
 
 #define vpaes_ssse3_prepare_dec() \
     vpaes_ssse3_prepare(); \
-    asm volatile (PUSH_STACK_PTR \
-                  "callq *%q[core] \n\t" \
-                  POP_STACK_PTR \
-                  : \
-                  : [core] "r" (_gcry_aes_ssse3_dec_preload) \
-                  : "rax", "cc", "memory" )
+    _gcry_aes_ssse3_dec_preload();
 
 
-
-void
+void ASM_FUNC_ATTR
 _gcry_aes_ssse3_do_setkey (RIJNDAEL_context *ctx, const byte *key)
 {
   unsigned int keybits = (ctx->rounds - 10) * 32 + 128;
@@ -161,23 +171,7 @@ _gcry_aes_ssse3_do_setkey (RIJNDAEL_context *ctx, const byte *key)
 
   vpaes_ssse3_prepare();
 
-  asm volatile ("leaq %q[key], %%rdi"                  "\n\t"
-                "movl %[bits], %%esi"                  "\n\t"
-                "leaq %[buf], %%rdx"                   "\n\t"
-                "movl %[dir], %%ecx"                   "\n\t"
-                "movl %[rotoffs], %%r8d"               "\n\t"
-                PUSH_STACK_PTR
-                "callq *%q[core]"                      "\n\t"
-                POP_STACK_PTR
-                :
-                : [core] "r" (&_gcry_aes_ssse3_schedule_core),
-                  [key] "m" (*key),
-                  [bits] "g" (keybits),
-                  [buf] "m" (ctx->keyschenc32[0][0]),
-                  [dir] "g" (0),
-                  [rotoffs] "g" (48)
-                : "r8", "r9", "r10", "r11", "rax", "rcx", "rdx", "rdi", "rsi",
-                  "cc", "memory");
+  _gcry_aes_ssse3_schedule_core(key, keybits, &ctx->keyschenc32[0][0], 0, 48);
 
   /* Save key for setting up decryption. */
   if (keybits > 192)
@@ -208,71 +202,49 @@ _gcry_aes_ssse3_do_setkey (RIJNDAEL_context *ctx, const byte *key)
 
 
 /* Make a decryption key from an encryption key. */
-void
-_gcry_aes_ssse3_prepare_decryption (RIJNDAEL_context *ctx)
+static ASM_FUNC_ATTR_INLINE void
+do_ssse3_prepare_decryption (RIJNDAEL_context *ctx,
+                             byte ssse3_state[SSSE3_STATE_SIZE])
 {
   unsigned int keybits = (ctx->rounds - 10) * 32 + 128;
-  byte ssse3_state[SSSE3_STATE_SIZE];
 
   vpaes_ssse3_prepare();
 
-  asm volatile ("leaq %q[key], %%rdi"                  "\n\t"
-                "movl %[bits], %%esi"                  "\n\t"
-                "leaq %[buf], %%rdx"                   "\n\t"
-                "movl %[dir], %%ecx"                   "\n\t"
-                "movl %[rotoffs], %%r8d"               "\n\t"
-                PUSH_STACK_PTR
-                "callq *%q[core]"                      "\n\t"
-                POP_STACK_PTR
-                :
-                : [core] "r" (_gcry_aes_ssse3_schedule_core),
-                  [key] "m" (ctx->keyschdec32[0][0]),
-                  [bits] "g" (keybits),
-                  [buf] "m" (ctx->keyschdec32[ctx->rounds][0]),
-                  [dir] "g" (1),
-                  [rotoffs] "g" ((keybits == 192) ? 0 : 32)
-                : "r8", "r9", "r10", "r11", "rax", "rcx", "rdx", "rdi", "rsi",
-                  "cc", "memory");
+  _gcry_aes_ssse3_schedule_core(&ctx->keyschdec32[0][0], keybits,
+                               &ctx->keyschdec32[ctx->rounds][0], 1,
+                               (keybits == 192) ? 0 : 32);
 
   vpaes_ssse3_cleanup();
 }
 
+void ASM_FUNC_ATTR
+_gcry_aes_ssse3_prepare_decryption (RIJNDAEL_context *ctx)
+{
+  byte ssse3_state[SSSE3_STATE_SIZE];
+
+  do_ssse3_prepare_decryption(ctx, ssse3_state);
+}
+
 
 /* Encrypt one block using the Intel SSSE3 instructions.  Block is input
 * and output through SSE register xmm0. */
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 do_vpaes_ssse3_enc (const RIJNDAEL_context *ctx, unsigned int nrounds)
 {
-  unsigned int middle_rounds = nrounds - 1;
-  const void *keysched = ctx->keyschenc32;
-
-  asm volatile (PUSH_STACK_PTR
-               "callq *%q[core]"                       "\n\t"
-               POP_STACK_PTR
-               : "+a" (middle_rounds), "+d" (keysched)
-               : [core] "r" (_gcry_aes_ssse3_encrypt_core)
-               : "rcx", "rsi", "rdi", "cc", "memory");
+  _gcry_aes_ssse3_encrypt_core(ctx->keyschenc32, nrounds);
 }
 
 
 /* Decrypt one block using the Intel SSSE3 instructions.  Block is input
 * and output through SSE register xmm0. */
-static inline void
+static ASM_FUNC_ATTR_INLINE void
 do_vpaes_ssse3_dec (const RIJNDAEL_context *ctx, unsigned int nrounds)
 {
-  unsigned int middle_rounds = nrounds - 1;
-  const void *keysched = ctx->keyschdec32;
-
-  asm volatile (PUSH_STACK_PTR
-               "callq *%q[core]"                       "\n\t"
-               POP_STACK_PTR
-               : "+a" (middle_rounds), "+d" (keysched)
-               : [core] "r" (_gcry_aes_ssse3_decrypt_core)
-               : "rcx", "rsi", "cc", "memory");
+  _gcry_aes_ssse3_decrypt_core(ctx->keyschdec32, nrounds);
 }
 
 
-unsigned int
+unsigned int ASM_FUNC_ATTR
 _gcry_aes_ssse3_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
                         const unsigned char *src)
 {
@@ -294,10 +266,10 @@ _gcry_aes_ssse3_encrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
 }
 
 
-void
-_gcry_aes_ssse3_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                        const unsigned char *inbuf, unsigned char *iv,
-                        size_t nblocks)
+void ASM_FUNC_ATTR
+_gcry_aes_ssse3_cfb_enc (RIJNDAEL_context *ctx, unsigned char *iv,
+                         unsigned char *outbuf, const unsigned char *inbuf,
+                         size_t nblocks)
 {
   unsigned int nrounds = ctx->rounds;
   byte ssse3_state[SSSE3_STATE_SIZE];
@@ -333,10 +305,10 @@ _gcry_aes_ssse3_cfb_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 
-void
-_gcry_aes_ssse3_cbc_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                        const unsigned char *inbuf, unsigned char *iv,
-                        size_t nblocks, int cbc_mac)
+void ASM_FUNC_ATTR
+_gcry_aes_ssse3_cbc_enc (RIJNDAEL_context *ctx, unsigned char *iv,
+                         unsigned char *outbuf, const unsigned char *inbuf,
+                         size_t nblocks, int cbc_mac)
 {
   unsigned int nrounds = ctx->rounds;
   byte ssse3_state[SSSE3_STATE_SIZE];
@@ -378,10 +350,10 @@ _gcry_aes_ssse3_cbc_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 
-void
-_gcry_aes_ssse3_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                        const unsigned char *inbuf, unsigned char *ctr,
-                        size_t nblocks)
+void ASM_FUNC_ATTR
+_gcry_aes_ssse3_ctr_enc (RIJNDAEL_context *ctx, unsigned char *ctr,
+                         unsigned char *outbuf, const unsigned char *inbuf,
+                         size_t nblocks)
 {
   static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
     { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
@@ -445,9 +417,9 @@ _gcry_aes_ssse3_ctr_enc (RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 
-unsigned int
+unsigned int ASM_FUNC_ATTR
 _gcry_aes_ssse3_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
-                        const unsigned char *src)
+                         const unsigned char *src)
 {
   unsigned int nrounds = ctx->rounds;
   byte ssse3_state[SSSE3_STATE_SIZE];
@@ -467,10 +439,10 @@ _gcry_aes_ssse3_decrypt (const RIJNDAEL_context *ctx, unsigned char *dst,
 }
 
 
-void
-_gcry_aes_ssse3_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                        const unsigned char *inbuf, unsigned char *iv,
-                        size_t nblocks)
+void ASM_FUNC_ATTR
+_gcry_aes_ssse3_cfb_dec (RIJNDAEL_context *ctx, unsigned char *iv,
+                         unsigned char *outbuf, const unsigned char *inbuf,
+                         size_t nblocks)
 {
   unsigned int nrounds = ctx->rounds;
   byte ssse3_state[SSSE3_STATE_SIZE];
@@ -507,14 +479,20 @@ _gcry_aes_ssse3_cfb_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 
-void
-_gcry_aes_ssse3_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
-                        const unsigned char *inbuf, unsigned char *iv,
-                        size_t nblocks)
+void ASM_FUNC_ATTR
+_gcry_aes_ssse3_cbc_dec (RIJNDAEL_context *ctx, unsigned char *iv,
+                         unsigned char *outbuf, const unsigned char *inbuf,
+                         size_t nblocks)
 {
   unsigned int nrounds = ctx->rounds;
   byte ssse3_state[SSSE3_STATE_SIZE];
 
+  if ( !ctx->decryption_prepared )
+    {
+      do_ssse3_prepare_decryption ( ctx, ssse3_state );
+      ctx->decryption_prepared = 1;
+    }
+
   vpaes_ssse3_prepare_dec ();
 
   asm volatile ("movdqu %[iv], %%xmm7\n\t"     /* use xmm7 as fast IV storage */
@@ -552,7 +530,7 @@ _gcry_aes_ssse3_cbc_dec (RIJNDAEL_context *ctx, unsigned char *outbuf,
 }
 
 
-static void
+static void ASM_FUNC_ATTR
 ssse3_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
                const void *inbuf_arg, size_t nblocks)
 {
@@ -577,7 +555,7 @@ ssse3_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
     {
       const unsigned char *l;
 
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* Checksum_i = Checksum_{i-1} xor P_i  */
@@ -615,7 +593,7 @@ ssse3_ocb_enc (gcry_cipher_hd_t c, void *outbuf_arg,
   vpaes_ssse3_cleanup ();
 }
 
-static void
+static void ASM_FUNC_ATTR
 ssse3_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
                const void *inbuf_arg, size_t nblocks)
 {
@@ -626,6 +604,12 @@ ssse3_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
   unsigned int nrounds = ctx->rounds;
   byte ssse3_state[SSSE3_STATE_SIZE];
 
+  if ( !ctx->decryption_prepared )
+    {
+      do_ssse3_prepare_decryption ( ctx, ssse3_state );
+      ctx->decryption_prepared = 1;
+    }
+
   vpaes_ssse3_prepare_dec ();
 
   /* Preload Offset and Checksum */
@@ -640,7 +624,7 @@ ssse3_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
     {
       const unsigned char *l;
 
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
@@ -679,7 +663,7 @@ ssse3_ocb_dec (gcry_cipher_hd_t c, void *outbuf_arg,
 }
 
 
-void
+size_t ASM_FUNC_ATTR
 _gcry_aes_ssse3_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
                           const void *inbuf_arg, size_t nblocks, int encrypt)
 {
@@ -687,10 +671,12 @@ _gcry_aes_ssse3_ocb_crypt(gcry_cipher_hd_t c, void *outbuf_arg,
     ssse3_ocb_enc(c, outbuf_arg, inbuf_arg, nblocks);
   else
     ssse3_ocb_dec(c, outbuf_arg, inbuf_arg, nblocks);
+
+  return 0;
 }
 
 
-void
+size_t ASM_FUNC_ATTR
 _gcry_aes_ssse3_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
                           size_t nblocks)
 {
@@ -714,7 +700,7 @@ _gcry_aes_ssse3_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
     {
       const unsigned char *l;
 
-      l = ocb_get_l(c, ++n);
+      l = aes_ocb_get_l(c, ++n);
 
       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
@@ -746,6 +732,12 @@ _gcry_aes_ssse3_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
                 : "memory" );
 
   vpaes_ssse3_cleanup ();
+
+  return 0;
 }
 
+#if __clang__
+#  pragma clang attribute pop
+#endif
+
 #endif /* USE_SSSE3 */
index 8359470..b54d959 100644 (file)
 /* To keep the actual implementation at a readable size we use this
    include file to define the tables.  */
 
-static const u32 encT[256] =
+static struct
+{
+  volatile u32 counter_head;
+  u32 cacheline_align[64 / 4 - 1];
+  u32 T[256];
+  volatile u32 counter_tail;
+} enc_tables ATTR_ALIGNED_64 =
   {
-    0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
-    0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
-    0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
-    0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
-    0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
-    0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
-    0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,
-    0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b,
-    0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
-    0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
-    0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9,
-    0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
-    0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d,
-    0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f,
-    0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
-    0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea,
-    0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,
-    0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
-    0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d,
-    0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
-    0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
-    0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,
-    0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972,
-    0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
-    0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
-    0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511,
-    0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
-    0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b,
-    0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05,
-    0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
-    0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142,
-    0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,
-    0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
-    0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e,
-    0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
-    0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
-    0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,
-    0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b,
-    0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
-    0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
-    0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14,
-    0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
-    0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4,
-    0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2,
-    0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
-    0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949,
-    0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,
-    0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
-    0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c,
-    0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
-    0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
-    0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,
-    0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc,
-    0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
-    0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
-    0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27,
-    0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
-    0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433,
-    0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9,
-    0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
-    0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
-    0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
-    0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
-    0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c
+    0,
+    { 0, },
+    {
+      0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
+      0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
+      0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
+      0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
+      0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+      0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
+      0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,
+      0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b,
+      0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
+      0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+      0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9,
+      0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
+      0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d,
+      0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f,
+      0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+      0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea,
+      0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,
+      0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
+      0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d,
+      0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+      0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
+      0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,
+      0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972,
+      0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
+      0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+      0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511,
+      0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
+      0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b,
+      0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05,
+      0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+      0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142,
+      0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,
+      0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
+      0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e,
+      0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+      0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
+      0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,
+      0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b,
+      0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
+      0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+      0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14,
+      0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
+      0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4,
+      0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2,
+      0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+      0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949,
+      0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,
+      0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
+      0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c,
+      0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+      0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
+      0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,
+      0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc,
+      0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
+      0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+      0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27,
+      0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
+      0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433,
+      0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9,
+      0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+      0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
+      0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
+      0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
+      0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c
+    },
+    0
   };
 
-static const struct
+#define encT enc_tables.T
+
+static struct
 {
+  volatile u32 counter_head;
+  u32 cacheline_align[64 / 4 - 1];
   u32 T[256];
   byte inv_sbox[256];
-} dec_tables =
+  volatile u32 counter_tail;
+} dec_tables ATTR_ALIGNED_64 =
   {
+    0,
+    { 0, },
     {
       0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a,
       0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b,
@@ -194,7 +212,8 @@ static const struct
       0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
       0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
       0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
-    }
+    },
+    0
   };
 
 #define decT dec_tables.T
diff --git a/cipher/rijndael-vaes-avx2-amd64.S b/cipher/rijndael-vaes-avx2-amd64.S
new file mode 100644 (file)
index 0000000..f94b58d
--- /dev/null
@@ -0,0 +1,3021 @@
+/* VAES/AVX2 AMD64 accelerated AES for Libgcrypt
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#if defined(__x86_64__)
+#include <config.h>
+#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
+    defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT) && \
+    defined(HAVE_GCC_INLINE_ASM_VAES_VPCLMUL)
+
+#include "asm-common-amd64.h"
+
+.text
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+#define no(...) /*_*/
+#define yes(...) __VA_ARGS__
+
+#define AES_OP8(op, key, b0, b1, b2, b3, b4, b5, b6, b7) \
+       op key, b0, b0; \
+       op key, b1, b1; \
+       op key, b2, b2; \
+       op key, b3, b3; \
+       op key, b4, b4; \
+       op key, b5, b5; \
+       op key, b6, b6; \
+       op key, b7, b7;
+
+#define VAESENC8(key, b0, b1, b2, b3, b4, b5, b6, b7) \
+       AES_OP8(vaesenc, key, b0, b1, b2, b3, b4, b5, b6, b7)
+
+#define VAESDEC8(key, b0, b1, b2, b3, b4, b5, b6, b7) \
+       AES_OP8(vaesdec, key, b0, b1, b2, b3, b4, b5, b6, b7)
+
+#define XOR8(key, b0, b1, b2, b3, b4, b5, b6, b7) \
+       AES_OP8(vpxor, key, b0, b1, b2, b3, b4, b5, b6, b7)
+
+#define AES_OP4(op, key, b0, b1, b2, b3) \
+       op key, b0, b0; \
+       op key, b1, b1; \
+       op key, b2, b2; \
+       op key, b3, b3;
+
+#define VAESENC4(key, b0, b1, b2, b3) \
+       AES_OP4(vaesenc, key, b0, b1, b2, b3)
+
+#define VAESDEC4(key, b0, b1, b2, b3) \
+       AES_OP4(vaesdec, key, b0, b1, b2, b3)
+
+#define XOR4(key, b0, b1, b2, b3) \
+       AES_OP4(vpxor, key, b0, b1, b2, b3)
+
+#define AES_OP2(op, key, b0, b1) \
+       op key, b0, b0; \
+       op key, b1, b1;
+
+#define VAESENC2(key, b0, b1) \
+       AES_OP2(vaesenc, key, b0, b1)
+
+#define VAESDEC2(key, b0, b1) \
+       AES_OP2(vaesdec, key, b0, b1)
+
+#define XOR2(key, b0, b1) \
+       AES_OP2(vpxor, key, b0, b1)
+
+/**********************************************************************
+  CBC-mode decryption
+ **********************************************************************/
+ELF(.type _gcry_vaes_avx2_cbc_dec_amd64,@function)
+.globl _gcry_vaes_avx2_cbc_dec_amd64
+_gcry_vaes_avx2_cbc_dec_amd64:
+       /* input:
+        *      %rdi: round keys
+        *      %rsi: iv
+        *      %rdx: dst
+        *      %rcx: src
+        *      %r8:  nblocks
+        *      %r9:  nrounds
+        */
+       CFI_STARTPROC();
+
+       /* Load IV. */
+       vmovdqu (%rsi), %xmm15;
+
+       /* Process 16 blocks per loop. */
+.align 8
+.Lcbc_dec_blk16:
+       cmpq $16, %r8;
+       jb .Lcbc_dec_blk8;
+
+       leaq -16(%r8), %r8;
+
+       /* Load input and xor first key. Update IV. */
+       vbroadcasti128 (0 * 16)(%rdi), %ymm8;
+       vmovdqu (0 * 16)(%rcx), %ymm0;
+       vmovdqu (2 * 16)(%rcx), %ymm1;
+       vmovdqu (4 * 16)(%rcx), %ymm2;
+       vmovdqu (6 * 16)(%rcx), %ymm3;
+       vmovdqu (8 * 16)(%rcx), %ymm4;
+       vmovdqu (10 * 16)(%rcx), %ymm5;
+       vmovdqu (12 * 16)(%rcx), %ymm6;
+       vmovdqu (14 * 16)(%rcx), %ymm7;
+       vpxor %ymm8, %ymm0, %ymm0;
+       vpxor %ymm8, %ymm1, %ymm1;
+       vpxor %ymm8, %ymm2, %ymm2;
+       vpxor %ymm8, %ymm3, %ymm3;
+       vpxor %ymm8, %ymm4, %ymm4;
+       vpxor %ymm8, %ymm5, %ymm5;
+       vpxor %ymm8, %ymm6, %ymm6;
+       vpxor %ymm8, %ymm7, %ymm7;
+       vbroadcasti128 (1 * 16)(%rdi), %ymm8;
+       vinserti128 $1, (0 * 16)(%rcx), %ymm15, %ymm9;
+       vmovdqu (1 * 16)(%rcx), %ymm10;
+       vmovdqu (3 * 16)(%rcx), %ymm11;
+       vmovdqu (5 * 16)(%rcx), %ymm12;
+       vmovdqu (7 * 16)(%rcx), %ymm13;
+       vmovdqu (9 * 16)(%rcx), %ymm14;
+       vmovdqu (15 * 16)(%rcx), %xmm15;
+       leaq (16 * 16)(%rcx), %rcx;
+
+       /* AES rounds */
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm8;
+       cmpl $12, %r9d;
+       jb .Lcbc_dec_blk16_last;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm8;
+       jz .Lcbc_dec_blk16_last;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm8;
+       VAESDEC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm8;
+
+       /* Last round and output handling. */
+  .Lcbc_dec_blk16_last:
+       vpxor %ymm8, %ymm9, %ymm9;
+       vpxor %ymm8, %ymm10, %ymm10;
+       vpxor %ymm8, %ymm11, %ymm11;
+       vpxor %ymm8, %ymm12, %ymm12;
+       vpxor %ymm8, %ymm13, %ymm13;
+       vpxor %ymm8, %ymm14, %ymm14;
+       vaesdeclast %ymm9, %ymm0, %ymm0;
+       vaesdeclast %ymm10, %ymm1, %ymm1;
+       vpxor (-5 * 16)(%rcx), %ymm8, %ymm9;
+       vpxor (-3 * 16)(%rcx), %ymm8, %ymm10;
+       vaesdeclast %ymm11, %ymm2, %ymm2;
+       vaesdeclast %ymm12, %ymm3, %ymm3;
+       vaesdeclast %ymm13, %ymm4, %ymm4;
+       vaesdeclast %ymm14, %ymm5, %ymm5;
+       vaesdeclast %ymm9, %ymm6, %ymm6;
+       vaesdeclast %ymm10, %ymm7, %ymm7;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       vmovdqu %ymm2, (4 * 16)(%rdx);
+       vmovdqu %ymm3, (6 * 16)(%rdx);
+       vmovdqu %ymm4, (8 * 16)(%rdx);
+       vmovdqu %ymm5, (10 * 16)(%rdx);
+       vmovdqu %ymm6, (12 * 16)(%rdx);
+       vmovdqu %ymm7, (14 * 16)(%rdx);
+       leaq (16 * 16)(%rdx), %rdx;
+
+       jmp .Lcbc_dec_blk16;
+
+       /* Handle trailing eight blocks. */
+.align 8
+.Lcbc_dec_blk8:
+       cmpq $8, %r8;
+       jb .Lcbc_dec_blk4;
+
+       leaq -8(%r8), %r8;
+
+       /* Load input and xor first key. Update IV. */
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+       vmovdqu (0 * 16)(%rcx), %ymm0;
+       vmovdqu (2 * 16)(%rcx), %ymm1;
+       vmovdqu (4 * 16)(%rcx), %ymm2;
+       vmovdqu (6 * 16)(%rcx), %ymm3;
+       vpxor %ymm4, %ymm0, %ymm0;
+       vpxor %ymm4, %ymm1, %ymm1;
+       vpxor %ymm4, %ymm2, %ymm2;
+       vpxor %ymm4, %ymm3, %ymm3;
+       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+       vinserti128 $1, (0 * 16)(%rcx), %ymm15, %ymm10;
+       vmovdqu (1 * 16)(%rcx), %ymm11;
+       vmovdqu (3 * 16)(%rcx), %ymm12;
+       vmovdqu (5 * 16)(%rcx), %ymm13;
+       vmovdqu (7 * 16)(%rcx), %xmm15;
+       leaq (8 * 16)(%rcx), %rcx;
+
+       /* AES rounds */
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+       cmpl $12, %r9d;
+       jb .Lcbc_dec_blk8_last;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+       jz .Lcbc_dec_blk8_last;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+       /* Last round and output handling. */
+  .Lcbc_dec_blk8_last:
+       vpxor %ymm4, %ymm10, %ymm10;
+       vpxor %ymm4, %ymm11, %ymm11;
+       vpxor %ymm4, %ymm12, %ymm12;
+       vpxor %ymm4, %ymm13, %ymm13;
+       vaesdeclast %ymm10, %ymm0, %ymm0;
+       vaesdeclast %ymm11, %ymm1, %ymm1;
+       vaesdeclast %ymm12, %ymm2, %ymm2;
+       vaesdeclast %ymm13, %ymm3, %ymm3;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       vmovdqu %ymm2, (4 * 16)(%rdx);
+       vmovdqu %ymm3, (6 * 16)(%rdx);
+       leaq (8 * 16)(%rdx), %rdx;
+
+       /* Handle trailing four blocks. */
+.align 8
+.Lcbc_dec_blk4:
+       cmpq $4, %r8;
+       jb .Lcbc_dec_blk1;
+
+       leaq -4(%r8), %r8;
+
+       /* Load input and xor first key. Update IV. */
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+       vmovdqu (0 * 16)(%rcx), %ymm0;
+       vmovdqu (2 * 16)(%rcx), %ymm1;
+       vpxor %ymm4, %ymm0, %ymm0;
+       vpxor %ymm4, %ymm1, %ymm1;
+       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+       vinserti128 $1, (0 * 16)(%rcx), %ymm15, %ymm10;
+       vmovdqu (1 * 16)(%rcx), %ymm11;
+       vmovdqu (3 * 16)(%rcx), %xmm15;
+       leaq (4 * 16)(%rcx), %rcx;
+
+       /* AES rounds */
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+       cmpl $12, %r9d;
+       jb .Lcbc_dec_blk4_last;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+       jz .Lcbc_dec_blk4_last;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+       VAESDEC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+       /* Last round and output handling. */
+  .Lcbc_dec_blk4_last:
+       vpxor %ymm4, %ymm10, %ymm10;
+       vpxor %ymm4, %ymm11, %ymm11;
+       vaesdeclast %ymm10, %ymm0, %ymm0;
+       vaesdeclast %ymm11, %ymm1, %ymm1;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       leaq (4 * 16)(%rdx), %rdx;
+
+       /* Process trailing one to three blocks, one per loop. */
+.align 8
+.Lcbc_dec_blk1:
+       cmpq $1, %r8;
+       jb .Ldone_cbc_dec;
+
+       leaq -1(%r8), %r8;
+
+       /* Load input. */
+       vmovdqu (%rcx), %xmm2;
+       leaq 16(%rcx), %rcx;
+
+       /* Xor first key. */
+       vpxor (0 * 16)(%rdi), %xmm2, %xmm0;
+
+       /* AES rounds. */
+       vaesdec (1 * 16)(%rdi), %xmm0, %xmm0;
+       vaesdec (2 * 16)(%rdi), %xmm0, %xmm0;
+       vaesdec (3 * 16)(%rdi), %xmm0, %xmm0;
+       vaesdec (4 * 16)(%rdi), %xmm0, %xmm0;
+       vaesdec (5 * 16)(%rdi), %xmm0, %xmm0;
+       vaesdec (6 * 16)(%rdi), %xmm0, %xmm0;
+       vaesdec (7 * 16)(%rdi), %xmm0, %xmm0;
+       vaesdec (8 * 16)(%rdi), %xmm0, %xmm0;
+       vaesdec (9 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (10 * 16)(%rdi), %xmm1;
+       cmpl $12, %r9d;
+       jb .Lcbc_dec_blk1_last;
+       vaesdec %xmm1, %xmm0, %xmm0;
+       vaesdec (11 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (12 * 16)(%rdi), %xmm1;
+       jz .Lcbc_dec_blk1_last;
+       vaesdec %xmm1, %xmm0, %xmm0;
+       vaesdec (13 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (14 * 16)(%rdi), %xmm1;
+
+       /* Last round and output handling. */
+  .Lcbc_dec_blk1_last:
+       vpxor %xmm1, %xmm15, %xmm15;
+       vaesdeclast %xmm15, %xmm0, %xmm0;
+       vmovdqa %xmm2, %xmm15;
+       vmovdqu %xmm0, (%rdx);
+       leaq 16(%rdx), %rdx;
+
+       jmp .Lcbc_dec_blk1;
+
+.align 8
+.Ldone_cbc_dec:
+       /* Store IV. */
+       vmovdqu %xmm15, (%rsi);
+
+       vzeroall;
+       ret_spec_stop
+       CFI_ENDPROC();
+ELF(.size _gcry_vaes_avx2_cbc_dec_amd64,.-_gcry_vaes_avx2_cbc_dec_amd64)
+
+/**********************************************************************
+  CFB-mode decryption
+ **********************************************************************/
+ELF(.type _gcry_vaes_avx2_cfb_dec_amd64,@function)
+.globl _gcry_vaes_avx2_cfb_dec_amd64
+_gcry_vaes_avx2_cfb_dec_amd64:
+       /* input:
+        *      %rdi: round keys
+        *      %rsi: iv
+        *      %rdx: dst
+        *      %rcx: src
+        *      %r8:  nblocks
+        *      %r9:  nrounds
+        */
+       CFI_STARTPROC();
+
+       /* Load IV. */
+       vmovdqu (%rsi), %xmm15;
+
+       /* Process 16 blocks per loop. */
+.align 8
+.Lcfb_dec_blk16:
+       cmpq $16, %r8;
+       jb .Lcfb_dec_blk8;
+
+       leaq -16(%r8), %r8;
+
+       /* Load input and xor first key. Update IV. */
+       vbroadcasti128 (0 * 16)(%rdi), %ymm8;
+       vinserti128 $1, (0 * 16)(%rcx), %ymm15, %ymm0;
+       vmovdqu (1 * 16)(%rcx), %ymm1;
+       vmovdqu (3 * 16)(%rcx), %ymm2;
+       vmovdqu (5 * 16)(%rcx), %ymm3;
+       vmovdqu (7 * 16)(%rcx), %ymm4;
+       vmovdqu (9 * 16)(%rcx), %ymm5;
+       vmovdqu (11 * 16)(%rcx), %ymm6;
+       vmovdqu (13 * 16)(%rcx), %ymm7;
+       vmovdqu (15 * 16)(%rcx), %xmm15;
+       vpxor %ymm8, %ymm0, %ymm0;
+       vpxor %ymm8, %ymm1, %ymm1;
+       vpxor %ymm8, %ymm2, %ymm2;
+       vpxor %ymm8, %ymm3, %ymm3;
+       vpxor %ymm8, %ymm4, %ymm4;
+       vpxor %ymm8, %ymm5, %ymm5;
+       vpxor %ymm8, %ymm6, %ymm6;
+       vpxor %ymm8, %ymm7, %ymm7;
+       vbroadcasti128 (1 * 16)(%rdi), %ymm8;
+       vmovdqu (0 * 16)(%rcx), %ymm9;
+       vmovdqu (2 * 16)(%rcx), %ymm10;
+       vmovdqu (4 * 16)(%rcx), %ymm11;
+       vmovdqu (6 * 16)(%rcx), %ymm12;
+       vmovdqu (8 * 16)(%rcx), %ymm13;
+       vmovdqu (10 * 16)(%rcx), %ymm14;
+
+       leaq (16 * 16)(%rcx), %rcx;
+
+       /* AES rounds */
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm8;
+       cmpl $12, %r9d;
+       jb .Lcfb_dec_blk16_last;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm8;
+       jz .Lcfb_dec_blk16_last;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm8;
+
+       /* Last round and output handling. */
+  .Lcfb_dec_blk16_last:
+       vpxor %ymm8, %ymm9, %ymm9;
+       vpxor %ymm8, %ymm10, %ymm10;
+       vpxor %ymm8, %ymm11, %ymm11;
+       vpxor %ymm8, %ymm12, %ymm12;
+       vpxor %ymm8, %ymm13, %ymm13;
+       vpxor %ymm8, %ymm14, %ymm14;
+       vaesenclast %ymm9, %ymm0, %ymm0;
+       vaesenclast %ymm10, %ymm1, %ymm1;
+       vpxor (-4 * 16)(%rcx), %ymm8, %ymm9;
+       vpxor (-2 * 16)(%rcx), %ymm8, %ymm10;
+       vaesenclast %ymm11, %ymm2, %ymm2;
+       vaesenclast %ymm12, %ymm3, %ymm3;
+       vaesenclast %ymm13, %ymm4, %ymm4;
+       vaesenclast %ymm14, %ymm5, %ymm5;
+       vaesenclast %ymm9, %ymm6, %ymm6;
+       vaesenclast %ymm10, %ymm7, %ymm7;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       vmovdqu %ymm2, (4 * 16)(%rdx);
+       vmovdqu %ymm3, (6 * 16)(%rdx);
+       vmovdqu %ymm4, (8 * 16)(%rdx);
+       vmovdqu %ymm5, (10 * 16)(%rdx);
+       vmovdqu %ymm6, (12 * 16)(%rdx);
+       vmovdqu %ymm7, (14 * 16)(%rdx);
+       leaq (16 * 16)(%rdx), %rdx;
+
+       jmp .Lcfb_dec_blk16;
+
+       /* Handle trailing eight blocks. */
+.align 8
+.Lcfb_dec_blk8:
+       cmpq $8, %r8;
+       jb .Lcfb_dec_blk4;
+
+       leaq -8(%r8), %r8;
+
+       /* Load input and xor first key. Update IV. */
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+       vinserti128 $1, (0 * 16)(%rcx), %ymm15, %ymm0;
+       vmovdqu (1 * 16)(%rcx), %ymm1;
+       vmovdqu (3 * 16)(%rcx), %ymm2;
+       vmovdqu (5 * 16)(%rcx), %ymm3;
+       vmovdqu (7 * 16)(%rcx), %xmm15;
+       vpxor %ymm4, %ymm0, %ymm0;
+       vpxor %ymm4, %ymm1, %ymm1;
+       vpxor %ymm4, %ymm2, %ymm2;
+       vpxor %ymm4, %ymm3, %ymm3;
+       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+       vmovdqu (0 * 16)(%rcx), %ymm10;
+       vmovdqu (2 * 16)(%rcx), %ymm11;
+       vmovdqu (4 * 16)(%rcx), %ymm12;
+       vmovdqu (6 * 16)(%rcx), %ymm13;
+
+       leaq (8 * 16)(%rcx), %rcx;
+
+       /* AES rounds */
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+       cmpl $12, %r9d;
+       jb .Lcfb_dec_blk8_last;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+       jz .Lcfb_dec_blk8_last;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+       /* Last round and output handling. */
+  .Lcfb_dec_blk8_last:
+       vpxor %ymm4, %ymm10, %ymm10;
+       vpxor %ymm4, %ymm11, %ymm11;
+       vpxor %ymm4, %ymm12, %ymm12;
+       vpxor %ymm4, %ymm13, %ymm13;
+       vaesenclast %ymm10, %ymm0, %ymm0;
+       vaesenclast %ymm11, %ymm1, %ymm1;
+       vaesenclast %ymm12, %ymm2, %ymm2;
+       vaesenclast %ymm13, %ymm3, %ymm3;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       vmovdqu %ymm2, (4 * 16)(%rdx);
+       vmovdqu %ymm3, (6 * 16)(%rdx);
+       leaq (8 * 16)(%rdx), %rdx;
+
+       /* Handle trailing four blocks. */
+.align 8
+.Lcfb_dec_blk4:
+       cmpq $4, %r8;
+       jb .Lcfb_dec_blk1;
+
+       leaq -4(%r8), %r8;
+
+       /* Load input and xor first key. Update IV. */
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+       vinserti128 $1, (0 * 16)(%rcx), %ymm15, %ymm0;
+       vmovdqu (1 * 16)(%rcx), %ymm1;
+       vmovdqu (3 * 16)(%rcx), %xmm15;
+       vpxor %ymm4, %ymm0, %ymm0;
+       vpxor %ymm4, %ymm1, %ymm1;
+       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+       vmovdqu (0 * 16)(%rcx), %ymm10;
+       vmovdqu (2 * 16)(%rcx), %ymm11;
+
+       leaq (4 * 16)(%rcx), %rcx;
+
+       /* AES rounds */
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+       cmpl $12, %r9d;
+       jb .Lcfb_dec_blk4_last;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+       jz .Lcfb_dec_blk4_last;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+       /* Last round and output handling. */
+  .Lcfb_dec_blk4_last:
+       vpxor %ymm4, %ymm10, %ymm10;
+       vpxor %ymm4, %ymm11, %ymm11;
+       vaesenclast %ymm10, %ymm0, %ymm0;
+       vaesenclast %ymm11, %ymm1, %ymm1;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       leaq (4 * 16)(%rdx), %rdx;
+
+       /* Process trailing one to three blocks, one per loop. */
+.align 8
+.Lcfb_dec_blk1:
+       cmpq $1, %r8;
+       jb .Ldone_cfb_dec;
+
+       leaq -1(%r8), %r8;
+
+       /* Xor first key. */
+       vpxor (0 * 16)(%rdi), %xmm15, %xmm0;
+
+       /* Load input as next IV. */
+       vmovdqu (%rcx), %xmm15;
+       leaq 16(%rcx), %rcx;
+
+       /* AES rounds. */
+       vaesenc (1 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (2 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (3 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (4 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (5 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (6 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (7 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (8 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (9 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (10 * 16)(%rdi), %xmm1;
+       cmpl $12, %r9d;
+       jb .Lcfb_dec_blk1_last;
+       vaesenc %xmm1, %xmm0, %xmm0;
+       vaesenc (11 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (12 * 16)(%rdi), %xmm1;
+       jz .Lcfb_dec_blk1_last;
+       vaesenc %xmm1, %xmm0, %xmm0;
+       vaesenc (13 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (14 * 16)(%rdi), %xmm1;
+
+       /* Last round and output handling. */
+  .Lcfb_dec_blk1_last:
+       vpxor %xmm15, %xmm1, %xmm1;
+       vaesenclast %xmm1, %xmm0, %xmm0;
+       vmovdqu %xmm0, (%rdx);
+       leaq 16(%rdx), %rdx;
+
+       jmp .Lcfb_dec_blk1;
+
+.align 8
+.Ldone_cfb_dec:
+       /* Store IV. */
+       vmovdqu %xmm15, (%rsi);
+
+       vzeroall;
+       ret_spec_stop
+       CFI_ENDPROC();
+ELF(.size _gcry_vaes_avx2_cfb_dec_amd64,.-_gcry_vaes_avx2_cfb_dec_amd64)
+
+/**********************************************************************
+  CTR-mode encryption
+ **********************************************************************/
+ELF(.type _gcry_vaes_avx2_ctr_enc_amd64,@function)
+.globl _gcry_vaes_avx2_ctr_enc_amd64
+_gcry_vaes_avx2_ctr_enc_amd64:
+       /* input:
+        *      %rdi: round keys
+        *      %rsi: counter
+        *      %rdx: dst
+        *      %rcx: src
+        *      %r8:  nblocks
+        *      %r9:  nrounds
+        */
+       CFI_STARTPROC();
+
+       movq 8(%rsi), %r10;
+       movq 0(%rsi), %r11;
+       bswapq %r10;
+       bswapq %r11;
+
+       vpcmpeqd %ymm15, %ymm15, %ymm15;
+       vpsrldq $8, %ymm15, %ymm15;     // 0:-1
+       vpaddq %ymm15, %ymm15, %ymm14;  // 0:-2
+       vbroadcasti128 .Lbswap128_mask rRIP, %ymm13;
+
+#define inc_le128(x, minus_one, tmp) \
+       vpcmpeqq minus_one, x, tmp; \
+       vpsubq minus_one, x, x; \
+       vpslldq $8, tmp, tmp; \
+       vpsubq tmp, x, x;
+
+#define add2_le128(x, minus_one, minus_two, tmp1, tmp2) \
+       vpcmpeqq minus_one, x, tmp1; \
+       vpcmpeqq minus_two, x, tmp2; \
+       vpor tmp1, tmp2, tmp2; \
+       vpsubq minus_two, x, x; \
+       vpslldq $8, tmp2, tmp2; \
+       vpsubq tmp2, x, x;
+
+       /* Process 16 blocks per loop. */
+.align 8
+.Lctr_enc_blk16:
+       cmpq $16, %r8;
+       jb .Lctr_enc_blk8;
+
+       leaq -16(%r8), %r8;
+
+       vbroadcasti128 (%rsi), %ymm7;
+       vbroadcasti128 (0 * 16)(%rdi), %ymm8;
+
+       /* detect if carry handling is needed */
+       addb $16, 15(%rsi);
+       jc .Lctr_enc_blk16_handle_carry;
+
+       /* Increment counters. */
+       vpaddb .Lbige_addb_0 rRIP, %ymm7, %ymm0;
+       vpaddb .Lbige_addb_2 rRIP, %ymm7, %ymm1;
+       vpaddb .Lbige_addb_4 rRIP, %ymm7, %ymm2;
+       vpaddb .Lbige_addb_6 rRIP, %ymm7, %ymm3;
+       vpaddb .Lbige_addb_8 rRIP, %ymm7, %ymm4;
+       vpaddb .Lbige_addb_10 rRIP, %ymm7, %ymm5;
+       vpaddb .Lbige_addb_12 rRIP, %ymm7, %ymm6;
+       vpaddb .Lbige_addb_14 rRIP, %ymm7, %ymm7;
+       leaq 16(%r10), %r10;
+
+  .Lctr_enc_blk16_rounds:
+       /* AES rounds */
+       XOR8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (1 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm8;
+       cmpl $12, %r9d;
+       jb .Lctr_enc_blk16_last;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm8;
+       jz .Lctr_enc_blk16_last;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm8;
+
+       /* Last round and output handling. */
+  .Lctr_enc_blk16_last:
+       vpxor (0 * 16)(%rcx), %ymm8, %ymm9; /* Xor src to last round key. */
+       vpxor (2 * 16)(%rcx), %ymm8, %ymm10;
+       vpxor (4 * 16)(%rcx), %ymm8, %ymm11;
+       vpxor (6 * 16)(%rcx), %ymm8, %ymm12;
+       vaesenclast %ymm9, %ymm0, %ymm0;
+       vaesenclast %ymm10, %ymm1, %ymm1;
+       vaesenclast %ymm11, %ymm2, %ymm2;
+       vaesenclast %ymm12, %ymm3, %ymm3;
+       vpxor (8 * 16)(%rcx), %ymm8, %ymm9;
+       vpxor (10 * 16)(%rcx), %ymm8, %ymm10;
+       vpxor (12 * 16)(%rcx), %ymm8, %ymm11;
+       vpxor (14 * 16)(%rcx), %ymm8, %ymm8;
+       leaq (16 * 16)(%rcx), %rcx;
+       vaesenclast %ymm9, %ymm4, %ymm4;
+       vaesenclast %ymm10, %ymm5, %ymm5;
+       vaesenclast %ymm11, %ymm6, %ymm6;
+       vaesenclast %ymm8, %ymm7, %ymm7;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       vmovdqu %ymm2, (4 * 16)(%rdx);
+       vmovdqu %ymm3, (6 * 16)(%rdx);
+       vmovdqu %ymm4, (8 * 16)(%rdx);
+       vmovdqu %ymm5, (10 * 16)(%rdx);
+       vmovdqu %ymm6, (12 * 16)(%rdx);
+       vmovdqu %ymm7, (14 * 16)(%rdx);
+       leaq (16 * 16)(%rdx), %rdx;
+
+       jmp .Lctr_enc_blk16;
+
+  .align 8
+  .Lctr_enc_blk16_handle_carry:
+       /* Increment counters (handle carry). */
+       vpshufb %xmm13, %xmm7, %xmm1; /* be => le */
+       vmovdqa %xmm1, %xmm0;
+       inc_le128(%xmm1, %xmm15, %xmm5);
+       vinserti128 $1, %xmm1, %ymm0, %ymm7; /* ctr: +1:+0 */
+       vpshufb %ymm13, %ymm7, %ymm0;
+       addq $16, %r10;
+       adcq $0, %r11;
+       bswapq %r10;
+       bswapq %r11;
+       movq %r10, 8(%rsi);
+       movq %r11, 0(%rsi);
+       bswapq %r10;
+       bswapq %r11;
+       add2_le128(%ymm7, %ymm15, %ymm14, %ymm9, %ymm10); /* ctr: +3:+2 */
+       vpshufb %ymm13, %ymm7, %ymm1;
+       add2_le128(%ymm7, %ymm15, %ymm14, %ymm9, %ymm10); /* ctr: +5:+4 */
+       vpshufb %ymm13, %ymm7, %ymm2;
+       add2_le128(%ymm7, %ymm15, %ymm14, %ymm9, %ymm10); /* ctr: +7:+6 */
+       vpshufb %ymm13, %ymm7, %ymm3;
+       add2_le128(%ymm7, %ymm15, %ymm14, %ymm9, %ymm10); /* ctr: +9:+8 */
+       vpshufb %ymm13, %ymm7, %ymm4;
+       add2_le128(%ymm7, %ymm15, %ymm14, %ymm9, %ymm10); /* ctr: +11:+10 */
+       vpshufb %ymm13, %ymm7, %ymm5;
+       add2_le128(%ymm7, %ymm15, %ymm14, %ymm9, %ymm10); /* ctr: +13:+12 */
+       vpshufb %ymm13, %ymm7, %ymm6;
+       add2_le128(%ymm7, %ymm15, %ymm14, %ymm9, %ymm10); /* ctr: +15:+14 */
+       vpshufb %ymm13, %ymm7, %ymm7;
+
+       jmp .Lctr_enc_blk16_rounds;
+
+       /* Handle trailing eight blocks. */
+.align 8
+.Lctr_enc_blk8:
+       cmpq $8, %r8;
+       jb .Lctr_enc_blk4;
+
+       leaq -8(%r8), %r8;
+
+       vbroadcasti128 (%rsi), %ymm3;
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+
+       /* detect if carry handling is needed */
+       addb $8, 15(%rsi);
+       jc .Lctr_enc_blk8_handle_carry;
+
+       /* Increment counters. */
+       vpaddb .Lbige_addb_0 rRIP, %ymm3, %ymm0;
+       vpaddb .Lbige_addb_2 rRIP, %ymm3, %ymm1;
+       vpaddb .Lbige_addb_4 rRIP, %ymm3, %ymm2;
+       vpaddb .Lbige_addb_6 rRIP, %ymm3, %ymm3;
+       leaq 8(%r10), %r10;
+
+  .Lctr_enc_blk8_rounds:
+       /* AES rounds */
+       XOR4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+       cmpl $12, %r9d;
+       jb .Lctr_enc_blk8_last;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+       jz .Lctr_enc_blk8_last;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+       /* Last round and output handling. */
+  .Lctr_enc_blk8_last:
+       vpxor (0 * 16)(%rcx), %ymm4, %ymm5; /* Xor src to last round key. */
+       vpxor (2 * 16)(%rcx), %ymm4, %ymm6;
+       vpxor (4 * 16)(%rcx), %ymm4, %ymm7;
+       vpxor (6 * 16)(%rcx), %ymm4, %ymm4;
+       leaq (8 * 16)(%rcx), %rcx;
+       vaesenclast %ymm5, %ymm0, %ymm0;
+       vaesenclast %ymm6, %ymm1, %ymm1;
+       vaesenclast %ymm7, %ymm2, %ymm2;
+       vaesenclast %ymm4, %ymm3, %ymm3;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       vmovdqu %ymm2, (4 * 16)(%rdx);
+       vmovdqu %ymm3, (6 * 16)(%rdx);
+       leaq (8 * 16)(%rdx), %rdx;
+
+       jmp .Lctr_enc_blk4;
+
+  .align 8
+  .Lctr_enc_blk8_handle_carry:
+       /* Increment counters (handle carry). */
+       vpshufb %xmm13, %xmm3, %xmm1; /* be => le */
+       vmovdqa %xmm1, %xmm0;
+       inc_le128(%xmm1, %xmm15, %xmm5);
+       vinserti128 $1, %xmm1, %ymm0, %ymm3; /* ctr: +1:+0 */
+       vpshufb %ymm13, %ymm3, %ymm0;
+       addq $8, %r10;
+       adcq $0, %r11;
+       bswapq %r10;
+       bswapq %r11;
+       movq %r10, 8(%rsi);
+       movq %r11, 0(%rsi);
+       bswapq %r10;
+       bswapq %r11;
+       add2_le128(%ymm3, %ymm15, %ymm14, %ymm5, %ymm6); /* ctr: +3:+2 */
+       vpshufb %ymm13, %ymm3, %ymm1;
+       add2_le128(%ymm3, %ymm15, %ymm14, %ymm5, %ymm6); /* ctr: +5:+4 */
+       vpshufb %ymm13, %ymm3, %ymm2;
+       add2_le128(%ymm3, %ymm15, %ymm14, %ymm5, %ymm6); /* ctr: +7:+6 */
+       vpshufb %ymm13, %ymm3, %ymm3;
+
+       jmp .Lctr_enc_blk8_rounds;
+
+       /* Handle trailing four blocks. */
+.align 8
+.Lctr_enc_blk4:
+       cmpq $4, %r8;
+       jb .Lctr_enc_blk1;
+
+       leaq -4(%r8), %r8;
+
+       vbroadcasti128 (%rsi), %ymm3;
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+
+       /* detect if carry handling is needed */
+       addb $4, 15(%rsi);
+       jc .Lctr_enc_blk4_handle_carry;
+
+       /* Increment counters. */
+       vpaddb .Lbige_addb_0 rRIP, %ymm3, %ymm0;
+       vpaddb .Lbige_addb_2 rRIP, %ymm3, %ymm1;
+       leaq 4(%r10), %r10;
+
+  .Lctr_enc_blk4_rounds:
+       /* AES rounds */
+       XOR2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+       cmpl $12, %r9d;
+       jb .Lctr_enc_blk4_last;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+       jz .Lctr_enc_blk4_last;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+       /* Last round and output handling. */
+  .Lctr_enc_blk4_last:
+       vpxor (0 * 16)(%rcx), %ymm4, %ymm5; /* Xor src to last round key. */
+       vpxor (2 * 16)(%rcx), %ymm4, %ymm6;
+       leaq (4 * 16)(%rcx), %rcx;
+       vaesenclast %ymm5, %ymm0, %ymm0;
+       vaesenclast %ymm6, %ymm1, %ymm1;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       leaq (4 * 16)(%rdx), %rdx;
+
+       jmp .Lctr_enc_blk1;
+
+  .align 8
+  .Lctr_enc_blk4_handle_carry:
+       /* Increment counters (handle carry). */
+       vpshufb %xmm13, %xmm3, %xmm1; /* be => le */
+       vmovdqa %xmm1, %xmm0;
+       inc_le128(%xmm1, %xmm15, %xmm5);
+       vinserti128 $1, %xmm1, %ymm0, %ymm3; /* ctr: +1:+0 */
+       vpshufb %ymm13, %ymm3, %ymm0;
+       addq $4, %r10;
+       adcq $0, %r11;
+       bswapq %r10;
+       bswapq %r11;
+       movq %r10, 8(%rsi);
+       movq %r11, 0(%rsi);
+       bswapq %r10;
+       bswapq %r11;
+       add2_le128(%ymm3, %ymm15, %ymm14, %ymm5, %ymm6); /* ctr: +3:+2 */
+       vpshufb %ymm13, %ymm3, %ymm1;
+
+       jmp .Lctr_enc_blk4_rounds;
+
+       /* Process trailing one to three blocks, one per loop. */
+.align 8
+.Lctr_enc_blk1:
+       cmpq $1, %r8;
+       jb .Ldone_ctr_enc;
+
+       leaq -1(%r8), %r8;
+
+       /* Load and increament counter. */
+       vmovdqu (%rsi), %xmm0;
+       addq $1, %r10;
+       adcq $0, %r11;
+       bswapq %r10;
+       bswapq %r11;
+       movq %r10, 8(%rsi);
+       movq %r11, 0(%rsi);
+       bswapq %r10;
+       bswapq %r11;
+
+       /* AES rounds. */
+       vpxor (0 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (1 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (2 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (3 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (4 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (5 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (6 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (7 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (8 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (9 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (10 * 16)(%rdi), %xmm1;
+       cmpl $12, %r9d;
+       jb .Lctr_enc_blk1_last;
+       vaesenc %xmm1, %xmm0, %xmm0;
+       vaesenc (11 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (12 * 16)(%rdi), %xmm1;
+       jz .Lctr_enc_blk1_last;
+       vaesenc %xmm1, %xmm0, %xmm0;
+       vaesenc (13 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (14 * 16)(%rdi), %xmm1;
+
+       /* Last round and output handling. */
+  .Lctr_enc_blk1_last:
+       vpxor (%rcx), %xmm1, %xmm1; /* Xor src to last round key. */
+       leaq 16(%rcx), %rcx;
+       vaesenclast %xmm1, %xmm0, %xmm0; /* Last round and xor with xmm1. */
+       vmovdqu %xmm0, (%rdx);
+       leaq 16(%rdx), %rdx;
+
+       jmp .Lctr_enc_blk1;
+
+.align 8
+.Ldone_ctr_enc:
+       vzeroall;
+       xorl %r10d, %r10d;
+       xorl %r11d, %r11d;
+       ret_spec_stop
+       CFI_ENDPROC();
+ELF(.size _gcry_vaes_avx2_ctr_enc_amd64,.-_gcry_vaes_avx2_ctr_enc_amd64)
+
+/**********************************************************************
+  Little-endian 32-bit CTR-mode encryption (GCM-SIV)
+ **********************************************************************/
+ELF(.type _gcry_vaes_avx2_ctr32le_enc_amd64,@function)
+.globl _gcry_vaes_avx2_ctr32le_enc_amd64
+_gcry_vaes_avx2_ctr32le_enc_amd64:
+       /* input:
+        *      %rdi: round keys
+        *      %rsi: counter
+        *      %rdx: dst
+        *      %rcx: src
+        *      %r8:  nblocks
+        *      %r9:  nrounds
+        */
+       CFI_STARTPROC();
+
+       vbroadcasti128 (%rsi), %ymm15; // CTR
+
+       /* Process 16 blocks per loop. */
+.align 8
+.Lctr32le_enc_blk16:
+       cmpq $16, %r8;
+       jb .Lctr32le_enc_blk8;
+
+       leaq -16(%r8), %r8;
+
+       vbroadcasti128 (0 * 16)(%rdi), %ymm8;
+
+       /* Increment counters. */
+       vpaddd .Lle_addd_0 rRIP, %ymm15, %ymm0;
+       vpaddd .Lle_addd_2 rRIP, %ymm15, %ymm1;
+       vpaddd .Lle_addd_4 rRIP, %ymm15, %ymm2;
+       vpaddd .Lle_addd_6 rRIP, %ymm15, %ymm3;
+       vpaddd .Lle_addd_8 rRIP, %ymm15, %ymm4;
+       vpaddd .Lle_addd_10 rRIP, %ymm15, %ymm5;
+       vpaddd .Lle_addd_12 rRIP, %ymm15, %ymm6;
+       vpaddd .Lle_addd_14 rRIP, %ymm15, %ymm7;
+
+       vpaddd .Lle_addd_16_2 rRIP, %ymm15, %ymm15;
+
+       /* AES rounds */
+       XOR8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (1 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm8;
+       cmpl $12, %r9d;
+       jb .Lctr32le_enc_blk16_last;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm8;
+       jz .Lctr32le_enc_blk16_last;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm8;
+       VAESENC8(%ymm8, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm8;
+
+       /* Last round and output handling. */
+  .Lctr32le_enc_blk16_last:
+       vpxor (0 * 16)(%rcx), %ymm8, %ymm9; /* Xor src to last round key. */
+       vpxor (2 * 16)(%rcx), %ymm8, %ymm10;
+       vpxor (4 * 16)(%rcx), %ymm8, %ymm11;
+       vpxor (6 * 16)(%rcx), %ymm8, %ymm12;
+       vaesenclast %ymm9, %ymm0, %ymm0;
+       vaesenclast %ymm10, %ymm1, %ymm1;
+       vaesenclast %ymm11, %ymm2, %ymm2;
+       vaesenclast %ymm12, %ymm3, %ymm3;
+       vpxor (8 * 16)(%rcx), %ymm8, %ymm9;
+       vpxor (10 * 16)(%rcx), %ymm8, %ymm10;
+       vpxor (12 * 16)(%rcx), %ymm8, %ymm11;
+       vpxor (14 * 16)(%rcx), %ymm8, %ymm8;
+       leaq (16 * 16)(%rcx), %rcx;
+       vaesenclast %ymm9, %ymm4, %ymm4;
+       vaesenclast %ymm10, %ymm5, %ymm5;
+       vaesenclast %ymm11, %ymm6, %ymm6;
+       vaesenclast %ymm8, %ymm7, %ymm7;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       vmovdqu %ymm2, (4 * 16)(%rdx);
+       vmovdqu %ymm3, (6 * 16)(%rdx);
+       vmovdqu %ymm4, (8 * 16)(%rdx);
+       vmovdqu %ymm5, (10 * 16)(%rdx);
+       vmovdqu %ymm6, (12 * 16)(%rdx);
+       vmovdqu %ymm7, (14 * 16)(%rdx);
+       leaq (16 * 16)(%rdx), %rdx;
+
+       jmp .Lctr32le_enc_blk16;
+
+       /* Handle trailing eight blocks. */
+.align 8
+.Lctr32le_enc_blk8:
+       cmpq $8, %r8;
+       jb .Lctr32le_enc_blk4;
+
+       leaq -8(%r8), %r8;
+
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+
+       /* Increment counters. */
+       vpaddd .Lle_addd_0 rRIP, %ymm15, %ymm0;
+       vpaddd .Lle_addd_2 rRIP, %ymm15, %ymm1;
+       vpaddd .Lle_addd_4 rRIP, %ymm15, %ymm2;
+       vpaddd .Lle_addd_6 rRIP, %ymm15, %ymm3;
+
+       vpaddd .Lle_addd_8_2 rRIP, %ymm15, %ymm15;
+
+       /* AES rounds */
+       XOR4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+       cmpl $12, %r9d;
+       jb .Lctr32le_enc_blk8_last;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+       jz .Lctr32le_enc_blk8_last;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+       /* Last round and output handling. */
+  .Lctr32le_enc_blk8_last:
+       vpxor (0 * 16)(%rcx), %ymm4, %ymm5; /* Xor src to last round key. */
+       vpxor (2 * 16)(%rcx), %ymm4, %ymm6;
+       vpxor (4 * 16)(%rcx), %ymm4, %ymm7;
+       vpxor (6 * 16)(%rcx), %ymm4, %ymm4;
+       leaq (8 * 16)(%rcx), %rcx;
+       vaesenclast %ymm5, %ymm0, %ymm0;
+       vaesenclast %ymm6, %ymm1, %ymm1;
+       vaesenclast %ymm7, %ymm2, %ymm2;
+       vaesenclast %ymm4, %ymm3, %ymm3;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       vmovdqu %ymm2, (4 * 16)(%rdx);
+       vmovdqu %ymm3, (6 * 16)(%rdx);
+       leaq (8 * 16)(%rdx), %rdx;
+
+       /* Handle trailing four blocks. */
+.align 8
+.Lctr32le_enc_blk4:
+       cmpq $4, %r8;
+       jb .Lctr32le_enc_blk1;
+
+       leaq -4(%r8), %r8;
+
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+
+       /* Increment counters. */
+       vpaddd .Lle_addd_0 rRIP, %ymm15, %ymm0;
+       vpaddd .Lle_addd_2 rRIP, %ymm15, %ymm1;
+
+       vpaddd .Lle_addd_4_2 rRIP, %ymm15, %ymm15;
+
+       /* AES rounds */
+       XOR2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+       cmpl $12, %r9d;
+       jb .Lctr32le_enc_blk4_last;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+       jz .Lctr32le_enc_blk4_last;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+       VAESENC2(%ymm4, %ymm0, %ymm1);
+       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+       /* Last round and output handling. */
+  .Lctr32le_enc_blk4_last:
+       vpxor (0 * 16)(%rcx), %ymm4, %ymm5; /* Xor src to last round key. */
+       vpxor (2 * 16)(%rcx), %ymm4, %ymm6;
+       leaq (4 * 16)(%rcx), %rcx;
+       vaesenclast %ymm5, %ymm0, %ymm0;
+       vaesenclast %ymm6, %ymm1, %ymm1;
+       vmovdqu %ymm0, (0 * 16)(%rdx);
+       vmovdqu %ymm1, (2 * 16)(%rdx);
+       leaq (4 * 16)(%rdx), %rdx;
+
+       /* Process trailing one to three blocks, one per loop. */
+.align 8
+.Lctr32le_enc_blk1:
+       cmpq $1, %r8;
+       jb .Ldone_ctr32le_enc;
+
+       leaq -1(%r8), %r8;
+
+       /* Load and increament counter. */
+       vmovdqu %xmm15, %xmm0;
+       vpaddd .Lle_addd_1 rRIP, %xmm15, %xmm15;
+
+       /* AES rounds. */
+       vpxor (0 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (1 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (2 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (3 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (4 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (5 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (6 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (7 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (8 * 16)(%rdi), %xmm0, %xmm0;
+       vaesenc (9 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (10 * 16)(%rdi), %xmm1;
+       cmpl $12, %r9d;
+       jb .Lctr32le_enc_blk1_last;
+       vaesenc %xmm1, %xmm0, %xmm0;
+       vaesenc (11 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (12 * 16)(%rdi), %xmm1;
+       jz .Lctr32le_enc_blk1_last;
+       vaesenc %xmm1, %xmm0, %xmm0;
+       vaesenc (13 * 16)(%rdi), %xmm0, %xmm0;
+       vmovdqa (14 * 16)(%rdi), %xmm1;
+
+       /* Last round and output handling. */
+  .Lctr32le_enc_blk1_last:
+       vpxor (%rcx), %xmm1, %xmm1; /* Xor src to last round key. */
+       leaq 16(%rcx), %rcx;
+       vaesenclast %xmm1, %xmm0, %xmm0; /* Last round and xor with xmm1. */
+       vmovdqu %xmm0, (%rdx);
+       leaq 16(%rdx), %rdx;
+
+       jmp .Lctr32le_enc_blk1;
+
+.align 8
+.Ldone_ctr32le_enc:
+       vmovdqu %xmm15, (%rsi);
+       vzeroall;
+       ret_spec_stop
+       CFI_ENDPROC();
+ELF(.size _gcry_vaes_avx2_ctr32le_enc_amd64,.-_gcry_vaes_avx2_ctr32le_enc_amd64)
+
+/**********************************************************************
+  OCB-mode encryption/decryption
+ **********************************************************************/
+ELF(.type _gcry_vaes_avx2_ocb_checksum,@function)
+_gcry_vaes_avx2_ocb_checksum:
+       /* input:
+        *      %rax:     offset pointer
+        *      %r10:     plaintext pointer
+        *      %r11:     nblocks
+        */
+       CFI_STARTPROC();
+
+       vpxor %xmm0, %xmm0, %xmm0;
+       cmpq $4, %r11;
+       jb .Locb_checksum_blk1;
+       vpxor %xmm1, %xmm1, %xmm1;
+       vpxor %xmm2, %xmm2, %xmm2;
+       vpxor %xmm3, %xmm3, %xmm3;
+       cmpq $16, %r11;
+       jb .Locb_checksum_blk4;
+       vpxor %xmm4, %xmm4, %xmm4;
+       vpxor %xmm5, %xmm5, %xmm5;
+       vpxor %xmm6, %xmm6, %xmm6;
+       vpxor %xmm7, %xmm7, %xmm7;
+       cmpq $32, %r11;
+       jb .Locb_checksum_blk16;
+       vpxor %xmm8, %xmm8, %xmm8;
+       vpxor %xmm9, %xmm9, %xmm9;
+       vpxor %xmm10, %xmm10, %xmm10;
+       vpxor %xmm11, %xmm11, %xmm11;
+       vpxor %xmm12, %xmm12, %xmm12;
+       vpxor %xmm13, %xmm13, %xmm13;
+       vpxor %xmm14, %xmm14, %xmm14;
+       vpxor %xmm15, %xmm15, %xmm15;
+
+.align 8
+.Locb_checksum_blk32:
+       cmpq $32, %r11;
+       jb .Locb_checksum_blk32_done;
+
+       leaq -32(%r11), %r11;
+
+       vpxor (0 * 16)(%r10), %ymm0, %ymm0;
+       vpxor (2 * 16)(%r10), %ymm1, %ymm1;
+       vpxor (4 * 16)(%r10), %ymm2, %ymm2;
+       vpxor (6 * 16)(%r10), %ymm3, %ymm3;
+       vpxor (8 * 16)(%r10), %ymm4, %ymm4;
+       vpxor (10 * 16)(%r10), %ymm5, %ymm5;
+       vpxor (12 * 16)(%r10), %ymm6, %ymm6;
+       vpxor (14 * 16)(%r10), %ymm7, %ymm7;
+       vpxor (16 * 16)(%r10), %ymm8, %ymm8;
+       vpxor (18 * 16)(%r10), %ymm9, %ymm9;
+       vpxor (20 * 16)(%r10), %ymm10, %ymm10;
+       vpxor (22 * 16)(%r10), %ymm11, %ymm11;
+       vpxor (24 * 16)(%r10), %ymm12, %ymm12;
+       vpxor (26 * 16)(%r10), %ymm13, %ymm13;
+       vpxor (28 * 16)(%r10), %ymm14, %ymm14;
+       vpxor (30 * 16)(%r10), %ymm15, %ymm15;
+       leaq (32 * 16)(%r10), %r10;
+
+       jmp .Locb_checksum_blk32;
+
+.align 8
+.Locb_checksum_blk32_done:
+       vpxor %ymm8, %ymm0, %ymm0;
+       vpxor %ymm9, %ymm1, %ymm1;
+       vpxor %ymm10, %ymm2, %ymm2;
+       vpxor %ymm11, %ymm3, %ymm3;
+       vpxor %ymm12, %ymm4, %ymm4;
+       vpxor %ymm13, %ymm5, %ymm5;
+       vpxor %ymm14, %ymm6, %ymm6;
+       vpxor %ymm15, %ymm7, %ymm7;
+
+.align 8
+.Locb_checksum_blk16:
+       cmpq $16, %r11;
+       jb .Locb_checksum_blk16_done;
+
+       leaq -16(%r11), %r11;
+
+       vpxor (0 * 16)(%r10), %ymm0, %ymm0;
+       vpxor (2 * 16)(%r10), %ymm1, %ymm1;
+       vpxor (4 * 16)(%r10), %ymm2, %ymm2;
+       vpxor (6 * 16)(%r10), %ymm3, %ymm3;
+       vpxor (8 * 16)(%r10), %ymm4, %ymm4;
+       vpxor (10 * 16)(%r10), %ymm5, %ymm5;
+       vpxor (12 * 16)(%r10), %ymm6, %ymm6;
+       vpxor (14 * 16)(%r10), %ymm7, %ymm7;
+       leaq (16 * 16)(%r10), %r10;
+
+       jmp .Locb_checksum_blk16;
+
+.align 8
+.Locb_checksum_blk16_done:
+       vpxor %ymm4, %ymm0, %ymm0;
+       vpxor %ymm5, %ymm1, %ymm1;
+       vpxor %ymm6, %ymm2, %ymm2;
+       vpxor %ymm7, %ymm3, %ymm3;
+       vextracti128 $1, %ymm0, %xmm4;
+       vextracti128 $1, %ymm1, %xmm5;
+       vextracti128 $1, %ymm2, %xmm6;
+       vextracti128 $1, %ymm3, %xmm7;
+       vpxor %xmm4, %xmm0, %xmm0;
+       vpxor %xmm5, %xmm1, %xmm1;
+       vpxor %xmm6, %xmm2, %xmm2;
+       vpxor %xmm7, %xmm3, %xmm3;
+
+.align 8
+.Locb_checksum_blk4:
+       cmpq $4, %r11;
+       jb .Locb_checksum_blk4_done;
+
+       leaq -4(%r11), %r11;
+
+       vpxor (0 * 16)(%r10), %xmm0, %xmm0;
+       vpxor (1 * 16)(%r10), %xmm1, %xmm1;
+       vpxor (2 * 16)(%r10), %xmm2, %xmm2;
+       vpxor (3 * 16)(%r10), %xmm3, %xmm3;
+       leaq (4 * 16)(%r10), %r10;
+
+       jmp .Locb_checksum_blk4;
+
+.align 8
+.Locb_checksum_blk4_done:
+       vpxor %xmm1, %xmm0, %xmm0;
+       vpxor %xmm3, %xmm2, %xmm2;
+       vpxor %xmm2, %xmm0, %xmm0;
+
+.align 8
+.Locb_checksum_blk1:
+       cmpq $1, %r11;
+       jb .Locb_checksum_done;
+
+       leaq -1(%r11), %r11;
+
+       vpxor (%r10), %xmm0, %xmm0;
+       leaq 16(%r10), %r10;
+
+       jmp .Locb_checksum_blk1;
+
+.align 8
+.Locb_checksum_done:
+       vpxor (%rax), %xmm0, %xmm0;
+       vmovdqu %xmm0, (%rax);
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_vaes_avx2_ocb_checksum,.-_gcry_vaes_avx2_ocb_checksum)
+
+ELF(.type _gcry_vaes_avx2_ocb_crypt_amd64,@function)
+.globl _gcry_vaes_avx2_ocb_crypt_amd64
+_gcry_vaes_avx2_ocb_crypt_amd64:
+       /* input:
+        *      %rdi:     round keys
+        *      %esi:     nblk
+        *      %rdx:     dst
+        *      %rcx:     src
+        *      %r8:      nblocks
+        *      %r9:      nrounds
+        *      16(%rbp): offset
+        *      24(%rbp): checksum
+        *      32(%rbp): L-array
+        *      40(%rbp): encrypt (%r15d)
+        */
+       CFI_STARTPROC();
+
+#define STACK_REGS_POS (16 * 16 + 4 * 16)
+#define STACK_ALLOC (STACK_REGS_POS + 6 * 8)
+
+       pushq %rbp;
+       CFI_PUSH(%rbp);
+       movq %rsp, %rbp;
+       CFI_DEF_CFA_REGISTER(%rbp);
+
+       subq $STACK_ALLOC, %rsp;
+       andq $~63, %rsp;
+
+       movq %r12, (STACK_REGS_POS + 0 * 8)(%rsp);
+       CFI_REG_ON_STACK(r12, STACK_REGS_POS + 0 * 8);
+       movq %r13, (STACK_REGS_POS + 1 * 8)(%rsp);
+       CFI_REG_ON_STACK(r13, STACK_REGS_POS + 1 * 8);
+       movq %r14, (STACK_REGS_POS + 2 * 8)(%rsp);
+       CFI_REG_ON_STACK(r14, STACK_REGS_POS + 2 * 8);
+       movq %r15, (STACK_REGS_POS + 3 * 8)(%rsp);
+       CFI_REG_ON_STACK(r15, STACK_REGS_POS + 3 * 8);
+
+       movl 40(%rbp), %r15d; /* encrypt-flag. */
+       movq 16(%rbp), %r14; /* offset ptr. */
+
+       /* Handle encryption checksumming. */
+       testl %r15d, %r15d;
+       jz .Locb_dec_checksum_prepare;
+       movq 24(%rbp), %rax; /* checksum ptr. */
+       movq %rcx, %r10;
+       movq %r8, %r11;
+       call _gcry_vaes_avx2_ocb_checksum;
+       jmp .Locb_enc_checksum_done;
+.Locb_dec_checksum_prepare:
+       /* Store plaintext address and number of blocks for decryption
+        * checksumming. */
+       movq %rdx, (STACK_REGS_POS + 4 * 8)(%rsp);
+       movq %r8, (STACK_REGS_POS + 5 * 8)(%rsp);
+.Locb_enc_checksum_done:
+
+       vmovdqu (%r14), %xmm15; /* Load offset. */
+       movq 32(%rbp), %r14; /* L-array ptr. */
+       vmovdqa (0 * 16)(%rdi), %xmm0; /* first key */
+       movl $(10 * 16), %eax;
+       cmpl $12, %r9d;
+       jb .Llast_key_ptr;
+       movl $(12 * 16), %eax;
+       je .Llast_key_ptr;
+       movl $(14 * 16), %eax;
+  .align 8
+  .Llast_key_ptr:
+       vpxor (%rdi, %rax), %xmm0, %xmm0; /* first key ^ last key */
+       vpxor (0 * 16)(%rdi), %xmm15, %xmm15; /* offset ^ first key */
+       vmovdqa %xmm0, (14 * 16)(%rsp);
+       vmovdqa %xmm0, (15 * 16)(%rsp);
+
+.align 8
+.Lhandle_unaligned_ocb:
+       /* Get number of blocks to align nblk to 16 (and L-array optimization). */
+       movl %esi, %r10d;
+       negl %r10d;
+       andl $15, %r10d;
+       cmpq %r8, %r10;
+       cmovaq %r8, %r10;
+       cmpq $1, %r10;
+       jb .Lunaligned_ocb_done;
+
+       /* Number of blocks after alignment. */
+       movq %r8, %r11;
+       subq %r10, %r11;
+
+       /* If number after alignment is less than 16, skip aligned handling
+        * completely. */
+       cmp $16, %r11;
+       cmovbq %r8, %r10;
+
+       /* Unaligned: Process eight blocks per loop. */
+.align 8
+.Locb_unaligned_blk8:
+       cmpq $8, %r10;
+       jb .Locb_unaligned_blk4;
+
+       leaq -8(%r8), %r8;
+       leaq -8(%r10), %r10;
+
+       leal 1(%esi), %r11d;
+       leal 2(%esi), %r12d;
+       leal 3(%esi), %r13d;
+       leal 4(%esi), %eax;
+       tzcntl %r11d, %r11d;
+       tzcntl %r12d, %r12d;
+       tzcntl %r13d, %r13d;
+       tzcntl %eax, %eax;
+       shll $4, %r11d;
+       shll $4, %r12d;
+       shll $4, %r13d;
+       shll $4, %eax;
+       vpxor (%r14, %r11), %xmm15, %xmm5;
+       vpxor (%r14, %r12), %xmm5, %xmm6;
+       vpxor (%r14, %r13), %xmm6, %xmm7;
+       vpxor (%r14, %rax), %xmm7, %xmm8;
+
+       leal 5(%esi), %r11d;
+       leal 6(%esi), %r12d;
+       leal 7(%esi), %r13d;
+       leal 8(%esi), %esi;
+       tzcntl %r11d, %r11d;
+       tzcntl %r12d, %r12d;
+       tzcntl %r13d, %r13d;
+       tzcntl %esi, %eax;
+       shll $4, %r11d;
+       shll $4, %r12d;
+       shll $4, %r13d;
+       shll $4, %eax;
+       vpxor (%r14, %r11), %xmm8, %xmm9;
+       vpxor (%r14, %r12), %xmm9, %xmm10;
+       vpxor (%r14, %r13), %xmm10, %xmm11;
+       vpxor (%r14, %rax), %xmm11, %xmm15;
+
+       vinserti128 $1, %xmm6, %ymm5, %ymm5;
+       vinserti128 $1, %xmm8, %ymm7, %ymm6;
+       vinserti128 $1, %xmm10, %ymm9, %ymm7;
+       vinserti128 $1, %xmm15, %ymm11, %ymm8;
+
+       vpxor (0 * 16)(%rcx), %ymm5, %ymm0;
+       vpxor (2 * 16)(%rcx), %ymm6, %ymm1;
+       vpxor (4 * 16)(%rcx), %ymm7, %ymm2;
+       vpxor (6 * 16)(%rcx), %ymm8, %ymm3;
+       leaq (8 * 16)(%rcx), %rcx;
+
+       vmovdqa (14 * 16)(%rsp), %ymm9;
+
+       testl %r15d, %r15d;
+       jz .Locb_unaligned_blk8_dec;
+               /* AES rounds */
+               vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               cmpl $12, %r9d;
+               jb .Locb_unaligned_blk8_enc_last;
+               vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               jz .Locb_unaligned_blk8_enc_last;
+               vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+
+               /* Last round and output handling. */
+       .Locb_unaligned_blk8_enc_last:
+               vpxor %ymm5, %ymm9, %ymm5; /* Xor src to last round key. */
+               vpxor %ymm6, %ymm9, %ymm6;
+               vpxor %ymm7, %ymm9, %ymm7;
+               vpxor %ymm8, %ymm9, %ymm4;
+               vaesenclast %ymm5, %ymm0, %ymm0;
+               vaesenclast %ymm6, %ymm1, %ymm1;
+               vaesenclast %ymm7, %ymm2, %ymm2;
+               vaesenclast %ymm4, %ymm3, %ymm3;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               vmovdqu %ymm2, (4 * 16)(%rdx);
+               vmovdqu %ymm3, (6 * 16)(%rdx);
+               leaq (8 * 16)(%rdx), %rdx;
+
+               jmp .Locb_unaligned_blk8;
+
+       .align 8
+       .Locb_unaligned_blk8_dec:
+               /* AES rounds */
+               vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               cmpl $12, %r9d;
+               jb .Locb_unaligned_blk8_dec_last;
+               vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               jz .Locb_unaligned_blk8_dec_last;
+               vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+
+               /* Last round and output handling. */
+       .Locb_unaligned_blk8_dec_last:
+               vpxor %ymm5, %ymm9, %ymm5; /* Xor src to last round key. */
+               vpxor %ymm6, %ymm9, %ymm6;
+               vpxor %ymm7, %ymm9, %ymm7;
+               vpxor %ymm8, %ymm9, %ymm4;
+               vaesdeclast %ymm5, %ymm0, %ymm0;
+               vaesdeclast %ymm6, %ymm1, %ymm1;
+               vaesdeclast %ymm7, %ymm2, %ymm2;
+               vaesdeclast %ymm4, %ymm3, %ymm3;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               vmovdqu %ymm2, (4 * 16)(%rdx);
+               vmovdqu %ymm3, (6 * 16)(%rdx);
+               leaq (8 * 16)(%rdx), %rdx;
+
+               jmp .Locb_unaligned_blk8;
+
+       /* Unaligned: Process four blocks. */
+.align 8
+.Locb_unaligned_blk4:
+       cmpq $4, %r10;
+       jb .Locb_unaligned_blk1;
+
+       leaq -4(%r8), %r8;
+       leaq -4(%r10), %r10;
+
+       leal 1(%esi), %r11d;
+       leal 2(%esi), %r12d;
+       leal 3(%esi), %r13d;
+       leal 4(%esi), %esi;
+       tzcntl %r11d, %r11d;
+       tzcntl %r12d, %r12d;
+       tzcntl %r13d, %r13d;
+       tzcntl %esi, %eax;
+       shll $4, %r11d;
+       shll $4, %r12d;
+       shll $4, %r13d;
+       shll $4, %eax;
+
+       vpxor (%r14, %r11), %xmm15, %xmm5;
+       vpxor (%r14, %r12), %xmm5, %xmm6;
+       vinserti128 $1, %xmm6, %ymm5, %ymm5;
+       vpxor (%r14, %r13), %xmm6, %xmm7;
+       vpxor (%r14, %rax), %xmm7, %xmm15;
+       vinserti128 $1, %xmm15, %ymm7, %ymm6;
+
+       vpxor (0 * 16)(%rcx), %ymm5, %ymm0;
+       vpxor (2 * 16)(%rcx), %ymm6, %ymm1;
+       leaq (4 * 16)(%rcx), %rcx;
+
+       testl %r15d, %r15d;
+       jz .Locb_unaligned_blk4_dec;
+               /* AES rounds */
+               vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               cmpl $12, %r9d;
+               jb .Locb_unaligned_blk4_enc_last;
+               vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               jz .Locb_unaligned_blk4_enc_last;
+               vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+
+             /* Last round and output handling. */
+       .Locb_unaligned_blk4_enc_last:
+               vmovdqa (14 * 16)(%rsp), %ymm8;
+               vpxor %ymm5, %ymm8, %ymm5; /* Xor src to last round key. */
+               vpxor %ymm6, %ymm8, %ymm6;
+               vaesenclast %ymm5, %ymm0, %ymm0;
+               vaesenclast %ymm6, %ymm1, %ymm1;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               leaq (4 * 16)(%rdx), %rdx;
+
+               jmp .Locb_unaligned_blk1;
+
+       .align 8
+       .Locb_unaligned_blk4_dec:
+               /* AES rounds */
+               vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               cmpl $12, %r9d;
+               jb .Locb_unaligned_blk4_dec_last;
+               vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               jz .Locb_unaligned_blk4_dec_last;
+               vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+
+             /* Last round and output handling. */
+       .Locb_unaligned_blk4_dec_last:
+               vmovdqa (14 * 16)(%rsp), %ymm8;
+               vpxor %ymm5, %ymm8, %ymm5; /* Xor src to last round key. */
+               vpxor %ymm6, %ymm8, %ymm6;
+               vaesdeclast %ymm5, %ymm0, %ymm0;
+               vaesdeclast %ymm6, %ymm1, %ymm1;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               leaq (4 * 16)(%rdx), %rdx;
+
+       /* Unaligned: Process one block per loop. */
+.align 8
+.Locb_unaligned_blk1:
+       cmpq $1, %r10;
+       jb .Lunaligned_ocb_done;
+
+       leaq -1(%r8), %r8;
+       leaq -1(%r10), %r10;
+
+       leal 1(%esi), %esi;
+       tzcntl %esi, %r11d;
+       shll $4, %r11d;
+       vpxor (%r14, %r11), %xmm15, %xmm15;
+       vpxor (%rcx), %xmm15, %xmm0;
+       leaq 16(%rcx), %rcx;
+
+       testl %r15d, %r15d;
+       jz .Locb_unaligned_blk1_dec;
+               /* AES rounds. */
+               vaesenc (1 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (2 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (3 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (4 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (5 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (6 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (7 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (8 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (9 * 16)(%rdi), %xmm0, %xmm0;
+               cmpl $12, %r9d;
+               jb .Locb_unaligned_blk1_enc_last;
+               vaesenc (10 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (11 * 16)(%rdi), %xmm0, %xmm0;
+               jz .Locb_unaligned_blk1_enc_last;
+               vaesenc (12 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (13 * 16)(%rdi), %xmm0, %xmm0;
+
+               /* Last round and output handling. */
+       .Locb_unaligned_blk1_enc_last:
+               vpxor (14 * 16)(%rsp), %xmm15, %xmm1;
+               vaesenclast %xmm1, %xmm0, %xmm0;
+               vmovdqu %xmm0, (%rdx);
+               leaq 16(%rdx), %rdx;
+
+               jmp .Locb_unaligned_blk1;
+
+       .align 8
+       .Locb_unaligned_blk1_dec:
+               /* AES rounds. */
+               vaesdec (1 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (2 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (3 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (4 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (5 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (6 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (7 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (8 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (9 * 16)(%rdi), %xmm0, %xmm0;
+               cmpl $12, %r9d;
+               jb .Locb_unaligned_blk1_dec_last;
+               vaesdec (10 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (11 * 16)(%rdi), %xmm0, %xmm0;
+               jz .Locb_unaligned_blk1_dec_last;
+               vaesdec (12 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (13 * 16)(%rdi), %xmm0, %xmm0;
+
+               /* Last round and output handling. */
+       .Locb_unaligned_blk1_dec_last:
+               vpxor (14 * 16)(%rsp), %xmm15, %xmm1;
+               vaesdeclast %xmm1, %xmm0, %xmm0;
+               vmovdqu %xmm0, (%rdx);
+               leaq 16(%rdx), %rdx;
+
+               jmp .Locb_unaligned_blk1;
+
+.align 8
+.Lunaligned_ocb_done:
+       cmpq $1, %r8;
+       jb .Ldone_ocb;
+
+       /* Short buffers do not benefit from L-array optimization. */
+       movq %r8, %r10;
+       cmpq $16, %r8;
+       jb .Locb_unaligned_blk8;
+
+       vinserti128 $1, %xmm15, %ymm15, %ymm15;
+
+       /* Prepare L-array optimization.
+        * Since nblk is aligned to 16, offsets will have following
+        * construction:
+        *  - block1 = ntz{0} = offset ^ L[0]
+        *  - block2 = ntz{1} = offset ^ L[0] ^ L[1]
+        *  - block3 = ntz{0} = offset ^ L[1]
+        *  - block4 = ntz{2} = offset ^ L[1] ^ L[2]
+        *  - block5 = ntz{0} = offset ^ L[0] ^ L[1] ^ L[2]
+        *  - block6 = ntz{1} = offset ^ L[0] ^ L[2]
+        *  - block7 = ntz{0} = offset ^ L[2]
+        *  - block8 = ntz{3} = offset ^ L[2] ^ L[3]
+        *  - block9 = ntz{0} = offset ^ L[0] ^ L[2] ^ L[3]
+        *  - block10 = ntz{1} = offset ^ L[0] ^ L[1] ^ L[2] ^ L[3]
+        *  - block11 = ntz{0} = offset ^ L[1] ^ L[2] ^ L[3]
+        *  - block12 = ntz{2} = offset ^ L[1] ^ L[3]
+        *  - block13 = ntz{0} = offset ^ L[0] ^ L[1] ^ L[3]
+        *  - block14 = ntz{1} = offset ^ L[0] ^ L[3]
+        *  - block15 = ntz{0} = offset ^ L[3]
+        *  - block16 = ntz{x} = offset ^ L[3] ^ L[ntz{x}]
+        */
+       vmovdqu (0 * 16)(%r14), %xmm0;
+       vmovdqu (1 * 16)(%r14), %xmm1;
+       vmovdqu (2 * 16)(%r14), %xmm2;
+       vmovdqu (3 * 16)(%r14), %xmm3;
+       vpxor %xmm0, %xmm1, %xmm4; /* L[0] ^ L[1] */
+       vpxor %xmm0, %xmm2, %xmm5; /* L[0] ^ L[2] */
+       vpxor %xmm0, %xmm3, %xmm6; /* L[0] ^ L[3] */
+       vpxor %xmm1, %xmm2, %xmm7; /* L[1] ^ L[2] */
+       vpxor %xmm1, %xmm3, %xmm8; /* L[1] ^ L[3] */
+       vpxor %xmm2, %xmm3, %xmm9; /* L[2] ^ L[3] */
+       vpxor %xmm4, %xmm2, %xmm10; /* L[0] ^ L[1] ^ L[2] */
+       vpxor %xmm5, %xmm3, %xmm11; /* L[0] ^ L[2] ^ L[3] */
+       vpxor %xmm7, %xmm3, %xmm12; /* L[1] ^ L[2] ^ L[3] */
+       vpxor %xmm0, %xmm8, %xmm13; /* L[0] ^ L[1] ^ L[3] */
+       vpxor %xmm4, %xmm9, %xmm14; /* L[0] ^ L[1] ^ L[2] ^ L[3] */
+       vinserti128 $1, %xmm4, %ymm0, %ymm0;
+       vinserti128 $1, %xmm7, %ymm1, %ymm1;
+       vinserti128 $1, %xmm5, %ymm10, %ymm10;
+       vinserti128 $1, %xmm9, %ymm2, %ymm2;
+       vinserti128 $1, %xmm14, %ymm11, %ymm11;
+       vinserti128 $1, %xmm8, %ymm12, %ymm12;
+       vinserti128 $1, %xmm6, %ymm13, %ymm13;
+       vmovdqa %ymm0,  (0 * 16)(%rsp);
+       vmovdqa %ymm1,  (2 * 16)(%rsp);
+       vmovdqa %ymm10, (4 * 16)(%rsp);
+       vmovdqa %ymm2,  (6 * 16)(%rsp);
+       vmovdqa %ymm11, (8 * 16)(%rsp);
+       vmovdqa %ymm12, (10 * 16)(%rsp);
+       vmovdqa %ymm13, (12 * 16)(%rsp);
+
+       /* Aligned: Process 16 blocks per loop. */
+.align 8
+.Locb_aligned_blk16:
+       cmpq $16, %r8;
+       jb .Locb_aligned_blk8;
+
+       leaq -16(%r8), %r8;
+
+       leal 16(%esi), %esi;
+       tzcntl %esi, %eax;
+       shll $4, %eax;
+
+       vpxor (0 * 16)(%rsp), %ymm15, %ymm8;
+       vpxor (2 * 16)(%rsp), %ymm15, %ymm9;
+       vpxor (4 * 16)(%rsp), %ymm15, %ymm10;
+       vpxor (6 * 16)(%rsp), %ymm15, %ymm11;
+       vpxor (8 * 16)(%rsp), %ymm15, %ymm12;
+
+       vpxor (3 * 16)(%r14), %xmm15, %xmm13; /* offset ^ first key ^ L[3] */
+       vpxor (%r14, %rax), %xmm13, %xmm14; /* offset ^ first key ^ L[3] ^ L[ntz{nblk+16}] */
+       vinserti128 $1, %xmm14, %ymm13, %ymm14;
+
+       vpxor (10 * 16)(%rsp), %ymm15, %ymm13;
+       vpxor (14 * 16)(%rcx), %ymm14, %ymm7;
+
+       vpxor (0 * 16)(%rcx), %ymm8, %ymm0;
+       vpxor (2 * 16)(%rcx), %ymm9, %ymm1;
+       vpxor (4 * 16)(%rcx), %ymm10, %ymm2;
+       vpxor (6 * 16)(%rcx), %ymm11, %ymm3;
+       vpxor (8 * 16)(%rcx), %ymm12, %ymm4;
+       vpxor (10 * 16)(%rcx), %ymm13, %ymm5;
+       vmovdqa %ymm13, (16 * 16)(%rsp);
+       vpxor (12 * 16)(%rsp), %ymm15, %ymm13;
+       vpxor (12 * 16)(%rcx), %ymm13, %ymm6;
+       vmovdqa %ymm13, (18 * 16)(%rsp);
+
+       leaq (16 * 16)(%rcx), %rcx;
+
+       vperm2i128 $0x11, %ymm14, %ymm14, %ymm15;
+
+       testl %r15d, %r15d;
+       jz .Locb_aligned_blk16_dec;
+               /* AES rounds */
+               vbroadcasti128 (1 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               cmpl $12, %r9d;
+               jb .Locb_aligned_blk16_enc_last;
+               vbroadcasti128 (10 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               jz .Locb_aligned_blk16_enc_last;
+               vbroadcasti128 (12 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm13;
+               VAESENC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+
+               /* Last round and output handling. */
+       .Locb_aligned_blk16_enc_last:
+               vmovdqa (14 * 16)(%rsp), %ymm13;
+               vpxor %ymm8, %ymm13, %ymm8;
+               vpxor %ymm9, %ymm13, %ymm9;
+               vpxor %ymm10, %ymm13, %ymm10;
+               vpxor %ymm11, %ymm13, %ymm11;
+               vaesenclast %ymm8, %ymm0, %ymm0;
+               vaesenclast %ymm9, %ymm1, %ymm1;
+               vaesenclast %ymm10, %ymm2, %ymm2;
+               vaesenclast %ymm11, %ymm3, %ymm3;
+               vpxor %ymm12, %ymm13, %ymm12;
+               vpxor (16 * 16)(%rsp), %ymm13, %ymm8;
+               vpxor (18 * 16)(%rsp), %ymm13, %ymm9;
+               vpxor %ymm14, %ymm13, %ymm13;
+               vaesenclast %ymm12, %ymm4, %ymm4;
+               vaesenclast %ymm8, %ymm5, %ymm5;
+               vaesenclast %ymm9, %ymm6, %ymm6;
+               vaesenclast %ymm13, %ymm7, %ymm7;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               vmovdqu %ymm2, (4 * 16)(%rdx);
+               vmovdqu %ymm3, (6 * 16)(%rdx);
+               vmovdqu %ymm4, (8 * 16)(%rdx);
+               vmovdqu %ymm5, (10 * 16)(%rdx);
+               vmovdqu %ymm6, (12 * 16)(%rdx);
+               vmovdqu %ymm7, (14 * 16)(%rdx);
+               leaq (16 * 16)(%rdx), %rdx;
+
+               jmp .Locb_aligned_blk16;
+
+       .align 8
+       .Locb_aligned_blk16_dec:
+               /* AES rounds */
+               vbroadcasti128 (1 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               cmpl $12, %r9d;
+               jb .Locb_aligned_blk16_dec_last;
+               vbroadcasti128 (10 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               jz .Locb_aligned_blk16_dec_last;
+               vbroadcasti128 (12 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm13;
+               VAESDEC8(%ymm13, %ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7);
+
+               /* Last round and output handling. */
+       .Locb_aligned_blk16_dec_last:
+               vmovdqa (14 * 16)(%rsp), %ymm13;
+               vpxor %ymm8, %ymm13, %ymm8;
+               vpxor %ymm9, %ymm13, %ymm9;
+               vpxor %ymm10, %ymm13, %ymm10;
+               vpxor %ymm11, %ymm13, %ymm11;
+               vaesdeclast %ymm8, %ymm0, %ymm0;
+               vaesdeclast %ymm9, %ymm1, %ymm1;
+               vaesdeclast %ymm10, %ymm2, %ymm2;
+               vaesdeclast %ymm11, %ymm3, %ymm3;
+               vpxor %ymm12, %ymm13, %ymm12;
+               vpxor (16 * 16)(%rsp), %ymm13, %ymm8;
+               vpxor (18 * 16)(%rsp), %ymm13, %ymm9;
+               vpxor %ymm14, %ymm13, %ymm13;
+               vaesdeclast %ymm12, %ymm4, %ymm4;
+               vaesdeclast %ymm8, %ymm5, %ymm5;
+               vaesdeclast %ymm9, %ymm6, %ymm6;
+               vaesdeclast %ymm13, %ymm7, %ymm7;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               vmovdqu %ymm2, (4 * 16)(%rdx);
+               vmovdqu %ymm3, (6 * 16)(%rdx);
+               vmovdqu %ymm4, (8 * 16)(%rdx);
+               vmovdqu %ymm5, (10 * 16)(%rdx);
+               vmovdqu %ymm6, (12 * 16)(%rdx);
+               vmovdqu %ymm7, (14 * 16)(%rdx);
+               leaq (16 * 16)(%rdx), %rdx;
+
+               jmp .Locb_aligned_blk16;
+
+       /* Aligned: Process trailing eight blocks. */
+.align 8
+.Locb_aligned_blk8:
+       cmpq $8, %r8;
+       jb .Locb_aligned_done;
+
+       leaq -8(%r8), %r8;
+
+       leal 8(%esi), %esi;
+       tzcntl %esi, %eax;
+       shll $4, %eax;
+
+       vpxor (0 * 16)(%rsp), %ymm15, %ymm5;
+       vpxor (2 * 16)(%rsp), %ymm15, %ymm6;
+       vpxor (4 * 16)(%rsp), %ymm15, %ymm7;
+
+       vpxor (2 * 16)(%r14), %xmm15, %xmm13; /* offset ^ first key ^ L[2] */
+       vpxor (%r14, %rax), %xmm13, %xmm14; /* offset ^ first key ^ L[2] ^ L[ntz{nblk+8}] */
+       vinserti128 $1, %xmm14, %ymm13, %ymm14;
+
+       vpxor (0 * 16)(%rcx), %ymm5, %ymm0;
+       vpxor (2 * 16)(%rcx), %ymm6, %ymm1;
+       vpxor (4 * 16)(%rcx), %ymm7, %ymm2;
+       vpxor (6 * 16)(%rcx), %ymm14, %ymm3;
+       leaq (8 * 16)(%rcx), %rcx;
+
+       vperm2i128 $0x11, %ymm14, %ymm14, %ymm15;
+
+       vmovdqa (14 * 16)(%rsp), %ymm8;
+
+       testl %r15d, %r15d;
+       jz .Locb_aligned_blk8_dec;
+               /* AES rounds */
+               vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               cmpl $12, %r9d;
+               jb .Locb_aligned_blk8_enc_last;
+               vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               jz .Locb_aligned_blk8_enc_last;
+               vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+               VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+
+               /* Last round and output handling. */
+       .Locb_aligned_blk8_enc_last:
+               vpxor %ymm5, %ymm8, %ymm5;
+               vpxor %ymm6, %ymm8, %ymm6;
+               vpxor %ymm7, %ymm8, %ymm7;
+               vpxor %ymm14, %ymm8, %ymm4;
+               vaesenclast %ymm5, %ymm0, %ymm0;
+               vaesenclast %ymm6, %ymm1, %ymm1;
+               vaesenclast %ymm7, %ymm2, %ymm2;
+               vaesenclast %ymm4, %ymm3, %ymm3;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               vmovdqu %ymm2, (4 * 16)(%rdx);
+               vmovdqu %ymm3, (6 * 16)(%rdx);
+               leaq (8 * 16)(%rdx), %rdx;
+
+               jmp .Locb_aligned_done;
+
+       .align 8
+       .Locb_aligned_blk8_dec:
+               /* AES rounds */
+               vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               cmpl $12, %r9d;
+               jb .Locb_aligned_blk8_dec_last;
+               vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               jz .Locb_aligned_blk8_dec_last;
+               vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+               VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+               vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+               /* Last round and output handling. */
+       .Locb_aligned_blk8_dec_last:
+               vpxor %ymm5, %ymm8, %ymm5;
+               vpxor %ymm6, %ymm8, %ymm6;
+               vpxor %ymm7, %ymm8, %ymm7;
+               vpxor %ymm14, %ymm8, %ymm4;
+               vaesdeclast %ymm5, %ymm0, %ymm0;
+               vaesdeclast %ymm6, %ymm1, %ymm1;
+               vaesdeclast %ymm7, %ymm2, %ymm2;
+               vaesdeclast %ymm4, %ymm3, %ymm3;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               vmovdqu %ymm2, (4 * 16)(%rdx);
+               vmovdqu %ymm3, (6 * 16)(%rdx);
+               leaq (8 * 16)(%rdx), %rdx;
+
+.align 8
+.Locb_aligned_done:
+       /* Burn stack. */
+       vpxor %ymm0, %ymm0, %ymm0;
+       vmovdqa %ymm0, (0 * 16)(%rsp);
+       vmovdqa %ymm0, (2 * 16)(%rsp);
+       vmovdqa %ymm0, (4 * 16)(%rsp);
+       vmovdqa %ymm0, (6 * 16)(%rsp);
+       vmovdqa %ymm0, (8 * 16)(%rsp);
+       vmovdqa %ymm0, (10 * 16)(%rsp);
+       vmovdqa %ymm0, (12 * 16)(%rsp);
+       vmovdqa %ymm0, (16 * 16)(%rsp);
+       vmovdqa %ymm0, (18 * 16)(%rsp);
+
+       /* Handle tailing 1…7 blocks in nblk-unaligned loop. */
+       movq %r8, %r10;
+       cmpq $1, %r8;
+       jnb .Locb_unaligned_blk8;
+
+.align 8
+.Ldone_ocb:
+       movq 16(%rbp), %r14; /* offset ptr. */
+       vpxor (0 * 16)(%rdi), %xmm15, %xmm15; /* offset ^ first key ^ first key */
+       vmovdqu %xmm15, (%r14); /* Store offset. */
+
+       /* Handle decryption checksumming. */
+
+       testl %r15d, %r15d;
+       jnz .Locb_dec_checksum_done;
+       movq 24(%rbp), %rax; /* checksum ptr. */
+       movq (STACK_REGS_POS + 4 * 8)(%rsp), %r10;
+       movq (STACK_REGS_POS + 5 * 8)(%rsp), %r11;
+       call _gcry_vaes_avx2_ocb_checksum;
+.Locb_dec_checksum_done:
+
+       /* Burn stack. */
+       vpxor %ymm0, %ymm0, %ymm0;
+       vmovdqa %ymm0, (14 * 16)(%rsp);
+
+       vzeroall;
+
+       movq (STACK_REGS_POS + 0 * 8)(%rsp), %r12;
+       CFI_RESTORE(%r12);
+       movq (STACK_REGS_POS + 1 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r13);
+       movq (STACK_REGS_POS + 2 * 8)(%rsp), %r14;
+       CFI_RESTORE(%r14);
+       movq (STACK_REGS_POS + 3 * 8)(%rsp), %r15;
+       CFI_RESTORE(%r15);
+
+       leave;
+       CFI_LEAVE();
+       ret_spec_stop
+
+#undef STACK_REGS_POS
+#undef STACK_ALLOC
+
+       CFI_ENDPROC();
+ELF(.size _gcry_vaes_avx2_ocb_crypt_amd64,.-_gcry_vaes_avx2_ocb_crypt_amd64)
+
+/**********************************************************************
+  CTR-mode encryption
+ **********************************************************************/
+ELF(.type _gcry_vaes_avx2_xts_crypt_amd64,@function)
+.globl _gcry_vaes_avx2_xts_crypt_amd64
+_gcry_vaes_avx2_xts_crypt_amd64:
+       /* input:
+        *      %rdi: round keys
+        *      %rsi: tweak
+        *      %rdx: dst
+        *      %rcx: src
+        *      %r8:  nblocks
+        *      %r9:  nrounds
+        *      8(%rsp): encrypt
+        */
+       CFI_STARTPROC();
+
+       movl 8(%rsp), %eax;
+
+#define tweak_clmul(shift, out, tweak, hi_tweak, tmp1, tmp2) \
+       vpsrld $(32-(shift)), hi_tweak, tmp2; \
+       vpsllq $(shift), tweak, out; \
+       vpclmulqdq $0, .Lxts_gfmul_clmul rRIP, tmp2, tmp1; \
+       vpunpckhqdq tmp2, tmp1, tmp1; \
+       vpxor tmp1, out, out;
+
+       /* Prepare tweak. */
+       vmovdqu (%rsi), %xmm15;
+       vpshufb .Lxts_high_bit_shuf rRIP, %xmm15, %xmm13;
+       tweak_clmul(1, %xmm11, %xmm15, %xmm13, %xmm0, %xmm1);
+       vinserti128 $1, %xmm11, %ymm15, %ymm15; /* tweak:tweak1 */
+       vpshufb .Lxts_high_bit_shuf rRIP, %ymm15, %ymm13;
+
+       cmpq $8, %r8;
+       jb .Lxts_crypt_blk4;
+
+       /* Process eight blocks per loop. */
+       leaq -8(%r8), %r8;
+
+       vmovdqa %ymm15, %ymm5;
+       tweak_clmul(2, %ymm6, %ymm15, %ymm13, %ymm0, %ymm1);
+       tweak_clmul(4, %ymm7, %ymm15, %ymm13, %ymm0, %ymm1);
+       tweak_clmul(6, %ymm8, %ymm15, %ymm13, %ymm0, %ymm1);
+       tweak_clmul(8, %ymm15, %ymm15, %ymm13, %ymm0, %ymm1);
+       vpshufb .Lxts_high_bit_shuf rRIP, %ymm15, %ymm13;
+
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+       vpxor (0 * 16)(%rcx), %ymm5, %ymm0;
+       vpxor (2 * 16)(%rcx), %ymm6, %ymm1;
+       vpxor (4 * 16)(%rcx), %ymm7, %ymm2;
+       vpxor (6 * 16)(%rcx), %ymm8, %ymm3;
+
+       leaq (8 * 16)(%rcx), %rcx;
+
+.align 8
+.Lxts_crypt_blk8_loop:
+       cmpq $8, %r8;
+       jb .Lxts_crypt_blk8_tail;
+               leaq -8(%r8), %r8;
+
+               testl %eax, %eax;
+               jz .Lxts_dec_blk8;
+                       /* AES rounds */
+                       XOR4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                         vmovdqa %ymm15, %ymm9;
+                         tweak_clmul(2, %ymm10, %ymm15, %ymm13, %ymm12, %ymm14);
+                         tweak_clmul(4, %ymm11, %ymm15, %ymm13, %ymm12, %ymm14);
+                       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+                       cmpl $12, %r9d;
+                       jb .Lxts_enc_blk8_last;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+                       jz .Lxts_enc_blk8_last;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+                       /* Last round and output handling. */
+               .Lxts_enc_blk8_last:
+                       vpxor %ymm4, %ymm5, %ymm5; /* Xor tweak to last round key. */
+                       vpxor %ymm4, %ymm6, %ymm6;
+                       vpxor %ymm4, %ymm7, %ymm7;
+                       vpxor %ymm4, %ymm8, %ymm4;
+                         tweak_clmul(6, %ymm8, %ymm15, %ymm13, %ymm12, %ymm14);
+                         tweak_clmul(8, %ymm15, %ymm15, %ymm13, %ymm12, %ymm14);
+                       vpshufb .Lxts_high_bit_shuf rRIP, %ymm15, %ymm13;
+                       vaesenclast %ymm5, %ymm0, %ymm0;
+                       vaesenclast %ymm6, %ymm1, %ymm1;
+                       vaesenclast %ymm7, %ymm2, %ymm2;
+                       vaesenclast %ymm4, %ymm3, %ymm3;
+
+                       vmovdqu %ymm0, (0 * 16)(%rdx);
+                       vmovdqu %ymm1, (2 * 16)(%rdx);
+                       vmovdqu %ymm2, (4 * 16)(%rdx);
+                       vmovdqu %ymm3, (6 * 16)(%rdx);
+                       leaq (8 * 16)(%rdx), %rdx;
+
+                       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+                       vpxor (0 * 16)(%rcx), %ymm9, %ymm0;
+                       vpxor (2 * 16)(%rcx), %ymm10, %ymm1;
+                       vpxor (4 * 16)(%rcx), %ymm11, %ymm2;
+                       vpxor (6 * 16)(%rcx), %ymm8, %ymm3;
+
+                         vmovdqa %ymm9, %ymm5;
+                         vmovdqa %ymm10, %ymm6;
+                         vmovdqa %ymm11, %ymm7;
+
+                       leaq (8 * 16)(%rcx), %rcx;
+
+                       jmp .Lxts_crypt_blk8_loop;
+
+               .align 8
+               .Lxts_dec_blk8:
+                       /* AES rounds */
+                       XOR4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                         vmovdqa %ymm15, %ymm9;
+                         tweak_clmul(2, %ymm10, %ymm15, %ymm13, %ymm12, %ymm14);
+                         tweak_clmul(4, %ymm11, %ymm15, %ymm13, %ymm12, %ymm14);
+                       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+                       cmpl $12, %r9d;
+                       jb .Lxts_dec_blk8_last;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+                       jz .Lxts_dec_blk8_last;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+                       /* Last round and output handling. */
+               .Lxts_dec_blk8_last:
+                       vpxor %ymm4, %ymm5, %ymm5; /* Xor tweak to last round key. */
+                       vpxor %ymm4, %ymm6, %ymm6;
+                       vpxor %ymm4, %ymm7, %ymm7;
+                       vpxor %ymm4, %ymm8, %ymm4;
+                         tweak_clmul(6, %ymm8, %ymm15, %ymm13, %ymm12, %ymm14);
+                         tweak_clmul(8, %ymm15, %ymm15, %ymm13, %ymm12, %ymm14);
+                       vpshufb .Lxts_high_bit_shuf rRIP, %ymm15, %ymm13;
+                       vaesdeclast %ymm5, %ymm0, %ymm0;
+                       vaesdeclast %ymm6, %ymm1, %ymm1;
+                       vaesdeclast %ymm7, %ymm2, %ymm2;
+                       vaesdeclast %ymm4, %ymm3, %ymm3;
+
+                       vmovdqu %ymm0, (0 * 16)(%rdx);
+                       vmovdqu %ymm1, (2 * 16)(%rdx);
+                       vmovdqu %ymm2, (4 * 16)(%rdx);
+                       vmovdqu %ymm3, (6 * 16)(%rdx);
+                       leaq (8 * 16)(%rdx), %rdx;
+
+                       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+                       vpxor (0 * 16)(%rcx), %ymm9, %ymm0;
+                       vpxor (2 * 16)(%rcx), %ymm10, %ymm1;
+                       vpxor (4 * 16)(%rcx), %ymm11, %ymm2;
+                       vpxor (6 * 16)(%rcx), %ymm8, %ymm3;
+
+                         vmovdqa %ymm9, %ymm5;
+                         vmovdqa %ymm10, %ymm6;
+                         vmovdqa %ymm11, %ymm7;
+
+                       leaq (8 * 16)(%rcx), %rcx;
+
+                       jmp .Lxts_crypt_blk8_loop;
+
+       .align 8
+       .Lxts_crypt_blk8_tail:
+               testl %eax, %eax;
+               jz .Lxts_dec_tail_blk8;
+                       /* AES rounds */
+                       XOR4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+                       cmpl $12, %r9d;
+                       jb .Lxts_enc_blk8_tail_last;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+                       jz .Lxts_enc_blk8_tail_last;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+                       VAESENC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+                       /* Last round and output handling. */
+               .Lxts_enc_blk8_tail_last:
+                       vpxor %ymm4, %ymm5, %ymm5; /* Xor tweak to last round key. */
+                       vpxor %ymm4, %ymm6, %ymm6;
+                       vpxor %ymm4, %ymm7, %ymm7;
+                       vpxor %ymm4, %ymm8, %ymm4;
+                       vaesenclast %ymm5, %ymm0, %ymm0;
+                       vaesenclast %ymm6, %ymm1, %ymm1;
+                       vaesenclast %ymm7, %ymm2, %ymm2;
+                       vaesenclast %ymm4, %ymm3, %ymm3;
+                       vmovdqu %ymm0, (0 * 16)(%rdx);
+                       vmovdqu %ymm1, (2 * 16)(%rdx);
+                       vmovdqu %ymm2, (4 * 16)(%rdx);
+                       vmovdqu %ymm3, (6 * 16)(%rdx);
+                       leaq (8 * 16)(%rdx), %rdx;
+
+                       jmp .Lxts_crypt_blk4;
+
+               .align 8
+               .Lxts_dec_tail_blk8:
+                       /* AES rounds */
+                       XOR4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+                       cmpl $12, %r9d;
+                       jb .Lxts_dec_blk8_tail_last;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+                       jz .Lxts_dec_blk8_tail_last;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+                       VAESDEC4(%ymm4, %ymm0, %ymm1, %ymm2, %ymm3);
+                       vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+                       /* Last round and output handling. */
+               .Lxts_dec_blk8_tail_last:
+                       vpxor %ymm4, %ymm5, %ymm5; /* Xor tweak to last round key. */
+                       vpxor %ymm4, %ymm6, %ymm6;
+                       vpxor %ymm4, %ymm7, %ymm7;
+                       vpxor %ymm4, %ymm8, %ymm4;
+                       vaesdeclast %ymm5, %ymm0, %ymm0;
+                       vaesdeclast %ymm6, %ymm1, %ymm1;
+                       vaesdeclast %ymm7, %ymm2, %ymm2;
+                       vaesdeclast %ymm4, %ymm3, %ymm3;
+                       vmovdqu %ymm0, (0 * 16)(%rdx);
+                       vmovdqu %ymm1, (2 * 16)(%rdx);
+                       vmovdqu %ymm2, (4 * 16)(%rdx);
+                       vmovdqu %ymm3, (6 * 16)(%rdx);
+                       leaq (8 * 16)(%rdx), %rdx;
+
+       /* Handle trailing four blocks. */
+.align 8
+.Lxts_crypt_blk4:
+       /* Try exit early as typically input length is large power of 2. */
+       cmpq $0, %r8;
+       jb .Ldone_xts_crypt;
+       cmpq $4, %r8;
+       jb .Lxts_crypt_blk1;
+
+       leaq -4(%r8), %r8;
+
+       vmovdqa %ymm15, %ymm5;
+       tweak_clmul(2, %ymm6, %ymm15, %ymm13, %ymm0, %ymm1);
+       tweak_clmul(4, %ymm15, %ymm15, %ymm13, %ymm0, %ymm1);
+       vpshufb .Lxts_high_bit_shuf rRIP, %ymm15, %ymm13;
+
+       vbroadcasti128 (0 * 16)(%rdi), %ymm4;
+       vpxor (0 * 16)(%rcx), %ymm5, %ymm0;
+       vpxor (2 * 16)(%rcx), %ymm6, %ymm1;
+
+       leaq (4 * 16)(%rcx), %rcx;
+
+       testl %eax, %eax;
+       jz .Lxts_dec_blk4;
+               /* AES rounds */
+               XOR2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+               cmpl $12, %r9d;
+               jb .Lxts_enc_blk4_last;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+               jz .Lxts_enc_blk4_last;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+               VAESENC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+               /* Last round and output handling. */
+       .Lxts_enc_blk4_last:
+               vpxor %ymm4, %ymm5, %ymm5; /* Xor tweak to last round key. */
+               vpxor %ymm4, %ymm6, %ymm6;
+               vaesenclast %ymm5, %ymm0, %ymm0;
+               vaesenclast %ymm6, %ymm1, %ymm1;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               leaq (4 * 16)(%rdx), %rdx;
+
+               jmp .Lxts_crypt_blk1;
+
+       .align 8
+       .Lxts_dec_blk4:
+               /* AES rounds */
+               XOR2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (1 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (2 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (3 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (4 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (5 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (6 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (7 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (8 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (9 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (10 * 16)(%rdi), %ymm4;
+               cmpl $12, %r9d;
+               jb .Lxts_dec_blk4_last;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (11 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (12 * 16)(%rdi), %ymm4;
+               jz .Lxts_dec_blk4_last;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (13 * 16)(%rdi), %ymm4;
+               VAESDEC2(%ymm4, %ymm0, %ymm1);
+               vbroadcasti128 (14 * 16)(%rdi), %ymm4;
+
+               /* Last round and output handling. */
+       .Lxts_dec_blk4_last:
+               vpxor %ymm4, %ymm5, %ymm5; /* Xor tweak to last round key. */
+               vpxor %ymm4, %ymm6, %ymm6;
+               vaesdeclast %ymm5, %ymm0, %ymm0;
+               vaesdeclast %ymm6, %ymm1, %ymm1;
+               vmovdqu %ymm0, (0 * 16)(%rdx);
+               vmovdqu %ymm1, (2 * 16)(%rdx);
+               leaq (4 * 16)(%rdx), %rdx;
+
+       /* Process trailing one to three blocks, one per loop. */
+.align 8
+.Lxts_crypt_blk1:
+       cmpq $1, %r8;
+       jb .Ldone_xts_crypt;
+
+       leaq -1(%r8), %r8;
+
+       vpxor (%rcx), %xmm15, %xmm0;
+       vmovdqa %xmm15, %xmm5;
+       tweak_clmul(1, %xmm15, %xmm15, %xmm13, %xmm2, %xmm3);
+       vpshufb .Lxts_high_bit_shuf rRIP, %xmm15, %xmm13;
+
+       leaq 16(%rcx), %rcx;
+
+       testl %eax, %eax;
+       jz .Lxts_dec_blk1;
+               /* AES rounds. */
+               vpxor (0 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (1 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (2 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (3 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (4 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (5 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (6 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (7 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (8 * 16)(%rdi), %xmm0, %xmm0;
+               vaesenc (9 * 16)(%rdi), %xmm0, %xmm0;
+               vmovdqa (10 * 16)(%rdi), %xmm1;
+               cmpl $12, %r9d;
+               jb .Lxts_enc_blk1_last;
+               vaesenc %xmm1, %xmm0, %xmm0;
+               vaesenc (11 * 16)(%rdi), %xmm0, %xmm0;
+               vmovdqa (12 * 16)(%rdi), %xmm1;
+               jz .Lxts_enc_blk1_last;
+               vaesenc %xmm1, %xmm0, %xmm0;
+               vaesenc (13 * 16)(%rdi), %xmm0, %xmm0;
+               vmovdqa (14 * 16)(%rdi), %xmm1;
+
+               /* Last round and output handling. */
+       .Lxts_enc_blk1_last:
+               vpxor %xmm1, %xmm5, %xmm5; /* Xor tweak to last round key. */
+               vaesenclast %xmm5, %xmm0, %xmm0;
+               vmovdqu %xmm0, (%rdx);
+               leaq 16(%rdx), %rdx;
+
+               jmp .Lxts_crypt_blk1;
+
+       .align 8
+       .Lxts_dec_blk1:
+               /* AES rounds. */
+               vpxor (0 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (1 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (2 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (3 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (4 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (5 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (6 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (7 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (8 * 16)(%rdi), %xmm0, %xmm0;
+               vaesdec (9 * 16)(%rdi), %xmm0, %xmm0;
+               vmovdqa (10 * 16)(%rdi), %xmm1;
+               cmpl $12, %r9d;
+               jb .Lxts_dec_blk1_last;
+               vaesdec %xmm1, %xmm0, %xmm0;
+               vaesdec (11 * 16)(%rdi), %xmm0, %xmm0;
+               vmovdqa (12 * 16)(%rdi), %xmm1;
+               jz .Lxts_dec_blk1_last;
+               vaesdec %xmm1, %xmm0, %xmm0;
+               vaesdec (13 * 16)(%rdi), %xmm0, %xmm0;
+               vmovdqa (14 * 16)(%rdi), %xmm1;
+
+               /* Last round and output handling. */
+       .Lxts_dec_blk1_last:
+               vpxor %xmm1, %xmm5, %xmm5; /* Xor tweak to last round key. */
+               vaesdeclast %xmm5, %xmm0, %xmm0;
+               vmovdqu %xmm0, (%rdx);
+               leaq 16(%rdx), %rdx;
+
+               jmp .Lxts_crypt_blk1;
+
+.align 8
+.Ldone_xts_crypt:
+       /* Store IV. */
+       vmovdqu %xmm15, (%rsi);
+
+       vzeroall;
+
+       xorl %eax, %eax
+       ret_spec_stop
+       CFI_ENDPROC();
+ELF(.size _gcry_vaes_avx2_xts_crypt_amd64,.-_gcry_vaes_avx2_xts_crypt_amd64)
+
+/**********************************************************************
+  constants
+ **********************************************************************/
+ELF(.type _gcry_vaes_consts,@object)
+_gcry_vaes_consts:
+.align 32
+.Lbige_addb_0:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lbige_addb_1:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+.Lbige_addb_2:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2
+.Lbige_addb_3:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3
+.Lbige_addb_4:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4
+.Lbige_addb_5:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5
+.Lbige_addb_6:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
+.Lbige_addb_7:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7
+.Lbige_addb_8:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8
+.Lbige_addb_9:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9
+.Lbige_addb_10:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10
+.Lbige_addb_11:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11
+.Lbige_addb_12:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12
+.Lbige_addb_13:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13
+.Lbige_addb_14:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14
+.Lbige_addb_15:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15
+
+.Lle_addd_0:
+       .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_1:
+       .byte 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_2:
+       .byte 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_3:
+       .byte 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_4:
+       .byte 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_5:
+       .byte 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_6:
+       .byte 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_7:
+       .byte 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_8:
+       .byte 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_9:
+       .byte 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_10:
+       .byte 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_11:
+       .byte 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_12:
+       .byte 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_13:
+       .byte 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_14:
+       .byte 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_15:
+       .byte 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+
+.Lle_addd_4_2:
+       .byte 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+       .byte 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_8_2:
+       .byte 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+       .byte 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+.Lle_addd_16_2:
+       .byte 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+       .byte 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+
+.Lxts_gfmul_clmul:
+       .long 0x00, 0x87, 0x00, 0x00
+       .long 0x00, 0x87, 0x00, 0x00
+.Lxts_high_bit_shuf:
+       .byte -1, -1, -1, -1, 12, 13, 14, 15
+       .byte 4, 5, 6, 7, -1, -1, -1, -1
+       .byte -1, -1, -1, -1, 12, 13, 14, 15
+       .byte 4, 5, 6, 7, -1, -1, -1, -1
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+ELF(.size _gcry_vaes_consts,.-_gcry_vaes_consts)
+
+#endif /* HAVE_GCC_INLINE_ASM_VAES */
+#endif /* __x86_64__ */
diff --git a/cipher/rijndael-vaes.c b/cipher/rijndael-vaes.c
new file mode 100644 (file)
index 0000000..0d7d136
--- /dev/null
@@ -0,0 +1,197 @@
+/* VAES/AVX2 accelerated AES for Libgcrypt
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "types.h"  /* for byte and u32 typedefs */
+#include "g10lib.h"
+#include "cipher.h"
+#include "bufhelp.h"
+#include "cipher-selftest.h"
+#include "rijndael-internal.h"
+#include "./cipher-internal.h"
+
+
+#ifdef USE_VAES
+
+
+# ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
+#  define ASM_FUNC_ABI __attribute__((sysv_abi))
+# else
+#  define ASM_FUNC_ABI
+# endif
+
+
+extern void _gcry_aes_aesni_prepare_decryption(RIJNDAEL_context *ctx);
+
+
+extern void _gcry_vaes_avx2_cbc_dec_amd64 (const void *keysched,
+                                          unsigned char *iv,
+                                          void *outbuf_arg,
+                                          const void *inbuf_arg,
+                                          size_t nblocks,
+                                          unsigned int nrounds) ASM_FUNC_ABI;
+
+extern void _gcry_vaes_avx2_cfb_dec_amd64 (const void *keysched,
+                                          unsigned char *iv,
+                                          void *outbuf_arg,
+                                          const void *inbuf_arg,
+                                          size_t nblocks,
+                                          unsigned int nrounds) ASM_FUNC_ABI;
+
+extern void _gcry_vaes_avx2_ctr_enc_amd64 (const void *keysched,
+                                          unsigned char *ctr,
+                                          void *outbuf_arg,
+                                          const void *inbuf_arg,
+                                          size_t nblocks,
+                                          unsigned int nrounds) ASM_FUNC_ABI;
+
+extern void _gcry_vaes_avx2_ctr32le_enc_amd64 (const void *keysched,
+                                              unsigned char *ctr,
+                                              void *outbuf_arg,
+                                              const void *inbuf_arg,
+                                              size_t nblocks,
+                                              unsigned int nrounds)
+                                               ASM_FUNC_ABI;
+
+extern void _gcry_vaes_avx2_ocb_crypt_amd64 (const void *keysched,
+                                            unsigned int blkn,
+                                            void *outbuf_arg,
+                                            const void *inbuf_arg,
+                                            size_t nblocks,
+                                            unsigned int nrounds,
+                                            unsigned char *offset,
+                                            unsigned char *checksum,
+                                            unsigned char *L_table,
+                                            int encrypt) ASM_FUNC_ABI;
+
+extern void _gcry_vaes_avx2_xts_crypt_amd64 (const void *keysched,
+                                            unsigned char *tweak,
+                                            void *outbuf_arg,
+                                            const void *inbuf_arg,
+                                            size_t nblocks,
+                                            unsigned int nrounds,
+                                            int encrypt) ASM_FUNC_ABI;
+
+
+void
+_gcry_aes_vaes_cbc_dec (void *context, unsigned char *iv,
+                       void *outbuf, const void *inbuf,
+                       size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  const void *keysched = ctx->keyschdec32;
+  unsigned int nrounds = ctx->rounds;
+
+  if (!ctx->decryption_prepared)
+    {
+      _gcry_aes_aesni_prepare_decryption (ctx);
+      ctx->decryption_prepared = 1;
+    }
+
+  _gcry_vaes_avx2_cbc_dec_amd64 (keysched, iv, outbuf, inbuf, nblocks, nrounds);
+}
+
+void
+_gcry_aes_vaes_cfb_dec (void *context, unsigned char *iv,
+                       void *outbuf, const void *inbuf,
+                       size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  const void *keysched = ctx->keyschenc32;
+  unsigned int nrounds = ctx->rounds;
+
+  _gcry_vaes_avx2_cfb_dec_amd64 (keysched, iv, outbuf, inbuf, nblocks, nrounds);
+}
+
+void
+_gcry_aes_vaes_ctr_enc (void *context, unsigned char *iv,
+                       void *outbuf, const void *inbuf,
+                       size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  const void *keysched = ctx->keyschenc32;
+  unsigned int nrounds = ctx->rounds;
+
+  _gcry_vaes_avx2_ctr_enc_amd64 (keysched, iv, outbuf, inbuf, nblocks, nrounds);
+}
+
+void
+_gcry_aes_vaes_ctr32le_enc (void *context, unsigned char *iv,
+                           void *outbuf, const void *inbuf,
+                           size_t nblocks)
+{
+  RIJNDAEL_context *ctx = context;
+  const void *keysched = ctx->keyschenc32;
+  unsigned int nrounds = ctx->rounds;
+
+  _gcry_vaes_avx2_ctr32le_enc_amd64 (keysched, iv, outbuf, inbuf, nblocks,
+                                    nrounds);
+}
+
+size_t
+_gcry_aes_vaes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                         const void *inbuf_arg, size_t nblocks,
+                         int encrypt)
+{
+  RIJNDAEL_context *ctx = (void *)&c->context.c;
+  const void *keysched = encrypt ? ctx->keyschenc32 : ctx->keyschdec32;
+  unsigned char *outbuf = outbuf_arg;
+  const unsigned char *inbuf = inbuf_arg;
+  unsigned int nrounds = ctx->rounds;
+  u64 blkn = c->u_mode.ocb.data_nblocks;
+
+  if (!encrypt && !ctx->decryption_prepared)
+    {
+      _gcry_aes_aesni_prepare_decryption (ctx);
+      ctx->decryption_prepared = 1;
+    }
+
+  c->u_mode.ocb.data_nblocks = blkn + nblocks;
+
+  _gcry_vaes_avx2_ocb_crypt_amd64 (keysched, (unsigned int)blkn, outbuf, inbuf,
+                                  nblocks, nrounds, c->u_iv.iv, c->u_ctr.ctr,
+                                  c->u_mode.ocb.L[0], encrypt);
+
+  return 0;
+}
+
+void
+_gcry_aes_vaes_xts_crypt (void *context, unsigned char *tweak,
+                         void *outbuf, const void *inbuf,
+                         size_t nblocks, int encrypt)
+{
+  RIJNDAEL_context *ctx = context;
+  const void *keysched = encrypt ? ctx->keyschenc32 : ctx->keyschdec32;
+  unsigned int nrounds = ctx->rounds;
+
+  if (!encrypt && !ctx->decryption_prepared)
+    {
+      _gcry_aes_aesni_prepare_decryption (ctx);
+      ctx->decryption_prepared = 1;
+    }
+
+  _gcry_vaes_avx2_xts_crypt_amd64 (keysched, tweak, outbuf, inbuf, nblocks,
+                                  nrounds, encrypt);
+}
+
+#endif /* USE_VAES */
index 8637195..9b96b61 100644 (file)
@@ -77,32 +77,55 @@ extern unsigned int _gcry_aes_aesni_encrypt (const RIJNDAEL_context *ctx,
 extern unsigned int _gcry_aes_aesni_decrypt (const RIJNDAEL_context *ctx,
                                              unsigned char *dst,
                                              const unsigned char *src);
-extern void _gcry_aes_aesni_cfb_enc (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_aesni_cbc_enc (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *iv, size_t nblocks,
-                                     int cbc_mac);
-extern void _gcry_aes_aesni_ctr_enc (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *ctr, size_t nblocks);
-extern void _gcry_aes_aesni_cfb_dec (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_aesni_cbc_dec (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_aesni_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
-                                       const void *inbuf_arg, size_t nblocks,
-                                       int encrypt);
-extern void _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
-                                      size_t nblocks);
+extern void _gcry_aes_aesni_cfb_enc (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_aesni_cbc_enc (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks, int cbc_mac);
+extern void _gcry_aes_aesni_ctr_enc (void *context, unsigned char *ctr,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_aesni_ctr32le_enc (void *context, unsigned char *ctr,
+                                        void *outbuf_arg,
+                                        const void *inbuf_arg, size_t nblocks);
+extern void _gcry_aes_aesni_cfb_dec (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_aesni_cbc_dec (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern size_t _gcry_aes_aesni_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                         const void *inbuf_arg, size_t nblocks,
+                                         int encrypt);
+extern size_t _gcry_aes_aesni_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
+                                        size_t nblocks);
+extern void _gcry_aes_aesni_xts_crypt (void *context, unsigned char *tweak,
+                                       void *outbuf_arg, const void *inbuf_arg,
+                                       size_t nblocks, int encrypt);
+#endif
+
+#ifdef USE_VAES
+/* VAES (AMD64) accelerated implementation of AES */
+
+extern void _gcry_aes_vaes_cfb_dec (void *context, unsigned char *iv,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+extern void _gcry_aes_vaes_cbc_dec (void *context, unsigned char *iv,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+extern void _gcry_aes_vaes_ctr_enc (void *context, unsigned char *ctr,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+extern void _gcry_aes_vaes_ctr32le_enc (void *context, unsigned char *ctr,
+                                       void *outbuf_arg, const void *inbuf_arg,
+                                       size_t nblocks);
+extern size_t _gcry_aes_vaes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                       const void *inbuf_arg, size_t nblocks,
+                                       int encrypt);
+extern void _gcry_aes_vaes_xts_crypt (void *context, unsigned char *tweak,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks, int encrypt);
 #endif
 
 #ifdef USE_SSSE3
@@ -116,32 +139,27 @@ extern unsigned int _gcry_aes_ssse3_encrypt (const RIJNDAEL_context *ctx,
 extern unsigned int _gcry_aes_ssse3_decrypt (const RIJNDAEL_context *ctx,
                                              unsigned char *dst,
                                              const unsigned char *src);
-extern void _gcry_aes_ssse3_cfb_enc (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_ssse3_cbc_enc (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *iv, size_t nblocks,
+extern void _gcry_aes_ssse3_cfb_enc (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_ssse3_cbc_enc (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks,
                                      int cbc_mac);
-extern void _gcry_aes_ssse3_ctr_enc (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *ctr, size_t nblocks);
-extern void _gcry_aes_ssse3_cfb_dec (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_ssse3_cbc_dec (RIJNDAEL_context *ctx,
-                                     unsigned char *outbuf,
-                                     const unsigned char *inbuf,
-                                     unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_ssse3_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
-                                       const void *inbuf_arg, size_t nblocks,
-                                       int encrypt);
-extern void _gcry_aes_ssse3_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
-                                      size_t nblocks);
+extern void _gcry_aes_ssse3_ctr_enc (void *context, unsigned char *ctr,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_ssse3_cfb_dec (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_ssse3_cbc_dec (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern size_t _gcry_aes_ssse3_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                         const void *inbuf_arg, size_t nblocks,
+                                         int encrypt);
+extern size_t _gcry_aes_ssse3_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
+                                        size_t nblocks);
 #endif
 
 #ifdef USE_PADLOCK
@@ -151,6 +169,7 @@ extern unsigned int _gcry_aes_padlock_encrypt (const RIJNDAEL_context *ctx,
 extern unsigned int _gcry_aes_padlock_decrypt (const RIJNDAEL_context *ctx,
                                                unsigned char *bx,
                                                const unsigned char *ax);
+extern void _gcry_aes_padlock_prepare_decryption (RIJNDAEL_context *ctx);
 #endif
 
 #ifdef USE_ARM_ASM
@@ -180,39 +199,164 @@ extern unsigned int _gcry_aes_armv8_ce_decrypt(const RIJNDAEL_context *ctx,
                                                unsigned char *dst,
                                                const unsigned char *src);
 
-extern void _gcry_aes_armv8_ce_cfb_enc (RIJNDAEL_context *ctx,
-                                        unsigned char *outbuf,
-                                        const unsigned char *inbuf,
-                                        unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_armv8_ce_cbc_enc (RIJNDAEL_context *ctx,
-                                        unsigned char *outbuf,
-                                        const unsigned char *inbuf,
-                                        unsigned char *iv, size_t nblocks,
+extern void _gcry_aes_armv8_ce_cfb_enc (void *context, unsigned char *iv,
+                                        void *outbuf_arg, const void *inbuf_arg,
+                                        size_t nblocks);
+extern void _gcry_aes_armv8_ce_cbc_enc (void *context, unsigned char *iv,
+                                        void *outbuf_arg, const void *inbuf_arg,
+                                        size_t nblocks,
                                         int cbc_mac);
-extern void _gcry_aes_armv8_ce_ctr_enc (RIJNDAEL_context *ctx,
-                                        unsigned char *outbuf,
-                                        const unsigned char *inbuf,
-                                        unsigned char *ctr, size_t nblocks);
-extern void _gcry_aes_armv8_ce_cfb_dec (RIJNDAEL_context *ctx,
-                                        unsigned char *outbuf,
-                                        const unsigned char *inbuf,
-                                        unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_armv8_ce_cbc_dec (RIJNDAEL_context *ctx,
-                                        unsigned char *outbuf,
-                                        const unsigned char *inbuf,
-                                        unsigned char *iv, size_t nblocks);
-extern void _gcry_aes_armv8_ce_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
-                                          const void *inbuf_arg, size_t nblocks,
-                                          int encrypt);
-extern void _gcry_aes_armv8_ce_ocb_auth (gcry_cipher_hd_t c,
-                                         const void *abuf_arg, size_t nblocks);
+extern void _gcry_aes_armv8_ce_ctr_enc (void *context, unsigned char *ctr,
+                                        void *outbuf_arg, const void *inbuf_arg,
+                                        size_t nblocks);
+extern void _gcry_aes_armv8_ce_ctr32le_enc (void *context, unsigned char *ctr,
+                                            void *outbuf_arg,
+                                            const void *inbuf_arg,
+                                            size_t nblocks);
+extern void _gcry_aes_armv8_ce_cfb_dec (void *context, unsigned char *iv,
+                                        void *outbuf_arg, const void *inbuf_arg,
+                                        size_t nblocks);
+extern void _gcry_aes_armv8_ce_cbc_dec (void *context, unsigned char *iv,
+                                        void *outbuf_arg, const void *inbuf_arg,
+                                        size_t nblocks);
+extern size_t _gcry_aes_armv8_ce_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                            const void *inbuf_arg, size_t nblocks,
+                                            int encrypt);
+extern size_t _gcry_aes_armv8_ce_ocb_auth (gcry_cipher_hd_t c,
+                                           const void *abuf_arg, size_t nblocks);
+extern void _gcry_aes_armv8_ce_xts_crypt (void *context, unsigned char *tweak,
+                                          void *outbuf_arg,
+                                          const void *inbuf_arg,
+                                          size_t nblocks, int encrypt);
 #endif /*USE_ARM_ASM*/
 
+#ifdef USE_PPC_CRYPTO
+/* PowerPC Crypto implementations of AES */
+extern void _gcry_aes_ppc8_setkey(RIJNDAEL_context *ctx, const byte *key);
+extern void _gcry_aes_ppc8_prepare_decryption(RIJNDAEL_context *ctx);
+
+extern unsigned int _gcry_aes_ppc8_encrypt(const RIJNDAEL_context *ctx,
+                                          unsigned char *dst,
+                                          const unsigned char *src);
+extern unsigned int _gcry_aes_ppc8_decrypt(const RIJNDAEL_context *ctx,
+                                          unsigned char *dst,
+                                          const unsigned char *src);
+
+extern void _gcry_aes_ppc8_cfb_enc (void *context, unsigned char *iv,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+extern void _gcry_aes_ppc8_cbc_enc (void *context, unsigned char *iv,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks, int cbc_mac);
+extern void _gcry_aes_ppc8_ctr_enc (void *context, unsigned char *ctr,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+extern void _gcry_aes_ppc8_cfb_dec (void *context, unsigned char *iv,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+extern void _gcry_aes_ppc8_cbc_dec (void *context, unsigned char *iv,
+                                   void *outbuf_arg, const void *inbuf_arg,
+                                   size_t nblocks);
+
+extern size_t _gcry_aes_ppc8_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                       const void *inbuf_arg, size_t nblocks,
+                                       int encrypt);
+extern size_t _gcry_aes_ppc8_ocb_auth (gcry_cipher_hd_t c,
+                                      const void *abuf_arg, size_t nblocks);
+
+extern void _gcry_aes_ppc8_xts_crypt (void *context, unsigned char *tweak,
+                                     void *outbuf_arg,
+                                     const void *inbuf_arg,
+                                     size_t nblocks, int encrypt);
+#endif /*USE_PPC_CRYPTO*/
+
+#ifdef USE_PPC_CRYPTO_WITH_PPC9LE
+/* Power9 little-endian crypto implementations of AES */
+extern unsigned int _gcry_aes_ppc9le_encrypt(const RIJNDAEL_context *ctx,
+                                           unsigned char *dst,
+                                           const unsigned char *src);
+extern unsigned int _gcry_aes_ppc9le_decrypt(const RIJNDAEL_context *ctx,
+                                           unsigned char *dst,
+                                           const unsigned char *src);
+
+extern void _gcry_aes_ppc9le_cfb_enc (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_ppc9le_cbc_enc (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks, int cbc_mac);
+extern void _gcry_aes_ppc9le_ctr_enc (void *context, unsigned char *ctr,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_ppc9le_cfb_dec (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+extern void _gcry_aes_ppc9le_cbc_dec (void *context, unsigned char *iv,
+                                     void *outbuf_arg, const void *inbuf_arg,
+                                     size_t nblocks);
+
+extern size_t _gcry_aes_ppc9le_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                         const void *inbuf_arg, size_t nblocks,
+                                         int encrypt);
+extern size_t _gcry_aes_ppc9le_ocb_auth (gcry_cipher_hd_t c,
+                                       const void *abuf_arg, size_t nblocks);
+
+extern void _gcry_aes_ppc9le_xts_crypt (void *context, unsigned char *tweak,
+                                       void *outbuf_arg,
+                                       const void *inbuf_arg,
+                                       size_t nblocks, int encrypt);
+
+extern size_t _gcry_aes_p10le_gcm_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                        const void *inbuf_arg,
+                                        size_t nblocks, int encrypt);
+#endif /*USE_PPC_CRYPTO_WITH_PPC9LE*/
+
+#ifdef USE_S390X_CRYPTO
+/* zSeries crypto implementations of AES */
+extern int _gcry_aes_s390x_setup_acceleration(RIJNDAEL_context *ctx,
+                                             unsigned int keylen,
+                                             unsigned int hwfeatures,
+                                             cipher_bulk_ops_t *bulk_ops);
+extern void _gcry_aes_s390x_setkey(RIJNDAEL_context *ctx, const byte *key);
+extern void _gcry_aes_s390x_prepare_decryption(RIJNDAEL_context *ctx);
+
+extern unsigned int _gcry_aes_s390x_encrypt(const RIJNDAEL_context *ctx,
+                                           unsigned char *dst,
+                                           const unsigned char *src);
+extern unsigned int _gcry_aes_s390x_decrypt(const RIJNDAEL_context *ctx,
+                                           unsigned char *dst,
+                                           const unsigned char *src);
+
+#endif /*USE_S390X_CRYPTO*/
+
 static unsigned int do_encrypt (const RIJNDAEL_context *ctx, unsigned char *bx,
                                 const unsigned char *ax);
 static unsigned int do_decrypt (const RIJNDAEL_context *ctx, unsigned char *bx,
                                 const unsigned char *ax);
 
+static void _gcry_aes_cfb_enc (void *context, unsigned char *iv,
+                              void *outbuf, const void *inbuf,
+                              size_t nblocks);
+static void _gcry_aes_cfb_dec (void *context, unsigned char *iv,
+                              void *outbuf_arg, const void *inbuf_arg,
+                              size_t nblocks);
+static void _gcry_aes_cbc_enc (void *context, unsigned char *iv,
+                              void *outbuf_arg, const void *inbuf_arg,
+                              size_t nblocks, int cbc_mac);
+static void _gcry_aes_cbc_dec (void *context, unsigned char *iv,
+                              void *outbuf_arg, const void *inbuf_arg,
+                              size_t nblocks);
+static void _gcry_aes_ctr_enc (void *context, unsigned char *ctr,
+                              void *outbuf_arg, const void *inbuf_arg,
+                              size_t nblocks);
+static size_t _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                  const void *inbuf_arg, size_t nblocks,
+                                  int encrypt);
+static size_t _gcry_aes_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
+                                 size_t nblocks);
+static void _gcry_aes_xts_crypt (void *context, unsigned char *tweak,
+                                void *outbuf_arg, const void *inbuf_arg,
+                                size_t nblocks, int encrypt);
 \f
 
 /* All the numbers.  */
@@ -223,15 +367,16 @@ static unsigned int do_decrypt (const RIJNDAEL_context *ctx, unsigned char *bx,
 
 /* Function prototypes.  */
 static const char *selftest(void);
+static void prepare_decryption(RIJNDAEL_context *ctx);
 
 
 \f
 /* Prefetching for encryption/decryption tables. */
-static void prefetch_table(const volatile byte *tab, size_t len)
+static inline void prefetch_table(const volatile byte *tab, size_t len)
 {
   size_t i;
 
-  for (i = 0; i < len; i += 8 * 32)
+  for (i = 0; len - i >= 8 * 32; i += 8 * 32)
     {
       (void)tab[i + 0 * 32];
       (void)tab[i + 1 * 32];
@@ -242,17 +387,37 @@ static void prefetch_table(const volatile byte *tab, size_t len)
       (void)tab[i + 6 * 32];
       (void)tab[i + 7 * 32];
     }
+  for (; i < len; i += 32)
+    {
+      (void)tab[i];
+    }
 
   (void)tab[len - 1];
 }
 
 static void prefetch_enc(void)
 {
-  prefetch_table((const void *)encT, sizeof(encT));
+  /* Modify counters to trigger copy-on-write and unsharing if physical pages
+   * of look-up table are shared between processes.  Modifying counters also
+   * causes checksums for pages to change and hint same-page merging algorithm
+   * that these pages are frequently changing.  */
+  enc_tables.counter_head++;
+  enc_tables.counter_tail++;
+
+  /* Prefetch look-up tables to cache.  */
+  prefetch_table((const void *)&enc_tables, sizeof(enc_tables));
 }
 
 static void prefetch_dec(void)
 {
+  /* Modify counters to trigger copy-on-write and unsharing if physical pages
+   * of look-up table are shared between processes.  Modifying counters also
+   * causes checksums for pages to change and hint same-page merging algorithm
+   * that these pages are frequently changing.  */
+  dec_tables.counter_head++;
+  dec_tables.counter_tail++;
+
+  /* Prefetch look-up tables to cache.  */
   prefetch_table((const void *)&dec_tables, sizeof(dec_tables));
 }
 
@@ -260,17 +425,16 @@ static void prefetch_dec(void)
 \f
 /* Perform the key setup.  */
 static gcry_err_code_t
-do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
+do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen,
+           cipher_bulk_ops_t *bulk_ops)
 {
   static int initialized = 0;
   static const char *selftest_failed = 0;
+  void (*hw_setkey)(RIJNDAEL_context *ctx, const byte *key) = NULL;
   int rounds;
   int i,j, r, t, rconpointer = 0;
   int KC;
-#if defined(USE_AESNI) || defined(USE_PADLOCK) || defined(USE_SSSE3) \
-    || defined(USE_ARM_CE)
   unsigned int hwfeatures;
-#endif
 
   /* The on-the-fly self tests are only run in non-fips mode. In fips
      mode explicit self-tests are required.  Actually the on-the-fly
@@ -308,25 +472,22 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
     return GPG_ERR_INV_KEYLEN;
 
   ctx->rounds = rounds;
-
-#if defined(USE_AESNI) || defined(USE_PADLOCK) || defined(USE_SSSE3) \
-    || defined(USE_ARM_CE)
   hwfeatures = _gcry_get_hw_features ();
-#endif
 
   ctx->decryption_prepared = 0;
-#ifdef USE_PADLOCK
-  ctx->use_padlock = 0;
-#endif
-#ifdef USE_AESNI
-  ctx->use_aesni = 0;
-#endif
-#ifdef USE_SSSE3
-  ctx->use_ssse3 = 0;
-#endif
-#ifdef USE_ARM_CE
-  ctx->use_arm_ce = 0;
-#endif
+
+  /* Setup default bulk encryption routines.  */
+  memset (bulk_ops, 0, sizeof(*bulk_ops));
+  bulk_ops->cfb_enc = _gcry_aes_cfb_enc;
+  bulk_ops->cfb_dec = _gcry_aes_cfb_dec;
+  bulk_ops->cbc_enc = _gcry_aes_cbc_enc;
+  bulk_ops->cbc_dec = _gcry_aes_cbc_dec;
+  bulk_ops->ctr_enc = _gcry_aes_ctr_enc;
+  bulk_ops->ocb_crypt = _gcry_aes_ocb_crypt;
+  bulk_ops->ocb_auth  = _gcry_aes_ocb_auth;
+  bulk_ops->xts_crypt = _gcry_aes_xts_crypt;
+
+  (void)hwfeatures;
 
   if (0)
     {
@@ -335,42 +496,148 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
 #ifdef USE_AESNI
   else if (hwfeatures & HWF_INTEL_AESNI)
     {
+      hw_setkey = _gcry_aes_aesni_do_setkey;
       ctx->encrypt_fn = _gcry_aes_aesni_encrypt;
       ctx->decrypt_fn = _gcry_aes_aesni_decrypt;
       ctx->prefetch_enc_fn = NULL;
       ctx->prefetch_dec_fn = NULL;
-      ctx->use_aesni = 1;
+      ctx->prepare_decryption = _gcry_aes_aesni_prepare_decryption;
+      ctx->use_avx = !!(hwfeatures & HWF_INTEL_AVX);
+      ctx->use_avx2 = !!(hwfeatures & HWF_INTEL_AVX2);
+
+      /* Setup AES-NI bulk encryption routines.  */
+      bulk_ops->cfb_enc = _gcry_aes_aesni_cfb_enc;
+      bulk_ops->cfb_dec = _gcry_aes_aesni_cfb_dec;
+      bulk_ops->cbc_enc = _gcry_aes_aesni_cbc_enc;
+      bulk_ops->cbc_dec = _gcry_aes_aesni_cbc_dec;
+      bulk_ops->ctr_enc = _gcry_aes_aesni_ctr_enc;
+      bulk_ops->ctr32le_enc = _gcry_aes_aesni_ctr32le_enc;
+      bulk_ops->ocb_crypt = _gcry_aes_aesni_ocb_crypt;
+      bulk_ops->ocb_auth = _gcry_aes_aesni_ocb_auth;
+      bulk_ops->xts_crypt = _gcry_aes_aesni_xts_crypt;
+
+#ifdef USE_VAES
+      if ((hwfeatures & HWF_INTEL_VAES_VPCLMUL) &&
+         (hwfeatures & HWF_INTEL_AVX2))
+       {
+         /* Setup VAES bulk encryption routines.  */
+         bulk_ops->cfb_dec = _gcry_aes_vaes_cfb_dec;
+         bulk_ops->cbc_dec = _gcry_aes_vaes_cbc_dec;
+         bulk_ops->ctr_enc = _gcry_aes_vaes_ctr_enc;
+         bulk_ops->ctr32le_enc = _gcry_aes_vaes_ctr32le_enc;
+         bulk_ops->ocb_crypt = _gcry_aes_vaes_ocb_crypt;
+         bulk_ops->xts_crypt = _gcry_aes_vaes_xts_crypt;
+       }
+#endif
     }
 #endif
 #ifdef USE_PADLOCK
-  else if (hwfeatures & HWF_PADLOCK_AES && keylen == 128/8)
+  else if ((hwfeatures & HWF_PADLOCK_AES) && keylen == 128/8)
     {
       ctx->encrypt_fn = _gcry_aes_padlock_encrypt;
       ctx->decrypt_fn = _gcry_aes_padlock_decrypt;
       ctx->prefetch_enc_fn = NULL;
       ctx->prefetch_dec_fn = NULL;
-      ctx->use_padlock = 1;
+      ctx->prepare_decryption = _gcry_aes_padlock_prepare_decryption;
       memcpy (ctx->padlockkey, key, keylen);
     }
 #endif
 #ifdef USE_SSSE3
   else if (hwfeatures & HWF_INTEL_SSSE3)
     {
+      hw_setkey = _gcry_aes_ssse3_do_setkey;
       ctx->encrypt_fn = _gcry_aes_ssse3_encrypt;
       ctx->decrypt_fn = _gcry_aes_ssse3_decrypt;
       ctx->prefetch_enc_fn = NULL;
       ctx->prefetch_dec_fn = NULL;
-      ctx->use_ssse3 = 1;
+      ctx->prepare_decryption = _gcry_aes_ssse3_prepare_decryption;
+
+      /* Setup SSSE3 bulk encryption routines.  */
+      bulk_ops->cfb_enc = _gcry_aes_ssse3_cfb_enc;
+      bulk_ops->cfb_dec = _gcry_aes_ssse3_cfb_dec;
+      bulk_ops->cbc_enc = _gcry_aes_ssse3_cbc_enc;
+      bulk_ops->cbc_dec = _gcry_aes_ssse3_cbc_dec;
+      bulk_ops->ctr_enc = _gcry_aes_ssse3_ctr_enc;
+      bulk_ops->ocb_crypt = _gcry_aes_ssse3_ocb_crypt;
+      bulk_ops->ocb_auth = _gcry_aes_ssse3_ocb_auth;
     }
 #endif
 #ifdef USE_ARM_CE
   else if (hwfeatures & HWF_ARM_AES)
     {
+      hw_setkey = _gcry_aes_armv8_ce_setkey;
       ctx->encrypt_fn = _gcry_aes_armv8_ce_encrypt;
       ctx->decrypt_fn = _gcry_aes_armv8_ce_decrypt;
       ctx->prefetch_enc_fn = NULL;
       ctx->prefetch_dec_fn = NULL;
-      ctx->use_arm_ce = 1;
+      ctx->prepare_decryption = _gcry_aes_armv8_ce_prepare_decryption;
+
+      /* Setup ARM-CE bulk encryption routines.  */
+      bulk_ops->cfb_enc = _gcry_aes_armv8_ce_cfb_enc;
+      bulk_ops->cfb_dec = _gcry_aes_armv8_ce_cfb_dec;
+      bulk_ops->cbc_enc = _gcry_aes_armv8_ce_cbc_enc;
+      bulk_ops->cbc_dec = _gcry_aes_armv8_ce_cbc_dec;
+      bulk_ops->ctr_enc = _gcry_aes_armv8_ce_ctr_enc;
+      bulk_ops->ctr32le_enc = _gcry_aes_armv8_ce_ctr32le_enc;
+      bulk_ops->ocb_crypt = _gcry_aes_armv8_ce_ocb_crypt;
+      bulk_ops->ocb_auth = _gcry_aes_armv8_ce_ocb_auth;
+      bulk_ops->xts_crypt = _gcry_aes_armv8_ce_xts_crypt;
+    }
+#endif
+#ifdef USE_PPC_CRYPTO_WITH_PPC9LE
+  else if ((hwfeatures & HWF_PPC_VCRYPTO) && (hwfeatures & HWF_PPC_ARCH_3_00))
+    {
+      hw_setkey = _gcry_aes_ppc8_setkey;
+      ctx->encrypt_fn = _gcry_aes_ppc9le_encrypt;
+      ctx->decrypt_fn = _gcry_aes_ppc9le_decrypt;
+      ctx->prefetch_enc_fn = NULL;
+      ctx->prefetch_dec_fn = NULL;
+      ctx->prepare_decryption = _gcry_aes_ppc8_prepare_decryption;
+
+      /* Setup PPC9LE bulk encryption routines.  */
+      bulk_ops->cfb_enc = _gcry_aes_ppc9le_cfb_enc;
+      bulk_ops->cfb_dec = _gcry_aes_ppc9le_cfb_dec;
+      bulk_ops->cbc_enc = _gcry_aes_ppc9le_cbc_enc;
+      bulk_ops->cbc_dec = _gcry_aes_ppc9le_cbc_dec;
+      bulk_ops->ctr_enc = _gcry_aes_ppc9le_ctr_enc;
+      bulk_ops->ocb_crypt = _gcry_aes_ppc9le_ocb_crypt;
+      bulk_ops->ocb_auth = _gcry_aes_ppc9le_ocb_auth;
+      bulk_ops->xts_crypt = _gcry_aes_ppc9le_xts_crypt;
+      if (hwfeatures & HWF_PPC_ARCH_3_10)  /* for P10 */
+        bulk_ops->gcm_crypt = _gcry_aes_p10le_gcm_crypt;
+    }
+#endif
+#ifdef USE_PPC_CRYPTO
+  else if (hwfeatures & HWF_PPC_VCRYPTO)
+    {
+      hw_setkey = _gcry_aes_ppc8_setkey;
+      ctx->encrypt_fn = _gcry_aes_ppc8_encrypt;
+      ctx->decrypt_fn = _gcry_aes_ppc8_decrypt;
+      ctx->prefetch_enc_fn = NULL;
+      ctx->prefetch_dec_fn = NULL;
+      ctx->prepare_decryption = _gcry_aes_ppc8_prepare_decryption;
+
+      /* Setup PPC8 bulk encryption routines.  */
+      bulk_ops->cfb_enc = _gcry_aes_ppc8_cfb_enc;
+      bulk_ops->cfb_dec = _gcry_aes_ppc8_cfb_dec;
+      bulk_ops->cbc_enc = _gcry_aes_ppc8_cbc_enc;
+      bulk_ops->cbc_dec = _gcry_aes_ppc8_cbc_dec;
+      bulk_ops->ctr_enc = _gcry_aes_ppc8_ctr_enc;
+      bulk_ops->ocb_crypt = _gcry_aes_ppc8_ocb_crypt;
+      bulk_ops->ocb_auth = _gcry_aes_ppc8_ocb_auth;
+      bulk_ops->xts_crypt = _gcry_aes_ppc8_xts_crypt;
+    }
+#endif
+#ifdef USE_S390X_CRYPTO
+  else if (_gcry_aes_s390x_setup_acceleration (ctx, keylen, hwfeatures,
+                                              bulk_ops))
+  {
+      hw_setkey = _gcry_aes_s390x_setkey;
+      ctx->encrypt_fn = _gcry_aes_s390x_encrypt;
+      ctx->decrypt_fn = _gcry_aes_s390x_decrypt;
+      ctx->prefetch_enc_fn = NULL;
+      ctx->prefetch_dec_fn = NULL;
+      ctx->prepare_decryption = _gcry_aes_s390x_prepare_decryption;
     }
 #endif
   else
@@ -379,26 +646,15 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
       ctx->decrypt_fn = do_decrypt;
       ctx->prefetch_enc_fn = prefetch_enc;
       ctx->prefetch_dec_fn = prefetch_dec;
+      ctx->prepare_decryption = prepare_decryption;
     }
 
   /* NB: We don't yet support Padlock hardware key generation.  */
 
-  if (0)
+  if (hw_setkey)
     {
-      ;
+      hw_setkey (ctx, key);
     }
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
-    _gcry_aes_aesni_do_setkey (ctx, key);
-#endif
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
-    _gcry_aes_ssse3_do_setkey (ctx, key);
-#endif
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
-    _gcry_aes_armv8_ce_setkey (ctx, key);
-#endif
   else
     {
       const byte *sbox = ((const byte *)encT) + 1;
@@ -503,10 +759,11 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen)
 
 
 static gcry_err_code_t
-rijndael_setkey (void *context, const byte *key, const unsigned keylen)
+rijndael_setkey (void *context, const byte *key, const unsigned keylen,
+                 cipher_bulk_ops_t *bulk_ops)
 {
   RIJNDAEL_context *ctx = context;
-  return do_setkey (ctx, key, keylen);
+  return do_setkey (ctx, key, keylen, bulk_ops);
 }
 
 
@@ -514,82 +771,52 @@ rijndael_setkey (void *context, const byte *key, const unsigned keylen)
 static void
 prepare_decryption( RIJNDAEL_context *ctx )
 {
+  const byte *sbox = ((const byte *)encT) + 1;
   int r;
 
-  if (0)
-    ;
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
-    {
-      _gcry_aes_aesni_prepare_decryption (ctx);
+  prefetch_enc();
+  prefetch_dec();
+
+  ctx->keyschdec32[0][0] = ctx->keyschenc32[0][0];
+  ctx->keyschdec32[0][1] = ctx->keyschenc32[0][1];
+  ctx->keyschdec32[0][2] = ctx->keyschenc32[0][2];
+  ctx->keyschdec32[0][3] = ctx->keyschenc32[0][3];
+
+  for (r = 1; r < ctx->rounds; r++)
+    {
+      u32 *wi = ctx->keyschenc32[r];
+      u32 *wo = ctx->keyschdec32[r];
+      u32 wt;
+
+      wt = wi[0];
+      wo[0] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0)
+             ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1)
+             ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2)
+             ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3);
+
+      wt = wi[1];
+      wo[1] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0)
+             ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1)
+             ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2)
+             ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3);
+
+      wt = wi[2];
+      wo[2] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0)
+             ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1)
+             ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2)
+             ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3);
+
+      wt = wi[3];
+      wo[3] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0)
+             ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1)
+             ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2)
+             ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3);
     }
-#endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
-    {
-      _gcry_aes_ssse3_prepare_decryption (ctx);
-    }
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
-    {
-      _gcry_aes_armv8_ce_prepare_decryption (ctx);
-    }
-#endif /*USE_SSSE3*/
-#ifdef USE_PADLOCK
-  else if (ctx->use_padlock)
-    {
-      /* Padlock does not need decryption subkeys. */
-    }
-#endif /*USE_PADLOCK*/
-  else
-    {
-      const byte *sbox = ((const byte *)encT) + 1;
 
-      prefetch_enc();
-      prefetch_dec();
-
-      ctx->keyschdec32[0][0] = ctx->keyschenc32[0][0];
-      ctx->keyschdec32[0][1] = ctx->keyschenc32[0][1];
-      ctx->keyschdec32[0][2] = ctx->keyschenc32[0][2];
-      ctx->keyschdec32[0][3] = ctx->keyschenc32[0][3];
-
-      for (r = 1; r < ctx->rounds; r++)
-        {
-          u32 *wi = ctx->keyschenc32[r];
-          u32 *wo = ctx->keyschdec32[r];
-          u32 wt;
-
-          wt = wi[0];
-          wo[0] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0)
-                 ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1)
-                 ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2)
-                 ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3);
-
-          wt = wi[1];
-          wo[1] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0)
-                 ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1)
-                 ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2)
-                 ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3);
-
-          wt = wi[2];
-          wo[2] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0)
-                 ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1)
-                 ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2)
-                 ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3);
-
-          wt = wi[3];
-          wo[3] = rol(decT[sbox[(byte)(wt >> 0) * 4]], 8 * 0)
-                 ^ rol(decT[sbox[(byte)(wt >> 8) * 4]], 8 * 1)
-                 ^ rol(decT[sbox[(byte)(wt >> 16) * 4]], 8 * 2)
-                 ^ rol(decT[sbox[(byte)(wt >> 24) * 4]], 8 * 3);
-        }
-
-      ctx->keyschdec32[r][0] = ctx->keyschenc32[r][0];
-      ctx->keyschdec32[r][1] = ctx->keyschenc32[r][1];
-      ctx->keyschdec32[r][2] = ctx->keyschenc32[r][2];
-      ctx->keyschdec32[r][3] = ctx->keyschenc32[r][3];
-    }
+  ctx->keyschdec32[r][0] = ctx->keyschenc32[r][0];
+  ctx->keyschdec32[r][1] = ctx->keyschenc32[r][1];
+  ctx->keyschdec32[r][2] = ctx->keyschenc32[r][2];
+  ctx->keyschdec32[r][3] = ctx->keyschenc32[r][3];
 }
 
 \f
@@ -695,28 +922,28 @@ do_encrypt_fn (const RIJNDAEL_context *ctx, unsigned char *b,
 
   /* Last round is special. */
 
-  sb[0] = (sbox[(byte)(sa[0] >> (0 * 8)) * 4]) << (0 * 8);
-  sb[3] = (sbox[(byte)(sa[0] >> (1 * 8)) * 4]) << (1 * 8);
-  sb[2] = (sbox[(byte)(sa[0] >> (2 * 8)) * 4]) << (2 * 8);
-  sb[1] = (sbox[(byte)(sa[0] >> (3 * 8)) * 4]) << (3 * 8);
+  sb[0] = ((u32)sbox[(byte)(sa[0] >> (0 * 8)) * 4]) << (0 * 8);
+  sb[3] = ((u32)sbox[(byte)(sa[0] >> (1 * 8)) * 4]) << (1 * 8);
+  sb[2] = ((u32)sbox[(byte)(sa[0] >> (2 * 8)) * 4]) << (2 * 8);
+  sb[1] = ((u32)sbox[(byte)(sa[0] >> (3 * 8)) * 4]) << (3 * 8);
   sa[0] = rk[r][0] ^ sb[0];
 
-  sb[1] ^= (sbox[(byte)(sa[1] >> (0 * 8)) * 4]) << (0 * 8);
-  sa[0] ^= (sbox[(byte)(sa[1] >> (1 * 8)) * 4]) << (1 * 8);
-  sb[3] ^= (sbox[(byte)(sa[1] >> (2 * 8)) * 4]) << (2 * 8);
-  sb[2] ^= (sbox[(byte)(sa[1] >> (3 * 8)) * 4]) << (3 * 8);
+  sb[1] ^= ((u32)sbox[(byte)(sa[1] >> (0 * 8)) * 4]) << (0 * 8);
+  sa[0] ^= ((u32)sbox[(byte)(sa[1] >> (1 * 8)) * 4]) << (1 * 8);
+  sb[3] ^= ((u32)sbox[(byte)(sa[1] >> (2 * 8)) * 4]) << (2 * 8);
+  sb[2] ^= ((u32)sbox[(byte)(sa[1] >> (3 * 8)) * 4]) << (3 * 8);
   sa[1] = rk[r][1] ^ sb[1];
 
-  sb[2] ^= (sbox[(byte)(sa[2] >> (0 * 8)) * 4]) << (0 * 8);
-  sa[1] ^= (sbox[(byte)(sa[2] >> (1 * 8)) * 4]) << (1 * 8);
-  sa[0] ^= (sbox[(byte)(sa[2] >> (2 * 8)) * 4]) << (2 * 8);
-  sb[3] ^= (sbox[(byte)(sa[2] >> (3 * 8)) * 4]) << (3 * 8);
+  sb[2] ^= ((u32)sbox[(byte)(sa[2] >> (0 * 8)) * 4]) << (0 * 8);
+  sa[1] ^= ((u32)sbox[(byte)(sa[2] >> (1 * 8)) * 4]) << (1 * 8);
+  sa[0] ^= ((u32)sbox[(byte)(sa[2] >> (2 * 8)) * 4]) << (2 * 8);
+  sb[3] ^= ((u32)sbox[(byte)(sa[2] >> (3 * 8)) * 4]) << (3 * 8);
   sa[2] = rk[r][2] ^ sb[2];
 
-  sb[3] ^= (sbox[(byte)(sa[3] >> (0 * 8)) * 4]) << (0 * 8);
-  sa[2] ^= (sbox[(byte)(sa[3] >> (1 * 8)) * 4]) << (1 * 8);
-  sa[1] ^= (sbox[(byte)(sa[3] >> (2 * 8)) * 4]) << (2 * 8);
-  sa[0] ^= (sbox[(byte)(sa[3] >> (3 * 8)) * 4]) << (3 * 8);
+  sb[3] ^= ((u32)sbox[(byte)(sa[3] >> (0 * 8)) * 4]) << (0 * 8);
+  sa[2] ^= ((u32)sbox[(byte)(sa[3] >> (1 * 8)) * 4]) << (1 * 8);
+  sa[1] ^= ((u32)sbox[(byte)(sa[3] >> (2 * 8)) * 4]) << (2 * 8);
+  sa[0] ^= ((u32)sbox[(byte)(sa[3] >> (3 * 8)) * 4]) << (3 * 8);
   sa[3] = rk[r][3] ^ sb[3];
 
   buf_put_le32(b + 0, sa[0]);
@@ -735,29 +962,11 @@ do_encrypt (const RIJNDAEL_context *ctx,
             unsigned char *bx, const unsigned char *ax)
 {
 #ifdef USE_AMD64_ASM
-# ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
   return _gcry_aes_amd64_encrypt_block(ctx->keyschenc, bx, ax, ctx->rounds,
-                                      encT);
-# else
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  const void *key = ctx->keyschenc;
-  uintptr_t rounds = ctx->rounds;
-  uintptr_t ret;
-  asm volatile ("movq %[encT], %%r8\n\t"
-                "callq *%[ret]\n\t"
-                : [ret] "=a" (ret),
-                  "+D" (key),
-                  "+S" (bx),
-                  "+d" (ax),
-                  "+c" (rounds)
-                : "0" (_gcry_aes_amd64_encrypt_block),
-                  [encT] "r" (encT)
-                : "cc", "memory", "r8", "r9", "r10", "r11");
-  return ret;
-# endif /* HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS */
+                                      enc_tables.T);
 #elif defined(USE_ARM_ASM)
-  return _gcry_aes_arm_encrypt_block(ctx->keyschenc, bx, ax, ctx->rounds, encT);
+  return _gcry_aes_arm_encrypt_block(ctx->keyschenc, bx, ax, ctx->rounds,
+                                    enc_tables.T);
 #else
   return do_encrypt_fn (ctx, bx, ax);
 #endif /* !USE_ARM_ASM && !USE_AMD64_ASM*/
@@ -780,7 +989,7 @@ rijndael_encrypt (void *context, byte *b, const byte *a)
    make sure that IV is aligned on an unsigned long boundary.  This
    function is only intended for the bulk encryption feature of
    cipher.c. */
-void
+static void
 _gcry_aes_cfb_enc (void *context, unsigned char *iv,
                    void *outbuf_arg, const void *inbuf_arg,
                    size_t nblocks)
@@ -789,46 +998,19 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv,
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
   unsigned int burn_depth = 0;
+  rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
 
   if (ctx->prefetch_enc_fn)
     ctx->prefetch_enc_fn();
 
-  if (0)
-    ;
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
-    {
-      _gcry_aes_aesni_cfb_enc (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
-    {
-      _gcry_aes_ssse3_cfb_enc (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
+  for ( ;nblocks; nblocks-- )
     {
-      _gcry_aes_armv8_ce_cfb_enc (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_ARM_CE*/
-  else
-    {
-      rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
-
-      for ( ;nblocks; nblocks-- )
-        {
-          /* Encrypt the IV. */
-          burn_depth = encrypt_fn (ctx, iv, iv);
-          /* XOR the input with the IV and store input into IV.  */
-          buf_xor_2dst(outbuf, iv, inbuf, BLOCKSIZE);
-          outbuf += BLOCKSIZE;
-          inbuf  += BLOCKSIZE;
-        }
+      /* Encrypt the IV. */
+      burn_depth = encrypt_fn (ctx, iv, iv);
+      /* XOR the input with the IV and store input into IV.  */
+      cipher_block_xor_2dst(outbuf, iv, inbuf, BLOCKSIZE);
+      outbuf += BLOCKSIZE;
+      inbuf  += BLOCKSIZE;
     }
 
   if (burn_depth)
@@ -840,7 +1022,7 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv,
    make sure that IV is aligned on an unsigned long boundary.  This
    function is only intended for the bulk encryption feature of
    cipher.c. */
-void
+static void
 _gcry_aes_cbc_enc (void *context, unsigned char *iv,
                    void *outbuf_arg, const void *inbuf_arg,
                    size_t nblocks, int cbc_mac)
@@ -850,55 +1032,28 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv,
   const unsigned char *inbuf = inbuf_arg;
   unsigned char *last_iv;
   unsigned int burn_depth = 0;
+  rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
 
   if (ctx->prefetch_enc_fn)
     ctx->prefetch_enc_fn();
 
-  if (0)
-    ;
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
-    {
-      _gcry_aes_aesni_cbc_enc (ctx, outbuf, inbuf, iv, nblocks, cbc_mac);
-      burn_depth = 0;
-    }
-#endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
-    {
-      _gcry_aes_ssse3_cbc_enc (ctx, outbuf, inbuf, iv, nblocks, cbc_mac);
-      burn_depth = 0;
-    }
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
-    {
-      _gcry_aes_armv8_ce_cbc_enc (ctx, outbuf, inbuf, iv, nblocks, cbc_mac);
-      burn_depth = 0;
-    }
-#endif /*USE_ARM_CE*/
-  else
-    {
-      rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
-
-      last_iv = iv;
-
-      for ( ;nblocks; nblocks-- )
-        {
-          buf_xor(outbuf, inbuf, last_iv, BLOCKSIZE);
+  last_iv = iv;
 
-          burn_depth = encrypt_fn (ctx, outbuf, outbuf);
+  for ( ;nblocks; nblocks-- )
+    {
+      cipher_block_xor(outbuf, inbuf, last_iv, BLOCKSIZE);
 
-          last_iv = outbuf;
-          inbuf += BLOCKSIZE;
-          if (!cbc_mac)
-            outbuf += BLOCKSIZE;
-        }
+      burn_depth = encrypt_fn (ctx, outbuf, outbuf);
 
-      if (last_iv != iv)
-        buf_cpy (iv, last_iv, BLOCKSIZE);
+      last_iv = outbuf;
+      inbuf += BLOCKSIZE;
+      if (!cbc_mac)
+       outbuf += BLOCKSIZE;
     }
 
+  if (last_iv != iv)
+    cipher_block_cpy (iv, last_iv, BLOCKSIZE);
+
   if (burn_depth)
     _gcry_burn_stack (burn_depth + 4 * sizeof(void *));
 }
@@ -909,7 +1064,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv,
    minimum alignment is for an u32.  This function is only intended
    for the bulk encryption feature of cipher.c.  CTR is expected to be
    of size BLOCKSIZE. */
-void
+static void
 _gcry_aes_ctr_enc (void *context, unsigned char *ctr,
                    void *outbuf_arg, const void *inbuf_arg,
                    size_t nblocks)
@@ -918,58 +1073,25 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr,
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
   unsigned int burn_depth = 0;
-  int i;
+  union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } tmp;
+  rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
 
   if (ctx->prefetch_enc_fn)
     ctx->prefetch_enc_fn();
 
-  if (0)
-    ;
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
+  for ( ;nblocks; nblocks-- )
     {
-      _gcry_aes_aesni_ctr_enc (ctx, outbuf, inbuf, ctr, nblocks);
-      burn_depth = 0;
+      /* Encrypt the counter. */
+      burn_depth = encrypt_fn (ctx, tmp.x1, ctr);
+      /* XOR the input with the encrypted counter and store in output.  */
+      cipher_block_xor(outbuf, tmp.x1, inbuf, BLOCKSIZE);
+      outbuf += BLOCKSIZE;
+      inbuf  += BLOCKSIZE;
+      /* Increment the counter.  */
+      cipher_block_add(ctr, 1, BLOCKSIZE);
     }
-#endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
-    {
-      _gcry_aes_ssse3_ctr_enc (ctx, outbuf, inbuf, ctr, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
-    {
-      _gcry_aes_armv8_ce_ctr_enc (ctx, outbuf, inbuf, ctr, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_ARM_CE*/
-  else
-    {
-      union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } tmp;
-      rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
 
-      for ( ;nblocks; nblocks-- )
-        {
-          /* Encrypt the counter. */
-          burn_depth = encrypt_fn (ctx, tmp.x1, ctr);
-          /* XOR the input with the encrypted counter and store in output.  */
-          buf_xor(outbuf, tmp.x1, inbuf, BLOCKSIZE);
-          outbuf += BLOCKSIZE;
-          inbuf  += BLOCKSIZE;
-          /* Increment the counter.  */
-          for (i = BLOCKSIZE; i > 0; i--)
-            {
-              ctr[i-1]++;
-              if (ctr[i-1])
-                break;
-            }
-        }
-
-      wipememory(&tmp, sizeof(tmp));
-    }
+  wipememory(&tmp, sizeof(tmp));
 
   if (burn_depth)
     _gcry_burn_stack (burn_depth + 4 * sizeof(void *));
@@ -1077,28 +1199,28 @@ do_decrypt_fn (const RIJNDAEL_context *ctx, unsigned char *b,
   sa[3] = rk[1][3] ^ sb[3];
 
   /* Last round is special. */
-  sb[0] = inv_sbox[(byte)(sa[0] >> (0 * 8))] << (0 * 8);
-  sb[1] = inv_sbox[(byte)(sa[0] >> (1 * 8))] << (1 * 8);
-  sb[2] = inv_sbox[(byte)(sa[0] >> (2 * 8))] << (2 * 8);
-  sb[3] = inv_sbox[(byte)(sa[0] >> (3 * 8))] << (3 * 8);
+  sb[0] = (u32)inv_sbox[(byte)(sa[0] >> (0 * 8))] << (0 * 8);
+  sb[1] = (u32)inv_sbox[(byte)(sa[0] >> (1 * 8))] << (1 * 8);
+  sb[2] = (u32)inv_sbox[(byte)(sa[0] >> (2 * 8))] << (2 * 8);
+  sb[3] = (u32)inv_sbox[(byte)(sa[0] >> (3 * 8))] << (3 * 8);
   sa[0] = sb[0] ^ rk[0][0];
 
-  sb[1] ^= inv_sbox[(byte)(sa[1] >> (0 * 8))] << (0 * 8);
-  sb[2] ^= inv_sbox[(byte)(sa[1] >> (1 * 8))] << (1 * 8);
-  sb[3] ^= inv_sbox[(byte)(sa[1] >> (2 * 8))] << (2 * 8);
-  sa[0] ^= inv_sbox[(byte)(sa[1] >> (3 * 8))] << (3 * 8);
+  sb[1] ^= (u32)inv_sbox[(byte)(sa[1] >> (0 * 8))] << (0 * 8);
+  sb[2] ^= (u32)inv_sbox[(byte)(sa[1] >> (1 * 8))] << (1 * 8);
+  sb[3] ^= (u32)inv_sbox[(byte)(sa[1] >> (2 * 8))] << (2 * 8);
+  sa[0] ^= (u32)inv_sbox[(byte)(sa[1] >> (3 * 8))] << (3 * 8);
   sa[1] = sb[1] ^ rk[0][1];
 
-  sb[2] ^= inv_sbox[(byte)(sa[2] >> (0 * 8))] << (0 * 8);
-  sb[3] ^= inv_sbox[(byte)(sa[2] >> (1 * 8))] << (1 * 8);
-  sa[0] ^= inv_sbox[(byte)(sa[2] >> (2 * 8))] << (2 * 8);
-  sa[1] ^= inv_sbox[(byte)(sa[2] >> (3 * 8))] << (3 * 8);
+  sb[2] ^= (u32)inv_sbox[(byte)(sa[2] >> (0 * 8))] << (0 * 8);
+  sb[3] ^= (u32)inv_sbox[(byte)(sa[2] >> (1 * 8))] << (1 * 8);
+  sa[0] ^= (u32)inv_sbox[(byte)(sa[2] >> (2 * 8))] << (2 * 8);
+  sa[1] ^= (u32)inv_sbox[(byte)(sa[2] >> (3 * 8))] << (3 * 8);
   sa[2] = sb[2] ^ rk[0][2];
 
-  sb[3] ^= inv_sbox[(byte)(sa[3] >> (0 * 8))] << (0 * 8);
-  sa[0] ^= inv_sbox[(byte)(sa[3] >> (1 * 8))] << (1 * 8);
-  sa[1] ^= inv_sbox[(byte)(sa[3] >> (2 * 8))] << (2 * 8);
-  sa[2] ^= inv_sbox[(byte)(sa[3] >> (3 * 8))] << (3 * 8);
+  sb[3] ^= (u32)inv_sbox[(byte)(sa[3] >> (0 * 8))] << (0 * 8);
+  sa[0] ^= (u32)inv_sbox[(byte)(sa[3] >> (1 * 8))] << (1 * 8);
+  sa[1] ^= (u32)inv_sbox[(byte)(sa[3] >> (2 * 8))] << (2 * 8);
+  sa[2] ^= (u32)inv_sbox[(byte)(sa[3] >> (3 * 8))] << (3 * 8);
   sa[3] = sb[3] ^ rk[0][3];
 
   buf_put_le32(b + 0, sa[0]);
@@ -1118,30 +1240,11 @@ do_decrypt (const RIJNDAEL_context *ctx, unsigned char *bx,
             const unsigned char *ax)
 {
 #ifdef USE_AMD64_ASM
-# ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
   return _gcry_aes_amd64_decrypt_block(ctx->keyschdec, bx, ax, ctx->rounds,
-                                      &dec_tables);
-# else
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  const void *key = ctx->keyschdec;
-  uintptr_t rounds = ctx->rounds;
-  uintptr_t ret;
-  asm volatile ("movq %[dectabs], %%r8\n\t"
-                "callq *%[ret]\n\t"
-                : [ret] "=a" (ret),
-                  "+D" (key),
-                  "+S" (bx),
-                  "+d" (ax),
-                  "+c" (rounds)
-                : "0" (_gcry_aes_amd64_decrypt_block),
-                  [dectabs] "r" (&dec_tables)
-                : "cc", "memory", "r8", "r9", "r10", "r11");
-  return ret;
-# endif /* HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS */
+                                      dec_tables.T);
 #elif defined(USE_ARM_ASM)
   return _gcry_aes_arm_decrypt_block(ctx->keyschdec, bx, ax, ctx->rounds,
-                                    &dec_tables);
+                                    dec_tables.T);
 #else
   return do_decrypt_fn (ctx, bx, ax);
 #endif /*!USE_ARM_ASM && !USE_AMD64_ASM*/
@@ -1153,7 +1256,7 @@ check_decryption_preparation (RIJNDAEL_context *ctx)
 {
   if ( !ctx->decryption_prepared )
     {
-      prepare_decryption ( ctx );
+      ctx->prepare_decryption ( ctx );
       ctx->decryption_prepared = 1;
     }
 }
@@ -1177,7 +1280,7 @@ rijndael_decrypt (void *context, byte *b, const byte *a)
    make sure that IV is aligned on an unsigned long boundary.  This
    function is only intended for the bulk encryption feature of
    cipher.c. */
-void
+static void
 _gcry_aes_cfb_dec (void *context, unsigned char *iv,
                    void *outbuf_arg, const void *inbuf_arg,
                    size_t nblocks)
@@ -1186,44 +1289,17 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv,
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
   unsigned int burn_depth = 0;
+  rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
 
   if (ctx->prefetch_enc_fn)
     ctx->prefetch_enc_fn();
 
-  if (0)
-    ;
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
-    {
-      _gcry_aes_aesni_cfb_dec (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
-    {
-      _gcry_aes_ssse3_cfb_dec (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
+  for ( ;nblocks; nblocks-- )
     {
-      _gcry_aes_armv8_ce_cfb_dec (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_ARM_CE*/
-  else
-    {
-      rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
-
-      for ( ;nblocks; nblocks-- )
-        {
-          burn_depth = encrypt_fn (ctx, iv, iv);
-          buf_xor_n_copy(outbuf, iv, inbuf, BLOCKSIZE);
-          outbuf += BLOCKSIZE;
-          inbuf  += BLOCKSIZE;
-        }
+      burn_depth = encrypt_fn (ctx, iv, iv);
+      cipher_block_xor_n_copy(outbuf, iv, inbuf, BLOCKSIZE);
+      outbuf += BLOCKSIZE;
+      inbuf  += BLOCKSIZE;
     }
 
   if (burn_depth)
@@ -1235,7 +1311,7 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv,
    make sure that IV is aligned on an unsigned long boundary.  This
    function is only intended for the bulk encryption feature of
    cipher.c. */
-void
+static void
 _gcry_aes_cbc_dec (void *context, unsigned char *iv,
                    void *outbuf_arg, const void *inbuf_arg,
                    size_t nblocks)
@@ -1244,55 +1320,28 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv,
   unsigned char *outbuf = outbuf_arg;
   const unsigned char *inbuf = inbuf_arg;
   unsigned int burn_depth = 0;
+  unsigned char savebuf[BLOCKSIZE] ATTR_ALIGNED_16;
+  rijndael_cryptfn_t decrypt_fn = ctx->decrypt_fn;
 
   check_decryption_preparation (ctx);
 
   if (ctx->prefetch_dec_fn)
     ctx->prefetch_dec_fn();
 
-  if (0)
-    ;
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
-    {
-      _gcry_aes_aesni_cbc_dec (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
-    {
-      _gcry_aes_ssse3_cbc_dec (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
-    {
-      _gcry_aes_armv8_ce_cbc_dec (ctx, outbuf, inbuf, iv, nblocks);
-      burn_depth = 0;
-    }
-#endif /*USE_ARM_CE*/
-  else
+  for ( ;nblocks; nblocks-- )
     {
-      unsigned char savebuf[BLOCKSIZE] ATTR_ALIGNED_16;
-      rijndael_cryptfn_t decrypt_fn = ctx->decrypt_fn;
-
-      for ( ;nblocks; nblocks-- )
-        {
-          /* INBUF is needed later and it may be identical to OUTBUF, so store
-             the intermediate result to SAVEBUF.  */
+      /* INBUF is needed later and it may be identical to OUTBUF, so store
+         the intermediate result to SAVEBUF.  */
 
-          burn_depth = decrypt_fn (ctx, savebuf, inbuf);
-
-          buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE);
-          inbuf += BLOCKSIZE;
-          outbuf += BLOCKSIZE;
-        }
+      burn_depth = decrypt_fn (ctx, savebuf, inbuf);
 
-      wipememory(savebuf, sizeof(savebuf));
+      cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE);
+      inbuf += BLOCKSIZE;
+      outbuf += BLOCKSIZE;
     }
 
+  wipememory(savebuf, sizeof(savebuf));
+
   if (burn_depth)
     _gcry_burn_stack (burn_depth + 4 * sizeof(void *));
 }
@@ -1300,7 +1349,7 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv,
 
 \f
 /* Bulk encryption/decryption of complete blocks in OCB mode. */
-size_t
+static size_t
 _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
                      const void *inbuf_arg, size_t nblocks, int encrypt)
 {
@@ -1311,60 +1360,27 @@ _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
 
   if (encrypt)
     {
-      if (ctx->prefetch_enc_fn)
-        ctx->prefetch_enc_fn();
-    }
-  else
-    {
-      check_decryption_preparation (ctx);
-
-      if (ctx->prefetch_dec_fn)
-        ctx->prefetch_dec_fn();
-    }
-
-  if (0)
-    ;
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
-    {
-      _gcry_aes_aesni_ocb_crypt (c, outbuf, inbuf, nblocks, encrypt);
-      burn_depth = 0;
-    }
-#endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
-    {
-      _gcry_aes_ssse3_ocb_crypt (c, outbuf, inbuf, nblocks, encrypt);
-      burn_depth = 0;
-    }
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
-    {
-      _gcry_aes_armv8_ce_ocb_crypt (c, outbuf, inbuf, nblocks, encrypt);
-      burn_depth = 0;
-    }
-#endif /*USE_ARM_CE*/
-  else if (encrypt)
-    {
       union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
       rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
 
+      if (ctx->prefetch_enc_fn)
+        ctx->prefetch_enc_fn();
+
       for ( ;nblocks; nblocks-- )
         {
           u64 i = ++c->u_mode.ocb.data_nblocks;
           const unsigned char *l = ocb_get_l(c, i);
 
           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-          buf_xor_1 (c->u_iv.iv, l, BLOCKSIZE);
-          buf_cpy (l_tmp.x1, inbuf, BLOCKSIZE);
+          cipher_block_xor_1 (c->u_iv.iv, l, BLOCKSIZE);
+          cipher_block_cpy (l_tmp.x1, inbuf, BLOCKSIZE);
           /* Checksum_i = Checksum_{i-1} xor P_i  */
-          buf_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE);
+          cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE);
           /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
-          buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
+          cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
           burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1);
-          buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
-          buf_cpy (outbuf, l_tmp.x1, BLOCKSIZE);
+          cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
+          cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE);
 
           inbuf += BLOCKSIZE;
           outbuf += BLOCKSIZE;
@@ -1375,21 +1391,26 @@ _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
       union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
       rijndael_cryptfn_t decrypt_fn = ctx->decrypt_fn;
 
+      check_decryption_preparation (ctx);
+
+      if (ctx->prefetch_dec_fn)
+        ctx->prefetch_dec_fn();
+
       for ( ;nblocks; nblocks-- )
         {
           u64 i = ++c->u_mode.ocb.data_nblocks;
           const unsigned char *l = ocb_get_l(c, i);
 
           /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-          buf_xor_1 (c->u_iv.iv, l, BLOCKSIZE);
-          buf_cpy (l_tmp.x1, inbuf, BLOCKSIZE);
+          cipher_block_xor_1 (c->u_iv.iv, l, BLOCKSIZE);
+          cipher_block_cpy (l_tmp.x1, inbuf, BLOCKSIZE);
           /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
-          buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
+          cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
           burn_depth = decrypt_fn (ctx, l_tmp.x1, l_tmp.x1);
-          buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
+          cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE);
           /* Checksum_i = Checksum_{i-1} xor P_i  */
-          buf_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE);
-          buf_cpy (outbuf, l_tmp.x1, BLOCKSIZE);
+          cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE);
+          cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE);
 
           inbuf += BLOCKSIZE;
           outbuf += BLOCKSIZE;
@@ -1404,69 +1425,110 @@ _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
 
 
 /* Bulk authentication of complete blocks in OCB mode. */
-size_t
+static size_t
 _gcry_aes_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks)
 {
   RIJNDAEL_context *ctx = (void *)&c->context.c;
   const unsigned char *abuf = abuf_arg;
   unsigned int burn_depth = 0;
+  union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
+  rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
 
   if (ctx->prefetch_enc_fn)
     ctx->prefetch_enc_fn();
 
-  if (0)
-    ;
-#ifdef USE_AESNI
-  else if (ctx->use_aesni)
+  for ( ;nblocks; nblocks-- )
     {
-      _gcry_aes_aesni_ocb_auth (c, abuf, nblocks);
-      burn_depth = 0;
+      u64 i = ++c->u_mode.ocb.aad_nblocks;
+      const unsigned char *l = ocb_get_l(c, i);
+
+      /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+      cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l, BLOCKSIZE);
+      /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
+      cipher_block_xor (l_tmp.x1, c->u_mode.ocb.aad_offset, abuf,
+                       BLOCKSIZE);
+      burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1);
+      cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp.x1, BLOCKSIZE);
+
+      abuf += BLOCKSIZE;
     }
-#endif /*USE_AESNI*/
-#ifdef USE_SSSE3
-  else if (ctx->use_ssse3)
+
+  wipememory(&l_tmp, sizeof(l_tmp));
+
+  if (burn_depth)
+    _gcry_burn_stack (burn_depth + 4 * sizeof(void *));
+
+  return 0;
+}
+
+
+/* Bulk encryption/decryption of complete blocks in XTS mode. */
+static void
+_gcry_aes_xts_crypt (void *context, unsigned char *tweak,
+                    void *outbuf_arg, const void *inbuf_arg,
+                    size_t nblocks, int encrypt)
+{
+  RIJNDAEL_context *ctx = context;
+  unsigned char *outbuf = outbuf_arg;
+  const unsigned char *inbuf = inbuf_arg;
+  unsigned int burn_depth = 0;
+  rijndael_cryptfn_t crypt_fn;
+  u64 tweak_lo, tweak_hi, tweak_next_lo, tweak_next_hi, tmp_lo, tmp_hi, carry;
+
+  if (encrypt)
     {
-      _gcry_aes_ssse3_ocb_auth (c, abuf, nblocks);
-      burn_depth = 0;
+      if (ctx->prefetch_enc_fn)
+       ctx->prefetch_enc_fn();
+
+      crypt_fn = ctx->encrypt_fn;
     }
-#endif /*USE_SSSE3*/
-#ifdef USE_ARM_CE
-  else if (ctx->use_arm_ce)
+  else
     {
-      _gcry_aes_armv8_ce_ocb_auth (c, abuf, nblocks);
-      burn_depth = 0;
+      check_decryption_preparation (ctx);
+
+      if (ctx->prefetch_dec_fn)
+       ctx->prefetch_dec_fn();
+
+      crypt_fn = ctx->decrypt_fn;
     }
-#endif /*USE_ARM_CE*/
-  else
+
+  tweak_next_lo = buf_get_le64 (tweak + 0);
+  tweak_next_hi = buf_get_le64 (tweak + 8);
+
+  while (nblocks)
     {
-      union { unsigned char x1[16] ATTR_ALIGNED_16; u32 x32[4]; } l_tmp;
-      rijndael_cryptfn_t encrypt_fn = ctx->encrypt_fn;
+      tweak_lo = tweak_next_lo;
+      tweak_hi = tweak_next_hi;
 
-      for ( ;nblocks; nblocks-- )
-        {
-          u64 i = ++c->u_mode.ocb.aad_nblocks;
-          const unsigned char *l = ocb_get_l(c, i);
+      /* Xor-Encrypt/Decrypt-Xor block. */
+      tmp_lo = buf_get_le64 (inbuf + 0) ^ tweak_lo;
+      tmp_hi = buf_get_le64 (inbuf + 8) ^ tweak_hi;
 
-          /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
-          buf_xor_1 (c->u_mode.ocb.aad_offset, l, BLOCKSIZE);
-          /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
-          buf_xor (l_tmp.x1, c->u_mode.ocb.aad_offset, abuf, BLOCKSIZE);
-          burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1);
-          buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp.x1, BLOCKSIZE);
+      buf_put_le64 (outbuf + 0, tmp_lo);
+      buf_put_le64 (outbuf + 8, tmp_hi);
 
-          abuf += BLOCKSIZE;
-        }
+      /* Generate next tweak. */
+      carry = -(tweak_next_hi >> 63) & 0x87;
+      tweak_next_hi = (tweak_next_hi << 1) + (tweak_next_lo >> 63);
+      tweak_next_lo = (tweak_next_lo << 1) ^ carry;
+
+      burn_depth = crypt_fn (ctx, outbuf, outbuf);
+
+      buf_put_le64 (outbuf + 0, buf_get_le64 (outbuf + 0) ^ tweak_lo);
+      buf_put_le64 (outbuf + 8, buf_get_le64 (outbuf + 8) ^ tweak_hi);
 
-      wipememory(&l_tmp, sizeof(l_tmp));
+      outbuf += GCRY_XTS_BLOCK_LEN;
+      inbuf += GCRY_XTS_BLOCK_LEN;
+      nblocks--;
     }
 
-  if (burn_depth)
-    _gcry_burn_stack (burn_depth + 4 * sizeof(void *));
+  buf_put_le64 (tweak + 0, tweak_next_lo);
+  buf_put_le64 (tweak + 8, tweak_next_hi);
 
-  return 0;
+  if (burn_depth)
+    _gcry_burn_stack (burn_depth + 5 * sizeof(void *));
 }
 
-
 \f
 /* Run the self-tests for AES 128.  Returns NULL on success. */
 static const char*
@@ -1475,6 +1537,7 @@ selftest_basic_128 (void)
   RIJNDAEL_context *ctx;
   unsigned char *ctxmem;
   unsigned char scratch[16];
+  cipher_bulk_ops_t bulk_ops;
 
   /* The test vectors are from the AES supplied ones; more or less
      randomly taken from ecb_tbl.txt (I=42,81,14) */
@@ -1522,7 +1585,7 @@ selftest_basic_128 (void)
   if (!ctx)
     return "failed to allocate memory";
 
-  rijndael_setkey (ctx, key_128, sizeof (key_128));
+  rijndael_setkey (ctx, key_128, sizeof (key_128), &bulk_ops);
   rijndael_encrypt (ctx, scratch, plaintext_128);
   if (memcmp (scratch, ciphertext_128, sizeof (ciphertext_128)))
     {
@@ -1544,6 +1607,7 @@ selftest_basic_192 (void)
   RIJNDAEL_context *ctx;
   unsigned char *ctxmem;
   unsigned char scratch[16];
+  cipher_bulk_ops_t bulk_ops;
 
   static unsigned char plaintext_192[16] =
     {
@@ -1565,7 +1629,7 @@ selftest_basic_192 (void)
   ctx = _gcry_cipher_selftest_alloc_ctx (sizeof *ctx, &ctxmem);
   if (!ctx)
     return "failed to allocate memory";
-  rijndael_setkey (ctx, key_192, sizeof(key_192));
+  rijndael_setkey (ctx, key_192, sizeof(key_192), &bulk_ops);
   rijndael_encrypt (ctx, scratch, plaintext_192);
   if (memcmp (scratch, ciphertext_192, sizeof (ciphertext_192)))
     {
@@ -1588,6 +1652,7 @@ selftest_basic_256 (void)
   RIJNDAEL_context *ctx;
   unsigned char *ctxmem;
   unsigned char scratch[16];
+  cipher_bulk_ops_t bulk_ops;
 
   static unsigned char plaintext_256[16] =
     {
@@ -1610,7 +1675,7 @@ selftest_basic_256 (void)
   ctx = _gcry_cipher_selftest_alloc_ctx (sizeof *ctx, &ctxmem);
   if (!ctx)
     return "failed to allocate memory";
-  rijndael_setkey (ctx, key_256, sizeof(key_256));
+  rijndael_setkey (ctx, key_256, sizeof(key_256), &bulk_ops);
   rijndael_encrypt (ctx, scratch, plaintext_256);
   if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256)))
     {
@@ -1631,13 +1696,16 @@ selftest_basic_256 (void)
 static const char*
 selftest_ctr_128 (void)
 {
+#ifdef USE_VAES
+  const int nblocks = 16+1;
+#else
   const int nblocks = 8+1;
+#endif
   const int blocksize = BLOCKSIZE;
   const int context_size = sizeof(RIJNDAEL_context);
 
   return _gcry_selftest_helper_ctr("AES", &rijndael_setkey,
-           &rijndael_encrypt, &_gcry_aes_ctr_enc, nblocks, blocksize,
-          context_size);
+           &rijndael_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1646,13 +1714,16 @@ selftest_ctr_128 (void)
 static const char*
 selftest_cbc_128 (void)
 {
+#ifdef USE_VAES
+  const int nblocks = 16+2;
+#else
   const int nblocks = 8+2;
+#endif
   const int blocksize = BLOCKSIZE;
   const int context_size = sizeof(RIJNDAEL_context);
 
   return _gcry_selftest_helper_cbc("AES", &rijndael_setkey,
-           &rijndael_encrypt, &_gcry_aes_cbc_dec, nblocks, blocksize,
-          context_size);
+           &rijndael_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1661,13 +1732,16 @@ selftest_cbc_128 (void)
 static const char*
 selftest_cfb_128 (void)
 {
+#ifdef USE_VAES
+  const int nblocks = 16+2;
+#else
   const int nblocks = 8+2;
+#endif
   const int blocksize = BLOCKSIZE;
   const int context_size = sizeof(RIJNDAEL_context);
 
   return _gcry_selftest_helper_cfb("AES", &rijndael_setkey,
-           &rijndael_encrypt, &_gcry_aes_cfb_dec, nblocks, blocksize,
-          context_size);
+           &rijndael_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1948,12 +2022,14 @@ static const char *rijndael_names[] =
     NULL
   };
 
-static gcry_cipher_oid_spec_t rijndael_oids[] =
+static const gcry_cipher_oid_spec_t rijndael_oids[] =
   {
     { "2.16.840.1.101.3.4.1.1", GCRY_CIPHER_MODE_ECB },
     { "2.16.840.1.101.3.4.1.2", GCRY_CIPHER_MODE_CBC },
     { "2.16.840.1.101.3.4.1.3", GCRY_CIPHER_MODE_OFB },
     { "2.16.840.1.101.3.4.1.4", GCRY_CIPHER_MODE_CFB },
+    { "2.16.840.1.101.3.4.1.6", GCRY_CIPHER_MODE_GCM },
+    { "2.16.840.1.101.3.4.1.7", GCRY_CIPHER_MODE_CCM },
     { NULL }
   };
 
@@ -1975,12 +2051,14 @@ static const char *rijndael192_names[] =
     NULL
   };
 
-static gcry_cipher_oid_spec_t rijndael192_oids[] =
+static const gcry_cipher_oid_spec_t rijndael192_oids[] =
   {
     { "2.16.840.1.101.3.4.1.21", GCRY_CIPHER_MODE_ECB },
     { "2.16.840.1.101.3.4.1.22", GCRY_CIPHER_MODE_CBC },
     { "2.16.840.1.101.3.4.1.23", GCRY_CIPHER_MODE_OFB },
     { "2.16.840.1.101.3.4.1.24", GCRY_CIPHER_MODE_CFB },
+    { "2.16.840.1.101.3.4.1.26", GCRY_CIPHER_MODE_GCM },
+    { "2.16.840.1.101.3.4.1.27", GCRY_CIPHER_MODE_CCM },
     { NULL }
   };
 
@@ -2002,12 +2080,14 @@ static const char *rijndael256_names[] =
     NULL
   };
 
-static gcry_cipher_oid_spec_t rijndael256_oids[] =
+static const gcry_cipher_oid_spec_t rijndael256_oids[] =
   {
     { "2.16.840.1.101.3.4.1.41", GCRY_CIPHER_MODE_ECB },
     { "2.16.840.1.101.3.4.1.42", GCRY_CIPHER_MODE_CBC },
     { "2.16.840.1.101.3.4.1.43", GCRY_CIPHER_MODE_OFB },
     { "2.16.840.1.101.3.4.1.44", GCRY_CIPHER_MODE_CFB },
+    { "2.16.840.1.101.3.4.1.46", GCRY_CIPHER_MODE_GCM },
+    { "2.16.840.1.101.3.4.1.47", GCRY_CIPHER_MODE_CCM },
     { NULL }
   };
 
index 0a019b9..5c54fdf 100644 (file)
@@ -166,7 +166,7 @@ rmd160_init (void *context, unsigned int flags)
   hd->bctx.nblocks = 0;
   hd->bctx.nblocks_high = 0;
   hd->bctx.count = 0;
-  hd->bctx.blocksize = 64;
+  hd->bctx.blocksize_shift = _gcry_ctz(64);
   hd->bctx.bwrite = transform;
 }
 
@@ -410,8 +410,6 @@ rmd160_final( void *context )
   byte *p;
   unsigned int burn;
 
-  _gcry_md_block_write(hd, NULL, 0); /* flush */;
-
   t = hd->bctx.nblocks;
   if (sizeof t == sizeof hd->bctx.nblocks)
     th = hd->bctx.nblocks_high;
@@ -431,25 +429,28 @@ rmd160_final( void *context )
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->bctx.count < 56 )  /* enough room */
+  if (hd->bctx.count < 56)  /* enough room */
     {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
-      while( hd->bctx.count < 56 )
-        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
+      if (hd->bctx.count < 56)
+       memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count);
+
+      /* append the 64 bit count */
+      buf_put_le32(hd->bctx.buf + 56, lsb);
+      buf_put_le32(hd->bctx.buf + 60, msb);
+      burn = transform (hd, hd->bctx.buf, 1);
     }
-  else  /* need one extra block */
+  else /* need one extra block */
     {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
-      while( hd->bctx.count < 64 )
-        hd->bctx.buf[hd->bctx.count++] = 0;
-      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
-      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
+      /* fill pad and next block with zeroes */
+      memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56);
+
+      /* append the 64 bit count */
+      buf_put_le32(hd->bctx.buf + 64 + 56, lsb);
+      buf_put_le32(hd->bctx.buf + 64 + 60, msb);
+      burn = transform (hd, hd->bctx.buf, 2);
     }
-  /* append the 64 bit count */
-  buf_put_le32(hd->bctx.buf + 56, lsb);
-  buf_put_le32(hd->bctx.buf + 60, msb);
-  burn = transform ( hd, hd->bctx.buf, 1 );
-  _gcry_burn_stack (burn);
 
   p = hd->bctx.buf;
 #define X(a) do { buf_put_le32(p, hd->h##a); p += 4; } while(0)
@@ -459,6 +460,10 @@ rmd160_final( void *context )
   X(3);
   X(4);
 #undef X
+
+  hd->bctx.count = 0;
+
+  _gcry_burn_stack (burn);
 }
 
 static byte *
@@ -472,25 +477,31 @@ 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 )
+static void
+_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);
-  _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);
   rmd160_final ( &hd );
   memcpy ( outbuf, hd.bctx.buf, 20 );
 }
 
-static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */
+
+static const byte asn[15] = /* Object ID is 1.3.36.3.2.1 */
   { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
     0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
 
-static gcry_md_oid_spec_t oid_spec_rmd160[] =
+static const gcry_md_oid_spec_t oid_spec_rmd160[] =
   {
     /* rsaSignatureWithripemd160 */
     { "1.3.36.3.3.1.2" },
@@ -499,10 +510,11 @@ static gcry_md_oid_spec_t oid_spec_rmd160[] =
     { NULL }
   };
 
-gcry_md_spec_t _gcry_digest_spec_rmd160 =
+const 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_buffers,
     sizeof (RMD160_CONTEXT)
   };
index 29b7bc8..233ddb2 100644 (file)
@@ -737,14 +737,16 @@ _gcry_rsa_oaep_decode (unsigned char **r_result, size_t *r_resultlen,
 
 
 /* RFC-3447 (pkcs#1 v2.1) PSS encoding.  Encode {VALUE,VALUELEN} for
-   an NBITS key.  Note that VALUE is already the mHash from the
-   picture below.  ALGO is a valid hash algorithm and SALTLEN is the
-   length of salt to be used.  On success the result is stored as a
-   new MPI at R_RESULT.  On error the value at R_RESULT is undefined.
+   an NBITS key.  ALGO is a valid hash algorithm and SALTLEN is the
+   length of salt to be used.  When HASHED_ALREADY is set, VALUE is
+   already the mHash from the picture below.  Otherwise, VALUE is M.
 
-   If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as
-   the salt instead of using a random string for the salt.  This
-   feature is only useful for regression tests.
+   On success the result is stored as a new MPI at R_RESULT.  On error
+   the value at R_RESULT is undefined.
+
+   If RANDOM_OVERRIDE is given it is used as the salt instead of using
+   a random string for the salt.  This feature is only useful for
+   regression tests.
 
    Here is figure 2 from the RFC (errata 595 applied) depicting the
    process:
@@ -777,10 +779,13 @@ _gcry_rsa_oaep_decode (unsigned char **r_result, size_t *r_resultlen,
   */
 gpg_err_code_t
 _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
-                      const unsigned char *value, size_t valuelen, int saltlen,
-                      const void *random_override, size_t random_override_len)
+                      int saltlen, int hashed_already,
+                      const unsigned char *value, size_t valuelen,
+                      const void *random_override)
 {
   gcry_err_code_t rc = 0;
+  gcry_md_hd_t hd = NULL;
+  unsigned char *digest;
   size_t hlen;                 /* Length of the hash digest.  */
   unsigned char *em = NULL;    /* Encoded message.  */
   size_t emlen = (nbits+7)/8;  /* Length in bytes of EM.  */
@@ -793,8 +798,13 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
   unsigned char *p;
   size_t n;
 
+
   /* This code is implemented as described by rfc-3447 9.1.1.  */
 
+  rc = _gcry_md_open (&hd, algo, 0);
+  if (rc)
+    return rc;
+
   /* Get the length of the digest.  */
   hlen = _gcry_md_get_algo_dlen (algo);
   gcry_assert (hlen);  /* We expect a valid ALGO here.  */
@@ -811,14 +821,23 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
   salt  = mhash + hlen;
   dbmask= salt + saltlen;
 
-  /* Step 2: That would be: mHash = Hash(M) but our input is already
-     mHash thus we do only a consistency check and copy to MHASH.  */
-  if (valuelen != hlen)
+  /* Step 2: mHash = Hash(M) (or copy input to mHash, if already hashed).   */
+  if (!hashed_already)
     {
-      rc = GPG_ERR_INV_LENGTH;
-      goto leave;
+      _gcry_md_write (hd, value, valuelen);
+      digest = _gcry_md_read (hd, 0);
+      memcpy (mhash, digest, hlen);
+      _gcry_md_reset (hd);
+    }
+  else
+    {
+      if (valuelen != hlen)
+        {
+          rc = GPG_ERR_INV_LENGTH;
+          goto leave;
+        }
+      memcpy (mhash, value, hlen);
     }
-  memcpy (mhash, value, hlen);
 
   /* Step 3: Check length constraints.  */
   if (emlen < hlen + saltlen + 2)
@@ -840,21 +859,17 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
   if (saltlen)
     {
       if (random_override)
-        {
-          if (random_override_len != saltlen)
-            {
-              rc = GPG_ERR_INV_ARG;
-              goto leave;
-            }
-          memcpy (salt, random_override, saltlen);
-        }
+        memcpy (salt, random_override, saltlen);
       else
         _gcry_randomize (salt, saltlen, GCRY_STRONG_RANDOM);
     }
 
   /* Step 5 and 6: M' = Hash(Padding1 || mHash || salt).  */
   memset (buf, 0, 8);  /* Padding.  */
-  _gcry_md_hash_buffer (algo, h, buf, 8 + hlen + saltlen);
+
+  _gcry_md_write (hd, buf, 8 + hlen + saltlen);
+  digest = _gcry_md_read (hd, 0);
+  memcpy (h, digest, hlen);
 
   /* Step 7 and 8: DB = PS || 0x01 || salt.  */
   /* Note that we use EM to store DB and later Xor in-place.  */
@@ -882,6 +897,7 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
     log_mpidump ("PSS encoded data", *r_result);
 
  leave:
+  _gcry_md_close (hd);
   if (em)
     {
       wipememory (em, emlen);
@@ -896,17 +912,21 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo,
 }
 
 
-/* Verify a signature assuming PSS padding.  VALUE is the hash of the
-   message (mHash) encoded as an MPI; its length must match the digest
-   length of ALGO.  ENCODED is the output of the RSA public key
-   function (EM).  NBITS is the size of the public key.  ALGO is the
-   hash algorithm and SALTLEN is the length of the used salt.  The
+/* Verify a signature assuming PSS padding.  When HASHED_ALREADY is
+   set, VALUE is the hash of the message (mHash); its length must
+   match the digest length of ALGO.  Otherwise, its M (before mHash).
+   VALUE is an opaque MPI.  ENCODED is the output of the RSA public
+   key function (EM).  NBITS is the size of the public key.  ALGO is
+   the hash algorithm and SALTLEN is the length of the used salt.  The
    function returns 0 on success or on error code.  */
 gpg_err_code_t
-_gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
+_gcry_rsa_pss_verify (gcry_mpi_t value, int hashed_already,
+                      gcry_mpi_t encoded,
                       unsigned int nbits, int algo, size_t saltlen)
 {
   gcry_err_code_t rc = 0;
+  gcry_md_hd_t hd = NULL;
+  unsigned char *digest;
   size_t hlen;                 /* Length of the hash digest.  */
   unsigned char *em = NULL;    /* Encoded message.  */
   size_t emlen = (nbits+7)/8;  /* Length in bytes of EM.  */
@@ -918,9 +938,14 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
   unsigned char *mhash;        /* Points into BUF.  */
   unsigned char *p;
   size_t n;
+  unsigned int input_nbits;
 
   /* This code is implemented as described by rfc-3447 9.1.2.  */
 
+  rc = _gcry_md_open (&hd, algo, 0);
+  if (rc)
+    return rc;
+
   /* Get the length of the digest.  */
   hlen = _gcry_md_get_algo_dlen (algo);
   gcry_assert (hlen);  /* We expect a valid ALGO here.  */
@@ -950,11 +975,23 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
   dbmask = buf;
   mhash = buf + buflen - hlen;
 
-  /* Step 2: That would be: mHash = Hash(M) but our input is already
-     mHash thus we only need to convert VALUE into MHASH.  */
-  rc = octet_string_from_mpi (NULL, mhash, value, hlen);
-  if (rc)
-    goto leave;
+  /* Step 2: mHash = Hash(M) (or copy input to mHash, if already hashed).   */
+  p = mpi_get_opaque (value, &input_nbits);
+  if (!p)
+    {
+      rc = GPG_ERR_INV_ARG;
+      goto leave;
+    }
+
+  if (!hashed_already)
+    {
+      _gcry_md_write (hd, p, (input_nbits+7)/8);
+      digest = _gcry_md_read (hd, 0);
+      memcpy (mhash, digest, hlen);
+      _gcry_md_reset (hd);
+    }
+  else
+    memcpy (mhash, p, hlen);
 
   /* Convert the signature into an octet string.  */
   rc = octet_string_from_mpi (&em, NULL, encoded, emlen);
@@ -1018,12 +1055,15 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, gcry_mpi_t encoded,
   memcpy (buf+8+hlen, salt, saltlen);
 
   /* Step 13:  H' = Hash(M').  */
-  _gcry_md_hash_buffer (algo, buf, buf, 8 + hlen + saltlen);
+  _gcry_md_write (hd, buf, 8 + hlen + saltlen);
+  digest = _gcry_md_read (hd, 0);
+  memcpy (buf, digest, hlen);
 
   /* Step 14:  Check H == H'.   */
   rc = memcmp (h, buf, hlen) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR;
 
  leave:
+  _gcry_md_close (hd);
   if (em)
     {
       wipememory (em, emlen);
index 575ea94..3f1cd72 100644 (file)
@@ -220,14 +220,6 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
   gcry_mpi_t f;
   gcry_random_level_t random_level;
 
-  if (fips_mode ())
-    {
-      if (nbits < 1024)
-        return GPG_ERR_INV_VALUE;
-      if (transient_key)
-        return GPG_ERR_INV_VALUE;
-    }
-
   /* The random quality depends on the transient_key flag.  */
   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
 
@@ -356,6 +348,17 @@ generate_std (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
 }
 
 
+/* Check the RSA key length is acceptable for key generation or usage */
+static gpg_err_code_t
+rsa_check_keysize (unsigned int nbits)
+{
+  if (fips_mode() && nbits < 2048)
+    return GPG_ERR_INV_VALUE;
+
+  return GPG_ERR_NO_ERROR;
+}
+
+
 /****************
  * Generate a key pair with a key of size NBITS.
  * USE_E = 0 let Libcgrypt decide what exponent to use.
@@ -385,12 +388,16 @@ generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
   unsigned int pbits = nbits/2;
   unsigned int i;
   int pqswitch;
-  gpg_err_code_t ec = GPG_ERR_NO_PRIME;
+  gpg_err_code_t ec;
 
-  if (nbits < 1024 || (nbits & 0x1FF))
+  if (nbits <= 1024 || (nbits & 0x1FF))
     return GPG_ERR_INV_VALUE;
-  if (_gcry_enforced_fips_mode() && nbits != 2048 && nbits != 3072)
-      return GPG_ERR_INV_VALUE;
+  ec = rsa_check_keysize (nbits);
+  if (ec)
+    return ec;
+
+  /* Set default error code.  */
+  ec = GPG_ERR_NO_PRIME;
 
   /* The random quality depends on the transient_key flag.  */
   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
@@ -588,7 +595,7 @@ generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e,
       mpi_invm (u, p, q );
     }
 
-  ec = 0;
+  ec = 0; /* Success.  */
 
   if (DBG_CIPHER)
     {
@@ -696,7 +703,9 @@ generate_x931 (RSA_secret_key *sk, unsigned int nbits, unsigned long e_value,
 
   *swapped = 0;
 
-  if (e_value == 1)   /* Alias for a secure value. */
+  if (e_value == 0)        /* 65537 is the libgcrypt's selection. */
+    e_value = 65537;
+  else if (e_value == 1)   /* Alias for a secure value. */
     e_value = 65537;
 
   /* Point 1 of section 4.1:  k = 1024 + 256s with S >= 0  */
@@ -1282,9 +1291,13 @@ rsa_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   gcry_mpi_t data = NULL;
   RSA_public_key pk = {NULL, NULL};
   gcry_mpi_t ciph = NULL;
+  unsigned int nbits = rsa_get_nbits (keyparms);
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT,
-                                   rsa_get_nbits (keyparms));
+  rc = rsa_check_keysize (nbits);
+  if (rc)
+    return rc;
+
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
@@ -1354,9 +1367,13 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   gcry_mpi_t plain = NULL;
   unsigned char *unpad = NULL;
   size_t unpadlen = 0;
+  unsigned int nbits = rsa_get_nbits (keyparms);
+
+  rc = rsa_check_keysize (nbits);
+  if (rc)
+    return rc;
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT,
-                                   rsa_get_nbits (keyparms));
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_preparse_encval (s_data, rsa_names, &l1, &ctx);
@@ -1399,7 +1416,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   mpi_fdiv_r (data, data, sk.n);
 
   /* Allocate MPI for the plaintext.  */
-  plain = mpi_snew (ctx.nbits);
+  plain = mpi_snew (nbits);
 
   /* We use blinding by default to mitigate timing attacks which can
      be practically mounted over the network as shown by Brumley and
@@ -1407,7 +1424,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING))
     secret (plain, data, &sk);
   else
-    secret_blinded (plain, data, &sk, ctx.nbits);
+    secret_blinded (plain, data, &sk, nbits);
 
   if (DBG_CIPHER)
     log_printmpi ("rsa_decrypt  res", plain);
@@ -1416,7 +1433,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   switch (ctx.encoding)
     {
     case PUBKEY_ENC_PKCS1:
-      rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, ctx.nbits, plain);
+      rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain);
       mpi_free (plain);
       plain = NULL;
       if (!rc)
@@ -1425,7 +1442,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
 
     case PUBKEY_ENC_OAEP:
       rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen,
-                                  ctx.nbits, ctx.hash_algo,
+                                  nbits, ctx.hash_algo,
                                   plain, ctx.label, ctx.labellen);
       mpi_free (plain);
       plain = NULL;
@@ -1470,9 +1487,13 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   RSA_public_key pk;
   gcry_mpi_t sig = NULL;
   gcry_mpi_t result = NULL;
+  unsigned int nbits = rsa_get_nbits (keyparms);
+
+  rc = rsa_check_keysize (nbits);
+  if (rc)
+    return rc;
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN,
-                                   rsa_get_nbits (keyparms));
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
@@ -1510,7 +1531,7 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING))
     secret (sig, data, &sk);
   else
-    secret_blinded (sig, data, &sk, ctx.nbits);
+    secret_blinded (sig, data, &sk, nbits);
   if (DBG_CIPHER)
     log_printmpi ("rsa_sign    res", sig);
 
@@ -1572,9 +1593,13 @@ rsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   gcry_mpi_t data = NULL;
   RSA_public_key pk = { NULL, NULL };
   gcry_mpi_t result = NULL;
+  unsigned int nbits = rsa_get_nbits (keyparms);
 
-  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY,
-                                   rsa_get_nbits (keyparms));
+  rc = rsa_check_keysize (nbits);
+  if (rc)
+    return rc;
+
+  _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY, nbits);
 
   /* Extract the data.  */
   rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx);
@@ -1582,7 +1607,7 @@ rsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
     goto leave;
   if (DBG_CIPHER)
     log_printmpi ("rsa_verify data", data);
-  if (mpi_is_opaque (data))
+  if (ctx.encoding != PUBKEY_ENC_PSS && mpi_is_opaque (data))
     {
       rc = GPG_ERR_INV_DATA;
       goto leave;
@@ -1884,7 +1909,7 @@ selftest_encr_2048 (gcry_sexp_t pkey, gcry_sexp_t skey)
   ciphertext = extract_a_from_sexp (encr);
   if (!ciphertext)
     {
-      errtxt = "gcry_pk_decrypt returned garbage";
+      errtxt = "gcry_pk_encrypt returned garbage";
       goto leave;
     }
 
index 470c32a..6462606 100644 (file)
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_SALSA20)
 
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -40,6 +36,7 @@
 .globl _gcry_salsa20_amd64_keysetup
 ELF(.type  _gcry_salsa20_amd64_keysetup,@function;)
 _gcry_salsa20_amd64_keysetup:
+       CFI_STARTPROC();
        movl   0(%rsi),%r8d
        movl   4(%rsi),%r9d
        movl   8(%rsi),%eax
@@ -86,12 +83,14 @@ _gcry_salsa20_amd64_keysetup:
        movl   %ecx,8(%rdi)
        movl   %r8d,12(%rdi)
 .L_keysetupdone:
-       ret
+       ret_spec_stop
+       CFI_ENDPROC();
 
 .align 8
 .globl _gcry_salsa20_amd64_ivsetup
 ELF(.type  _gcry_salsa20_amd64_ivsetup,@function;)
 _gcry_salsa20_amd64_ivsetup:
+       CFI_STARTPROC();
        movl   0(%rsi),%r8d
        movl   4(%rsi),%esi
        mov  $0,%r9
@@ -100,7 +99,8 @@ _gcry_salsa20_amd64_ivsetup:
        movl   %esi,44(%rdi)
        movl   %r9d,32(%rdi)
        movl   %eax,52(%rdi)
-       ret
+       ret_spec_stop
+       CFI_ENDPROC();
 
 .align 8
 .globl _gcry_salsa20_amd64_encrypt_blocks
@@ -112,13 +112,15 @@ _gcry_salsa20_amd64_encrypt_blocks:
         *  - Length is input as number of blocks, so don't handle tail bytes
         *    (this is done in salsa20.c).
         */
+       CFI_STARTPROC();
        push %rbx
+       CFI_PUSH(%rbx);
        shlq $6, %rcx /* blocks to bytes */
        mov %r8, %rbx
        mov %rsp,%r11
-       and $31,%r11
-       add $384,%r11
-       sub %r11,%rsp
+       CFI_DEF_CFA_REGISTER(%r11);
+       sub $384,%rsp
+       and $~31,%rsp
        mov  %rdi,%r8
        mov  %rsi,%rsi
        mov  %rdx,%rdi
@@ -916,15 +918,22 @@ _gcry_salsa20_amd64_encrypt_blocks:
        cmp  $64,%rdx
        ja .L_bytes_are_128_or_192
 .L_done:
-       add %r11,%rsp
+       CFI_REMEMBER_STATE();
        mov %r11,%rax
+       sub %rsp,%rax
+       mov %r11,%rsp
+       CFI_REGISTER(%r11, %rsp)
+       CFI_DEF_CFA_REGISTER(%rsp)
        pop %rbx
-       ret
+       CFI_POP(%rbx)
+       ret_spec_stop
+       CFI_RESTORE_STATE();
 .L_bytes_are_128_or_192:
        sub  $64,%rdx
        add  $64,%rdi
        add  $64,%rsi
        jmp .L_bytes_are_64_128_or_192
+       CFI_ENDPROC();
 ELF(.size _gcry_salsa20_amd64_encrypt_blocks,.-_gcry_salsa20_amd64_encrypt_blocks;)
 
 #endif /*defined(USE_SALSA20)*/
index 9768198..d8c5c81 100644 (file)
@@ -39,6 +39,7 @@
 #include "g10lib.h"
 #include "cipher.h"
 #include "bufhelp.h"
+#include "cipher-internal.h"
 
 
 /* USE_AMD64 indicates whether to compile with AMD64 code. */
@@ -366,10 +367,12 @@ salsa20_do_setkey (SALSA20_context_t *ctx,
 
 
 static gcry_err_code_t
-salsa20_setkey (void *context, const byte *key, unsigned int keylen)
+salsa20_setkey (void *context, const byte *key, unsigned int keylen,
+                cipher_bulk_ops_t *bulk_ops)
 {
   SALSA20_context_t *ctx = (SALSA20_context_t *)context;
   gcry_err_code_t rc = salsa20_do_setkey (ctx, key, keylen);
+  (void)bulk_ops;
   _gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *));
   return rc;
 }
@@ -522,7 +525,7 @@ selftest (void)
   /* 16-byte alignment required for amd64 implementation. */
   ctx = (SALSA20_context_t *)((uintptr_t)(ctxbuf + 15) & ~(uintptr_t)15);
 
-  salsa20_setkey (ctx, key_1, sizeof key_1);
+  salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
   salsa20_setiv  (ctx, nonce_1, sizeof nonce_1);
   scratch[8] = 0;
   salsa20_encrypt_stream (ctx, scratch, plaintext_1, sizeof plaintext_1);
@@ -530,7 +533,7 @@ selftest (void)
     return "Salsa20 encryption test 1 failed.";
   if (scratch[8])
     return "Salsa20 wrote too much.";
-  salsa20_setkey( ctx, key_1, sizeof(key_1));
+  salsa20_setkey( ctx, key_1, sizeof(key_1), NULL);
   salsa20_setiv  (ctx, nonce_1, sizeof nonce_1);
   salsa20_encrypt_stream (ctx, scratch, scratch, sizeof plaintext_1);
   if (memcmp (scratch, plaintext_1, sizeof plaintext_1))
@@ -538,12 +541,12 @@ selftest (void)
 
   for (i = 0; i < sizeof buf; i++)
     buf[i] = i;
-  salsa20_setkey (ctx, key_1, sizeof key_1);
+  salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
   salsa20_setiv (ctx, nonce_1, sizeof nonce_1);
   /*encrypt*/
   salsa20_encrypt_stream (ctx, buf, buf, sizeof buf);
   /*decrypt*/
-  salsa20_setkey (ctx, key_1, sizeof key_1);
+  salsa20_setkey (ctx, key_1, sizeof key_1, NULL);
   salsa20_setiv (ctx, nonce_1, sizeof nonce_1);
   salsa20_encrypt_stream (ctx, buf, buf, 1);
   salsa20_encrypt_stream (ctx, buf+1, buf+1, (sizeof buf)-1-1);
index 13fd1cf..5502bdc 100644 (file)
@@ -309,7 +309,7 @@ _gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen,
   for (i = 0; !ec && i < p; i++)
     scrypt_ro_mix (r, &B[i * r128], N, tmp1, tmp2);
 
-  for (i = 0; !ec && i < p; i++)
+  if (!ec)
     ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, B, p * r128,
                           1 /* iterations */, dkLen, DK);
 
index 9f87c05..4fd93d7 100644 (file)
@@ -30,6 +30,7 @@
 #include "g10lib.h"
 #include "cipher.h"
 #include "bufhelp.h"
+#include "cipher-internal.h"
 
 #define NUMKC  16
 
@@ -309,11 +310,12 @@ do_setkey (SEED_context *ctx, const byte *key, const unsigned keylen)
 }
 
 static gcry_err_code_t
-seed_setkey (void *context, const byte *key, const unsigned keylen)
+seed_setkey (void *context, const byte *key, const unsigned keylen,
+             cipher_bulk_ops_t *bulk_ops)
 {
   SEED_context *ctx = context;
-
   int rc = do_setkey (ctx, key, keylen);
+  (void)bulk_ops;
   _gcry_burn_stack (4*6 + sizeof(void*)*2 + sizeof(int)*2);
   return rc;
 }
@@ -446,7 +448,7 @@ selftest (void)
     0x22, 0x6B, 0xC3, 0x14, 0x2C, 0xD4, 0x0D, 0x4A,
   };
 
-  seed_setkey (&ctx, key, sizeof(key));
+  seed_setkey (&ctx, key, sizeof(key), NULL);
   seed_encrypt (&ctx, scratch, plaintext);
   if (memcmp (scratch, ciphertext, sizeof (ciphertext)))
     return "SEED test encryption failed.";
@@ -459,7 +461,7 @@ selftest (void)
 
 \f
 
-static gcry_cipher_oid_spec_t seed_oids[] =
+static const gcry_cipher_oid_spec_t seed_oids[] =
   {
     { "1.2.410.200004.1.3", GCRY_CIPHER_MODE_ECB },
     { "1.2.410.200004.1.4", GCRY_CIPHER_MODE_CBC },
index 8d60a15..d3515a2 100644 (file)
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifdef __x86_64
 #include <config.h>
+
+#ifdef __x86_64
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_SERPENT) && \
     defined(ENABLE_AVX2_SUPPORT)
 
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
+#include "asm-common-amd64.h"
 
 /* struct serpent_context: */
 #define ctx_keys 0
@@ -421,6 +412,7 @@ __serpent_enc_blk16:
         *      RA4, RA1, RA2, RA0, RB4, RB1, RB2, RB0: sixteen parallel
         *                                              ciphertext blocks
         */
+       CFI_STARTPROC();
 
        vpcmpeqd RNOT, RNOT, RNOT;
 
@@ -495,7 +487,8 @@ __serpent_enc_blk16:
        transpose_4x4(RA4, RA1, RA2, RA0, RA3, RTMP0, RTMP1);
        transpose_4x4(RB4, RB1, RB2, RB0, RB3, RTMP0, RTMP1);
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __serpent_enc_blk16,.-__serpent_enc_blk16;)
 
 .align 8
@@ -509,6 +502,7 @@ __serpent_dec_blk16:
         *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
         *                                              plaintext blocks
         */
+       CFI_STARTPROC();
 
        vpcmpeqd RNOT, RNOT, RNOT;
 
@@ -585,7 +579,8 @@ __serpent_dec_blk16:
        transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
        transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __serpent_dec_blk16,.-__serpent_dec_blk16;)
 
 #define inc_le128(x, minus_one, tmp) \
@@ -604,13 +599,14 @@ _gcry_serpent_avx2_ctr_enc:
         *      %rdx: src (16 blocks)
         *      %rcx: iv (big endian, 128bit)
         */
+       CFI_STARTPROC();
 
        movq 8(%rcx), %rax;
        bswapq %rax;
 
        vzeroupper;
 
-       vbroadcasti128 .Lbswap128_mask RIP, RTMP3;
+       vbroadcasti128 .Lbswap128_mask rRIP, RTMP3;
        vpcmpeqd RNOT, RNOT, RNOT;
        vpsrldq $8, RNOT, RNOT;   /* ab: -1:0 ; cd: -1:0 */
        vpaddq RNOT, RNOT, RTMP2; /* ab: -2:0 ; cd: -2:0 */
@@ -701,7 +697,8 @@ _gcry_serpent_avx2_ctr_enc:
 
        vzeroall;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_avx2_ctr_enc,.-_gcry_serpent_avx2_ctr_enc;)
 
 .align 8
@@ -714,6 +711,7 @@ _gcry_serpent_avx2_cbc_dec:
         *      %rdx: src (16 blocks)
         *      %rcx: iv
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
@@ -752,7 +750,8 @@ _gcry_serpent_avx2_cbc_dec:
 
        vzeroall;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_avx2_cbc_dec,.-_gcry_serpent_avx2_cbc_dec;)
 
 .align 8
@@ -765,6 +764,7 @@ _gcry_serpent_avx2_cfb_dec:
         *      %rdx: src (16 blocks)
         *      %rcx: iv
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
@@ -805,7 +805,8 @@ _gcry_serpent_avx2_cfb_dec:
 
        vzeroall;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_avx2_cfb_dec,.-_gcry_serpent_avx2_cfb_dec;)
 
 .align 8
@@ -821,15 +822,21 @@ _gcry_serpent_avx2_ocb_enc:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        vmovdqu (%rcx), RTMP0x;
        vmovdqu (%r8), RTMP1x;
@@ -882,10 +889,15 @@ _gcry_serpent_avx2_ocb_enc:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __serpent_enc_blk16;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        vpxor (0 * 32)(%rsi), RA4, RA4;
        vpxor (1 * 32)(%rsi), RA1, RA1;
@@ -907,7 +919,8 @@ _gcry_serpent_avx2_ocb_enc:
 
        vzeroall;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_avx2_ocb_enc,.-_gcry_serpent_avx2_ocb_enc;)
 
 .align 8
@@ -923,15 +936,21 @@ _gcry_serpent_avx2_ocb_dec:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        vmovdqu (%rcx), RTMP0x;
 
@@ -978,10 +997,15 @@ _gcry_serpent_avx2_ocb_dec:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __serpent_dec_blk16;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        vmovdqu (%r8), RTMP1x;
 
@@ -1019,7 +1043,8 @@ _gcry_serpent_avx2_ocb_dec:
 
        vzeroall;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_avx2_ocb_dec,.-_gcry_serpent_avx2_ocb_dec;)
 
 .align 8
@@ -1034,15 +1059,21 @@ _gcry_serpent_avx2_ocb_auth:
         *      %rcx: checksum
         *      %r8 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        vmovdqu (%rdx), RTMP0x;
 
@@ -1088,10 +1119,15 @@ _gcry_serpent_avx2_ocb_auth:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __serpent_enc_blk16;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        vpxor RA4, RB4, RA4;
        vpxor RA1, RB1, RA1;
@@ -1110,7 +1146,8 @@ _gcry_serpent_avx2_ocb_auth:
 
        vzeroall;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_avx2_ocb_auth,.-_gcry_serpent_avx2_ocb_auth;)
 
 .align 16
index b149af2..b593509 100644 (file)
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_SERPENT)
 
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
+#include "asm-common-amd64.h"
 
 /* struct serpent_context: */
 #define ctx_keys 0
@@ -444,6 +434,7 @@ __serpent_enc_blk8:
         *      RA4, RA1, RA2, RA0, RB4, RB1, RB2, RB0: eight parallel
         *                                              ciphertext blocks
         */
+       CFI_STARTPROC();
 
        pcmpeqd RNOT, RNOT;
 
@@ -518,7 +509,8 @@ __serpent_enc_blk8:
        transpose_4x4(RA4, RA1, RA2, RA0, RA3, RTMP0, RTMP1);
        transpose_4x4(RB4, RB1, RB2, RB0, RB3, RTMP0, RTMP1);
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __serpent_enc_blk8,.-__serpent_enc_blk8;)
 
 .align 8
@@ -532,6 +524,7 @@ __serpent_dec_blk8:
         *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: eight parallel plaintext
         *                                              blocks
         */
+       CFI_STARTPROC();
 
        pcmpeqd RNOT, RNOT;
 
@@ -608,7 +601,8 @@ __serpent_dec_blk8:
        transpose_4x4(RA0, RA1, RA2, RA3, RA4, RTMP0, RTMP1);
        transpose_4x4(RB0, RB1, RB2, RB3, RB4, RTMP0, RTMP1);
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __serpent_dec_blk8,.-__serpent_dec_blk8;)
 
 .align 8
@@ -621,6 +615,7 @@ _gcry_serpent_sse2_ctr_enc:
         *      %rdx: src (8 blocks)
         *      %rcx: iv (big endian, 128bit)
         */
+       CFI_STARTPROC();
 
        /* load IV and byteswap */
        movdqu (%rcx), RA0;
@@ -738,7 +733,8 @@ _gcry_serpent_sse2_ctr_enc:
        pxor RTMP2, RTMP2;
        pxor RNOT, RNOT;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_sse2_ctr_enc,.-_gcry_serpent_sse2_ctr_enc;)
 
 .align 8
@@ -751,6 +747,7 @@ _gcry_serpent_sse2_cbc_dec:
         *      %rdx: src (8 blocks)
         *      %rcx: iv
         */
+       CFI_STARTPROC();
 
        movdqu (0 * 16)(%rdx), RA0;
        movdqu (1 * 16)(%rdx), RA1;
@@ -799,7 +796,8 @@ _gcry_serpent_sse2_cbc_dec:
        pxor RTMP2, RTMP2;
        pxor RNOT, RNOT;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_sse2_cbc_dec,.-_gcry_serpent_sse2_cbc_dec;)
 
 .align 8
@@ -812,6 +810,7 @@ _gcry_serpent_sse2_cfb_dec:
         *      %rdx: src (8 blocks)
         *      %rcx: iv
         */
+       CFI_STARTPROC();
 
        /* Load input */
        movdqu (%rcx), RA0;
@@ -863,7 +862,8 @@ _gcry_serpent_sse2_cfb_dec:
        pxor RTMP2, RTMP2;
        pxor RNOT, RNOT;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_sse2_cfb_dec,.-_gcry_serpent_sse2_cfb_dec;)
 
 .align 8
@@ -879,13 +879,19 @@ _gcry_serpent_sse2_ocb_enc:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[8])
         */
+       CFI_STARTPROC();
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        movdqu (%rcx), RTMP0;
        movdqu (%r8), RTMP1;
@@ -926,10 +932,15 @@ _gcry_serpent_sse2_ocb_enc:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __serpent_enc_blk8;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        pxor_u((0 * 16)(%rsi), RA4, RTMP0);
        pxor_u((1 * 16)(%rsi), RA1, RTMP0);
@@ -965,7 +976,8 @@ _gcry_serpent_sse2_ocb_enc:
        pxor RTMP2, RTMP2;
        pxor RNOT, RNOT;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_sse2_ocb_enc,.-_gcry_serpent_sse2_ocb_enc;)
 
 .align 8
@@ -981,13 +993,19 @@ _gcry_serpent_sse2_ocb_dec:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[8])
         */
+       CFI_STARTPROC();
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        movdqu (%rcx), RTMP0;
 
@@ -1024,10 +1042,15 @@ _gcry_serpent_sse2_ocb_dec:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __serpent_dec_blk8;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        movdqu (%r8), RTMP0;
 
@@ -1077,7 +1100,8 @@ _gcry_serpent_sse2_ocb_dec:
        pxor RTMP2, RTMP2;
        pxor RNOT, RNOT;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_sse2_ocb_dec,.-_gcry_serpent_sse2_ocb_dec;)
 
 .align 8
@@ -1092,13 +1116,19 @@ _gcry_serpent_sse2_ocb_auth:
         *      %rcx: checksum
         *      %r8 : L pointers (void *L[8])
         */
+       CFI_STARTPROC();
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        movdqu (%rdx), RTMP0;
 
@@ -1134,10 +1164,15 @@ _gcry_serpent_sse2_ocb_auth:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __serpent_enc_blk8;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        movdqu (%rcx), RTMP0;
        pxor RB4, RA4;
@@ -1168,7 +1203,8 @@ _gcry_serpent_sse2_ocb_auth:
        pxor RTMP2, RTMP2;
        pxor RNOT, RNOT;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_serpent_sse2_ocb_auth,.-_gcry_serpent_sse2_ocb_auth;)
 
 #endif /*defined(USE_SERPENT)*/
index ea4b8ed..159d889 100644 (file)
@@ -222,9 +222,24 @@ extern void _gcry_serpent_neon_ocb_auth(serpent_context_t *ctx,
 #endif
 
 
-/* A prototype.  */
+/* Prototypes.  */
 static const char *serpent_test (void);
 
+static void _gcry_serpent_ctr_enc (void *context, unsigned char *ctr,
+                                  void *outbuf_arg, const void *inbuf_arg,
+                                  size_t nblocks);
+static void _gcry_serpent_cbc_dec (void *context, unsigned char *iv,
+                                  void *outbuf_arg, const void *inbuf_arg,
+                                  size_t nblocks);
+static void _gcry_serpent_cfb_dec (void *context, unsigned char *iv,
+                                  void *outbuf_arg, const void *inbuf_arg,
+                                  size_t nblocks);
+static size_t _gcry_serpent_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                      const void *inbuf_arg, size_t nblocks,
+                                      int encrypt);
+static size_t _gcry_serpent_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
+                                     size_t nblocks);
+
 
 /*
  * These are the S-Boxes of Serpent from following research paper.
@@ -717,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);
 
@@ -743,12 +761,14 @@ 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.  */
 static gcry_err_code_t
 serpent_setkey (void *ctx,
-               const byte *key, unsigned int key_length)
+               const byte *key, unsigned int key_length,
+                cipher_bulk_ops_t *bulk_ops)
 {
   serpent_context_t *context = ctx;
   static const char *serpent_test_ret;
@@ -764,10 +784,18 @@ serpent_setkey (void *ctx,
        log_error ("Serpent test failure: %s\n", serpent_test_ret);
     }
 
+  /* Setup bulk encryption routines.  */
+  memset (bulk_ops, 0, sizeof(*bulk_ops));
+  bulk_ops->cbc_dec = _gcry_serpent_cbc_dec;
+  bulk_ops->cfb_dec = _gcry_serpent_cfb_dec;
+  bulk_ops->ctr_enc = _gcry_serpent_ctr_enc;
+  bulk_ops->ocb_crypt = _gcry_serpent_ocb_crypt;
+  bulk_ops->ocb_auth  = _gcry_serpent_ocb_auth;
+
   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;
 }
@@ -899,7 +927,7 @@ serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
 /* Bulk encryption of complete blocks in CTR mode.  This function is only
    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
    of size sizeof(serpent_block_t). */
-void
+static void
 _gcry_serpent_ctr_enc(void *context, unsigned char *ctr,
                       void *outbuf_arg, const void *inbuf_arg,
                       size_t nblocks)
@@ -909,7 +937,6 @@ _gcry_serpent_ctr_enc(void *context, unsigned char *ctr,
   const unsigned char *inbuf = inbuf_arg;
   unsigned char tmpbuf[sizeof(serpent_block_t)];
   int burn_stack_depth = 2 * sizeof (serpent_block_t);
-  int i;
 
 #ifdef USE_AVX2
   if (ctx->use_avx2)
@@ -999,16 +1026,11 @@ _gcry_serpent_ctr_enc(void *context, unsigned char *ctr,
       /* Encrypt the counter. */
       serpent_encrypt_internal(ctx, ctr, tmpbuf);
       /* XOR the input with the encrypted counter and store in output.  */
-      buf_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t));
+      cipher_block_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t));
       outbuf += sizeof(serpent_block_t);
       inbuf  += sizeof(serpent_block_t);
       /* Increment the counter.  */
-      for (i = sizeof(serpent_block_t); i > 0; i--)
-        {
-          ctr[i-1]++;
-          if (ctr[i-1])
-            break;
-        }
+      cipher_block_add(ctr, 1, sizeof(serpent_block_t));
     }
 
   wipememory(tmpbuf, sizeof(tmpbuf));
@@ -1017,7 +1039,7 @@ _gcry_serpent_ctr_enc(void *context, unsigned char *ctr,
 
 /* Bulk decryption of complete blocks in CBC mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_serpent_cbc_dec(void *context, unsigned char *iv,
                       void *outbuf_arg, const void *inbuf_arg,
                       size_t nblocks)
@@ -1114,7 +1136,8 @@ _gcry_serpent_cbc_dec(void *context, unsigned char *iv,
          the intermediate result to SAVEBUF.  */
       serpent_decrypt_internal (ctx, inbuf, savebuf);
 
-      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, sizeof(serpent_block_t));
+      cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf,
+                                sizeof(serpent_block_t));
       inbuf += sizeof(serpent_block_t);
       outbuf += sizeof(serpent_block_t);
     }
@@ -1125,7 +1148,7 @@ _gcry_serpent_cbc_dec(void *context, unsigned char *iv,
 
 /* Bulk decryption of complete blocks in CFB mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_serpent_cfb_dec(void *context, unsigned char *iv,
                       void *outbuf_arg, const void *inbuf_arg,
                       size_t nblocks)
@@ -1218,7 +1241,7 @@ _gcry_serpent_cfb_dec(void *context, unsigned char *iv,
   for ( ;nblocks; nblocks-- )
     {
       serpent_encrypt_internal(ctx, iv, iv);
-      buf_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t));
+      cipher_block_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t));
       outbuf += sizeof(serpent_block_t);
       inbuf  += sizeof(serpent_block_t);
     }
@@ -1227,7 +1250,7 @@ _gcry_serpent_cfb_dec(void *context, unsigned char *iv,
 }
 
 /* Bulk encryption/decryption of complete blocks in OCB mode. */
-size_t
+static size_t
 _gcry_serpent_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
                        const void *inbuf_arg, size_t nblocks, int encrypt)
 {
@@ -1414,7 +1437,7 @@ _gcry_serpent_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
 }
 
 /* Bulk authentication of complete blocks in OCB mode. */
-size_t
+static size_t
 _gcry_serpent_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
                        size_t nblocks)
 {
@@ -1594,8 +1617,7 @@ selftest_ctr_128 (void)
   const int context_size = sizeof(serpent_context_t);
 
   return _gcry_selftest_helper_ctr("SERPENT", &serpent_setkey,
-           &serpent_encrypt, &_gcry_serpent_ctr_enc, nblocks, blocksize,
-          context_size);
+           &serpent_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1609,8 +1631,7 @@ selftest_cbc_128 (void)
   const int context_size = sizeof(serpent_context_t);
 
   return _gcry_selftest_helper_cbc("SERPENT", &serpent_setkey,
-           &serpent_encrypt, &_gcry_serpent_cbc_dec, nblocks, blocksize,
-          context_size);
+           &serpent_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1624,8 +1645,7 @@ selftest_cfb_128 (void)
   const int context_size = sizeof(serpent_context_t);
 
   return _gcry_selftest_helper_cfb("SERPENT", &serpent_setkey,
-           &serpent_encrypt, &_gcry_serpent_cfb_dec, nblocks, blocksize,
-          context_size);
+           &serpent_encrypt, nblocks, blocksize, context_size);
 }
 
 
@@ -1722,7 +1742,7 @@ serpent_test (void)
 }
 
 \f
-static gcry_cipher_oid_spec_t serpent128_oids[] =
+static const gcry_cipher_oid_spec_t serpent128_oids[] =
   {
     {"1.3.6.1.4.1.11591.13.2.1", GCRY_CIPHER_MODE_ECB },
     {"1.3.6.1.4.1.11591.13.2.2", GCRY_CIPHER_MODE_CBC },
@@ -1731,7 +1751,7 @@ static gcry_cipher_oid_spec_t serpent128_oids[] =
     { NULL }
   };
 
-static gcry_cipher_oid_spec_t serpent192_oids[] =
+static const gcry_cipher_oid_spec_t serpent192_oids[] =
   {
     {"1.3.6.1.4.1.11591.13.2.21", GCRY_CIPHER_MODE_ECB },
     {"1.3.6.1.4.1.11591.13.2.22", GCRY_CIPHER_MODE_CBC },
@@ -1740,7 +1760,7 @@ static gcry_cipher_oid_spec_t serpent192_oids[] =
     { NULL }
   };
 
-static gcry_cipher_oid_spec_t serpent256_oids[] =
+static const gcry_cipher_oid_spec_t serpent256_oids[] =
   {
     {"1.3.6.1.4.1.11591.13.2.41", GCRY_CIPHER_MODE_ECB },
     {"1.3.6.1.4.1.11591.13.2.42", GCRY_CIPHER_MODE_CBC },
index 61cc541..2de678b 100644 (file)
@@ -303,7 +303,7 @@ gcry_sha1_armv7_neon_K_VEC:
 
 /* Other functional macros */
 
-#define CLEAR_REG(reg) veor reg, reg;
+#define CLEAR_REG(reg) vmov.i8 reg, #0;
 
 
 /*
index bf2b233..059b9a8 100644 (file)
@@ -100,7 +100,7 @@ gcry_sha1_aarch32_ce_K_VEC:
 
 /* Other functional macros */
 
-#define CLEAR_REG(reg) veor reg, reg;
+#define CLEAR_REG(reg) vmov.i8 reg, #0;
 
 
 /*
index ec1810d..ea26564 100644 (file)
@@ -17,7 +17,7 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "asm-common-aarch64.h"
 
 #if defined(__AARCH64EL__) && \
     defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
 .text
 
 
-#define GET_DATA_POINTER(reg, name) \
-               adrp    reg, :got:name ; \
-               ldr     reg, [reg, #:got_lo12:name] ;
-
-
 /* Constants */
 
 #define K1  0x5A827999
@@ -93,7 +88,7 @@ gcry_sha1_aarch64_ce_K_VEC:
 
 /* Other functional macros */
 
-#define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
+#define CLEAR_REG(reg) movi reg.16b, #0;
 
 
 /*
@@ -103,13 +98,14 @@ gcry_sha1_aarch64_ce_K_VEC:
  */
 .align 3
 .globl _gcry_sha1_transform_armv8_ce
-.type  _gcry_sha1_transform_armv8_ce,%function;
+ELF(.type  _gcry_sha1_transform_armv8_ce,%function;)
 _gcry_sha1_transform_armv8_ce:
   /* input:
    *   x0: ctx, CTX
    *   x1: data (64*nblks bytes)
    *   x2: nblks
    */
+  CFI_STARTPROC();
 
   cbz x2, .Ldo_nothing;
 
@@ -198,7 +194,8 @@ _gcry_sha1_transform_armv8_ce:
 
 .Ldo_nothing:
   mov x0, #0
-  ret
-.size _gcry_sha1_transform_armv8_ce,.-_gcry_sha1_transform_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_sha1_transform_armv8_ce,.-_gcry_sha1_transform_armv8_ce;)
 
 #endif
index b14603b..acada96 100644 (file)
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
     defined(HAVE_GCC_INLINE_ASM_AVX) && defined(USE_SHA1)
 
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 
 /* Context structure */
        vpshufb BSWAP_REG, tmp0, W;
 
 #define W_PRECALC_00_15_2(i, W, tmp0) \
-       vpaddd (.LK_XMM + ((i)/20)*16) RIP, W, tmp0;
+       vpaddd (.LK_XMM + ((i)/20)*16) rRIP, W, tmp0;
 
 #define W_PRECALC_00_15_3(i, W, tmp0) \
        vmovdqa tmp0, WK(i&~3);
 #define W_PRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
        vpxor W, tmp0, tmp0; \
        vpxor tmp1, tmp0, W; \
-       vpaddd (.LK_XMM + ((i)/20)*16) RIP, W, tmp0; \
+       vpaddd (.LK_XMM + ((i)/20)*16) rRIP, W, tmp0; \
        vmovdqa tmp0, WK((i)&~3);
 
 #define W_PRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
 
 #define W_PRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
        vpor W, tmp0, W; \
-       vpaddd (.LK_XMM + ((i)/20)*16) RIP, W, tmp0; \
+       vpaddd (.LK_XMM + ((i)/20)*16) rRIP, W, tmp0; \
        vmovdqa tmp0, WK((i)&~3);
 
 
@@ -223,6 +212,7 @@ _gcry_sha1_transform_amd64_avx:
    *   %rsi: data (64*nblks bytes)
    *   %rdx: nblks
    */
+  CFI_STARTPROC();
 
   xorl %eax, %eax;
   cmpq $0, %rdx;
@@ -234,9 +224,12 @@ _gcry_sha1_transform_amd64_avx:
   movq %rdi, RSTATE;
   movq %rsi, RDATA;
   pushq %rbx;
+  CFI_PUSH(%rbx);
   pushq %rbp;
+  CFI_PUSH(%rbp);
 
   movq %rsp, ROLDSTACK;
+  CFI_DEF_CFA_REGISTER(ROLDSTACK);
 
   subq $(16*4), %rsp;
   andq $(~31), %rsp;
@@ -248,7 +241,7 @@ _gcry_sha1_transform_amd64_avx:
   movl state_h3(RSTATE), d;
   movl state_h4(RSTATE), e;
 
-  movdqa .Lbswap_shufb_ctl RIP, BSWAP_REG;
+  vmovdqa .Lbswap_shufb_ctl rRIP, BSWAP_REG;
 
   /* Precalc 0-15. */
   W_PRECALC_00_15_0(0, W0, Wtmp0);
@@ -380,7 +373,7 @@ _gcry_sha1_transform_amd64_avx:
 .Lend:
   vzeroall;
 
-  /* Transform 64-79. */
+  /* Transform 64-79 + burn stack */
   R( b, c, d, e, a, F4, 64 );
   R( a, b, c, d, e, F4, 65 );
   R( e, a, b, c, d, F4, 66 );
@@ -393,12 +386,15 @@ _gcry_sha1_transform_amd64_avx:
   R( c, d, e, a, b, F4, 73 );
   R( b, c, d, e, a, F4, 74 );
   R( a, b, c, d, e, F4, 75 );
-  R( e, a, b, c, d, F4, 76 );
-  R( d, e, a, b, c, F4, 77 );
-  R( c, d, e, a, b, F4, 78 );
+  R( e, a, b, c, d, F4, 76 ); vmovdqa %xmm0, (0*16)(%rsp);
+  R( d, e, a, b, c, F4, 77 ); vmovdqa %xmm0, (1*16)(%rsp);
+  R( c, d, e, a, b, F4, 78 ); vmovdqa %xmm0, (2*16)(%rsp);
   addl state_h0(RSTATE), a;
   R( b, c, d, e, a, F4, 79 );
 
+  /* 16*4/16-1 = 3 */
+  vmovdqa %xmm0, (3*16)(%rsp);
+
   /* Update the chaining variables. */
   addl state_h3(RSTATE), d;
   addl state_h2(RSTATE), c;
@@ -412,15 +408,22 @@ _gcry_sha1_transform_amd64_avx:
   movl e, state_h4(RSTATE);
 
   movq ROLDSTACK, %rsp;
+  CFI_REGISTER(ROLDSTACK, %rsp);
+  CFI_DEF_CFA_REGISTER(%rsp);
 
   popq %rbp;
+  CFI_POP(%rbp);
   popq %rbx;
+  CFI_POP(%rbx);
 
-  /* burn_stack */
-  movl $(16*4 + 2*8 + 31), %eax;
+  /* stack already burned */
+  xorl %eax, %eax;
 
 .Lret:
-  ret;
+  ret_spec_stop;
+  CFI_ENDPROC();
+ELF(.size _gcry_sha1_transform_amd64_avx,
+    .-_gcry_sha1_transform_amd64_avx;)
 
 #endif
 #endif
index b267693..5f4b9e6 100644 (file)
     defined(HAVE_GCC_INLINE_ASM_BMI2) && \
     defined(HAVE_GCC_INLINE_ASM_AVX) && defined(USE_SHA1)
 
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 
 /* Context structure */
 /* Constants */
 
 .text
-#define K1  0x5A827999
-#define K2  0x6ED9EBA1
-#define K3  0x8F1BBCDC
-#define K4  0xCA62C1D6
 .align 16
-.LK_XMM:
-.LK1:  .long K1, K1, K1, K1
-.LK2:  .long K2, K2, K2, K2
-.LK3:  .long K3, K3, K3, K3
-.LK4:  .long K4, K4, K4, K4
-
 .Lbswap_shufb_ctl:
        .long 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f
 
+.LK1:  .long 0x5A827999
+.LK2:  .long 0x6ED9EBA1
+.LK3:  .long 0x8F1BBCDC
+.LK4:  .long 0xCA62C1D6
+
 
 /* Register macros */
 
 #define ROLDSTACK %r10
 #define RNBLKS %r11
 
-#define a %eax
-#define b %ebx
-#define c %ecx
+#define a %esi
+#define b %edi
+#define c %ebp
 #define d %edx
-#define e %edi
+#define e %ecx
+#define ne %ebx
 
-#define RT0 %esi
-#define RT1 %ebp
+#define RT0 %eax
+#define RT1 %r12d
 
 #define Wtmp0 %xmm0
 #define Wtmp1 %xmm1
 
 #define BSWAP_REG %xmm10
 
+#define K1 %xmm11
+#define K2 %xmm12
+#define K3 %xmm13
+#define K4 %xmm14
+
 
 /* Round function macros. */
 
        andl b, RT0; \
        rorxl $2, b, b; \
        addl RT1, e; \
-       leal (RT0,e), e; \
-       rorxl $27, a, RT1; \
-       addl RT1, e;
+       addl ne, a; \
+       leal (RT0,e), ne; \
+       rorxl $27, a, e;
 
 #define R_F2(a,b,c,d,e,i) \
        movl c, RT0; \
        xorl b, RT0; \
        rorxl $2, b, b; \
        xorl d, RT0; \
-       leal (RT0,e), e; \
-       rorxl $27, a, RT1; \
-       addl RT1, e;
+       addl ne, a; \
+       leal (RT0,e), ne; \
+       rorxl $27, a, e;
 
 #define R_F3(a,b,c,d,e,i) \
        movl c, RT0; \
        movl b, RT1; \
+       addl WK(i), e; \
        xorl b, RT0; \
        andl c, RT1; \
        andl d, RT0; \
        addl RT1, e; \
-       addl WK(i), e; \
        rorxl $2, b, b; \
-       leal (RT0,e), e; \
-       rorxl $27, a, RT1; \
-       addl RT1, e;
+       addl ne, a; \
+       leal (RT0,e), ne; \
+       rorxl $27, a, e;
 
 #define R_F4(a,b,c,d,e,i) R_F2(a,b,c,d,e,i)
 
 #define W_PRECALC_00_15_1(i, W, tmp0) \
        vpshufb BSWAP_REG, tmp0, W;
 
-#define W_PRECALC_00_15_2(i, W, tmp0) \
-       vpaddd (.LK_XMM + ((i)/20)*16) RIP, W, tmp0;
+#define W_PRECALC_00_15_2(i, W, tmp0, K) \
+       vpaddd K, W, tmp0;
 
 #define W_PRECALC_00_15_3(i, W, tmp0) \
        vmovdqa tmp0, WK(i&~3);
        vpsrld $30, tmp1, W; \
        vpslld $2, tmp1, tmp1;
 
-#define W_PRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
+#define W_PRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1, K) \
        vpxor W, tmp0, tmp0; \
        vpxor tmp1, tmp0, W; \
-       vpaddd (.LK_XMM + ((i)/20)*16) RIP, W, tmp0; \
+       vpaddd K, W, tmp0; \
        vmovdqa tmp0, WK((i)&~3);
 
 #define W_PRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
        vpsrld $30, W, tmp0; \
        vpslld $2, W, W;
 
-#define W_PRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
+#define W_PRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0, K) \
        vpor W, tmp0, W; \
-       vpaddd (.LK_XMM + ((i)/20)*16) RIP, W, tmp0; \
+       vpaddd K, W, tmp0; \
        vmovdqa tmp0, WK((i)&~3);
 
 
@@ -221,6 +211,7 @@ _gcry_sha1_transform_amd64_avx_bmi2:
    *   %rsi: data (64*nblks bytes)
    *   %rdx: nblks
    */
+  CFI_STARTPROC();
 
   xorl %eax, %eax;
   cmpq $0, %rdx;
@@ -232,9 +223,14 @@ _gcry_sha1_transform_amd64_avx_bmi2:
   movq %rdi, RSTATE;
   movq %rsi, RDATA;
   pushq %rbx;
+  CFI_PUSH(%rbx);
   pushq %rbp;
+  CFI_PUSH(%rbp);
+  pushq %r12;
+  CFI_PUSH(%r12);
 
   movq %rsp, ROLDSTACK;
+  CFI_DEF_CFA_REGISTER(ROLDSTACK);
 
   subq $(16*4), %rsp;
   andq $(~31), %rsp;
@@ -245,25 +241,30 @@ _gcry_sha1_transform_amd64_avx_bmi2:
   movl state_h2(RSTATE), c;
   movl state_h3(RSTATE), d;
   movl state_h4(RSTATE), e;
+  xorl ne, ne;
 
-  movdqa .Lbswap_shufb_ctl RIP, BSWAP_REG;
+  vmovdqa .Lbswap_shufb_ctl rRIP, BSWAP_REG;
+  vpbroadcastd .LK1 rRIP, K1;
+  vpbroadcastd .LK2 rRIP, K2;
+  vpbroadcastd .LK3 rRIP, K3;
+  vpbroadcastd .LK4 rRIP, K4;
 
   /* Precalc 0-15. */
   W_PRECALC_00_15_0(0, W0, Wtmp0);
   W_PRECALC_00_15_1(1, W0, Wtmp0);
-  W_PRECALC_00_15_2(2, W0, Wtmp0);
+  W_PRECALC_00_15_2(2, W0, Wtmp0, K1);
   W_PRECALC_00_15_3(3, W0, Wtmp0);
   W_PRECALC_00_15_0(4, W7, Wtmp0);
   W_PRECALC_00_15_1(5, W7, Wtmp0);
-  W_PRECALC_00_15_2(6, W7, Wtmp0);
+  W_PRECALC_00_15_2(6, W7, Wtmp0, K1);
   W_PRECALC_00_15_3(7, W7, Wtmp0);
   W_PRECALC_00_15_0(8, W6, Wtmp0);
   W_PRECALC_00_15_1(9, W6, Wtmp0);
-  W_PRECALC_00_15_2(10, W6, Wtmp0);
+  W_PRECALC_00_15_2(10, W6, Wtmp0, K1);
   W_PRECALC_00_15_3(11, W6, Wtmp0);
   W_PRECALC_00_15_0(12, W5, Wtmp0);
   W_PRECALC_00_15_1(13, W5, Wtmp0);
-  W_PRECALC_00_15_2(14, W5, Wtmp0);
+  W_PRECALC_00_15_2(14, W5, Wtmp0, K1);
   W_PRECALC_00_15_3(15, W5, Wtmp0);
 
 .align 8
@@ -274,69 +275,69 @@ _gcry_sha1_transform_amd64_avx_bmi2:
   R( a, b, c, d, e, F1,  0 ); W_PRECALC_16_31_0(16, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
   R( e, a, b, c, d, F1,  1 ); W_PRECALC_16_31_1(17, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
   R( d, e, a, b, c, F1,  2 ); W_PRECALC_16_31_2(18, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
-  R( c, d, e, a, b, F1,  3 ); W_PRECALC_16_31_3(19, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
+  R( c, d, e, a, b, F1,  3 ); W_PRECALC_16_31_3(19, W4, W5, W6, W7, W0, Wtmp0, Wtmp1, K1);
   R( b, c, d, e, a, F1,  4 ); W_PRECALC_16_31_0(20, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
   R( a, b, c, d, e, F1,  5 ); W_PRECALC_16_31_1(21, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
   R( e, a, b, c, d, F1,  6 ); W_PRECALC_16_31_2(22, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
-  R( d, e, a, b, c, F1,  7 ); W_PRECALC_16_31_3(23, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
+  R( d, e, a, b, c, F1,  7 ); W_PRECALC_16_31_3(23, W3, W4, W5, W6, W7, Wtmp0, Wtmp1, K2);
   R( c, d, e, a, b, F1,  8 ); W_PRECALC_16_31_0(24, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
   R( b, c, d, e, a, F1,  9 ); W_PRECALC_16_31_1(25, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
   R( a, b, c, d, e, F1, 10 ); W_PRECALC_16_31_2(26, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
-  R( e, a, b, c, d, F1, 11 ); W_PRECALC_16_31_3(27, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
+  R( e, a, b, c, d, F1, 11 ); W_PRECALC_16_31_3(27, W2, W3, W4, W5, W6, Wtmp0, Wtmp1, K2);
   R( d, e, a, b, c, F1, 12 ); W_PRECALC_16_31_0(28, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
   R( c, d, e, a, b, F1, 13 ); W_PRECALC_16_31_1(29, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
   R( b, c, d, e, a, F1, 14 ); W_PRECALC_16_31_2(30, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
-  R( a, b, c, d, e, F1, 15 ); W_PRECALC_16_31_3(31, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
+  R( a, b, c, d, e, F1, 15 ); W_PRECALC_16_31_3(31, W1, W2, W3, W4, W5, Wtmp0, Wtmp1, K2);
 
   /* Transform 16-63 + Precalc 32-79. */
   R( e, a, b, c, d, F1, 16 ); W_PRECALC_32_79_0(32, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
   R( d, e, a, b, c, F1, 17 ); W_PRECALC_32_79_1(33, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
   R( c, d, e, a, b, F1, 18 ); W_PRECALC_32_79_2(34, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
-  R( b, c, d, e, a, F1, 19 ); W_PRECALC_32_79_3(35, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
+  R( b, c, d, e, a, F1, 19 ); W_PRECALC_32_79_3(35, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0, K2);
   R( a, b, c, d, e, F2, 20 ); W_PRECALC_32_79_0(36, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
   R( e, a, b, c, d, F2, 21 ); W_PRECALC_32_79_1(37, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
   R( d, e, a, b, c, F2, 22 ); W_PRECALC_32_79_2(38, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
-  R( c, d, e, a, b, F2, 23 ); W_PRECALC_32_79_3(39, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
+  R( c, d, e, a, b, F2, 23 ); W_PRECALC_32_79_3(39, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0, K2);
   R( b, c, d, e, a, F2, 24 ); W_PRECALC_32_79_0(40, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
   R( a, b, c, d, e, F2, 25 ); W_PRECALC_32_79_1(41, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
   R( e, a, b, c, d, F2, 26 ); W_PRECALC_32_79_2(42, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
-  R( d, e, a, b, c, F2, 27 ); W_PRECALC_32_79_3(43, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
+  R( d, e, a, b, c, F2, 27 ); W_PRECALC_32_79_3(43, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0, K3);
   R( c, d, e, a, b, F2, 28 ); W_PRECALC_32_79_0(44, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
   R( b, c, d, e, a, F2, 29 ); W_PRECALC_32_79_1(45, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
   R( a, b, c, d, e, F2, 30 ); W_PRECALC_32_79_2(46, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
-  R( e, a, b, c, d, F2, 31 ); W_PRECALC_32_79_3(47, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
+  R( e, a, b, c, d, F2, 31 ); W_PRECALC_32_79_3(47, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0, K3);
   R( d, e, a, b, c, F2, 32 ); W_PRECALC_32_79_0(48, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
   R( c, d, e, a, b, F2, 33 ); W_PRECALC_32_79_1(49, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
   R( b, c, d, e, a, F2, 34 ); W_PRECALC_32_79_2(50, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
-  R( a, b, c, d, e, F2, 35 ); W_PRECALC_32_79_3(51, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
+  R( a, b, c, d, e, F2, 35 ); W_PRECALC_32_79_3(51, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0, K3);
   R( e, a, b, c, d, F2, 36 ); W_PRECALC_32_79_0(52, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
   R( d, e, a, b, c, F2, 37 ); W_PRECALC_32_79_1(53, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
   R( c, d, e, a, b, F2, 38 ); W_PRECALC_32_79_2(54, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
-  R( b, c, d, e, a, F2, 39 ); W_PRECALC_32_79_3(55, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
+  R( b, c, d, e, a, F2, 39 ); W_PRECALC_32_79_3(55, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0, K3);
   R( a, b, c, d, e, F3, 40 ); W_PRECALC_32_79_0(56, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
   R( e, a, b, c, d, F3, 41 ); W_PRECALC_32_79_1(57, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
   R( d, e, a, b, c, F3, 42 ); W_PRECALC_32_79_2(58, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
-  R( c, d, e, a, b, F3, 43 ); W_PRECALC_32_79_3(59, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
+  R( c, d, e, a, b, F3, 43 ); W_PRECALC_32_79_3(59, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0, K3);
   R( b, c, d, e, a, F3, 44 ); W_PRECALC_32_79_0(60, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
   R( a, b, c, d, e, F3, 45 ); W_PRECALC_32_79_1(61, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
   R( e, a, b, c, d, F3, 46 ); W_PRECALC_32_79_2(62, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
-  R( d, e, a, b, c, F3, 47 ); W_PRECALC_32_79_3(63, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
+  R( d, e, a, b, c, F3, 47 ); W_PRECALC_32_79_3(63, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0, K4);
   R( c, d, e, a, b, F3, 48 ); W_PRECALC_32_79_0(64, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
   R( b, c, d, e, a, F3, 49 ); W_PRECALC_32_79_1(65, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
   R( a, b, c, d, e, F3, 50 ); W_PRECALC_32_79_2(66, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
-  R( e, a, b, c, d, F3, 51 ); W_PRECALC_32_79_3(67, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
+  R( e, a, b, c, d, F3, 51 ); W_PRECALC_32_79_3(67, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0, K4);
   R( d, e, a, b, c, F3, 52 ); W_PRECALC_32_79_0(68, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
   R( c, d, e, a, b, F3, 53 ); W_PRECALC_32_79_1(69, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
   R( b, c, d, e, a, F3, 54 ); W_PRECALC_32_79_2(70, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
-  R( a, b, c, d, e, F3, 55 ); W_PRECALC_32_79_3(71, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
+  R( a, b, c, d, e, F3, 55 ); W_PRECALC_32_79_3(71, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0, K4);
   R( e, a, b, c, d, F3, 56 ); W_PRECALC_32_79_0(72, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
   R( d, e, a, b, c, F3, 57 ); W_PRECALC_32_79_1(73, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
   R( c, d, e, a, b, F3, 58 ); W_PRECALC_32_79_2(74, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
-  R( b, c, d, e, a, F3, 59 ); W_PRECALC_32_79_3(75, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
+  R( b, c, d, e, a, F3, 59 ); W_PRECALC_32_79_3(75, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0, K4);
   R( a, b, c, d, e, F4, 60 ); W_PRECALC_32_79_0(76, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
   R( e, a, b, c, d, F4, 61 ); W_PRECALC_32_79_1(77, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
   R( d, e, a, b, c, F4, 62 ); W_PRECALC_32_79_2(78, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
-  R( c, d, e, a, b, F4, 63 ); W_PRECALC_32_79_3(79, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
+  R( c, d, e, a, b, F4, 63 ); W_PRECALC_32_79_3(79, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0, K4);
 
   decq RNBLKS;
   jz .Lend;
@@ -344,21 +345,23 @@ _gcry_sha1_transform_amd64_avx_bmi2:
   /* Transform 64-79 + Precalc 0-15 of next block. */
   R( b, c, d, e, a, F4, 64 ); W_PRECALC_00_15_0(0, W0, Wtmp0);
   R( a, b, c, d, e, F4, 65 ); W_PRECALC_00_15_1(1, W0, Wtmp0);
-  R( e, a, b, c, d, F4, 66 ); W_PRECALC_00_15_2(2, W0, Wtmp0);
+  R( e, a, b, c, d, F4, 66 ); W_PRECALC_00_15_2(2, W0, Wtmp0, K1);
   R( d, e, a, b, c, F4, 67 ); W_PRECALC_00_15_3(3, W0, Wtmp0);
   R( c, d, e, a, b, F4, 68 ); W_PRECALC_00_15_0(4, W7, Wtmp0);
   R( b, c, d, e, a, F4, 69 ); W_PRECALC_00_15_1(5, W7, Wtmp0);
-  R( a, b, c, d, e, F4, 70 ); W_PRECALC_00_15_2(6, W7, Wtmp0);
+  R( a, b, c, d, e, F4, 70 ); W_PRECALC_00_15_2(6, W7, Wtmp0, K1);
   R( e, a, b, c, d, F4, 71 ); W_PRECALC_00_15_3(7, W7, Wtmp0);
   R( d, e, a, b, c, F4, 72 ); W_PRECALC_00_15_0(8, W6, Wtmp0);
   R( c, d, e, a, b, F4, 73 ); W_PRECALC_00_15_1(9, W6, Wtmp0);
-  R( b, c, d, e, a, F4, 74 ); W_PRECALC_00_15_2(10, W6, Wtmp0);
+  R( b, c, d, e, a, F4, 74 ); W_PRECALC_00_15_2(10, W6, Wtmp0, K1);
   R( a, b, c, d, e, F4, 75 ); W_PRECALC_00_15_3(11, W6, Wtmp0);
   R( e, a, b, c, d, F4, 76 ); W_PRECALC_00_15_0(12, W5, Wtmp0);
   R( d, e, a, b, c, F4, 77 ); W_PRECALC_00_15_1(13, W5, Wtmp0);
   R( c, d, e, a, b, F4, 78 );
-  addl state_h0(RSTATE), a;   W_PRECALC_00_15_2(14, W5, Wtmp0);
+  addl state_h0(RSTATE), a;   W_PRECALC_00_15_2(14, W5, Wtmp0, K1);
   R( b, c, d, e, a, F4, 79 ); W_PRECALC_00_15_3(15, W5, Wtmp0);
+  addl ne, a;
+  xorl ne, ne;
 
   /* Update the chaining variables. */
   addl state_h3(RSTATE), d;
@@ -378,7 +381,7 @@ _gcry_sha1_transform_amd64_avx_bmi2:
 .Lend:
   vzeroall;
 
-  /* Transform 64-79. */
+  /* Transform 64-79 + burn stack */
   R( b, c, d, e, a, F4, 64 );
   R( a, b, c, d, e, F4, 65 );
   R( e, a, b, c, d, F4, 66 );
@@ -391,11 +394,16 @@ _gcry_sha1_transform_amd64_avx_bmi2:
   R( c, d, e, a, b, F4, 73 );
   R( b, c, d, e, a, F4, 74 );
   R( a, b, c, d, e, F4, 75 );
-  R( e, a, b, c, d, F4, 76 );
-  R( d, e, a, b, c, F4, 77 );
-  R( c, d, e, a, b, F4, 78 );
+  R( e, a, b, c, d, F4, 76 ); vmovdqa %xmm0, (0*16)(%rsp);
+  R( d, e, a, b, c, F4, 77 ); vmovdqa %xmm0, (1*16)(%rsp);
+  R( c, d, e, a, b, F4, 78 ); vmovdqa %xmm0, (2*16)(%rsp);
   addl state_h0(RSTATE), a;
   R( b, c, d, e, a, F4, 79 );
+  addl ne, a;
+  xorl ne, ne;
+
+  /* 16*4/16-1 = 3 */
+  vmovdqa %xmm0, (3*16)(%rsp);
 
   /* Update the chaining variables. */
   addl state_h3(RSTATE), d;
@@ -410,15 +418,24 @@ _gcry_sha1_transform_amd64_avx_bmi2:
   movl e, state_h4(RSTATE);
 
   movq ROLDSTACK, %rsp;
+  CFI_REGISTER(ROLDSTACK, %rsp);
+  CFI_DEF_CFA_REGISTER(%rsp);
 
+  popq %r12;
+  CFI_POP(%r12);
   popq %rbp;
+  CFI_POP(%rbp);
   popq %rbx;
+  CFI_POP(%rbx);
 
-  /* burn_stack */
-  movl $(16*4 + 2*8 + 31), %eax;
+  /* stack already burned */
+  xorl %eax, %eax;
 
 .Lret:
-  ret;
+  ret_spec_stop;
+  CFI_ENDPROC();
+ELF(.size _gcry_sha1_transform_amd64_avx_bmi2,
+    .-_gcry_sha1_transform_amd64_avx_bmi2;)
 
 #endif
 #endif
diff --git a/cipher/sha1-avx2-bmi2-amd64.S b/cipher/sha1-avx2-bmi2-amd64.S
new file mode 100644 (file)
index 0000000..ed52761
--- /dev/null
@@ -0,0 +1,573 @@
+/* sha1-avx2-bmi2-amd64.S - Intel AVX2/BMI2 accelerated SHA-1 transform function
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * Based on sha1.c:
+ *  Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Intel SSSE3 accelerated SHA-1 implementation based on white paper:
+ *  "Improving the Performance of the Secure Hash Algorithm (SHA-1)"
+ *  http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1
+ */
+
+#ifdef __x86_64__
+#include <config.h>
+
+#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
+     defined(HAVE_GCC_INLINE_ASM_BMI2) && defined(HAVE_GCC_INLINE_ASM_AVX) && \
+     defined(HAVE_GCC_INLINE_ASM_AVX2) && defined(USE_SHA1)
+
+#include "asm-common-amd64.h"
+
+
+/* Context structure */
+
+#define state_h0 0
+#define state_h1 4
+#define state_h2 8
+#define state_h3 12
+#define state_h4 16
+
+
+/* Constants */
+
+#define WK_STACK_WORDS (80 * 2)
+
+.text
+.align 16
+.Lbswap_shufb_ctl:
+       .long 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f
+
+.LK1:  .long 0x5A827999
+.LK2:  .long 0x6ED9EBA1
+.LK3:  .long 0x8F1BBCDC
+.LK4:  .long 0xCA62C1D6
+
+
+/* Register macros */
+
+#define RSTATE %r8
+#define RDATA %r9
+#define ROLDSTACK %r10
+#define RNBLKS %r11
+
+#define a %eax
+#define b %ebx
+#define c %ecx
+#define d %edx
+#define e %edi
+#define ne %r12d
+
+#define RT0 %esi
+#define RT1 %ebp
+
+#define Wtmp0 %ymm0
+#define Wtmp1 %ymm1
+#define Wtmp0x %xmm0
+#define Wtmp1x %xmm1
+
+#define W0 %ymm2
+#define W1 %ymm3
+#define W2 %ymm4
+#define W3 %ymm5
+#define W4 %ymm6
+#define W5 %ymm7
+#define W6 %ymm8
+#define W7 %ymm9
+
+#define BSWAP_REG %ymm10
+
+#define K1 %ymm11
+#define K2 %ymm12
+#define K3 %ymm13
+#define K4 %ymm14
+
+
+/* Round function macros. */
+
+#define WK(i,block) ((block) * 16 + ((i) / 4) * 32 + ((i) % 4) * 4)(%rsp)
+#define PRE_WK(i) ((i) * 4 * 2)(%rsp)
+
+#define R_F1(a,b,c,d,e,i,block) \
+       movl c, RT0; \
+       andn d, b, RT1; \
+       addl WK(i,block), e; \
+       andl b, RT0; \
+       leal (a,ne), a; \
+       rorxl $2, b, b; \
+       addl RT1, e; \
+       rorxl $27, a, ne; \
+       addl RT0, e;
+
+#define R_F2(a,b,c,d,e,i,block) \
+       addl WK(i,block), e; \
+       movl c, RT0; \
+       xorl b, RT0; \
+       leal (a,ne), a; \
+       rorxl $2, b, b; \
+       xorl d, RT0; \
+       addl RT0, e; \
+       rorxl $27, a, ne;
+
+#define R_F3(a,b,c,d,e,i,block) \
+       movl c, RT0; \
+       addl WK(i,block), e; \
+       movl b, RT1; \
+       xorl b, RT0; \
+       leal (a,ne), a; \
+       rorxl $2, b, b; \
+       andl c, RT1; \
+       addl RT1, e; \
+       andl d, RT0; \
+       rorxl $27, a, ne; \
+       addl RT0, e;
+
+#define R_F4(a,b,c,d,e,i,block) R_F2(a,b,c,d,e,i,block)
+
+#define R(a,b,c,d,e,f,i,block) \
+       R_##f(a,b,c,d,e,i,block)
+
+
+/* Input expansion macros. */
+
+#define W_PRECALC_00_15_0(i, W, tmp0) \
+       vmovdqu (4*(i))(RDATA), tmp0##x; \
+       vinserti128 $1, (4*(i) + 64)(RDATA), tmp0, tmp0;
+
+#define W_PRECALC_00_15_1(i, W, tmp0) \
+       vpshufb BSWAP_REG, tmp0, W;
+
+#define W_PRECALC_00_15_2(i, W, tmp0, K) \
+       vpaddd K, W, tmp0;
+
+#define W_PRECALC_00_15_3(i, W, tmp0) \
+       vmovdqa tmp0, PRE_WK((i)&~3);
+
+#define W_PRECALC_16_31_0(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
+       vpalignr $8, W_m16, W_m12, W; \
+       vpsrldq $4, W_m04, tmp0; \
+       vpxor W_m08, W, W;
+
+#define W_PRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
+       vpxor W_m16, tmp0, tmp0; \
+       vpxor tmp0, W, W; \
+       vpslld $1, W, tmp0; \
+       vpslldq $12, W, tmp1; \
+       vpsrld $31, W, W;
+
+#define W_PRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1) \
+       vpor W, tmp0, tmp0; \
+       vpsrld $30, tmp1, W; \
+       vpslld $2, tmp1, tmp1;
+
+#define W_PRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, tmp0, tmp1, K) \
+       vpxor W, tmp0, tmp0; \
+       vpxor tmp1, tmp0, W; \
+       vpaddd K, W, tmp0; \
+       vmovdqa tmp0, PRE_WK((i)&~3);
+
+#define W_PRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
+       vpxor W_m28, W, W; \
+       vpalignr $8, W_m08, W_m04, tmp0;
+
+#define W_PRECALC_32_79_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
+       vpxor W_m16, W, W; \
+       vpxor tmp0, W, W;
+
+#define W_PRECALC_32_79_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
+       vpsrld $30, W, tmp0; \
+       vpslld $2, W, W;
+
+#define W_PRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0, K) \
+       vpor W, tmp0, W; \
+       vpaddd K, W, tmp0; \
+       vmovdqa tmp0, PRE_WK((i)&~3);
+
+
+/*
+ * Transform 2*nblks*64 bytes (2*nblks*16 32-bit words) at DATA.
+ *
+ * unsigned int
+ * _gcry_sha1_transform_amd64_avx2_bmi2 (void *ctx, const unsigned char *data,
+ *                                       size_t nblks)
+ */
+.globl _gcry_sha1_transform_amd64_avx2_bmi2
+ELF(.type _gcry_sha1_transform_amd64_avx2_bmi2,@function)
+.align 16
+_gcry_sha1_transform_amd64_avx2_bmi2:
+  /* input:
+   *   %rdi: ctx, CTX
+   *   %rsi: data (64*nblks bytes)
+   *   %rdx: nblks (multiple of 2, larger than 0)
+   */
+  CFI_STARTPROC();
+
+  vzeroupper;
+
+  movq %rdx, RNBLKS;
+  movq %rdi, RSTATE;
+  movq %rsi, RDATA;
+  pushq %rbx;
+  CFI_PUSH(%rbx);
+  pushq %rbp;
+  CFI_PUSH(%rbp);
+  pushq %r12;
+  CFI_PUSH(%r12);
+
+  movq %rsp, ROLDSTACK;
+  CFI_DEF_CFA_REGISTER(ROLDSTACK);
+
+  subq $(WK_STACK_WORDS*4), %rsp;
+  andq $(~63), %rsp;
+
+  /* Get the values of the chaining variables. */
+  movl state_h0(RSTATE), a;
+  movl state_h1(RSTATE), b;
+  movl state_h2(RSTATE), c;
+  movl state_h3(RSTATE), d;
+  movl state_h4(RSTATE), e;
+  xorl ne, ne;
+
+  vbroadcasti128 .Lbswap_shufb_ctl rRIP, BSWAP_REG;
+  vpbroadcastd .LK1 rRIP, K1;
+  vpbroadcastd .LK2 rRIP, K2;
+  vpbroadcastd .LK3 rRIP, K3;
+  vpbroadcastd .LK4 rRIP, K4;
+
+  /* Precalc 0-31 for block 1 & 2. */
+  W_PRECALC_00_15_0(0, W0, Wtmp0);
+  W_PRECALC_00_15_1(1, W0, Wtmp0);
+  W_PRECALC_00_15_2(2, W0, Wtmp0, K1);
+  W_PRECALC_00_15_3(3, W0, Wtmp0);
+  W_PRECALC_00_15_0(4, W7, Wtmp0);
+  W_PRECALC_00_15_1(5, W7, Wtmp0);
+  W_PRECALC_00_15_2(6, W7, Wtmp0, K1);
+  W_PRECALC_00_15_3(7, W7, Wtmp0);
+  W_PRECALC_00_15_0(8, W6, Wtmp0);
+  W_PRECALC_00_15_1(9, W6, Wtmp0);
+  W_PRECALC_00_15_2(10, W6, Wtmp0, K1);
+  W_PRECALC_00_15_3(11, W6, Wtmp0);
+  W_PRECALC_00_15_0(12, W5, Wtmp0);
+  W_PRECALC_00_15_1(13, W5, Wtmp0);
+  W_PRECALC_00_15_2(14, W5, Wtmp0, K1);
+  W_PRECALC_00_15_3(15, W5, Wtmp0);
+  W_PRECALC_16_31_0(16, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_1(17, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_2(18, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_3(19, W4, W5, W6, W7, W0, Wtmp0, Wtmp1, K1);
+  W_PRECALC_16_31_0(20, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_1(21, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_2(22, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_3(23, W3, W4, W5, W6, W7, Wtmp0, Wtmp1, K2);
+  W_PRECALC_16_31_0(24, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_1(25, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_2(26, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_3(27, W2, W3, W4, W5, W6, Wtmp0, Wtmp1, K2);
+  W_PRECALC_16_31_0(28, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_1(29, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_2(30, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
+  W_PRECALC_16_31_3(31, W1, W2, W3, W4, W5, Wtmp0, Wtmp1, K2);
+
+.align 8
+.Loop:
+  addq $(2 * 64), RDATA;
+
+  /* Transform 0-15 for block 1 + Precalc 32-47 for block 1 & 2. */
+  R( a, b, c, d, e, F1,  0, 0 ); W_PRECALC_32_79_0(32, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
+  R( e, a, b, c, d, F1,  1, 0 ); W_PRECALC_32_79_1(33, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
+  R( d, e, a, b, c, F1,  2, 0 ); W_PRECALC_32_79_2(34, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
+  R( c, d, e, a, b, F1,  3, 0 ); W_PRECALC_32_79_3(35, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0, K2);
+  R( b, c, d, e, a, F1,  4, 0 ); W_PRECALC_32_79_0(36, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
+  R( a, b, c, d, e, F1,  5, 0 ); W_PRECALC_32_79_1(37, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
+  R( e, a, b, c, d, F1,  6, 0 ); W_PRECALC_32_79_2(38, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
+  R( d, e, a, b, c, F1,  7, 0 ); W_PRECALC_32_79_3(39, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0, K2);
+  R( c, d, e, a, b, F1,  8, 0 ); W_PRECALC_32_79_0(40, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
+  R( b, c, d, e, a, F1,  9, 0 ); W_PRECALC_32_79_1(41, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
+  R( a, b, c, d, e, F1, 10, 0 ); W_PRECALC_32_79_2(42, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
+  R( e, a, b, c, d, F1, 11, 0 ); W_PRECALC_32_79_3(43, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0, K3);
+  R( d, e, a, b, c, F1, 12, 0 ); W_PRECALC_32_79_0(44, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
+  R( c, d, e, a, b, F1, 13, 0 ); W_PRECALC_32_79_1(45, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
+  R( b, c, d, e, a, F1, 14, 0 ); W_PRECALC_32_79_2(46, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
+  R( a, b, c, d, e, F1, 15, 0 ); W_PRECALC_32_79_3(47, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0, K3);
+
+  /* Transform 16-47 for block 1 + Precalc 48-79 for block 1 & 2. */
+  R( e, a, b, c, d, F1, 16, 0 ); W_PRECALC_32_79_0(48, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
+  R( d, e, a, b, c, F1, 17, 0 ); W_PRECALC_32_79_1(49, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
+  R( c, d, e, a, b, F1, 18, 0 ); W_PRECALC_32_79_2(50, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0);
+  R( b, c, d, e, a, F1, 19, 0 ); W_PRECALC_32_79_3(51, W4, W5, W6, W7, W0, W1, W2, W3, Wtmp0, K3);
+  R( a, b, c, d, e, F2, 20, 0 ); W_PRECALC_32_79_0(52, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
+  R( e, a, b, c, d, F2, 21, 0 ); W_PRECALC_32_79_1(53, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
+  R( d, e, a, b, c, F2, 22, 0 ); W_PRECALC_32_79_2(54, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0);
+  R( c, d, e, a, b, F2, 23, 0 ); W_PRECALC_32_79_3(55, W3, W4, W5, W6, W7, W0, W1, W2, Wtmp0, K3);
+  R( b, c, d, e, a, F2, 24, 0 ); W_PRECALC_32_79_0(56, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
+  R( a, b, c, d, e, F2, 25, 0 ); W_PRECALC_32_79_1(57, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
+  R( e, a, b, c, d, F2, 26, 0 ); W_PRECALC_32_79_2(58, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0);
+  R( d, e, a, b, c, F2, 27, 0 ); W_PRECALC_32_79_3(59, W2, W3, W4, W5, W6, W7, W0, W1, Wtmp0, K3);
+  R( c, d, e, a, b, F2, 28, 0 ); W_PRECALC_32_79_0(60, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
+  R( b, c, d, e, a, F2, 29, 0 ); W_PRECALC_32_79_1(61, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
+  R( a, b, c, d, e, F2, 30, 0 ); W_PRECALC_32_79_2(62, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0);
+  R( e, a, b, c, d, F2, 31, 0 ); W_PRECALC_32_79_3(63, W1, W2, W3, W4, W5, W6, W7, W0, Wtmp0, K4);
+  R( d, e, a, b, c, F2, 32, 0 ); W_PRECALC_32_79_0(64, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
+  R( c, d, e, a, b, F2, 33, 0 ); W_PRECALC_32_79_1(65, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
+  R( b, c, d, e, a, F2, 34, 0 ); W_PRECALC_32_79_2(66, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0);
+  R( a, b, c, d, e, F2, 35, 0 ); W_PRECALC_32_79_3(67, W0, W1, W2, W3, W4, W5, W6, W7, Wtmp0, K4);
+  R( e, a, b, c, d, F2, 36, 0 ); W_PRECALC_32_79_0(68, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
+  R( d, e, a, b, c, F2, 37, 0 ); W_PRECALC_32_79_1(69, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
+  R( c, d, e, a, b, F2, 38, 0 ); W_PRECALC_32_79_2(70, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0);
+  R( b, c, d, e, a, F2, 39, 0 ); W_PRECALC_32_79_3(71, W7, W0, W1, W2, W3, W4, W5, W6, Wtmp0, K4);
+  R( a, b, c, d, e, F3, 40, 0 ); W_PRECALC_32_79_0(72, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
+  R( e, a, b, c, d, F3, 41, 0 ); W_PRECALC_32_79_1(73, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
+  R( d, e, a, b, c, F3, 42, 0 ); W_PRECALC_32_79_2(74, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0);
+  R( c, d, e, a, b, F3, 43, 0 ); W_PRECALC_32_79_3(75, W6, W7, W0, W1, W2, W3, W4, W5, Wtmp0, K4);
+  R( b, c, d, e, a, F3, 44, 0 ); W_PRECALC_32_79_0(76, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
+  R( a, b, c, d, e, F3, 45, 0 ); W_PRECALC_32_79_1(77, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
+  R( e, a, b, c, d, F3, 46, 0 ); W_PRECALC_32_79_2(78, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0);
+  R( d, e, a, b, c, F3, 47, 0 ); W_PRECALC_32_79_3(79, W5, W6, W7, W0, W1, W2, W3, W4, Wtmp0, K4);
+
+  /* Transform 48-79 for block 1. */
+  R( c, d, e, a, b, F3, 48, 0 );
+  R( b, c, d, e, a, F3, 49, 0 );
+  R( a, b, c, d, e, F3, 50, 0 );
+  R( e, a, b, c, d, F3, 51, 0 );
+  R( d, e, a, b, c, F3, 52, 0 );
+  R( c, d, e, a, b, F3, 53, 0 );
+  R( b, c, d, e, a, F3, 54, 0 );
+  R( a, b, c, d, e, F3, 55, 0 );
+  R( e, a, b, c, d, F3, 56, 0 );
+  R( d, e, a, b, c, F3, 57, 0 );
+  R( c, d, e, a, b, F3, 58, 0 );
+  R( b, c, d, e, a, F3, 59, 0 );
+  R( a, b, c, d, e, F4, 60, 0 );
+  R( e, a, b, c, d, F4, 61, 0 );
+  R( d, e, a, b, c, F4, 62, 0 );
+  R( c, d, e, a, b, F4, 63, 0 );
+  R( b, c, d, e, a, F4, 64, 0 );
+  R( a, b, c, d, e, F4, 65, 0 );
+  R( e, a, b, c, d, F4, 66, 0 );
+  R( d, e, a, b, c, F4, 67, 0 );
+  R( c, d, e, a, b, F4, 68, 0 );
+  R( b, c, d, e, a, F4, 69, 0 );
+  R( a, b, c, d, e, F4, 70, 0 );
+  R( e, a, b, c, d, F4, 71, 0 );
+  R( d, e, a, b, c, F4, 72, 0 );
+  R( c, d, e, a, b, F4, 73, 0 );
+  R( b, c, d, e, a, F4, 74, 0 );
+  R( a, b, c, d, e, F4, 75, 0 );
+  R( e, a, b, c, d, F4, 76, 0 );
+  R( d, e, a, b, c, F4, 77, 0 );
+  R( c, d, e, a, b, F4, 78, 0 );
+  addl state_h0(RSTATE), a;
+  R( b, c, d, e, a, F4, 79, 0 );
+  addl ne, a;
+  xorl ne, ne;
+
+  /* Update the chaining variables. */
+  addl state_h3(RSTATE), d;
+  addl state_h2(RSTATE), c;
+  addl state_h1(RSTATE), b;
+  addl state_h4(RSTATE), e;
+
+  movl d, state_h3(RSTATE);
+  movl c, state_h2(RSTATE);
+  movl b, state_h1(RSTATE);
+  movl a, state_h0(RSTATE);
+  movl e, state_h4(RSTATE);
+
+  /* Transform 0-47 for block 2. */
+  R( a, b, c, d, e, F1,  0, 1 );
+  R( e, a, b, c, d, F1,  1, 1 );
+  R( d, e, a, b, c, F1,  2, 1 );
+  R( c, d, e, a, b, F1,  3, 1 );
+  R( b, c, d, e, a, F1,  4, 1 );
+  R( a, b, c, d, e, F1,  5, 1 );
+  R( e, a, b, c, d, F1,  6, 1 );
+  R( d, e, a, b, c, F1,  7, 1 );
+  R( c, d, e, a, b, F1,  8, 1 );
+  R( b, c, d, e, a, F1,  9, 1 );
+  R( a, b, c, d, e, F1, 10, 1 );
+  R( e, a, b, c, d, F1, 11, 1 );
+  R( d, e, a, b, c, F1, 12, 1 );
+  R( c, d, e, a, b, F1, 13, 1 );
+  R( b, c, d, e, a, F1, 14, 1 );
+  R( a, b, c, d, e, F1, 15, 1 );
+  R( e, a, b, c, d, F1, 16, 1 );
+  R( d, e, a, b, c, F1, 17, 1 );
+  R( c, d, e, a, b, F1, 18, 1 );
+  R( b, c, d, e, a, F1, 19, 1 );
+  R( a, b, c, d, e, F2, 20, 1 );
+  R( e, a, b, c, d, F2, 21, 1 );
+  R( d, e, a, b, c, F2, 22, 1 );
+  R( c, d, e, a, b, F2, 23, 1 );
+  R( b, c, d, e, a, F2, 24, 1 );
+  R( a, b, c, d, e, F2, 25, 1 );
+  R( e, a, b, c, d, F2, 26, 1 );
+  R( d, e, a, b, c, F2, 27, 1 );
+  R( c, d, e, a, b, F2, 28, 1 );
+  R( b, c, d, e, a, F2, 29, 1 );
+  R( a, b, c, d, e, F2, 30, 1 );
+  R( e, a, b, c, d, F2, 31, 1 );
+  R( d, e, a, b, c, F2, 32, 1 );
+  R( c, d, e, a, b, F2, 33, 1 );
+  R( b, c, d, e, a, F2, 34, 1 );
+  R( a, b, c, d, e, F2, 35, 1 );
+  R( e, a, b, c, d, F2, 36, 1 );
+  R( d, e, a, b, c, F2, 37, 1 );
+  R( c, d, e, a, b, F2, 38, 1 );
+  R( b, c, d, e, a, F2, 39, 1 );
+  R( a, b, c, d, e, F3, 40, 1 );
+  R( e, a, b, c, d, F3, 41, 1 );
+  R( d, e, a, b, c, F3, 42, 1 );
+  R( c, d, e, a, b, F3, 43, 1 );
+  R( b, c, d, e, a, F3, 44, 1 );
+  R( a, b, c, d, e, F3, 45, 1 );
+  R( e, a, b, c, d, F3, 46, 1 );
+  R( d, e, a, b, c, F3, 47, 1 );
+
+  addq $-2, RNBLKS;
+  jz .Lend;
+
+  /* Transform 48-79 for block 2 + Precalc 0-31 for next two blocks. */
+  R( c, d, e, a, b, F3, 48, 1 ); W_PRECALC_00_15_0(0, W0, Wtmp0);
+  R( b, c, d, e, a, F3, 49, 1 ); W_PRECALC_00_15_1(1, W0, Wtmp0);
+  R( a, b, c, d, e, F3, 50, 1 ); W_PRECALC_00_15_2(2, W0, Wtmp0, K1);
+  R( e, a, b, c, d, F3, 51, 1 ); W_PRECALC_00_15_3(3, W0, Wtmp0);
+  R( d, e, a, b, c, F3, 52, 1 ); W_PRECALC_00_15_0(4, W7, Wtmp0);
+  R( c, d, e, a, b, F3, 53, 1 ); W_PRECALC_00_15_1(5, W7, Wtmp0);
+  R( b, c, d, e, a, F3, 54, 1 ); W_PRECALC_00_15_2(6, W7, Wtmp0, K1);
+  R( a, b, c, d, e, F3, 55, 1 ); W_PRECALC_00_15_3(7, W7, Wtmp0);
+  R( e, a, b, c, d, F3, 56, 1 ); W_PRECALC_00_15_0(8, W6, Wtmp0);
+  R( d, e, a, b, c, F3, 57, 1 ); W_PRECALC_00_15_1(9, W6, Wtmp0);
+  R( c, d, e, a, b, F3, 58, 1 ); W_PRECALC_00_15_2(10, W6, Wtmp0, K1);
+  R( b, c, d, e, a, F3, 59, 1 ); W_PRECALC_00_15_3(11, W6, Wtmp0);
+  R( a, b, c, d, e, F4, 60, 1 ); W_PRECALC_00_15_0(12, W5, Wtmp0);
+  R( e, a, b, c, d, F4, 61, 1 ); W_PRECALC_00_15_1(13, W5, Wtmp0);
+  R( d, e, a, b, c, F4, 62, 1 ); W_PRECALC_00_15_2(14, W5, Wtmp0, K1);
+  R( c, d, e, a, b, F4, 63, 1 ); W_PRECALC_00_15_3(15, W5, Wtmp0);
+  R( b, c, d, e, a, F4, 64, 1 ); W_PRECALC_16_31_0(16, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
+  R( a, b, c, d, e, F4, 65, 1 ); W_PRECALC_16_31_1(17, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
+  R( e, a, b, c, d, F4, 66, 1 ); W_PRECALC_16_31_2(18, W4, W5, W6, W7, W0, Wtmp0, Wtmp1);
+  R( d, e, a, b, c, F4, 67, 1 ); W_PRECALC_16_31_3(19, W4, W5, W6, W7, W0, Wtmp0, Wtmp1, K1);
+  R( c, d, e, a, b, F4, 68, 1 ); W_PRECALC_16_31_0(20, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
+  R( b, c, d, e, a, F4, 69, 1 ); W_PRECALC_16_31_1(21, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
+  R( a, b, c, d, e, F4, 70, 1 ); W_PRECALC_16_31_2(22, W3, W4, W5, W6, W7, Wtmp0, Wtmp1);
+  R( e, a, b, c, d, F4, 71, 1 ); W_PRECALC_16_31_3(23, W3, W4, W5, W6, W7, Wtmp0, Wtmp1, K2);
+  R( d, e, a, b, c, F4, 72, 1 ); W_PRECALC_16_31_0(24, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
+  R( c, d, e, a, b, F4, 73, 1 ); W_PRECALC_16_31_1(25, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
+  R( b, c, d, e, a, F4, 74, 1 ); W_PRECALC_16_31_2(26, W2, W3, W4, W5, W6, Wtmp0, Wtmp1);
+  R( a, b, c, d, e, F4, 75, 1 ); W_PRECALC_16_31_3(27, W2, W3, W4, W5, W6, Wtmp0, Wtmp1, K2);
+  R( e, a, b, c, d, F4, 76, 1 ); W_PRECALC_16_31_0(28, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
+  R( d, e, a, b, c, F4, 77, 1 ); W_PRECALC_16_31_1(29, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
+  R( c, d, e, a, b, F4, 78, 1 ); W_PRECALC_16_31_2(30, W1, W2, W3, W4, W5, Wtmp0, Wtmp1);
+  addl state_h0(RSTATE), a;      W_PRECALC_16_31_3(31, W1, W2, W3, W4, W5, Wtmp0, Wtmp1, K2);
+  R( b, c, d, e, a, F4, 79, 1 );
+  addl ne, a;
+  xorl ne, ne;
+
+  /* Update the chaining variables. */
+  addl state_h3(RSTATE), d;
+  addl state_h2(RSTATE), c;
+  addl state_h1(RSTATE), b;
+  addl state_h4(RSTATE), e;
+
+  movl d, state_h3(RSTATE);
+  movl c, state_h2(RSTATE);
+  movl b, state_h1(RSTATE);
+  movl a, state_h0(RSTATE);
+  movl e, state_h4(RSTATE);
+
+  jmp .Loop;
+
+.align 16
+.Lend:
+  vzeroall;
+
+  /* Transform 48-79 for block 2 + burn stack */
+  R( c, d, e, a, b, F3, 48, 1 );
+  R( b, c, d, e, a, F3, 49, 1 );
+  R( a, b, c, d, e, F3, 50, 1 );
+  R( e, a, b, c, d, F3, 51, 1 );
+  R( d, e, a, b, c, F3, 52, 1 );
+  R( c, d, e, a, b, F3, 53, 1 );
+  R( b, c, d, e, a, F3, 54, 1 );
+  R( a, b, c, d, e, F3, 55, 1 );
+  R( e, a, b, c, d, F3, 56, 1 );
+  R( d, e, a, b, c, F3, 57, 1 );
+  R( c, d, e, a, b, F3, 58, 1 );
+  R( b, c, d, e, a, F3, 59, 1 );
+  R( a, b, c, d, e, F4, 60, 1 ); vmovdqa %ymm0, (0*32)(%rsp);
+  R( e, a, b, c, d, F4, 61, 1 ); vmovdqa %ymm0, (1*32)(%rsp);
+  R( d, e, a, b, c, F4, 62, 1 ); vmovdqa %ymm0, (2*32)(%rsp);
+  R( c, d, e, a, b, F4, 63, 1 ); vmovdqa %ymm0, (3*32)(%rsp);
+  R( b, c, d, e, a, F4, 64, 1 ); vmovdqa %ymm0, (4*32)(%rsp);
+  R( a, b, c, d, e, F4, 65, 1 ); vmovdqa %ymm0, (5*32)(%rsp);
+  R( e, a, b, c, d, F4, 66, 1 ); vmovdqa %ymm0, (6*32)(%rsp);
+  R( d, e, a, b, c, F4, 67, 1 ); vmovdqa %ymm0, (7*32)(%rsp);
+  R( c, d, e, a, b, F4, 68, 1 ); vmovdqa %ymm0, (8*32)(%rsp);
+  R( b, c, d, e, a, F4, 69, 1 ); vmovdqa %ymm0, (9*32)(%rsp);
+  R( a, b, c, d, e, F4, 70, 1 ); vmovdqa %ymm0, (10*32)(%rsp);
+  R( e, a, b, c, d, F4, 71, 1 ); vmovdqa %ymm0, (11*32)(%rsp);
+  R( d, e, a, b, c, F4, 72, 1 ); vmovdqa %ymm0, (12*32)(%rsp);
+  R( c, d, e, a, b, F4, 73, 1 ); vmovdqa %ymm0, (13*32)(%rsp);
+  R( b, c, d, e, a, F4, 74, 1 ); vmovdqa %ymm0, (14*32)(%rsp);
+  R( a, b, c, d, e, F4, 75, 1 ); vmovdqa %ymm0, (15*32)(%rsp);
+  R( e, a, b, c, d, F4, 76, 1 ); vmovdqa %ymm0, (16*32)(%rsp);
+  R( d, e, a, b, c, F4, 77, 1 ); vmovdqa %ymm0, (17*32)(%rsp);
+  R( c, d, e, a, b, F4, 78, 1 ); vmovdqa %ymm0, (18*32)(%rsp);
+  addl state_h0(RSTATE), a;
+  R( b, c, d, e, a, F4, 79, 1 );
+  addl ne, a;
+  xorl ne, ne;
+
+  /* WK_STACK_WORDS*4/32-1 = 19 */
+  vmovdqa %ymm0, (19*32)(%rsp);
+
+  /* Update the chaining variables. */
+  addl state_h3(RSTATE), d;
+  addl state_h2(RSTATE), c;
+  addl state_h1(RSTATE), b;
+  addl state_h4(RSTATE), e;
+
+  movl d, state_h3(RSTATE);
+  movl c, state_h2(RSTATE);
+  movl b, state_h1(RSTATE);
+  movl a, state_h0(RSTATE);
+  movl e, state_h4(RSTATE);
+
+  movq ROLDSTACK, %rsp;
+  CFI_REGISTER(ROLDSTACK, %rsp);
+  CFI_DEF_CFA_REGISTER(%rsp);
+
+  popq %r12;
+  CFI_POP(%r12);
+  popq %rbp;
+  CFI_POP(%rbp);
+  popq %rbx;
+  CFI_POP(%rbx);
+
+  /* stack already burned */
+  xorl %eax, %eax;
+
+  ret_spec_stop;
+  CFI_ENDPROC();
+ELF(.size _gcry_sha1_transform_amd64_avx2_bmi2,
+    .-_gcry_sha1_transform_amd64_avx2_bmi2;)
+
+#endif
+#endif
diff --git a/cipher/sha1-intel-shaext.c b/cipher/sha1-intel-shaext.c
new file mode 100644 (file)
index 0000000..ddf2be2
--- /dev/null
@@ -0,0 +1,292 @@
+/* sha1-intel-shaext.S - SHAEXT accelerated SHA-1 transform function
+ * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "types.h"
+
+#if defined(HAVE_GCC_INLINE_ASM_SHAEXT) && \
+    defined(HAVE_GCC_INLINE_ASM_SSE41) && defined(USE_SHA1) && \
+    defined(ENABLE_SHAEXT_SUPPORT)
+
+#if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
+/* Prevent compiler from issuing SSE instructions between asm blocks. */
+#  pragma GCC target("no-sse")
+#endif
+#if __clang__
+#  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
+#endif
+
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR NO_INSTRUMENT_FUNCTION
+
+/* Two macros to be called prior and after the use of SHA-EXT
+   instructions.  There should be no external function calls between
+   the use of these macros.  There purpose is to make sure that the
+   SSE regsiters are cleared and won't reveal any information about
+   the key or the data.  */
+#ifdef __WIN64__
+/* XMM6-XMM15 are callee-saved registers on WIN64. */
+# define shaext_prepare_variable char win64tmp[2*16]
+# define shaext_prepare_variable_size sizeof(win64tmp)
+# define shaext_prepare()                                               \
+   do { asm volatile ("movdqu %%xmm6, (%0)\n"                           \
+                      "movdqu %%xmm7, (%1)\n"                           \
+                      :                                                 \
+                      : "r" (&win64tmp[0]), "r" (&win64tmp[16])         \
+                      : "memory");                                      \
+   } while (0)
+# define shaext_cleanup(tmp0,tmp1)                                      \
+   do { asm volatile ("movdqu (%0), %%xmm6\n"                           \
+                      "movdqu (%1), %%xmm7\n"                           \
+                      "pxor %%xmm0, %%xmm0\n"                           \
+                      "pxor %%xmm1, %%xmm1\n"                           \
+                      "pxor %%xmm2, %%xmm2\n"                           \
+                      "pxor %%xmm3, %%xmm3\n"                           \
+                      "pxor %%xmm4, %%xmm4\n"                           \
+                      "pxor %%xmm5, %%xmm5\n"                           \
+                      "movdqa %%xmm0, (%2)\n\t"                         \
+                      "movdqa %%xmm0, (%3)\n\t"                         \
+                      :                                                 \
+                      : "r" (&win64tmp[0]), "r" (&win64tmp[16]),        \
+                        "r" (tmp0), "r" (tmp1)                          \
+                      : "memory");                                      \
+   } while (0)
+#else
+# define shaext_prepare_variable
+# define shaext_prepare_variable_size 0
+# define shaext_prepare() do { } while (0)
+# define shaext_cleanup(tmp0,tmp1)                                      \
+   do { asm volatile ("pxor %%xmm0, %%xmm0\n"                           \
+                      "pxor %%xmm1, %%xmm1\n"                           \
+                      "pxor %%xmm2, %%xmm2\n"                           \
+                      "pxor %%xmm3, %%xmm3\n"                           \
+                      "pxor %%xmm4, %%xmm4\n"                           \
+                      "pxor %%xmm5, %%xmm5\n"                           \
+                      "pxor %%xmm6, %%xmm6\n"                           \
+                      "pxor %%xmm7, %%xmm7\n"                           \
+                      "movdqa %%xmm0, (%0)\n\t"                         \
+                      "movdqa %%xmm0, (%1)\n\t"                         \
+                      :                                                 \
+                      : "r" (tmp0), "r" (tmp1)                          \
+                      : "memory");                                      \
+   } while (0)
+#endif
+
+/*
+ * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
+ */
+unsigned int ASM_FUNC_ATTR
+_gcry_sha1_transform_intel_shaext(void *state, const unsigned char *data,
+                                  size_t nblks)
+{
+  static const unsigned char be_mask[16] __attribute__ ((aligned (16))) =
+    { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+  char save_buf[2 * 16 + 15];
+  char *abcd_save;
+  char *e_save;
+  shaext_prepare_variable;
+
+  if (nblks == 0)
+    return 0;
+
+  shaext_prepare ();
+
+  asm volatile ("" : "=r" (abcd_save) : "0" (save_buf) : "memory");
+  abcd_save = abcd_save + (-(uintptr_t)abcd_save & 15);
+  e_save = abcd_save + 16;
+
+  /* byteswap mask => XMM7 */
+  asm volatile ("movdqa %[mask], %%xmm7\n\t" /* Preload mask */
+                :
+                : [mask] "m" (*be_mask)
+                : "memory");
+
+  /* Load state.. ABCD => XMM4, E => XMM5 */
+  asm volatile ("movd 16(%[state]), %%xmm5\n\t"
+                "movdqu (%[state]), %%xmm4\n\t"
+                "pslldq $12, %%xmm5\n\t"
+                "pshufd $0x1b, %%xmm4, %%xmm4\n\t"
+                "movdqa %%xmm5, (%[e_save])\n\t"
+                "movdqa %%xmm4, (%[abcd_save])\n\t"
+                :
+                : [state] "r" (state), [abcd_save] "r" (abcd_save),
+                  [e_save] "r" (e_save)
+                : "memory" );
+
+  /* DATA => XMM[0..4] */
+  asm volatile ("movdqu 0(%[data]), %%xmm0\n\t"
+                "movdqu 16(%[data]), %%xmm1\n\t"
+                "movdqu 32(%[data]), %%xmm2\n\t"
+                "movdqu 48(%[data]), %%xmm3\n\t"
+                "pshufb %%xmm7, %%xmm0\n\t"
+                "pshufb %%xmm7, %%xmm1\n\t"
+                "pshufb %%xmm7, %%xmm2\n\t"
+                "pshufb %%xmm7, %%xmm3\n\t"
+                :
+                : [data] "r" (data)
+                : "memory" );
+  data += 64;
+
+  while (1)
+    {
+      /* Round 0..3 */
+      asm volatile ("paddd %%xmm0, %%xmm5\n\t"
+                    "movdqa %%xmm4, %%xmm6\n\t" /* ABCD => E1 */
+                    "sha1rnds4 $0, %%xmm5, %%xmm4\n\t"
+                    ::: "memory" );
+
+      /* Round 4..7 */
+      asm volatile ("sha1nexte %%xmm1, %%xmm6\n\t"
+                    "movdqa %%xmm4, %%xmm5\n\t"
+                    "sha1rnds4 $0, %%xmm6, %%xmm4\n\t"
+                    "sha1msg1 %%xmm1, %%xmm0\n\t"
+                    ::: "memory" );
+
+      /* Round 8..11 */
+      asm volatile ("sha1nexte %%xmm2, %%xmm5\n\t"
+                    "movdqa %%xmm4, %%xmm6\n\t"
+                    "sha1rnds4 $0, %%xmm5, %%xmm4\n\t"
+                    "sha1msg1 %%xmm2, %%xmm1\n\t"
+                    "pxor %%xmm2, %%xmm0\n\t"
+                    ::: "memory" );
+
+#define ROUND(imm, E0, E1, MSG0, MSG1, MSG2, MSG3) \
+      asm volatile ("sha1nexte %%"MSG0", %%"E0"\n\t" \
+                    "movdqa %%xmm4, %%"E1"\n\t" \
+                    "sha1msg2 %%"MSG0", %%"MSG1"\n\t" \
+                    "sha1rnds4 $"imm", %%"E0", %%xmm4\n\t" \
+                    "sha1msg1 %%"MSG0", %%"MSG3"\n\t" \
+                    "pxor %%"MSG0", %%"MSG2"\n\t" \
+                    ::: "memory" )
+
+      /* Rounds 12..15 to 64..67 */
+      ROUND("0", "xmm6", "xmm5", "xmm3", "xmm0", "xmm1", "xmm2");
+      ROUND("0", "xmm5", "xmm6", "xmm0", "xmm1", "xmm2", "xmm3");
+      ROUND("1", "xmm6", "xmm5", "xmm1", "xmm2", "xmm3", "xmm0");
+      ROUND("1", "xmm5", "xmm6", "xmm2", "xmm3", "xmm0", "xmm1");
+      ROUND("1", "xmm6", "xmm5", "xmm3", "xmm0", "xmm1", "xmm2");
+      ROUND("1", "xmm5", "xmm6", "xmm0", "xmm1", "xmm2", "xmm3");
+      ROUND("1", "xmm6", "xmm5", "xmm1", "xmm2", "xmm3", "xmm0");
+      ROUND("2", "xmm5", "xmm6", "xmm2", "xmm3", "xmm0", "xmm1");
+      ROUND("2", "xmm6", "xmm5", "xmm3", "xmm0", "xmm1", "xmm2");
+      ROUND("2", "xmm5", "xmm6", "xmm0", "xmm1", "xmm2", "xmm3");
+      ROUND("2", "xmm6", "xmm5", "xmm1", "xmm2", "xmm3", "xmm0");
+      ROUND("2", "xmm5", "xmm6", "xmm2", "xmm3", "xmm0", "xmm1");
+      ROUND("3", "xmm6", "xmm5", "xmm3", "xmm0", "xmm1", "xmm2");
+      ROUND("3", "xmm5", "xmm6", "xmm0", "xmm1", "xmm2", "xmm3");
+
+      if (--nblks == 0)
+        break;
+
+      /* Round 68..71 */
+      asm volatile ("movdqu 0(%[data]), %%xmm0\n\t"
+                    "sha1nexte %%xmm1, %%xmm6\n\t"
+                    "movdqa %%xmm4, %%xmm5\n\t"
+                    "sha1msg2 %%xmm1, %%xmm2\n\t"
+                    "sha1rnds4 $3, %%xmm6, %%xmm4\n\t"
+                    "pxor %%xmm1, %%xmm3\n\t"
+                    "pshufb %%xmm7, %%xmm0\n\t"
+                    :
+                    : [data] "r" (data)
+                    : "memory" );
+
+      /* Round 72..75 */
+      asm volatile ("movdqu 16(%[data]), %%xmm1\n\t"
+                    "sha1nexte %%xmm2, %%xmm5\n\t"
+                    "movdqa %%xmm4, %%xmm6\n\t"
+                    "sha1msg2 %%xmm2, %%xmm3\n\t"
+                    "sha1rnds4 $3, %%xmm5, %%xmm4\n\t"
+                    "pshufb %%xmm7, %%xmm1\n\t"
+                    :
+                    : [data] "r" (data)
+                    : "memory" );
+
+      /* Round 76..79 */
+      asm volatile ("movdqu 32(%[data]), %%xmm2\n\t"
+                    "sha1nexte %%xmm3, %%xmm6\n\t"
+                    "movdqa %%xmm4, %%xmm5\n\t"
+                    "sha1rnds4 $3, %%xmm6, %%xmm4\n\t"
+                    "pshufb %%xmm7, %%xmm2\n\t"
+                    :
+                    : [data] "r" (data)
+                    : "memory" );
+
+      /* Merge states, store current. */
+      asm volatile ("movdqu 48(%[data]), %%xmm3\n\t"
+                    "sha1nexte (%[e_save]), %%xmm5\n\t"
+                    "paddd (%[abcd_save]), %%xmm4\n\t"
+                    "pshufb %%xmm7, %%xmm3\n\t"
+                    "movdqa %%xmm5, (%[e_save])\n\t"
+                    "movdqa %%xmm4, (%[abcd_save])\n\t"
+                    :
+                    : [abcd_save] "r" (abcd_save), [e_save] "r" (e_save),
+                      [data] "r" (data)
+                    : "memory" );
+
+      data += 64;
+    }
+
+  /* Round 68..71 */
+  asm volatile ("sha1nexte %%xmm1, %%xmm6\n\t"
+                "movdqa %%xmm4, %%xmm5\n\t"
+                "sha1msg2 %%xmm1, %%xmm2\n\t"
+                "sha1rnds4 $3, %%xmm6, %%xmm4\n\t"
+                "pxor %%xmm1, %%xmm3\n\t"
+                ::: "memory" );
+
+  /* Round 72..75 */
+  asm volatile ("sha1nexte %%xmm2, %%xmm5\n\t"
+                "movdqa %%xmm4, %%xmm6\n\t"
+                "sha1msg2 %%xmm2, %%xmm3\n\t"
+                "sha1rnds4 $3, %%xmm5, %%xmm4\n\t"
+                ::: "memory" );
+
+  /* Round 76..79 */
+  asm volatile ("sha1nexte %%xmm3, %%xmm6\n\t"
+                "movdqa %%xmm4, %%xmm5\n\t"
+                "sha1rnds4 $3, %%xmm6, %%xmm4\n\t"
+                ::: "memory" );
+
+  /* Merge states. */
+  asm volatile ("sha1nexte (%[e_save]), %%xmm5\n\t"
+                "paddd (%[abcd_save]), %%xmm4\n\t"
+                :
+                : [abcd_save] "r" (abcd_save), [e_save] "r" (e_save)
+                : "memory" );
+
+  /* Save state */
+  asm volatile ("pshufd $0x1b, %%xmm4, %%xmm4\n\t"
+                "psrldq $12, %%xmm5\n\t"
+                "movdqu %%xmm4, (%[state])\n\t"
+                "movd %%xmm5, 16(%[state])\n\t"
+                :
+                : [state] "r" (state)
+                : "memory" );
+
+  shaext_cleanup (abcd_save, e_save);
+  return 0;
+}
+
+#if __clang__
+#  pragma clang attribute pop
+#endif
+
+#endif /* HAVE_GCC_INLINE_ASM_SHA_EXT */
index 2b43947..f09b1de 100644 (file)
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
     defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(USE_SHA1)
 
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
-
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 
 /* Context structure */
        movdqa tmp0, W;
 
 #define W_PRECALC_00_15_2(i, W, tmp0) \
-       paddd (.LK_XMM + ((i)/20)*16) RIP, tmp0;
+       paddd (.LK_XMM + ((i)/20)*16) rRIP, tmp0;
 
 #define W_PRECALC_00_15_3(i, W, tmp0) \
        movdqa tmp0, WK(i&~3);
        pxor W, tmp0; \
        pxor tmp1, tmp0; \
        movdqa tmp0, W; \
-       paddd (.LK_XMM + ((i)/20)*16) RIP, tmp0; \
+       paddd (.LK_XMM + ((i)/20)*16) rRIP, tmp0; \
        movdqa tmp0, WK((i)&~3);
 
 #define W_PRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
 
 #define W_PRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28, tmp0) \
        movdqa tmp0, W; \
-       paddd (.LK_XMM + ((i)/20)*16) RIP, tmp0; \
+       paddd (.LK_XMM + ((i)/20)*16) rRIP, tmp0; \
        movdqa tmp0, WK((i)&~3);
 
 #define CLEAR_REG(reg) pxor reg, reg;
@@ -235,6 +224,7 @@ _gcry_sha1_transform_amd64_ssse3:
    *   %rsi: data (64*nblks bytes)
    *   %rdx: nblks
    */
+  CFI_STARTPROC();
 
   xorl %eax, %eax;
   cmpq $0, %rdx;
@@ -244,9 +234,12 @@ _gcry_sha1_transform_amd64_ssse3:
   movq %rdi, RSTATE;
   movq %rsi, RDATA;
   pushq %rbx;
+  CFI_PUSH(%rbx);
   pushq %rbp;
+  CFI_PUSH(%rbp);
 
   movq %rsp, ROLDSTACK;
+  CFI_DEF_CFA_REGISTER(ROLDSTACK);
 
   subq $(16*4), %rsp;
   andq $(~31), %rsp;
@@ -258,7 +251,7 @@ _gcry_sha1_transform_amd64_ssse3:
   movl state_h3(RSTATE), d;
   movl state_h4(RSTATE), e;
 
-  movdqa .Lbswap_shufb_ctl RIP, BSWAP_REG;
+  movdqa .Lbswap_shufb_ctl rRIP, BSWAP_REG;
 
   /* Precalc 0-15. */
   W_PRECALC_00_15_0(0, W0, Wtmp0);
@@ -388,7 +381,7 @@ _gcry_sha1_transform_amd64_ssse3:
 
 .align 16
 .Lend:
-  /* Transform 64-79 + Clear XMM registers. */
+  /* Transform 64-79 + Clear XMM registers + Burn stack. */
   R( b, c, d, e, a, F4, 64 ); CLEAR_REG(BSWAP_REG);
   R( a, b, c, d, e, F4, 65 ); CLEAR_REG(Wtmp0);
   R( e, a, b, c, d, F4, 66 ); CLEAR_REG(Wtmp1);
@@ -401,12 +394,15 @@ _gcry_sha1_transform_amd64_ssse3:
   R( c, d, e, a, b, F4, 73 ); CLEAR_REG(W6);
   R( b, c, d, e, a, F4, 74 ); CLEAR_REG(W7);
   R( a, b, c, d, e, F4, 75 );
-  R( e, a, b, c, d, F4, 76 );
-  R( d, e, a, b, c, F4, 77 );
-  R( c, d, e, a, b, F4, 78 );
+  R( e, a, b, c, d, F4, 76 ); movdqa Wtmp0, (0*16)(%rsp);
+  R( d, e, a, b, c, F4, 77 ); movdqa Wtmp0, (1*16)(%rsp);
+  R( c, d, e, a, b, F4, 78 ); movdqa Wtmp0, (2*16)(%rsp);
   addl state_h0(RSTATE), a;
   R( b, c, d, e, a, F4, 79 );
 
+  /* 16*4/16-1 = 3 */
+  movdqa Wtmp0, (3*16)(%rsp);
+
   /* Update the chaining variables. */
   addl state_h3(RSTATE), d;
   addl state_h2(RSTATE), c;
@@ -420,15 +416,22 @@ _gcry_sha1_transform_amd64_ssse3:
   movl e, state_h4(RSTATE);
 
   movq ROLDSTACK, %rsp;
+  CFI_REGISTER(ROLDSTACK, %rsp);
+  CFI_DEF_CFA_REGISTER(%rsp);
 
   popq %rbp;
+  CFI_POP(%rbp);
   popq %rbx;
+  CFI_POP(%rbx);
 
-  /* burn_stack */
-  movl $(16*4 + 2*8 + 31), %eax;
+  /* stack already burned */
+  xorl %eax, %eax;
 
 .Lret:
-  ret;
+  ret_spec_stop;
+  CFI_ENDPROC();
+ELF(.size _gcry_sha1_transform_amd64_ssse3,
+    .-_gcry_sha1_transform_amd64_ssse3;)
 
 #endif
 #endif
index 78b172f..b83b9de 100644 (file)
 # define USE_BMI2 1
 #endif
 
+/* USE_AVX2 indicates whether to compile with Intel AVX2/BMI2 code. */
+#undef USE_AVX2
+#if defined(USE_BMI2) && defined(HAVE_GCC_INLINE_ASM_AVX2)
+# define USE_AVX2 1
+#endif
+
+/* USE_SHAEXT indicates whether to compile with Intel SHA Extension code. */
+#undef USE_SHAEXT
+#if defined(HAVE_GCC_INLINE_ASM_SHAEXT) && \
+    defined(HAVE_GCC_INLINE_ASM_SSE41) && \
+    defined(ENABLE_SHAEXT_SUPPORT)
+# define USE_SHAEXT 1
+#endif
+
 /* USE_NEON indicates whether to enable ARM NEON assembly code. */
 #undef USE_NEON
 #ifdef ENABLE_NEON_SUPPORT
 # endif
 #endif
 
+
 /* A macro to test whether P is properly aligned for an u32 type.
    Note that config.h provides a suitable replacement for uintptr_t if
    it does not exist in stdint.h.  */
 /* #endif */
 
 
+
+/* Assembly implementations use SystemV ABI, ABI conversion and additional
+ * stack to store XMM6-XMM15 needed on Win64. */
+#undef ASM_FUNC_ABI
+#undef ASM_EXTRA_STACK
+#if defined(USE_SSSE3) || defined(USE_AVX) || defined(USE_BMI2) || \
+    defined(USE_SHAEXT)
+# ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
+#  define ASM_FUNC_ABI __attribute__((sysv_abi))
+#  define ASM_EXTRA_STACK (10 * 16 + sizeof(void *) * 4)
+# else
+#  define ASM_FUNC_ABI
+#  define ASM_EXTRA_STACK 0
+# endif
+#endif
+
+
+#ifdef USE_SSSE3
+unsigned int
+_gcry_sha1_transform_amd64_ssse3 (void *state, const unsigned char *data,
+                                  size_t nblks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha1_transform_amd64_ssse3 (void *ctx, const unsigned char *data,
+                               size_t nblks)
+{
+  SHA1_CONTEXT *hd = ctx;
+  return _gcry_sha1_transform_amd64_ssse3 (&hd->h0, data, nblks)
+         + ASM_EXTRA_STACK;
+}
+#endif
+
+#ifdef USE_AVX
+unsigned int
+_gcry_sha1_transform_amd64_avx (void *state, const unsigned char *data,
+                                 size_t nblks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha1_transform_amd64_avx (void *ctx, const unsigned char *data,
+                             size_t nblks)
+{
+  SHA1_CONTEXT *hd = ctx;
+  return _gcry_sha1_transform_amd64_avx (&hd->h0, data, nblks)
+         + ASM_EXTRA_STACK;
+}
+#endif
+
+#ifdef USE_BMI2
+unsigned int
+_gcry_sha1_transform_amd64_avx_bmi2 (void *state, const unsigned char *data,
+                                     size_t nblks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha1_transform_amd64_avx_bmi2 (void *ctx, const unsigned char *data,
+                                  size_t nblks)
+{
+  SHA1_CONTEXT *hd = ctx;
+  return _gcry_sha1_transform_amd64_avx_bmi2 (&hd->h0, data, nblks)
+         + ASM_EXTRA_STACK;
+}
+
+#ifdef USE_AVX2
+unsigned int
+_gcry_sha1_transform_amd64_avx2_bmi2 (void *state, const unsigned char *data,
+                                      size_t nblks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha1_transform_amd64_avx2_bmi2 (void *ctx, const unsigned char *data,
+                                   size_t nblks)
+{
+  SHA1_CONTEXT *hd = ctx;
+
+  /* AVX2/BMI2 function only handles pair of blocks so nblks needs to be
+   * multiple of 2 and function does not handle zero nblks. Use AVX/BMI2
+   * code to handle these cases. */
+
+  if (nblks <= 1)
+    return do_sha1_transform_amd64_avx_bmi2 (ctx, data, nblks);
+
+  if (nblks & 1)
+    {
+      (void)_gcry_sha1_transform_amd64_avx_bmi2 (&hd->h0, data, 1);
+      nblks--;
+      data += 64;
+    }
+
+  return _gcry_sha1_transform_amd64_avx2_bmi2 (&hd->h0, data, nblks)
+         + ASM_EXTRA_STACK;
+}
+#endif /* USE_AVX2 */
+#endif /* USE_BMI2 */
+
+#ifdef USE_SHAEXT
+/* Does not need ASM_FUNC_ABI */
+unsigned int
+_gcry_sha1_transform_intel_shaext (void *state, const unsigned char *data,
+                                   size_t nblks);
+
+static unsigned int
+do_sha1_transform_intel_shaext (void *ctx, const unsigned char *data,
+                                size_t nblks)
+{
+  SHA1_CONTEXT *hd = ctx;
+  return _gcry_sha1_transform_intel_shaext (&hd->h0, data, nblks);
+}
+#endif
+
+#ifdef USE_NEON
+unsigned int
+_gcry_sha1_transform_armv7_neon (void *state, const unsigned char *data,
+                                 size_t nblks);
+
+static unsigned int
+do_sha1_transform_armv7_neon (void *ctx, const unsigned char *data,
+                              size_t nblks)
+{
+  SHA1_CONTEXT *hd = ctx;
+  return _gcry_sha1_transform_armv7_neon (&hd->h0, data, nblks);
+}
+#endif
+
+#ifdef USE_ARM_CE
+unsigned int
+_gcry_sha1_transform_armv8_ce (void *state, const unsigned char *data,
+                               size_t nblks);
+
+static unsigned int
+do_sha1_transform_armv8_ce (void *ctx, const unsigned char *data,
+                            size_t nblks)
+{
+  SHA1_CONTEXT *hd = ctx;
+  return _gcry_sha1_transform_armv8_ce (&hd->h0, data, nblks);
+}
+#endif
+
+#ifdef SHA1_USE_S390X_CRYPTO
+#include "asm-inline-s390x.h"
+
+static unsigned int
+do_sha1_transform_s390x (void *ctx, const unsigned char *data, size_t nblks)
+{
+  SHA1_CONTEXT *hd = ctx;
+
+  kimd_execute (KMID_FUNCTION_SHA1, &hd->h0, data, nblks * 64);
+  return 0;
+}
+
+static unsigned int
+do_sha1_final_s390x (void *ctx, const unsigned char *data, size_t datalen,
+                    u32 len_msb, u32 len_lsb)
+{
+  SHA1_CONTEXT *hd = ctx;
+
+  /* Make sure that 'final_len' is positioned at correct offset relative
+   * to 'h0'. This is because we are passing 'h0' pointer as start of
+   * parameter block to 'klmd' instruction. */
+
+  gcry_assert (offsetof (SHA1_CONTEXT, final_len_msb)
+              - offsetof (SHA1_CONTEXT, h0) == 5 * sizeof(u32));
+  gcry_assert (offsetof (SHA1_CONTEXT, final_len_lsb)
+              - offsetof (SHA1_CONTEXT, final_len_msb) == 1 * sizeof(u32));
+
+  hd->final_len_msb = len_msb;
+  hd->final_len_lsb = len_lsb;
+
+  klmd_execute (KMID_FUNCTION_SHA1, &hd->h0, data, datalen);
+  return 0;
+}
+#endif
+
+
 static unsigned int
-transform (void *c, const unsigned char *data, size_t nblks);
+do_transform_generic (void *c, const unsigned char *data, size_t nblks);
 
 
 static void
@@ -124,26 +310,56 @@ sha1_init (void *context, unsigned int flags)
   hd->bctx.nblocks = 0;
   hd->bctx.nblocks_high = 0;
   hd->bctx.count = 0;
-  hd->bctx.blocksize = 64;
-  hd->bctx.bwrite = transform;
+  hd->bctx.blocksize_shift = _gcry_ctz(64);
 
+  /* Order of feature checks is important here; last match will be
+   * selected.  Keep slower implementations at the top and faster at
+   * the bottom.  */
+  hd->bctx.bwrite = do_transform_generic;
 #ifdef USE_SSSE3
-  hd->use_ssse3 = (features & HWF_INTEL_SSSE3) != 0;
+  if ((features & HWF_INTEL_SSSE3) != 0)
+    hd->bctx.bwrite = do_sha1_transform_amd64_ssse3;
 #endif
 #ifdef USE_AVX
   /* AVX implementation uses SHLD which is known to be slow on non-Intel CPUs.
    * Therefore use this implementation on Intel CPUs only. */
-  hd->use_avx = (features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD);
+  if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD))
+    hd->bctx.bwrite = do_sha1_transform_amd64_avx;
 #endif
 #ifdef USE_BMI2
-  hd->use_bmi2 = (features & HWF_INTEL_AVX) && (features & HWF_INTEL_BMI2);
+  if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_BMI2))
+    hd->bctx.bwrite = do_sha1_transform_amd64_avx_bmi2;
+#endif
+#ifdef USE_AVX2
+  if ((features & HWF_INTEL_AVX2) && (features & HWF_INTEL_AVX) &&
+      (features & HWF_INTEL_BMI2))
+    hd->bctx.bwrite = do_sha1_transform_amd64_avx2_bmi2;
+#endif
+#ifdef USE_SHAEXT
+  if ((features & HWF_INTEL_SHAEXT) && (features & HWF_INTEL_SSE4_1))
+    hd->bctx.bwrite = do_sha1_transform_intel_shaext;
 #endif
 #ifdef USE_NEON
-  hd->use_neon = (features & HWF_ARM_NEON) != 0;
+  if ((features & HWF_ARM_NEON) != 0)
+    hd->bctx.bwrite = do_sha1_transform_armv7_neon;
 #endif
 #ifdef USE_ARM_CE
-  hd->use_arm_ce = (features & HWF_ARM_SHA1) != 0;
+  if ((features & HWF_ARM_SHA1) != 0)
+    hd->bctx.bwrite = do_sha1_transform_armv8_ce;
+#endif
+#ifdef SHA1_USE_S390X_CRYPTO
+  hd->use_s390x_crypto = 0;
+  if ((features & HWF_S390X_MSA) != 0)
+    {
+      if ((kimd_query () & km_function_to_mask (KMID_FUNCTION_SHA1)) &&
+         (klmd_query () & km_function_to_mask (KMID_FUNCTION_SHA1)))
+       {
+         hd->bctx.bwrite = do_sha1_transform_s390x;
+         hd->use_s390x_crypto = 1;
+       }
+    }
 #endif
+
   (void)features;
 }
 
@@ -180,30 +396,20 @@ _gcry_sha1_mixblock_init (SHA1_CONTEXT *hd)
                                 b = rol( b, 30 );    \
                               } while(0)
 
-
-#ifdef USE_NEON
-unsigned int
-_gcry_sha1_transform_armv7_neon (void *state, const unsigned char *data,
-                                 size_t nblks);
-#endif
-
-#ifdef USE_ARM_CE
-unsigned int
-_gcry_sha1_transform_armv8_ce (void *state, const unsigned char *data,
-                               size_t nblks);
-#endif
-
 /*
  * Transform NBLOCKS of each 64 bytes (16 32-bit words) at DATA.
  */
 static unsigned int
-transform_blk (void *ctx, const unsigned char *data)
+do_transform_generic (void *ctx, const unsigned char *data, size_t nblks)
 {
   SHA1_CONTEXT *hd = ctx;
-  const u32 *idata = (const void *)data;
-  register u32 a, b, c, d, e; /* Local copies of the chaining variables.  */
-  register u32 tm;            /* Helper.  */
-  u32 x[16];                  /* The array we work on. */
+
+  do
+    {
+      const u32 *idata = (const void *)data;
+      u32 a, b, c, d, e; /* Local copies of the chaining variables.  */
+      u32 tm;            /* Helper.  */
+      u32 x[16];         /* The array we work on. */
 
 #define I(i) (x[i] = buf_get_be32(idata + i))
 
@@ -303,91 +509,11 @@ transform_blk (void *ctx, const unsigned char *data)
       hd->h3 += d;
       hd->h4 += e;
 
-  return /* burn_stack */ 88+4*sizeof(void*);
-}
-
-
-/* Assembly implementations use SystemV ABI, ABI conversion and additional
- * stack to store XMM6-XMM15 needed on Win64. */
-#undef ASM_FUNC_ABI
-#undef ASM_EXTRA_STACK
-#if defined(USE_SSSE3) || defined(USE_AVX) || defined(USE_BMI2)
-# ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-#  define ASM_FUNC_ABI __attribute__((sysv_abi))
-#  define ASM_EXTRA_STACK (10 * 16)
-# else
-#  define ASM_FUNC_ABI
-#  define ASM_EXTRA_STACK 0
-# endif
-#endif
-
-
-#ifdef USE_SSSE3
-unsigned int
-_gcry_sha1_transform_amd64_ssse3 (void *state, const unsigned char *data,
-                                  size_t nblks) ASM_FUNC_ABI;
-#endif
-
-#ifdef USE_AVX
-unsigned int
-_gcry_sha1_transform_amd64_avx (void *state, const unsigned char *data,
-                                 size_t nblks) ASM_FUNC_ABI;
-#endif
-
-#ifdef USE_BMI2
-unsigned int
-_gcry_sha1_transform_amd64_avx_bmi2 (void *state, const unsigned char *data,
-                                     size_t nblks) ASM_FUNC_ABI;
-#endif
-
-
-static unsigned int
-transform (void *ctx, const unsigned char *data, size_t nblks)
-{
-  SHA1_CONTEXT *hd = ctx;
-  unsigned int burn;
-
-#ifdef USE_BMI2
-  if (hd->use_bmi2)
-    return _gcry_sha1_transform_amd64_avx_bmi2 (&hd->h0, data, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
-#endif
-#ifdef USE_AVX
-  if (hd->use_avx)
-    return _gcry_sha1_transform_amd64_avx (&hd->h0, data, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
-#endif
-#ifdef USE_SSSE3
-  if (hd->use_ssse3)
-    return _gcry_sha1_transform_amd64_ssse3 (&hd->h0, data, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
-#endif
-#ifdef USE_ARM_CE
-  if (hd->use_arm_ce)
-    return _gcry_sha1_transform_armv8_ce (&hd->h0, data, nblks);
-#endif
-#ifdef USE_NEON
-  if (hd->use_neon)
-    return _gcry_sha1_transform_armv7_neon (&hd->h0, data, nblks)
-           + 4 * sizeof(void*);
-#endif
-
-  do
-    {
-      burn = transform_blk (hd, data);
       data += 64;
     }
   while (--nblks);
 
-#ifdef ASM_EXTRA_STACK
-  /* 'transform_blk' is typically inlined and XMM6-XMM15 are stored at
-   *  the prologue of this function. Therefore need to add ASM_EXTRA_STACK to
-   *  here too.
-   */
-  burn += ASM_EXTRA_STACK;
-#endif
-
-  return burn;
+  return 88+4*sizeof(void*);
 }
 
 
@@ -407,7 +533,7 @@ _gcry_sha1_mixblock (SHA1_CONTEXT *hd, void *blockof64byte)
   u32 *p = blockof64byte;
   unsigned int nburn;
 
-  nburn = transform (hd, blockof64byte, 1);
+  nburn = (*hd->bctx.bwrite) (hd, blockof64byte, 1);
   p[0] = hd->h0;
   p[1] = hd->h1;
   p[2] = hd->h2;
@@ -433,8 +559,6 @@ sha1_final(void *context)
   unsigned char *p;
   unsigned int burn;
 
-  _gcry_md_block_write (hd, NULL, 0); /* flush */;
-
   t = hd->bctx.nblocks;
   if (sizeof t == sizeof hd->bctx.nblocks)
     th = hd->bctx.nblocks_high;
@@ -454,25 +578,36 @@ sha1_final(void *context)
   msb <<= 3;
   msb |= t >> 29;
 
-  if( hd->bctx.count < 56 )  /* enough room */
+  if (0)
+    { }
+#ifdef SHA1_USE_S390X_CRYPTO
+  else if (hd->use_s390x_crypto)
+    {
+      burn = do_sha1_final_s390x (hd, hd->bctx.buf, hd->bctx.count, msb, lsb);
+    }
+#endif
+  else if (hd->bctx.count < 56)  /* enough room */
     {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
-      while( hd->bctx.count < 56 )
-        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
+      if (hd->bctx.count < 56)
+       memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count);
+
+      /* append the 64 bit count */
+      buf_put_be32(hd->bctx.buf + 56, msb);
+      buf_put_be32(hd->bctx.buf + 60, lsb);
+      burn = (*hd->bctx.bwrite) ( hd, hd->bctx.buf, 1 );
     }
   else  /* need one extra block */
     {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
-      while( hd->bctx.count < 64 )
-        hd->bctx.buf[hd->bctx.count++] = 0;
-      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
-      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
+      /* fill pad and next block with zeroes */
+      memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56);
+
+      /* append the 64 bit count */
+      buf_put_be32(hd->bctx.buf + 64 + 56, msb);
+      buf_put_be32(hd->bctx.buf + 64 + 60, lsb);
+      burn = (*hd->bctx.bwrite) ( hd, hd->bctx.buf, 2 );
     }
-  /* append the 64 bit count */
-  buf_put_be32(hd->bctx.buf + 56, msb);
-  buf_put_be32(hd->bctx.buf + 60, lsb);
-  burn = transform( hd, hd->bctx.buf, 1 );
-  _gcry_burn_stack (burn);
 
   p = hd->bctx.buf;
 #define X(a) do { buf_put_be32(p, hd->h##a); p += 4; } while(0)
@@ -483,6 +618,9 @@ sha1_final(void *context)
   X(4);
 #undef X
 
+  hd->bctx.count = 0;
+
+  _gcry_burn_stack (burn);
 }
 
 static unsigned char *
@@ -493,34 +631,37 @@ 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, size_t nbytes,
+                        const gcry_buffer_t *iov, int iovcnt)
 {
   SHA1_CONTEXT hd;
 
+  (void)nbytes;
+
   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, 20, &iov, 1);
 }
 
 
@@ -597,11 +738,11 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
 
 
 \f
-static unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */
+static const unsigned char asn[15] = /* Object ID is 1.3.14.3.2.26 */
   { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
     0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
 
-static gcry_md_oid_spec_t oid_spec_sha1[] =
+static const gcry_md_oid_spec_t oid_spec_sha1[] =
   {
     /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 (sha1WithRSAEncryption) */
     { "1.2.840.113549.1.1.5" },
@@ -616,11 +757,12 @@ static gcry_md_oid_spec_t oid_spec_sha1[] =
     { NULL },
   };
 
-gcry_md_spec_t _gcry_digest_spec_sha1 =
+const 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_buffers,
     sizeof (SHA1_CONTEXT),
     run_selftests
   };
index d448fca..a359765 100644 (file)
 
 #include "hash-common.h"
 
+
+/* SHA1_USE_S390X_CRYPTO indicates whether to enable zSeries code. */
+#undef SHA1_USE_S390X_CRYPTO
+#if defined(HAVE_GCC_INLINE_ASM_S390X)
+# define SHA1_USE_S390X_CRYPTO 1
+#endif /* SHA1_USE_S390X_CRYPTO */
+
+
 /* We need this here for direct use by random-csprng.c. */
 typedef struct
 {
   gcry_md_block_ctx_t bctx;
   u32          h0,h1,h2,h3,h4;
-  unsigned int use_ssse3:1;
-  unsigned int use_avx:1;
-  unsigned int use_bmi2:1;
-  unsigned int use_neon:1;
-  unsigned int use_arm_ce:1;
+#ifdef SHA1_USE_S390X_CRYPTO
+  u32          final_len_msb, final_len_lsb; /* needs to be right after h4. */
+  int          use_s390x_crypto;
+#endif
 } SHA1_CONTEXT;
 
 
index 2b17ab1..95778b4 100644 (file)
@@ -111,7 +111,7 @@ gcry_sha256_aarch32_ce_K:
 
 /* Other functional macros */
 
-#define CLEAR_REG(reg) veor reg, reg;
+#define CLEAR_REG(reg) vmov.i8 reg, #0;
 
 
 /*
index a4575da..d0fa628 100644 (file)
@@ -17,7 +17,7 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "asm-common-aarch64.h"
 
 #if defined(__AARCH64EL__) && \
     defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
 .text
 
 
-#define GET_DATA_POINTER(reg, name) \
-               adrp    reg, :got:name ; \
-               ldr     reg, [reg, #:got_lo12:name] ;
-
-
 /* Constants */
 
 .align 4
@@ -103,7 +98,7 @@ gcry_sha256_aarch64_ce_K:
 
 /* Other functional macros */
 
-#define CLEAR_REG(reg) eor reg.16b, reg.16b, reg.16b;
+#define CLEAR_REG(reg) movi reg.16b, #0;
 
 
 /*
@@ -113,13 +108,14 @@ gcry_sha256_aarch64_ce_K:
  */
 .align 3
 .globl _gcry_sha256_transform_armv8_ce
-.type  _gcry_sha256_transform_armv8_ce,%function;
+ELF(.type  _gcry_sha256_transform_armv8_ce,%function;)
 _gcry_sha256_transform_armv8_ce:
   /* input:
    *   r0: ctx, CTX
    *   r1: data (64*nblks bytes)
    *   r2: nblks
    */
+  CFI_STARTPROC();
 
   cbz x2, .Ldo_nothing;
 
@@ -212,7 +208,8 @@ _gcry_sha256_transform_armv8_ce:
 
 .Ldo_nothing:
   mov x0, #0
-  ret
-.size _gcry_sha256_transform_armv8_ce,.-_gcry_sha256_transform_armv8_ce;
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_sha256_transform_armv8_ce,.-_gcry_sha256_transform_armv8_ce;)
 
 #endif
index 6953855..be8a799 100644 (file)
     defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
     defined(HAVE_GCC_INLINE_ASM_AVX) && defined(USE_SHA256)
 
-#ifdef __PIC__
-#  define ADD_RIP +rip
-#else
-#  define ADD_RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .intel_syntax noprefix
 
 #define        VMOVDQ vmovdqu /* assume buffers not aligned */
 
-.macro ROR p1 p2
-       /* shld is faster than ror on Intel Sandybridge */
-       shld    \p1, \p1, (32 - \p2)
-.endm
+#define ROR(p1, p2) \
+       /* shld is faster than ror on Intel Sandybridge */ \
+       shld    p1, p1, (32 - p2);
 
 /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Define Macros*/
 
 /* addm [mem], reg
  * Add reg to mem using reg-mem add and store */
-.macro addm p1 p2
-       add     \p2, \p1
-       mov     \p1, \p2
-.endm
+#define addm(p1, p2) \
+       add     p2, p1; \
+       mov     p1, p2;
 
 /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/
 
 /* COPY_XMM_AND_BSWAP xmm, [mem], byte_flip_mask
  * Load xmm with mem and byte swap each dword */
-.macro COPY_XMM_AND_BSWAP p1 p2 p3
-       VMOVDQ \p1, \p2
-       vpshufb \p1, \p1, \p3
-.endm
+#define COPY_XMM_AND_BSWAP(p1, p2, p3) \
+       VMOVDQ p1, p2; \
+       vpshufb p1, p1, p3;
 
 /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/
 
-X0 = xmm4
-X1 = xmm5
-X2 = xmm6
-X3 = xmm7
+#define X0 xmm4
+#define X1 xmm5
+#define X2 xmm6
+#define X3 xmm7
 
-XTMP0 = xmm0
-XTMP1 = xmm1
-XTMP2 = xmm2
-XTMP3 = xmm3
-XTMP4 = xmm8
-XFER  = xmm9
+#define XTMP0 xmm0
+#define XTMP1 xmm1
+#define XTMP2 xmm2
+#define XTMP3 xmm3
+#define XTMP4 xmm8
+#define XFER xmm9
 
-SHUF_00BA = xmm10 /* shuffle xBxA -> 00BA */
-SHUF_DC00 = xmm11 /* shuffle xDxC -> DC00 */
-BYTE_FLIP_MASK = xmm12
+#define SHUF_00BA xmm10 /* shuffle xBxA -> 00BA */
+#define SHUF_DC00 xmm11 /* shuffle xDxC -> DC00 */
+#define BYTE_FLIP_MASK xmm12
 
-NUM_BLKS = rdx /* 3rd arg */
-CTX = rsi      /* 2nd arg */
-INP = rdi      /* 1st arg */
+#define NUM_BLKS rdx   /* 3rd arg */
+#define CTX rsi        /* 2nd arg */
+#define INP rdi        /* 1st arg */
 
-SRND = rdi     /* clobbers INP */
-c = ecx
-d = r8d
-e = edx
+#define SRND rdi       /* clobbers INP */
+#define c ecx
+#define d r8d
+#define e edx
 
-TBL = rbp
-a = eax
-b = ebx
+#define TBL rbp
+#define a eax
+#define b ebx
 
-f = r9d
-g = r10d
-h = r11d
+#define f r9d
+#define g r10d
+#define h r11d
 
-y0 = r13d
-y1 = r14d
-y2 = r15d
+#define y0 r13d
+#define y1 r14d
+#define y2 r15d
 
 
 
@@ -152,220 +139,197 @@ y2 = r15d
 #define _XMM_SAVE      (_XFER     + _XFER_SIZE + _ALIGN_SIZE)
 #define STACK_SIZE     (_XMM_SAVE + _XMM_SAVE_SIZE)
 
-/* rotate_Xs
- * Rotate values of symbols X0...X3 */
-.macro rotate_Xs
-X_ = X0
-X0 = X1
-X1 = X2
-X2 = X3
-X3 = X_
-.endm
-
-/* ROTATE_ARGS
- * Rotate values of symbols a...h */
-.macro ROTATE_ARGS
-TMP_ = h
-h = g
-g = f
-f = e
-e = d
-d = c
-c = b
-b = a
-a = TMP_
-.endm
-
-.macro FOUR_ROUNDS_AND_SCHED
-               /* compute s0 four at a time and s1 two at a time
-                * compute W[-16] + W[-7] 4 at a time */
-       mov     y0, e           /* y0 = e */
-       ROR     y0, (25-11)     /* y0 = e >> (25-11) */
-       mov     y1, a           /* y1 = a */
-               vpalignr        XTMP0, X3, X2, 4        /* XTMP0 = W[-7] */
-       ROR     y1, (22-13)     /* y1 = a >> (22-13) */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       mov     y2, f           /* y2 = f */
-       ROR     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       xor     y2, g           /* y2 = f^g */
-               vpaddd  XTMP0, XTMP0, X0        /* XTMP0 = W[-7] + W[-16] */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       and     y2, e           /* y2 = (f^g)&e */
-       ROR     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-               /* compute s0 */
-               vpalignr        XTMP1, X1, X0, 4        /* XTMP1 = W[-15] */
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       ROR     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-       ROR     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-       add     y2, y0          /* y2 = S1 + CH */
-       add     y2, [rsp + _XFER + 0*4] /* y2 = k + w + S1 + CH */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-               vpslld  XTMP2, XTMP1, (32-7)
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-               vpsrld  XTMP3, XTMP1, 7
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-               vpor    XTMP3, XTMP3, XTMP2     /* XTMP1 = W[-15] ror 7 */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+
+#define FOUR_ROUNDS_AND_SCHED_0(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+               /* compute s0 four at a time and s1 two at a time */; \
+               /* compute W[-16] + W[-7] 4 at a time */; \
+       mov     y0, e           /* y0 = e */; \
+       ROR(    y0, (25-11))    /* y0 = e >> (25-11) */; \
+       mov     y1, a           /* y1 = a */; \
+               vpalignr        XTMP0, X3, X2, 4        /* XTMP0 = W[-7] */; \
+       ROR(    y1, (22-13))    /* y1 = a >> (22-13) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       mov     y2, f           /* y2 = f */; \
+       ROR(    y0, (11-6))     /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       xor     y2, g           /* y2 = f^g */; \
+               vpaddd  XTMP0, XTMP0, X0        /* XTMP0 = W[-7] + W[-16] */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+       ROR(    y1, (13-2))     /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+               /* compute s0 */; \
+               vpalignr        XTMP1, X1, X0, 4        /* XTMP1 = W[-15] */; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       ROR(    y0, 6)          /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+       ROR(    y1, 2)          /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       add     y2, [rsp + _XFER + 0*4] /* y2 = k + w + S1 + CH */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+               vpslld  XTMP2, XTMP1, (32-7); \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+               vpsrld  XTMP3, XTMP1, 7; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+               vpor    XTMP3, XTMP3, XTMP2     /* XTMP1 = W[-15] ror 7 */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
 
-ROTATE_ARGS
-       mov     y0, e           /* y0 = e */
-       mov     y1, a           /* y1 = a */
-       ROR     y0, (25-11)     /* y0 = e >> (25-11) */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       mov     y2, f           /* y2 = f */
-       ROR     y1, (22-13)     /* y1 = a >> (22-13) */
-               vpslld  XTMP2, XTMP1, (32-18)
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       ROR     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-       xor     y2, g           /* y2 = f^g */
-               vpsrld  XTMP4, XTMP1, 18
-       ROR     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       and     y2, e           /* y2 = (f^g)&e */
-       ROR     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-               vpxor   XTMP4, XTMP4, XTMP3
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-               vpsrld  XTMP1, XTMP1, 3 /* XTMP4 = W[-15] >> 3 */
-       add     y2, y0          /* y2 = S1 + CH */
-       add     y2, [rsp + _XFER + 1*4] /* y2 = k + w + S1 + CH */
-       ROR     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-               vpxor   XTMP1, XTMP1, XTMP2     /* XTMP1 = W[-15] ror 7 ^ W[-15] ror 18 */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-               vpxor   XTMP1, XTMP1, XTMP4     /* XTMP1 = s0 */
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-               /* compute low s1 */
-               vpshufd XTMP2, X3, 0b11111010   /* XTMP2 = W[-2] {BBAA} */
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-               vpaddd  XTMP0, XTMP0, XTMP1     /* XTMP0 = W[-16] + W[-7] + s0 */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+#define FOUR_ROUNDS_AND_SCHED_1(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+       mov     y0, e           /* y0 = e */; \
+       mov     y1, a           /* y1 = a */; \
+       ROR(    y0, (25-11))    /* y0 = e >> (25-11) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       mov     y2, f           /* y2 = f */; \
+       ROR(    y1, (22-13))    /* y1 = a >> (22-13) */; \
+               vpslld  XTMP2, XTMP1, (32-18); \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       ROR(    y0, (11-6))     /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+       xor     y2, g           /* y2 = f^g */; \
+               vpsrld  XTMP4, XTMP1, 18; \
+       ROR(    y1, (13-2))     /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+       ROR(    y0, 6)          /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+               vpxor   XTMP4, XTMP4, XTMP3; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+               vpsrld  XTMP1, XTMP1, 3 /* XTMP4 = W[-15] >> 3 */; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       add     y2, [rsp + _XFER + 1*4] /* y2 = k + w + S1 + CH */; \
+       ROR(    y1, 2)          /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+               vpxor   XTMP1, XTMP1, XTMP2     /* XTMP1 = W[-15] ror 7 ^ W[-15] ror 18 */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+               vpxor   XTMP1, XTMP1, XTMP4     /* XTMP1 = s0 */; \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+               /* compute low s1 */; \
+               vpshufd XTMP2, X3, 0b11111010   /* XTMP2 = W[-2] {BBAA} */; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+               vpaddd  XTMP0, XTMP0, XTMP1     /* XTMP0 = W[-16] + W[-7] + s0 */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
 
-ROTATE_ARGS
-       mov     y0, e           /* y0 = e */
-       mov     y1, a           /* y1 = a */
-       ROR     y0, (25-11)     /* y0 = e >> (25-11) */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       ROR     y1, (22-13)     /* y1 = a >> (22-13) */
-       mov     y2, f           /* y2 = f */
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       ROR     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-               vpsrlq  XTMP3, XTMP2, 17        /* XTMP2 = W[-2] ror 17 {xBxA} */
-       xor     y2, g           /* y2 = f^g */
-               vpsrlq  XTMP4, XTMP2, 19        /* XTMP3 = W[-2] ror 19 {xBxA} */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       and     y2, e           /* y2 = (f^g)&e */
-               vpsrld  XTMP2, XTMP2, 10        /* XTMP4 = W[-2] >> 10 {BBAA} */
-       ROR     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-       ROR     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-               vpxor   XTMP2, XTMP2, XTMP3
-       add     y2, y0          /* y2 = S1 + CH */
-       ROR     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-       add     y2, [rsp + _XFER + 2*4] /* y2 = k + w + S1 + CH */
-               vpxor   XTMP4, XTMP4, XTMP2     /* XTMP4 = s1 {xBxA} */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-               vpshufb XTMP4, XTMP4, SHUF_00BA /* XTMP4 = s1 {00BA} */
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-               vpaddd  XTMP0, XTMP0, XTMP4     /* XTMP0 = {..., ..., W[1], W[0]} */
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-               /* compute high s1 */
-               vpshufd XTMP2, XTMP0, 0b01010000 /* XTMP2 = W[-2] {DDCC} */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+#define FOUR_ROUNDS_AND_SCHED_2(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+       mov     y0, e           /* y0 = e */; \
+       mov     y1, a           /* y1 = a */; \
+       ROR(    y0, (25-11))    /* y0 = e >> (25-11) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       ROR(    y1, (22-13))    /* y1 = a >> (22-13) */; \
+       mov     y2, f           /* y2 = f */; \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       ROR(    y0, (11-6))     /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+               vpsrlq  XTMP3, XTMP2, 17        /* XTMP2 = W[-2] ror 17 {xBxA} */; \
+       xor     y2, g           /* y2 = f^g */; \
+               vpsrlq  XTMP4, XTMP2, 19        /* XTMP3 = W[-2] ror 19 {xBxA} */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+               vpsrld  XTMP2, XTMP2, 10        /* XTMP4 = W[-2] >> 10 {BBAA} */; \
+       ROR(    y1, (13-2))     /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+       ROR(    y0, 6)          /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+               vpxor   XTMP2, XTMP2, XTMP3; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       ROR(    y1, 2)          /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+       add     y2, [rsp + _XFER + 2*4] /* y2 = k + w + S1 + CH */; \
+               vpxor   XTMP4, XTMP4, XTMP2     /* XTMP4 = s1 {xBxA} */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+               vpshufb XTMP4, XTMP4, SHUF_00BA /* XTMP4 = s1 {00BA} */; \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+               vpaddd  XTMP0, XTMP0, XTMP4     /* XTMP0 = {..., ..., W[1], W[0]} */; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+               /* compute high s1 */; \
+               vpshufd XTMP2, XTMP0, 0b01010000 /* XTMP2 = W[-2] {DDCC} */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
 
-ROTATE_ARGS
-       mov     y0, e           /* y0 = e */
-       ROR     y0, (25-11)     /* y0 = e >> (25-11) */
-       mov     y1, a           /* y1 = a */
-       ROR     y1, (22-13)     /* y1 = a >> (22-13) */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       mov     y2, f           /* y2 = f */
-       ROR     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-               vpsrlq  XTMP3, XTMP2, 17        /* XTMP2 = W[-2] ror 17 {xDxC} */
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       xor     y2, g           /* y2 = f^g */
-               vpsrlq  X0, XTMP2, 19   /* XTMP3 = W[-2] ror 19 {xDxC} */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       and     y2, e           /* y2 = (f^g)&e */
-       ROR     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-               vpsrld  XTMP2, XTMP2,    10     /* X0 = W[-2] >> 10 {DDCC} */
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       ROR     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-               vpxor   XTMP2, XTMP2, XTMP3
-       ROR     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-       add     y2, y0          /* y2 = S1 + CH */
-       add     y2, [rsp + _XFER + 3*4] /* y2 = k + w + S1 + CH */
-               vpxor   X0, X0, XTMP2   /* X0 = s1 {xDxC} */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-               vpshufb X0, X0, SHUF_DC00       /* X0 = s1 {DC00} */
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-               vpaddd  X0, X0, XTMP0   /* X0 = {W[3], W[2], W[1], W[0]} */
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+#define FOUR_ROUNDS_AND_SCHED_3(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+       mov     y0, e           /* y0 = e */; \
+       ROR(    y0, (25-11))    /* y0 = e >> (25-11) */; \
+       mov     y1, a           /* y1 = a */; \
+       ROR(    y1, (22-13))    /* y1 = a >> (22-13) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       mov     y2, f           /* y2 = f */; \
+       ROR(    y0, (11-6))     /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+               vpsrlq  XTMP3, XTMP2, 17        /* XTMP2 = W[-2] ror 17 {xDxC} */; \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       xor     y2, g           /* y2 = f^g */; \
+               vpsrlq  X0, XTMP2, 19   /* XTMP3 = W[-2] ror 19 {xDxC} */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+       ROR(    y1, (13-2))     /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+               vpsrld  XTMP2, XTMP2,    10     /* X0 = W[-2] >> 10 {DDCC} */; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       ROR(    y0, 6)          /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+               vpxor   XTMP2, XTMP2, XTMP3; \
+       ROR(    y1, 2)          /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       add     y2, [rsp + _XFER + 3*4] /* y2 = k + w + S1 + CH */; \
+               vpxor   X0, X0, XTMP2   /* X0 = s1 {xDxC} */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+               vpshufb X0, X0, SHUF_DC00       /* X0 = s1 {DC00} */; \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+               vpaddd  X0, X0, XTMP0   /* X0 = {W[3], W[2], W[1], W[0]} */; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
 
-ROTATE_ARGS
-rotate_Xs
-.endm
+#define FOUR_ROUNDS_AND_SCHED(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+       FOUR_ROUNDS_AND_SCHED_0(X0, X1, X2, X3, a, b, c, d, e, f, g, h); \
+       FOUR_ROUNDS_AND_SCHED_1(X0, X1, X2, X3, h, a, b, c, d, e, f, g); \
+       FOUR_ROUNDS_AND_SCHED_2(X0, X1, X2, X3, g, h, a, b, c, d, e, f); \
+       FOUR_ROUNDS_AND_SCHED_3(X0, X1, X2, X3, f, g, h, a, b, c, d, e);
 
 /* input is [rsp + _XFER + %1 * 4] */
-.macro DO_ROUND i1
-       mov     y0, e           /* y0 = e */
-       ROR     y0, (25-11)     /* y0 = e >> (25-11) */
-       mov     y1, a           /* y1 = a */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       ROR     y1, (22-13)     /* y1 = a >> (22-13) */
-       mov     y2, f           /* y2 = f */
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       ROR     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-       xor     y2, g           /* y2 = f^g */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       ROR     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-       and     y2, e           /* y2 = (f^g)&e */
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       ROR     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-       add     y2, y0          /* y2 = S1 + CH */
-       ROR     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-       add     y2, [rsp + _XFER + \i1 * 4]     /* y2 = k + w + S1 + CH */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+#define DO_ROUND(i1, a, b, c, d, e, f, g, h) \
+       mov     y0, e           /* y0 = e */; \
+       ROR(    y0, (25-11))    /* y0 = e >> (25-11) */; \
+       mov     y1, a           /* y1 = a */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       ROR(    y1, (22-13))    /* y1 = a >> (22-13) */; \
+       mov     y2, f           /* y2 = f */; \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       ROR(    y0, (11-6))     /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+       xor     y2, g           /* y2 = f^g */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       ROR(    y1, (13-2))     /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       ROR(    y0, 6)          /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       ROR(    y1, 2)          /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+       add     y2, [rsp + _XFER + i1 * 4]      /* y2 = k + w + S1 + CH */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
-       ROTATE_ARGS
-.endm
 
 /*
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -380,15 +344,22 @@ rotate_Xs
 ELF(.type  _gcry_sha256_transform_amd64_avx,@function;)
 .align 16
 _gcry_sha256_transform_amd64_avx:
+       CFI_STARTPROC()
        vzeroupper
 
        push    rbx
+       CFI_PUSH(rbx)
        push    rbp
+       CFI_PUSH(rbp)
        push    r13
+       CFI_PUSH(r13)
        push    r14
+       CFI_PUSH(r14)
        push    r15
+       CFI_PUSH(r15)
 
        sub     rsp, STACK_SIZE
+       CFI_ADJUST_CFA_OFFSET(STACK_SIZE);
 
        shl     NUM_BLKS, 6     /* convert to bytes */
        jz      .Ldone_hash
@@ -413,10 +384,10 @@ _gcry_sha256_transform_amd64_avx:
        lea     TBL, [.LK256 ADD_RIP]
 
        /* byte swap first 16 dwords */
-       COPY_XMM_AND_BSWAP      X0, [INP + 0*16], BYTE_FLIP_MASK
-       COPY_XMM_AND_BSWAP      X1, [INP + 1*16], BYTE_FLIP_MASK
-       COPY_XMM_AND_BSWAP      X2, [INP + 2*16], BYTE_FLIP_MASK
-       COPY_XMM_AND_BSWAP      X3, [INP + 3*16], BYTE_FLIP_MASK
+       COPY_XMM_AND_BSWAP(X0, [INP + 0*16], BYTE_FLIP_MASK)
+       COPY_XMM_AND_BSWAP(X1, [INP + 1*16], BYTE_FLIP_MASK)
+       COPY_XMM_AND_BSWAP(X2, [INP + 2*16], BYTE_FLIP_MASK)
+       COPY_XMM_AND_BSWAP(X3, [INP + 3*16], BYTE_FLIP_MASK)
 
        mov     [rsp + _INP], INP
 
@@ -426,20 +397,20 @@ _gcry_sha256_transform_amd64_avx:
 .Loop1:
        vpaddd  XFER, X0, [TBL + 0*16]
        vmovdqa [rsp + _XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+       FOUR_ROUNDS_AND_SCHED(X0, X1, X2, X3, a, b, c, d, e, f, g, h)
 
-       vpaddd  XFER, X0, [TBL + 1*16]
+       vpaddd  XFER, X1, [TBL + 1*16]
        vmovdqa [rsp + _XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+       FOUR_ROUNDS_AND_SCHED(X1, X2, X3, X0, e, f, g, h, a, b, c, d)
 
-       vpaddd  XFER, X0, [TBL + 2*16]
+       vpaddd  XFER, X2, [TBL + 2*16]
        vmovdqa [rsp + _XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+       FOUR_ROUNDS_AND_SCHED(X2, X3, X0, X1, a, b, c, d, e, f, g, h)
 
-       vpaddd  XFER, X0, [TBL + 3*16]
+       vpaddd  XFER, X3, [TBL + 3*16]
        vmovdqa [rsp + _XFER], XFER
        add     TBL, 4*16
-       FOUR_ROUNDS_AND_SCHED
+       FOUR_ROUNDS_AND_SCHED(X3, X0, X1, X2, e, f, g, h, a, b, c, d)
 
        sub     SRND, 1
        jne     .Loop1
@@ -448,17 +419,17 @@ _gcry_sha256_transform_amd64_avx:
 .Loop2:
        vpaddd  X0, X0, [TBL + 0*16]
        vmovdqa [rsp + _XFER], X0
-       DO_ROUND        0
-       DO_ROUND        1
-       DO_ROUND        2
-       DO_ROUND        3
+       DO_ROUND(0, a, b, c, d, e, f, g, h)
+       DO_ROUND(1, h, a, b, c, d, e, f, g)
+       DO_ROUND(2, g, h, a, b, c, d, e, f)
+       DO_ROUND(3, f, g, h, a, b, c, d, e)
        vpaddd  X1, X1, [TBL + 1*16]
        vmovdqa [rsp + _XFER], X1
        add     TBL, 2*16
-       DO_ROUND        0
-       DO_ROUND        1
-       DO_ROUND        2
-       DO_ROUND        3
+       DO_ROUND(0, e, f, g, h, a, b, c, d)
+       DO_ROUND(1, d, e, f, g, h, a, b, c)
+       DO_ROUND(2, c, d, e, f, g, h, a, b)
+       DO_ROUND(3, b, c, d, e, f, g, h, a)
 
        vmovdqa X0, X2
        vmovdqa X1, X3
@@ -466,34 +437,42 @@ _gcry_sha256_transform_amd64_avx:
        sub     SRND, 1
        jne     .Loop2
 
-       addm    [4*0 + CTX],a
-       addm    [4*1 + CTX],b
-       addm    [4*2 + CTX],c
-       addm    [4*3 + CTX],d
-       addm    [4*4 + CTX],e
-       addm    [4*5 + CTX],f
-       addm    [4*6 + CTX],g
-       addm    [4*7 + CTX],h
+       addm([4*0 + CTX],a)
+       addm([4*1 + CTX],b)
+       addm([4*2 + CTX],c)
+       addm([4*3 + CTX],d)
+       addm([4*4 + CTX],e)
+       addm([4*5 + CTX],f)
+       addm([4*6 + CTX],g)
+       addm([4*7 + CTX],h)
 
        mov     INP, [rsp + _INP]
        add     INP, 64
        cmp     INP, [rsp + _INP_END]
        jne     .Loop0
 
+.Ldone_hash:
        vzeroall
 
-.Ldone_hash:
+       vmovdqa [rsp + _XFER], XFER
+       xor     eax, eax
+
        add     rsp, STACK_SIZE
+       CFI_ADJUST_CFA_OFFSET(-STACK_SIZE);
 
        pop     r15
+       CFI_POP(r15)
        pop     r14
+       CFI_POP(r14)
        pop     r13
+       CFI_POP(r13)
        pop     rbp
+       CFI_POP(rbp)
        pop     rbx
+       CFI_POP(rbx)
 
-       mov     eax, STACK_SIZE + 5*8
-
-       ret
+       ret_spec_stop
+       CFI_ENDPROC()
 
 
 .align 16
index 85e663f..60ad442 100644 (file)
     defined(HAVE_GCC_INLINE_ASM_AVX2) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \
     defined(USE_SHA256)
 
-#ifdef __PIC__
-#  define ADD_RIP +rip
-#else
-#  define ADD_RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .intel_syntax noprefix
 
 
 /*  addm [mem], reg */
 /*  Add reg to mem using reg-mem add and store */
-.macro addm p1 p2
-       add     \p2, \p1
-       mov     \p1, \p2
-.endm
+#define addm(p1, p2) \
+       add     p2, p1; \
+       mov     p1, p2;
 
 /* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
 
-X0 = ymm4
-X1 = ymm5
-X2 = ymm6
-X3 = ymm7
+#define X0 ymm4
+#define X1 ymm5
+#define X2 ymm6
+#define X3 ymm7
 
 /*  XMM versions of above */
-XWORD0 = xmm4
-XWORD1 = xmm5
-XWORD2 = xmm6
-XWORD3 = xmm7
-
-XTMP0 = ymm0
-XTMP1 = ymm1
-XTMP2 = ymm2
-XTMP3 = ymm3
-XTMP4 = ymm8
-XFER =  ymm9
-XTMP5 = ymm11
-
-SHUF_00BA = ymm10 /*  shuffle xBxA -> 00BA */
-SHUF_DC00 = ymm12 /*  shuffle xDxC -> DC00 */
-BYTE_FLIP_MASK = ymm13
-
-X_BYTE_FLIP_MASK = xmm13 /*  XMM version of BYTE_FLIP_MASK */
-
-NUM_BLKS = rdx /*  3rd arg */
-CTX =  rsi     /*  2nd arg */
-INP =  rdi     /*  1st arg */
-c =    ecx
-d =    r8d
-e =    edx     /*  clobbers NUM_BLKS */
-y3 =   edi     /*  clobbers INP */
-
-TBL =  rbp
-SRND = CTX     /*  SRND is same register as CTX */
-
-a =    eax
-b =    ebx
-f =    r9d
-g =    r10d
-h =    r11d
-old_h =        r11d
-
-T1 = r12d
-y0 = r13d
-y1 = r14d
-y2 = r15d
-
-
-_XFER_SIZE     = 2*64*4        /*  2 blocks, 64 rounds, 4 bytes/round */
-_XMM_SAVE_SIZE  = 0
-_INP_END_SIZE  = 8
-_INP_SIZE      = 8
-_CTX_SIZE      = 8
-_RSP_SIZE      = 8
-
-_XFER          = 0
-_XMM_SAVE      = _XFER     + _XFER_SIZE
-_INP_END       = _XMM_SAVE + _XMM_SAVE_SIZE
-_INP           = _INP_END  + _INP_END_SIZE
-_CTX           = _INP      + _INP_SIZE
-_RSP           = _CTX      + _CTX_SIZE
-STACK_SIZE     = _RSP      + _RSP_SIZE
-
-/*  rotate_Xs */
-/*  Rotate values of symbols X0...X3 */
-.macro rotate_Xs
-X_ = X0
-X0 = X1
-X1 = X2
-X2 = X3
-X3 = X_
-.endm
-
-/*  ROTATE_ARGS */
-/*  Rotate values of symbols a...h */
-.macro ROTATE_ARGS
-old_h = h
-TMP_ = h
-h = g
-g = f
-f = e
-e = d
-d = c
-c = b
-b = a
-a = TMP_
-.endm
-
-.macro FOUR_ROUNDS_AND_SCHED XFER
-/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       mov     y3, a           /*  y3 = a                                ; MAJA         */
-       rorx    y0, e, 25       /*  y0 = e >> 25                                ; S1A */
-       rorx    y1, e, 11       /*  y1 = e >> 11                                ; S1B */
-
-       add     h, [\XFER+0*4]          /*  h = k + w + h         ; --   */
-       or      y3, c           /*  y3 = a|c                              ; MAJA         */
-               vpalignr        XTMP0, X3, X2, 4        /*  XTMP0 = W[-7] */
-       mov     y2, f           /*  y2 = f                                ; CH   */
-       rorx    T1, a, 13       /*  T1 = a >> 13                                ; S0B */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11)              ; S1 */
-       xor     y2, g           /*  y2 = f^g                              ; CH   */
-               vpaddd  XTMP0, XTMP0, X0        /*  XTMP0 = W[-7] + W[-16]; y1 = (e >> 6)                                       ; S1 */
-       rorx    y1, e, 6        /*  y1 = (e >> 6)                               ; S1 */
-
-       and     y2, e           /*  y2 = (f^g)&e                          ; CH   */
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11) ^ (e>>6)     ; S1 */
-       rorx    y1, a, 22       /*  y1 = a >> 22                                ; S0A */
-       add     d, h            /*  d = k + w + h + d                     ; --   */
-
-       and     y3, b           /*  y3 = (a|c)&b                          ; MAJA         */
-               vpalignr        XTMP1, X1, X0, 4        /*  XTMP1 = W[-15] */
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13)              ; S0 */
-       rorx    T1, a, 2        /*  T1 = (a >> 2)                               ; S0 */
-
-       xor     y2, g           /*  y2 = CH = ((f^g)&e)^g                 ; CH   */
-               vpsrld  XTMP2, XTMP1, 7
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13) ^ (a>>2)     ; S0 */
-       mov     T1, a           /*  T1 = a                                ; MAJB         */
-       and     T1, c           /*  T1 = a&c                              ; MAJB         */
-
-       add     y2, y0          /*  y2 = S1 + CH                          ; --   */
-               vpslld  XTMP3, XTMP1, (32-7)
-       or      y3, T1          /*  y3 = MAJ = (a|c)&b)|(a&c)             ; MAJ  */
-       add     h, y1           /*  h = k + w + h + S0                    ; --   */
-
-       add     d, y2           /*  d = k + w + h + d + S1 + CH = d + t1  ; --   */
-               vpor    XTMP3, XTMP3, XTMP2     /*  XTMP3 = W[-15] ror 7 */
-
-               vpsrld  XTMP2, XTMP1,18
-       add     h, y2           /*  h = k + w + h + S0 + S1 + CH = t1 + S0; --   */
-       lea     h, [h + y3]     /*  h = t1 + S0 + MAJ                     ; --   */
-
-
-ROTATE_ARGS
-
-/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-
-       mov     y3, a           /*  y3 = a                                ; MAJA         */
-       rorx    y0, e, 25       /*  y0 = e >> 25                                ; S1A */
-       rorx    y1, e, 11       /*  y1 = e >> 11                                ; S1B */
-       add     h, [\XFER+1*4]          /*  h = k + w + h         ; --   */
-       or      y3, c           /*  y3 = a|c                              ; MAJA         */
-
-
-               vpsrld  XTMP4, XTMP1, 3 /*  XTMP4 = W[-15] >> 3 */
-       mov     y2, f           /*  y2 = f                                ; CH   */
-       rorx    T1, a, 13       /*  T1 = a >> 13                                ; S0B */
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11)              ; S1 */
-       xor     y2, g           /*  y2 = f^g                              ; CH   */
-
-
-       rorx    y1, e, 6        /*  y1 = (e >> 6)                               ; S1 */
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11) ^ (e>>6)     ; S1 */
-       rorx    y1, a, 22       /*  y1 = a >> 22                                ; S0A */
-       and     y2, e           /*  y2 = (f^g)&e                          ; CH   */
-       add     d, h            /*  d = k + w + h + d                     ; --   */
-
-               vpslld  XTMP1, XTMP1, (32-18)
-       and     y3, b           /*  y3 = (a|c)&b                          ; MAJA         */
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13)              ; S0 */
-
-               vpxor   XTMP3, XTMP3, XTMP1
-       rorx    T1, a, 2        /*  T1 = (a >> 2)                               ; S0 */
-       xor     y2, g           /*  y2 = CH = ((f^g)&e)^g                 ; CH   */
-
-               vpxor   XTMP3, XTMP3, XTMP2     /*  XTMP3 = W[-15] ror 7 ^ W[-15] ror 18 */
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13) ^ (a>>2)     ; S0 */
-       mov     T1, a           /*  T1 = a                                ; MAJB         */
-       and     T1, c           /*  T1 = a&c                              ; MAJB         */
-       add     y2, y0          /*  y2 = S1 + CH                          ; --   */
-
-               vpxor   XTMP1, XTMP3, XTMP4     /*  XTMP1 = s0 */
-               vpshufd XTMP2, X3, 0b11111010   /*  XTMP2 = W[-2] {BBAA} */
-       or      y3, T1          /*  y3 = MAJ = (a|c)&b)|(a&c)             ; MAJ  */
-       add     h, y1           /*  h = k + w + h + S0                    ; --   */
-
-               vpaddd  XTMP0, XTMP0, XTMP1     /*  XTMP0 = W[-16] + W[-7] + s0 */
-       add     d, y2           /*  d = k + w + h + d + S1 + CH = d + t1  ; --   */
-       add     h, y2           /*  h = k + w + h + S0 + S1 + CH = t1 + S0; --   */
-       lea     h, [h + y3]     /*  h = t1 + S0 + MAJ                     ; --   */
-
-               vpsrld  XTMP4, XTMP2, 10        /*  XTMP4 = W[-2] >> 10 {BBAA} */
-
-
-ROTATE_ARGS
-
-/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       mov     y3, a           /*  y3 = a                                ; MAJA         */
-       rorx    y0, e, 25       /*  y0 = e >> 25                                ; S1A */
-       add     h, [\XFER+2*4]          /*  h = k + w + h         ; --   */
-
-               vpsrlq  XTMP3, XTMP2, 19        /*  XTMP3 = W[-2] ror 19 {xBxA} */
-       rorx    y1, e, 11       /*  y1 = e >> 11                                ; S1B */
-       or      y3, c           /*  y3 = a|c                              ; MAJA         */
-       mov     y2, f           /*  y2 = f                                ; CH   */
-       xor     y2, g           /*  y2 = f^g                              ; CH   */
-
-       rorx    T1, a, 13       /*  T1 = a >> 13                                ; S0B */
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11)              ; S1 */
-               vpsrlq  XTMP2, XTMP2, 17        /*  XTMP2 = W[-2] ror 17 {xBxA} */
-       and     y2, e           /*  y2 = (f^g)&e                          ; CH   */
-
-       rorx    y1, e, 6        /*  y1 = (e >> 6)                               ; S1 */
-               vpxor   XTMP2, XTMP2, XTMP3
-       add     d, h            /*  d = k + w + h + d                     ; --   */
-       and     y3, b           /*  y3 = (a|c)&b                          ; MAJA         */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11) ^ (e>>6)     ; S1 */
-       rorx    y1, a, 22       /*  y1 = a >> 22                                ; S0A */
-               vpxor   XTMP4, XTMP4, XTMP2     /*  XTMP4 = s1 {xBxA} */
-       xor     y2, g           /*  y2 = CH = ((f^g)&e)^g                 ; CH   */
-
-               vpshufb XTMP4, XTMP4, SHUF_00BA /*  XTMP4 = s1 {00BA} */
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13)              ; S0 */
-       rorx    T1, a, 2        /*  T1 = (a >> 2)                               ; S0 */
-               vpaddd  XTMP0, XTMP0, XTMP4     /*  XTMP0 = {..., ..., W[1], W[0]} */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13) ^ (a>>2)     ; S0 */
-       mov     T1, a           /*  T1 = a                                ; MAJB         */
-       and     T1, c           /*  T1 = a&c                              ; MAJB         */
-       add     y2, y0          /*  y2 = S1 + CH                          ; --   */
-               vpshufd XTMP2, XTMP0, 0b1010000 /*  XTMP2 = W[-2] {DDCC} */
-
-       or      y3, T1          /*  y3 = MAJ = (a|c)&b)|(a&c)             ; MAJ  */
-       add     h, y1           /*  h = k + w + h + S0                    ; --   */
-       add     d, y2           /*  d = k + w + h + d + S1 + CH = d + t1  ; --   */
-       add     h, y2           /*  h = k + w + h + S0 + S1 + CH = t1 + S0; --   */
-
-       lea     h, [h + y3]     /*  h = t1 + S0 + MAJ                     ; --   */
-
-
-ROTATE_ARGS
-
-/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       mov     y3, a           /*  y3 = a                                ; MAJA         */
-       rorx    y0, e, 25       /*  y0 = e >> 25                                ; S1A */
-       rorx    y1, e, 11       /*  y1 = e >> 11                                ; S1B */
-       add     h, [\XFER+3*4]          /*  h = k + w + h         ; --   */
-       or      y3, c           /*  y3 = a|c                              ; MAJA         */
-
-
-               vpsrld  XTMP5, XTMP2,   10      /*  XTMP5 = W[-2] >> 10 {DDCC} */
-       mov     y2, f           /*  y2 = f                                ; CH   */
-       rorx    T1, a, 13       /*  T1 = a >> 13                                ; S0B */
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11)              ; S1 */
-       xor     y2, g           /*  y2 = f^g                              ; CH   */
-
-
-               vpsrlq  XTMP3, XTMP2, 19        /*  XTMP3 = W[-2] ror 19 {xDxC} */
-       rorx    y1, e, 6        /*  y1 = (e >> 6)                               ; S1 */
-       and     y2, e           /*  y2 = (f^g)&e                          ; CH   */
-       add     d, h            /*  d = k + w + h + d                     ; --   */
-       and     y3, b           /*  y3 = (a|c)&b                          ; MAJA         */
-
-               vpsrlq  XTMP2, XTMP2, 17        /*  XTMP2 = W[-2] ror 17 {xDxC} */
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11) ^ (e>>6)     ; S1 */
-       xor     y2, g           /*  y2 = CH = ((f^g)&e)^g                 ; CH   */
-
-               vpxor   XTMP2, XTMP2, XTMP3
-       rorx    y1, a, 22       /*  y1 = a >> 22                                ; S0A */
-       add     y2, y0          /*  y2 = S1 + CH                          ; --   */
-
-               vpxor   XTMP5, XTMP5, XTMP2     /*  XTMP5 = s1 {xDxC} */
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13)              ; S0 */
-       add     d, y2           /*  d = k + w + h + d + S1 + CH = d + t1  ; --   */
-
-       rorx    T1, a, 2        /*  T1 = (a >> 2)                               ; S0 */
-               vpshufb XTMP5, XTMP5, SHUF_DC00 /*  XTMP5 = s1 {DC00} */
-
-               vpaddd  X0, XTMP5, XTMP0        /*  X0 = {W[3], W[2], W[1], W[0]} */
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13) ^ (a>>2)     ; S0 */
-       mov     T1, a           /*  T1 = a                                ; MAJB         */
-       and     T1, c           /*  T1 = a&c                              ; MAJB         */
-       or      y3, T1          /*  y3 = MAJ = (a|c)&b)|(a&c)             ; MAJ  */
-
-       add     h, y1           /*  h = k + w + h + S0                    ; --   */
-       add     h, y2           /*  h = k + w + h + S0 + S1 + CH = t1 + S0; --   */
-       lea     h, [h + y3]     /*  h = t1 + S0 + MAJ                     ; --   */
-
-ROTATE_ARGS
-rotate_Xs
-.endm
-
-.macro DO_4ROUNDS XFER
-/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       mov     y2, f           /*  y2 = f                                ; CH   */
-       rorx    y0, e, 25       /*  y0 = e >> 25                                ; S1A */
-       rorx    y1, e, 11       /*  y1 = e >> 11                                ; S1B */
-       xor     y2, g           /*  y2 = f^g                              ; CH   */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11)              ; S1 */
-       rorx    y1, e, 6        /*  y1 = (e >> 6)                               ; S1 */
-       and     y2, e           /*  y2 = (f^g)&e                          ; CH   */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11) ^ (e>>6)     ; S1 */
-       rorx    T1, a, 13       /*  T1 = a >> 13                                ; S0B */
-       xor     y2, g           /*  y2 = CH = ((f^g)&e)^g                 ; CH   */
-       rorx    y1, a, 22       /*  y1 = a >> 22                                ; S0A */
-       mov     y3, a           /*  y3 = a                                ; MAJA         */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13)              ; S0 */
-       rorx    T1, a, 2        /*  T1 = (a >> 2)                               ; S0 */
-       add     h, [\XFER + 4*0]                /*  h = k + w + h ; --   */
-       or      y3, c           /*  y3 = a|c                              ; MAJA         */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13) ^ (a>>2)     ; S0 */
-       mov     T1, a           /*  T1 = a                                ; MAJB         */
-       and     y3, b           /*  y3 = (a|c)&b                          ; MAJA         */
-       and     T1, c           /*  T1 = a&c                              ; MAJB         */
-       add     y2, y0          /*  y2 = S1 + CH                          ; --   */
-
-
-       add     d, h            /*  d = k + w + h + d                     ; --   */
-       or      y3, T1          /*  y3 = MAJ = (a|c)&b)|(a&c)             ; MAJ  */
-       add     h, y1           /*  h = k + w + h + S0                    ; --   */
-
-       add     d, y2           /*  d = k + w + h + d + S1 + CH = d + t1  ; --   */
-
-
-       /* add  h, y2           ; h = k + w + h + S0 + S1 + CH = t1 + S0; --     */
-
-       /* lea  h, [h + y3]     ; h = t1 + S0 + MAJ                     ; --     */
-
-       ROTATE_ARGS
-
-/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       add     old_h, y2       /*  h = k + w + h + S0 + S1 + CH = t1 + S0; --   */
-       mov     y2, f           /*  y2 = f                                ; CH   */
-       rorx    y0, e, 25       /*  y0 = e >> 25                                ; S1A */
-       rorx    y1, e, 11       /*  y1 = e >> 11                                ; S1B */
-       xor     y2, g           /*  y2 = f^g                              ; CH   */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11)              ; S1 */
-       rorx    y1, e, 6        /*  y1 = (e >> 6)                               ; S1 */
-       and     y2, e           /*  y2 = (f^g)&e                          ; CH   */
-       add     old_h, y3       /*  h = t1 + S0 + MAJ                     ; --   */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11) ^ (e>>6)     ; S1 */
-       rorx    T1, a, 13       /*  T1 = a >> 13                                ; S0B */
-       xor     y2, g           /*  y2 = CH = ((f^g)&e)^g                 ; CH   */
-       rorx    y1, a, 22       /*  y1 = a >> 22                                ; S0A */
-       mov     y3, a           /*  y3 = a                                ; MAJA         */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13)              ; S0 */
-       rorx    T1, a, 2        /*  T1 = (a >> 2)                               ; S0 */
-       add     h, [\XFER + 4*1]                /*  h = k + w + h ; --   */
-       or      y3, c           /*  y3 = a|c                              ; MAJA         */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13) ^ (a>>2)     ; S0 */
-       mov     T1, a           /*  T1 = a                                ; MAJB         */
-       and     y3, b           /*  y3 = (a|c)&b                          ; MAJA         */
-       and     T1, c           /*  T1 = a&c                              ; MAJB         */
-       add     y2, y0          /*  y2 = S1 + CH                          ; --   */
-
-
-       add     d, h            /*  d = k + w + h + d                     ; --   */
-       or      y3, T1          /*  y3 = MAJ = (a|c)&b)|(a&c)             ; MAJ  */
-       add     h, y1           /*  h = k + w + h + S0                    ; --   */
-
-       add     d, y2           /*  d = k + w + h + d + S1 + CH = d + t1  ; --   */
-
-
-       /* add  h, y2           ; h = k + w + h + S0 + S1 + CH = t1 + S0; --     */
-
-       /* lea  h, [h + y3]     ; h = t1 + S0 + MAJ                     ; --     */
-
-       ROTATE_ARGS
-
-/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       add     old_h, y2       /*  h = k + w + h + S0 + S1 + CH = t1 + S0; --   */
-       mov     y2, f           /*  y2 = f                                ; CH   */
-       rorx    y0, e, 25       /*  y0 = e >> 25                                ; S1A */
-       rorx    y1, e, 11       /*  y1 = e >> 11                                ; S1B */
-       xor     y2, g           /*  y2 = f^g                              ; CH   */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11)              ; S1 */
-       rorx    y1, e, 6        /*  y1 = (e >> 6)                               ; S1 */
-       and     y2, e           /*  y2 = (f^g)&e                          ; CH   */
-       add     old_h, y3       /*  h = t1 + S0 + MAJ                     ; --   */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11) ^ (e>>6)     ; S1 */
-       rorx    T1, a, 13       /*  T1 = a >> 13                                ; S0B */
-       xor     y2, g           /*  y2 = CH = ((f^g)&e)^g                 ; CH   */
-       rorx    y1, a, 22       /*  y1 = a >> 22                                ; S0A */
-       mov     y3, a           /*  y3 = a                                ; MAJA         */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13)              ; S0 */
-       rorx    T1, a, 2        /*  T1 = (a >> 2)                               ; S0 */
-       add     h, [\XFER + 4*2]                /*  h = k + w + h ; --   */
-       or      y3, c           /*  y3 = a|c                              ; MAJA         */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13) ^ (a>>2)     ; S0 */
-       mov     T1, a           /*  T1 = a                                ; MAJB         */
-       and     y3, b           /*  y3 = (a|c)&b                          ; MAJA         */
-       and     T1, c           /*  T1 = a&c                              ; MAJB         */
-       add     y2, y0          /*  y2 = S1 + CH                          ; --   */
-
-
-       add     d, h            /*  d = k + w + h + d                     ; --   */
-       or      y3, T1          /*  y3 = MAJ = (a|c)&b)|(a&c)             ; MAJ  */
-       add     h, y1           /*  h = k + w + h + S0                    ; --   */
-
-       add     d, y2           /*  d = k + w + h + d + S1 + CH = d + t1  ; --   */
-
-
-       /* add  h, y2           ; h = k + w + h + S0 + S1 + CH = t1 + S0; --     */
-
-       /* lea  h, [h + y3]     ; h = t1 + S0 + MAJ                     ; --     */
-
-       ROTATE_ARGS
-
-/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       add     old_h, y2       /*  h = k + w + h + S0 + S1 + CH = t1 + S0; --   */
-       mov     y2, f           /*  y2 = f                                ; CH   */
-       rorx    y0, e, 25       /*  y0 = e >> 25                                ; S1A */
-       rorx    y1, e, 11       /*  y1 = e >> 11                                ; S1B */
-       xor     y2, g           /*  y2 = f^g                              ; CH   */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11)              ; S1 */
-       rorx    y1, e, 6        /*  y1 = (e >> 6)                               ; S1 */
-       and     y2, e           /*  y2 = (f^g)&e                          ; CH   */
-       add     old_h, y3       /*  h = t1 + S0 + MAJ                     ; --   */
-
-       xor     y0, y1          /*  y0 = (e>>25) ^ (e>>11) ^ (e>>6)     ; S1 */
-       rorx    T1, a, 13       /*  T1 = a >> 13                                ; S0B */
-       xor     y2, g           /*  y2 = CH = ((f^g)&e)^g                 ; CH   */
-       rorx    y1, a, 22       /*  y1 = a >> 22                                ; S0A */
-       mov     y3, a           /*  y3 = a                                ; MAJA         */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13)              ; S0 */
-       rorx    T1, a, 2        /*  T1 = (a >> 2)                               ; S0 */
-       add     h, [\XFER + 4*3]                /*  h = k + w + h ; --   */
-       or      y3, c           /*  y3 = a|c                              ; MAJA         */
-
-       xor     y1, T1          /*  y1 = (a>>22) ^ (a>>13) ^ (a>>2)     ; S0 */
-       mov     T1, a           /*  T1 = a                                ; MAJB         */
-       and     y3, b           /*  y3 = (a|c)&b                          ; MAJA         */
-       and     T1, c           /*  T1 = a&c                              ; MAJB         */
-       add     y2, y0          /*  y2 = S1 + CH                          ; --   */
-
-
-       add     d, h            /*  d = k + w + h + d                     ; --   */
-       or      y3, T1          /*  y3 = MAJ = (a|c)&b)|(a&c)             ; MAJ  */
-       add     h, y1           /*  h = k + w + h + S0                    ; --   */
-
-       add     d, y2           /*  d = k + w + h + d + S1 + CH = d + t1  ; --   */
-
-
-       add     h, y2           /*  h = k + w + h + S0 + S1 + CH = t1 + S0; --   */
-
-       lea     h, [h + y3]     /*  h = t1 + S0 + MAJ                     ; --   */
-
-       ROTATE_ARGS
-.endm
+#define XWORD0 xmm4
+#define XWORD1 xmm5
+#define XWORD2 xmm6
+#define XWORD3 xmm7
+
+#define XTMP0 ymm0
+#define XTMP1 ymm1
+#define XTMP2 ymm2
+#define XTMP3 ymm3
+#define XTMP4 ymm8
+#define XFER ymm9
+#define XTMP5 ymm11
+
+#define SHUF_00BA ymm10 /*  shuffle xBxA -> 00BA */
+#define SHUF_DC00 ymm12 /*  shuffle xDxC -> DC00 */
+#define BYTE_FLIP_MASK ymm13
+
+#define X_BYTE_FLIP_MASK xmm13 /*  XMM version of BYTE_FLIP_MASK */
+
+#define NUM_BLKS rdx /*  3rd arg */
+#define CTX rsi      /*  2nd arg */
+#define INP rdi      /*  1st arg */
+#define c ecx
+#define d r8d
+#define e edx        /*  clobbers NUM_BLKS */
+#define y3 edi       /*  clobbers INP */
+
+#define TBL rbp
+#define SRND CTX     /*  SRND is same register as CTX */
+
+#define a eax
+#define b ebx
+#define f r9d
+#define g r10d
+#define h r11d
+#define old_h r11d
+
+#define T1 r12d
+#define y0 r13d
+#define y1 r14d
+#define y2 r15d
+
+
+#define _XFER_SIZE 2*64*4      /*  2 blocks, 64 rounds, 4 bytes/round */
+#define _XMM_SAVE_SIZE 0
+#define _INP_END_SIZE 8
+#define _INP_SIZE 8
+#define _CTX_SIZE 8
+#define _RSP_SIZE 8
+
+#define _XFER 0
+#define _XMM_SAVE  _XFER     + _XFER_SIZE
+#define _INP_END   _XMM_SAVE + _XMM_SAVE_SIZE
+#define _INP       _INP_END  + _INP_END_SIZE
+#define _CTX       _INP      + _INP_SIZE
+#define _RSP       _CTX      + _CTX_SIZE
+#define STACK_SIZE _RSP      + _RSP_SIZE
+
+#define ONE_ROUND_PART1(XFERIN, a, b, c, d, e, f, g, h) \
+       /* h += Sum1 (e) + Ch (e, f, g) + (k[t] + w[0]); */ \
+       /* d += h; */ \
+       /* h += Sum0 (a) + Maj (a, b, c); */ \
+       \
+       /* Ch(x, y, z) => ((x & y) + (~x & z)) */ \
+       /* Maj(x, y, z) => ((x & y) + (z & (x ^ y))) */ \
+       \
+       mov y3, e; \
+       add h, [XFERIN]; \
+       and y3, f; \
+       rorx y0, e, 25; \
+       rorx y1, e, 11; \
+       lea h, [h + y3]; \
+       andn y3, e, g; \
+       rorx T1, a, 13; \
+       xor y0, y1; \
+       lea h, [h + y3]
+
+#define ONE_ROUND_PART2(a, b, c, d, e, f, g, h) \
+       rorx y2, a, 22; \
+       rorx y1, e, 6; \
+       mov y3, a; \
+       xor T1, y2; \
+       xor y0, y1; \
+       xor y3, b; \
+       lea h, [h + y0]; \
+       mov y0, a; \
+       rorx y2, a, 2; \
+       add d, h; \
+       and y3, c; \
+       xor T1, y2; \
+       lea h, [h + y3]; \
+       lea h, [h + T1]; \
+       and y0, b; \
+       lea h, [h + y0]
+
+#define ONE_ROUND(XFER, a, b, c, d, e, f, g, h) \
+       ONE_ROUND_PART1(XFER, a, b, c, d, e, f, g, h); \
+       ONE_ROUND_PART2(a, b, c, d, e, f, g, h)
+
+#define FOUR_ROUNDS_AND_SCHED(XFERIN, XFEROUT, X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+       /* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; */; \
+               vpalignr        XTMP0, X3, X2, 4        /*  XTMP0 = W[-7] */; \
+               vpaddd  XTMP0, XTMP0, X0        /*  XTMP0 = W[-7] + W[-16]; y1 = (e >> 6); S1 */; \
+               vpalignr        XTMP1, X1, X0, 4        /*  XTMP1 = W[-15] */; \
+               vpsrld  XTMP2, XTMP1, 7; \
+               vpslld  XTMP3, XTMP1, (32-7); \
+               vpor    XTMP3, XTMP3, XTMP2     /*  XTMP3 = W[-15] ror 7 */; \
+               vpsrld  XTMP2, XTMP1,18; \
+       \
+       ONE_ROUND(0*4+XFERIN, a, b, c, d, e, f, g, h); \
+       \
+       /* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; */; \
+               vpsrld  XTMP4, XTMP1, 3 /*  XTMP4 = W[-15] >> 3 */; \
+               vpslld  XTMP1, XTMP1, (32-18); \
+               vpxor   XTMP3, XTMP3, XTMP1; \
+               vpxor   XTMP3, XTMP3, XTMP2     /*  XTMP3 = W[-15] ror 7 ^ W[-15] ror 18 */; \
+               vpxor   XTMP1, XTMP3, XTMP4     /*  XTMP1 = s0 */; \
+               vpshufd XTMP2, X3, 0b11111010   /*  XTMP2 = W[-2] {BBAA} */; \
+               vpaddd  XTMP0, XTMP0, XTMP1     /*  XTMP0 = W[-16] + W[-7] + s0 */; \
+               vpsrld  XTMP4, XTMP2, 10        /*  XTMP4 = W[-2] >> 10 {BBAA} */; \
+       \
+       ONE_ROUND(1*4+XFERIN, h, a, b, c, d, e, f, g); \
+       \
+       /* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; */; \
+               vpsrlq  XTMP3, XTMP2, 19        /*  XTMP3 = W[-2] ror 19 {xBxA} */; \
+               vpsrlq  XTMP2, XTMP2, 17        /*  XTMP2 = W[-2] ror 17 {xBxA} */; \
+               vpxor   XTMP2, XTMP2, XTMP3; \
+               vpxor   XTMP4, XTMP4, XTMP2     /*  XTMP4 = s1 {xBxA} */; \
+               vpshufb XTMP4, XTMP4, SHUF_00BA /*  XTMP4 = s1 {00BA} */; \
+               vpaddd  XTMP0, XTMP0, XTMP4     /*  XTMP0 = {..., ..., W[1], W[0]} */; \
+               vpshufd XTMP2, XTMP0, 0b1010000 /*  XTMP2 = W[-2] {DDCC} */; \
+       \
+       ONE_ROUND(2*4+XFERIN, g, h, a, b, c, d, e, f); \
+       \
+       /* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;; */; \
+               vpsrld  XTMP5, XTMP2,   10      /*  XTMP5 = W[-2] >> 10 {DDCC} */; \
+               vpsrlq  XTMP3, XTMP2, 19        /*  XTMP3 = W[-2] ror 19 {xDxC} */; \
+               vpsrlq  XTMP2, XTMP2, 17        /*  XTMP2 = W[-2] ror 17 {xDxC} */; \
+               vpxor   XTMP2, XTMP2, XTMP3; \
+               vpxor   XTMP5, XTMP5, XTMP2     /*  XTMP5 = s1 {xDxC} */; \
+               vpshufb XTMP5, XTMP5, SHUF_DC00 /*  XTMP5 = s1 {DC00} */; \
+               vpaddd  X0, XTMP5, XTMP0        /*  X0 = {W[3], W[2], W[1], W[0]} */; \
+               vpaddd  XFER, X0, [TBL + XFEROUT]; \
+       \
+       ONE_ROUND_PART1(3*4+XFERIN, f, g, h, a, b, c, d, e); \
+               vmovdqa [rsp + _XFER + XFEROUT], XFER; \
+       ONE_ROUND_PART2(f, g, h, a, b, c, d, e);
+
+#define DO_4ROUNDS(XFERIN, a, b, c, d, e, f, g, h) \
+       ONE_ROUND(0*4+XFERIN, a, b, c, d, e, f, g, h); \
+       ONE_ROUND(1*4+XFERIN, h, a, b, c, d, e, f, g); \
+       ONE_ROUND(2*4+XFERIN, g, h, a, b, c, d, e, f); \
+       ONE_ROUND(3*4+XFERIN, f, g, h, a, b, c, d, e)
 
 /*
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -565,27 +249,46 @@ rotate_Xs
 ELF(.type _gcry_sha256_transform_amd64_avx2,@function)
 .align 32
 _gcry_sha256_transform_amd64_avx2:
+       CFI_STARTPROC()
+       xor eax, eax
+
+       cmp rdx, 0
+       je .Lnowork
+
        push    rbx
+       CFI_PUSH(rbx)
        push    rbp
+       CFI_PUSH(rbp)
        push    r12
+       CFI_PUSH(r12)
        push    r13
+       CFI_PUSH(r13)
        push    r14
+       CFI_PUSH(r14)
        push    r15
+       CFI_PUSH(r15)
 
        vzeroupper
 
+       vmovdqa BYTE_FLIP_MASK, [.LPSHUFFLE_BYTE_FLIP_MASK ADD_RIP]
+       vmovdqa SHUF_00BA, [.L_SHUF_00BA ADD_RIP]
+       vmovdqa SHUF_DC00, [.L_SHUF_DC00 ADD_RIP]
+
        mov     rax, rsp
+       CFI_DEF_CFA_REGISTER(rax);
        sub     rsp, STACK_SIZE
-       and     rsp, -32
+       and     rsp, ~63
        mov     [rsp + _RSP], rax
+       CFI_CFA_ON_STACK(_RSP, 6 * 8)
 
        shl     NUM_BLKS, 6     /*  convert to bytes */
-       jz      .Ldone_hash
        lea     NUM_BLKS, [NUM_BLKS + INP - 64] /*  pointer to last block */
        mov     [rsp + _INP_END], NUM_BLKS
 
-       cmp     INP, NUM_BLKS
-       je      .Lonly_one_block
+       /* Check if only one block of input. Note: Loading initial digest
+        * only uses 'mov' instruction and does not change condition
+        * flags. */
+       cmp     NUM_BLKS, INP
 
        /* ; load initial digest */
        mov     a,[4*0 + CTX]
@@ -597,12 +300,10 @@ _gcry_sha256_transform_amd64_avx2:
        mov     g,[4*6 + CTX]
        mov     h,[4*7 + CTX]
 
-       vmovdqa BYTE_FLIP_MASK, [.LPSHUFFLE_BYTE_FLIP_MASK ADD_RIP]
-       vmovdqa SHUF_00BA, [.L_SHUF_00BA ADD_RIP]
-       vmovdqa SHUF_DC00, [.L_SHUF_DC00 ADD_RIP]
-
        mov     [rsp + _CTX], CTX
 
+       je      .Ldo_last_block
+
 .Loop0:
        lea     TBL, [.LK256 ADD_RIP]
 
@@ -631,55 +332,43 @@ _gcry_sha256_transform_amd64_avx2:
        /* ; schedule 48 input dwords, by doing 3 rounds of 12 each */
        xor     SRND, SRND
 
+       vpaddd  XFER, X0, [TBL + 0*32]
+       vmovdqa [rsp + _XFER + 0*32], XFER
+       vpaddd  XFER, X1, [TBL + 1*32]
+       vmovdqa [rsp + _XFER + 1*32], XFER
+       vpaddd  XFER, X2, [TBL + 2*32]
+       vmovdqa [rsp + _XFER + 2*32], XFER
+       vpaddd  XFER, X3, [TBL + 3*32]
+       vmovdqa [rsp + _XFER + 3*32], XFER
+
 .align 16
 .Loop1:
-       vpaddd  XFER, X0, [TBL + SRND + 0*32]
-       vmovdqa [rsp + _XFER + SRND + 0*32], XFER
-       FOUR_ROUNDS_AND_SCHED   rsp + _XFER + SRND + 0*32
-
-       vpaddd  XFER, X0, [TBL + SRND + 1*32]
-       vmovdqa [rsp + _XFER + SRND + 1*32], XFER
-       FOUR_ROUNDS_AND_SCHED   rsp + _XFER + SRND + 1*32
-
-       vpaddd  XFER, X0, [TBL + SRND + 2*32]
-       vmovdqa [rsp + _XFER + SRND + 2*32], XFER
-       FOUR_ROUNDS_AND_SCHED   rsp + _XFER + SRND + 2*32
-
-       vpaddd  XFER, X0, [TBL + SRND + 3*32]
-       vmovdqa [rsp + _XFER + SRND + 3*32], XFER
-       FOUR_ROUNDS_AND_SCHED   rsp + _XFER + SRND + 3*32
+       FOUR_ROUNDS_AND_SCHED(rsp + _XFER + SRND + 0*32, SRND + 4*32, X0, X1, X2, X3, a, b, c, d, e, f, g, h)
+       FOUR_ROUNDS_AND_SCHED(rsp + _XFER + SRND + 1*32, SRND + 5*32, X1, X2, X3, X0, e, f, g, h, a, b, c, d)
+       FOUR_ROUNDS_AND_SCHED(rsp + _XFER + SRND + 2*32, SRND + 6*32, X2, X3, X0, X1, a, b, c, d, e, f, g, h)
+       FOUR_ROUNDS_AND_SCHED(rsp + _XFER + SRND + 3*32, SRND + 7*32, X3, X0, X1, X2, e, f, g, h, a, b, c, d)
 
        add     SRND, 4*32
        cmp     SRND, 3 * 4*32
        jb      .Loop1
 
-.Loop2:
        /* ; Do last 16 rounds with no scheduling */
-       vpaddd  XFER, X0, [TBL + SRND + 0*32]
-       vmovdqa [rsp + _XFER + SRND + 0*32], XFER
-       DO_4ROUNDS      rsp + _XFER + SRND + 0*32
-       vpaddd  XFER, X1, [TBL + SRND + 1*32]
-       vmovdqa [rsp + _XFER + SRND + 1*32], XFER
-       DO_4ROUNDS      rsp + _XFER + SRND + 1*32
-       add     SRND, 2*32
-
-       vmovdqa X0, X2
-       vmovdqa X1, X3
-
-       cmp     SRND, 4 * 4*32
-       jb      .Loop2
+       DO_4ROUNDS(rsp + _XFER + (3*4*32 + 0*32), a, b, c, d, e, f, g, h)
+       DO_4ROUNDS(rsp + _XFER + (3*4*32 + 1*32), e, f, g, h, a, b, c, d)
+       DO_4ROUNDS(rsp + _XFER + (3*4*32 + 2*32), a, b, c, d, e, f, g, h)
+       DO_4ROUNDS(rsp + _XFER + (3*4*32 + 3*32), e, f, g, h, a, b, c, d)
 
        mov     CTX, [rsp + _CTX]
        mov     INP, [rsp + _INP]
 
-       addm    [4*0 + CTX],a
-       addm    [4*1 + CTX],b
-       addm    [4*2 + CTX],c
-       addm    [4*3 + CTX],d
-       addm    [4*4 + CTX],e
-       addm    [4*5 + CTX],f
-       addm    [4*6 + CTX],g
-       addm    [4*7 + CTX],h
+       addm([4*0 + CTX],a)
+       addm([4*1 + CTX],b)
+       addm([4*2 + CTX],c)
+       addm([4*3 + CTX],d)
+       addm([4*4 + CTX],e)
+       addm([4*5 + CTX],f)
+       addm([4*6 + CTX],g)
+       addm([4*7 + CTX],h)
 
        cmp     INP, [rsp + _INP_END]
        ja      .Ldone_hash
@@ -688,8 +377,8 @@ _gcry_sha256_transform_amd64_avx2:
        xor     SRND, SRND
 .align 16
 .Loop3:
-       DO_4ROUNDS      rsp + _XFER + SRND + 0*32 + 16
-       DO_4ROUNDS      rsp + _XFER + SRND + 1*32 + 16
+       DO_4ROUNDS(rsp + _XFER + SRND + 0*32 + 16, a, b, c, d, e, f, g, h)
+       DO_4ROUNDS(rsp + _XFER + SRND + 1*32 + 16, e, f, g, h, a, b, c, d)
        add     SRND, 2*32
        cmp     SRND, 4 * 4*32
        jb .Loop3
@@ -698,14 +387,14 @@ _gcry_sha256_transform_amd64_avx2:
        mov     INP, [rsp + _INP]
        add     INP, 64
 
-       addm    [4*0 + CTX],a
-       addm    [4*1 + CTX],b
-       addm    [4*2 + CTX],c
-       addm    [4*3 + CTX],d
-       addm    [4*4 + CTX],e
-       addm    [4*5 + CTX],f
-       addm    [4*6 + CTX],g
-       addm    [4*7 + CTX],h
+       addm([4*0 + CTX],a)
+       addm([4*1 + CTX],b)
+       addm([4*2 + CTX],c)
+       addm([4*3 + CTX],d)
+       addm([4*4 + CTX],e)
+       addm([4*5 + CTX],f)
+       addm([4*6 + CTX],g)
+       addm([4*7 + CTX],h)
 
        cmp     INP, [rsp + _INP_END]
        jb      .Loop0
@@ -747,21 +436,46 @@ _gcry_sha256_transform_amd64_avx2:
        jmp     .Ldo_last_block
 
 .Ldone_hash:
-       mov     rsp, [rsp + _RSP]
-
        vzeroall
 
+       /* burn stack */
+       vmovdqa [rsp + _XFER + 0 * 32], ymm0
+       vmovdqa [rsp + _XFER + 1 * 32], ymm0
+       vmovdqa [rsp + _XFER + 2 * 32], ymm0
+       vmovdqa [rsp + _XFER + 3 * 32], ymm0
+       vmovdqa [rsp + _XFER + 4 * 32], ymm0
+       vmovdqa [rsp + _XFER + 5 * 32], ymm0
+       vmovdqa [rsp + _XFER + 6 * 32], ymm0
+       vmovdqa [rsp + _XFER + 7 * 32], ymm0
+       vmovdqa [rsp + _XFER + 8 * 32], ymm0
+       vmovdqa [rsp + _XFER + 9 * 32], ymm0
+       vmovdqa [rsp + _XFER + 10 * 32], ymm0
+       vmovdqa [rsp + _XFER + 11 * 32], ymm0
+       vmovdqa [rsp + _XFER + 12 * 32], ymm0
+       vmovdqa [rsp + _XFER + 13 * 32], ymm0
+       vmovdqa [rsp + _XFER + 14 * 32], ymm0
+       vmovdqa [rsp + _XFER + 15 * 32], ymm0
+       xor     eax, eax
+
+       mov     rsp, [rsp + _RSP]
+       CFI_DEF_CFA_REGISTER(rsp)
+
        pop     r15
+       CFI_POP(r15)
        pop     r14
+       CFI_POP(r14)
        pop     r13
+       CFI_POP(r13)
        pop     r12
+       CFI_POP(r12)
        pop     rbp
+       CFI_POP(rbp)
        pop     rbx
+       CFI_POP(rbx)
 
-       /* stack burn depth */
-       mov     eax, STACK_SIZE + 6*8 + 31
-
-       ret
+.Lnowork:
+       ret_spec_stop
+       CFI_ENDPROC()
 
 .align 64
 .LK256:
diff --git a/cipher/sha256-intel-shaext.c b/cipher/sha256-intel-shaext.c
new file mode 100644 (file)
index 0000000..48c09ee
--- /dev/null
@@ -0,0 +1,363 @@
+/* sha256-intel-shaext.S - SHAEXT accelerated SHA-256 transform function
+ * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "types.h"
+
+#if defined(HAVE_GCC_INLINE_ASM_SHAEXT) && \
+    defined(HAVE_GCC_INLINE_ASM_SSE41) && defined(USE_SHA256) && \
+    defined(ENABLE_SHAEXT_SUPPORT)
+
+#if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
+/* Prevent compiler from issuing SSE instructions between asm blocks. */
+#  pragma GCC target("no-sse")
+#endif
+#if __clang__
+#  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
+#endif
+
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR NO_INSTRUMENT_FUNCTION
+
+/* Two macros to be called prior and after the use of SHA-EXT
+   instructions.  There should be no external function calls between
+   the use of these macros.  There purpose is to make sure that the
+   SSE regsiters are cleared and won't reveal any information about
+   the key or the data.  */
+#ifdef __WIN64__
+/* XMM6-XMM15 are callee-saved registers on WIN64. */
+# define shaext_prepare_variable char win64tmp[2*16]
+# define shaext_prepare_variable_size sizeof(win64tmp)
+# define shaext_prepare()                                               \
+   do { asm volatile ("movdqu %%xmm6, (%0)\n"                           \
+                      "movdqu %%xmm7, (%1)\n"                           \
+                      :                                                 \
+                      : "r" (&win64tmp[0]), "r" (&win64tmp[16])         \
+                      : "memory");                                      \
+   } while (0)
+# define shaext_cleanup(tmp0,tmp1)                                      \
+   do { asm volatile ("movdqu (%0), %%xmm6\n"                           \
+                      "movdqu (%1), %%xmm7\n"                           \
+                      "pxor %%xmm0, %%xmm0\n"                           \
+                      "pxor %%xmm1, %%xmm1\n"                           \
+                      "pxor %%xmm2, %%xmm2\n"                           \
+                      "pxor %%xmm3, %%xmm3\n"                           \
+                      "pxor %%xmm4, %%xmm4\n"                           \
+                      "pxor %%xmm5, %%xmm5\n"                           \
+                      "movdqa %%xmm0, (%2)\n\t"                         \
+                      "movdqa %%xmm0, (%3)\n\t"                         \
+                      :                                                 \
+                      : "r" (&win64tmp[0]), "r" (&win64tmp[16]),        \
+                        "r" (tmp0), "r" (tmp1)                          \
+                      : "memory");                                      \
+   } while (0)
+#else
+# define shaext_prepare_variable
+# define shaext_prepare_variable_size 0
+# define shaext_prepare() do { } while (0)
+# define shaext_cleanup(tmp0,tmp1)                                      \
+   do { asm volatile ("pxor %%xmm0, %%xmm0\n"                           \
+                      "pxor %%xmm1, %%xmm1\n"                           \
+                      "pxor %%xmm2, %%xmm2\n"                           \
+                      "pxor %%xmm3, %%xmm3\n"                           \
+                      "pxor %%xmm4, %%xmm4\n"                           \
+                      "pxor %%xmm5, %%xmm5\n"                           \
+                      "pxor %%xmm6, %%xmm6\n"                           \
+                      "pxor %%xmm7, %%xmm7\n"                           \
+                      "movdqa %%xmm0, (%0)\n\t"                         \
+                      "movdqa %%xmm0, (%1)\n\t"                         \
+                      :                                                 \
+                      : "r" (tmp0), "r" (tmp1)                          \
+                      : "memory");                                      \
+   } while (0)
+#endif
+
+typedef struct u128_s
+{
+  u32 a, b, c, d;
+} u128_t;
+
+/*
+ * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
+ */
+unsigned int ASM_FUNC_ATTR
+_gcry_sha256_transform_intel_shaext(u32 state[8], const unsigned char *data,
+                                    size_t nblks)
+{
+  static const unsigned char bshuf_mask[16] __attribute__ ((aligned (16))) =
+    { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 };
+  static const u128_t K[16] __attribute__ ((aligned (16))) =
+  {
+    { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 },
+    { 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 },
+    { 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 },
+    { 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 },
+    { 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc },
+    { 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da },
+    { 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 },
+    { 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 },
+    { 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 },
+    { 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 },
+    { 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 },
+    { 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 },
+    { 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 },
+    { 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 },
+    { 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 },
+    { 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }
+  };
+  char save_buf[2 * 16 + 15];
+  char *abef_save;
+  char *cdgh_save;
+  shaext_prepare_variable;
+
+  if (nblks == 0)
+    return 0;
+
+  shaext_prepare ();
+
+  asm volatile ("" : "=r" (abef_save) : "0" (save_buf) : "memory");
+  abef_save = abef_save + (-(uintptr_t)abef_save & 15);
+  cdgh_save = abef_save + 16;
+
+  /* byteswap mask => XMM7 */
+  asm volatile ("movdqa %[mask], %%xmm7\n\t" /* Preload mask */
+                :
+                : [mask] "m" (*bshuf_mask)
+                : "memory");
+
+  /* Load state.. ABEF_SAVE => STATE0 XMM1, CDGH_STATE => STATE1 XMM2 */
+  asm volatile ("movups 16(%[state]), %%xmm1\n\t" /* HGFE (xmm=EFGH) */
+                "movups  0(%[state]), %%xmm0\n\t" /* DCBA (xmm=ABCD) */
+                "movaps %%xmm1, %%xmm2\n\t"
+                "shufps $0x11, %%xmm0, %%xmm1\n\t" /* ABEF (xmm=FEBA) */
+                "shufps $0xbb, %%xmm0, %%xmm2\n\t" /* CDGH (xmm=HGDC) */
+                :
+                : [state] "r" (state)
+                : "memory" );
+
+  /* Load message */
+  asm volatile ("movdqu 0*16(%[data]), %%xmm3\n\t"
+                "movdqu 1*16(%[data]), %%xmm4\n\t"
+                "movdqu 2*16(%[data]), %%xmm5\n\t"
+                "movdqu 3*16(%[data]), %%xmm6\n\t"
+                "pshufb %%xmm7, %%xmm3\n\t"
+                "pshufb %%xmm7, %%xmm4\n\t"
+                "pshufb %%xmm7, %%xmm5\n\t"
+                "pshufb %%xmm7, %%xmm6\n\t"
+                :
+                : [data] "r" (data)
+                : "memory" );
+  data += 64;
+
+  do
+    {
+      /* Save state */
+      asm volatile ("movdqa %%xmm1, (%[abef_save])\n\t"
+                    "movdqa %%xmm2, (%[cdgh_save])\n\t"
+                    :
+                    : [abef_save] "r" (abef_save), [cdgh_save] "r" (cdgh_save)
+                    : "memory" );
+
+      /* Round 0..3 */
+      asm volatile ("movdqa %%xmm3, %%xmm0\n\t"
+                      "paddd %[constants], %%xmm0\n\t"
+                      "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                      "psrldq $8, %%xmm0\n\t"
+                      "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                    :
+                    : [constants] "m" (K[0].a)
+                    : "memory" );
+
+      /* Round 4..7 */
+      asm volatile ("movdqa %%xmm4, %%xmm0\n\t"
+                      "paddd %[constants], %%xmm0\n\t"
+                      "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                      "psrldq $8, %%xmm0\n\t"
+                      "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                    "sha256msg1 %%xmm4, %%xmm3\n\t"
+                    :
+                    : [constants] "m" (K[1].a)
+                    : "memory" );
+
+      /* Round 8..11 */
+      asm volatile ("movdqa %%xmm5, %%xmm0\n\t"
+                      "paddd %[constants], %%xmm0\n\t"
+                      "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                      "psrldq $8, %%xmm0\n\t"
+                      "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                    "sha256msg1 %%xmm5, %%xmm4\n\t"
+                    :
+                    : [constants] "m" (K[2].a)
+                    : "memory" );
+
+#define ROUND(k, MSG0, MSG1, MSG2, MSG3) \
+      asm volatile ("movdqa %%"MSG0", %%xmm0\n\t" \
+                      "paddd %[constants], %%xmm0\n\t" \
+                      "sha256rnds2 %%xmm1, %%xmm2\n\t" \
+                    "movdqa %%"MSG0", %%xmm7\n\t" \
+                    "palignr $4, %%"MSG3", %%xmm7\n\t" \
+                    "paddd %%xmm7, %%"MSG1"\n\t" \
+                    "sha256msg2 %%"MSG0", %%"MSG1"\n\t" \
+                      "psrldq $8, %%xmm0\n\t" \
+                      "sha256rnds2 %%xmm2, %%xmm1\n\t" \
+                    "sha256msg1 %%"MSG0", %%"MSG3"\n\t" \
+                    : \
+                    : [constants] "m" (K[k].a) \
+                    : "memory" )
+
+      /* Rounds 12..15 to 48..51 */
+      ROUND(3, "xmm6", "xmm3", "xmm4", "xmm5");
+      ROUND(4, "xmm3", "xmm4", "xmm5", "xmm6");
+      ROUND(5, "xmm4", "xmm5", "xmm6", "xmm3");
+      ROUND(6, "xmm5", "xmm6", "xmm3", "xmm4");
+      ROUND(7, "xmm6", "xmm3", "xmm4", "xmm5");
+      ROUND(8, "xmm3", "xmm4", "xmm5", "xmm6");
+      ROUND(9, "xmm4", "xmm5", "xmm6", "xmm3");
+      ROUND(10, "xmm5", "xmm6", "xmm3", "xmm4");
+      ROUND(11, "xmm6", "xmm3", "xmm4", "xmm5");
+      ROUND(12, "xmm3", "xmm4", "xmm5", "xmm6");
+
+      if (--nblks == 0)
+        break;
+
+      /* Round 52..55 */
+      asm volatile ("movdqa %%xmm4, %%xmm0\n\t"
+                      "paddd %[constants], %%xmm0\n\t"
+                      "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                    "movdqa %%xmm4, %%xmm7\n\t"
+                    "palignr $4, %%xmm3, %%xmm7\n\t"
+                    "movdqu 0*16(%[data]), %%xmm3\n\t"
+                    "paddd %%xmm7, %%xmm5\n\t"
+                    "sha256msg2 %%xmm4, %%xmm5\n\t"
+                      "psrldq $8, %%xmm0\n\t"
+                      "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                    :
+                    : [constants] "m" (K[13].a), [data] "r" (data)
+                    : "memory" );
+
+      /* Round 56..59 */
+      asm volatile ("movdqa %%xmm5, %%xmm0\n\t"
+                      "paddd %[constants], %%xmm0\n\t"
+                      "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                    "movdqa %%xmm5, %%xmm7\n\t"
+                    "palignr $4, %%xmm4, %%xmm7\n\t"
+                    "movdqu 1*16(%[data]), %%xmm4\n\t"
+                    "paddd %%xmm7, %%xmm6\n\t"
+                    "movdqa %[mask], %%xmm7\n\t" /* Reload mask */
+                    "sha256msg2 %%xmm5, %%xmm6\n\t"
+                    "movdqu 2*16(%[data]), %%xmm5\n\t"
+                      "psrldq $8, %%xmm0\n\t"
+                      "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                    :
+                    : [constants] "m" (K[14].a), [mask] "m" (*bshuf_mask),
+                      [data] "r" (data)
+                    : "memory" );
+
+      /* Round 60..63 */
+      asm volatile ("movdqa %%xmm6, %%xmm0\n\t"
+                    "pshufb %%xmm7, %%xmm3\n\t"
+                    "movdqu 3*16(%[data]), %%xmm6\n\t"
+                      "paddd %[constants], %%xmm0\n\t"
+                    "pshufb %%xmm7, %%xmm4\n\t"
+                      "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                      "psrldq $8, %%xmm0\n\t"
+                    "pshufb %%xmm7, %%xmm5\n\t"
+                      "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                    :
+                    : [constants] "m" (K[15].a), [data] "r" (data)
+                    : "memory" );
+      data += 64;
+
+      /* Merge states */
+      asm volatile ("paddd (%[abef_save]), %%xmm1\n\t"
+                    "paddd (%[cdgh_save]), %%xmm2\n\t"
+                    "pshufb %%xmm7, %%xmm6\n\t"
+                    :
+                    : [abef_save] "r" (abef_save), [cdgh_save] "r" (cdgh_save)
+                    : "memory" );
+    }
+  while (1);
+
+  /* Round 52..55 */
+  asm volatile ("movdqa %%xmm4, %%xmm0\n\t"
+                  "paddd %[constants], %%xmm0\n\t"
+                  "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                "movdqa %%xmm4, %%xmm7\n\t"
+                "palignr $4, %%xmm3, %%xmm7\n\t"
+                "paddd %%xmm7, %%xmm5\n\t"
+                "sha256msg2 %%xmm4, %%xmm5\n\t"
+                  "psrldq $8, %%xmm0\n\t"
+                  "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                :
+                : [constants] "m" (K[13].a)
+                : "memory" );
+
+  /* Round 56..59 */
+  asm volatile ("movdqa %%xmm5, %%xmm0\n\t"
+                  "paddd %[constants], %%xmm0\n\t"
+                  "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                "movdqa %%xmm5, %%xmm7\n\t"
+                "palignr $4, %%xmm4, %%xmm7\n\t"
+                "paddd %%xmm7, %%xmm6\n\t"
+                "movdqa %[mask], %%xmm7\n\t" /* Reload mask */
+                "sha256msg2 %%xmm5, %%xmm6\n\t"
+                  "psrldq $8, %%xmm0\n\t"
+                  "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                :
+                : [constants] "m" (K[14].a), [mask] "m" (*bshuf_mask)
+                : "memory" );
+
+  /* Round 60..63 */
+  asm volatile ("movdqa %%xmm6, %%xmm0\n\t"
+                  "paddd %[constants], %%xmm0\n\t"
+                  "sha256rnds2 %%xmm1, %%xmm2\n\t"
+                  "psrldq $8, %%xmm0\n\t"
+                  "sha256rnds2 %%xmm2, %%xmm1\n\t"
+                :
+                : [constants] "m" (K[15].a)
+                : "memory" );
+
+  /* Merge states */
+  asm volatile ("paddd (%[abef_save]), %%xmm1\n\t"
+                "paddd (%[cdgh_save]), %%xmm2\n\t"
+                :
+                : [abef_save] "r" (abef_save), [cdgh_save] "r" (cdgh_save)
+                : "memory" );
+
+  /* Save state (XMM1=FEBA, XMM2=HGDC) */
+  asm volatile ("movaps %%xmm1, %%xmm0\n\t"
+                "shufps $0x11, %%xmm2, %%xmm1\n\t" /* xmm=ABCD */
+                "shufps $0xbb, %%xmm2, %%xmm0\n\t" /* xmm=EFGH */
+                "movups %%xmm1, 16(%[state])\n\t"
+                "movups %%xmm0,  0(%[state])\n\t"
+                :
+                : [state] "r" (state)
+                : "memory" );
+
+  shaext_cleanup (abef_save, cdgh_save);
+  return 0;
+}
+
+#if __clang__
+#  pragma clang attribute pop
+#endif
+
+#endif /* HAVE_GCC_INLINE_ASM_SHA_EXT */
diff --git a/cipher/sha256-ppc.c b/cipher/sha256-ppc.c
new file mode 100644 (file)
index 0000000..a9b5971
--- /dev/null
@@ -0,0 +1,795 @@
+/* sha256-ppc.c - PowerPC vcrypto implementation of SHA-256 transform
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#if defined(ENABLE_PPC_CRYPTO_SUPPORT) && \
+    defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+    defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) && \
+    defined(USE_SHA256) && \
+    __GNUC__ >= 4
+
+#include <altivec.h>
+#include "bufhelp.h"
+
+
+typedef vector unsigned char vector16x_u8;
+typedef vector unsigned int vector4x_u32;
+typedef vector unsigned long long vector2x_u64;
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR          NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE   ASM_FUNC_ATTR ALWAYS_INLINE
+#define ASM_FUNC_ATTR_NOINLINE ASM_FUNC_ATTR NO_INLINE
+
+
+static const u32 K[64] =
+  {
+#define TBL(v) v
+    TBL(0x428a2f98), TBL(0x71374491), TBL(0xb5c0fbcf), TBL(0xe9b5dba5),
+    TBL(0x3956c25b), TBL(0x59f111f1), TBL(0x923f82a4), TBL(0xab1c5ed5),
+    TBL(0xd807aa98), TBL(0x12835b01), TBL(0x243185be), TBL(0x550c7dc3),
+    TBL(0x72be5d74), TBL(0x80deb1fe), TBL(0x9bdc06a7), TBL(0xc19bf174),
+    TBL(0xe49b69c1), TBL(0xefbe4786), TBL(0x0fc19dc6), TBL(0x240ca1cc),
+    TBL(0x2de92c6f), TBL(0x4a7484aa), TBL(0x5cb0a9dc), TBL(0x76f988da),
+    TBL(0x983e5152), TBL(0xa831c66d), TBL(0xb00327c8), TBL(0xbf597fc7),
+    TBL(0xc6e00bf3), TBL(0xd5a79147), TBL(0x06ca6351), TBL(0x14292967),
+    TBL(0x27b70a85), TBL(0x2e1b2138), TBL(0x4d2c6dfc), TBL(0x53380d13),
+    TBL(0x650a7354), TBL(0x766a0abb), TBL(0x81c2c92e), TBL(0x92722c85),
+    TBL(0xa2bfe8a1), TBL(0xa81a664b), TBL(0xc24b8b70), TBL(0xc76c51a3),
+    TBL(0xd192e819), TBL(0xd6990624), TBL(0xf40e3585), TBL(0x106aa070),
+    TBL(0x19a4c116), TBL(0x1e376c08), TBL(0x2748774c), TBL(0x34b0bcb5),
+    TBL(0x391c0cb3), TBL(0x4ed8aa4a), TBL(0x5b9cca4f), TBL(0x682e6ff3),
+    TBL(0x748f82ee), TBL(0x78a5636f), TBL(0x84c87814), TBL(0x8cc70208),
+    TBL(0x90befffa), TBL(0xa4506ceb), TBL(0xbef9a3f7), TBL(0xc67178f2)
+#undef TBL
+  };
+
+
+static ASM_FUNC_ATTR_INLINE vector4x_u32
+vec_rol_elems(vector4x_u32 v, unsigned int idx)
+{
+#ifndef WORDS_BIGENDIAN
+  return vec_sld (v, v, (16 - (4 * idx)) & 15);
+#else
+  return vec_sld (v, v, (4 * idx) & 15);
+#endif
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector4x_u32
+vec_merge_idx0_elems(vector4x_u32 v0, vector4x_u32 v1,
+                    vector4x_u32 v2, vector4x_u32 v3)
+{
+  return (vector4x_u32)vec_mergeh ((vector2x_u64) vec_mergeh(v0, v1),
+                                  (vector2x_u64) vec_mergeh(v2, v3));
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector4x_u32
+vec_ror_u32(vector4x_u32 v, unsigned int shift)
+{
+  return (v >> (shift & 31)) ^ (v << ((32 - shift) & 31));
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector4x_u32
+vec_vshasigma_u32(vector4x_u32 v, unsigned int a, unsigned int b)
+{
+  asm ("vshasigmaw %0,%1,%2,%3"
+       : "=v" (v)
+       : "v" (v), "g" (a), "g" (b)
+       : "memory");
+  return v;
+}
+
+
+/* SHA2 round in vector registers */
+#define R(a,b,c,d,e,f,g,h,k,w) do                             \
+    {                                                         \
+      t1  = (h);                                              \
+      t1 += ((k) + (w));                                      \
+      t1 += Cho((e),(f),(g));                                 \
+      t1 += Sum1((e));                                        \
+      t2  = Sum0((a));                                        \
+      t2 += Maj((a),(b),(c));                                 \
+      d  += t1;                                               \
+      h   = t1 + t2;                                          \
+    } while (0)
+
+#define Cho(b, c, d)  (vec_sel(d, c, b))
+
+#define Maj(c, d, b)  (vec_sel(c, b, c ^ d))
+
+#define Sum0(x)       (vec_vshasigma_u32(x, 1, 0))
+
+#define Sum1(x)       (vec_vshasigma_u32(x, 1, 15))
+
+
+/* Message expansion on general purpose registers */
+#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3))
+#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10))
+
+#define I(i) ( w[i] = buf_get_be32(data + i * 4) )
+#define W(i) ({ w[i&0x0f] +=    w[(i-7) &0x0f];  \
+               w[i&0x0f] += S0(w[(i-15)&0x0f]); \
+               w[i&0x0f] += S1(w[(i-2) &0x0f]); \
+               w[i&0x0f]; })
+
+#define I2(i) ( w2[i] = buf_get_be32(64 + data + i * 4), I(i) )
+#define W2(i) ({ w2[i]  = w2[i-7];       \
+                w2[i] += S1(w2[i-2]);   \
+                w2[i] += S0(w2[i-15]);  \
+                w2[i] += w2[i-16];      \
+                W(i); })
+#define R2(i) ( w2[i] )
+
+
+unsigned int ASM_FUNC_ATTR
+_gcry_sha256_transform_ppc8(u32 state[8], const unsigned char *data,
+                           size_t nblks)
+{
+  /* GPRs used for message expansion as vector intrinsics based generates
+   * slower code. */
+  vector4x_u32 h0, h1, h2, h3, h4, h5, h6, h7;
+  vector4x_u32 h0_h3, h4_h7;
+  vector4x_u32 a, b, c, d, e, f, g, h, t1, t2;
+  u32 w[16];
+  u32 w2[64];
+
+  h0_h3 = vec_vsx_ld (4 * 0, state);
+  h4_h7 = vec_vsx_ld (4 * 4, state);
+
+  h0 = h0_h3;
+  h1 = vec_rol_elems (h0_h3, 1);
+  h2 = vec_rol_elems (h0_h3, 2);
+  h3 = vec_rol_elems (h0_h3, 3);
+  h4 = h4_h7;
+  h5 = vec_rol_elems (h4_h7, 1);
+  h6 = vec_rol_elems (h4_h7, 2);
+  h7 = vec_rol_elems (h4_h7, 3);
+
+  while (nblks >= 2)
+    {
+      a = h0;
+      b = h1;
+      c = h2;
+      d = h3;
+      e = h4;
+      f = h5;
+      g = h6;
+      h = h7;
+
+      R(a, b, c, d, e, f, g, h, K[0], I2(0));
+      R(h, a, b, c, d, e, f, g, K[1], I2(1));
+      R(g, h, a, b, c, d, e, f, K[2], I2(2));
+      R(f, g, h, a, b, c, d, e, K[3], I2(3));
+      R(e, f, g, h, a, b, c, d, K[4], I2(4));
+      R(d, e, f, g, h, a, b, c, K[5], I2(5));
+      R(c, d, e, f, g, h, a, b, K[6], I2(6));
+      R(b, c, d, e, f, g, h, a, K[7], I2(7));
+      R(a, b, c, d, e, f, g, h, K[8], I2(8));
+      R(h, a, b, c, d, e, f, g, K[9], I2(9));
+      R(g, h, a, b, c, d, e, f, K[10], I2(10));
+      R(f, g, h, a, b, c, d, e, K[11], I2(11));
+      R(e, f, g, h, a, b, c, d, K[12], I2(12));
+      R(d, e, f, g, h, a, b, c, K[13], I2(13));
+      R(c, d, e, f, g, h, a, b, K[14], I2(14));
+      R(b, c, d, e, f, g, h, a, K[15], I2(15));
+      data += 64 * 2;
+
+      R(a, b, c, d, e, f, g, h, K[16], W2(16));
+      R(h, a, b, c, d, e, f, g, K[17], W2(17));
+      R(g, h, a, b, c, d, e, f, K[18], W2(18));
+      R(f, g, h, a, b, c, d, e, K[19], W2(19));
+      R(e, f, g, h, a, b, c, d, K[20], W2(20));
+      R(d, e, f, g, h, a, b, c, K[21], W2(21));
+      R(c, d, e, f, g, h, a, b, K[22], W2(22));
+      R(b, c, d, e, f, g, h, a, K[23], W2(23));
+      R(a, b, c, d, e, f, g, h, K[24], W2(24));
+      R(h, a, b, c, d, e, f, g, K[25], W2(25));
+      R(g, h, a, b, c, d, e, f, K[26], W2(26));
+      R(f, g, h, a, b, c, d, e, K[27], W2(27));
+      R(e, f, g, h, a, b, c, d, K[28], W2(28));
+      R(d, e, f, g, h, a, b, c, K[29], W2(29));
+      R(c, d, e, f, g, h, a, b, K[30], W2(30));
+      R(b, c, d, e, f, g, h, a, K[31], W2(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W2(32));
+      R(h, a, b, c, d, e, f, g, K[33], W2(33));
+      R(g, h, a, b, c, d, e, f, K[34], W2(34));
+      R(f, g, h, a, b, c, d, e, K[35], W2(35));
+      R(e, f, g, h, a, b, c, d, K[36], W2(36));
+      R(d, e, f, g, h, a, b, c, K[37], W2(37));
+      R(c, d, e, f, g, h, a, b, K[38], W2(38));
+      R(b, c, d, e, f, g, h, a, K[39], W2(39));
+      R(a, b, c, d, e, f, g, h, K[40], W2(40));
+      R(h, a, b, c, d, e, f, g, K[41], W2(41));
+      R(g, h, a, b, c, d, e, f, K[42], W2(42));
+      R(f, g, h, a, b, c, d, e, K[43], W2(43));
+      R(e, f, g, h, a, b, c, d, K[44], W2(44));
+      R(d, e, f, g, h, a, b, c, K[45], W2(45));
+      R(c, d, e, f, g, h, a, b, K[46], W2(46));
+      R(b, c, d, e, f, g, h, a, K[47], W2(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W2(48));
+      R(h, a, b, c, d, e, f, g, K[49], W2(49));
+      R(g, h, a, b, c, d, e, f, K[50], W2(50));
+      R(f, g, h, a, b, c, d, e, K[51], W2(51));
+      R(e, f, g, h, a, b, c, d, K[52], W2(52));
+      R(d, e, f, g, h, a, b, c, K[53], W2(53));
+      R(c, d, e, f, g, h, a, b, K[54], W2(54));
+      R(b, c, d, e, f, g, h, a, K[55], W2(55));
+      R(a, b, c, d, e, f, g, h, K[56], W2(56));
+      R(h, a, b, c, d, e, f, g, K[57], W2(57));
+      R(g, h, a, b, c, d, e, f, K[58], W2(58));
+      R(f, g, h, a, b, c, d, e, K[59], W2(59));
+      R(e, f, g, h, a, b, c, d, K[60], W2(60));
+      R(d, e, f, g, h, a, b, c, K[61], W2(61));
+      R(c, d, e, f, g, h, a, b, K[62], W2(62));
+      R(b, c, d, e, f, g, h, a, K[63], W2(63));
+
+      h0 += a;
+      h1 += b;
+      h2 += c;
+      h3 += d;
+      h4 += e;
+      h5 += f;
+      h6 += g;
+      h7 += h;
+
+      a = h0;
+      b = h1;
+      c = h2;
+      d = h3;
+      e = h4;
+      f = h5;
+      g = h6;
+      h = h7;
+
+      R(a, b, c, d, e, f, g, h, K[0], R2(0));
+      R(h, a, b, c, d, e, f, g, K[1], R2(1));
+      R(g, h, a, b, c, d, e, f, K[2], R2(2));
+      R(f, g, h, a, b, c, d, e, K[3], R2(3));
+      R(e, f, g, h, a, b, c, d, K[4], R2(4));
+      R(d, e, f, g, h, a, b, c, K[5], R2(5));
+      R(c, d, e, f, g, h, a, b, K[6], R2(6));
+      R(b, c, d, e, f, g, h, a, K[7], R2(7));
+      R(a, b, c, d, e, f, g, h, K[8], R2(8));
+      R(h, a, b, c, d, e, f, g, K[9], R2(9));
+      R(g, h, a, b, c, d, e, f, K[10], R2(10));
+      R(f, g, h, a, b, c, d, e, K[11], R2(11));
+      R(e, f, g, h, a, b, c, d, K[12], R2(12));
+      R(d, e, f, g, h, a, b, c, K[13], R2(13));
+      R(c, d, e, f, g, h, a, b, K[14], R2(14));
+      R(b, c, d, e, f, g, h, a, K[15], R2(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], R2(16));
+      R(h, a, b, c, d, e, f, g, K[17], R2(17));
+      R(g, h, a, b, c, d, e, f, K[18], R2(18));
+      R(f, g, h, a, b, c, d, e, K[19], R2(19));
+      R(e, f, g, h, a, b, c, d, K[20], R2(20));
+      R(d, e, f, g, h, a, b, c, K[21], R2(21));
+      R(c, d, e, f, g, h, a, b, K[22], R2(22));
+      R(b, c, d, e, f, g, h, a, K[23], R2(23));
+      R(a, b, c, d, e, f, g, h, K[24], R2(24));
+      R(h, a, b, c, d, e, f, g, K[25], R2(25));
+      R(g, h, a, b, c, d, e, f, K[26], R2(26));
+      R(f, g, h, a, b, c, d, e, K[27], R2(27));
+      R(e, f, g, h, a, b, c, d, K[28], R2(28));
+      R(d, e, f, g, h, a, b, c, K[29], R2(29));
+      R(c, d, e, f, g, h, a, b, K[30], R2(30));
+      R(b, c, d, e, f, g, h, a, K[31], R2(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], R2(32));
+      R(h, a, b, c, d, e, f, g, K[33], R2(33));
+      R(g, h, a, b, c, d, e, f, K[34], R2(34));
+      R(f, g, h, a, b, c, d, e, K[35], R2(35));
+      R(e, f, g, h, a, b, c, d, K[36], R2(36));
+      R(d, e, f, g, h, a, b, c, K[37], R2(37));
+      R(c, d, e, f, g, h, a, b, K[38], R2(38));
+      R(b, c, d, e, f, g, h, a, K[39], R2(39));
+      R(a, b, c, d, e, f, g, h, K[40], R2(40));
+      R(h, a, b, c, d, e, f, g, K[41], R2(41));
+      R(g, h, a, b, c, d, e, f, K[42], R2(42));
+      R(f, g, h, a, b, c, d, e, K[43], R2(43));
+      R(e, f, g, h, a, b, c, d, K[44], R2(44));
+      R(d, e, f, g, h, a, b, c, K[45], R2(45));
+      R(c, d, e, f, g, h, a, b, K[46], R2(46));
+      R(b, c, d, e, f, g, h, a, K[47], R2(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], R2(48));
+      R(h, a, b, c, d, e, f, g, K[49], R2(49));
+      R(g, h, a, b, c, d, e, f, K[50], R2(50));
+      R(f, g, h, a, b, c, d, e, K[51], R2(51));
+      R(e, f, g, h, a, b, c, d, K[52], R2(52));
+      R(d, e, f, g, h, a, b, c, K[53], R2(53));
+      R(c, d, e, f, g, h, a, b, K[54], R2(54));
+      R(b, c, d, e, f, g, h, a, K[55], R2(55));
+      R(a, b, c, d, e, f, g, h, K[56], R2(56));
+      R(h, a, b, c, d, e, f, g, K[57], R2(57));
+      R(g, h, a, b, c, d, e, f, K[58], R2(58));
+      R(f, g, h, a, b, c, d, e, K[59], R2(59));
+      R(e, f, g, h, a, b, c, d, K[60], R2(60));
+      R(d, e, f, g, h, a, b, c, K[61], R2(61));
+      R(c, d, e, f, g, h, a, b, K[62], R2(62));
+      R(b, c, d, e, f, g, h, a, K[63], R2(63));
+
+      h0 += a;
+      h1 += b;
+      h2 += c;
+      h3 += d;
+      h4 += e;
+      h5 += f;
+      h6 += g;
+      h7 += h;
+
+      nblks -= 2;
+    }
+
+  while (nblks)
+    {
+      a = h0;
+      b = h1;
+      c = h2;
+      d = h3;
+      e = h4;
+      f = h5;
+      g = h6;
+      h = h7;
+
+      R(a, b, c, d, e, f, g, h, K[0], I(0));
+      R(h, a, b, c, d, e, f, g, K[1], I(1));
+      R(g, h, a, b, c, d, e, f, K[2], I(2));
+      R(f, g, h, a, b, c, d, e, K[3], I(3));
+      R(e, f, g, h, a, b, c, d, K[4], I(4));
+      R(d, e, f, g, h, a, b, c, K[5], I(5));
+      R(c, d, e, f, g, h, a, b, K[6], I(6));
+      R(b, c, d, e, f, g, h, a, K[7], I(7));
+      R(a, b, c, d, e, f, g, h, K[8], I(8));
+      R(h, a, b, c, d, e, f, g, K[9], I(9));
+      R(g, h, a, b, c, d, e, f, K[10], I(10));
+      R(f, g, h, a, b, c, d, e, K[11], I(11));
+      R(e, f, g, h, a, b, c, d, K[12], I(12));
+      R(d, e, f, g, h, a, b, c, K[13], I(13));
+      R(c, d, e, f, g, h, a, b, K[14], I(14));
+      R(b, c, d, e, f, g, h, a, K[15], I(15));
+      data += 64;
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W(48));
+      R(h, a, b, c, d, e, f, g, K[49], W(49));
+      R(g, h, a, b, c, d, e, f, K[50], W(50));
+      R(f, g, h, a, b, c, d, e, K[51], W(51));
+      R(e, f, g, h, a, b, c, d, K[52], W(52));
+      R(d, e, f, g, h, a, b, c, K[53], W(53));
+      R(c, d, e, f, g, h, a, b, K[54], W(54));
+      R(b, c, d, e, f, g, h, a, K[55], W(55));
+      R(a, b, c, d, e, f, g, h, K[56], W(56));
+      R(h, a, b, c, d, e, f, g, K[57], W(57));
+      R(g, h, a, b, c, d, e, f, K[58], W(58));
+      R(f, g, h, a, b, c, d, e, K[59], W(59));
+      R(e, f, g, h, a, b, c, d, K[60], W(60));
+      R(d, e, f, g, h, a, b, c, K[61], W(61));
+      R(c, d, e, f, g, h, a, b, K[62], W(62));
+      R(b, c, d, e, f, g, h, a, K[63], W(63));
+
+      h0 += a;
+      h1 += b;
+      h2 += c;
+      h3 += d;
+      h4 += e;
+      h5 += f;
+      h6 += g;
+      h7 += h;
+
+      nblks--;
+    }
+
+  h0_h3 = vec_merge_idx0_elems (h0, h1, h2, h3);
+  h4_h7 = vec_merge_idx0_elems (h4, h5, h6, h7);
+  vec_vsx_st (h0_h3, 4 * 0, state);
+  vec_vsx_st (h4_h7, 4 * 4, state);
+
+  return sizeof(w2) + sizeof(w);
+}
+#undef R
+#undef Cho
+#undef Maj
+#undef Sum0
+#undef Sum1
+#undef S0
+#undef S1
+#undef I
+#undef W
+#undef I2
+#undef W2
+#undef R2
+
+
+/* SHA2 round in general purpose registers */
+#define R(a,b,c,d,e,f,g,h,k,w) do                                 \
+          {                                                       \
+            t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + ((k) + (w));\
+            t2 = Sum0((a)) + Maj((a),(b),(c));                    \
+            d += t1;                                              \
+            h  = t1 + t2;                                         \
+          } while (0)
+
+#define Cho(x, y, z)  ((x & y) + (~x & z))
+
+#define Maj(z, x, y)  ((x & y) + (z & (x ^ y)))
+
+#define Sum0(x)       (ror (x, 2) ^ ror (x ^ ror (x, 22-13), 13))
+
+#define Sum1(x)       (ror (x, 6) ^ ror (x, 11) ^ ror (x, 25))
+
+
+/* Message expansion on general purpose registers */
+#define S0(x) (ror ((x), 7) ^ ror ((x), 18) ^ ((x) >> 3))
+#define S1(x) (ror ((x), 17) ^ ror ((x), 19) ^ ((x) >> 10))
+
+#define I(i) ( w[i] = buf_get_be32(data + i * 4) )
+#define WN(i) ({ w[i&0x0f] +=    w[(i-7) &0x0f];  \
+                w[i&0x0f] += S0(w[(i-15)&0x0f]); \
+                w[i&0x0f] += S1(w[(i-2) &0x0f]); \
+                w[i&0x0f]; })
+#define W(i) ({ u32 r = w[i&0x0f]; WN(i); r; })
+#define L(i) w[i&0x0f]
+
+
+unsigned int ASM_FUNC_ATTR
+_gcry_sha256_transform_ppc9(u32 state[8], const unsigned char *data,
+                           size_t nblks)
+{
+  /* GPRs used for round function and message expansion as vector intrinsics
+   * based generates slower code for POWER9. */
+  u32 a, b, c, d, e, f, g, h, t1, t2;
+  u32 w[16];
+
+  a = state[0];
+  b = state[1];
+  c = state[2];
+  d = state[3];
+  e = state[4];
+  f = state[5];
+  g = state[6];
+  h = state[7];
+
+  while (nblks >= 2)
+    {
+      I(0); I(1); I(2); I(3);
+      I(4); I(5); I(6); I(7);
+      I(8); I(9); I(10); I(11);
+      I(12); I(13); I(14); I(15);
+      data += 64;
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], L(48));
+      R(h, a, b, c, d, e, f, g, K[49], L(49));
+      R(g, h, a, b, c, d, e, f, K[50], L(50));
+      R(f, g, h, a, b, c, d, e, K[51], L(51));
+      I(0); I(1); I(2); I(3);
+      R(e, f, g, h, a, b, c, d, K[52], L(52));
+      R(d, e, f, g, h, a, b, c, K[53], L(53));
+      R(c, d, e, f, g, h, a, b, K[54], L(54));
+      R(b, c, d, e, f, g, h, a, K[55], L(55));
+      I(4); I(5); I(6); I(7);
+      R(a, b, c, d, e, f, g, h, K[56], L(56));
+      R(h, a, b, c, d, e, f, g, K[57], L(57));
+      R(g, h, a, b, c, d, e, f, K[58], L(58));
+      R(f, g, h, a, b, c, d, e, K[59], L(59));
+      I(8); I(9); I(10); I(11);
+      R(e, f, g, h, a, b, c, d, K[60], L(60));
+      R(d, e, f, g, h, a, b, c, K[61], L(61));
+      R(c, d, e, f, g, h, a, b, K[62], L(62));
+      R(b, c, d, e, f, g, h, a, K[63], L(63));
+      I(12); I(13); I(14); I(15);
+      data += 64;
+
+      a += state[0];
+      b += state[1];
+      c += state[2];
+      d += state[3];
+      e += state[4];
+      f += state[5];
+      g += state[6];
+      h += state[7];
+      state[0] = a;
+      state[1] = b;
+      state[2] = c;
+      state[3] = d;
+      state[4] = e;
+      state[5] = f;
+      state[6] = g;
+      state[7] = h;
+
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], L(48));
+      R(h, a, b, c, d, e, f, g, K[49], L(49));
+      R(g, h, a, b, c, d, e, f, K[50], L(50));
+      R(f, g, h, a, b, c, d, e, K[51], L(51));
+      R(e, f, g, h, a, b, c, d, K[52], L(52));
+      R(d, e, f, g, h, a, b, c, K[53], L(53));
+      R(c, d, e, f, g, h, a, b, K[54], L(54));
+      R(b, c, d, e, f, g, h, a, K[55], L(55));
+      R(a, b, c, d, e, f, g, h, K[56], L(56));
+      R(h, a, b, c, d, e, f, g, K[57], L(57));
+      R(g, h, a, b, c, d, e, f, K[58], L(58));
+      R(f, g, h, a, b, c, d, e, K[59], L(59));
+      R(e, f, g, h, a, b, c, d, K[60], L(60));
+      R(d, e, f, g, h, a, b, c, K[61], L(61));
+      R(c, d, e, f, g, h, a, b, K[62], L(62));
+      R(b, c, d, e, f, g, h, a, K[63], L(63));
+
+      a += state[0];
+      b += state[1];
+      c += state[2];
+      d += state[3];
+      e += state[4];
+      f += state[5];
+      g += state[6];
+      h += state[7];
+      state[0] = a;
+      state[1] = b;
+      state[2] = c;
+      state[3] = d;
+      state[4] = e;
+      state[5] = f;
+      state[6] = g;
+      state[7] = h;
+
+      nblks -= 2;
+    }
+
+  while (nblks)
+    {
+      I(0); I(1); I(2); I(3);
+      I(4); I(5); I(6); I(7);
+      I(8); I(9); I(10); I(11);
+      I(12); I(13); I(14); I(15);
+      data += 64;
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], L(48));
+      R(h, a, b, c, d, e, f, g, K[49], L(49));
+      R(g, h, a, b, c, d, e, f, K[50], L(50));
+      R(f, g, h, a, b, c, d, e, K[51], L(51));
+      R(e, f, g, h, a, b, c, d, K[52], L(52));
+      R(d, e, f, g, h, a, b, c, K[53], L(53));
+      R(c, d, e, f, g, h, a, b, K[54], L(54));
+      R(b, c, d, e, f, g, h, a, K[55], L(55));
+      R(a, b, c, d, e, f, g, h, K[56], L(56));
+      R(h, a, b, c, d, e, f, g, K[57], L(57));
+      R(g, h, a, b, c, d, e, f, K[58], L(58));
+      R(f, g, h, a, b, c, d, e, K[59], L(59));
+      R(e, f, g, h, a, b, c, d, K[60], L(60));
+      R(d, e, f, g, h, a, b, c, K[61], L(61));
+      R(c, d, e, f, g, h, a, b, K[62], L(62));
+      R(b, c, d, e, f, g, h, a, K[63], L(63));
+
+      a += state[0];
+      b += state[1];
+      c += state[2];
+      d += state[3];
+      e += state[4];
+      f += state[5];
+      g += state[6];
+      h += state[7];
+      state[0] = a;
+      state[1] = b;
+      state[2] = c;
+      state[3] = d;
+      state[4] = e;
+      state[5] = f;
+      state[6] = g;
+      state[7] = h;
+
+      nblks--;
+    }
+
+  return sizeof(w);
+}
+
+#endif /* ENABLE_PPC_CRYPTO_SUPPORT */
index a9213e4..401ff6f 100644 (file)
     defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
     defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(USE_SHA256)
 
-#ifdef __PIC__
-#  define ADD_RIP +rip
-#else
-#  define ADD_RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .intel_syntax noprefix
 
 
 /* addm [mem], reg
  * Add reg to mem using reg-mem add and store */
-.macro addm p1 p2
-       add     \p2, \p1
-       mov     \p1, \p2
-.endm
+#define addm(p1, p2) \
+       add     p2, p1; \
+       mov     p1, p2;
 
 /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/
 
 /* COPY_XMM_AND_BSWAP xmm, [mem], byte_flip_mask
  * Load xmm with mem and byte swap each dword */
-.macro COPY_XMM_AND_BSWAP p1 p2 p3
-       MOVDQ \p1, \p2
-       pshufb \p1, \p3
-.endm
+#define COPY_XMM_AND_BSWAP(p1, p2, p3) \
+       MOVDQ p1, p2; \
+       pshufb p1, p3;
 
 /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/
 
-X0 = xmm4
-X1 = xmm5
-X2 = xmm6
-X3 = xmm7
+#define X0 xmm4
+#define X1 xmm5
+#define X2 xmm6
+#define X3 xmm7
 
-XTMP0 = xmm0
-XTMP1 = xmm1
-XTMP2 = xmm2
-XTMP3 = xmm3
-XTMP4 = xmm8
-XFER  = xmm9
+#define XTMP0 xmm0
+#define XTMP1 xmm1
+#define XTMP2 xmm2
+#define XTMP3 xmm3
+#define XTMP4 xmm8
+#define XFER xmm9
 
-SHUF_00BA = xmm10 /* shuffle xBxA -> 00BA */
-SHUF_DC00 = xmm11 /* shuffle xDxC -> DC00 */
-BYTE_FLIP_MASK = xmm12
+#define SHUF_00BA xmm10 /* shuffle xBxA -> 00BA */
+#define SHUF_DC00 xmm11 /* shuffle xDxC -> DC00 */
+#define BYTE_FLIP_MASK xmm12
 
-NUM_BLKS = rdx /* 3rd arg */
-CTX = rsi      /* 2nd arg */
-INP = rdi      /* 1st arg */
+#define NUM_BLKS rdx   /* 3rd arg */
+#define CTX rsi        /* 2nd arg */
+#define INP rdi        /* 1st arg */
 
-SRND = rdi     /* clobbers INP */
-c = ecx
-d = r8d
-e = edx
+#define SRND rdi       /* clobbers INP */
+#define c ecx
+#define d r8d
+#define e edx
 
-TBL = rbp
-a = eax
-b = ebx
+#define TBL rbp
+#define a eax
+#define b ebx
 
-f = r9d
-g = r10d
-h = r11d
+#define f r9d
+#define g r10d
+#define h r11d
 
-y0 = r13d
-y1 = r14d
-y2 = r15d
+#define y0 r13d
+#define y1 r14d
+#define y2 r15d
 
 
 
@@ -148,230 +136,207 @@ y2 = r15d
 #define _XMM_SAVE      (_XFER     + _XFER_SIZE + _ALIGN_SIZE)
 #define STACK_SIZE     (_XMM_SAVE + _XMM_SAVE_SIZE)
 
-/* rotate_Xs
- * Rotate values of symbols X0...X3 */
-.macro rotate_Xs
-X_ = X0
-X0 = X1
-X1 = X2
-X2 = X3
-X3 = X_
-.endm
-
-/* ROTATE_ARGS
- * Rotate values of symbols a...h */
-.macro ROTATE_ARGS
-TMP_ = h
-h = g
-g = f
-f = e
-e = d
-d = c
-c = b
-b = a
-a = TMP_
-.endm
-
-.macro FOUR_ROUNDS_AND_SCHED
-               /* compute s0 four at a time and s1 two at a time
-                * compute W[-16] + W[-7] 4 at a time */
-               movdqa  XTMP0, X3
-       mov     y0, e           /* y0 = e */
-       ror     y0, (25-11)     /* y0 = e >> (25-11) */
-       mov     y1, a           /* y1 = a */
-               palignr XTMP0, X2, 4    /* XTMP0 = W[-7] */
-       ror     y1, (22-13)     /* y1 = a >> (22-13) */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       mov     y2, f           /* y2 = f */
-       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-               movdqa  XTMP1, X1
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       xor     y2, g           /* y2 = f^g */
-               paddd   XTMP0, X0       /* XTMP0 = W[-7] + W[-16] */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       and     y2, e           /* y2 = (f^g)&e */
-       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-               /* compute s0 */
-               palignr XTMP1, X0, 4    /* XTMP1 = W[-15] */
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-               movdqa  XTMP2, XTMP1    /* XTMP2 = W[-15] */
-       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-       add     y2, y0          /* y2 = S1 + CH */
-       add     y2, [rsp + _XFER + 0*4] /* y2 = k + w + S1 + CH */
-               movdqa  XTMP3, XTMP1    /* XTMP3 = W[-15] */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-               pslld   XTMP1, (32-7)
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-               psrld   XTMP2, 7
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-               por     XTMP1, XTMP2    /* XTMP1 = W[-15] ror 7 */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+
+#define FOUR_ROUNDS_AND_SCHED_0(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+               /* compute s0 four at a time and s1 two at a time */; \
+               /* compute W[-16] + W[-7] 4 at a time */; \
+               movdqa  XTMP0, X3; \
+       mov     y0, e           /* y0 = e */; \
+       ror     y0, (25-11)     /* y0 = e >> (25-11) */; \
+       mov     y1, a           /* y1 = a */; \
+               palignr XTMP0, X2, 4    /* XTMP0 = W[-7] */; \
+       ror     y1, (22-13)     /* y1 = a >> (22-13) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       mov     y2, f           /* y2 = f */; \
+       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+               movdqa  XTMP1, X1; \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       xor     y2, g           /* y2 = f^g */; \
+               paddd   XTMP0, X0       /* XTMP0 = W[-7] + W[-16] */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+               /* compute s0 */; \
+               palignr XTMP1, X0, 4    /* XTMP1 = W[-15] */; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+               movdqa  XTMP2, XTMP1    /* XTMP2 = W[-15] */; \
+       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       add     y2, [rsp + _XFER + 0*4] /* y2 = k + w + S1 + CH */; \
+               movdqa  XTMP3, XTMP1    /* XTMP3 = W[-15] */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+               pslld   XTMP1, (32-7); \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+               psrld   XTMP2, 7; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+               por     XTMP1, XTMP2    /* XTMP1 = W[-15] ror 7 */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
 
-ROTATE_ARGS
-               movdqa  XTMP2, XTMP3    /* XTMP2 = W[-15] */
-       mov     y0, e           /* y0 = e */
-       mov     y1, a           /* y1 = a */
-               movdqa  XTMP4, XTMP3    /* XTMP4 = W[-15] */
-       ror     y0, (25-11)     /* y0 = e >> (25-11) */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       mov     y2, f           /* y2 = f */
-       ror     y1, (22-13)     /* y1 = a >> (22-13) */
-               pslld   XTMP3, (32-18)
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-       xor     y2, g           /* y2 = f^g */
-               psrld   XTMP2, 18
-       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       and     y2, e           /* y2 = (f^g)&e */
-       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-               pxor    XTMP1, XTMP3
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-               psrld   XTMP4, 3        /* XTMP4 = W[-15] >> 3 */
-       add     y2, y0          /* y2 = S1 + CH */
-       add     y2, [rsp + _XFER + 1*4] /* y2 = k + w + S1 + CH */
-       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-               pxor    XTMP1, XTMP2    /* XTMP1 = W[-15] ror 7 ^ W[-15] ror 18 */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-               pxor    XTMP1, XTMP4    /* XTMP1 = s0 */
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-               /* compute low s1 */
-               pshufd  XTMP2, X3, 0b11111010   /* XTMP2 = W[-2] {BBAA} */
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-               paddd   XTMP0, XTMP1    /* XTMP0 = W[-16] + W[-7] + s0 */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+#define FOUR_ROUNDS_AND_SCHED_1(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+               movdqa  XTMP2, XTMP3    /* XTMP2 = W[-15] */; \
+       mov     y0, e           /* y0 = e */; \
+       mov     y1, a           /* y1 = a */; \
+               movdqa  XTMP4, XTMP3    /* XTMP4 = W[-15] */; \
+       ror     y0, (25-11)     /* y0 = e >> (25-11) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       mov     y2, f           /* y2 = f */; \
+       ror     y1, (22-13)     /* y1 = a >> (22-13) */; \
+               pslld   XTMP3, (32-18); \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+       xor     y2, g           /* y2 = f^g */; \
+               psrld   XTMP2, 18; \
+       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+               pxor    XTMP1, XTMP3; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+               psrld   XTMP4, 3        /* XTMP4 = W[-15] >> 3 */; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       add     y2, [rsp + _XFER + 1*4] /* y2 = k + w + S1 + CH */; \
+       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+               pxor    XTMP1, XTMP2    /* XTMP1 = W[-15] ror 7 ^ W[-15] ror 18 */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+               pxor    XTMP1, XTMP4    /* XTMP1 = s0 */; \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+               /* compute low s1 */; \
+               pshufd  XTMP2, X3, 0b11111010   /* XTMP2 = W[-2] {BBAA} */; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+               paddd   XTMP0, XTMP1    /* XTMP0 = W[-16] + W[-7] + s0 */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
 
-ROTATE_ARGS
-               movdqa  XTMP3, XTMP2    /* XTMP3 = W[-2] {BBAA} */
-       mov     y0, e           /* y0 = e */
-       mov     y1, a           /* y1 = a */
-       ror     y0, (25-11)     /* y0 = e >> (25-11) */
-               movdqa  XTMP4, XTMP2    /* XTMP4 = W[-2] {BBAA} */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       ror     y1, (22-13)     /* y1 = a >> (22-13) */
-       mov     y2, f           /* y2 = f */
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-               psrlq   XTMP2, 17       /* XTMP2 = W[-2] ror 17 {xBxA} */
-       xor     y2, g           /* y2 = f^g */
-               psrlq   XTMP3, 19       /* XTMP3 = W[-2] ror 19 {xBxA} */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       and     y2, e           /* y2 = (f^g)&e */
-               psrld   XTMP4, 10       /* XTMP4 = W[-2] >> 10 {BBAA} */
-       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-               pxor    XTMP2, XTMP3
-       add     y2, y0          /* y2 = S1 + CH */
-       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-       add     y2, [rsp + _XFER + 2*4] /* y2 = k + w + S1 + CH */
-               pxor    XTMP4, XTMP2    /* XTMP4 = s1 {xBxA} */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-               pshufb  XTMP4, SHUF_00BA        /* XTMP4 = s1 {00BA} */
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-               paddd   XTMP0, XTMP4    /* XTMP0 = {..., ..., W[1], W[0]} */
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-               /* compute high s1 */
-               pshufd  XTMP2, XTMP0, 0b01010000 /* XTMP2 = W[-2] {DDCC} */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+#define FOUR_ROUNDS_AND_SCHED_2(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+               movdqa  XTMP3, XTMP2    /* XTMP3 = W[-2] {BBAA} */; \
+       mov     y0, e           /* y0 = e */; \
+       mov     y1, a           /* y1 = a */; \
+       ror     y0, (25-11)     /* y0 = e >> (25-11) */; \
+               movdqa  XTMP4, XTMP2    /* XTMP4 = W[-2] {BBAA} */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       ror     y1, (22-13)     /* y1 = a >> (22-13) */; \
+       mov     y2, f           /* y2 = f */; \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+               psrlq   XTMP2, 17       /* XTMP2 = W[-2] ror 17 {xBxA} */; \
+       xor     y2, g           /* y2 = f^g */; \
+               psrlq   XTMP3, 19       /* XTMP3 = W[-2] ror 19 {xBxA} */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+               psrld   XTMP4, 10       /* XTMP4 = W[-2] >> 10 {BBAA} */; \
+       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+               pxor    XTMP2, XTMP3; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+       add     y2, [rsp + _XFER + 2*4] /* y2 = k + w + S1 + CH */; \
+               pxor    XTMP4, XTMP2    /* XTMP4 = s1 {xBxA} */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+               pshufb  XTMP4, SHUF_00BA        /* XTMP4 = s1 {00BA} */; \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+               paddd   XTMP0, XTMP4    /* XTMP0 = {..., ..., W[1], W[0]} */; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+               /* compute high s1 */; \
+               pshufd  XTMP2, XTMP0, 0b01010000 /* XTMP2 = W[-2] {DDCC} */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
 
-ROTATE_ARGS
-               movdqa  XTMP3, XTMP2    /* XTMP3 = W[-2] {DDCC} */
-       mov     y0, e           /* y0 = e */
-       ror     y0, (25-11)     /* y0 = e >> (25-11) */
-       mov     y1, a           /* y1 = a */
-               movdqa  X0,    XTMP2    /* X0    = W[-2] {DDCC} */
-       ror     y1, (22-13)     /* y1 = a >> (22-13) */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       mov     y2, f           /* y2 = f */
-       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-               psrlq   XTMP2, 17       /* XTMP2 = W[-2] ror 17 {xDxC} */
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       xor     y2, g           /* y2 = f^g */
-               psrlq   XTMP3, 19       /* XTMP3 = W[-2] ror 19 {xDxC} */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       and     y2, e           /* y2 = (f^g)&e */
-       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-               psrld   X0,    10       /* X0 = W[-2] >> 10 {DDCC} */
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-               pxor    XTMP2, XTMP3
-       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-       add     y2, y0          /* y2 = S1 + CH */
-       add     y2, [rsp + _XFER + 3*4] /* y2 = k + w + S1 + CH */
-               pxor    X0, XTMP2       /* X0 = s1 {xDxC} */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-               pshufb  X0, SHUF_DC00   /* X0 = s1 {DC00} */
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-               paddd   X0, XTMP0       /* X0 = {W[3], W[2], W[1], W[0]} */
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+#define FOUR_ROUNDS_AND_SCHED_3(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+               movdqa  XTMP3, XTMP2    /* XTMP3 = W[-2] {DDCC} */; \
+       mov     y0, e           /* y0 = e */; \
+       ror     y0, (25-11)     /* y0 = e >> (25-11) */; \
+       mov     y1, a           /* y1 = a */; \
+               movdqa  X0,    XTMP2    /* X0    = W[-2] {DDCC} */; \
+       ror     y1, (22-13)     /* y1 = a >> (22-13) */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       mov     y2, f           /* y2 = f */; \
+       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+               psrlq   XTMP2, 17       /* XTMP2 = W[-2] ror 17 {xDxC} */; \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       xor     y2, g           /* y2 = f^g */; \
+               psrlq   XTMP3, 19       /* XTMP3 = W[-2] ror 19 {xDxC} */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+               psrld   X0,    10       /* X0 = W[-2] >> 10 {DDCC} */; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+               pxor    XTMP2, XTMP3; \
+       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       add     y2, [rsp + _XFER + 3*4] /* y2 = k + w + S1 + CH */; \
+               pxor    X0, XTMP2       /* X0 = s1 {xDxC} */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+               pshufb  X0, SHUF_DC00   /* X0 = s1 {DC00} */; \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+               paddd   X0, XTMP0       /* X0 = {W[3], W[2], W[1], W[0]} */; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
 
-ROTATE_ARGS
-rotate_Xs
-.endm
+#define FOUR_ROUNDS_AND_SCHED(X0, X1, X2, X3, a, b, c, d, e, f, g, h) \
+       FOUR_ROUNDS_AND_SCHED_0(X0, X1, X2, X3, a, b, c, d, e, f, g, h); \
+       FOUR_ROUNDS_AND_SCHED_1(X0, X1, X2, X3, h, a, b, c, d, e, f, g); \
+       FOUR_ROUNDS_AND_SCHED_2(X0, X1, X2, X3, g, h, a, b, c, d, e, f); \
+       FOUR_ROUNDS_AND_SCHED_3(X0, X1, X2, X3, f, g, h, a, b, c, d, e);
 
 /* input is [rsp + _XFER + %1 * 4] */
-.macro DO_ROUND i1
-       mov     y0, e           /* y0 = e */
-       ror     y0, (25-11)     /* y0 = e >> (25-11) */
-       mov     y1, a           /* y1 = a */
-       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */
-       ror     y1, (22-13)     /* y1 = a >> (22-13) */
-       mov     y2, f           /* y2 = f */
-       xor     y1, a           /* y1 = a ^ (a >> (22-13) */
-       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */
-       xor     y2, g           /* y2 = f^g */
-       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */
-       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */
-       and     y2, e           /* y2 = (f^g)&e */
-       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */
-       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */
-       add     y2, y0          /* y2 = S1 + CH */
-       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */
-       add     y2, [rsp + _XFER + \i1 * 4]     /* y2 = k + w + S1 + CH */
-       mov     y0, a           /* y0 = a */
-       add     h, y2           /* h = h + S1 + CH + k + w */
-       mov     y2, a           /* y2 = a */
-       or      y0, c           /* y0 = a|c */
-       add     d, h            /* d = d + h + S1 + CH + k + w */
-       and     y2, c           /* y2 = a&c */
-       and     y0, b           /* y0 = (a|c)&b */
-       add     h, y1           /* h = h + S1 + CH + k + w + S0 */
-       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */
+#define DO_ROUND(i1, a, b, c, d, e, f, g, h) \
+       mov     y0, e           /* y0 = e */; \
+       ror     y0, (25-11)     /* y0 = e >> (25-11) */; \
+       mov     y1, a           /* y1 = a */; \
+       xor     y0, e           /* y0 = e ^ (e >> (25-11)) */; \
+       ror     y1, (22-13)     /* y1 = a >> (22-13) */; \
+       mov     y2, f           /* y2 = f */; \
+       xor     y1, a           /* y1 = a ^ (a >> (22-13) */; \
+       ror     y0, (11-6)      /* y0 = (e >> (11-6)) ^ (e >> (25-6)) */; \
+       xor     y2, g           /* y2 = f^g */; \
+       xor     y0, e           /* y0 = e ^ (e >> (11-6)) ^ (e >> (25-6)) */; \
+       ror     y1, (13-2)      /* y1 = (a >> (13-2)) ^ (a >> (22-2)) */; \
+       and     y2, e           /* y2 = (f^g)&e */; \
+       xor     y1, a           /* y1 = a ^ (a >> (13-2)) ^ (a >> (22-2)) */; \
+       ror     y0, 6           /* y0 = S1 = (e>>6) & (e>>11) ^ (e>>25) */; \
+       xor     y2, g           /* y2 = CH = ((f^g)&e)^g */; \
+       add     y2, y0          /* y2 = S1 + CH */; \
+       ror     y1, 2           /* y1 = S0 = (a>>2) ^ (a>>13) ^ (a>>22) */; \
+       add     y2, [rsp + _XFER + i1 * 4]      /* y2 = k + w + S1 + CH */; \
+       mov     y0, a           /* y0 = a */; \
+       add     h, y2           /* h = h + S1 + CH + k + w */; \
+       mov     y2, a           /* y2 = a */; \
+       or      y0, c           /* y0 = a|c */; \
+       add     d, h            /* d = d + h + S1 + CH + k + w */; \
+       and     y2, c           /* y2 = a&c */; \
+       and     y0, b           /* y0 = (a|c)&b */; \
+       add     h, y1           /* h = h + S1 + CH + k + w + S0 */; \
+       or      y0, y2          /* y0 = MAJ = (a|c)&b)|(a&c) */; \
        lea     h, [h + y0]     /* h = h + S1 + CH + k + w + S0 + MAJ */
-       ROTATE_ARGS
-.endm
 
 /*
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -386,13 +351,20 @@ rotate_Xs
 ELF(.type  _gcry_sha256_transform_amd64_ssse3,@function;)
 .align 16
 _gcry_sha256_transform_amd64_ssse3:
+       CFI_STARTPROC()
        push    rbx
+       CFI_PUSH(rbx)
        push    rbp
+       CFI_PUSH(rbp)
        push    r13
+       CFI_PUSH(r13)
        push    r14
+       CFI_PUSH(r14)
        push    r15
+       CFI_PUSH(r15)
 
        sub     rsp, STACK_SIZE
+       CFI_ADJUST_CFA_OFFSET(STACK_SIZE);
 
        shl     NUM_BLKS, 6     /* convert to bytes */
        jz      .Ldone_hash
@@ -417,10 +389,10 @@ _gcry_sha256_transform_amd64_ssse3:
        lea     TBL, [.LK256 ADD_RIP]
 
        /* byte swap first 16 dwords */
-       COPY_XMM_AND_BSWAP      X0, [INP + 0*16], BYTE_FLIP_MASK
-       COPY_XMM_AND_BSWAP      X1, [INP + 1*16], BYTE_FLIP_MASK
-       COPY_XMM_AND_BSWAP      X2, [INP + 2*16], BYTE_FLIP_MASK
-       COPY_XMM_AND_BSWAP      X3, [INP + 3*16], BYTE_FLIP_MASK
+       COPY_XMM_AND_BSWAP(X0, [INP + 0*16], BYTE_FLIP_MASK)
+       COPY_XMM_AND_BSWAP(X1, [INP + 1*16], BYTE_FLIP_MASK)
+       COPY_XMM_AND_BSWAP(X2, [INP + 2*16], BYTE_FLIP_MASK)
+       COPY_XMM_AND_BSWAP(X3, [INP + 3*16], BYTE_FLIP_MASK)
 
        mov     [rsp + _INP], INP
 
@@ -431,23 +403,23 @@ _gcry_sha256_transform_amd64_ssse3:
        movdqa  XFER, [TBL + 0*16]
        paddd   XFER, X0
        movdqa  [rsp + _XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+       FOUR_ROUNDS_AND_SCHED(X0, X1, X2, X3, a, b, c, d, e, f, g, h)
 
        movdqa  XFER, [TBL + 1*16]
-       paddd   XFER, X0
+       paddd   XFER, X1
        movdqa  [rsp + _XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+       FOUR_ROUNDS_AND_SCHED(X1, X2, X3, X0, e, f, g, h, a, b, c, d)
 
        movdqa  XFER, [TBL + 2*16]
-       paddd   XFER, X0
+       paddd   XFER, X2
        movdqa  [rsp + _XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+       FOUR_ROUNDS_AND_SCHED(X2, X3, X0, X1, a, b, c, d, e, f, g, h)
 
        movdqa  XFER, [TBL + 3*16]
-       paddd   XFER, X0
+       paddd   XFER, X3
        movdqa  [rsp + _XFER], XFER
        add     TBL, 4*16
-       FOUR_ROUNDS_AND_SCHED
+       FOUR_ROUNDS_AND_SCHED(X3, X0, X1, X2, e, f, g, h, a, b, c, d)
 
        sub     SRND, 1
        jne     .Loop1
@@ -456,17 +428,17 @@ _gcry_sha256_transform_amd64_ssse3:
 .Loop2:
        paddd   X0, [TBL + 0*16]
        movdqa  [rsp + _XFER], X0
-       DO_ROUND        0
-       DO_ROUND        1
-       DO_ROUND        2
-       DO_ROUND        3
+       DO_ROUND(0, a, b, c, d, e, f, g, h)
+       DO_ROUND(1, h, a, b, c, d, e, f, g)
+       DO_ROUND(2, g, h, a, b, c, d, e, f)
+       DO_ROUND(3, f, g, h, a, b, c, d, e)
        paddd   X1, [TBL + 1*16]
        movdqa  [rsp + _XFER], X1
        add     TBL, 2*16
-       DO_ROUND        0
-       DO_ROUND        1
-       DO_ROUND        2
-       DO_ROUND        3
+       DO_ROUND(0, e, f, g, h, a, b, c, d)
+       DO_ROUND(1, d, e, f, g, h, a, b, c)
+       DO_ROUND(2, c, d, e, f, g, h, a, b)
+       DO_ROUND(3, b, c, d, e, f, g, h, a)
 
        movdqa  X0, X2
        movdqa  X1, X3
@@ -474,14 +446,14 @@ _gcry_sha256_transform_amd64_ssse3:
        sub     SRND, 1
        jne     .Loop2
 
-       addm    [4*0 + CTX],a
-       addm    [4*1 + CTX],b
-       addm    [4*2 + CTX],c
-       addm    [4*3 + CTX],d
-       addm    [4*4 + CTX],e
-       addm    [4*5 + CTX],f
-       addm    [4*6 + CTX],g
-       addm    [4*7 + CTX],h
+       addm([4*0 + CTX],a)
+       addm([4*1 + CTX],b)
+       addm([4*2 + CTX],c)
+       addm([4*3 + CTX],d)
+       addm([4*4 + CTX],e)
+       addm([4*5 + CTX],f)
+       addm([4*6 + CTX],g)
+       addm([4*7 + CTX],h)
 
        mov     INP, [rsp + _INP]
        add     INP, 64
@@ -503,17 +475,26 @@ _gcry_sha256_transform_amd64_ssse3:
        pxor    xmm12, xmm12
 
 .Ldone_hash:
+       pxor    XFER, XFER
+       movdqa  [rsp + _XFER], XFER
+       xor     eax, eax
+
        add     rsp, STACK_SIZE
+       CFI_ADJUST_CFA_OFFSET(-STACK_SIZE);
 
        pop     r15
+       CFI_POP(r15)
        pop     r14
+       CFI_POP(r14)
        pop     r13
+       CFI_POP(r13)
        pop     rbp
+       CFI_POP(rbp)
        pop     rbx
+       CFI_POP(rbx)
 
-       mov     eax, STACK_SIZE + 5*8
-
-       ret
+       ret_spec_stop
+       CFI_ENDPROC()
 
 
 .align 16
index d174321..24cab56 100644 (file)
 # define USE_AVX2 1
 #endif
 
+/* USE_SHAEXT indicates whether to compile with Intel SHA Extension code. */
+#undef USE_SHAEXT
+#if defined(HAVE_GCC_INLINE_ASM_SHAEXT) && \
+    defined(HAVE_GCC_INLINE_ASM_SSE41) && \
+    defined(ENABLE_SHAEXT_SUPPORT)
+# define USE_SHAEXT 1
+#endif
+
 /* USE_ARM_CE indicates whether to enable ARMv8 Crypto Extension assembly
  * code. */
 #undef USE_ARM_CE
 # endif
 #endif
 
+/* USE_PPC_CRYPTO indicates whether to enable PowerPC vector crypto
+ * accelerated code. */
+#undef USE_PPC_CRYPTO
+#ifdef ENABLE_PPC_CRYPTO_SUPPORT
+# if defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+     defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC)
+#  if __GNUC__ >= 4
+#   define USE_PPC_CRYPTO 1
+#  endif
+# endif
+#endif
+
+/* USE_S390X_CRYPTO indicates whether to enable zSeries code. */
+#undef USE_S390X_CRYPTO
+#if defined(HAVE_GCC_INLINE_ASM_S390X)
+# define USE_S390X_CRYPTO 1
+#endif /* USE_S390X_CRYPTO */
+
 
 typedef struct {
   gcry_md_block_ctx_t bctx;
-  u32  h0,h1,h2,h3,h4,h5,h6,h7;
+  u32  h[8];
+#ifdef USE_S390X_CRYPTO
+  u32  final_len_msb, final_len_lsb; /* needs to be right after h[7]. */
+  int  use_s390x_crypto;
+#endif
+} SHA256_CONTEXT;
+
+
+/* Assembly implementations use SystemV ABI, ABI conversion and additional
+ * stack to store XMM6-XMM15 needed on Win64. */
+#undef ASM_FUNC_ABI
+#undef ASM_EXTRA_STACK
+#if defined(USE_SSSE3) || defined(USE_AVX) || defined(USE_AVX2) || \
+    defined(USE_SHAEXT)
+# ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
+#  define ASM_FUNC_ABI __attribute__((sysv_abi))
+#  define ASM_EXTRA_STACK (10 * 16 + sizeof(void *) * 4)
+# else
+#  define ASM_FUNC_ABI
+#  define ASM_EXTRA_STACK 0
+# endif
+#endif
+
+
 #ifdef USE_SSSE3
-  unsigned int use_ssse3:1;
+unsigned int _gcry_sha256_transform_amd64_ssse3(const void *input_data,
+                                                u32 state[8],
+                                                size_t num_blks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha256_transform_amd64_ssse3(void *ctx, const unsigned char *data,
+                                size_t nblks)
+{
+  SHA256_CONTEXT *hd = ctx;
+  return _gcry_sha256_transform_amd64_ssse3 (data, hd->h, nblks)
+         + ASM_EXTRA_STACK;
+}
 #endif
+
 #ifdef USE_AVX
-  unsigned int use_avx:1;
+unsigned int _gcry_sha256_transform_amd64_avx(const void *input_data,
+                                              u32 state[8],
+                                              size_t num_blks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha256_transform_amd64_avx(void *ctx, const unsigned char *data,
+                              size_t nblks)
+{
+  SHA256_CONTEXT *hd = ctx;
+  return _gcry_sha256_transform_amd64_avx (data, hd->h, nblks)
+         + ASM_EXTRA_STACK;
+}
 #endif
+
 #ifdef USE_AVX2
-  unsigned int use_avx2:1;
+unsigned int _gcry_sha256_transform_amd64_avx2(const void *input_data,
+                                               u32 state[8],
+                                               size_t num_blks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha256_transform_amd64_avx2(void *ctx, const unsigned char *data,
+                               size_t nblks)
+{
+  SHA256_CONTEXT *hd = ctx;
+  return _gcry_sha256_transform_amd64_avx2 (data, hd->h, nblks)
+         + ASM_EXTRA_STACK;
+}
+#endif
+
+#ifdef USE_SHAEXT
+/* Does not need ASM_FUNC_ABI */
+unsigned int
+_gcry_sha256_transform_intel_shaext(u32 state[8],
+                                    const unsigned char *input_data,
+                                    size_t num_blks);
+
+static unsigned int
+do_sha256_transform_intel_shaext(void *ctx, const unsigned char *data,
+                                 size_t nblks)
+{
+  SHA256_CONTEXT *hd = ctx;
+  return _gcry_sha256_transform_intel_shaext (hd->h, data, nblks);
+}
 #endif
+
 #ifdef USE_ARM_CE
-  unsigned int use_arm_ce:1;
+unsigned int _gcry_sha256_transform_armv8_ce(u32 state[8],
+                                             const void *input_data,
+                                             size_t num_blks);
+
+static unsigned int
+do_sha256_transform_armv8_ce(void *ctx, const unsigned char *data,
+                             size_t nblks)
+{
+  SHA256_CONTEXT *hd = ctx;
+  return _gcry_sha256_transform_armv8_ce (hd->h, data, nblks);
+}
 #endif
-} SHA256_CONTEXT;
 
+#ifdef USE_PPC_CRYPTO
+unsigned int _gcry_sha256_transform_ppc8(u32 state[8],
+                                        const unsigned char *input_data,
+                                        size_t num_blks);
+
+unsigned int _gcry_sha256_transform_ppc9(u32 state[8],
+                                        const unsigned char *input_data,
+                                        size_t num_blks);
+
+static unsigned int
+do_sha256_transform_ppc8(void *ctx, const unsigned char *data, size_t nblks)
+{
+  SHA256_CONTEXT *hd = ctx;
+  return _gcry_sha256_transform_ppc8 (hd->h, data, nblks);
+}
 
 static unsigned int
-transform (void *c, const unsigned char *data, size_t nblks);
+do_sha256_transform_ppc9(void *ctx, const unsigned char *data, size_t nblks)
+{
+  SHA256_CONTEXT *hd = ctx;
+  return _gcry_sha256_transform_ppc9 (hd->h, data, nblks);
+}
+#endif
 
+#ifdef USE_S390X_CRYPTO
+#include "asm-inline-s390x.h"
 
-static void
-sha256_init (void *context, unsigned int flags)
+static unsigned int
+do_sha256_transform_s390x (void *ctx, const unsigned char *data, size_t nblks)
 {
-  SHA256_CONTEXT *hd = context;
-  unsigned int features = _gcry_get_hw_features ();
+  SHA256_CONTEXT *hd = ctx;
 
-  (void)flags;
+  kimd_execute (KMID_FUNCTION_SHA256, hd->h, data, nblks * 64);
+  return 0;
+}
 
-  hd->h0 = 0x6a09e667;
-  hd->h1 = 0xbb67ae85;
-  hd->h2 = 0x3c6ef372;
-  hd->h3 = 0xa54ff53a;
-  hd->h4 = 0x510e527f;
-  hd->h5 = 0x9b05688c;
-  hd->h6 = 0x1f83d9ab;
-  hd->h7 = 0x5be0cd19;
+static unsigned int
+do_sha256_final_s390x (void *ctx, const unsigned char *data, size_t datalen,
+                      u32 len_msb, u32 len_lsb)
+{
+  SHA256_CONTEXT *hd = ctx;
+
+  /* Make sure that 'final_len' is positioned at correct offset relative
+   * to 'h[0]'. This is because we are passing 'h[0]' pointer as start of
+   * parameter block to 'klmd' instruction. */
+
+  gcry_assert (offsetof (SHA256_CONTEXT, final_len_msb)
+              - offsetof (SHA256_CONTEXT, h[0]) == 8 * sizeof(u32));
+  gcry_assert (offsetof (SHA256_CONTEXT, final_len_lsb)
+              - offsetof (SHA256_CONTEXT, final_len_msb) == 1 * sizeof(u32));
+
+  hd->final_len_msb = len_msb;
+  hd->final_len_lsb = len_lsb;
+
+  klmd_execute (KMID_FUNCTION_SHA256, hd->h, data, datalen);
+  return 0;
+}
+#endif
+
+
+static unsigned int
+do_transform_generic (void *ctx, const unsigned char *data, size_t nblks);
+
+
+static void
+sha256_common_init (SHA256_CONTEXT *hd)
+{
+  unsigned int features = _gcry_get_hw_features ();
 
   hd->bctx.nblocks = 0;
   hd->bctx.nblocks_high = 0;
   hd->bctx.count = 0;
-  hd->bctx.blocksize = 64;
-  hd->bctx.bwrite = transform;
+  hd->bctx.blocksize_shift = _gcry_ctz(64);
 
+  /* Order of feature checks is important here; last match will be
+   * selected.  Keep slower implementations at the top and faster at
+   * the bottom.  */
+  hd->bctx.bwrite = do_transform_generic;
 #ifdef USE_SSSE3
-  hd->use_ssse3 = (features & HWF_INTEL_SSSE3) != 0;
+  if ((features & HWF_INTEL_SSSE3) != 0)
+    hd->bctx.bwrite = do_sha256_transform_amd64_ssse3;
 #endif
 #ifdef USE_AVX
   /* AVX implementation uses SHLD which is known to be slow on non-Intel CPUs.
    * Therefore use this implementation on Intel CPUs only. */
-  hd->use_avx = (features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD);
+  if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD))
+    hd->bctx.bwrite = do_sha256_transform_amd64_avx;
 #endif
 #ifdef USE_AVX2
-  hd->use_avx2 = (features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2);
+  if ((features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2))
+    hd->bctx.bwrite = do_sha256_transform_amd64_avx2;
+#endif
+#ifdef USE_SHAEXT
+  if ((features & HWF_INTEL_SHAEXT) && (features & HWF_INTEL_SSE4_1))
+    hd->bctx.bwrite = do_sha256_transform_intel_shaext;
 #endif
 #ifdef USE_ARM_CE
-  hd->use_arm_ce = (features & HWF_ARM_SHA2) != 0;
+  if ((features & HWF_ARM_SHA2) != 0)
+    hd->bctx.bwrite = do_sha256_transform_armv8_ce;
+#endif
+#ifdef USE_PPC_CRYPTO
+  if ((features & HWF_PPC_VCRYPTO) != 0)
+    hd->bctx.bwrite = do_sha256_transform_ppc8;
+  if ((features & HWF_PPC_VCRYPTO) != 0 && (features & HWF_PPC_ARCH_3_00) != 0)
+    hd->bctx.bwrite = do_sha256_transform_ppc9;
+#endif
+#ifdef USE_S390X_CRYPTO
+  hd->use_s390x_crypto = 0;
+  if ((features & HWF_S390X_MSA) != 0)
+    {
+      if ((kimd_query () & km_function_to_mask (KMID_FUNCTION_SHA256)) &&
+         (klmd_query () & km_function_to_mask (KMID_FUNCTION_SHA256)))
+       {
+         hd->bctx.bwrite = do_sha256_transform_s390x;
+         hd->use_s390x_crypto = 1;
+       }
+    }
 #endif
   (void)features;
 }
 
 
 static void
-sha224_init (void *context, unsigned int flags)
+sha256_init (void *context, unsigned int flags)
 {
   SHA256_CONTEXT *hd = context;
-  unsigned int features = _gcry_get_hw_features ();
 
   (void)flags;
 
-  hd->h0 = 0xc1059ed8;
-  hd->h1 = 0x367cd507;
-  hd->h2 = 0x3070dd17;
-  hd->h3 = 0xf70e5939;
-  hd->h4 = 0xffc00b31;
-  hd->h5 = 0x68581511;
-  hd->h6 = 0x64f98fa7;
-  hd->h7 = 0xbefa4fa4;
+  hd->h[0] = 0x6a09e667;
+  hd->h[1] = 0xbb67ae85;
+  hd->h[2] = 0x3c6ef372;
+  hd->h[3] = 0xa54ff53a;
+  hd->h[4] = 0x510e527f;
+  hd->h[5] = 0x9b05688c;
+  hd->h[6] = 0x1f83d9ab;
+  hd->h[7] = 0x5be0cd19;
 
-  hd->bctx.nblocks = 0;
-  hd->bctx.nblocks_high = 0;
-  hd->bctx.count = 0;
-  hd->bctx.blocksize = 64;
-  hd->bctx.bwrite = transform;
+  sha256_common_init (hd);
+}
 
-#ifdef USE_SSSE3
-  hd->use_ssse3 = (features & HWF_INTEL_SSSE3) != 0;
-#endif
-#ifdef USE_AVX
-  /* AVX implementation uses SHLD which is known to be slow on non-Intel CPUs.
-   * Therefore use this implementation on Intel CPUs only. */
-  hd->use_avx = (features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD);
-#endif
-#ifdef USE_AVX2
-  hd->use_avx2 = (features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2);
-#endif
-#ifdef USE_ARM_CE
-  hd->use_arm_ce = (features & HWF_ARM_SHA2) != 0;
-#endif
-  (void)features;
+
+static void
+sha224_init (void *context, unsigned int flags)
+{
+  SHA256_CONTEXT *hd = context;
+
+  (void)flags;
+
+  hd->h[0] = 0xc1059ed8;
+  hd->h[1] = 0x367cd507;
+  hd->h[2] = 0x3070dd17;
+  hd->h[3] = 0xf70e5939;
+  hd->h[4] = 0xffc00b31;
+  hd->h[5] = 0x68581511;
+  hd->h[6] = 0x64f98fa7;
+  hd->h[7] = 0xbefa4fa4;
+
+  sha256_common_init (hd);
 }
 
 
@@ -228,7 +413,7 @@ sha224_init (void *context, unsigned int flags)
                             +    w[(i-16)&0x0f] )
 
 static unsigned int
-transform_blk (void *ctx, const unsigned char *data)
+do_transform_generic (void *ctx, const unsigned char *data, size_t nblks)
 {
   SHA256_CONTEXT *hd = ctx;
   static const u32 K[64] = {
@@ -250,188 +435,109 @@ transform_blk (void *ctx, const unsigned char *data)
     0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
   };
 
-  u32 a,b,c,d,e,f,g,h,t1,t2;
-  u32 w[16];
-
-  a = hd->h0;
-  b = hd->h1;
-  c = hd->h2;
-  d = hd->h3;
-  e = hd->h4;
-  f = hd->h5;
-  g = hd->h6;
-  h = hd->h7;
-
-  R(a, b, c, d, e, f, g, h, K[0], I(0));
-  R(h, a, b, c, d, e, f, g, K[1], I(1));
-  R(g, h, a, b, c, d, e, f, K[2], I(2));
-  R(f, g, h, a, b, c, d, e, K[3], I(3));
-  R(e, f, g, h, a, b, c, d, K[4], I(4));
-  R(d, e, f, g, h, a, b, c, K[5], I(5));
-  R(c, d, e, f, g, h, a, b, K[6], I(6));
-  R(b, c, d, e, f, g, h, a, K[7], I(7));
-  R(a, b, c, d, e, f, g, h, K[8], I(8));
-  R(h, a, b, c, d, e, f, g, K[9], I(9));
-  R(g, h, a, b, c, d, e, f, K[10], I(10));
-  R(f, g, h, a, b, c, d, e, K[11], I(11));
-  R(e, f, g, h, a, b, c, d, K[12], I(12));
-  R(d, e, f, g, h, a, b, c, K[13], I(13));
-  R(c, d, e, f, g, h, a, b, K[14], I(14));
-  R(b, c, d, e, f, g, h, a, K[15], I(15));
-
-  R(a, b, c, d, e, f, g, h, K[16], W(16));
-  R(h, a, b, c, d, e, f, g, K[17], W(17));
-  R(g, h, a, b, c, d, e, f, K[18], W(18));
-  R(f, g, h, a, b, c, d, e, K[19], W(19));
-  R(e, f, g, h, a, b, c, d, K[20], W(20));
-  R(d, e, f, g, h, a, b, c, K[21], W(21));
-  R(c, d, e, f, g, h, a, b, K[22], W(22));
-  R(b, c, d, e, f, g, h, a, K[23], W(23));
-  R(a, b, c, d, e, f, g, h, K[24], W(24));
-  R(h, a, b, c, d, e, f, g, K[25], W(25));
-  R(g, h, a, b, c, d, e, f, K[26], W(26));
-  R(f, g, h, a, b, c, d, e, K[27], W(27));
-  R(e, f, g, h, a, b, c, d, K[28], W(28));
-  R(d, e, f, g, h, a, b, c, K[29], W(29));
-  R(c, d, e, f, g, h, a, b, K[30], W(30));
-  R(b, c, d, e, f, g, h, a, K[31], W(31));
-
-  R(a, b, c, d, e, f, g, h, K[32], W(32));
-  R(h, a, b, c, d, e, f, g, K[33], W(33));
-  R(g, h, a, b, c, d, e, f, K[34], W(34));
-  R(f, g, h, a, b, c, d, e, K[35], W(35));
-  R(e, f, g, h, a, b, c, d, K[36], W(36));
-  R(d, e, f, g, h, a, b, c, K[37], W(37));
-  R(c, d, e, f, g, h, a, b, K[38], W(38));
-  R(b, c, d, e, f, g, h, a, K[39], W(39));
-  R(a, b, c, d, e, f, g, h, K[40], W(40));
-  R(h, a, b, c, d, e, f, g, K[41], W(41));
-  R(g, h, a, b, c, d, e, f, K[42], W(42));
-  R(f, g, h, a, b, c, d, e, K[43], W(43));
-  R(e, f, g, h, a, b, c, d, K[44], W(44));
-  R(d, e, f, g, h, a, b, c, K[45], W(45));
-  R(c, d, e, f, g, h, a, b, K[46], W(46));
-  R(b, c, d, e, f, g, h, a, K[47], W(47));
-
-  R(a, b, c, d, e, f, g, h, K[48], W(48));
-  R(h, a, b, c, d, e, f, g, K[49], W(49));
-  R(g, h, a, b, c, d, e, f, K[50], W(50));
-  R(f, g, h, a, b, c, d, e, K[51], W(51));
-  R(e, f, g, h, a, b, c, d, K[52], W(52));
-  R(d, e, f, g, h, a, b, c, K[53], W(53));
-  R(c, d, e, f, g, h, a, b, K[54], W(54));
-  R(b, c, d, e, f, g, h, a, K[55], W(55));
-  R(a, b, c, d, e, f, g, h, K[56], W(56));
-  R(h, a, b, c, d, e, f, g, K[57], W(57));
-  R(g, h, a, b, c, d, e, f, K[58], W(58));
-  R(f, g, h, a, b, c, d, e, K[59], W(59));
-  R(e, f, g, h, a, b, c, d, K[60], W(60));
-  R(d, e, f, g, h, a, b, c, K[61], W(61));
-  R(c, d, e, f, g, h, a, b, K[62], W(62));
-  R(b, c, d, e, f, g, h, a, K[63], W(63));
-
-  hd->h0 += a;
-  hd->h1 += b;
-  hd->h2 += c;
-  hd->h3 += d;
-  hd->h4 += e;
-  hd->h5 += f;
-  hd->h6 += g;
-  hd->h7 += h;
-
-  return /*burn_stack*/ 26*4+32;
-}
-#undef S0
-#undef S1
-#undef R
-
-
-/* Assembly implementations use SystemV ABI, ABI conversion and additional
- * stack to store XMM6-XMM15 needed on Win64. */
-#undef ASM_FUNC_ABI
-#undef ASM_EXTRA_STACK
-#if defined(USE_SSSE3) || defined(USE_AVX) || defined(USE_AVX2)
-# ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-#  define ASM_FUNC_ABI __attribute__((sysv_abi))
-#  define ASM_EXTRA_STACK (10 * 16)
-# else
-#  define ASM_FUNC_ABI
-#  define ASM_EXTRA_STACK 0
-# endif
-#endif
-
-
-#ifdef USE_SSSE3
-unsigned int _gcry_sha256_transform_amd64_ssse3(const void *input_data,
-                                                u32 state[8],
-                                                size_t num_blks) ASM_FUNC_ABI;
-#endif
-
-#ifdef USE_AVX
-unsigned int _gcry_sha256_transform_amd64_avx(const void *input_data,
-                                              u32 state[8],
-                                              size_t num_blks) ASM_FUNC_ABI;
-#endif
-
-#ifdef USE_AVX2
-unsigned int _gcry_sha256_transform_amd64_avx2(const void *input_data,
-                                               u32 state[8],
-                                               size_t num_blks) ASM_FUNC_ABI;
-#endif
-
-#ifdef USE_ARM_CE
-unsigned int _gcry_sha256_transform_armv8_ce(u32 state[8],
-                                             const void *input_data,
-                                             size_t num_blks);
-#endif
-
-static unsigned int
-transform (void *ctx, const unsigned char *data, size_t nblks)
-{
-  SHA256_CONTEXT *hd = ctx;
-  unsigned int burn;
-
-#ifdef USE_AVX2
-  if (hd->use_avx2)
-    return _gcry_sha256_transform_amd64_avx2 (data, &hd->h0, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
-#endif
-
-#ifdef USE_AVX
-  if (hd->use_avx)
-    return _gcry_sha256_transform_amd64_avx (data, &hd->h0, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
-#endif
-
-#ifdef USE_SSSE3
-  if (hd->use_ssse3)
-    return _gcry_sha256_transform_amd64_ssse3 (data, &hd->h0, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
-#endif
-
-#ifdef USE_ARM_CE
-  if (hd->use_arm_ce)
-    return _gcry_sha256_transform_armv8_ce (&hd->h0, data, nblks);
-#endif
-
   do
     {
-      burn = transform_blk (hd, data);
+
+      u32 a,b,c,d,e,f,g,h,t1,t2;
+      u32 w[16];
+
+      a = hd->h[0];
+      b = hd->h[1];
+      c = hd->h[2];
+      d = hd->h[3];
+      e = hd->h[4];
+      f = hd->h[5];
+      g = hd->h[6];
+      h = hd->h[7];
+
+      R(a, b, c, d, e, f, g, h, K[0], I(0));
+      R(h, a, b, c, d, e, f, g, K[1], I(1));
+      R(g, h, a, b, c, d, e, f, K[2], I(2));
+      R(f, g, h, a, b, c, d, e, K[3], I(3));
+      R(e, f, g, h, a, b, c, d, K[4], I(4));
+      R(d, e, f, g, h, a, b, c, K[5], I(5));
+      R(c, d, e, f, g, h, a, b, K[6], I(6));
+      R(b, c, d, e, f, g, h, a, K[7], I(7));
+      R(a, b, c, d, e, f, g, h, K[8], I(8));
+      R(h, a, b, c, d, e, f, g, K[9], I(9));
+      R(g, h, a, b, c, d, e, f, K[10], I(10));
+      R(f, g, h, a, b, c, d, e, K[11], I(11));
+      R(e, f, g, h, a, b, c, d, K[12], I(12));
+      R(d, e, f, g, h, a, b, c, K[13], I(13));
+      R(c, d, e, f, g, h, a, b, K[14], I(14));
+      R(b, c, d, e, f, g, h, a, K[15], I(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W(48));
+      R(h, a, b, c, d, e, f, g, K[49], W(49));
+      R(g, h, a, b, c, d, e, f, K[50], W(50));
+      R(f, g, h, a, b, c, d, e, K[51], W(51));
+      R(e, f, g, h, a, b, c, d, K[52], W(52));
+      R(d, e, f, g, h, a, b, c, K[53], W(53));
+      R(c, d, e, f, g, h, a, b, K[54], W(54));
+      R(b, c, d, e, f, g, h, a, K[55], W(55));
+      R(a, b, c, d, e, f, g, h, K[56], W(56));
+      R(h, a, b, c, d, e, f, g, K[57], W(57));
+      R(g, h, a, b, c, d, e, f, K[58], W(58));
+      R(f, g, h, a, b, c, d, e, K[59], W(59));
+      R(e, f, g, h, a, b, c, d, K[60], W(60));
+      R(d, e, f, g, h, a, b, c, K[61], W(61));
+      R(c, d, e, f, g, h, a, b, K[62], W(62));
+      R(b, c, d, e, f, g, h, a, K[63], W(63));
+
+      hd->h[0] += a;
+      hd->h[1] += b;
+      hd->h[2] += c;
+      hd->h[3] += d;
+      hd->h[4] += e;
+      hd->h[5] += f;
+      hd->h[6] += g;
+      hd->h[7] += h;
+
       data += 64;
     }
   while (--nblks);
 
-#ifdef ASM_EXTRA_STACK
-  /* 'transform_blk' is typically inlined and XMM6-XMM15 are stored at
-   *  the prologue of this function. Therefore need to add ASM_EXTRA_STACK to
-   *  here too.
-   */
-  burn += ASM_EXTRA_STACK;
-#endif
-
-  return burn;
+  return 26*4 + 32 + 3 * sizeof(void*);
 }
 
+#undef S0
+#undef S1
+#undef R
+
 
 /*
    The routine finally terminates the computation and returns the
@@ -446,8 +552,6 @@ sha256_final(void *context)
   byte *p;
   unsigned int burn;
 
-  _gcry_md_block_write (hd, NULL, 0); /* flush */;
-
   t = hd->bctx.nblocks;
   if (sizeof t == sizeof hd->bctx.nblocks)
     th = hd->bctx.nblocks_high;
@@ -467,28 +571,39 @@ sha256_final(void *context)
   msb <<= 3;
   msb |= t >> 29;
 
-  if (hd->bctx.count < 56)
-    { /* enough room */
+  if (0)
+    { }
+#ifdef USE_S390X_CRYPTO
+  else if (hd->use_s390x_crypto)
+    {
+      burn = do_sha256_final_s390x (hd, hd->bctx.buf, hd->bctx.count, msb, lsb);
+    }
+#endif
+  else if (hd->bctx.count < 56)  /* enough room */
+    {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
-      while (hd->bctx.count < 56)
-        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
+      if (hd->bctx.count < 56)
+       memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count);
+
+      /* append the 64 bit count */
+      buf_put_be32(hd->bctx.buf + 56, msb);
+      buf_put_be32(hd->bctx.buf + 60, lsb);
+      burn = (*hd->bctx.bwrite) (hd, hd->bctx.buf, 1);
     }
-  else
-    { /* need one extra block */
+  else  /* need one extra block */
+    {
       hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
-      while (hd->bctx.count < 64)
-        hd->bctx.buf[hd->bctx.count++] = 0;
-      _gcry_md_block_write (hd, NULL, 0);  /* flush */;
-      memset (hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
+      /* fill pad and next block with zeroes */
+      memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56);
+
+      /* append the 64 bit count */
+      buf_put_be32(hd->bctx.buf + 64 + 56, msb);
+      buf_put_be32(hd->bctx.buf + 64 + 60, lsb);
+      burn = (*hd->bctx.bwrite) (hd, hd->bctx.buf, 2);
     }
-  /* append the 64 bit count */
-  buf_put_be32(hd->bctx.buf + 56, msb);
-  buf_put_be32(hd->bctx.buf + 60, lsb);
-  burn = transform (hd, hd->bctx.buf, 1);
-  _gcry_burn_stack (burn);
 
   p = hd->bctx.buf;
-#define X(a) do { buf_put_be32(p, hd->h##a); p += 4; } while(0)
+#define X(a) do { buf_put_be32(p, hd->h[a]); p += 4; } while(0)
   X(0);
   X(1);
   X(2);
@@ -498,6 +613,10 @@ sha256_final(void *context)
   X(6);
   X(7);
 #undef X
+
+  hd->bctx.count = 0;
+
+  _gcry_burn_stack (burn);
 }
 
 static byte *
@@ -509,32 +628,41 @@ 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)
+static void
+_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);
-  _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);
   sha256_final (&hd);
   memcpy (outbuf, hd.bctx.buf, 32);
 }
 
 
-/* Variant of the above shortcut function using multiple buffers.  */
-void
-_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, size_t nbytes,
+                          const gcry_buffer_t *iov, int iovcnt)
 {
   SHA256_CONTEXT hd;
 
-  sha256_init (&hd, 0);
+  (void)nbytes;
+
+  sha224_init (&hd, 0);
   for (;iovcnt > 0; iov++, iovcnt--)
     _gcry_md_block_write (&hd,
                           (const char*)iov[0].data + iov[0].off, iov[0].len);
   sha256_final (&hd);
-  memcpy (outbuf, hd.bctx.buf, 32);
+  memcpy (outbuf, hd.bctx.buf, 28);
 }
 
 
@@ -660,48 +788,54 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
 
 
 \f
-static byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */
+static const byte asn224[19] = /* Object ID is 2.16.840.1.101.3.4.2.4 */
   { 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
     0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
     0x1C
   };
 
-static gcry_md_oid_spec_t oid_spec_sha224[] =
+static const gcry_md_oid_spec_t oid_spec_sha224[] =
   {
     /* From RFC3874, Section 4 */
     { "2.16.840.1.101.3.4.2.4" },
+    /* ANSI X9.62  ecdsaWithSHA224 */
+    { "1.2.840.10045.4.3.1" },
     { NULL },
   };
 
-static byte asn256[19] = /* Object ID is  2.16.840.1.101.3.4.2.1 */
+static const byte asn256[19] = /* Object ID is  2.16.840.1.101.3.4.2.1 */
   { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
     0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
     0x00, 0x04, 0x20 };
 
-static gcry_md_oid_spec_t oid_spec_sha256[] =
+static const gcry_md_oid_spec_t oid_spec_sha256[] =
   {
     /* According to the OpenPGP draft rfc2440-bis06 */
     { "2.16.840.1.101.3.4.2.1" },
     /* PKCS#1 sha256WithRSAEncryption */
     { "1.2.840.113549.1.1.11" },
+    /* ANSI X9.62  ecdsaWithSHA256 */
+    { "1.2.840.10045.4.3.2" },
 
     { NULL },
   };
 
-gcry_md_spec_t _gcry_digest_spec_sha224 =
+const 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_buffers,
     sizeof (SHA256_CONTEXT),
     run_selftests
   };
 
-gcry_md_spec_t _gcry_digest_spec_sha256 =
+const 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_buffers,
     sizeof (SHA256_CONTEXT),
     run_selftests
   };
index a9d1272..2b186b4 100644 (file)
@@ -91,6 +91,8 @@
 #define RW1213q q14
 #define RW1415q q15
 
+#define CLEAR_REG(reg) vmov.i8 reg, #0;
+
 /***********************************************************************
  * ARM assembly implementation of sha512 transform
  ***********************************************************************/
@@ -426,23 +428,24 @@ _gcry_sha512_transform_armv7_neon:
 
        /* Clear used registers */
        /* d16-d31 */
-       veor.u64 RW01q, RW01q;
-       veor.u64 RW23q, RW23q;
-       veor.u64 RW45q, RW45q;
-       veor.u64 RW67q, RW67q;
+       CLEAR_REG(RW01q);
+       CLEAR_REG(RW23q);
+       CLEAR_REG(RW45q);
+       CLEAR_REG(RW67q);
        vst1.64 {RE-RH}, [%r0]; /* Store the last half of context */
-       veor.u64 RW89q, RW89q;
-       veor.u64 RW1011q, RW1011q;
-       veor.u64 RW1213q, RW1213q;
-       veor.u64 RW1415q, RW1415q;
+       CLEAR_REG(RW89q);
+       CLEAR_REG(RW1011q);
+       CLEAR_REG(RW1213q);
+       CLEAR_REG(RW1415q);
        /* d8-d15 */
        vpop {RT0-RT7};
        /* d0-d7 (q0-q3) */
-       veor.u64 %q0, %q0;
-       veor.u64 %q1, %q1;
-       veor.u64 %q2, %q2;
-       veor.u64 %q3, %q3;
+       CLEAR_REG(%q0);
+       CLEAR_REG(%q1);
+       CLEAR_REG(%q2);
+       CLEAR_REG(%q3);
 
+       eor %r0, %r0;
        pop {%pc};
 .size _gcry_sha512_transform_armv7_neon,.-_gcry_sha512_transform_armv7_neon;
 
index 446a8b4..bfc4435 100644 (file)
     defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
     defined(HAVE_GCC_INLINE_ASM_AVX) && defined(USE_SHA512)
 
-#ifdef __PIC__
-#  define ADD_RIP +rip
-#else
-#  define ADD_RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .intel_syntax noprefix
 
 .text
 
 /* Virtual Registers */
-msg = rdi /* ARG1 */
-digest = rsi /* ARG2 */
-msglen = rdx /* ARG3 */
-T1 = rcx
-T2 = r8
-a_64 = r9
-b_64 = r10
-c_64 = r11
-d_64 = r12
-e_64 = r13
-f_64 = r14
-g_64 = r15
-h_64 = rbx
-tmp0 = rax
+#define msg rdi /* ARG1 */
+#define digest rsi /* ARG2 */
+#define msglen rdx /* ARG3 */
+#define T1 rcx
+#define T2 r8
+#define a_64 r9
+#define b_64 r10
+#define c_64 r11
+#define d_64 r12
+#define e_64 r13
+#define f_64 r14
+#define g_64 r15
+#define h_64 rbx
+#define tmp0 rax
 
 /*
 ; Local variables (stack frame)
 ; Note: frame_size must be an odd multiple of 8 bytes to XMM align RSP
 */
-frame_W      = 0 /* Message Schedule */
-frame_W_size = (80 * 8)
-frame_WK      = ((frame_W) + (frame_W_size)) /* W[t] + K[t] | W[t+1] + K[t+1] */
-frame_WK_size = (2 * 8)
-frame_GPRSAVE      = ((frame_WK) + (frame_WK_size))
-frame_GPRSAVE_size = (5 * 8)
-frame_size = ((frame_GPRSAVE) + (frame_GPRSAVE_size))
+#define frame_W 0 /* Message Schedule */
+#define frame_W_size (80 * 8)
+#define frame_WK ((frame_W) + (frame_W_size)) /* W[t] + K[t] | W[t+1] + K[t+1] */
+#define frame_WK_size (2 * 8)
+#define frame_GPRSAVE ((frame_WK) + (frame_WK_size))
+#define frame_GPRSAVE_size (5 * 8)
+#define frame_size ((frame_GPRSAVE) + (frame_GPRSAVE_size))
 
 
 /* Useful QWORD "arrays" for simpler memory references */
@@ -100,162 +90,151 @@ frame_size = ((frame_GPRSAVE) + (frame_GPRSAVE_size))
 /* MSG, DIGEST, K_t, W_t are arrays */
 /* WK_2(t) points to 1 of 2 qwords at frame.WK depdending on t being odd/even */
 
-.macro RotateState
-       /* Rotate symbles a..h right */
-       __TMP = h_64
-       h_64 =  g_64
-       g_64 =  f_64
-       f_64 =  e_64
-       e_64 =  d_64
-       d_64 =  c_64
-       c_64 =  b_64
-       b_64 =  a_64
-       a_64 =  __TMP
-.endm
-
-.macro RORQ p1 p2
-       /* shld is faster than ror on Intel Sandybridge */
-       shld    \p1, \p1, (64 - \p2)
-.endm
-
-.macro SHA512_Round t
-       /* Compute Round %%t */
-       mov     T1,   f_64        /* T1 = f */
-       mov     tmp0, e_64        /* tmp = e */
-       xor     T1,   g_64        /* T1 = f ^ g */
-       RORQ    tmp0, 23 /* 41     ; tmp = e ror 23 */
-       and     T1,   e_64        /* T1 = (f ^ g) & e */
-       xor     tmp0, e_64        /* tmp = (e ror 23) ^ e */
-       xor     T1,   g_64        /* T1 = ((f ^ g) & e) ^ g = CH(e,f,g) */
-       add     T1,   [WK_2(\t)] /* W[t] + K[t] from message scheduler */
-       RORQ    tmp0, 4 /* 18      ; tmp = ((e ror 23) ^ e) ror 4 */
-       xor     tmp0, e_64        /* tmp = (((e ror 23) ^ e) ror 4) ^ e */
-       mov     T2,   a_64        /* T2 = a */
-       add     T1,   h_64        /* T1 = CH(e,f,g) + W[t] + K[t] + h */
-       RORQ    tmp0, 14 /* 14     ; tmp = ((((e ror23)^e)ror4)^e)ror14 = S1(e) */
-       add     T1,   tmp0        /* T1 = CH(e,f,g) + W[t] + K[t] + S1(e) */
-       mov     tmp0, a_64        /* tmp = a */
-       xor     T2,   c_64        /* T2 = a ^ c */
-       and     tmp0, c_64        /* tmp = a & c */
-       and     T2,   b_64        /* T2 = (a ^ c) & b */
-       xor     T2,   tmp0        /* T2 = ((a ^ c) & b) ^ (a & c) = Maj(a,b,c) */
-       mov     tmp0, a_64        /* tmp = a */
-       RORQ    tmp0, 5 /* 39      ; tmp = a ror 5 */
-       xor     tmp0, a_64        /* tmp = (a ror 5) ^ a */
-       add     d_64, T1          /* e(next_state) = d + T1  */
-       RORQ    tmp0, 6 /* 34      ; tmp = ((a ror 5) ^ a) ror 6 */
-       xor     tmp0, a_64        /* tmp = (((a ror 5) ^ a) ror 6) ^ a */
-       lea     h_64, [T1 + T2]   /* a(next_state) = T1 + Maj(a,b,c) */
-       RORQ    tmp0, 28 /* 28     ; tmp = ((((a ror5)^a)ror6)^a)ror28 = S0(a) */
-       add     h_64, tmp0        /* a(next_state) = T1 + Maj(a,b,c) S0(a) */
-       RotateState
-.endm
-
-.macro SHA512_2Sched_2Round_avx t
-/*     ; Compute rounds %%t-2 and %%t-1
-       ; Compute message schedule QWORDS %%t and %%t+1
-
-       ;   Two rounds are computed based on the values for K[t-2]+W[t-2] and
-       ; K[t-1]+W[t-1] which were previously stored at WK_2 by the message
-       ; scheduler.
-       ;   The two new schedule QWORDS are stored at [W_t(%%t)] and [W_t(%%t+1)].
-       ; They are then added to their respective SHA512 constants at
-       ; [K_t(%%t)] and [K_t(%%t+1)] and stored at dqword [WK_2(%%t)]
-       ;   For brievity, the comments following vectored instructions only refer to
-       ; the first of a pair of QWORDS.
-       ; Eg. XMM4=W[t-2] really means XMM4={W[t-2]|W[t-1]}
-       ;   The computation of the message schedule and the rounds are tightly
-       ; stitched to take advantage of instruction-level parallelism.
-       ; For clarity, integer instructions (for the rounds calculation) are indented
-       ; by one tab. Vectored instructions (for the message scheduler) are indented
-       ; by two tabs. */
-
-               vmovdqa xmm4, [W_t(\t-2)]   /* XMM4 = W[t-2] */
-               vmovdqu xmm5, [W_t(\t-15)]  /* XMM5 = W[t-15] */
-       mov     T1,   f_64
-               vpsrlq  xmm0, xmm4, 61       /* XMM0 = W[t-2]>>61 */
-       mov     tmp0, e_64
-               vpsrlq  xmm6, xmm5, 1        /* XMM6 = W[t-15]>>1 */
-       xor     T1,   g_64
-       RORQ    tmp0, 23 /* 41 */
-               vpsrlq  xmm1, xmm4, 19       /* XMM1 = W[t-2]>>19 */
-       and     T1,   e_64
-       xor     tmp0, e_64
-               vpxor   xmm0, xmm0, xmm1           /* XMM0 = W[t-2]>>61 ^ W[t-2]>>19 */
-       xor     T1,   g_64
-       add     T1,   [WK_2(\t)];
-               vpsrlq  xmm7, xmm5, 8        /* XMM7 = W[t-15]>>8 */
-       RORQ    tmp0, 4 /* 18 */
-               vpsrlq  xmm2, xmm4, 6        /* XMM2 = W[t-2]>>6 */
-       xor     tmp0, e_64
-       mov     T2,   a_64
-       add     T1,   h_64
-               vpxor   xmm6, xmm6, xmm7           /* XMM6 = W[t-15]>>1 ^ W[t-15]>>8 */
-       RORQ    tmp0, 14 /* 14 */
-       add     T1,   tmp0
-               vpsrlq  xmm8, xmm5, 7        /* XMM8 = W[t-15]>>7 */
-       mov     tmp0, a_64
-       xor     T2,   c_64
-               vpsllq  xmm3, xmm4, (64-61)  /* XMM3 = W[t-2]<<3 */
-       and     tmp0, c_64
-       and     T2,   b_64
-               vpxor   xmm2, xmm2, xmm3           /* XMM2 = W[t-2]>>6 ^ W[t-2]<<3 */
-       xor     T2,   tmp0
-       mov     tmp0, a_64
-               vpsllq  xmm9, xmm5, (64-1)   /* XMM9 = W[t-15]<<63 */
-       RORQ    tmp0, 5 /* 39 */
-               vpxor   xmm8, xmm8, xmm9           /* XMM8 = W[t-15]>>7 ^ W[t-15]<<63 */
-       xor     tmp0, a_64
-       add     d_64, T1
-       RORQ    tmp0, 6 /* 34 */
-       xor     tmp0, a_64
-               vpxor   xmm6, xmm6, xmm8           /* XMM6 = W[t-15]>>1 ^ W[t-15]>>8 ^ W[t-15]>>7 ^ W[t-15]<<63 */
-       lea     h_64, [T1 + T2]
-       RORQ    tmp0, 28 /* 28 */
-               vpsllq  xmm4, xmm4, (64-19)        /* XMM4 = W[t-2]<<25 */
-       add     h_64, tmp0
-       RotateState
-               vpxor   xmm0, xmm0, xmm4           /* XMM0 = W[t-2]>>61 ^ W[t-2]>>19 ^ W[t-2]<<25 */
-       mov     T1, f_64
-               vpxor   xmm0, xmm0, xmm2           /* XMM0 = s1(W[t-2]) */
-       mov     tmp0, e_64
-       xor     T1,   g_64
-               vpaddq  xmm0, xmm0, [W_t(\t-16)]  /* XMM0 = s1(W[t-2]) + W[t-16] */
-               vmovdqu xmm1, [W_t(\t- 7)]  /* XMM1 = W[t-7] */
-       RORQ    tmp0, 23 /* 41 */
-       and     T1,   e_64
-       xor     tmp0, e_64
-       xor     T1,   g_64
-               vpsllq  xmm5, xmm5, (64-8)         /* XMM5 = W[t-15]<<56 */
-       add     T1,   [WK_2(\t+1)]
-               vpxor   xmm6, xmm6, xmm5           /* XMM6 = s0(W[t-15]) */
-       RORQ    tmp0, 4 /* 18 */
-               vpaddq  xmm0, xmm0, xmm6           /* XMM0 = s1(W[t-2]) + W[t-16] + s0(W[t-15]) */
-       xor     tmp0, e_64
-               vpaddq  xmm0, xmm0, xmm1           /* XMM0 = W[t] = s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16] */
-       mov     T2,   a_64
-       add     T1,   h_64
-       RORQ    tmp0, 14 /* 14 */
-       add     T1,   tmp0
-               vmovdqa [W_t(\t)], xmm0      /* Store W[t] */
-               vpaddq  xmm0, xmm0, [K_t(t)]        /* Compute W[t]+K[t] */
-               vmovdqa [WK_2(t)], xmm0       /* Store W[t]+K[t] for next rounds */
-       mov     tmp0, a_64
-       xor     T2,   c_64
-       and     tmp0, c_64
-       and     T2,   b_64
-       xor     T2,   tmp0
-       mov     tmp0, a_64
-       RORQ    tmp0, 5 /* 39 */
-       xor     tmp0, a_64
-       add     d_64, T1
-       RORQ    tmp0, 6 /* 34 */
-       xor     tmp0, a_64
-       lea     h_64, [T1 + T2]
-       RORQ    tmp0, 28 /* 28 */
-       add     h_64, tmp0
-       RotateState
-.endm
+#define RORQ(p1, p2) \
+       /* shld is faster than ror on Intel Sandybridge */ \
+       shld    p1, p1, (64 - p2)
+
+#define SHA512_Round(t, a, b, c, d, e, f, g, h) \
+       /* Compute Round %%t */; \
+       mov     T1,   f        /* T1 = f */; \
+       mov     tmp0, e        /* tmp = e */; \
+       xor     T1,   g        /* T1 = f ^ g */; \
+       RORQ(   tmp0, 23) /* 41     ; tmp = e ror 23 */; \
+       and     T1,   e        /* T1 = (f ^ g) & e */; \
+       xor     tmp0, e        /* tmp = (e ror 23) ^ e */; \
+       xor     T1,   g        /* T1 = ((f ^ g) & e) ^ g = CH(e,f,g) */; \
+       add     T1,   [WK_2(t)] /* W[t] + K[t] from message scheduler */; \
+       RORQ(   tmp0, 4) /* 18      ; tmp = ((e ror 23) ^ e) ror 4 */; \
+       xor     tmp0, e        /* tmp = (((e ror 23) ^ e) ror 4) ^ e */; \
+       mov     T2,   a        /* T2 = a */; \
+       add     T1,   h        /* T1 = CH(e,f,g) + W[t] + K[t] + h */; \
+       RORQ(   tmp0, 14) /* 14     ; tmp = ((((e ror23)^e)ror4)^e)ror14 = S1(e) */; \
+       add     T1,   tmp0        /* T1 = CH(e,f,g) + W[t] + K[t] + S1(e) */; \
+       mov     tmp0, a        /* tmp = a */; \
+       xor     T2,   c        /* T2 = a ^ c */; \
+       and     tmp0, c        /* tmp = a & c */; \
+       and     T2,   b        /* T2 = (a ^ c) & b */; \
+       xor     T2,   tmp0        /* T2 = ((a ^ c) & b) ^ (a & c) = Maj(a,b,c) */; \
+       mov     tmp0, a        /* tmp = a */; \
+       RORQ(   tmp0, 5) /* 39      ; tmp = a ror 5 */; \
+       xor     tmp0, a        /* tmp = (a ror 5) ^ a */; \
+       add     d, T1          /* e(next_state) = d + T1  */; \
+       RORQ(   tmp0, 6) /* 34      ; tmp = ((a ror 5) ^ a) ror 6 */; \
+       xor     tmp0, a        /* tmp = (((a ror 5) ^ a) ror 6) ^ a */; \
+       lea     h, [T1 + T2]   /* a(next_state) = T1 + Maj(a,b,c) */; \
+       RORQ(   tmp0, 28) /* 28     ; tmp = ((((a ror5)^a)ror6)^a)ror28 = S0(a) */; \
+       add     h, tmp0        /* a(next_state) = T1 + Maj(a,b,c) S0(a) */
+
+#define SHA512_2Sched_2Round_avx_PART1(t, a, b, c, d, e, f, g, h) \
+       /* \
+       ; Compute rounds %%t-2 and %%t-1 \
+       ; Compute message schedule QWORDS %%t and %%t+1 \
+       ; \
+       ;   Two rounds are computed based on the values for K[t-2]+W[t-2] and \
+       ; K[t-1]+W[t-1] which were previously stored at WK_2 by the message \
+       ; scheduler. \
+       ;   The two new schedule QWORDS are stored at [W_t(%%t)] and [W_t(%%t+1)]. \
+       ; They are then added to their respective SHA512 constants at \
+       ; [K_t(%%t)] and [K_t(%%t+1)] and stored at dqword [WK_2(%%t)] \
+       ;   For brievity, the comments following vectored instructions only refer to \
+       ; the first of a pair of QWORDS. \
+       ; Eg. XMM4=W[t-2] really means XMM4={W[t-2]|W[t-1]} \
+       ;   The computation of the message schedule and the rounds are tightly \
+       ; stitched to take advantage of instruction-level parallelism. \
+       ; For clarity, integer instructions (for the rounds calculation) are indented \
+       ; by one tab. Vectored instructions (for the message scheduler) are indented \
+       ; by two tabs. \
+       */ \
+       \
+               vmovdqa xmm4, [W_t(t-2)]   /* XMM4 = W[t-2] */; \
+               vmovdqu xmm5, [W_t(t-15)]  /* XMM5 = W[t-15] */; \
+       mov     T1,   f; \
+               vpsrlq  xmm0, xmm4, 61       /* XMM0 = W[t-2]>>61 */; \
+       mov     tmp0, e; \
+               vpsrlq  xmm6, xmm5, 1        /* XMM6 = W[t-15]>>1 */; \
+       xor     T1,   g; \
+       RORQ(   tmp0, 23) /* 41 */; \
+               vpsrlq  xmm1, xmm4, 19       /* XMM1 = W[t-2]>>19 */; \
+       and     T1,   e; \
+       xor     tmp0, e; \
+               vpxor   xmm0, xmm0, xmm1           /* XMM0 = W[t-2]>>61 ^ W[t-2]>>19 */; \
+       xor     T1,   g; \
+       add     T1,   [WK_2(t)]; \
+               vpsrlq  xmm7, xmm5, 8        /* XMM7 = W[t-15]>>8 */; \
+       RORQ(   tmp0, 4) /* 18 */; \
+               vpsrlq  xmm2, xmm4, 6        /* XMM2 = W[t-2]>>6 */; \
+       xor     tmp0, e; \
+       mov     T2,   a; \
+       add     T1,   h; \
+               vpxor   xmm6, xmm6, xmm7           /* XMM6 = W[t-15]>>1 ^ W[t-15]>>8 */; \
+       RORQ(   tmp0, 14) /* 14 */; \
+       add     T1,   tmp0; \
+               vpsrlq  xmm8, xmm5, 7        /* XMM8 = W[t-15]>>7 */; \
+       mov     tmp0, a; \
+       xor     T2,   c; \
+               vpsllq  xmm3, xmm4, (64-61)  /* XMM3 = W[t-2]<<3 */; \
+       and     tmp0, c; \
+       and     T2,   b; \
+               vpxor   xmm2, xmm2, xmm3           /* XMM2 = W[t-2]>>6 ^ W[t-2]<<3 */; \
+       xor     T2,   tmp0; \
+       mov     tmp0, a; \
+               vpsllq  xmm9, xmm5, (64-1)   /* XMM9 = W[t-15]<<63 */; \
+       RORQ(   tmp0, 5) /* 39 */; \
+               vpxor   xmm8, xmm8, xmm9           /* XMM8 = W[t-15]>>7 ^ W[t-15]<<63 */; \
+       xor     tmp0, a; \
+       add     d, T1; \
+       RORQ(   tmp0, 6) /* 34 */; \
+       xor     tmp0, a; \
+               vpxor   xmm6, xmm6, xmm8           /* XMM6 = W[t-15]>>1 ^ W[t-15]>>8 ^ W[t-15]>>7 ^ W[t-15]<<63 */; \
+       lea     h, [T1 + T2]; \
+       RORQ(   tmp0, 28) /* 28 */; \
+               vpsllq  xmm4, xmm4, (64-19)        /* XMM4 = W[t-2]<<25 */; \
+       add     h, tmp0
+
+#define SHA512_2Sched_2Round_avx_PART2(t, a, b, c, d, e, f, g, h) \
+               vpxor   xmm0, xmm0, xmm4           /* XMM0 = W[t-2]>>61 ^ W[t-2]>>19 ^ W[t-2]<<25 */; \
+       mov     T1, f; \
+               vpxor   xmm0, xmm0, xmm2           /* XMM0 = s1(W[t-2]) */; \
+       mov     tmp0, e; \
+       xor     T1,   g; \
+               vpaddq  xmm0, xmm0, [W_t(t-16)]  /* XMM0 = s1(W[t-2]) + W[t-16] */; \
+               vmovdqu xmm1, [W_t(t- 7)]  /* XMM1 = W[t-7] */; \
+       RORQ(   tmp0, 23) /* 41 */; \
+       and     T1,   e; \
+       xor     tmp0, e; \
+       xor     T1,   g; \
+               vpsllq  xmm5, xmm5, (64-8)         /* XMM5 = W[t-15]<<56 */; \
+       add     T1,   [WK_2(t+1)]; \
+               vpxor   xmm6, xmm6, xmm5           /* XMM6 = s0(W[t-15]) */; \
+       RORQ(   tmp0, 4) /* 18 */; \
+               vpaddq  xmm0, xmm0, xmm6           /* XMM0 = s1(W[t-2]) + W[t-16] + s0(W[t-15]) */; \
+       xor     tmp0, e; \
+               vpaddq  xmm0, xmm0, xmm1           /* XMM0 = W[t] = s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16] */; \
+       mov     T2,   a; \
+       add     T1,   h; \
+       RORQ(   tmp0, 14) /* 14 */; \
+       add     T1,   tmp0; \
+               vmovdqa [W_t(t)], xmm0      /* Store W[t] */; \
+               vpaddq  xmm0, xmm0, [K_t(t)]        /* Compute W[t]+K[t] */; \
+               vmovdqa [WK_2(t)], xmm0       /* Store W[t]+K[t] for next rounds */; \
+       mov     tmp0, a; \
+       xor     T2,   c; \
+       and     tmp0, c; \
+       and     T2,   b; \
+       xor     T2,   tmp0; \
+       mov     tmp0, a; \
+       RORQ(   tmp0, 5) /* 39 */; \
+       xor     tmp0, a; \
+       add     d, T1; \
+       RORQ(   tmp0, 6) /* 34 */; \
+       xor     tmp0, a; \
+       lea     h, [T1 + T2]; \
+       RORQ(   tmp0, 28) /* 28 */; \
+       add     h, tmp0
+
+#define SHA512_2Sched_2Round_avx(t, a, b, c, d, e, f, g, h) \
+       SHA512_2Sched_2Round_avx_PART1(t, a, b, c, d, e, f, g, h); \
+       SHA512_2Sched_2Round_avx_PART2(t, h, a, b, c, d, e, f, g)
 
 /*
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -269,6 +248,7 @@ frame_size = ((frame_GPRSAVE) + (frame_GPRSAVE_size))
 ELF(.type _gcry_sha512_transform_amd64_avx,@function;)
 .align 16
 _gcry_sha512_transform_amd64_avx:
+       CFI_STARTPROC()
        xor eax, eax
 
        cmp     msglen, 0
@@ -278,6 +258,7 @@ _gcry_sha512_transform_amd64_avx:
 
        /* Allocate Stack Space */
        sub     rsp, frame_size
+       CFI_ADJUST_CFA_OFFSET(frame_size);
 
        /* Save GPRs */
        mov     [rsp + frame_GPRSAVE + 8 * 0], rbx
@@ -285,6 +266,11 @@ _gcry_sha512_transform_amd64_avx:
        mov     [rsp + frame_GPRSAVE + 8 * 2], r13
        mov     [rsp + frame_GPRSAVE + 8 * 3], r14
        mov     [rsp + frame_GPRSAVE + 8 * 4], r15
+       CFI_REL_OFFSET(rbx, frame_GPRSAVE + 8 * 0);
+       CFI_REL_OFFSET(r12, frame_GPRSAVE + 8 * 1);
+       CFI_REL_OFFSET(r13, frame_GPRSAVE + 8 * 2);
+       CFI_REL_OFFSET(r14, frame_GPRSAVE + 8 * 3);
+       CFI_REL_OFFSET(r15, frame_GPRSAVE + 8 * 4);
 
 .Lupdateblock:
 
@@ -298,37 +284,77 @@ _gcry_sha512_transform_amd64_avx:
        mov     g_64, [DIGEST(6)]
        mov     h_64, [DIGEST(7)]
 
-       t = 0
-       .rept 80/2 + 1
-       /* (80 rounds) / (2 rounds/iteration) + (1 iteration) */
-       /* +1 iteration because the scheduler leads hashing by 1 iteration */
-               .if t < 2
-                       /* BSWAP 2 QWORDS */
-                       vmovdqa xmm1, [.LXMM_QWORD_BSWAP ADD_RIP]
-                       vmovdqu xmm0, [MSG(t)]
-                       vpshufb xmm0, xmm0, xmm1     /* BSWAP */
-                       vmovdqa [W_t(t)], xmm0       /* Store Scheduled Pair */
-                       vpaddq  xmm0, xmm0, [K_t(t)] /* Compute W[t]+K[t] */
-                       vmovdqa [WK_2(t)], xmm0      /* Store into WK for rounds */
-               .elseif t < 16
-                       /* BSWAP 2 QWORDS, Compute 2 Rounds */
-                       vmovdqu xmm0, [MSG(t)]
-                       vpshufb xmm0, xmm0, xmm1     /* BSWAP */
-                       SHA512_Round (t - 2)         /* Round t-2 */
-                       vmovdqa [W_t(t)], xmm0       /* Store Scheduled Pair */
-                       vpaddq  xmm0, xmm0, [K_t(t)] /* Compute W[t]+K[t] */
-                       SHA512_Round (t - 1)         /* Round t-1 */
-                       vmovdqa [WK_2(t)], xmm0      /* W[t]+K[t] into WK */
-               .elseif t < 79
-                       /* Schedule 2 QWORDS; Compute 2 Rounds */
-                       SHA512_2Sched_2Round_avx t
-               .else
-                       /* Compute 2 Rounds */
-                       SHA512_Round (t - 2)
-                       SHA512_Round (t - 1)
-               .endif
-               t = ((t)+2)
-       .endr
+       /* BSWAP 2 QWORDS */
+       vmovdqa xmm1, [.LXMM_QWORD_BSWAP ADD_RIP]
+       vmovdqu xmm0, [MSG(0)]
+       vpshufb xmm0, xmm0, xmm1     /* BSWAP */
+       vmovdqa [W_t(0)], xmm0       /* Store Scheduled Pair */
+       vpaddq  xmm0, xmm0, [K_t(0)] /* Compute W[t]+K[t] */
+       vmovdqa [WK_2(0)], xmm0      /* Store into WK for rounds */
+
+       #define T_2_14(t, a, b, c, d, e, f, g, h) \
+               /* BSWAP 2 QWORDS, Compute 2 Rounds */; \
+               vmovdqu xmm0, [MSG(t)]; \
+               vpshufb xmm0, xmm0, xmm1     /* BSWAP */; \
+               SHA512_Round(((t) - 2), a##_64, b##_64, c##_64, d##_64, \
+                                       e##_64, f##_64, g##_64, h##_64); \
+               vmovdqa [W_t(t)], xmm0       /* Store Scheduled Pair */; \
+               vpaddq  xmm0, xmm0, [K_t(t)] /* Compute W[t]+K[t] */; \
+               SHA512_Round(((t) - 1), h##_64, a##_64, b##_64, c##_64, \
+                                       d##_64, e##_64, f##_64, g##_64); \
+               vmovdqa [WK_2(t)], xmm0      /* W[t]+K[t] into WK */
+
+       #define T_16_78(t, a, b, c, d, e, f, g, h) \
+               SHA512_2Sched_2Round_avx((t), a##_64, b##_64, c##_64, d##_64, \
+                                             e##_64, f##_64, g##_64, h##_64)
+
+       #define T_80(t, a, b, c, d, e, f, g, h) \
+               /* Compute 2 Rounds */; \
+               SHA512_Round((t - 2), a##_64, b##_64, c##_64, d##_64, \
+                                     e##_64, f##_64, g##_64, h##_64); \
+               SHA512_Round((t - 1), h##_64, a##_64, b##_64, c##_64, \
+                                     d##_64, e##_64, f##_64, g##_64)
+
+       T_2_14(2, a, b, c, d, e, f, g, h)
+       T_2_14(4, g, h, a, b, c, d, e, f)
+       T_2_14(6, e, f, g, h, a, b, c, d)
+       T_2_14(8, c, d, e, f, g, h, a, b)
+       T_2_14(10, a, b, c, d, e, f, g, h)
+       T_2_14(12, g, h, a, b, c, d, e, f)
+       T_2_14(14, e, f, g, h, a, b, c, d)
+       T_16_78(16, c, d, e, f, g, h, a, b)
+       T_16_78(18, a, b, c, d, e, f, g, h)
+       T_16_78(20, g, h, a, b, c, d, e, f)
+       T_16_78(22, e, f, g, h, a, b, c, d)
+       T_16_78(24, c, d, e, f, g, h, a, b)
+       T_16_78(26, a, b, c, d, e, f, g, h)
+       T_16_78(28, g, h, a, b, c, d, e, f)
+       T_16_78(30, e, f, g, h, a, b, c, d)
+       T_16_78(32, c, d, e, f, g, h, a, b)
+       T_16_78(34, a, b, c, d, e, f, g, h)
+       T_16_78(36, g, h, a, b, c, d, e, f)
+       T_16_78(38, e, f, g, h, a, b, c, d)
+       T_16_78(40, c, d, e, f, g, h, a, b)
+       T_16_78(42, a, b, c, d, e, f, g, h)
+       T_16_78(44, g, h, a, b, c, d, e, f)
+       T_16_78(46, e, f, g, h, a, b, c, d)
+       T_16_78(48, c, d, e, f, g, h, a, b)
+       T_16_78(50, a, b, c, d, e, f, g, h)
+       T_16_78(52, g, h, a, b, c, d, e, f)
+       T_16_78(54, e, f, g, h, a, b, c, d)
+       T_16_78(56, c, d, e, f, g, h, a, b)
+       T_16_78(58, a, b, c, d, e, f, g, h)
+       T_16_78(60, g, h, a, b, c, d, e, f)
+       T_16_78(62, e, f, g, h, a, b, c, d)
+       T_16_78(64, c, d, e, f, g, h, a, b)
+       T_16_78(66, a, b, c, d, e, f, g, h)
+       T_16_78(68, g, h, a, b, c, d, e, f)
+       T_16_78(70, e, f, g, h, a, b, c, d)
+       T_16_78(72, c, d, e, f, g, h, a, b)
+       T_16_78(74, a, b, c, d, e, f, g, h)
+       T_16_78(76, g, h, a, b, c, d, e, f)
+       T_16_78(78, e, f, g, h, a, b, c, d)
+       T_80(80, c, d, e, f, g, h, a, b)
 
        /* Update digest */
        add     [DIGEST(0)], a_64
@@ -351,17 +377,31 @@ _gcry_sha512_transform_amd64_avx:
        mov     r13, [rsp + frame_GPRSAVE + 8 * 2]
        mov     r14, [rsp + frame_GPRSAVE + 8 * 3]
        mov     r15, [rsp + frame_GPRSAVE + 8 * 4]
-
-       /* Restore Stack Pointer */
-       add     rsp, frame_size
+       CFI_RESTORE(rbx)
+       CFI_RESTORE(r12)
+       CFI_RESTORE(r13)
+       CFI_RESTORE(r14)
+       CFI_RESTORE(r15)
 
        vzeroall
 
-       /* Return stack burn depth */
-       mov     rax, frame_size
+       /* Burn stack */
+       mov eax, 0
+.Lerase_stack:
+       vmovdqu [rsp + rax], ymm0
+       add eax, 32
+       cmp eax, frame_W_size
+       jne .Lerase_stack
+       vmovdqu [rsp + frame_WK], xmm0
+       xor     eax, eax
+
+       /* Restore Stack Pointer */
+       add     rsp, frame_size
+       CFI_ADJUST_CFA_OFFSET(-frame_size);
 
 .Lnowork:
-       ret
+       ret_spec_stop
+       CFI_ENDPROC()
 
 /*
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
index 05bef64..a431e19 100644 (file)
     defined(HAVE_GCC_INLINE_ASM_AVX2) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \
     defined(USE_SHA512)
 
-#ifdef __PIC__
-#  define ADD_RIP +rip
-#else
-#  define ADD_RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .intel_syntax noprefix
 
 .text
 
 /* Virtual Registers */
-Y_0 = ymm4
-Y_1 = ymm5
-Y_2 = ymm6
-Y_3 = ymm7
-
-YTMP0 = ymm0
-YTMP1 = ymm1
-YTMP2 = ymm2
-YTMP3 = ymm3
-YTMP4 = ymm8
-XFER =  YTMP0
-
-BYTE_FLIP_MASK =  ymm9
-
-INP =         rdi /* 1st arg */
-CTX =         rsi /* 2nd arg */
-NUM_BLKS =    rdx /* 3rd arg */
-c =           rcx
-d =           r8
-e =           rdx
-y3 =          rdi
-
-TBL =   rbp
-
-a =     rax
-b =     rbx
-
-f =     r9
-g =     r10
-h =     r11
-old_h = r11
-
-T1 =    r12
-y0 =    r13
-y1 =    r14
-y2 =    r15
-
-y4 =    r12
+#define Y_0 ymm4
+#define Y_1 ymm5
+#define Y_2 ymm6
+#define Y_3 ymm7
+
+#define YTMP0 ymm0
+#define YTMP1 ymm1
+#define YTMP2 ymm2
+#define YTMP3 ymm3
+#define YTMP4 ymm8
+#define XFER YTMP0
+
+#define BYTE_FLIP_MASK ymm9
+#define MASK_YMM_LO ymm10
+#define MASK_YMM_LOx xmm10
+
+#define INP rdi /* 1st arg */
+#define CTX rsi /* 2nd arg */
+#define NUM_BLKS rdx /* 3rd arg */
+#define c rcx
+#define d r8
+#define e rdx
+#define y3 rdi
+
+#define TBL rbp
+
+#define a rax
+#define b rbx
+
+#define f r9
+#define g r10
+#define h r11
+
+#define T1 r12
+#define y0 r13
+#define y1 r14
+#define y2 r15
+
+#define y4 r12
 
 /* Local variables (stack frame) */
 #define frame_XFER      0
-#define frame_XFER_size (4*8)
+#define frame_XFER_size (4*4*8)
 #define frame_SRND      (frame_XFER + frame_XFER_size)
 #define frame_SRND_size (1*8)
 #define frame_INP      (frame_SRND + frame_SRND_size)
 #define frame_INP_size (1*8)
-#define frame_INPEND      (frame_INP + frame_INP_size)
-#define frame_INPEND_size (1*8)
-#define frame_RSPSAVE      (frame_INPEND + frame_INPEND_size)
+#define frame_NBLKS      (frame_INP + frame_INP_size)
+#define frame_NBLKS_size (1*8)
+#define frame_RSPSAVE      (frame_NBLKS + frame_NBLKS_size)
 #define frame_RSPSAVE_size (1*8)
 #define frame_GPRSAVE      (frame_RSPSAVE + frame_RSPSAVE_size)
 #define frame_GPRSAVE_size (6*8)
@@ -124,474 +115,153 @@ y4 =    r12
 
 /* addm [mem], reg */
 /* Add reg to mem using reg-mem add and store */
-.macro addm p1 p2
-       add     \p2, \p1
-       mov     \p1, \p2
-.endm
+#define addm(p1, p2) \
+       add     p2, p1; \
+       mov     p1, p2;
 
 
 /* COPY_YMM_AND_BSWAP ymm, [mem], byte_flip_mask */
 /* Load ymm with mem and byte swap each dword */
-.macro COPY_YMM_AND_BSWAP p1 p2 p3
-       VMOVDQ \p1, \p2
-       vpshufb \p1, \p1, \p3
-.endm
-/* rotate_Ys */
-/* Rotate values of symbols Y0...Y3 */
-.macro rotate_Ys
-       __Y_ = Y_0
-       Y_0 = Y_1
-       Y_1 = Y_2
-       Y_2 = Y_3
-       Y_3 = __Y_
-.endm
-
-/* RotateState */
-.macro RotateState
-       /* Rotate symbles a..h right */
-       old_h =  h
-       __TMP_ = h
-       h =      g
-       g =      f
-       f =      e
-       e =      d
-       d =      c
-       c =      b
-       b =      a
-       a =      __TMP_
-.endm
+#define COPY_YMM_AND_BSWAP(p1, p2, p3) \
+       VMOVDQ p1, p2; \
+       vpshufb p1, p1, p3
 
 /* %macro MY_VPALIGNR  YDST, YSRC1, YSRC2, RVAL */
 /* YDST = {YSRC1, YSRC2} >> RVAL*8 */
-.macro MY_VPALIGNR YDST, YSRC1, YSRC2, RVAL
-       vperm2f128      \YDST, \YSRC1, \YSRC2, 0x3      /* YDST = {YS1_LO, YS2_HI} */
-       vpalignr        \YDST, \YDST, \YSRC2, \RVAL     /* YDST = {YDS1, YS2} >> RVAL*8 */
-.endm
-
-.macro FOUR_ROUNDS_AND_SCHED
-/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-               /* Extract w[t-7] */
-               MY_VPALIGNR     YTMP0, Y_3, Y_2, 8              /* YTMP0 = W[-7] */
-               /* Calculate w[t-16] + w[t-7] */
-               vpaddq          YTMP0, YTMP0, Y_0               /* YTMP0 = W[-7] + W[-16] */
-               /* Extract w[t-15] */
-               MY_VPALIGNR     YTMP1, Y_1, Y_0, 8              /* YTMP1 = W[-15] */
-
-               /* Calculate sigma0 */
-
-               /* Calculate w[t-15] ror 1 */
-               vpsrlq          YTMP2, YTMP1, 1
-               vpsllq          YTMP3, YTMP1, (64-1)
-               vpor            YTMP3, YTMP3, YTMP2             /* YTMP3 = W[-15] ror 1 */
-               /* Calculate w[t-15] shr 7 */
-               vpsrlq          YTMP4, YTMP1, 7                 /* YTMP4 = W[-15] >> 7 */
-
-       mov     y3, a           /* y3 = a                                       ; MAJA   */
-       rorx    y0, e, 41       /* y0 = e >> 41                                 ; S1A */
-       rorx    y1, e, 18       /* y1 = e >> 18                                 ; S1B */
-
-       add     h, [rsp+frame_XFER+0*8]         /* h = k + w + h                                ; --     */
-       or      y3, c           /* y3 = a|c                                     ; MAJA   */
-       mov     y2, f           /* y2 = f                                       ; CH     */
-       rorx    T1, a, 34       /* T1 = a >> 34                                 ; S0B */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18)                       ; S1 */
-       xor     y2, g           /* y2 = f^g                                     ; CH     */
-       rorx    y1, e, 14       /* y1 = (e >> 14)                                       ; S1 */
-
-       and     y2, e           /* y2 = (f^g)&e                                 ; CH     */
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18) ^ (e>>14)             ; S1 */
-       rorx    y1, a, 39       /* y1 = a >> 39                                 ; S0A */
-       add     d, h            /* d = k + w + h + d                            ; --     */
-
-       and     y3, b           /* y3 = (a|c)&b                                 ; MAJA   */
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34)                       ; S0 */
-       rorx    T1, a, 28       /* T1 = (a >> 28)                                       ; S0 */
-
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g                        ; CH     */
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34) ^ (a>>28)             ; S0 */
-       mov     T1, a           /* T1 = a                                       ; MAJB   */
-       and     T1, c           /* T1 = a&c                                     ; MAJB   */
-
-       add     y2, y0          /* y2 = S1 + CH                                 ; --     */
-       or      y3, T1          /* y3 = MAJ = (a|c)&b)|(a&c)                    ; MAJ    */
-       add     h, y1           /* h = k + w + h + S0                           ; --     */
-
-       add     d, y2           /* d = k + w + h + d + S1 + CH = d + t1         ; --     */
-
-       add     h, y2           /* h = k + w + h + S0 + S1 + CH = t1 + S0       ; --     */
-       add     h, y3           /* h = t1 + S0 + MAJ                            ; --     */
-
-RotateState
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-               /* Calculate w[t-15] ror 8 */
-               vpsrlq          YTMP2, YTMP1, 8
-               vpsllq          YTMP1, YTMP1, (64-8)
-               vpor            YTMP1, YTMP1, YTMP2             /* YTMP1 = W[-15] ror 8 */
-               /* XOR the three components */
-               vpxor           YTMP3, YTMP3, YTMP4             /* YTMP3 = W[-15] ror 1 ^ W[-15] >> 7 */
-               vpxor           YTMP1, YTMP3, YTMP1             /* YTMP1 = s0 */
-
-
-               /* Add three components, w[t-16], w[t-7] and sigma0 */
-               vpaddq          YTMP0, YTMP0, YTMP1             /* YTMP0 = W[-16] + W[-7] + s0 */
-               /* Move to appropriate lanes for calculating w[16] and w[17] */
-               vperm2f128      Y_0, YTMP0, YTMP0, 0x0          /* Y_0 = W[-16] + W[-7] + s0 {BABA} */
-               /* Move to appropriate lanes for calculating w[18] and w[19] */
-               vpand           YTMP0, YTMP0, [.LMASK_YMM_LO ADD_RIP]   /* YTMP0 = W[-16] + W[-7] + s0 {DC00} */
-
-               /* Calculate w[16] and w[17] in both 128 bit lanes */
-
-               /* Calculate sigma1 for w[16] and w[17] on both 128 bit lanes */
-               vperm2f128      YTMP2, Y_3, Y_3, 0x11           /* YTMP2 = W[-2] {BABA} */
-               vpsrlq          YTMP4, YTMP2, 6                 /* YTMP4 = W[-2] >> 6 {BABA} */
-
-
-       mov     y3, a           /* y3 = a                                       ; MAJA   */
-       rorx    y0, e, 41       /* y0 = e >> 41                                 ; S1A */
-       rorx    y1, e, 18       /* y1 = e >> 18                                 ; S1B */
-       add     h, [rsp+frame_XFER+1*8]         /* h = k + w + h                                ; --     */
-       or      y3, c           /* y3 = a|c                                     ; MAJA   */
-
-
-       mov     y2, f           /* y2 = f                                       ; CH     */
-       rorx    T1, a, 34       /* T1 = a >> 34                                 ; S0B */
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18)                       ; S1 */
-       xor     y2, g           /* y2 = f^g                                     ; CH     */
-
-
-       rorx    y1, e, 14       /* y1 = (e >> 14)                                       ; S1 */
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18) ^ (e>>14)             ; S1 */
-       rorx    y1, a, 39       /* y1 = a >> 39                                 ; S0A */
-       and     y2, e           /* y2 = (f^g)&e                                 ; CH     */
-       add     d, h            /* d = k + w + h + d                            ; --     */
-
-       and     y3, b           /* y3 = (a|c)&b                                 ; MAJA   */
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34)                       ; S0 */
-
-       rorx    T1, a, 28       /* T1 = (a >> 28)                                       ; S0 */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g                        ; CH     */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34) ^ (a>>28)             ; S0 */
-       mov     T1, a           /* T1 = a                                       ; MAJB   */
-       and     T1, c           /* T1 = a&c                                     ; MAJB   */
-       add     y2, y0          /* y2 = S1 + CH                                 ; --     */
-
-       or      y3, T1          /* y3 = MAJ = (a|c)&b)|(a&c)                    ; MAJ    */
-       add     h, y1           /* h = k + w + h + S0                           ; --     */
-
-       add     d, y2           /* d = k + w + h + d + S1 + CH = d + t1         ; --     */
-       add     h, y2           /* h = k + w + h + S0 + S1 + CH = t1 + S0       ; --     */
-       add     h, y3           /* h = t1 + S0 + MAJ                            ; --     */
-
-RotateState
-
-
-
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-
-               vpsrlq          YTMP3, YTMP2, 19                /* YTMP3 = W[-2] >> 19 {BABA} */
-               vpsllq          YTMP1, YTMP2, (64-19)           /* YTMP1 = W[-2] << 19 {BABA} */
-               vpor            YTMP3, YTMP3, YTMP1             /* YTMP3 = W[-2] ror 19 {BABA} */
-               vpxor           YTMP4, YTMP4, YTMP3             /* YTMP4 = W[-2] ror 19 ^ W[-2] >> 6 {BABA} */
-               vpsrlq          YTMP3, YTMP2, 61                /* YTMP3 = W[-2] >> 61 {BABA} */
-               vpsllq          YTMP1, YTMP2, (64-61)           /* YTMP1 = W[-2] << 61 {BABA} */
-               vpor            YTMP3, YTMP3, YTMP1             /* YTMP3 = W[-2] ror 61 {BABA} */
-               vpxor           YTMP4, YTMP4, YTMP3             /* YTMP4 = s1 = (W[-2] ror 19) ^ (W[-2] ror 61) ^ (W[-2] >> 6) {BABA} */
-
-               /* Add sigma1 to the other compunents to get w[16] and w[17] */
-               vpaddq          Y_0, Y_0, YTMP4                 /* Y_0 = {W[1], W[0], W[1], W[0]} */
-
-               /* Calculate sigma1 for w[18] and w[19] for upper 128 bit lane */
-               vpsrlq          YTMP4, Y_0, 6                   /* YTMP4 = W[-2] >> 6 {DC--} */
-
-       mov     y3, a           /* y3 = a                                       ; MAJA   */
-       rorx    y0, e, 41       /* y0 = e >> 41                                 ; S1A */
-       add     h, [rsp+frame_XFER+2*8]         /* h = k + w + h                                ; --     */
-
-       rorx    y1, e, 18       /* y1 = e >> 18                                 ; S1B */
-       or      y3, c           /* y3 = a|c                                     ; MAJA   */
-       mov     y2, f           /* y2 = f                                       ; CH     */
-       xor     y2, g           /* y2 = f^g                                     ; CH     */
-
-       rorx    T1, a, 34       /* T1 = a >> 34                                 ; S0B */
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18)                       ; S1 */
-       and     y2, e           /* y2 = (f^g)&e                                 ; CH     */
-
-       rorx    y1, e, 14       /* y1 = (e >> 14)                                       ; S1 */
-       add     d, h            /* d = k + w + h + d                            ; --     */
-       and     y3, b           /* y3 = (a|c)&b                                 ; MAJA   */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18) ^ (e>>14)             ; S1 */
-       rorx    y1, a, 39       /* y1 = a >> 39                                 ; S0A */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g                        ; CH     */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34)                       ; S0 */
-       rorx    T1, a, 28       /* T1 = (a >> 28)                                       ; S0 */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34) ^ (a>>28)             ; S0 */
-       mov     T1, a           /* T1 = a                                       ; MAJB   */
-       and     T1, c           /* T1 = a&c                                     ; MAJB   */
-       add     y2, y0          /* y2 = S1 + CH                                 ; --     */
-
-       or      y3, T1          /* y3 = MAJ = (a|c)&b)|(a&c)                    ; MAJ    */
-       add     h, y1           /* h = k + w + h + S0                           ; --     */
-       add     d, y2           /* d = k + w + h + d + S1 + CH = d + t1         ; --     */
-       add     h, y2           /* h = k + w + h + S0 + S1 + CH = t1 + S0       ; --     */
-
-       add     h, y3           /* h = t1 + S0 + MAJ                            ; --     */
-
-RotateState
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-               vpsrlq          YTMP3, Y_0, 19                  /* YTMP3 = W[-2] >> 19 {DC--} */
-               vpsllq          YTMP1, Y_0, (64-19)             /* YTMP1 = W[-2] << 19 {DC--} */
-               vpor            YTMP3, YTMP3, YTMP1             /* YTMP3 = W[-2] ror 19 {DC--} */
-               vpxor           YTMP4, YTMP4, YTMP3             /* YTMP4 = W[-2] ror 19 ^ W[-2] >> 6 {DC--} */
-               vpsrlq          YTMP3, Y_0, 61                  /* YTMP3 = W[-2] >> 61 {DC--} */
-               vpsllq          YTMP1, Y_0, (64-61)             /* YTMP1 = W[-2] << 61 {DC--} */
-               vpor            YTMP3, YTMP3, YTMP1             /* YTMP3 = W[-2] ror 61 {DC--} */
-               vpxor           YTMP4, YTMP4, YTMP3             /* YTMP4 = s1 = (W[-2] ror 19) ^ (W[-2] ror 61) ^ (W[-2] >> 6) {DC--} */
-
-               /* Add the sigma0 + w[t-7] + w[t-16] for w[18] and w[19] to newly calculated sigma1 to get w[18] and w[19] */
-               vpaddq          YTMP2, YTMP0, YTMP4             /* YTMP2 = {W[3], W[2], --, --} */
-
-               /* Form w[19, w[18], w17], w[16] */
-               vpblendd                Y_0, Y_0, YTMP2, 0xF0           /* Y_0 = {W[3], W[2], W[1], W[0]} */
-/*             vperm2f128              Y_0, Y_0, YTMP2, 0x30 */
-
-       mov     y3, a           /* y3 = a                                       ; MAJA   */
-       rorx    y0, e, 41       /* y0 = e >> 41                                 ; S1A */
-       rorx    y1, e, 18       /* y1 = e >> 18                                 ; S1B */
-       add     h, [rsp+frame_XFER+3*8]         /* h = k + w + h                                ; --     */
-       or      y3, c           /* y3 = a|c                                     ; MAJA   */
-
-
-       mov     y2, f           /* y2 = f                                       ; CH     */
-       rorx    T1, a, 34       /* T1 = a >> 34                                 ; S0B */
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18)                       ; S1 */
-       xor     y2, g           /* y2 = f^g                                     ; CH     */
-
-
-       rorx    y1, e, 14       /* y1 = (e >> 14)                                       ; S1 */
-       and     y2, e           /* y2 = (f^g)&e                                 ; CH     */
-       add     d, h            /* d = k + w + h + d                            ; --     */
-       and     y3, b           /* y3 = (a|c)&b                                 ; MAJA   */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18) ^ (e>>14)             ; S1 */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g                        ; CH     */
-
-       rorx    y1, a, 39       /* y1 = a >> 39                                 ; S0A */
-       add     y2, y0          /* y2 = S1 + CH                                 ; --     */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34)                       ; S0 */
-       add     d, y2           /* d = k + w + h + d + S1 + CH = d + t1         ; --     */
-
-       rorx    T1, a, 28       /* T1 = (a >> 28)                                       ; S0 */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34) ^ (a>>28)             ; S0 */
-       mov     T1, a           /* T1 = a                                       ; MAJB   */
-       and     T1, c           /* T1 = a&c                                     ; MAJB   */
-       or      y3, T1          /* y3 = MAJ = (a|c)&b)|(a&c)                    ; MAJ    */
-
-       add     h, y1           /* h = k + w + h + S0                           ; --     */
-       add     h, y2           /* h = k + w + h + S0 + S1 + CH = t1 + S0       ; --     */
-       add     h, y3           /* h = t1 + S0 + MAJ                            ; --     */
-
-RotateState
-
-rotate_Ys
-.endm
-
-.macro DO_4ROUNDS
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       mov     y2, f           /* y2 = f                                       ; CH     */
-       rorx    y0, e, 41       /* y0 = e >> 41                                 ; S1A */
-       rorx    y1, e, 18       /* y1 = e >> 18                                 ; S1B */
-       xor     y2, g           /* y2 = f^g                                     ; CH     */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18)                       ; S1 */
-       rorx    y1, e, 14       /* y1 = (e >> 14)                                       ; S1 */
-       and     y2, e           /* y2 = (f^g)&e                                 ; CH     */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18) ^ (e>>14)             ; S1 */
-       rorx    T1, a, 34       /* T1 = a >> 34                                 ; S0B */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g                        ; CH     */
-       rorx    y1, a, 39       /* y1 = a >> 39                                 ; S0A */
-       mov     y3, a           /* y3 = a                                       ; MAJA   */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34)                       ; S0 */
-       rorx    T1, a, 28       /* T1 = (a >> 28)                                       ; S0 */
-       add     h, [rsp + frame_XFER + 8*0]             /* h = k + w + h                                ; --     */
-       or      y3, c           /* y3 = a|c                                     ; MAJA   */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34) ^ (a>>28)             ; S0 */
-       mov     T1, a           /* T1 = a                                       ; MAJB   */
-       and     y3, b           /* y3 = (a|c)&b                                 ; MAJA   */
-       and     T1, c           /* T1 = a&c                                     ; MAJB   */
-       add     y2, y0          /* y2 = S1 + CH                                 ; --     */
-
-
-       add     d, h            /* d = k + w + h + d                            ; --     */
-       or      y3, T1          /* y3 = MAJ = (a|c)&b)|(a&c)                    ; MAJ    */
-       add     h, y1           /* h = k + w + h + S0                           ; --     */
-
-       add     d, y2           /* d = k + w + h + d + S1 + CH = d + t1         ; --     */
-
-
-       /*add   h, y2           ; h = k + w + h + S0 + S1 + CH = t1 + S0       ; --      */
-
-       /*add   h, y3           ; h = t1 + S0 + MAJ                            ; --      */
-
-       RotateState
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       add     old_h, y2       /* h = k + w + h + S0 + S1 + CH = t1 + S0       ; --     */
-       mov     y2, f           /* y2 = f                                       ; CH     */
-       rorx    y0, e, 41       /* y0 = e >> 41                                 ; S1A */
-       rorx    y1, e, 18       /* y1 = e >> 18                                 ; S1B */
-       xor     y2, g           /* y2 = f^g                                     ; CH     */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18)                       ; S1 */
-       rorx    y1, e, 14       /* y1 = (e >> 14)                                       ; S1 */
-       and     y2, e           /* y2 = (f^g)&e                                 ; CH     */
-       add     old_h, y3       /* h = t1 + S0 + MAJ                            ; --     */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18) ^ (e>>14)             ; S1 */
-       rorx    T1, a, 34       /* T1 = a >> 34                                 ; S0B */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g                        ; CH     */
-       rorx    y1, a, 39       /* y1 = a >> 39                                 ; S0A */
-       mov     y3, a           /* y3 = a                                       ; MAJA   */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34)                       ; S0 */
-       rorx    T1, a, 28       /* T1 = (a >> 28)                                       ; S0 */
-       add     h, [rsp + frame_XFER + 8*1]             /* h = k + w + h                                ; --     */
-       or      y3, c           /* y3 = a|c                                     ; MAJA   */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34) ^ (a>>28)             ; S0 */
-       mov     T1, a           /* T1 = a                                       ; MAJB   */
-       and     y3, b           /* y3 = (a|c)&b                                 ; MAJA   */
-       and     T1, c           /* T1 = a&c                                     ; MAJB   */
-       add     y2, y0          /* y2 = S1 + CH                                 ; --     */
-
-
-       add     d, h            /* d = k + w + h + d                            ; --     */
-       or      y3, T1          /* y3 = MAJ = (a|c)&b)|(a&c)                    ; MAJ    */
-       add     h, y1           /* h = k + w + h + S0                           ; --     */
-
-       add     d, y2           /* d = k + w + h + d + S1 + CH = d + t1         ; --     */
-
-
-       /*add   h, y2           ; h = k + w + h + S0 + S1 + CH = t1 + S0       ; --      */
-
-       /*add   h, y3           ; h = t1 + S0 + MAJ                            ; --      */
-
-       RotateState
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       add     old_h, y2               /* h = k + w + h + S0 + S1 + CH = t1 + S0       ; --     */
-       mov     y2, f           /* y2 = f                                       ; CH     */
-       rorx    y0, e, 41       /* y0 = e >> 41                                 ; S1A */
-       rorx    y1, e, 18       /* y1 = e >> 18                                 ; S1B */
-       xor     y2, g           /* y2 = f^g                                     ; CH     */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18)                       ; S1 */
-       rorx    y1, e, 14       /* y1 = (e >> 14)                                       ; S1 */
-       and     y2, e           /* y2 = (f^g)&e                                 ; CH     */
-       add     old_h, y3       /* h = t1 + S0 + MAJ                            ; --     */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18) ^ (e>>14)             ; S1 */
-       rorx    T1, a, 34       /* T1 = a >> 34                                 ; S0B */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g                        ; CH     */
-       rorx    y1, a, 39       /* y1 = a >> 39                                 ; S0A */
-       mov     y3, a           /* y3 = a                                       ; MAJA   */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34)                       ; S0 */
-       rorx    T1, a, 28       /* T1 = (a >> 28)                                       ; S0 */
-       add     h, [rsp + frame_XFER + 8*2]             /* h = k + w + h                                ; --     */
-       or      y3, c           /* y3 = a|c                                     ; MAJA   */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34) ^ (a>>28)             ; S0 */
-       mov     T1, a           /* T1 = a                                       ; MAJB   */
-       and     y3, b           /* y3 = (a|c)&b                                 ; MAJA   */
-       and     T1, c           /* T1 = a&c                                     ; MAJB   */
-       add     y2, y0          /* y2 = S1 + CH                                 ; --     */
-
-
-       add     d, h            /* d = k + w + h + d                            ; --     */
-       or      y3, T1          /* y3 = MAJ = (a|c)&b)|(a&c)                    ; MAJ    */
-       add     h, y1           /* h = k + w + h + S0                           ; --     */
-
-       add     d, y2           /* d = k + w + h + d + S1 + CH = d + t1         ; --     */
-
-
-       /*add   h, y2           ; h = k + w + h + S0 + S1 + CH = t1 + S0       ; --      */
-
-       /*add   h, y3           ; h = t1 + S0 + MAJ                            ; --      */
-
-       RotateState
-
-/*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
-
-       add     old_h, y2               /* h = k + w + h + S0 + S1 + CH = t1 + S0       ; --     */
-       mov     y2, f           /* y2 = f                                       ; CH     */
-       rorx    y0, e, 41       /* y0 = e >> 41                                 ; S1A */
-       rorx    y1, e, 18       /* y1 = e >> 18                                 ; S1B */
-       xor     y2, g           /* y2 = f^g                                     ; CH     */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18)                       ; S1 */
-       rorx    y1, e, 14       /* y1 = (e >> 14)                                       ; S1 */
-       and     y2, e           /* y2 = (f^g)&e                                 ; CH     */
-       add     old_h, y3       /* h = t1 + S0 + MAJ                            ; --     */
-
-       xor     y0, y1          /* y0 = (e>>41) ^ (e>>18) ^ (e>>14)             ; S1 */
-       rorx    T1, a, 34       /* T1 = a >> 34                                 ; S0B */
-       xor     y2, g           /* y2 = CH = ((f^g)&e)^g                        ; CH     */
-       rorx    y1, a, 39       /* y1 = a >> 39                                 ; S0A */
-       mov     y3, a           /* y3 = a                                       ; MAJA   */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34)                       ; S0 */
-       rorx    T1, a, 28       /* T1 = (a >> 28)                                       ; S0 */
-       add     h, [rsp + frame_XFER + 8*3]             /* h = k + w + h                                ; --     */
-       or      y3, c           /* y3 = a|c                                     ; MAJA   */
-
-       xor     y1, T1          /* y1 = (a>>39) ^ (a>>34) ^ (a>>28)             ; S0 */
-       mov     T1, a           /* T1 = a                                       ; MAJB   */
-       and     y3, b           /* y3 = (a|c)&b                                 ; MAJA   */
-       and     T1, c           /* T1 = a&c                                     ; MAJB   */
-       add     y2, y0          /* y2 = S1 + CH                                 ; --     */
-
-
-       add     d, h            /* d = k + w + h + d                            ; --     */
-       or      y3, T1          /* y3 = MAJ = (a|c)&b)|(a&c)                    ; MAJ    */
-       add     h, y1           /* h = k + w + h + S0                           ; --     */
-
-       add     d, y2           /* d = k + w + h + d + S1 + CH = d + t1         ; --     */
-
-
-       add     h, y2           /* h = k + w + h + S0 + S1 + CH = t1 + S0       ; --     */
-
-       add     h, y3           /* h = t1 + S0 + MAJ                            ; --     */
-
-       RotateState
-
-.endm
+#define MY_VPALIGNR(YDST, YSRC1, YSRC2, RVAL) \
+       vperm2i128 YDST, YSRC1, YSRC2, 0x3 /* YDST = {YS1_LO, YS2_HI} */; \
+       vpalignr   YDST, YDST, YSRC2, RVAL /* YDST = {YDS1, YS2} >> RVAL*8 */
+
+#define ONE_ROUND_PART1(XFERIN, a, b, c, d, e, f, g, h) \
+       /* h += Sum1 (e) + Ch (e, f, g) + (k[t] + w[0]); \
+        * d += h; \
+        * h += Sum0 (a) + Maj (a, b, c); \
+        * \
+        * Ch(x, y, z) => ((x & y) + (~x & z)) \
+        * Maj(x, y, z) => ((x & y) + (z & (x ^ y))) \
+        */ \
+       \
+       mov y3, e; \
+       add h, [XFERIN]; \
+       and y3, f; \
+       rorx y0, e, 41; \
+       rorx y1, e, 18; \
+       lea h, [h + y3]; \
+       andn y3, e, g; \
+       rorx T1, a, 34; \
+       xor y0, y1; \
+       lea h, [h + y3]
+
+#define ONE_ROUND_PART2(a, b, c, d, e, f, g, h) \
+       rorx y2, a, 39; \
+       rorx y1, e, 14; \
+       mov y3, a; \
+       xor T1, y2; \
+       xor y0, y1; \
+       xor y3, b; \
+       lea h, [h + y0]; \
+       mov y0, a; \
+       rorx y2, a, 28; \
+       add d, h; \
+       and y3, c; \
+       xor T1, y2; \
+       lea h, [h + y3]; \
+       lea h, [h + T1]; \
+       and y0, b; \
+       lea h, [h + y0]
+
+#define ONE_ROUND(XFERIN, a, b, c, d, e, f, g, h) \
+       ONE_ROUND_PART1(XFERIN, a, b, c, d, e, f, g, h); \
+       ONE_ROUND_PART2(a, b, c, d, e, f, g, h)
+
+#define FOUR_ROUNDS_AND_SCHED(X, Y_0, Y_1, Y_2, Y_3, a, b, c, d, e, f, g, h) \
+       /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */; \
+               /* Extract w[t-7] */; \
+               MY_VPALIGNR(    YTMP0, Y_3, Y_2, 8)             /* YTMP0 = W[-7] */; \
+               /* Calculate w[t-16] + w[t-7] */; \
+               vpaddq          YTMP0, YTMP0, Y_0               /* YTMP0 = W[-7] + W[-16] */; \
+               /* Extract w[t-15] */; \
+               MY_VPALIGNR(    YTMP1, Y_1, Y_0, 8)             /* YTMP1 = W[-15] */; \
+               \
+               /* Calculate sigma0 */; \
+               \
+               /* Calculate w[t-15] ror 1 */; \
+               vpsrlq          YTMP2, YTMP1, 1; \
+               vpsllq          YTMP3, YTMP1, (64-1); \
+               vpor            YTMP3, YTMP3, YTMP2             /* YTMP3 = W[-15] ror 1 */; \
+               /* Calculate w[t-15] shr 7 */; \
+               vpsrlq          YTMP4, YTMP1, 7                 /* YTMP4 = W[-15] >> 7 */; \
+       \
+       ONE_ROUND(rsp+frame_XFER+0*8+X*32, a, b, c, d, e, f, g, h); \
+       \
+       /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */; \
+               /* Calculate w[t-15] ror 8 */; \
+               vpsrlq          YTMP2, YTMP1, 8; \
+               vpsllq          YTMP1, YTMP1, (64-8); \
+               vpor            YTMP1, YTMP1, YTMP2             /* YTMP1 = W[-15] ror 8 */; \
+               /* XOR the three components */; \
+               vpxor           YTMP3, YTMP3, YTMP4             /* YTMP3 = W[-15] ror 1 ^ W[-15] >> 7 */; \
+               vpxor           YTMP1, YTMP3, YTMP1             /* YTMP1 = s0 */; \
+               \
+               /* Add three components, w[t-16], w[t-7] and sigma0 */; \
+               vpaddq          YTMP0, YTMP0, YTMP1             /* YTMP0 = W[-16] + W[-7] + s0 */; \
+               /* Move to appropriate lanes for calculating w[16] and w[17] */; \
+               vperm2i128      Y_0, YTMP0, YTMP0, 0x0          /* Y_0 = W[-16] + W[-7] + s0 {BABA} */; \
+               /* Move to appropriate lanes for calculating w[18] and w[19] */; \
+               vpand           YTMP0, YTMP0, MASK_YMM_LO       /* YTMP0 = W[-16] + W[-7] + s0 {DC00} */; \
+               \
+               /* Calculate w[16] and w[17] in both 128 bit lanes */; \
+               \
+               /* Calculate sigma1 for w[16] and w[17] on both 128 bit lanes */; \
+               vperm2i128      YTMP2, Y_3, Y_3, 0x11           /* YTMP2 = W[-2] {BABA} */; \
+               vpsrlq          YTMP4, YTMP2, 6                 /* YTMP4 = W[-2] >> 6 {BABA} */; \
+       \
+       ONE_ROUND(rsp+frame_XFER+1*8+X*32, h, a, b, c, d, e, f, g); \
+       \
+       /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */; \
+               vpsrlq          YTMP3, YTMP2, 19                /* YTMP3 = W[-2] >> 19 {BABA} */; \
+               vpsllq          YTMP1, YTMP2, (64-19)           /* YTMP1 = W[-2] << 19 {BABA} */; \
+               vpor            YTMP3, YTMP3, YTMP1             /* YTMP3 = W[-2] ror 19 {BABA} */; \
+               vpxor           YTMP4, YTMP4, YTMP3             /* YTMP4 = W[-2] ror 19 ^ W[-2] >> 6 {BABA} */; \
+               vpsrlq          YTMP3, YTMP2, 61                /* YTMP3 = W[-2] >> 61 {BABA} */; \
+               vpsllq          YTMP1, YTMP2, (64-61)           /* YTMP1 = W[-2] << 61 {BABA} */; \
+               vpor            YTMP3, YTMP3, YTMP1             /* YTMP3 = W[-2] ror 61 {BABA} */; \
+               vpxor           YTMP4, YTMP4, YTMP3             /* YTMP4 = s1 = (W[-2] ror 19) ^ (W[-2] ror 61) ^ (W[-2] >> 6) {BABA} */; \
+               \
+               /* Add sigma1 to the other compunents to get w[16] and w[17] */; \
+               vpaddq          Y_0, Y_0, YTMP4                 /* Y_0 = {W[1], W[0], W[1], W[0]} */; \
+               \
+               /* Calculate sigma1 for w[18] and w[19] for upper 128 bit lane */; \
+               vpsrlq          YTMP4, Y_0, 6                   /* YTMP4 = W[-2] >> 6 {DC--} */; \
+       \
+       ONE_ROUND(rsp+frame_XFER+2*8+X*32, g, h, a, b, c, d, e, f); \
+       \
+       /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RND N + 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */; \
+               vpsrlq          YTMP3, Y_0, 19                  /* YTMP3 = W[-2] >> 19 {DC--} */; \
+               vpsllq          YTMP1, Y_0, (64-19)             /* YTMP1 = W[-2] << 19 {DC--} */; \
+               vpor            YTMP3, YTMP3, YTMP1             /* YTMP3 = W[-2] ror 19 {DC--} */; \
+               vpxor           YTMP4, YTMP4, YTMP3             /* YTMP4 = W[-2] ror 19 ^ W[-2] >> 6 {DC--} */; \
+               vpsrlq          YTMP3, Y_0, 61                  /* YTMP3 = W[-2] >> 61 {DC--} */; \
+               vpsllq          YTMP1, Y_0, (64-61)             /* YTMP1 = W[-2] << 61 {DC--} */; \
+               vpor            YTMP3, YTMP3, YTMP1             /* YTMP3 = W[-2] ror 61 {DC--} */; \
+               vpxor           YTMP4, YTMP4, YTMP3             /* YTMP4 = s1 = (W[-2] ror 19) ^ (W[-2] ror 61) ^ (W[-2] >> 6) {DC--} */; \
+               \
+               /* Add the sigma0 + w[t-7] + w[t-16] for w[18] and w[19] to newly calculated sigma1 to get w[18] and w[19] */; \
+               vpaddq          YTMP2, YTMP0, YTMP4             /* YTMP2 = {W[3], W[2], --, --} */; \
+               \
+               /* Form w[19, w[18], w17], w[16] */; \
+               vpblendd        Y_0, Y_0, YTMP2, 0xF0           /* Y_0 = {W[3], W[2], W[1], W[0]} */; \
+       \
+       ONE_ROUND_PART1(rsp+frame_XFER+3*8+X*32, f, g, h, a, b, c, d, e); \
+               vpaddq          XFER, Y_0, [TBL + (4+X)*32]; \
+               vmovdqa         [rsp + frame_XFER + X*32], XFER; \
+       ONE_ROUND_PART2(f, g, h, a, b, c, d, e)
+
+#define DO_4ROUNDS(X, a, b, c, d, e, f, g, h) \
+       ONE_ROUND(rsp+frame_XFER+0*8+X*32, a, b, c, d, e, f, g, h); \
+       ONE_ROUND(rsp+frame_XFER+1*8+X*32, h, a, b, c, d, e, f, g); \
+       ONE_ROUND(rsp+frame_XFER+2*8+X*32, g, h, a, b, c, d, e, f); \
+       ONE_ROUND(rsp+frame_XFER+3*8+X*32, f, g, h, a, b, c, d, e)
 
 /*
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -606,6 +276,7 @@ rotate_Ys
 ELF(.type _gcry_sha512_transform_amd64_avx2,@function;)
 .align 16
 _gcry_sha512_transform_amd64_avx2:
+       CFI_STARTPROC()
        xor eax, eax
 
        cmp rdx, 0
@@ -615,9 +286,11 @@ _gcry_sha512_transform_amd64_avx2:
 
        /* Allocate Stack Space */
        mov     rax, rsp
+       CFI_DEF_CFA_REGISTER(rax);
        sub     rsp, frame_size
-       and     rsp, ~(0x20 - 1)
+       and     rsp, ~(0x40 - 1)
        mov     [rsp + frame_RSPSAVE], rax
+       CFI_CFA_ON_STACK(frame_RSPSAVE, 0)
 
        /* Save GPRs */
        mov     [rsp + frame_GPRSAVE + 8 * 0], rbp
@@ -626,14 +299,14 @@ _gcry_sha512_transform_amd64_avx2:
        mov     [rsp + frame_GPRSAVE + 8 * 3], r13
        mov     [rsp + frame_GPRSAVE + 8 * 4], r14
        mov     [rsp + frame_GPRSAVE + 8 * 5], r15
+       CFI_REG_ON_STACK(rbp, frame_GPRSAVE + 8 * 0)
+       CFI_REG_ON_STACK(rbx, frame_GPRSAVE + 8 * 1)
+       CFI_REG_ON_STACK(r12, frame_GPRSAVE + 8 * 2)
+       CFI_REG_ON_STACK(r13, frame_GPRSAVE + 8 * 3)
+       CFI_REG_ON_STACK(r14, frame_GPRSAVE + 8 * 4)
+       CFI_REG_ON_STACK(r15, frame_GPRSAVE + 8 * 5)
 
-       vpblendd        xmm0, xmm0, xmm1, 0xf0
-       vpblendd        ymm0, ymm0, ymm1, 0xf0
-
-       shl     NUM_BLKS, 7     /* convert to bytes */
-       jz      .Ldone_hash
-       add     NUM_BLKS, INP   /* pointer to end of data */
-       mov     [rsp + frame_INPEND], NUM_BLKS
+       mov     [rsp + frame_NBLKS], NUM_BLKS
 
        /*; load initial digest */
        mov     a,[8*0 + CTX]
@@ -646,74 +319,106 @@ _gcry_sha512_transform_amd64_avx2:
        mov     h,[8*7 + CTX]
 
        vmovdqa BYTE_FLIP_MASK, [.LPSHUFFLE_BYTE_FLIP_MASK ADD_RIP]
+       vmovdqa MASK_YMM_LO, [.LMASK_YMM_LO ADD_RIP]
 
-.Loop0:
        lea     TBL,[.LK512 ADD_RIP]
 
        /*; byte swap first 16 dwords */
-       COPY_YMM_AND_BSWAP      Y_0, [INP + 0*32], BYTE_FLIP_MASK
-       COPY_YMM_AND_BSWAP      Y_1, [INP + 1*32], BYTE_FLIP_MASK
-       COPY_YMM_AND_BSWAP      Y_2, [INP + 2*32], BYTE_FLIP_MASK
-       COPY_YMM_AND_BSWAP      Y_3, [INP + 3*32], BYTE_FLIP_MASK
+       COPY_YMM_AND_BSWAP(Y_0, [INP + 0*32], BYTE_FLIP_MASK)
+       COPY_YMM_AND_BSWAP(Y_1, [INP + 1*32], BYTE_FLIP_MASK)
+       COPY_YMM_AND_BSWAP(Y_2, [INP + 2*32], BYTE_FLIP_MASK)
+       COPY_YMM_AND_BSWAP(Y_3, [INP + 3*32], BYTE_FLIP_MASK)
 
+       add     INP, 128
        mov     [rsp + frame_INP], INP
 
+       vpaddq  XFER, Y_0, [TBL + 0*32]
+       vmovdqa [rsp + frame_XFER + 0*32], XFER
+       vpaddq  XFER, Y_1, [TBL + 1*32]
+       vmovdqa [rsp + frame_XFER + 1*32], XFER
+       vpaddq  XFER, Y_2, [TBL + 2*32]
+       vmovdqa [rsp + frame_XFER + 2*32], XFER
+       vpaddq  XFER, Y_3, [TBL + 3*32]
+       vmovdqa [rsp + frame_XFER + 3*32], XFER
+
        /*; schedule 64 input dwords, by doing 12 rounds of 4 each */
-       movq    [rsp + frame_SRND],4
+       mov     qword ptr [rsp + frame_SRND], 4
 
 .align 16
-.Loop1:
-       vpaddq  XFER, Y_0, [TBL + 0*32]
-       vmovdqa [rsp + frame_XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+.Loop0:
+       FOUR_ROUNDS_AND_SCHED(0, Y_0, Y_1, Y_2, Y_3, a, b, c, d, e, f, g, h)
+       FOUR_ROUNDS_AND_SCHED(1, Y_1, Y_2, Y_3, Y_0, e, f, g, h, a, b, c, d)
+       FOUR_ROUNDS_AND_SCHED(2, Y_2, Y_3, Y_0, Y_1, a, b, c, d, e, f, g, h)
+       FOUR_ROUNDS_AND_SCHED(3, Y_3, Y_0, Y_1, Y_2, e, f, g, h, a, b, c, d)
+       add     TBL, 4*32
 
-       vpaddq  XFER, Y_0, [TBL + 1*32]
-       vmovdqa [rsp + frame_XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+       sub     qword ptr [rsp + frame_SRND], 1
+       jne     .Loop0
 
-       vpaddq  XFER, Y_0, [TBL + 2*32]
-       vmovdqa [rsp + frame_XFER], XFER
-       FOUR_ROUNDS_AND_SCHED
+       sub     qword ptr [rsp + frame_NBLKS], 1
+       je      .Ldone_hash
 
-       vpaddq  XFER, Y_0, [TBL + 3*32]
-       vmovdqa [rsp + frame_XFER], XFER
-       add     TBL, 4*32
-       FOUR_ROUNDS_AND_SCHED
+       mov     INP, [rsp + frame_INP]
 
-       subq    [rsp + frame_SRND], 1
-       jne     .Loop1
+       lea     TBL,[.LK512 ADD_RIP]
 
-       movq    [rsp + frame_SRND], 2
-.Loop2:
-       vpaddq  XFER, Y_0, [TBL + 0*32]
-       vmovdqa [rsp + frame_XFER], XFER
-       DO_4ROUNDS
-       vpaddq  XFER, Y_1, [TBL + 1*32]
-       vmovdqa [rsp + frame_XFER], XFER
-       add     TBL, 2*32
-       DO_4ROUNDS
+       /* load next block and byte swap */
+       COPY_YMM_AND_BSWAP(Y_0, [INP + 0*32], BYTE_FLIP_MASK)
+       COPY_YMM_AND_BSWAP(Y_1, [INP + 1*32], BYTE_FLIP_MASK)
+       COPY_YMM_AND_BSWAP(Y_2, [INP + 2*32], BYTE_FLIP_MASK)
+       COPY_YMM_AND_BSWAP(Y_3, [INP + 3*32], BYTE_FLIP_MASK)
 
-       vmovdqa Y_0, Y_2
-       vmovdqa Y_1, Y_3
+       add     INP, 128
+       mov     [rsp + frame_INP], INP
 
-       subq    [rsp + frame_SRND], 1
-       jne     .Loop2
+       DO_4ROUNDS(0, a, b, c, d, e, f, g, h)
+       vpaddq  XFER, Y_0, [TBL + 0*32]
+       vmovdqa [rsp + frame_XFER + 0*32], XFER
+       DO_4ROUNDS(1, e, f, g, h, a, b, c, d)
+       vpaddq  XFER, Y_1, [TBL + 1*32]
+       vmovdqa [rsp + frame_XFER + 1*32], XFER
+       DO_4ROUNDS(2, a, b, c, d, e, f, g, h)
+       vpaddq  XFER, Y_2, [TBL + 2*32]
+       vmovdqa [rsp + frame_XFER + 2*32], XFER
+       DO_4ROUNDS(3, e, f, g, h, a, b, c, d)
+       vpaddq  XFER, Y_3, [TBL + 3*32]
+       vmovdqa [rsp + frame_XFER + 3*32], XFER
+
+       addm([8*0 + CTX],a)
+       addm([8*1 + CTX],b)
+       addm([8*2 + CTX],c)
+       addm([8*3 + CTX],d)
+       addm([8*4 + CTX],e)
+       addm([8*5 + CTX],f)
+       addm([8*6 + CTX],g)
+       addm([8*7 + CTX],h)
 
-       addm    [8*0 + CTX],a
-       addm    [8*1 + CTX],b
-       addm    [8*2 + CTX],c
-       addm    [8*3 + CTX],d
-       addm    [8*4 + CTX],e
-       addm    [8*5 + CTX],f
-       addm    [8*6 + CTX],g
-       addm    [8*7 + CTX],h
+       /*; schedule 64 input dwords, by doing 12 rounds of 4 each */
+       mov     qword ptr [rsp + frame_SRND],4
 
-       mov     INP, [rsp + frame_INP]
-       add     INP, 128
-       cmp     INP, [rsp + frame_INPEND]
-       jne     .Loop0
+       jmp     .Loop0
 
 .Ldone_hash:
+       vzeroall
+
+       DO_4ROUNDS(0, a, b, c, d, e, f, g, h)
+       vmovdqa [rsp + frame_XFER + 0*32], ymm0 /* burn stack */
+       DO_4ROUNDS(1, e, f, g, h, a, b, c, d)
+       vmovdqa [rsp + frame_XFER + 1*32], ymm0 /* burn stack */
+       DO_4ROUNDS(2, a, b, c, d, e, f, g, h)
+       vmovdqa [rsp + frame_XFER + 2*32], ymm0 /* burn stack */
+       DO_4ROUNDS(3, e, f, g, h, a, b, c, d)
+       vmovdqa [rsp + frame_XFER + 3*32], ymm0 /* burn stack */
+
+       addm([8*0 + CTX],a)
+       xor     eax, eax /* burn stack */
+       addm([8*1 + CTX],b)
+       addm([8*2 + CTX],c)
+       addm([8*3 + CTX],d)
+       addm([8*4 + CTX],e)
+       addm([8*5 + CTX],f)
+       addm([8*6 + CTX],g)
+       addm([8*7 + CTX],h)
 
        /* Restore GPRs */
        mov     rbp, [rsp + frame_GPRSAVE + 8 * 0]
@@ -722,15 +427,20 @@ _gcry_sha512_transform_amd64_avx2:
        mov     r13, [rsp + frame_GPRSAVE + 8 * 3]
        mov     r14, [rsp + frame_GPRSAVE + 8 * 4]
        mov     r15, [rsp + frame_GPRSAVE + 8 * 5]
+       CFI_RESTORE(rbp)
+       CFI_RESTORE(rbx)
+       CFI_RESTORE(r12)
+       CFI_RESTORE(r13)
+       CFI_RESTORE(r14)
+       CFI_RESTORE(r15)
 
        /* Restore Stack Pointer */
        mov     rsp, [rsp + frame_RSPSAVE]
+       CFI_DEF_CFA_REGISTER(rsp)
 
-       vzeroall
-
-       mov     eax, frame_size + 31
 .Lnowork:
-       ret
+       ret_spec_stop
+       CFI_ENDPROC()
 
 /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; */
 /*;; Binary Data */
diff --git a/cipher/sha512-ppc.c b/cipher/sha512-ppc.c
new file mode 100644 (file)
index 0000000..31ea25b
--- /dev/null
@@ -0,0 +1,969 @@
+/* sha512-ppc.c - PowerPC vcrypto implementation of SHA-512 transform
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#if defined(ENABLE_PPC_CRYPTO_SUPPORT) && \
+    defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+    defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC) && \
+    defined(USE_SHA512) && \
+    __GNUC__ >= 4
+
+#include <altivec.h>
+#include "bufhelp.h"
+
+
+typedef vector unsigned char vector16x_u8;
+typedef vector unsigned long long vector2x_u64;
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR          NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE   ASM_FUNC_ATTR ALWAYS_INLINE
+#define ASM_FUNC_ATTR_NOINLINE ASM_FUNC_ATTR NO_INLINE
+
+
+static const u64 K[80] =
+  {
+    U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd),
+    U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc),
+    U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019),
+    U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118),
+    U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe),
+    U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2),
+    U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1),
+    U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694),
+    U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3),
+    U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65),
+    U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483),
+    U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5),
+    U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210),
+    U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4),
+    U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725),
+    U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70),
+    U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926),
+    U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df),
+    U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8),
+    U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b),
+    U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001),
+    U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30),
+    U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910),
+    U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8),
+    U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53),
+    U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8),
+    U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb),
+    U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3),
+    U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60),
+    U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec),
+    U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9),
+    U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b),
+    U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207),
+    U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178),
+    U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6),
+    U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b),
+    U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493),
+    U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c),
+    U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a),
+    U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817)
+  };
+
+
+static ASM_FUNC_ATTR_INLINE u64
+ror64 (u64 v, u64 shift)
+{
+  return (v >> (shift & 63)) ^ (v << ((64 - shift) & 63));
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+vec_rol_elems(vector2x_u64 v, unsigned int idx)
+{
+#ifndef WORDS_BIGENDIAN
+  return vec_sld (v, v, (16 - (8 * idx)) & 15);
+#else
+  return vec_sld (v, v, (8 * idx) & 15);
+#endif
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+vec_merge_idx0_elems(vector2x_u64 v0, vector2x_u64 v1)
+{
+  return vec_mergeh (v0, v1);
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+vec_vshasigma_u64(vector2x_u64 v, unsigned int a, unsigned int b)
+{
+  __asm__ ("vshasigmad %0,%1,%2,%3"
+          : "=v" (v)
+          : "v" (v), "g" (a), "g" (b)
+          : "memory");
+  return v;
+}
+
+
+static ASM_FUNC_ATTR_INLINE vector2x_u64
+vec_u64_load(unsigned long offset, const void *ptr)
+{
+  vector2x_u64 vecu64;
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ ("lxvd2x %x0,0,%1\n\t"
+            : "=wa" (vecu64)
+            : "r" ((uintptr_t)ptr)
+            : "memory");
+  else
+#endif
+    __asm__ ("lxvd2x %x0,%1,%2\n\t"
+            : "=wa" (vecu64)
+            : "r" (offset), "r" ((uintptr_t)ptr)
+            : "memory", "r0");
+#ifndef WORDS_BIGENDIAN
+  __asm__ ("xxswapd %x0, %x1"
+          : "=wa" (vecu64)
+          : "wa" (vecu64));
+#endif
+  return vecu64;
+}
+
+
+static ASM_FUNC_ATTR_INLINE void
+vec_u64_store(vector2x_u64 vecu64, unsigned long offset, void *ptr)
+{
+#ifndef WORDS_BIGENDIAN
+  __asm__ ("xxswapd %x0, %x1"
+          : "=wa" (vecu64)
+          : "wa" (vecu64));
+#endif
+#if __GNUC__ >= 4
+  if (__builtin_constant_p (offset) && offset == 0)
+    __asm__ ("stxvd2x %x0,0,%1\n\t"
+            :
+            : "wa" (vecu64), "r" ((uintptr_t)ptr)
+            : "memory");
+  else
+#endif
+    __asm__ ("stxvd2x %x0,%1,%2\n\t"
+            :
+            : "wa" (vecu64), "r" (offset), "r" ((uintptr_t)ptr)
+            : "memory", "r0");
+}
+
+
+/* SHA2 round in vector registers */
+#define R(a,b,c,d,e,f,g,h,k,w) do                             \
+    {                                                         \
+      t1  = (h);                                              \
+      t1 += ((k) + (w));                                      \
+      t1 += Cho((e),(f),(g));                                 \
+      t1 += Sum1((e));                                        \
+      t2  = Sum0((a));                                        \
+      t2 += Maj((a),(b),(c));                                 \
+      d  += t1;                                               \
+      h   = t1 + t2;                                          \
+    } while (0)
+
+#define Cho(b, c, d)  (vec_sel(d, c, b))
+
+#define Maj(c, d, b)  (vec_sel(c, b, c ^ d))
+
+#define Sum0(x)       (vec_vshasigma_u64(x, 1, 0))
+
+#define Sum1(x)       (vec_vshasigma_u64(x, 1, 15))
+
+
+/* Message expansion on general purpose registers */
+#define S0(x) (ror64 ((x), 1) ^ ror64 ((x), 8) ^ ((x) >> 7))
+#define S1(x) (ror64 ((x), 19) ^ ror64 ((x), 61) ^ ((x) >> 6))
+
+#define I(i) ( w[i] = buf_get_be64(data + i * 8) )
+#define WN(i) ({ w[i&0x0f] +=    w[(i-7) &0x0f];  \
+                w[i&0x0f] += S0(w[(i-15)&0x0f]); \
+                w[i&0x0f] += S1(w[(i-2) &0x0f]); \
+                w[i&0x0f]; })
+#define W(i) ({ u64 r = w[i&0x0f]; WN(i); r; })
+#define L(i) w[i&0x0f]
+
+
+unsigned int ASM_FUNC_ATTR
+_gcry_sha512_transform_ppc8(u64 state[8],
+                           const unsigned char *data, size_t nblks)
+{
+  /* GPRs used for message expansion as vector intrinsics based generates
+   * slower code. */
+  vector2x_u64 h0, h1, h2, h3, h4, h5, h6, h7;
+  vector2x_u64 a, b, c, d, e, f, g, h, t1, t2;
+  u64 w[16];
+
+  h0 = vec_u64_load (8 * 0, (unsigned long long *)state);
+  h1 = vec_rol_elems (h0, 1);
+  h2 = vec_u64_load (8 * 2, (unsigned long long *)state);
+  h3 = vec_rol_elems (h2, 1);
+  h4 = vec_u64_load (8 * 4, (unsigned long long *)state);
+  h5 = vec_rol_elems (h4, 1);
+  h6 = vec_u64_load (8 * 6, (unsigned long long *)state);
+  h7 = vec_rol_elems (h6, 1);
+
+  while (nblks >= 2)
+    {
+      a = h0;
+      b = h1;
+      c = h2;
+      d = h3;
+      e = h4;
+      f = h5;
+      g = h6;
+      h = h7;
+
+      I(0); I(1); I(2); I(3);
+      I(4); I(5); I(6); I(7);
+      I(8); I(9); I(10); I(11);
+      I(12); I(13); I(14); I(15);
+      data += 128;
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W(48));
+      R(h, a, b, c, d, e, f, g, K[49], W(49));
+      R(g, h, a, b, c, d, e, f, K[50], W(50));
+      R(f, g, h, a, b, c, d, e, K[51], W(51));
+      R(e, f, g, h, a, b, c, d, K[52], W(52));
+      R(d, e, f, g, h, a, b, c, K[53], W(53));
+      R(c, d, e, f, g, h, a, b, K[54], W(54));
+      R(b, c, d, e, f, g, h, a, K[55], W(55));
+      R(a, b, c, d, e, f, g, h, K[56], W(56));
+      R(h, a, b, c, d, e, f, g, K[57], W(57));
+      R(g, h, a, b, c, d, e, f, K[58], W(58));
+      R(f, g, h, a, b, c, d, e, K[59], W(59));
+      R(e, f, g, h, a, b, c, d, K[60], W(60));
+      R(d, e, f, g, h, a, b, c, K[61], W(61));
+      R(c, d, e, f, g, h, a, b, K[62], W(62));
+      R(b, c, d, e, f, g, h, a, K[63], W(63));
+
+      R(a, b, c, d, e, f, g, h, K[64], L(64));
+      R(h, a, b, c, d, e, f, g, K[65], L(65));
+      R(g, h, a, b, c, d, e, f, K[66], L(66));
+      R(f, g, h, a, b, c, d, e, K[67], L(67));
+      I(0); I(1); I(2); I(3);
+      R(e, f, g, h, a, b, c, d, K[68], L(68));
+      R(d, e, f, g, h, a, b, c, K[69], L(69));
+      R(c, d, e, f, g, h, a, b, K[70], L(70));
+      R(b, c, d, e, f, g, h, a, K[71], L(71));
+      I(4); I(5); I(6); I(7);
+      R(a, b, c, d, e, f, g, h, K[72], L(72));
+      R(h, a, b, c, d, e, f, g, K[73], L(73));
+      R(g, h, a, b, c, d, e, f, K[74], L(74));
+      R(f, g, h, a, b, c, d, e, K[75], L(75));
+      I(8); I(9); I(10); I(11);
+      R(e, f, g, h, a, b, c, d, K[76], L(76));
+      R(d, e, f, g, h, a, b, c, K[77], L(77));
+      R(c, d, e, f, g, h, a, b, K[78], L(78));
+      R(b, c, d, e, f, g, h, a, K[79], L(79));
+      I(12); I(13); I(14); I(15);
+      data += 128;
+
+      h0 += a;
+      h1 += b;
+      h2 += c;
+      h3 += d;
+      h4 += e;
+      h5 += f;
+      h6 += g;
+      h7 += h;
+      a = h0;
+      b = h1;
+      c = h2;
+      d = h3;
+      e = h4;
+      f = h5;
+      g = h6;
+      h = h7;
+
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W(48));
+      R(h, a, b, c, d, e, f, g, K[49], W(49));
+      R(g, h, a, b, c, d, e, f, K[50], W(50));
+      R(f, g, h, a, b, c, d, e, K[51], W(51));
+      R(e, f, g, h, a, b, c, d, K[52], W(52));
+      R(d, e, f, g, h, a, b, c, K[53], W(53));
+      R(c, d, e, f, g, h, a, b, K[54], W(54));
+      R(b, c, d, e, f, g, h, a, K[55], W(55));
+      R(a, b, c, d, e, f, g, h, K[56], W(56));
+      R(h, a, b, c, d, e, f, g, K[57], W(57));
+      R(g, h, a, b, c, d, e, f, K[58], W(58));
+      R(f, g, h, a, b, c, d, e, K[59], W(59));
+      R(e, f, g, h, a, b, c, d, K[60], W(60));
+      R(d, e, f, g, h, a, b, c, K[61], W(61));
+      R(c, d, e, f, g, h, a, b, K[62], W(62));
+      R(b, c, d, e, f, g, h, a, K[63], W(63));
+
+      R(a, b, c, d, e, f, g, h, K[64], L(64));
+      R(h, a, b, c, d, e, f, g, K[65], L(65));
+      R(g, h, a, b, c, d, e, f, K[66], L(66));
+      R(f, g, h, a, b, c, d, e, K[67], L(67));
+      R(e, f, g, h, a, b, c, d, K[68], L(68));
+      R(d, e, f, g, h, a, b, c, K[69], L(69));
+      R(c, d, e, f, g, h, a, b, K[70], L(70));
+      R(b, c, d, e, f, g, h, a, K[71], L(71));
+      R(a, b, c, d, e, f, g, h, K[72], L(72));
+      R(h, a, b, c, d, e, f, g, K[73], L(73));
+      R(g, h, a, b, c, d, e, f, K[74], L(74));
+      R(f, g, h, a, b, c, d, e, K[75], L(75));
+      R(e, f, g, h, a, b, c, d, K[76], L(76));
+      R(d, e, f, g, h, a, b, c, K[77], L(77));
+      R(c, d, e, f, g, h, a, b, K[78], L(78));
+      R(b, c, d, e, f, g, h, a, K[79], L(79));
+
+      h0 += a;
+      h1 += b;
+      h2 += c;
+      h3 += d;
+      h4 += e;
+      h5 += f;
+      h6 += g;
+      h7 += h;
+
+      nblks -= 2;
+    }
+
+  while (nblks)
+    {
+      a = h0;
+      b = h1;
+      c = h2;
+      d = h3;
+      e = h4;
+      f = h5;
+      g = h6;
+      h = h7;
+
+      I(0); I(1); I(2); I(3);
+      I(4); I(5); I(6); I(7);
+      I(8); I(9); I(10); I(11);
+      I(12); I(13); I(14); I(15);
+      data += 128;
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W(48));
+      R(h, a, b, c, d, e, f, g, K[49], W(49));
+      R(g, h, a, b, c, d, e, f, K[50], W(50));
+      R(f, g, h, a, b, c, d, e, K[51], W(51));
+      R(e, f, g, h, a, b, c, d, K[52], W(52));
+      R(d, e, f, g, h, a, b, c, K[53], W(53));
+      R(c, d, e, f, g, h, a, b, K[54], W(54));
+      R(b, c, d, e, f, g, h, a, K[55], W(55));
+      R(a, b, c, d, e, f, g, h, K[56], W(56));
+      R(h, a, b, c, d, e, f, g, K[57], W(57));
+      R(g, h, a, b, c, d, e, f, K[58], W(58));
+      R(f, g, h, a, b, c, d, e, K[59], W(59));
+      R(e, f, g, h, a, b, c, d, K[60], W(60));
+      R(d, e, f, g, h, a, b, c, K[61], W(61));
+      R(c, d, e, f, g, h, a, b, K[62], W(62));
+      R(b, c, d, e, f, g, h, a, K[63], W(63));
+
+      R(a, b, c, d, e, f, g, h, K[64], L(64));
+      R(h, a, b, c, d, e, f, g, K[65], L(65));
+      R(g, h, a, b, c, d, e, f, K[66], L(66));
+      R(f, g, h, a, b, c, d, e, K[67], L(67));
+      R(e, f, g, h, a, b, c, d, K[68], L(68));
+      R(d, e, f, g, h, a, b, c, K[69], L(69));
+      R(c, d, e, f, g, h, a, b, K[70], L(70));
+      R(b, c, d, e, f, g, h, a, K[71], L(71));
+      R(a, b, c, d, e, f, g, h, K[72], L(72));
+      R(h, a, b, c, d, e, f, g, K[73], L(73));
+      R(g, h, a, b, c, d, e, f, K[74], L(74));
+      R(f, g, h, a, b, c, d, e, K[75], L(75));
+      R(e, f, g, h, a, b, c, d, K[76], L(76));
+      R(d, e, f, g, h, a, b, c, K[77], L(77));
+      R(c, d, e, f, g, h, a, b, K[78], L(78));
+      R(b, c, d, e, f, g, h, a, K[79], L(79));
+
+      h0 += a;
+      h1 += b;
+      h2 += c;
+      h3 += d;
+      h4 += e;
+      h5 += f;
+      h6 += g;
+      h7 += h;
+
+      nblks--;
+    }
+
+  h0 = vec_merge_idx0_elems (h0, h1);
+  h2 = vec_merge_idx0_elems (h2, h3);
+  h4 = vec_merge_idx0_elems (h4, h5);
+  h6 = vec_merge_idx0_elems (h6, h7);
+  vec_u64_store (h0, 8 * 0, (unsigned long long *)state);
+  vec_u64_store (h2, 8 * 2, (unsigned long long *)state);
+  vec_u64_store (h4, 8 * 4, (unsigned long long *)state);
+  vec_u64_store (h6, 8 * 6, (unsigned long long *)state);
+
+  return sizeof(w);
+}
+#undef R
+#undef Cho
+#undef Maj
+#undef Sum0
+#undef Sum1
+#undef S0
+#undef S1
+#undef I
+#undef W
+#undef I2
+#undef W2
+#undef R2
+
+
+/* SHA2 round in general purpose registers */
+#define R(a,b,c,d,e,f,g,h,k,w) do                                 \
+          {                                                       \
+            t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + ((k) + (w));\
+            t2 = Sum0((a)) + Maj((a),(b),(c));                    \
+            d += t1;                                              \
+            h  = t1 + t2;                                         \
+          } while (0)
+
+#define Cho(x, y, z)  ((x & y) + (~x & z))
+
+#define Maj(z, x, y)  ((x & y) + (z & (x ^ y)))
+
+#define Sum0(x)       (ror64(x, 28) ^ ror64(x ^ ror64(x, 39-34), 34))
+
+#define Sum1(x)       (ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41))
+
+
+/* Message expansion on general purpose registers */
+#define S0(x) (ror64 ((x), 1) ^ ror64 ((x), 8) ^ ((x) >> 7))
+#define S1(x) (ror64 ((x), 19) ^ ror64 ((x), 61) ^ ((x) >> 6))
+
+#define I(i) ( w[i] = buf_get_be64(data + i * 8) )
+#define WN(i) ({ w[i&0x0f] +=    w[(i-7) &0x0f];  \
+                w[i&0x0f] += S0(w[(i-15)&0x0f]); \
+                w[i&0x0f] += S1(w[(i-2) &0x0f]); \
+                w[i&0x0f]; })
+#define W(i) ({ u64 r = w[i&0x0f]; WN(i); r; })
+#define L(i) w[i&0x0f]
+
+
+unsigned int ASM_FUNC_ATTR
+_gcry_sha512_transform_ppc9(u64 state[8], const unsigned char *data,
+                           size_t nblks)
+{
+  /* GPRs used for round function and message expansion as vector intrinsics
+   * based generates slower code for POWER9. */
+  u64 a, b, c, d, e, f, g, h, t1, t2;
+  u64 w[16];
+
+  a = state[0];
+  b = state[1];
+  c = state[2];
+  d = state[3];
+  e = state[4];
+  f = state[5];
+  g = state[6];
+  h = state[7];
+
+  while (nblks >= 2)
+    {
+      I(0); I(1); I(2); I(3);
+      I(4); I(5); I(6); I(7);
+      I(8); I(9); I(10); I(11);
+      I(12); I(13); I(14); I(15);
+      data += 128;
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W(48));
+      R(h, a, b, c, d, e, f, g, K[49], W(49));
+      R(g, h, a, b, c, d, e, f, K[50], W(50));
+      R(f, g, h, a, b, c, d, e, K[51], W(51));
+      R(e, f, g, h, a, b, c, d, K[52], W(52));
+      R(d, e, f, g, h, a, b, c, K[53], W(53));
+      R(c, d, e, f, g, h, a, b, K[54], W(54));
+      R(b, c, d, e, f, g, h, a, K[55], W(55));
+      R(a, b, c, d, e, f, g, h, K[56], W(56));
+      R(h, a, b, c, d, e, f, g, K[57], W(57));
+      R(g, h, a, b, c, d, e, f, K[58], W(58));
+      R(f, g, h, a, b, c, d, e, K[59], W(59));
+      R(e, f, g, h, a, b, c, d, K[60], W(60));
+      R(d, e, f, g, h, a, b, c, K[61], W(61));
+      R(c, d, e, f, g, h, a, b, K[62], W(62));
+      R(b, c, d, e, f, g, h, a, K[63], W(63));
+
+      R(a, b, c, d, e, f, g, h, K[64], L(64));
+      R(h, a, b, c, d, e, f, g, K[65], L(65));
+      R(g, h, a, b, c, d, e, f, K[66], L(66));
+      R(f, g, h, a, b, c, d, e, K[67], L(67));
+      I(0); I(1); I(2); I(3);
+      R(e, f, g, h, a, b, c, d, K[68], L(68));
+      R(d, e, f, g, h, a, b, c, K[69], L(69));
+      R(c, d, e, f, g, h, a, b, K[70], L(70));
+      R(b, c, d, e, f, g, h, a, K[71], L(71));
+      I(4); I(5); I(6); I(7);
+      R(a, b, c, d, e, f, g, h, K[72], L(72));
+      R(h, a, b, c, d, e, f, g, K[73], L(73));
+      R(g, h, a, b, c, d, e, f, K[74], L(74));
+      R(f, g, h, a, b, c, d, e, K[75], L(75));
+      I(8); I(9); I(10); I(11);
+      R(e, f, g, h, a, b, c, d, K[76], L(76));
+      R(d, e, f, g, h, a, b, c, K[77], L(77));
+      R(c, d, e, f, g, h, a, b, K[78], L(78));
+      R(b, c, d, e, f, g, h, a, K[79], L(79));
+      I(12); I(13); I(14); I(15);
+      data += 128;
+
+      a += state[0];
+      b += state[1];
+      c += state[2];
+      d += state[3];
+      e += state[4];
+      f += state[5];
+      g += state[6];
+      h += state[7];
+      state[0] = a;
+      state[1] = b;
+      state[2] = c;
+      state[3] = d;
+      state[4] = e;
+      state[5] = f;
+      state[6] = g;
+      state[7] = h;
+
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W(48));
+      R(h, a, b, c, d, e, f, g, K[49], W(49));
+      R(g, h, a, b, c, d, e, f, K[50], W(50));
+      R(f, g, h, a, b, c, d, e, K[51], W(51));
+      R(e, f, g, h, a, b, c, d, K[52], W(52));
+      R(d, e, f, g, h, a, b, c, K[53], W(53));
+      R(c, d, e, f, g, h, a, b, K[54], W(54));
+      R(b, c, d, e, f, g, h, a, K[55], W(55));
+      R(a, b, c, d, e, f, g, h, K[56], W(56));
+      R(h, a, b, c, d, e, f, g, K[57], W(57));
+      R(g, h, a, b, c, d, e, f, K[58], W(58));
+      R(f, g, h, a, b, c, d, e, K[59], W(59));
+      R(e, f, g, h, a, b, c, d, K[60], W(60));
+      R(d, e, f, g, h, a, b, c, K[61], W(61));
+      R(c, d, e, f, g, h, a, b, K[62], W(62));
+      R(b, c, d, e, f, g, h, a, K[63], W(63));
+
+      R(a, b, c, d, e, f, g, h, K[64], L(64));
+      R(h, a, b, c, d, e, f, g, K[65], L(65));
+      R(g, h, a, b, c, d, e, f, K[66], L(66));
+      R(f, g, h, a, b, c, d, e, K[67], L(67));
+      R(e, f, g, h, a, b, c, d, K[68], L(68));
+      R(d, e, f, g, h, a, b, c, K[69], L(69));
+      R(c, d, e, f, g, h, a, b, K[70], L(70));
+      R(b, c, d, e, f, g, h, a, K[71], L(71));
+      R(a, b, c, d, e, f, g, h, K[72], L(72));
+      R(h, a, b, c, d, e, f, g, K[73], L(73));
+      R(g, h, a, b, c, d, e, f, K[74], L(74));
+      R(f, g, h, a, b, c, d, e, K[75], L(75));
+      R(e, f, g, h, a, b, c, d, K[76], L(76));
+      R(d, e, f, g, h, a, b, c, K[77], L(77));
+      R(c, d, e, f, g, h, a, b, K[78], L(78));
+      R(b, c, d, e, f, g, h, a, K[79], L(79));
+
+      a += state[0];
+      b += state[1];
+      c += state[2];
+      d += state[3];
+      e += state[4];
+      f += state[5];
+      g += state[6];
+      h += state[7];
+      state[0] = a;
+      state[1] = b;
+      state[2] = c;
+      state[3] = d;
+      state[4] = e;
+      state[5] = f;
+      state[6] = g;
+      state[7] = h;
+
+      nblks -= 2;
+    }
+
+  while (nblks)
+    {
+      I(0); I(1); I(2); I(3);
+      I(4); I(5); I(6); I(7);
+      I(8); I(9); I(10); I(11);
+      I(12); I(13); I(14); I(15);
+      data += 128;
+      R(a, b, c, d, e, f, g, h, K[0], W(0));
+      R(h, a, b, c, d, e, f, g, K[1], W(1));
+      R(g, h, a, b, c, d, e, f, K[2], W(2));
+      R(f, g, h, a, b, c, d, e, K[3], W(3));
+      R(e, f, g, h, a, b, c, d, K[4], W(4));
+      R(d, e, f, g, h, a, b, c, K[5], W(5));
+      R(c, d, e, f, g, h, a, b, K[6], W(6));
+      R(b, c, d, e, f, g, h, a, K[7], W(7));
+      R(a, b, c, d, e, f, g, h, K[8], W(8));
+      R(h, a, b, c, d, e, f, g, K[9], W(9));
+      R(g, h, a, b, c, d, e, f, K[10], W(10));
+      R(f, g, h, a, b, c, d, e, K[11], W(11));
+      R(e, f, g, h, a, b, c, d, K[12], W(12));
+      R(d, e, f, g, h, a, b, c, K[13], W(13));
+      R(c, d, e, f, g, h, a, b, K[14], W(14));
+      R(b, c, d, e, f, g, h, a, K[15], W(15));
+
+      R(a, b, c, d, e, f, g, h, K[16], W(16));
+      R(h, a, b, c, d, e, f, g, K[17], W(17));
+      R(g, h, a, b, c, d, e, f, K[18], W(18));
+      R(f, g, h, a, b, c, d, e, K[19], W(19));
+      R(e, f, g, h, a, b, c, d, K[20], W(20));
+      R(d, e, f, g, h, a, b, c, K[21], W(21));
+      R(c, d, e, f, g, h, a, b, K[22], W(22));
+      R(b, c, d, e, f, g, h, a, K[23], W(23));
+      R(a, b, c, d, e, f, g, h, K[24], W(24));
+      R(h, a, b, c, d, e, f, g, K[25], W(25));
+      R(g, h, a, b, c, d, e, f, K[26], W(26));
+      R(f, g, h, a, b, c, d, e, K[27], W(27));
+      R(e, f, g, h, a, b, c, d, K[28], W(28));
+      R(d, e, f, g, h, a, b, c, K[29], W(29));
+      R(c, d, e, f, g, h, a, b, K[30], W(30));
+      R(b, c, d, e, f, g, h, a, K[31], W(31));
+
+      R(a, b, c, d, e, f, g, h, K[32], W(32));
+      R(h, a, b, c, d, e, f, g, K[33], W(33));
+      R(g, h, a, b, c, d, e, f, K[34], W(34));
+      R(f, g, h, a, b, c, d, e, K[35], W(35));
+      R(e, f, g, h, a, b, c, d, K[36], W(36));
+      R(d, e, f, g, h, a, b, c, K[37], W(37));
+      R(c, d, e, f, g, h, a, b, K[38], W(38));
+      R(b, c, d, e, f, g, h, a, K[39], W(39));
+      R(a, b, c, d, e, f, g, h, K[40], W(40));
+      R(h, a, b, c, d, e, f, g, K[41], W(41));
+      R(g, h, a, b, c, d, e, f, K[42], W(42));
+      R(f, g, h, a, b, c, d, e, K[43], W(43));
+      R(e, f, g, h, a, b, c, d, K[44], W(44));
+      R(d, e, f, g, h, a, b, c, K[45], W(45));
+      R(c, d, e, f, g, h, a, b, K[46], W(46));
+      R(b, c, d, e, f, g, h, a, K[47], W(47));
+
+      R(a, b, c, d, e, f, g, h, K[48], W(48));
+      R(h, a, b, c, d, e, f, g, K[49], W(49));
+      R(g, h, a, b, c, d, e, f, K[50], W(50));
+      R(f, g, h, a, b, c, d, e, K[51], W(51));
+      R(e, f, g, h, a, b, c, d, K[52], W(52));
+      R(d, e, f, g, h, a, b, c, K[53], W(53));
+      R(c, d, e, f, g, h, a, b, K[54], W(54));
+      R(b, c, d, e, f, g, h, a, K[55], W(55));
+      R(a, b, c, d, e, f, g, h, K[56], W(56));
+      R(h, a, b, c, d, e, f, g, K[57], W(57));
+      R(g, h, a, b, c, d, e, f, K[58], W(58));
+      R(f, g, h, a, b, c, d, e, K[59], W(59));
+      R(e, f, g, h, a, b, c, d, K[60], W(60));
+      R(d, e, f, g, h, a, b, c, K[61], W(61));
+      R(c, d, e, f, g, h, a, b, K[62], W(62));
+      R(b, c, d, e, f, g, h, a, K[63], W(63));
+
+      R(a, b, c, d, e, f, g, h, K[64], L(64));
+      R(h, a, b, c, d, e, f, g, K[65], L(65));
+      R(g, h, a, b, c, d, e, f, K[66], L(66));
+      R(f, g, h, a, b, c, d, e, K[67], L(67));
+      R(e, f, g, h, a, b, c, d, K[68], L(68));
+      R(d, e, f, g, h, a, b, c, K[69], L(69));
+      R(c, d, e, f, g, h, a, b, K[70], L(70));
+      R(b, c, d, e, f, g, h, a, K[71], L(71));
+      R(a, b, c, d, e, f, g, h, K[72], L(72));
+      R(h, a, b, c, d, e, f, g, K[73], L(73));
+      R(g, h, a, b, c, d, e, f, K[74], L(74));
+      R(f, g, h, a, b, c, d, e, K[75], L(75));
+      R(e, f, g, h, a, b, c, d, K[76], L(76));
+      R(d, e, f, g, h, a, b, c, K[77], L(77));
+      R(c, d, e, f, g, h, a, b, K[78], L(78));
+      R(b, c, d, e, f, g, h, a, K[79], L(79));
+
+      a += state[0];
+      b += state[1];
+      c += state[2];
+      d += state[3];
+      e += state[4];
+      f += state[5];
+      g += state[6];
+      h += state[7];
+      state[0] = a;
+      state[1] = b;
+      state[2] = c;
+      state[3] = d;
+      state[4] = e;
+      state[5] = f;
+      state[6] = g;
+      state[7] = h;
+
+      nblks--;
+    }
+
+  return sizeof(w);
+}
+
+#endif /* ENABLE_PPC_CRYPTO_SUPPORT */
index 51193b3..9cc3089 100644 (file)
     defined(HAVE_INTEL_SYNTAX_PLATFORM_AS) && \
     defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(USE_SHA512)
 
-#ifdef __PIC__
-#  define ADD_RIP +rip
-#else
-#  define ADD_RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .intel_syntax noprefix
 
 .text
 
 /* Virtual Registers */
-msg = rdi /* ARG1 */
-digest = rsi /* ARG2 */
-msglen = rdx /* ARG3 */
-T1 = rcx
-T2 = r8
-a_64 = r9
-b_64 = r10
-c_64 = r11
-d_64 = r12
-e_64 = r13
-f_64 = r14
-g_64 = r15
-h_64 = rbx
-tmp0 = rax
+#define msg rdi /* ARG1 */
+#define digest rsi /* ARG2 */
+#define msglen rdx /* ARG3 */
+#define T1 rcx
+#define T2 r8
+#define a_64 r9
+#define b_64 r10
+#define c_64 r11
+#define d_64 r12
+#define e_64 r13
+#define f_64 r14
+#define g_64 r15
+#define h_64 rbx
+#define tmp0 rax
 
 /*
 ; Local variables (stack frame)
 ; Note: frame_size must be an odd multiple of 8 bytes to XMM align RSP
 */
-frame_W      = 0 /* Message Schedule */
-frame_W_size = (80 * 8)
-frame_WK      = ((frame_W) + (frame_W_size)) /* W[t] + K[t] | W[t+1] + K[t+1] */
-frame_WK_size = (2 * 8)
-frame_GPRSAVE      = ((frame_WK) + (frame_WK_size))
-frame_GPRSAVE_size = (5 * 8)
-frame_size = ((frame_GPRSAVE) + (frame_GPRSAVE_size))
+#define frame_W 0 /* Message Schedule */
+#define frame_W_size (80 * 8)
+#define frame_WK ((frame_W) + (frame_W_size)) /* W[t] + K[t] | W[t+1] + K[t+1] */
+#define frame_WK_size (2 * 8)
+#define frame_GPRSAVE ((frame_WK) + (frame_WK_size))
+#define frame_GPRSAVE_size (5 * 8)
+#define frame_size ((frame_GPRSAVE) + (frame_GPRSAVE_size))
 
 
 /* Useful QWORD "arrays" for simpler memory references */
@@ -103,161 +93,151 @@ frame_size = ((frame_GPRSAVE) + (frame_GPRSAVE_size))
 /* MSG, DIGEST, K_t, W_t are arrays */
 /* WK_2(t) points to 1 of 2 qwords at frame.WK depdending on t being odd/even */
 
-.macro RotateState
-       /* Rotate symbles a..h right */
-       __TMP = h_64
-       h_64 =  g_64
-       g_64 =  f_64
-       f_64 =  e_64
-       e_64 =  d_64
-       d_64 =  c_64
-       c_64 =  b_64
-       b_64 =  a_64
-       a_64 =  __TMP
-.endm
-
-.macro SHA512_Round t
-       /* Compute Round %%t */
-       mov     T1,   f_64        /* T1 = f */
-       mov     tmp0, e_64        /* tmp = e */
-       xor     T1,   g_64        /* T1 = f ^ g */
-       ror     tmp0, 23 /* 41     ; tmp = e ror 23 */
-       and     T1,   e_64        /* T1 = (f ^ g) & e */
-       xor     tmp0, e_64        /* tmp = (e ror 23) ^ e */
-       xor     T1,   g_64        /* T1 = ((f ^ g) & e) ^ g = CH(e,f,g) */
-       add     T1,   [WK_2(\t)] /* W[t] + K[t] from message scheduler */
-       ror     tmp0, 4 /* 18      ; tmp = ((e ror 23) ^ e) ror 4 */
-       xor     tmp0, e_64        /* tmp = (((e ror 23) ^ e) ror 4) ^ e */
-       mov     T2,   a_64        /* T2 = a */
-       add     T1,   h_64        /* T1 = CH(e,f,g) + W[t] + K[t] + h */
-       ror     tmp0, 14 /* 14     ; tmp = ((((e ror23)^e)ror4)^e)ror14 = S1(e) */
-       add     T1,   tmp0        /* T1 = CH(e,f,g) + W[t] + K[t] + S1(e) */
-       mov     tmp0, a_64        /* tmp = a */
-       xor     T2,   c_64        /* T2 = a ^ c */
-       and     tmp0, c_64        /* tmp = a & c */
-       and     T2,   b_64        /* T2 = (a ^ c) & b */
-       xor     T2,   tmp0        /* T2 = ((a ^ c) & b) ^ (a & c) = Maj(a,b,c) */
-       mov     tmp0, a_64        /* tmp = a */
-       ror     tmp0, 5 /* 39      ; tmp = a ror 5 */
-       xor     tmp0, a_64        /* tmp = (a ror 5) ^ a */
-       add     d_64, T1          /* e(next_state) = d + T1  */
-       ror     tmp0, 6 /* 34      ; tmp = ((a ror 5) ^ a) ror 6 */
-       xor     tmp0, a_64        /* tmp = (((a ror 5) ^ a) ror 6) ^ a */
-       lea     h_64, [T1 + T2]   /* a(next_state) = T1 + Maj(a,b,c) */
-       ror     tmp0, 28 /* 28     ; tmp = ((((a ror5)^a)ror6)^a)ror28 = S0(a) */
-       add     h_64, tmp0        /* a(next_state) = T1 + Maj(a,b,c) S0(a) */
-       RotateState
-.endm
-
-.macro SHA512_2Sched_2Round_sse t
-/*     ; Compute rounds %%t-2 and %%t-1
-       ; Compute message schedule QWORDS %%t and %%t+1
-
-       ;   Two rounds are computed based on the values for K[t-2]+W[t-2] and
-       ; K[t-1]+W[t-1] which were previously stored at WK_2 by the message
-       ; scheduler.
-       ;   The two new schedule QWORDS are stored at [W_t(%%t)] and [W_t(%%t+1)].
-       ; They are then added to their respective SHA512 constants at
-       ; [K_t(%%t)] and [K_t(%%t+1)] and stored at dqword [WK_2(%%t)]
-       ;   For brievity, the comments following vectored instructions only refer to
-       ; the first of a pair of QWORDS.
-       ; Eg. XMM2=W[t-2] really means XMM2={W[t-2]|W[t-1]}
-       ;   The computation of the message schedule and the rounds are tightly
-       ; stitched to take advantage of instruction-level parallelism.
-       ; For clarity, integer instructions (for the rounds calculation) are indented
-       ; by one tab. Vectored instructions (for the message scheduler) are indented
-       ; by two tabs. */
-
-       mov     T1, f_64
-               movdqa  xmm2, [W_t(\t-2)]  /* XMM2 = W[t-2] */
-       xor     T1,   g_64
-       and     T1,   e_64
-               movdqa  xmm0, xmm2          /* XMM0 = W[t-2] */
-       xor     T1,   g_64
-       add     T1,   [WK_2(\t)]
-               movdqu  xmm5, [W_t(\t-15)] /* XMM5 = W[t-15] */
-       mov     tmp0, e_64
-       ror     tmp0, 23 /* 41 */
-               movdqa  xmm3, xmm5          /* XMM3 = W[t-15] */
-       xor     tmp0, e_64
-       ror     tmp0, 4 /* 18 */
-               psrlq   xmm0, 61 - 19       /* XMM0 = W[t-2] >> 42 */
-       xor     tmp0, e_64
-       ror     tmp0, 14 /* 14 */
-               psrlq   xmm3, (8 - 7)       /* XMM3 = W[t-15] >> 1 */
-       add     T1,   tmp0
-       add     T1,   h_64
-               pxor    xmm0, xmm2          /* XMM0 = (W[t-2] >> 42) ^ W[t-2] */
-       mov     T2,   a_64
-       xor     T2,   c_64
-               pxor    xmm3, xmm5          /* XMM3 = (W[t-15] >> 1) ^ W[t-15] */
-       and     T2,   b_64
-       mov     tmp0, a_64
-               psrlq   xmm0, 19 - 6        /* XMM0 = ((W[t-2]>>42)^W[t-2])>>13 */
-       and     tmp0, c_64
-       xor     T2,   tmp0
-               psrlq   xmm3, (7 - 1)       /* XMM3 = ((W[t-15]>>1)^W[t-15])>>6 */
-       mov     tmp0, a_64
-       ror     tmp0, 5 /* 39 */
-               pxor    xmm0, xmm2          /* XMM0 = (((W[t-2]>>42)^W[t-2])>>13)^W[t-2] */
-       xor     tmp0, a_64
-       ror     tmp0, 6 /* 34 */
-               pxor    xmm3, xmm5          /* XMM3 = (((W[t-15]>>1)^W[t-15])>>6)^W[t-15] */
-       xor     tmp0, a_64
-       ror     tmp0, 28 /* 28 */
-               psrlq   xmm0, 6             /* XMM0 = ((((W[t-2]>>42)^W[t-2])>>13)^W[t-2])>>6 */
-       add     T2,   tmp0
-       add     d_64, T1
-               psrlq   xmm3, 1             /* XMM3 = (((W[t-15]>>1)^W[t-15])>>6)^W[t-15]>>1 */
-       lea     h_64, [T1 + T2]
-       RotateState
-               movdqa  xmm1, xmm2          /* XMM1 = W[t-2] */
-       mov     T1, f_64
-       xor     T1,   g_64
-               movdqa  xmm4, xmm5          /* XMM4 = W[t-15] */
-       and     T1,   e_64
-       xor     T1,   g_64
-               psllq   xmm1, (64 - 19) - (64 - 61) /* XMM1 = W[t-2] << 42 */
-       add     T1,   [WK_2(\t+1)]
-       mov     tmp0, e_64
-               psllq   xmm4, (64 - 1) - (64 - 8) /* XMM4 = W[t-15] << 7 */
-       ror     tmp0, 23 /* 41 */
-       xor     tmp0, e_64
-               pxor    xmm1, xmm2          /* XMM1 = (W[t-2] << 42)^W[t-2] */
-       ror     tmp0, 4 /* 18 */
-       xor     tmp0, e_64
-               pxor    xmm4, xmm5          /* XMM4 = (W[t-15]<<7)^W[t-15] */
-       ror     tmp0, 14 /* 14 */
-       add     T1,   tmp0
-               psllq   xmm1, (64 - 61)     /* XMM1 = ((W[t-2] << 42)^W[t-2])<<3 */
-       add     T1,   h_64
-       mov     T2,   a_64
-               psllq   xmm4, (64 - 8)      /* XMM4 = ((W[t-15]<<7)^W[t-15])<<56 */
-       xor     T2,   c_64
-       and     T2,   b_64
-               pxor    xmm0, xmm1          /* XMM0 = s1(W[t-2]) */
-       mov     tmp0, a_64
-       and     tmp0, c_64
-               movdqu  xmm1, [W_t(\t- 7)] /* XMM1 = W[t-7] */
-       xor     T2,   tmp0
-               pxor    xmm3, xmm4          /* XMM3 = s0(W[t-15]) */
-       mov     tmp0, a_64
-               paddq   xmm0, xmm3          /* XMM0 = s1(W[t-2]) + s0(W[t-15]) */
-       ror     tmp0, 5 /* 39 */
-               paddq   xmm0, [W_t(\t-16)] /* XMM0 = s1(W[t-2]) + s0(W[t-15]) + W[t-16] */
-       xor     tmp0, a_64
-               paddq   xmm0, xmm1          /* XMM0 = s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16] */
-       ror     tmp0, 6 /* 34 */
-               movdqa  [W_t(\t)], xmm0     /* Store scheduled qwords */
-       xor     tmp0, a_64
-               paddq   xmm0, [K_t(t)]      /* Compute W[t]+K[t] */
-       ror     tmp0, 28 /* 28 */
-               movdqa  [WK_2(t)], xmm0     /* Store W[t]+K[t] for next rounds */
-       add     T2,   tmp0
-       add     d_64, T1
-       lea     h_64, [T1 + T2]
-       RotateState
-.endm
+#define SHA512_Round(t, a, b, c, d, e, f, g, h) \
+       /* Compute Round %%t */; \
+       mov     T1,   f        /* T1 = f */; \
+       mov     tmp0, e        /* tmp = e */; \
+       xor     T1,   g        /* T1 = f ^ g */; \
+       ror     tmp0, 23 /* 41     ; tmp = e ror 23 */; \
+       and     T1,   e        /* T1 = (f ^ g) & e */; \
+       xor     tmp0, e        /* tmp = (e ror 23) ^ e */; \
+       xor     T1,   g        /* T1 = ((f ^ g) & e) ^ g = CH(e,f,g) */; \
+       add     T1,   [WK_2(t)] /* W[t] + K[t] from message scheduler */; \
+       ror     tmp0, 4 /* 18      ; tmp = ((e ror 23) ^ e) ror 4 */; \
+       xor     tmp0, e        /* tmp = (((e ror 23) ^ e) ror 4) ^ e */; \
+       mov     T2,   a        /* T2 = a */; \
+       add     T1,   h        /* T1 = CH(e,f,g) + W[t] + K[t] + h */; \
+       ror     tmp0, 14 /* 14     ; tmp = ((((e ror23)^e)ror4)^e)ror14 = S1(e) */; \
+       add     T1,   tmp0     /* T1 = CH(e,f,g) + W[t] + K[t] + S1(e) */; \
+       mov     tmp0, a        /* tmp = a */; \
+       xor     T2,   c        /* T2 = a ^ c */; \
+       and     tmp0, c        /* tmp = a & c */; \
+       and     T2,   b        /* T2 = (a ^ c) & b */; \
+       xor     T2,   tmp0     /* T2 = ((a ^ c) & b) ^ (a & c) = Maj(a,b,c) */; \
+       mov     tmp0, a        /* tmp = a */; \
+       ror     tmp0, 5 /* 39      ; tmp = a ror 5 */; \
+       xor     tmp0, a        /* tmp = (a ror 5) ^ a */; \
+       add     d, T1          /* e(next_state) = d + T1  */; \
+       ror     tmp0, 6 /* 34      ; tmp = ((a ror 5) ^ a) ror 6 */; \
+       xor     tmp0, a        /* tmp = (((a ror 5) ^ a) ror 6) ^ a */; \
+       lea     h, [T1 + T2]   /* a(next_state) = T1 + Maj(a,b,c) */; \
+       ror     tmp0, 28 /* 28     ; tmp = ((((a ror5)^a)ror6)^a)ror28 = S0(a) */; \
+       add     h, tmp0        /* a(next_state) = T1 + Maj(a,b,c) S0(a) */
+
+#define SHA512_2Sched_2Round_sse_PART1(t, a, b, c, d, e, f, g, h) \
+       /* \
+       ; Compute rounds %%t-2 and %%t-1 \
+       ; Compute message schedule QWORDS %%t and %%t+1 \
+       ; \
+       ;   Two rounds are computed based on the values for K[t-2]+W[t-2] and \
+       ; K[t-1]+W[t-1] which were previously stored at WK_2 by the message \
+       ; scheduler. \
+       ;   The two new schedule QWORDS are stored at [W_t(%%t)] and [W_t(%%t+1)]. \
+       ; They are then added to their respective SHA512 constants at \
+       ; [K_t(%%t)] and [K_t(%%t+1)] and stored at dqword [WK_2(%%t)] \
+       ;   For brievity, the comments following vectored instructions only refer to \
+       ; the first of a pair of QWORDS. \
+       ; Eg. XMM2=W[t-2] really means XMM2={W[t-2]|W[t-1]} \
+       ;   The computation of the message schedule and the rounds are tightly \
+       ; stitched to take advantage of instruction-level parallelism. \
+       ; For clarity, integer instructions (for the rounds calculation) are indented \
+       ; by one tab. Vectored instructions (for the message scheduler) are indented \
+       ; by two tabs. \
+       */ \
+       \
+       mov     T1, f; \
+               movdqa  xmm2, [W_t(t-2)]  /* XMM2 = W[t-2] */; \
+       xor     T1,   g; \
+       and     T1,   e; \
+               movdqa  xmm0, xmm2          /* XMM0 = W[t-2] */; \
+       xor     T1,   g; \
+       add     T1,   [WK_2(t)]; \
+               movdqu  xmm5, [W_t(t-15)] /* XMM5 = W[t-15] */; \
+       mov     tmp0, e; \
+       ror     tmp0, 23 /* 41 */; \
+               movdqa  xmm3, xmm5          /* XMM3 = W[t-15] */; \
+       xor     tmp0, e; \
+       ror     tmp0, 4 /* 18 */; \
+               psrlq   xmm0, 61 - 19       /* XMM0 = W[t-2] >> 42 */; \
+       xor     tmp0, e; \
+       ror     tmp0, 14 /* 14 */; \
+               psrlq   xmm3, (8 - 7)       /* XMM3 = W[t-15] >> 1 */; \
+       add     T1,   tmp0; \
+       add     T1,   h; \
+               pxor    xmm0, xmm2          /* XMM0 = (W[t-2] >> 42) ^ W[t-2] */; \
+       mov     T2,   a; \
+       xor     T2,   c; \
+               pxor    xmm3, xmm5          /* XMM3 = (W[t-15] >> 1) ^ W[t-15] */; \
+       and     T2,   b; \
+       mov     tmp0, a; \
+               psrlq   xmm0, 19 - 6        /* XMM0 = ((W[t-2]>>42)^W[t-2])>>13 */; \
+       and     tmp0, c; \
+       xor     T2,   tmp0; \
+               psrlq   xmm3, (7 - 1)       /* XMM3 = ((W[t-15]>>1)^W[t-15])>>6 */; \
+       mov     tmp0, a; \
+       ror     tmp0, 5 /* 39 */; \
+               pxor    xmm0, xmm2          /* XMM0 = (((W[t-2]>>42)^W[t-2])>>13)^W[t-2] */; \
+       xor     tmp0, a; \
+       ror     tmp0, 6 /* 34 */; \
+               pxor    xmm3, xmm5          /* XMM3 = (((W[t-15]>>1)^W[t-15])>>6)^W[t-15] */; \
+       xor     tmp0, a; \
+       ror     tmp0, 28 /* 28 */; \
+               psrlq   xmm0, 6             /* XMM0 = ((((W[t-2]>>42)^W[t-2])>>13)^W[t-2])>>6 */; \
+       add     T2,   tmp0; \
+       add     d, T1; \
+               psrlq   xmm3, 1             /* XMM3 = (((W[t-15]>>1)^W[t-15])>>6)^W[t-15]>>1 */; \
+       lea     h, [T1 + T2]
+
+#define SHA512_2Sched_2Round_sse_PART2(t, a, b, c, d, e, f, g, h) \
+               movdqa  xmm1, xmm2          /* XMM1 = W[t-2] */; \
+       mov     T1,   f; \
+       xor     T1,   g; \
+               movdqa  xmm4, xmm5          /* XMM4 = W[t-15] */; \
+       and     T1,   e; \
+       xor     T1,   g; \
+               psllq   xmm1, (64 - 19) - (64 - 61) /* XMM1 = W[t-2] << 42 */; \
+       add     T1,   [WK_2(t+1)]; \
+       mov     tmp0, e; \
+               psllq   xmm4, (64 - 1) - (64 - 8) /* XMM4 = W[t-15] << 7 */; \
+       ror     tmp0, 23 /* 41 */; \
+       xor     tmp0, e; \
+               pxor    xmm1, xmm2          /* XMM1 = (W[t-2] << 42)^W[t-2] */; \
+       ror     tmp0, 4 /* 18 */; \
+       xor     tmp0, e; \
+               pxor    xmm4, xmm5          /* XMM4 = (W[t-15]<<7)^W[t-15] */; \
+       ror     tmp0, 14 /* 14 */; \
+       add     T1,   tmp0; \
+               psllq   xmm1, (64 - 61)     /* XMM1 = ((W[t-2] << 42)^W[t-2])<<3 */; \
+       add     T1,   h; \
+       mov     T2,   a; \
+               psllq   xmm4, (64 - 8)      /* XMM4 = ((W[t-15]<<7)^W[t-15])<<56 */; \
+       xor     T2,   c; \
+       and     T2,   b; \
+               pxor    xmm0, xmm1          /* XMM0 = s1(W[t-2]) */; \
+       mov     tmp0, a; \
+       and     tmp0, c; \
+               movdqu  xmm1, [W_t(t- 7)] /* XMM1 = W[t-7] */; \
+       xor     T2,   tmp0; \
+               pxor    xmm3, xmm4          /* XMM3 = s0(W[t-15]) */; \
+       mov     tmp0, a; \
+               paddq   xmm0, xmm3          /* XMM0 = s1(W[t-2]) + s0(W[t-15]) */; \
+       ror     tmp0, 5 /* 39 */; \
+               paddq   xmm0, [W_t(t-16)] /* XMM0 = s1(W[t-2]) + s0(W[t-15]) + W[t-16] */; \
+       xor     tmp0, a; \
+               paddq   xmm0, xmm1          /* XMM0 = s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16] */; \
+       ror     tmp0, 6 /* 34 */; \
+               movdqa  [W_t(t)], xmm0     /* Store scheduled qwords */; \
+       xor     tmp0, a; \
+               paddq   xmm0, [K_t(t)]      /* Compute W[t]+K[t] */; \
+       ror     tmp0, 28 /* 28 */; \
+               movdqa  [WK_2(t)], xmm0     /* Store W[t]+K[t] for next rounds */; \
+       add     T2,   tmp0; \
+       add     d, T1; \
+       lea     h, [T1 + T2]
+
+#define SHA512_2Sched_2Round_sse(t, a, b, c, d, e, f, g, h) \
+       SHA512_2Sched_2Round_sse_PART1(t, a, b, c, d, e, f, g, h); \
+       SHA512_2Sched_2Round_sse_PART2(t, h, a, b, c, d, e, f, g)
 
 /*
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -271,6 +251,7 @@ frame_size = ((frame_GPRSAVE) + (frame_GPRSAVE_size))
 ELF(.type _gcry_sha512_transform_amd64_ssse3,@function;)
 .align 16
 _gcry_sha512_transform_amd64_ssse3:
+       CFI_STARTPROC()
        xor eax, eax
 
        cmp msglen, 0
@@ -278,6 +259,7 @@ _gcry_sha512_transform_amd64_ssse3:
 
        /* Allocate Stack Space */
        sub     rsp, frame_size
+       CFI_ADJUST_CFA_OFFSET(frame_size);
 
        /* Save GPRs */
        mov     [rsp + frame_GPRSAVE + 8 * 0], rbx
@@ -285,6 +267,11 @@ _gcry_sha512_transform_amd64_ssse3:
        mov     [rsp + frame_GPRSAVE + 8 * 2], r13
        mov     [rsp + frame_GPRSAVE + 8 * 3], r14
        mov     [rsp + frame_GPRSAVE + 8 * 4], r15
+       CFI_REL_OFFSET(rbx, frame_GPRSAVE + 8 * 0);
+       CFI_REL_OFFSET(r12, frame_GPRSAVE + 8 * 1);
+       CFI_REL_OFFSET(r13, frame_GPRSAVE + 8 * 2);
+       CFI_REL_OFFSET(r14, frame_GPRSAVE + 8 * 3);
+       CFI_REL_OFFSET(r15, frame_GPRSAVE + 8 * 4);
 
 .Lupdateblock:
 
@@ -298,37 +285,77 @@ _gcry_sha512_transform_amd64_ssse3:
        mov     g_64, [DIGEST(6)]
        mov     h_64, [DIGEST(7)]
 
-       t = 0
-       .rept 80/2 + 1
-       /* (80 rounds) / (2 rounds/iteration) + (1 iteration) */
-       /* +1 iteration because the scheduler leads hashing by 1 iteration */
-               .if t < 2
-                       /* BSWAP 2 QWORDS */
-                       movdqa  xmm1, [.LXMM_QWORD_BSWAP ADD_RIP]
-                       movdqu  xmm0, [MSG(t)]
-                       pshufb  xmm0, xmm1      /* BSWAP */
-                       movdqa  [W_t(t)], xmm0  /* Store Scheduled Pair */
-                       paddq   xmm0, [K_t(t)]  /* Compute W[t]+K[t] */
-                       movdqa  [WK_2(t)], xmm0 /* Store into WK for rounds */
-               .elseif t < 16
-                       /* BSWAP 2 QWORDS; Compute 2 Rounds */
-                       movdqu  xmm0, [MSG(t)]
-                       pshufb  xmm0, xmm1      /* BSWAP */
-                       SHA512_Round (t - 2)    /* Round t-2 */
-                       movdqa  [W_t(t)], xmm0  /* Store Scheduled Pair */
-                       paddq   xmm0, [K_t(t)]  /* Compute W[t]+K[t] */
-                       SHA512_Round (t - 1)    /* Round t-1 */
-                       movdqa  [WK_2(t)], xmm0 /* Store W[t]+K[t] into WK */
-               .elseif t < 79
-                       /* Schedule 2 QWORDS; Compute 2 Rounds */
-                       SHA512_2Sched_2Round_sse t
-               .else
-                       /* Compute 2 Rounds */
-                       SHA512_Round (t - 2)
-                       SHA512_Round (t - 1)
-               .endif
-               t = (t)+2
-       .endr
+       /* BSWAP 2 QWORDS */
+       movdqa  xmm1, [.LXMM_QWORD_BSWAP ADD_RIP]
+       movdqu  xmm0, [MSG(0)]
+       pshufb  xmm0, xmm1      /* BSWAP */
+       movdqa  [W_t(0)], xmm0  /* Store Scheduled Pair */
+       paddq   xmm0, [K_t(0)]  /* Compute W[t]+K[t] */
+       movdqa  [WK_2(0)], xmm0 /* Store into WK for rounds */
+
+       #define T_2_14(t, a, b, c, d, e, f, g, h) \
+               /* BSWAP 2 QWORDS; Compute 2 Rounds */; \
+               movdqu  xmm0, [MSG(t)]; \
+               pshufb  xmm0, xmm1      /* BSWAP */; \
+               SHA512_Round(((t) - 2), a##_64, b##_64, c##_64, d##_64, \
+                                       e##_64, f##_64, g##_64, h##_64); \
+               movdqa  [W_t(t)], xmm0  /* Store Scheduled Pair */; \
+               paddq   xmm0, [K_t(t)]  /* Compute W[t]+K[t] */; \
+               SHA512_Round(((t) - 1), h##_64, a##_64, b##_64, c##_64, \
+                                       d##_64, e##_64, f##_64, g##_64); \
+               movdqa  [WK_2(t)], xmm0 /* Store W[t]+K[t] into WK */
+
+       #define T_16_78(t, a, b, c, d, e, f, g, h) \
+               SHA512_2Sched_2Round_sse((t), a##_64, b##_64, c##_64, d##_64, \
+                                             e##_64, f##_64, g##_64, h##_64)
+
+       #define T_80(t, a, b, c, d, e, f, g, h) \
+               /* Compute 2 Rounds */; \
+               SHA512_Round((t - 2), a##_64, b##_64, c##_64, d##_64, \
+                                     e##_64, f##_64, g##_64, h##_64); \
+               SHA512_Round((t - 1), h##_64, a##_64, b##_64, c##_64, \
+                                     d##_64, e##_64, f##_64, g##_64)
+
+       T_2_14(2, a, b, c, d, e, f, g, h)
+       T_2_14(4, g, h, a, b, c, d, e, f)
+       T_2_14(6, e, f, g, h, a, b, c, d)
+       T_2_14(8, c, d, e, f, g, h, a, b)
+       T_2_14(10, a, b, c, d, e, f, g, h)
+       T_2_14(12, g, h, a, b, c, d, e, f)
+       T_2_14(14, e, f, g, h, a, b, c, d)
+       T_16_78(16, c, d, e, f, g, h, a, b)
+       T_16_78(18, a, b, c, d, e, f, g, h)
+       T_16_78(20, g, h, a, b, c, d, e, f)
+       T_16_78(22, e, f, g, h, a, b, c, d)
+       T_16_78(24, c, d, e, f, g, h, a, b)
+       T_16_78(26, a, b, c, d, e, f, g, h)
+       T_16_78(28, g, h, a, b, c, d, e, f)
+       T_16_78(30, e, f, g, h, a, b, c, d)
+       T_16_78(32, c, d, e, f, g, h, a, b)
+       T_16_78(34, a, b, c, d, e, f, g, h)
+       T_16_78(36, g, h, a, b, c, d, e, f)
+       T_16_78(38, e, f, g, h, a, b, c, d)
+       T_16_78(40, c, d, e, f, g, h, a, b)
+       T_16_78(42, a, b, c, d, e, f, g, h)
+       T_16_78(44, g, h, a, b, c, d, e, f)
+       T_16_78(46, e, f, g, h, a, b, c, d)
+       T_16_78(48, c, d, e, f, g, h, a, b)
+       T_16_78(50, a, b, c, d, e, f, g, h)
+       T_16_78(52, g, h, a, b, c, d, e, f)
+       T_16_78(54, e, f, g, h, a, b, c, d)
+       T_16_78(56, c, d, e, f, g, h, a, b)
+       T_16_78(58, a, b, c, d, e, f, g, h)
+       T_16_78(60, g, h, a, b, c, d, e, f)
+       T_16_78(62, e, f, g, h, a, b, c, d)
+       T_16_78(64, c, d, e, f, g, h, a, b)
+       T_16_78(66, a, b, c, d, e, f, g, h)
+       T_16_78(68, g, h, a, b, c, d, e, f)
+       T_16_78(70, e, f, g, h, a, b, c, d)
+       T_16_78(72, c, d, e, f, g, h, a, b)
+       T_16_78(74, a, b, c, d, e, f, g, h)
+       T_16_78(76, g, h, a, b, c, d, e, f)
+       T_16_78(78, e, f, g, h, a, b, c, d)
+       T_80(80, c, d, e, f, g, h, a, b)
 
        /* Update digest */
        add     [DIGEST(0)], a_64
@@ -351,9 +378,11 @@ _gcry_sha512_transform_amd64_ssse3:
        mov     r13, [rsp + frame_GPRSAVE + 8 * 2]
        mov     r14, [rsp + frame_GPRSAVE + 8 * 3]
        mov     r15, [rsp + frame_GPRSAVE + 8 * 4]
-
-       /* Restore Stack Pointer */
-       add     rsp, frame_size
+       CFI_RESTORE(rbx)
+       CFI_RESTORE(r12)
+       CFI_RESTORE(r13)
+       CFI_RESTORE(r14)
+       CFI_RESTORE(r15)
 
        pxor    xmm0, xmm0
        pxor    xmm1, xmm1
@@ -362,11 +391,23 @@ _gcry_sha512_transform_amd64_ssse3:
        pxor    xmm4, xmm4
        pxor    xmm5, xmm5
 
-       /* Return stack burn depth */
-       mov     rax, frame_size
+       /* Burn stack */
+       mov eax, 0
+.Lerase_stack:
+       movdqu [rsp + rax], xmm0
+       add eax, 16
+       cmp eax, frame_W_size
+       jne .Lerase_stack
+       movdqu [rsp + frame_WK], xmm0
+       xor     eax, eax
+
+       /* Restore Stack Pointer */
+       add     rsp, frame_size
+       CFI_ADJUST_CFA_OFFSET(-frame_size);
 
 .Lnowork:
-       ret
+       ret_spec_stop
+       CFI_ENDPROC()
 
 /*
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/cipher/sha512-ssse3-i386.c b/cipher/sha512-ssse3-i386.c
new file mode 100644 (file)
index 0000000..0fc98d8
--- /dev/null
@@ -0,0 +1,404 @@
+/* sha512-ssse3-i386.c - i386/SSSE3 implementation of SHA-512 transform
+ * Copyright (C) 2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * SHA512 Message Expansion (I2 and W2 macros) based on implementation
+ * from file "sha512-ssse3-amd64.s":
+ ************************************************************************
+ * Copyright (c) 2012, Intel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * * Neither the name of the Intel Corporation nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ************************************************************************
+ */
+
+#include <config.h>
+
+#if defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \
+    defined(HAVE_GCC_INLINE_ASM_SSSE3) && defined(USE_SHA512)
+
+#include "bufhelp.h"
+
+
+#if _GCRY_GCC_VERSION >= 40400 /* 4.4 */
+/* Prevent compiler from issuing SSE/MMX instructions between asm blocks. */
+#  pragma GCC target("no-sse")
+#  pragma GCC target("no-mmx")
+#endif
+#if __clang__
+#  pragma clang attribute push (__attribute__((target("no-sse"))), apply_to = function)
+#  pragma clang attribute push (__attribute__((target("no-mmx"))), apply_to = function)
+#endif
+
+
+#define ALWAYS_INLINE inline __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
+
+#define ASM_FUNC_ATTR          NO_INSTRUMENT_FUNCTION
+#define ASM_FUNC_ATTR_INLINE   ASM_FUNC_ATTR ALWAYS_INLINE
+#define ASM_FUNC_ATTR_NOINLINE ASM_FUNC_ATTR NO_INLINE
+
+
+static const u64 K[80] __attribute__ ((aligned (16))) =
+  {
+    U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd),
+    U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc),
+    U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019),
+    U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118),
+    U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe),
+    U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2),
+    U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1),
+    U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694),
+    U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3),
+    U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65),
+    U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483),
+    U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5),
+    U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210),
+    U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4),
+    U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725),
+    U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70),
+    U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926),
+    U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df),
+    U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8),
+    U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b),
+    U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001),
+    U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30),
+    U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910),
+    U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8),
+    U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53),
+    U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8),
+    U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb),
+    U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3),
+    U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60),
+    U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec),
+    U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9),
+    U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b),
+    U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207),
+    U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178),
+    U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6),
+    U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b),
+    U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493),
+    U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c),
+    U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a),
+    U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817)
+  };
+
+static const unsigned char bshuf_mask[16] __attribute__ ((aligned (16))) =
+  { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 };
+
+
+/* SHA2 round */
+#define RA "%%mm0"
+#define RB "%%mm1"
+#define RC "%%mm2"
+#define RD "%%mm3"
+#define RE "%%mm4"
+#define RF "%%mm5"
+#define RG "%%mm6"
+#define RH "%%mm7"
+
+#define Rx(a,b,c,d,e,f,g,h,wk) \
+       asm volatile (/* Cho + Sum1 */                                  \
+                     "movq2dq "a", %%xmm2;\n\t"                        \
+                     "movq "e", "a";\n\t"                              \
+                     "movq2dq "c", %%xmm3;\n\t"                        \
+                     "movq "e", "c";\n\t"                              \
+                     "movq2dq "b", %%xmm4;\n\t"                        \
+                     "movq "e", "b";\n\t"                              \
+                     "psrlq $(41-18), "c";\n\t"                        \
+                     "pandn "g", "a";\n\t"                             \
+                     "pxor "e", "c";\n\t"                              \
+                     "pand "f", "b";\n\t"                              \
+                     "psrlq $(18-14), "c";\n\t"                        \
+                     "paddq "a", "h";\n\t"                             \
+                     wk(a)                                             \
+                     "pxor "e", "c";\n\t"                              \
+                     "paddq "b", "h";\n\t"                             \
+                     "psrlq $(14), "c";\n\t"                           \
+                     "movq "e", "b";\n\t"                              \
+                     "psllq $(50-46), "b";\n\t"                        \
+                     "paddq "a", "h";\n\t"                             \
+                     "movdq2q %%xmm2, "a";\n\t"                        \
+                     "pxor "e", "b";\n\t"                              \
+                     "psllq $(46-23), "b";\n\t"                        \
+                     "pxor "e", "b";\n\t"                              \
+                     "psllq $(23), "b";\n\t"                           \
+                     "pxor "b", "c";\n\t"                              \
+                     "movdq2q %%xmm4, "b";\n\t"                        \
+                     "paddq "c", "h";\n\t"                             \
+                     "movdq2q %%xmm3, "c";\n\t"                        \
+                     \
+                     /* Maj + Sum0 */ \
+                     "movq2dq "e", %%xmm2;\n\t"                        \
+                     "movq "a", "e";\n\t"                              \
+                     "movq2dq "g", %%xmm3;\n\t"                        \
+                     "movq "a", "g";\n\t"                              \
+                     "movq2dq "f", %%xmm4;\n\t"                        \
+                     "movq "a", "f";\n\t"                              \
+                     "psrlq $(39-34), "g";\n\t"                        \
+                     "pxor "b", "e";\n\t"                              \
+                     "pxor "a", "g";\n\t"                              \
+                     "pand "b", "f";\n\t"                              \
+                     "psrlq $(34-28), "g";\n\t"                        \
+                     "pand "c", "e";\n\t"                              \
+                     "pxor "a", "g";\n\t"                              \
+                     "paddq "h", "d";\n\t"                             \
+                     "paddq "f", "h";\n\t"                             \
+                     "movdq2q %%xmm4, "f";\n\t"                        \
+                     "psrlq $28, "g";\n\t"                             \
+                     "paddq "e", "h";\n\t"                             \
+                     "movq "a", "e";\n\t"                              \
+                     "psllq $(36-30), "e";\n\t"                        \
+                     "pxor "a", "e";\n\t"                              \
+                     "psllq $(30-25), "e";\n\t"                        \
+                     "pxor "a", "e";\n\t"                              \
+                     "psllq $(25), "e";\n\t"                           \
+                     "pxor "e", "g";\n\t"                              \
+                     "movdq2q %%xmm2, "e";\n\t"                        \
+                     "paddq "g", "h";\n\t"                             \
+                     "movdq2q %%xmm3, "g";\n\t"                        \
+                     \
+                     :                                                 \
+                     :                                                 \
+                     : "memory" )
+
+#define WK0(tmp)      "movdq2q %%xmm0, "tmp";\n\t"                     \
+                     "pshufd $0xee, %%xmm0, %%xmm0;\n\t"
+
+#define WK1(tmp)      "movdq2q %%xmm0, "tmp";\n\t"
+
+/* Message expansion */
+#define I2(i) \
+       asm volatile ("movdqu %[inbuf], %%xmm0;\n\t"                    \
+                     "pshufb %%xmm6, %%xmm0;\n\t"                      \
+                     "movdqu %%xmm0, %[w];\n\t"                        \
+                     "paddq %[k], %%xmm0;\n\t"                         \
+                     :                                                 \
+                     : [k] "m" (K[i]),                                 \
+                       [w] "m" (w[i]),                                 \
+                       [inbuf] "m" (data[(i)*8])                       \
+                     : "memory" )
+
+#define W2(i) \
+       asm volatile ("movdqu %[w_t_m_2], %%xmm2;\n\t"                  \
+                     "movdqa %%xmm2, %%xmm0;\n\t"                      \
+                     "movdqu %[w_t_m_15], %%xmm5;\n\t"                 \
+                     :                                                 \
+                     : [w_t_m_2] "m" (w[(i)-2]),                       \
+                       [w_t_m_15] "m" (w[(i)-15])                      \
+                     : "memory" );                                     \
+       asm volatile ("movdqa %%xmm5, %%xmm3;\n\t"                      \
+                     "psrlq $(61-19), %%xmm0;\n\t"                     \
+                     "psrlq $(8-7), %%xmm3;\n\t"                       \
+                     "pxor %%xmm2, %%xmm0;\n\t"                        \
+                     "pxor %%xmm5, %%xmm3;\n\t"                        \
+                     "psrlq $(19-6), %%xmm0;\n\t"                      \
+                     "psrlq $(7-1), %%xmm3;\n\t"                       \
+                     "pxor %%xmm2, %%xmm0;\n\t"                        \
+                     "pxor %%xmm5, %%xmm3;\n\t"                        \
+                     "psrlq $6, %%xmm0;\n\t"                           \
+                     "psrlq $1, %%xmm3;\n\t"                           \
+                     "movdqa %%xmm2, %%xmm1;\n\t"                      \
+                     "movdqa %%xmm5, %%xmm4;\n\t"                      \
+                     "psllq $(61-19), %%xmm1;\n\t"                     \
+                     "psllq $(8-1), %%xmm4;\n\t"                       \
+                     "pxor %%xmm2, %%xmm1;\n\t"                        \
+                     "pxor %%xmm5, %%xmm4;\n\t"                        \
+                     "psllq $(64-61), %%xmm1;\n\t"                     \
+                     "psllq $(64-8), %%xmm4;\n\t"                      \
+                     "pxor %%xmm1, %%xmm0;\n\t"                        \
+                     "movdqu %[w_t_m_16], %%xmm2;\n\t"                 \
+                     "pxor %%xmm4, %%xmm3;\n\t"                        \
+                     "movdqu %[w_t_m_7], %%xmm1;\n\t"                  \
+                     :                                                 \
+                     : [w_t_m_7] "m" (w[(i)-7]),                       \
+                       [w_t_m_16] "m" (w[(i)-16])                      \
+                     : "memory" );                                     \
+       asm volatile ("paddq %%xmm3, %%xmm0;\n\t"                       \
+                     "paddq %%xmm2, %%xmm0;\n\t"                       \
+                     "paddq %%xmm1, %%xmm0;\n\t"                       \
+                     "movdqu %%xmm0, %[w_t_m_0];\n\t"                  \
+                     "paddq %[k], %%xmm0;\n\t"                         \
+                     : [w_t_m_0] "=m" (w[(i)-0])                       \
+                     : [k] "m" (K[i])                                  \
+                     : "memory" )
+
+unsigned int ASM_FUNC_ATTR
+_gcry_sha512_transform_i386_ssse3(u64 state[8], const unsigned char *data,
+                                 size_t nblks)
+{
+  unsigned int t;
+  u64 w[80];
+
+  /* Load state to MMX registers. */
+  asm volatile ("movq 8*0(%[state]), "RA";\n\t"
+               "movq 8*1(%[state]), "RB";\n\t"
+               "movq 8*2(%[state]), "RC";\n\t"
+               "movq 8*3(%[state]), "RD";\n\t"
+               "movq 8*4(%[state]), "RE";\n\t"
+               "movq 8*5(%[state]), "RF";\n\t"
+               "movq 8*6(%[state]), "RG";\n\t"
+               "movq 8*7(%[state]), "RH";\n\t"
+               :
+               : [state] "r" (state)
+               : "memory" );
+
+  asm volatile ("movdqa %[bshuf_mask], %%xmm6;\n\t"
+               :
+               : [bshuf_mask] "m" (*bshuf_mask)
+               : "memory" );
+
+  while (nblks)
+    {
+      I2(0);
+      Rx(RA, RB, RC, RD, RE, RF, RG, RH, WK0);
+      Rx(RH, RA, RB, RC, RD, RE, RF, RG, WK1);
+      I2(2);
+      Rx(RG, RH, RA, RB, RC, RD, RE, RF, WK0);
+      Rx(RF, RG, RH, RA, RB, RC, RD, RE, WK1);
+      I2(4);
+      Rx(RE, RF, RG, RH, RA, RB, RC, RD, WK0);
+      Rx(RD, RE, RF, RG, RH, RA, RB, RC, WK1);
+      I2(6);
+      Rx(RC, RD, RE, RF, RG, RH, RA, RB, WK0);
+      Rx(RB, RC, RD, RE, RF, RG, RH, RA, WK1);
+      I2(8);
+      Rx(RA, RB, RC, RD, RE, RF, RG, RH, WK0);
+      Rx(RH, RA, RB, RC, RD, RE, RF, RG, WK1);
+      I2(10);
+      Rx(RG, RH, RA, RB, RC, RD, RE, RF, WK0);
+      Rx(RF, RG, RH, RA, RB, RC, RD, RE, WK1);
+      I2(12);
+      Rx(RE, RF, RG, RH, RA, RB, RC, RD, WK0);
+      Rx(RD, RE, RF, RG, RH, RA, RB, RC, WK1);
+      I2(14);
+      Rx(RC, RD, RE, RF, RG, RH, RA, RB, WK0);
+      Rx(RB, RC, RD, RE, RF, RG, RH, RA, WK1);
+      data += 128;
+
+      for (t = 16; t < 80; t += 16)
+       {
+         W2(t + 0);
+         Rx(RA, RB, RC, RD, RE, RF, RG, RH, WK0);
+         Rx(RH, RA, RB, RC, RD, RE, RF, RG, WK1);
+         W2(t + 2);
+         Rx(RG, RH, RA, RB, RC, RD, RE, RF, WK0);
+         Rx(RF, RG, RH, RA, RB, RC, RD, RE, WK1);
+         W2(t + 4);
+         Rx(RE, RF, RG, RH, RA, RB, RC, RD, WK0);
+         Rx(RD, RE, RF, RG, RH, RA, RB, RC, WK1);
+         W2(t + 6);
+         Rx(RC, RD, RE, RF, RG, RH, RA, RB, WK0);
+         Rx(RB, RC, RD, RE, RF, RG, RH, RA, WK1);
+         W2(t + 8);
+         Rx(RA, RB, RC, RD, RE, RF, RG, RH, WK0);
+         Rx(RH, RA, RB, RC, RD, RE, RF, RG, WK1);
+         W2(t + 10);
+         Rx(RG, RH, RA, RB, RC, RD, RE, RF, WK0);
+         Rx(RF, RG, RH, RA, RB, RC, RD, RE, WK1);
+         W2(t + 12);
+         Rx(RE, RF, RG, RH, RA, RB, RC, RD, WK0);
+         Rx(RD, RE, RF, RG, RH, RA, RB, RC, WK1);
+         W2(t + 14);
+         Rx(RC, RD, RE, RF, RG, RH, RA, RB, WK0);
+         Rx(RB, RC, RD, RE, RF, RG, RH, RA, WK1);
+       }
+
+      asm volatile ("paddq 8*0(%[state]), "RA";\n\t"
+                   "paddq 8*1(%[state]), "RB";\n\t"
+                   "paddq 8*2(%[state]), "RC";\n\t"
+                   "paddq 8*3(%[state]), "RD";\n\t"
+                   "paddq 8*4(%[state]), "RE";\n\t"
+                   "paddq 8*5(%[state]), "RF";\n\t"
+                   "paddq 8*6(%[state]), "RG";\n\t"
+                   "paddq 8*7(%[state]), "RH";\n\t"
+                   "movq "RA", 8*0(%[state]);\n\t"
+                   "movq "RB", 8*1(%[state]);\n\t"
+                   "movq "RC", 8*2(%[state]);\n\t"
+                   "movq "RD", 8*3(%[state]);\n\t"
+                   "movq "RE", 8*4(%[state]);\n\t"
+                   "movq "RF", 8*5(%[state]);\n\t"
+                   "movq "RG", 8*6(%[state]);\n\t"
+                   "movq "RH", 8*7(%[state]);\n\t"
+                   :
+                   : [state] "r" (state)
+                   : "memory" );
+
+      nblks--;
+    }
+
+  /* Clear registers */
+  asm volatile ("pxor %%xmm0, %%xmm0;\n\t"
+               "pxor %%xmm1, %%xmm1;\n\t"
+               "pxor %%xmm2, %%xmm2;\n\t"
+               "pxor %%xmm3, %%xmm3;\n\t"
+               "pxor %%xmm4, %%xmm4;\n\t"
+               "pxor %%xmm5, %%xmm5;\n\t"
+               "pxor %%xmm6, %%xmm6;\n\t"
+               "pxor %%mm0, %%mm0;\n\t"
+               "pxor %%mm1, %%mm1;\n\t"
+               "pxor %%mm2, %%mm2;\n\t"
+               "pxor %%mm3, %%mm3;\n\t"
+               "pxor %%mm4, %%mm4;\n\t"
+               "pxor %%mm5, %%mm5;\n\t"
+               "pxor %%mm6, %%mm6;\n\t"
+               "pxor %%mm7, %%mm7;\n\t"
+               "emms;\n\t"
+              :
+              :
+              : "memory" );
+
+  return sizeof(w);
+}
+
+#if __clang__
+#  pragma clang attribute pop
+#  pragma clang attribute pop
+#endif
+
+#endif
index 06e8a2b..57a7466 100644 (file)
 #endif
 
 
-typedef struct
-{
-  u64 h0, h1, h2, h3, h4, h5, h6, h7;
-} SHA512_STATE;
-
-typedef struct
-{
-  gcry_md_block_ctx_t bctx;
-  SHA512_STATE state;
-#ifdef USE_ARM_NEON_ASM
-  unsigned int use_neon:1;
-#endif
-#ifdef USE_SSSE3
-  unsigned int use_ssse3:1;
-#endif
-#ifdef USE_AVX
-  unsigned int use_avx:1;
-#endif
-#ifdef USE_AVX2
-  unsigned int use_avx2:1;
+/* USE_SSSE3_I386 indicates whether to compile with Intel SSSE3/i386 code. */
+#undef USE_SSSE3_I386
+#if defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \
+    defined(HAVE_GCC_INLINE_ASM_SSSE3)
+# define USE_SSSE3_I386 1
 #endif
-} SHA512_CONTEXT;
-
-static unsigned int
-transform (void *context, const unsigned char *data, size_t nblks);
-
-static void
-sha512_init (void *context, unsigned int flags)
-{
-  SHA512_CONTEXT *ctx = context;
-  SHA512_STATE *hd = &ctx->state;
-  unsigned int features = _gcry_get_hw_features ();
-
-  (void)flags;
-
-  hd->h0 = U64_C(0x6a09e667f3bcc908);
-  hd->h1 = U64_C(0xbb67ae8584caa73b);
-  hd->h2 = U64_C(0x3c6ef372fe94f82b);
-  hd->h3 = U64_C(0xa54ff53a5f1d36f1);
-  hd->h4 = U64_C(0x510e527fade682d1);
-  hd->h5 = U64_C(0x9b05688c2b3e6c1f);
-  hd->h6 = U64_C(0x1f83d9abfb41bd6b);
-  hd->h7 = U64_C(0x5be0cd19137e2179);
 
-  ctx->bctx.nblocks = 0;
-  ctx->bctx.nblocks_high = 0;
-  ctx->bctx.count = 0;
-  ctx->bctx.blocksize = 128;
-  ctx->bctx.bwrite = transform;
 
-#ifdef USE_ARM_NEON_ASM
-  ctx->use_neon = (features & HWF_ARM_NEON) != 0;
-#endif
-#ifdef USE_SSSE3
-  ctx->use_ssse3 = (features & HWF_INTEL_SSSE3) != 0;
-#endif
-#ifdef USE_AVX
-  ctx->use_avx = (features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD);
-#endif
-#ifdef USE_AVX2
-  ctx->use_avx2 = (features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2);
+/* USE_PPC_CRYPTO indicates whether to enable PowerPC vector crypto
+ * accelerated code. */
+#undef USE_PPC_CRYPTO
+#ifdef ENABLE_PPC_CRYPTO_SUPPORT
+# if defined(HAVE_COMPATIBLE_CC_PPC_ALTIVEC) && \
+     defined(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC)
+#  if __GNUC__ >= 4
+#   define USE_PPC_CRYPTO 1
+#  endif
+# endif
 #endif
 
-  (void)features;
-}
-
-static void
-sha384_init (void *context, unsigned int flags)
-{
-  SHA512_CONTEXT *ctx = context;
-  SHA512_STATE *hd = &ctx->state;
-  unsigned int features = _gcry_get_hw_features ();
 
-  (void)flags;
+/* USE_S390X_CRYPTO indicates whether to enable zSeries code. */
+#undef USE_S390X_CRYPTO
+#if defined(HAVE_GCC_INLINE_ASM_S390X)
+# define USE_S390X_CRYPTO 1
+#endif /* USE_S390X_CRYPTO */
 
-  hd->h0 = U64_C(0xcbbb9d5dc1059ed8);
-  hd->h1 = U64_C(0x629a292a367cd507);
-  hd->h2 = U64_C(0x9159015a3070dd17);
-  hd->h3 = U64_C(0x152fecd8f70e5939);
-  hd->h4 = U64_C(0x67332667ffc00b31);
-  hd->h5 = U64_C(0x8eb44a8768581511);
-  hd->h6 = U64_C(0xdb0c2e0d64f98fa7);
-  hd->h7 = U64_C(0x47b5481dbefa4fa4);
 
-  ctx->bctx.nblocks = 0;
-  ctx->bctx.nblocks_high = 0;
-  ctx->bctx.count = 0;
-  ctx->bctx.blocksize = 128;
-  ctx->bctx.bwrite = transform;
+typedef struct
+{
+  u64 h[8];
+} SHA512_STATE;
 
-#ifdef USE_ARM_NEON_ASM
-  ctx->use_neon = (features & HWF_ARM_NEON) != 0;
-#endif
-#ifdef USE_SSSE3
-  ctx->use_ssse3 = (features & HWF_INTEL_SSSE3) != 0;
-#endif
-#ifdef USE_AVX
-  ctx->use_avx = (features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD);
-#endif
-#ifdef USE_AVX2
-  ctx->use_avx2 = (features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2);
+typedef struct
+{
+  gcry_md_block_ctx_t bctx;
+  SHA512_STATE state;
+#ifdef USE_S390X_CRYPTO
+  u64 final_len_msb, final_len_lsb; /* needs to be right after state.h[7]. */
+  int use_s390x_crypto;
 #endif
-
-  (void)features;
-}
+} SHA512_CONTEXT;
 
 
 static const u64 k[] =
@@ -255,305 +192,6 @@ static const u64 k[] =
     U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817)
   };
 
-#ifndef USE_ARM_ASM
-
-static inline u64
-ROTR (u64 x, u64 n)
-{
-  return ((x >> n) | (x << (64 - n)));
-}
-
-static inline u64
-Ch (u64 x, u64 y, u64 z)
-{
-  return ((x & y) ^ ( ~x & z));
-}
-
-static inline u64
-Maj (u64 x, u64 y, u64 z)
-{
-  return ((x & y) ^ (x & z) ^ (y & z));
-}
-
-static inline u64
-Sum0 (u64 x)
-{
-  return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39));
-}
-
-static inline u64
-Sum1 (u64 x)
-{
-  return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41));
-}
-
-/****************
- * Transform the message W which consists of 16 64-bit-words
- */
-static unsigned int
-transform_blk (SHA512_STATE *hd, const unsigned char *data)
-{
-  u64 a, b, c, d, e, f, g, h;
-  u64 w[16];
-  int t;
-
-  /* get values from the chaining vars */
-  a = hd->h0;
-  b = hd->h1;
-  c = hd->h2;
-  d = hd->h3;
-  e = hd->h4;
-  f = hd->h5;
-  g = hd->h6;
-  h = hd->h7;
-
-  for ( t = 0; t < 16; t++ )
-    w[t] = buf_get_be64(data + t * 8);
-
-#define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7))
-#define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
-
-  for (t = 0; t < 80 - 16; )
-    {
-      u64 t1, t2;
-
-      /* Performance on a AMD Athlon(tm) Dual Core Processor 4050e
-         with gcc 4.3.3 using gcry_md_hash_buffer of each 10000 bytes
-         initialized to 0,1,2,3...255,0,... and 1000 iterations:
-
-         Not unrolled with macros:  440ms
-         Unrolled with macros:      350ms
-         Unrolled with inline:      330ms
-      */
-#if 0 /* Not unrolled.  */
-      t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t%16];
-      w[t%16] += S1 (w[(t - 2)%16]) + w[(t - 7)%16] + S0 (w[(t - 15)%16]);
-      t2 = Sum0 (a) + Maj (a, b, c);
-      h = g;
-      g = f;
-      f = e;
-      e = d + t1;
-      d = c;
-      c = b;
-      b = a;
-      a = t1 + t2;
-      t++;
-#else /* Unrolled to interweave the chain variables.  */
-      t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0];
-      w[0] += S1 (w[14]) + w[9] + S0 (w[1]);
-      t2 = Sum0 (a) + Maj (a, b, c);
-      d += t1;
-      h = t1 + t2;
-
-      t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1];
-      w[1] += S1 (w[15]) + w[10] + S0 (w[2]);
-      t2 = Sum0 (h) + Maj (h, a, b);
-      c += t1;
-      g  = t1 + t2;
-
-      t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2];
-      w[2] += S1 (w[0]) + w[11] + S0 (w[3]);
-      t2 = Sum0 (g) + Maj (g, h, a);
-      b += t1;
-      f  = t1 + t2;
-
-      t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3];
-      w[3] += S1 (w[1]) + w[12] + S0 (w[4]);
-      t2 = Sum0 (f) + Maj (f, g, h);
-      a += t1;
-      e  = t1 + t2;
-
-      t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4];
-      w[4] += S1 (w[2]) + w[13] + S0 (w[5]);
-      t2 = Sum0 (e) + Maj (e, f, g);
-      h += t1;
-      d  = t1 + t2;
-
-      t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5];
-      w[5] += S1 (w[3]) + w[14] + S0 (w[6]);
-      t2 = Sum0 (d) + Maj (d, e, f);
-      g += t1;
-      c  = t1 + t2;
-
-      t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6];
-      w[6] += S1 (w[4]) + w[15] + S0 (w[7]);
-      t2 = Sum0 (c) + Maj (c, d, e);
-      f += t1;
-      b  = t1 + t2;
-
-      t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7];
-      w[7] += S1 (w[5]) + w[0] + S0 (w[8]);
-      t2 = Sum0 (b) + Maj (b, c, d);
-      e += t1;
-      a  = t1 + t2;
-
-      t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8];
-      w[8] += S1 (w[6]) + w[1] + S0 (w[9]);
-      t2 = Sum0 (a) + Maj (a, b, c);
-      d += t1;
-      h  = t1 + t2;
-
-      t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9];
-      w[9] += S1 (w[7]) + w[2] + S0 (w[10]);
-      t2 = Sum0 (h) + Maj (h, a, b);
-      c += t1;
-      g  = t1 + t2;
-
-      t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10];
-      w[10] += S1 (w[8]) + w[3] + S0 (w[11]);
-      t2 = Sum0 (g) + Maj (g, h, a);
-      b += t1;
-      f  = t1 + t2;
-
-      t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11];
-      w[11] += S1 (w[9]) + w[4] + S0 (w[12]);
-      t2 = Sum0 (f) + Maj (f, g, h);
-      a += t1;
-      e  = t1 + t2;
-
-      t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12];
-      w[12] += S1 (w[10]) + w[5] + S0 (w[13]);
-      t2 = Sum0 (e) + Maj (e, f, g);
-      h += t1;
-      d  = t1 + t2;
-
-      t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13];
-      w[13] += S1 (w[11]) + w[6] + S0 (w[14]);
-      t2 = Sum0 (d) + Maj (d, e, f);
-      g += t1;
-      c  = t1 + t2;
-
-      t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14];
-      w[14] += S1 (w[12]) + w[7] + S0 (w[15]);
-      t2 = Sum0 (c) + Maj (c, d, e);
-      f += t1;
-      b  = t1 + t2;
-
-      t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15];
-      w[15] += S1 (w[13]) + w[8] + S0 (w[0]);
-      t2 = Sum0 (b) + Maj (b, c, d);
-      e += t1;
-      a  = t1 + t2;
-
-      t += 16;
-#endif
-    }
-
-  for (; t < 80; )
-    {
-      u64 t1, t2;
-
-#if 0 /* Not unrolled.  */
-      t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t%16];
-      t2 = Sum0 (a) + Maj (a, b, c);
-      h = g;
-      g = f;
-      f = e;
-      e = d + t1;
-      d = c;
-      c = b;
-      b = a;
-      a = t1 + t2;
-      t++;
-#else /* Unrolled to interweave the chain variables.  */
-      t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0];
-      t2 = Sum0 (a) + Maj (a, b, c);
-      d += t1;
-      h  = t1 + t2;
-
-      t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1];
-      t2 = Sum0 (h) + Maj (h, a, b);
-      c += t1;
-      g  = t1 + t2;
-
-      t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2];
-      t2 = Sum0 (g) + Maj (g, h, a);
-      b += t1;
-      f  = t1 + t2;
-
-      t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3];
-      t2 = Sum0 (f) + Maj (f, g, h);
-      a += t1;
-      e  = t1 + t2;
-
-      t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4];
-      t2 = Sum0 (e) + Maj (e, f, g);
-      h += t1;
-      d  = t1 + t2;
-
-      t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5];
-      t2 = Sum0 (d) + Maj (d, e, f);
-      g += t1;
-      c  = t1 + t2;
-
-      t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6];
-      t2 = Sum0 (c) + Maj (c, d, e);
-      f += t1;
-      b  = t1 + t2;
-
-      t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7];
-      t2 = Sum0 (b) + Maj (b, c, d);
-      e += t1;
-      a  = t1 + t2;
-
-      t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8];
-      t2 = Sum0 (a) + Maj (a, b, c);
-      d += t1;
-      h  = t1 + t2;
-
-      t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9];
-      t2 = Sum0 (h) + Maj (h, a, b);
-      c += t1;
-      g  = t1 + t2;
-
-      t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10];
-      t2 = Sum0 (g) + Maj (g, h, a);
-      b += t1;
-      f  = t1 + t2;
-
-      t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11];
-      t2 = Sum0 (f) + Maj (f, g, h);
-      a += t1;
-      e  = t1 + t2;
-
-      t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12];
-      t2 = Sum0 (e) + Maj (e, f, g);
-      h += t1;
-      d  = t1 + t2;
-
-      t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13];
-      t2 = Sum0 (d) + Maj (d, e, f);
-      g += t1;
-      c  = t1 + t2;
-
-      t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14];
-      t2 = Sum0 (c) + Maj (c, d, e);
-      f += t1;
-      b  = t1 + t2;
-
-      t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15];
-      t2 = Sum0 (b) + Maj (b, c, d);
-      e += t1;
-      a  = t1 + t2;
-
-      t += 16;
-#endif
-    }
-
-  /* Update chaining vars.  */
-  hd->h0 += a;
-  hd->h1 += b;
-  hd->h2 += c;
-  hd->h3 += d;
-  hd->h4 += e;
-  hd->h5 += f;
-  hd->h6 += g;
-  hd->h7 += h;
-
-  return /* burn_stack */ (8 + 16) * sizeof(u64) + sizeof(u32) +
-                          3 * sizeof(void*);
-}
-#endif /*!USE_ARM_ASM*/
 
 /* AMD64 assembly implementations use SystemV ABI, ABI conversion and additional
  * stack to store XMM6-XMM15 needed on Win64. */
@@ -562,7 +200,7 @@ transform_blk (SHA512_STATE *hd, const unsigned char *data)
 #if defined(USE_SSSE3) || defined(USE_AVX) || defined(USE_AVX2)
 # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
 #  define ASM_FUNC_ABI __attribute__((sysv_abi))
-#  define ASM_EXTRA_STACK (10 * 16)
+#  define ASM_EXTRA_STACK (10 * 16 + 4 * sizeof(void *))
 # else
 #  define ASM_FUNC_ABI
 #  define ASM_EXTRA_STACK 0
@@ -571,92 +209,562 @@ transform_blk (SHA512_STATE *hd, const unsigned char *data)
 
 
 #ifdef USE_ARM_NEON_ASM
-void _gcry_sha512_transform_armv7_neon (SHA512_STATE *hd,
-                                       const unsigned char *data,
-                                       const u64 k[], size_t num_blks);
-#endif
+unsigned int _gcry_sha512_transform_armv7_neon (SHA512_STATE *hd,
+                                                const unsigned char *data,
+                                                const u64 k[], size_t num_blks);
 
-#ifdef USE_ARM_ASM
-unsigned int _gcry_sha512_transform_arm (SHA512_STATE *hd,
-                                        const unsigned char *data,
-                                        const u64 k[], size_t num_blks);
+static unsigned int
+do_sha512_transform_armv7_neon(void *ctx, const unsigned char *data,
+                               size_t nblks)
+{
+  SHA512_CONTEXT *hd = ctx;
+  return _gcry_sha512_transform_armv7_neon (&hd->state, data, k, nblks);
+}
 #endif
 
 #ifdef USE_SSSE3
 unsigned int _gcry_sha512_transform_amd64_ssse3(const void *input_data,
                                                 void *state,
                                                 size_t num_blks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha512_transform_amd64_ssse3(void *ctx, const unsigned char *data,
+                                size_t nblks)
+{
+  SHA512_CONTEXT *hd = ctx;
+  return _gcry_sha512_transform_amd64_ssse3 (data, &hd->state, nblks)
+         + ASM_EXTRA_STACK;
+}
 #endif
 
 #ifdef USE_AVX
 unsigned int _gcry_sha512_transform_amd64_avx(const void *input_data,
                                               void *state,
                                               size_t num_blks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha512_transform_amd64_avx(void *ctx, const unsigned char *data,
+                              size_t nblks)
+{
+  SHA512_CONTEXT *hd = ctx;
+  return _gcry_sha512_transform_amd64_avx (data, &hd->state, nblks)
+         + ASM_EXTRA_STACK;
+}
 #endif
 
 #ifdef USE_AVX2
 unsigned int _gcry_sha512_transform_amd64_avx2(const void *input_data,
                                                void *state,
                                                size_t num_blks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sha512_transform_amd64_avx2(void *ctx, const unsigned char *data,
+                               size_t nblks)
+{
+  SHA512_CONTEXT *hd = ctx;
+  return _gcry_sha512_transform_amd64_avx2 (data, &hd->state, nblks)
+         + ASM_EXTRA_STACK;
+}
 #endif
 
+#ifdef USE_SSSE3_I386
+unsigned int _gcry_sha512_transform_i386_ssse3(u64 state[8],
+                                              const unsigned char *input_data,
+                                              size_t num_blks);
 
 static unsigned int
-transform (void *context, const unsigned char *data, size_t nblks)
+do_sha512_transform_i386_ssse3(void *ctx, const unsigned char *data,
+                              size_t nblks)
 {
-  SHA512_CONTEXT *ctx = context;
-  unsigned int burn;
+  SHA512_CONTEXT *hd = ctx;
+  return _gcry_sha512_transform_i386_ssse3 (hd->state.h, data, nblks);
+}
+#endif
 
-#ifdef USE_AVX2
-  if (ctx->use_avx2)
-    return _gcry_sha512_transform_amd64_avx2 (data, &ctx->state, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
+
+#ifdef USE_ARM_ASM
+unsigned int _gcry_sha512_transform_arm (SHA512_STATE *hd,
+                                        const unsigned char *data,
+                                        const u64 k[], size_t num_blks);
+
+static unsigned int
+do_transform_generic (void *context, const unsigned char *data, size_t nblks)
+{
+  SHA512_CONTEXT *hd = context;
+  return _gcry_sha512_transform_arm (&hd->state, data, k, nblks);
+}
+#else
+static unsigned int
+do_transform_generic (void *context, const unsigned char *data, size_t nblks);
 #endif
 
-#ifdef USE_AVX
-  if (ctx->use_avx)
-    return _gcry_sha512_transform_amd64_avx (data, &ctx->state, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
+
+#ifdef USE_PPC_CRYPTO
+unsigned int _gcry_sha512_transform_ppc8(u64 state[8],
+                                        const unsigned char *input_data,
+                                        size_t num_blks);
+
+unsigned int _gcry_sha512_transform_ppc9(u64 state[8],
+                                        const unsigned char *input_data,
+                                        size_t num_blks);
+
+static unsigned int
+do_sha512_transform_ppc8(void *ctx, const unsigned char *data, size_t nblks)
+{
+  SHA512_CONTEXT *hd = ctx;
+  return _gcry_sha512_transform_ppc8 (hd->state.h, data, nblks);
+}
+
+static unsigned int
+do_sha512_transform_ppc9(void *ctx, const unsigned char *data, size_t nblks)
+{
+  SHA512_CONTEXT *hd = ctx;
+  return _gcry_sha512_transform_ppc9 (hd->state.h, data, nblks);
+}
 #endif
 
-#ifdef USE_SSSE3
-  if (ctx->use_ssse3)
-    return _gcry_sha512_transform_amd64_ssse3 (data, &ctx->state, nblks)
-           + 4 * sizeof(void*) + ASM_EXTRA_STACK;
+
+#ifdef USE_S390X_CRYPTO
+#include "asm-inline-s390x.h"
+
+static unsigned int
+do_sha512_transform_s390x (void *ctx, const unsigned char *data, size_t nblks)
+{
+  SHA512_CONTEXT *hd = ctx;
+
+  kimd_execute (KMID_FUNCTION_SHA512, hd->state.h, data, nblks * 128);
+  return 0;
+}
+
+static unsigned int
+do_sha512_final_s390x (void *ctx, const unsigned char *data, size_t datalen,
+                      u64 len_msb, u64 len_lsb)
+{
+  SHA512_CONTEXT *hd = ctx;
+
+  /* Make sure that 'final_len' is positioned at correct offset relative
+   * to 'state.h[0]'. This is because we are passing 'state.h[0]' pointer as
+   * start of parameter block to 'klmd' instruction. */
+
+  gcry_assert (offsetof (SHA512_CONTEXT, final_len_msb)
+              - offsetof (SHA512_CONTEXT, state.h[0]) == 8 * sizeof(u64));
+  gcry_assert (offsetof (SHA512_CONTEXT, final_len_lsb)
+              - offsetof (SHA512_CONTEXT, final_len_msb) == 1 * sizeof(u64));
+
+  hd->final_len_msb = len_msb;
+  hd->final_len_lsb = len_lsb;
+
+  klmd_execute (KMID_FUNCTION_SHA512, hd->state.h, data, datalen);
+  return 0;
+}
 #endif
 
+
+static void
+sha512_init_common (SHA512_CONTEXT *ctx, unsigned int flags)
+{
+  unsigned int features = _gcry_get_hw_features ();
+
+  (void)flags;
+  (void)k;
+
+  ctx->bctx.nblocks = 0;
+  ctx->bctx.nblocks_high = 0;
+  ctx->bctx.count = 0;
+  ctx->bctx.blocksize_shift = _gcry_ctz(128);
+
+  /* Order of feature checks is important here; last match will be
+   * selected.  Keep slower implementations at the top and faster at
+   * the bottom.  */
+  ctx->bctx.bwrite = do_transform_generic;
 #ifdef USE_ARM_NEON_ASM
-  if (ctx->use_neon)
+  if ((features & HWF_ARM_NEON) != 0)
+    ctx->bctx.bwrite = do_sha512_transform_armv7_neon;
+#endif
+#ifdef USE_SSSE3
+  if ((features & HWF_INTEL_SSSE3) != 0)
+    ctx->bctx.bwrite = do_sha512_transform_amd64_ssse3;
+#endif
+#ifdef USE_AVX
+  if ((features & HWF_INTEL_AVX) && (features & HWF_INTEL_FAST_SHLD))
+    ctx->bctx.bwrite = do_sha512_transform_amd64_avx;
+#endif
+#ifdef USE_AVX2
+  if ((features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2))
+    ctx->bctx.bwrite = do_sha512_transform_amd64_avx2;
+#endif
+#ifdef USE_PPC_CRYPTO
+  if ((features & HWF_PPC_VCRYPTO) != 0)
+    ctx->bctx.bwrite = do_sha512_transform_ppc8;
+  if ((features & HWF_PPC_VCRYPTO) != 0 && (features & HWF_PPC_ARCH_3_00) != 0)
+    ctx->bctx.bwrite = do_sha512_transform_ppc9;
+#endif
+#ifdef USE_SSSE3_I386
+  if ((features & HWF_INTEL_SSSE3) != 0)
+    ctx->bctx.bwrite = do_sha512_transform_i386_ssse3;
+#endif
+#ifdef USE_S390X_CRYPTO
+  ctx->use_s390x_crypto = 0;
+  if ((features & HWF_S390X_MSA) != 0)
     {
-      _gcry_sha512_transform_armv7_neon (&ctx->state, data, k, nblks);
-
-      /* _gcry_sha512_transform_armv7_neon does not store sensitive data
-       * to stack.  */
-      return /* no burn_stack */ 0;
+      if ((kimd_query () & km_function_to_mask (KMID_FUNCTION_SHA512)) &&
+         (klmd_query () & km_function_to_mask (KMID_FUNCTION_SHA512)))
+       {
+         ctx->bctx.bwrite = do_sha512_transform_s390x;
+         ctx->use_s390x_crypto = 1;
+       }
     }
 #endif
+  (void)features;
+}
+
+
+static void
+sha512_init (void *context, unsigned int flags)
+{
+  SHA512_CONTEXT *ctx = context;
+  SHA512_STATE *hd = &ctx->state;
+
+  hd->h[0] = U64_C(0x6a09e667f3bcc908);
+  hd->h[1] = U64_C(0xbb67ae8584caa73b);
+  hd->h[2] = U64_C(0x3c6ef372fe94f82b);
+  hd->h[3] = U64_C(0xa54ff53a5f1d36f1);
+  hd->h[4] = U64_C(0x510e527fade682d1);
+  hd->h[5] = U64_C(0x9b05688c2b3e6c1f);
+  hd->h[6] = U64_C(0x1f83d9abfb41bd6b);
+  hd->h[7] = U64_C(0x5be0cd19137e2179);
+
+  sha512_init_common (ctx, flags);
+}
+
+static void
+sha384_init (void *context, unsigned int flags)
+{
+  SHA512_CONTEXT *ctx = context;
+  SHA512_STATE *hd = &ctx->state;
+
+  hd->h[0] = U64_C(0xcbbb9d5dc1059ed8);
+  hd->h[1] = U64_C(0x629a292a367cd507);
+  hd->h[2] = U64_C(0x9159015a3070dd17);
+  hd->h[3] = U64_C(0x152fecd8f70e5939);
+  hd->h[4] = U64_C(0x67332667ffc00b31);
+  hd->h[5] = U64_C(0x8eb44a8768581511);
+  hd->h[6] = U64_C(0xdb0c2e0d64f98fa7);
+  hd->h[7] = U64_C(0x47b5481dbefa4fa4);
+
+  sha512_init_common (ctx, flags);
+}
+
+
+static void
+sha512_256_init (void *context, unsigned int flags)
+{
+  SHA512_CONTEXT *ctx = context;
+  SHA512_STATE *hd = &ctx->state;
+
+  hd->h[0] = U64_C(0x22312194fc2bf72c);
+  hd->h[1] = U64_C(0x9f555fa3c84c64c2);
+  hd->h[2] = U64_C(0x2393b86b6f53b151);
+  hd->h[3] = U64_C(0x963877195940eabd);
+  hd->h[4] = U64_C(0x96283ee2a88effe3);
+  hd->h[5] = U64_C(0xbe5e1e2553863992);
+  hd->h[6] = U64_C(0x2b0199fc2c85b8aa);
+  hd->h[7] = U64_C(0x0eb72ddc81c52ca2);
+
+  sha512_init_common (ctx, flags);
+}
+
+
+static void
+sha512_224_init (void *context, unsigned int flags)
+{
+  SHA512_CONTEXT *ctx = context;
+  SHA512_STATE *hd = &ctx->state;
+
+  hd->h[0] = U64_C(0x8c3d37c819544da2);
+  hd->h[1] = U64_C(0x73e1996689dcd4d6);
+  hd->h[2] = U64_C(0x1dfab7ae32ff9c82);
+  hd->h[3] = U64_C(0x679dd514582f9fcf);
+  hd->h[4] = U64_C(0x0f6d2b697bd44da8);
+  hd->h[5] = U64_C(0x77e36f7304c48942);
+  hd->h[6] = U64_C(0x3f9d85a86a1d36c8);
+  hd->h[7] = U64_C(0x1112e6ad91d692a1);
+
+  sha512_init_common (ctx, flags);
+}
+
+
+
+#ifndef USE_ARM_ASM
+
+static inline u64
+ROTR (u64 x, u64 n)
+{
+  return ((x >> n) | (x << (64 - n)));
+}
+
+static inline u64
+Ch (u64 x, u64 y, u64 z)
+{
+  return ((x & y) ^ ( ~x & z));
+}
+
+static inline u64
+Maj (u64 x, u64 y, u64 z)
+{
+  return ((x & y) ^ (x & z) ^ (y & z));
+}
+
+static inline u64
+Sum0 (u64 x)
+{
+  return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39));
+}
+
+static inline u64
+Sum1 (u64 x)
+{
+  return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41));
+}
+
+/****************
+ * Transform the message W which consists of 16 64-bit-words
+ */
+static unsigned int
+do_transform_generic (void *context, const unsigned char *data, size_t nblks)
+{
+  SHA512_CONTEXT *ctx = context;
+  SHA512_STATE *hd = &ctx->state;
 
-#ifdef USE_ARM_ASM
-  burn = _gcry_sha512_transform_arm (&ctx->state, data, k, nblks);
-#else
   do
     {
-      burn = transform_blk (&ctx->state, data) + 3 * sizeof(void*);
+      u64 a, b, c, d, e, f, g, h;
+      u64 w[16];
+      int t;
+
+      /* get values from the chaining vars */
+      a = hd->h[0];
+      b = hd->h[1];
+      c = hd->h[2];
+      d = hd->h[3];
+      e = hd->h[4];
+      f = hd->h[5];
+      g = hd->h[6];
+      h = hd->h[7];
+
+      for ( t = 0; t < 16; t++ )
+        w[t] = buf_get_be64(data + t * 8);
+
+#define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7))
+#define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
+
+      for (t = 0; t < 80 - 16; )
+        {
+          u64 t1, t2;
+
+          t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0];
+          w[0] += S1 (w[14]) + w[9] + S0 (w[1]);
+          t2 = Sum0 (a) + Maj (a, b, c);
+          d += t1;
+          h = t1 + t2;
+
+          t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1];
+          w[1] += S1 (w[15]) + w[10] + S0 (w[2]);
+          t2 = Sum0 (h) + Maj (h, a, b);
+          c += t1;
+          g  = t1 + t2;
+
+          t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2];
+          w[2] += S1 (w[0]) + w[11] + S0 (w[3]);
+          t2 = Sum0 (g) + Maj (g, h, a);
+          b += t1;
+          f  = t1 + t2;
+
+          t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3];
+          w[3] += S1 (w[1]) + w[12] + S0 (w[4]);
+          t2 = Sum0 (f) + Maj (f, g, h);
+          a += t1;
+          e  = t1 + t2;
+
+          t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4];
+          w[4] += S1 (w[2]) + w[13] + S0 (w[5]);
+          t2 = Sum0 (e) + Maj (e, f, g);
+          h += t1;
+          d  = t1 + t2;
+
+          t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5];
+          w[5] += S1 (w[3]) + w[14] + S0 (w[6]);
+          t2 = Sum0 (d) + Maj (d, e, f);
+          g += t1;
+          c  = t1 + t2;
+
+          t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6];
+          w[6] += S1 (w[4]) + w[15] + S0 (w[7]);
+          t2 = Sum0 (c) + Maj (c, d, e);
+          f += t1;
+          b  = t1 + t2;
+
+          t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7];
+          w[7] += S1 (w[5]) + w[0] + S0 (w[8]);
+          t2 = Sum0 (b) + Maj (b, c, d);
+          e += t1;
+          a  = t1 + t2;
+
+          t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8];
+          w[8] += S1 (w[6]) + w[1] + S0 (w[9]);
+          t2 = Sum0 (a) + Maj (a, b, c);
+          d += t1;
+          h  = t1 + t2;
+
+          t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9];
+          w[9] += S1 (w[7]) + w[2] + S0 (w[10]);
+          t2 = Sum0 (h) + Maj (h, a, b);
+          c += t1;
+          g  = t1 + t2;
+
+          t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10];
+          w[10] += S1 (w[8]) + w[3] + S0 (w[11]);
+          t2 = Sum0 (g) + Maj (g, h, a);
+          b += t1;
+          f  = t1 + t2;
+
+          t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11];
+          w[11] += S1 (w[9]) + w[4] + S0 (w[12]);
+          t2 = Sum0 (f) + Maj (f, g, h);
+          a += t1;
+          e  = t1 + t2;
+
+          t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12];
+          w[12] += S1 (w[10]) + w[5] + S0 (w[13]);
+          t2 = Sum0 (e) + Maj (e, f, g);
+          h += t1;
+          d  = t1 + t2;
+
+          t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13];
+          w[13] += S1 (w[11]) + w[6] + S0 (w[14]);
+          t2 = Sum0 (d) + Maj (d, e, f);
+          g += t1;
+          c  = t1 + t2;
+
+          t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14];
+          w[14] += S1 (w[12]) + w[7] + S0 (w[15]);
+          t2 = Sum0 (c) + Maj (c, d, e);
+          f += t1;
+          b  = t1 + t2;
+
+          t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15];
+          w[15] += S1 (w[13]) + w[8] + S0 (w[0]);
+          t2 = Sum0 (b) + Maj (b, c, d);
+          e += t1;
+          a  = t1 + t2;
+
+          t += 16;
+        }
+
+      for (; t < 80; )
+        {
+          u64 t1, t2;
+
+          t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[0];
+          t2 = Sum0 (a) + Maj (a, b, c);
+          d += t1;
+          h  = t1 + t2;
+
+          t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[1];
+          t2 = Sum0 (h) + Maj (h, a, b);
+          c += t1;
+          g  = t1 + t2;
+
+          t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[2];
+          t2 = Sum0 (g) + Maj (g, h, a);
+          b += t1;
+          f  = t1 + t2;
+
+          t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[3];
+          t2 = Sum0 (f) + Maj (f, g, h);
+          a += t1;
+          e  = t1 + t2;
+
+          t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[4];
+          t2 = Sum0 (e) + Maj (e, f, g);
+          h += t1;
+          d  = t1 + t2;
+
+          t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[5];
+          t2 = Sum0 (d) + Maj (d, e, f);
+          g += t1;
+          c  = t1 + t2;
+
+          t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[6];
+          t2 = Sum0 (c) + Maj (c, d, e);
+          f += t1;
+          b  = t1 + t2;
+
+          t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[7];
+          t2 = Sum0 (b) + Maj (b, c, d);
+          e += t1;
+          a  = t1 + t2;
+
+          t1 = h + Sum1 (e) + Ch (e, f, g) + k[t+8] + w[8];
+          t2 = Sum0 (a) + Maj (a, b, c);
+          d += t1;
+          h  = t1 + t2;
+
+          t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+9] + w[9];
+          t2 = Sum0 (h) + Maj (h, a, b);
+          c += t1;
+          g  = t1 + t2;
+
+          t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+10] + w[10];
+          t2 = Sum0 (g) + Maj (g, h, a);
+          b += t1;
+          f  = t1 + t2;
+
+          t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+11] + w[11];
+          t2 = Sum0 (f) + Maj (f, g, h);
+          a += t1;
+          e  = t1 + t2;
+
+          t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+12] + w[12];
+          t2 = Sum0 (e) + Maj (e, f, g);
+          h += t1;
+          d  = t1 + t2;
+
+          t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+13] + w[13];
+          t2 = Sum0 (d) + Maj (d, e, f);
+          g += t1;
+          c  = t1 + t2;
+
+          t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+14] + w[14];
+          t2 = Sum0 (c) + Maj (c, d, e);
+          f += t1;
+          b  = t1 + t2;
+
+          t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+15] + w[15];
+          t2 = Sum0 (b) + Maj (b, c, d);
+          e += t1;
+          a  = t1 + t2;
+
+          t += 16;
+        }
+
+      /* Update chaining vars.  */
+      hd->h[0] += a;
+      hd->h[1] += b;
+      hd->h[2] += c;
+      hd->h[3] += d;
+      hd->h[4] += e;
+      hd->h[5] += f;
+      hd->h[6] += g;
+      hd->h[7] += h;
+
       data += 128;
     }
   while (--nblks);
 
-#ifdef ASM_EXTRA_STACK
-  /* 'transform_blk' is typically inlined and XMM6-XMM15 are stored at
-   *  the prologue of this function. Therefore need to add ASM_EXTRA_STACK to
-   *  here too.
-   */
-  burn += ASM_EXTRA_STACK;
-#endif
-#endif
-
-  return burn;
+  return (8 + 16) * sizeof(u64) + sizeof(u32) + 3 * sizeof(void*);
 }
+#endif /*!USE_ARM_ASM*/
 
 
 /* The routine final terminates the computation and
@@ -671,12 +779,10 @@ static void
 sha512_final (void *context)
 {
   SHA512_CONTEXT *hd = context;
-  unsigned int stack_burn_depth;
+  unsigned int burn;
   u64 t, th, msb, lsb;
   byte *p;
 
-  _gcry_md_block_write (context, NULL, 0); /* flush */ ;
-
   t = hd->bctx.nblocks;
   /* if (sizeof t == sizeof hd->bctx.nblocks) */
   th = hd->bctx.nblocks_high;
@@ -696,28 +802,41 @@ sha512_final (void *context)
   msb <<= 3;
   msb |= t >> 61;
 
-  if (hd->bctx.count < 112)
-    {                          /* enough room */
-      hd->bctx.buf[hd->bctx.count++] = 0x80;   /* pad */
-      while (hd->bctx.count < 112)
-        hd->bctx.buf[hd->bctx.count++] = 0;    /* pad */
+  if (0)
+    { }
+#ifdef USE_S390X_CRYPTO
+  else if (hd->use_s390x_crypto)
+    {
+      burn = do_sha512_final_s390x (hd, hd->bctx.buf, hd->bctx.count, msb, lsb);
     }
+#endif
   else
-    {                          /* need one extra block */
-      hd->bctx.buf[hd->bctx.count++] = 0x80;   /* pad character */
-      while (hd->bctx.count < 128)
-        hd->bctx.buf[hd->bctx.count++] = 0;
-      _gcry_md_block_write (context, NULL, 0); /* flush */ ;
-      memset (hd->bctx.buf, 0, 112);   /* fill next block with zeroes */
+    {
+      if (hd->bctx.count < 112)
+       {
+         /* enough room */
+         hd->bctx.buf[hd->bctx.count++] = 0x80;  /* pad */
+         if (hd->bctx.count < 112)
+           memset (&hd->bctx.buf[hd->bctx.count], 0, 112 - hd->bctx.count);
+       }
+      else
+       {
+         /* need one extra block */
+         hd->bctx.buf[hd->bctx.count++] = 0x80;  /* pad character */
+         if (hd->bctx.count < 128)
+           memset (&hd->bctx.buf[hd->bctx.count], 0, 128 - hd->bctx.count);
+         hd->bctx.count = 128;
+         _gcry_md_block_write (context, NULL, 0); /* flush */
+         memset (hd->bctx.buf, 0, 112);  /* fill next block with zeroes */
+       }
+      /* append the 128 bit count */
+      buf_put_be64(hd->bctx.buf + 112, msb);
+      buf_put_be64(hd->bctx.buf + 120, lsb);
+      burn = (*hd->bctx.bwrite) (hd, hd->bctx.buf, 1);
     }
-  /* append the 128 bit count */
-  buf_put_be64(hd->bctx.buf + 112, msb);
-  buf_put_be64(hd->bctx.buf + 120, lsb);
-  stack_burn_depth = transform (hd, hd->bctx.buf, 1);
-  _gcry_burn_stack (stack_burn_depth);
 
   p = hd->bctx.buf;
-#define X(a) do { buf_put_be64(p, hd->state.h##a); p += 8; } while (0)
+#define X(a) do { buf_put_be64(p, hd->state.h[a]); p += 8; } while (0)
   X (0);
   X (1);
   X (2);
@@ -729,6 +848,10 @@ sha512_final (void *context)
   X (6);
   X (7);
 #undef X
+
+  hd->bctx.count = 0;
+
+  _gcry_burn_stack (burn);
 }
 
 static byte *
@@ -739,32 +862,82 @@ 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)
+static void
+_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);
-  _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);
   sha512_final (&hd);
   memcpy (outbuf, hd.bctx.buf, 64);
 }
 
 
-/* Variant of the above shortcut function using multiple buffers.  */
-void
-_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, size_t nbytes,
+                          const gcry_buffer_t *iov, int iovcnt)
 {
   SHA512_CONTEXT hd;
 
-  sha512_init (&hd, 0);
+  (void)nbytes;
+
+  sha384_init (&hd, 0);
   for (;iovcnt > 0; iov++, iovcnt--)
     _gcry_md_block_write (&hd,
                           (const char*)iov[0].data + iov[0].off, iov[0].len);
   sha512_final (&hd);
-  memcpy (outbuf, hd.bctx.buf, 64);
+  memcpy (outbuf, hd.bctx.buf, 48);
+}
+
+
+
+/* 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, 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--)
+    _gcry_md_block_write (&hd,
+                          (const char*)iov[0].data + iov[0].off, iov[0].len);
+  sha512_final (&hd);
+  memcpy (outbuf, hd.bctx.buf, 32);
+}
+
+
+
+/* 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, 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,
+                          (const char*)iov[0].data + iov[0].off, iov[0].len);
+  sha512_final (&hd);
+  memcpy (outbuf, hd.bctx.buf, 28);
 }
 
 
@@ -877,6 +1050,102 @@ selftests_sha512 (int extended, selftest_report_func_t report)
   return GPG_ERR_SELFTEST_FAILED;
 }
 
+static gpg_err_code_t
+selftests_sha512_224 (int extended, selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+
+  what = "short string";
+  errtxt = _gcry_hash_selftest_check_one
+    (GCRY_MD_SHA512_224, 0,
+     "abc", 3,
+     "\x46\x34\x27\x0F\x70\x7B\x6A\x54\xDA\xAE\x75\x30\x46\x08\x42\xE2"
+     "\x0E\x37\xED\x26\x5C\xEE\xE9\xA4\x3E\x89\x24\xAA",
+     28);
+  if (errtxt)
+    goto failed;
+
+  if (extended)
+    {
+      what = "long string";
+      errtxt = _gcry_hash_selftest_check_one
+        (GCRY_MD_SHA512_224, 0,
+         "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+         "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+         "\x23\xFE\xC5\xBB\x94\xD6\x0B\x23\x30\x81\x92\x64\x0B\x0C\x45\x33"
+         "\x35\xD6\x64\x73\x4F\xE4\x0E\x72\x68\x67\x4A\xF9",
+         28);
+      if (errtxt)
+        goto failed;
+
+      what = "one million \"a\"";
+      errtxt = _gcry_hash_selftest_check_one
+        (GCRY_MD_SHA512_224, 1,
+         NULL, 0,
+         "\x37\xab\x33\x1d\x76\xf0\xd3\x6d\xe4\x22\xbd\x0e\xde\xb2\x2a\x28"
+         "\xac\xcd\x48\x7b\x7a\x84\x53\xae\x96\x5d\xd2\x87",
+         28);
+      if (errtxt)
+        goto failed;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA512_224, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+static gpg_err_code_t
+selftests_sha512_256 (int extended, selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+
+  what = "short string";
+  errtxt = _gcry_hash_selftest_check_one
+    (GCRY_MD_SHA512_256, 0,
+     "abc", 3,
+     "\x53\x04\x8E\x26\x81\x94\x1E\xF9\x9B\x2E\x29\xB7\x6B\x4C\x7D\xAB"
+     "\xE4\xC2\xD0\xC6\x34\xFC\x6D\x46\xE0\xE2\xF1\x31\x07\xE7\xAF\x23",
+     32);
+  if (errtxt)
+    goto failed;
+
+  if (extended)
+    {
+      what = "long string";
+      errtxt = _gcry_hash_selftest_check_one
+        (GCRY_MD_SHA512_256, 0,
+         "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+         "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112,
+         "\x39\x28\xE1\x84\xFB\x86\x90\xF8\x40\xDA\x39\x88\x12\x1D\x31\xBE"
+         "\x65\xCB\x9D\x3E\xF8\x3E\xE6\x14\x6F\xEA\xC8\x61\xE1\x9B\x56\x3A",
+         32);
+      if (errtxt)
+        goto failed;
+
+      what = "one million \"a\"";
+      errtxt = _gcry_hash_selftest_check_one
+        (GCRY_MD_SHA512_256, 1,
+         NULL, 0,
+         "\x9a\x59\xa0\x52\x93\x01\x87\xa9\x70\x38\xca\xe6\x92\xf3\x07\x08"
+         "\xaa\x64\x91\x92\x3e\xf5\x19\x43\x94\xdc\x68\xd5\x6c\x74\xfb\x21",
+         32);
+      if (errtxt)
+        goto failed;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SHA512_256, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
 
 /* Run a full self-test for ALGO and return 0 on success.  */
 static gpg_err_code_t
@@ -892,6 +1161,12 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
     case GCRY_MD_SHA512:
       ec = selftests_sha512 (extended, report);
       break;
+    case GCRY_MD_SHA512_224:
+      ec = selftests_sha512_224 (extended, report);
+      break;
+    case GCRY_MD_SHA512_256:
+      ec = selftests_sha512_256 (extended, report);
+      break;
     default:
       ec = GPG_ERR_DIGEST_ALGO;
       break;
@@ -903,40 +1178,43 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
 
 
 \f
-static byte sha512_asn[] =     /* Object ID is 2.16.840.1.101.3.4.2.3 */
+static const byte sha512_asn[] =       /* Object ID is 2.16.840.1.101.3.4.2.3 */
   {
     0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
     0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
     0x00, 0x04, 0x40
   };
 
-static gcry_md_oid_spec_t oid_spec_sha512[] =
+static const gcry_md_oid_spec_t oid_spec_sha512[] =
   {
     { "2.16.840.1.101.3.4.2.3" },
 
     /* PKCS#1 sha512WithRSAEncryption */
     { "1.2.840.113549.1.1.13" },
+    /* ANSI X9.62  ecdsaWithSHA512 */
+    { "1.2.840.10045.4.3.4" },
 
     { NULL }
   };
 
-gcry_md_spec_t _gcry_digest_spec_sha512 =
+const 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_buffers,
     sizeof (SHA512_CONTEXT),
     run_selftests
   };
 
-static byte sha384_asn[] =     /* Object ID is 2.16.840.1.101.3.4.2.2 */
+static const byte sha384_asn[] =       /* Object ID is 2.16.840.1.101.3.4.2.2 */
   {
     0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
     0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
     0x00, 0x04, 0x30
   };
 
-static gcry_md_oid_spec_t oid_spec_sha384[] =
+static const gcry_md_oid_spec_t oid_spec_sha384[] =
   {
     { "2.16.840.1.101.3.4.2.2" },
 
@@ -946,14 +1224,66 @@ static gcry_md_oid_spec_t oid_spec_sha384[] =
     /* SHA384WithECDSA: RFC 7427 (A.3.3.) */
     { "1.2.840.10045.4.3.3" },
 
+    /* ANSI X9.62  ecdsaWithSHA384 */
+    { "1.2.840.10045.4.3.3" },
+
     { NULL },
   };
 
-gcry_md_spec_t _gcry_digest_spec_sha384 =
+const 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_buffers,
+    sizeof (SHA512_CONTEXT),
+    run_selftests
+  };
+
+static const byte sha512_256_asn[] =
+  {
+    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06, 0x05,
+    0x00, 0x04, 0x20
+  };
+
+static const gcry_md_oid_spec_t oid_spec_sha512_256[] =
+  {
+    { "2.16.840.1.101.3.4.2.6" },
+
+    { NULL },
+  };
+
+const 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_buffers,
+    sizeof (SHA512_CONTEXT),
+    run_selftests
+  };
+
+static const byte sha512_224_asn[] =
+  {
+    0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
+    0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05, 0x05,
+    0x00, 0x04, 0x1c
+  };
+
+static const gcry_md_oid_spec_t oid_spec_sha512_224[] =
+  {
+    { "2.16.840.1.101.3.4.2.5" },
+
+    { NULL },
+  };
+
+const 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_buffers,
     sizeof (SHA512_CONTEXT),
     run_selftests
   };
diff --git a/cipher/sm3-aarch64.S b/cipher/sm3-aarch64.S
new file mode 100644 (file)
index 0000000..3fb8900
--- /dev/null
@@ -0,0 +1,657 @@
+/* sm3-aarch64.S - ARMv8/AArch64 accelerated SM3 transform function
+ *
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "asm-common-aarch64.h"
+
+#if defined(__AARCH64EL__) && \
+    defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
+    defined(HAVE_GCC_INLINE_ASM_AARCH64_NEON) && \
+    defined(USE_SM3)
+
+.cpu generic+simd
+
+/* Constants */
+
+.text
+.align 4
+ELF(.type _gcry_sm3_aarch64_consts,@object)
+_gcry_sm3_aarch64_consts:
+.LKtable:
+  .long 0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb
+  .long 0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc
+  .long 0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce
+  .long 0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6
+  .long 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c
+  .long 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce
+  .long 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec
+  .long 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5
+  .long 0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53
+  .long 0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d
+  .long 0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4
+  .long 0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43
+  .long 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c
+  .long 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce
+  .long 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec
+  .long 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5
+ELF(.size _gcry_sm3_aarch64_consts,.-_gcry_sm3_aarch64_consts)
+
+/* Context structure */
+
+#define state_h0 0
+#define state_h1 4
+#define state_h2 8
+#define state_h3 12
+#define state_h4 16
+#define state_h5 20
+#define state_h6 24
+#define state_h7 28
+
+/* Stack structure */
+
+#define STACK_W_SIZE        (32 * 2 * 3)
+
+#define STACK_W             (0)
+#define STACK_SIZE          (STACK_W + STACK_W_SIZE)
+
+/* Register macros */
+
+#define RSTATE x0
+#define RDATA  x1
+#define RNBLKS x2
+#define RKPTR  x28
+#define RFRAME x29
+
+#define ra w3
+#define rb w4
+#define rc w5
+#define rd w6
+#define re w7
+#define rf w8
+#define rg w9
+#define rh w10
+
+#define t0 w11
+#define t1 w12
+#define t2 w13
+#define t3 w14
+#define t4 w15
+#define t5 w16
+#define t6 w17
+
+#define k_even w19
+#define k_odd w20
+
+#define addr0 x21
+#define addr1 x22
+
+#define s0 w23
+#define s1 w24
+#define s2 w25
+#define s3 w26
+
+#define W0 v0
+#define W1 v1
+#define W2 v2
+#define W3 v3
+#define W4 v4
+#define W5 v5
+
+#define XTMP0 v6
+#define XTMP1 v7
+#define XTMP2 v16
+#define XTMP3 v17
+#define XTMP4 v18
+#define XTMP5 v19
+#define XTMP6 v20
+
+/* Helper macros. */
+
+#define _(...) /*_*/
+
+#define clear_vec(x) \
+        movi x.8h, #0;
+
+#define rolw(o, a, n) \
+        ror o, a, #(32 - n);
+
+/* Round function macros. */
+
+#define GG1_1(x, y, z, o, t) \
+        eor o, x, y;
+#define GG1_2(x, y, z, o, t) \
+        eor o, o, z;
+#define GG1_3(x, y, z, o, t)
+
+#define FF1_1(x, y, z, o, t) GG1_1(x, y, z, o, t)
+#define FF1_2(x, y, z, o, t)
+#define FF1_3(x, y, z, o, t) GG1_2(x, y, z, o, t)
+
+#define GG2_1(x, y, z, o, t) \
+        bic o, z, x;
+#define GG2_2(x, y, z, o, t) \
+        and t, y, x;
+#define GG2_3(x, y, z, o, t) \
+        eor o, o, t;
+
+#define FF2_1(x, y, z, o, t) \
+        eor o, x, y;
+#define FF2_2(x, y, z, o, t) \
+        and t, x, y; \
+        and o, o, z;
+#define FF2_3(x, y, z, o, t) \
+        eor o, o, t;
+
+#define R(i, a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \
+        K_LOAD(round); \
+        ldr t5, [sp, #(wtype##_W1_ADDR(round, widx))]; \
+        rolw(t0, a, 12);                              /* rol(a, 12) => t0 */ \
+      IOP(1, iop_param); \
+        FF##i##_1(a, b, c, t1, t2); \
+        ldr t6, [sp, #(wtype##_W1W2_ADDR(round, widx))]; \
+        add k, k, e; \
+      IOP(2, iop_param); \
+        GG##i##_1(e, f, g, t3, t4); \
+        FF##i##_2(a, b, c, t1, t2); \
+      IOP(3, iop_param); \
+        add k, k, t0; \
+        add h, h, t5; \
+        add d, d, t6;                                 /* w1w2 + d => d */ \
+      IOP(4, iop_param); \
+        rolw(k, k, 7);                                /* rol (t0 + e + t), 7) => k */ \
+        GG##i##_2(e, f, g, t3, t4); \
+        add h, h, k;                                  /* h + w1 + k => h */ \
+      IOP(5, iop_param); \
+        FF##i##_3(a, b, c, t1, t2); \
+        eor t0, t0, k;                                /* k ^ t0 => t0 */ \
+        GG##i##_3(e, f, g, t3, t4); \
+        add d, d, t1;                                 /* FF(a,b,c) + d => d */ \
+      IOP(6, iop_param); \
+        add t3, t3, h;                                /* GG(e,f,g) + h => t3 */ \
+        rolw(b, b, 9);                                /* rol(b, 9) => b */ \
+        eor h, t3, t3, ror #(32-9); \
+      IOP(7, iop_param); \
+        add d, d, t0;                                 /* t0 + d => d */ \
+        rolw(f, f, 19);                               /* rol(f, 19) => f */ \
+      IOP(8, iop_param); \
+        eor h, h, t3, ror #(32-17);                   /* P0(t3) => h */ \
+
+#define R1(a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \
+        R(1, ##a, ##b, ##c, ##d, ##e, ##f, ##g, ##h, ##k, K_LOAD, round, widx, wtype, IOP, iop_param)
+
+#define R2(a, b, c, d, e, f, g, h, k, K_LOAD, round, widx, wtype, IOP, iop_param) \
+        R(2, ##a, ##b, ##c, ##d, ##e, ##f, ##g, ##h, ##k, K_LOAD, round, widx, wtype, IOP, iop_param)
+
+#define KL(round) \
+        ldp k_even, k_odd, [RKPTR, #(4*(round))];
+
+/* Input expansion macros. */
+
+/* Byte-swapped input address. */
+#define IW_W_ADDR(round, widx, offs) \
+        (STACK_W + ((round) / 4) * 64 + (offs) + ((widx) * 4))
+
+/* Expanded input address. */
+#define XW_W_ADDR(round, widx, offs) \
+        (STACK_W + ((((round) / 3) - 4) % 2) * 64 + (offs) + ((widx) * 4))
+
+/* Rounds 1-12, byte-swapped input block addresses. */
+#define IW_W1_ADDR(round, widx)   IW_W_ADDR(round, widx, 32)
+#define IW_W1W2_ADDR(round, widx) IW_W_ADDR(round, widx, 48)
+
+/* Rounds 1-12, expanded input block addresses. */
+#define XW_W1_ADDR(round, widx)   XW_W_ADDR(round, widx, 0)
+#define XW_W1W2_ADDR(round, widx) XW_W_ADDR(round, widx, 16)
+
+/* Input block loading.
+ * Interleaving within round function needed for in-order CPUs. */
+#define LOAD_W_VEC_1_1() \
+        add addr0, sp, #IW_W1_ADDR(0, 0);
+#define LOAD_W_VEC_1_2() \
+        add addr1, sp, #IW_W1_ADDR(4, 0);
+#define LOAD_W_VEC_1_3() \
+        ld1 {W0.16b}, [RDATA], #16;
+#define LOAD_W_VEC_1_4() \
+        ld1 {W1.16b}, [RDATA], #16;
+#define LOAD_W_VEC_1_5() \
+        ld1 {W2.16b}, [RDATA], #16;
+#define LOAD_W_VEC_1_6() \
+        ld1 {W3.16b}, [RDATA], #16;
+#define LOAD_W_VEC_1_7() \
+        rev32 XTMP0.16b, W0.16b;
+#define LOAD_W_VEC_1_8() \
+        rev32 XTMP1.16b, W1.16b;
+#define LOAD_W_VEC_2_1() \
+        rev32 XTMP2.16b, W2.16b;
+#define LOAD_W_VEC_2_2() \
+        rev32 XTMP3.16b, W3.16b;
+#define LOAD_W_VEC_2_3() \
+        eor XTMP4.16b, XTMP1.16b, XTMP0.16b;
+#define LOAD_W_VEC_2_4() \
+        eor XTMP5.16b, XTMP2.16b, XTMP1.16b;
+#define LOAD_W_VEC_2_5() \
+        st1 {XTMP0.16b}, [addr0], #16;
+#define LOAD_W_VEC_2_6() \
+        st1 {XTMP4.16b}, [addr0]; \
+        add addr0, sp, #IW_W1_ADDR(8, 0);
+#define LOAD_W_VEC_2_7() \
+        eor XTMP6.16b, XTMP3.16b, XTMP2.16b;
+#define LOAD_W_VEC_2_8() \
+        ext W0.16b, XTMP0.16b, XTMP0.16b, #8;  /* W0: xx, w0, xx, xx */
+#define LOAD_W_VEC_3_1() \
+        mov W2.16b, XTMP1.16b;                 /* W2: xx, w6, w5, w4 */
+#define LOAD_W_VEC_3_2() \
+        st1 {XTMP1.16b}, [addr1], #16;
+#define LOAD_W_VEC_3_3() \
+        st1 {XTMP5.16b}, [addr1]; \
+        ext W1.16b, XTMP0.16b, XTMP0.16b, #4;  /* W1: xx, w3, w2, w1 */
+#define LOAD_W_VEC_3_4() \
+        ext W3.16b, XTMP1.16b, XTMP2.16b, #12; /* W3: xx, w9, w8, w7 */
+#define LOAD_W_VEC_3_5() \
+        ext W4.16b, XTMP2.16b, XTMP3.16b, #8;  /* W4: xx, w12, w11, w10 */
+#define LOAD_W_VEC_3_6() \
+        st1 {XTMP2.16b}, [addr0], #16;
+#define LOAD_W_VEC_3_7() \
+        st1 {XTMP6.16b}, [addr0];
+#define LOAD_W_VEC_3_8() \
+        ext W5.16b, XTMP3.16b, XTMP3.16b, #4;  /* W5: xx, w15, w14, w13 */
+
+#define LOAD_W_VEC_1(iop_num, ...) \
+        LOAD_W_VEC_1_##iop_num()
+#define LOAD_W_VEC_2(iop_num, ...) \
+        LOAD_W_VEC_2_##iop_num()
+#define LOAD_W_VEC_3(iop_num, ...) \
+        LOAD_W_VEC_3_##iop_num()
+
+/* Message scheduling. Note: 3 words per vector register.
+ * Interleaving within round function needed for in-order CPUs. */
+#define SCHED_W_1_1(round, w0, w1, w2, w3, w4, w5) \
+        /* Load (w[i - 16]) => XTMP0 */ \
+        /* Load (w[i - 13]) => XTMP5 */ \
+        ext XTMP0.16b, w0.16b, w0.16b, #12;    /* XTMP0: w0, xx, xx, xx */
+#define SCHED_W_1_2(round, w0, w1, w2, w3, w4, w5) \
+        ext XTMP5.16b, w1.16b, w1.16b, #12;
+#define SCHED_W_1_3(round, w0, w1, w2, w3, w4, w5) \
+        ext XTMP0.16b, XTMP0.16b, w1.16b, #12; /* XTMP0: xx, w2, w1, w0 */
+#define SCHED_W_1_4(round, w0, w1, w2, w3, w4, w5) \
+        ext XTMP5.16b, XTMP5.16b, w2.16b, #12;
+#define SCHED_W_1_5(round, w0, w1, w2, w3, w4, w5) \
+        /* w[i - 9] == w3 */ \
+        /* W3 ^ XTMP0 => XTMP0 */ \
+        eor XTMP0.16b, XTMP0.16b, w3.16b;
+#define SCHED_W_1_6(round, w0, w1, w2, w3, w4, w5) \
+        /* w[i - 3] == w5 */ \
+        /* rol(XMM5, 15) ^ XTMP0 => XTMP0 */ \
+        /* rol(XTMP5, 7) => XTMP1 */ \
+        add addr0, sp, #XW_W1_ADDR((round), 0); \
+        shl XTMP2.4s, w5.4s, #15;
+#define SCHED_W_1_7(round, w0, w1, w2, w3, w4, w5) \
+        shl XTMP1.4s, XTMP5.4s, #7;
+#define SCHED_W_1_8(round, w0, w1, w2, w3, w4, w5) \
+        sri XTMP2.4s, w5.4s, #(32-15);
+#define SCHED_W_2_1(round, w0, w1, w2, w3, w4, w5) \
+        sri XTMP1.4s, XTMP5.4s, #(32-7);
+#define SCHED_W_2_2(round, w0, w1, w2, w3, w4, w5) \
+        eor XTMP0.16b, XTMP0.16b, XTMP2.16b;
+#define SCHED_W_2_3(round, w0, w1, w2, w3, w4, w5) \
+        /* w[i - 6] == W4 */ \
+        /* W4 ^ XTMP1 => XTMP1 */ \
+        eor XTMP1.16b, XTMP1.16b, w4.16b;
+#define SCHED_W_2_4(round, w0, w1, w2, w3, w4, w5) \
+        /* P1(XTMP0) ^ XTMP1 => W0 */ \
+        shl XTMP3.4s, XTMP0.4s, #15;
+#define SCHED_W_2_5(round, w0, w1, w2, w3, w4, w5) \
+        shl XTMP4.4s, XTMP0.4s, #23;
+#define SCHED_W_2_6(round, w0, w1, w2, w3, w4, w5) \
+        eor w0.16b, XTMP1.16b, XTMP0.16b;
+#define SCHED_W_2_7(round, w0, w1, w2, w3, w4, w5) \
+        sri XTMP3.4s, XTMP0.4s, #(32-15);
+#define SCHED_W_2_8(round, w0, w1, w2, w3, w4, w5) \
+        sri XTMP4.4s, XTMP0.4s, #(32-23);
+#define SCHED_W_3_1(round, w0, w1, w2, w3, w4, w5) \
+        eor w0.16b, w0.16b, XTMP3.16b;
+#define SCHED_W_3_2(round, w0, w1, w2, w3, w4, w5) \
+        /* Load (w[i - 3]) => XTMP2 */ \
+        ext XTMP2.16b, w4.16b, w4.16b, #12;
+#define SCHED_W_3_3(round, w0, w1, w2, w3, w4, w5) \
+        eor w0.16b, w0.16b, XTMP4.16b;
+#define SCHED_W_3_4(round, w0, w1, w2, w3, w4, w5) \
+        ext XTMP2.16b, XTMP2.16b, w5.16b, #12;
+#define SCHED_W_3_5(round, w0, w1, w2, w3, w4, w5) \
+        /* W1 ^ W2 => XTMP3 */ \
+        eor XTMP3.16b, XTMP2.16b, w0.16b;
+#define SCHED_W_3_6(round, w0, w1, w2, w3, w4, w5)
+#define SCHED_W_3_7(round, w0, w1, w2, w3, w4, w5) \
+        st1 { XTMP2.16b-XTMP3.16b }, [addr0];
+#define SCHED_W_3_8(round, w0, w1, w2, w3, w4, w5)
+
+#define SCHED_W_W0W1W2W3W4W5_1(iop_num, round) \
+        SCHED_W_1_##iop_num(round, W0, W1, W2, W3, W4, W5)
+#define SCHED_W_W0W1W2W3W4W5_2(iop_num, round) \
+        SCHED_W_2_##iop_num(round, W0, W1, W2, W3, W4, W5)
+#define SCHED_W_W0W1W2W3W4W5_3(iop_num, round) \
+        SCHED_W_3_##iop_num(round, W0, W1, W2, W3, W4, W5)
+
+#define SCHED_W_W1W2W3W4W5W0_1(iop_num, round) \
+        SCHED_W_1_##iop_num(round, W1, W2, W3, W4, W5, W0)
+#define SCHED_W_W1W2W3W4W5W0_2(iop_num, round) \
+        SCHED_W_2_##iop_num(round, W1, W2, W3, W4, W5, W0)
+#define SCHED_W_W1W2W3W4W5W0_3(iop_num, round) \
+        SCHED_W_3_##iop_num(round, W1, W2, W3, W4, W5, W0)
+
+#define SCHED_W_W2W3W4W5W0W1_1(iop_num, round) \
+        SCHED_W_1_##iop_num(round, W2, W3, W4, W5, W0, W1)
+#define SCHED_W_W2W3W4W5W0W1_2(iop_num, round) \
+        SCHED_W_2_##iop_num(round, W2, W3, W4, W5, W0, W1)
+#define SCHED_W_W2W3W4W5W0W1_3(iop_num, round) \
+        SCHED_W_3_##iop_num(round, W2, W3, W4, W5, W0, W1)
+
+#define SCHED_W_W3W4W5W0W1W2_1(iop_num, round) \
+        SCHED_W_1_##iop_num(round, W3, W4, W5, W0, W1, W2)
+#define SCHED_W_W3W4W5W0W1W2_2(iop_num, round) \
+        SCHED_W_2_##iop_num(round, W3, W4, W5, W0, W1, W2)
+#define SCHED_W_W3W4W5W0W1W2_3(iop_num, round) \
+        SCHED_W_3_##iop_num(round, W3, W4, W5, W0, W1, W2)
+
+#define SCHED_W_W4W5W0W1W2W3_1(iop_num, round) \
+        SCHED_W_1_##iop_num(round, W4, W5, W0, W1, W2, W3)
+#define SCHED_W_W4W5W0W1W2W3_2(iop_num, round) \
+        SCHED_W_2_##iop_num(round, W4, W5, W0, W1, W2, W3)
+#define SCHED_W_W4W5W0W1W2W3_3(iop_num, round) \
+        SCHED_W_3_##iop_num(round, W4, W5, W0, W1, W2, W3)
+
+#define SCHED_W_W5W0W1W2W3W4_1(iop_num, round) \
+        SCHED_W_1_##iop_num(round, W5, W0, W1, W2, W3, W4)
+#define SCHED_W_W5W0W1W2W3W4_2(iop_num, round) \
+        SCHED_W_2_##iop_num(round, W5, W0, W1, W2, W3, W4)
+#define SCHED_W_W5W0W1W2W3W4_3(iop_num, round) \
+        SCHED_W_3_##iop_num(round, W5, W0, W1, W2, W3, W4)
+
+/*
+ * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
+ *
+ * unsigned int
+ * _gcry_sm3_transform_aarch64 (void *ctx, const unsigned char *data,
+ *                              size_t nblks)
+ */
+.align 3
+.globl _gcry_sm3_transform_aarch64
+ELF(.type _gcry_sm3_transform_aarch64,%function;)
+_gcry_sm3_transform_aarch64:
+  CFI_STARTPROC();
+
+  ldp ra, rb, [RSTATE, #0];
+  ldp rc, rd, [RSTATE, #8];
+  ldp re, rf, [RSTATE, #16];
+  ldp rg, rh, [RSTATE, #24];
+
+  stp x28, x29, [sp, #-16]!;
+  CFI_ADJUST_CFA_OFFSET(16);
+  CFI_REG_ON_STACK(28, 0);
+  CFI_REG_ON_STACK(29, 8);
+  stp x19, x20, [sp, #-16]!;
+  CFI_ADJUST_CFA_OFFSET(16);
+  CFI_REG_ON_STACK(19, 0);
+  CFI_REG_ON_STACK(20, 8);
+  stp x21, x22, [sp, #-16]!;
+  CFI_ADJUST_CFA_OFFSET(16);
+  CFI_REG_ON_STACK(21, 0);
+  CFI_REG_ON_STACK(22, 8);
+  stp x23, x24, [sp, #-16]!;
+  CFI_ADJUST_CFA_OFFSET(16);
+  CFI_REG_ON_STACK(23, 0);
+  CFI_REG_ON_STACK(24, 8);
+  stp x25, x26, [sp, #-16]!;
+  CFI_ADJUST_CFA_OFFSET(16);
+  CFI_REG_ON_STACK(25, 0);
+  CFI_REG_ON_STACK(26, 8);
+  mov RFRAME, sp;
+  CFI_DEF_CFA_REGISTER(RFRAME);
+
+  sub addr0, sp, #STACK_SIZE;
+  GET_DATA_POINTER(RKPTR, .LKtable);
+  and sp, addr0, #(~63);
+
+  /* Preload first block. */
+  LOAD_W_VEC_1(1, 0);
+  LOAD_W_VEC_1(2, 0);
+  LOAD_W_VEC_1(3, 0);
+  LOAD_W_VEC_1(4, 0);
+  LOAD_W_VEC_1(5, 0);
+  LOAD_W_VEC_1(6, 0);
+  LOAD_W_VEC_1(7, 0);
+  LOAD_W_VEC_1(8, 0);
+  LOAD_W_VEC_2(1, 0);
+  LOAD_W_VEC_2(2, 0);
+  LOAD_W_VEC_2(3, 0);
+  LOAD_W_VEC_2(4, 0);
+  LOAD_W_VEC_2(5, 0);
+  LOAD_W_VEC_2(6, 0);
+  LOAD_W_VEC_2(7, 0);
+  LOAD_W_VEC_2(8, 0);
+  LOAD_W_VEC_3(1, 0);
+  LOAD_W_VEC_3(2, 0);
+  LOAD_W_VEC_3(3, 0);
+  LOAD_W_VEC_3(4, 0);
+  LOAD_W_VEC_3(5, 0);
+  LOAD_W_VEC_3(6, 0);
+  LOAD_W_VEC_3(7, 0);
+  LOAD_W_VEC_3(8, 0);
+
+.balign 16
+.Loop:
+  /* Transform 0-3 */
+  R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 0, 0, IW, _, 0);
+  R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  1, 1, IW, _, 0);
+  R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 2, 2, IW, _, 0);
+  R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  3, 3, IW, _, 0);
+
+  /* Transform 4-7 + Precalc 12-14 */
+  R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 4, 0, IW, _, 0);
+  R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  5, 1, IW, _, 0);
+  R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 6, 2, IW, SCHED_W_W0W1W2W3W4W5_1, 12);
+  R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  7, 3, IW, SCHED_W_W0W1W2W3W4W5_2, 12);
+
+  /* Transform 8-11 + Precalc 12-17 */
+  R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 8, 0, IW, SCHED_W_W0W1W2W3W4W5_3, 12);
+  R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  9, 1, IW, SCHED_W_W1W2W3W4W5W0_1, 15);
+  R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 10, 2, IW, SCHED_W_W1W2W3W4W5W0_2, 15);
+  R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  11, 3, IW, SCHED_W_W1W2W3W4W5W0_3, 15);
+
+  /* Transform 12-14 + Precalc 18-20 */
+  R1(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 12, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 18);
+  R1(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  13, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 18);
+  R1(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 14, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 18);
+
+  /* Transform 15-17 + Precalc 21-23 */
+  R1(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  15, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 21);
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 16, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 21);
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  17, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 21);
+
+  /* Transform 18-20 + Precalc 24-26 */
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 18, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 24)
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  19, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 24)
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 20, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 24)
+
+  /* Transform 21-23 + Precalc 27-29 */
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  21, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 27)
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 22, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 27)
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  23, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 27)
+
+  /* Transform 24-26 + Precalc 30-32 */
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 24, 0, XW, SCHED_W_W0W1W2W3W4W5_1, 30)
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  25, 1, XW, SCHED_W_W0W1W2W3W4W5_2, 30)
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 26, 2, XW, SCHED_W_W0W1W2W3W4W5_3, 30)
+
+  /* Transform 27-29 + Precalc 33-35 */
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  27, 0, XW, SCHED_W_W1W2W3W4W5W0_1, 33)
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 28, 1, XW, SCHED_W_W1W2W3W4W5W0_2, 33)
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  29, 2, XW, SCHED_W_W1W2W3W4W5W0_3, 33)
+
+  /* Transform 30-32 + Precalc 36-38 */
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 30, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 36)
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  31, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 36)
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 32, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 36)
+
+  /* Transform 33-35 + Precalc 39-41 */
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  33, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 39)
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 34, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 39)
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  35, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 39)
+
+  /* Transform 36-38 + Precalc 42-44 */
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 36, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 42)
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  37, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 42)
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 38, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 42)
+
+  /* Transform 39-41 + Precalc 45-47 */
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  39, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 45)
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 40, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 45)
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  41, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 45)
+
+  /* Transform 42-44 + Precalc 48-50 */
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 42, 0, XW, SCHED_W_W0W1W2W3W4W5_1, 48)
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  43, 1, XW, SCHED_W_W0W1W2W3W4W5_2, 48)
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 44, 2, XW, SCHED_W_W0W1W2W3W4W5_3, 48)
+
+  /* Transform 45-47 + Precalc 51-53 */
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  45, 0, XW, SCHED_W_W1W2W3W4W5W0_1, 51)
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 46, 1, XW, SCHED_W_W1W2W3W4W5W0_2, 51)
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  47, 2, XW, SCHED_W_W1W2W3W4W5W0_3, 51)
+
+  /* Transform 48-50 + Precalc 54-56 */
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 48, 0, XW, SCHED_W_W2W3W4W5W0W1_1, 54)
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  49, 1, XW, SCHED_W_W2W3W4W5W0W1_2, 54)
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 50, 2, XW, SCHED_W_W2W3W4W5W0W1_3, 54)
+
+  /* Transform 51-53 + Precalc 57-59 */
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  51, 0, XW, SCHED_W_W3W4W5W0W1W2_1, 57)
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 52, 1, XW, SCHED_W_W3W4W5W0W1W2_2, 57)
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  53, 2, XW, SCHED_W_W3W4W5W0W1W2_3, 57)
+
+  /* Transform 54-56 + Precalc 60-62 */
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 54, 0, XW, SCHED_W_W4W5W0W1W2W3_1, 60)
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  55, 1, XW, SCHED_W_W4W5W0W1W2W3_2, 60)
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 56, 2, XW, SCHED_W_W4W5W0W1W2W3_3, 60)
+
+  /* Transform 57-59 + Precalc 63 */
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  57, 0, XW, SCHED_W_W5W0W1W2W3W4_1, 63)
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 58, 1, XW, SCHED_W_W5W0W1W2W3W4_2, 63)
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  59, 2, XW, SCHED_W_W5W0W1W2W3W4_3, 63)
+
+  /* Transform 60 */
+  R2(ra, rb, rc, rd, re, rf, rg, rh, k_even, KL, 60, 0, XW, _, _);
+  subs RNBLKS, RNBLKS, #1;
+  b.eq .Lend;
+
+  /* Transform 61-63 + Preload next block */
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  61, 1, XW, LOAD_W_VEC_1, _);
+  ldp s0, s1, [RSTATE, #0];
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 62, 2, XW, LOAD_W_VEC_2, _);
+  ldp s2, s3, [RSTATE, #8];
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  63, 0, XW, LOAD_W_VEC_3, _);
+
+  /* Update the chaining variables. */
+  eor ra, ra, s0;
+  eor rb, rb, s1;
+  ldp s0, s1, [RSTATE, #16];
+  eor rc, rc, s2;
+  ldp k_even, k_odd, [RSTATE, #24];
+  eor rd, rd, s3;
+  eor re, re, s0;
+  stp ra, rb, [RSTATE, #0];
+  eor rf, rf, s1;
+  stp rc, rd, [RSTATE, #8];
+  eor rg, rg, k_even;
+  stp re, rf, [RSTATE, #16];
+  eor rh, rh, k_odd;
+  stp rg, rh, [RSTATE, #24];
+  b .Loop;
+
+.Lend:
+  /* Transform 61-63 */
+  R2(rd, ra, rb, rc, rh, re, rf, rg, k_odd,  _,  61, 1, XW, _, _);
+  ldp s0, s1, [RSTATE, #0];
+  R2(rc, rd, ra, rb, rg, rh, re, rf, k_even, KL, 62, 2, XW, _, _);
+  ldp s2, s3, [RSTATE, #8];
+  R2(rb, rc, rd, ra, rf, rg, rh, re, k_odd,  _,  63, 0, XW, _, _);
+
+  /* Update the chaining variables. */
+  eor ra, ra, s0;
+  clear_vec(W0);
+  eor rb, rb, s1;
+  clear_vec(W1);
+  ldp s0, s1, [RSTATE, #16];
+  clear_vec(W2);
+  eor rc, rc, s2;
+  clear_vec(W3);
+  ldp k_even, k_odd, [RSTATE, #24];
+  clear_vec(W4);
+  eor rd, rd, s3;
+  clear_vec(W5);
+  eor re, re, s0;
+  clear_vec(XTMP0);
+  stp ra, rb, [RSTATE, #0];
+  clear_vec(XTMP1);
+  eor rf, rf, s1;
+  clear_vec(XTMP2);
+  stp rc, rd, [RSTATE, #8];
+  clear_vec(XTMP3);
+  eor rg, rg, k_even;
+  clear_vec(XTMP4);
+  stp re, rf, [RSTATE, #16];
+  clear_vec(XTMP5);
+  eor rh, rh, k_odd;
+  clear_vec(XTMP6);
+  stp rg, rh, [RSTATE, #24];
+
+  /* Clear message expansion area */
+  add addr0, sp, #STACK_W;
+  eor x0, x0, x0; // stack burned
+  st1 {W0.16b-W3.16b}, [addr0], #64;
+  st1 {W0.16b-W3.16b}, [addr0], #64;
+  st1 {W0.16b-W3.16b}, [addr0];
+
+  mov sp, RFRAME;
+  CFI_DEF_CFA_REGISTER(sp);
+
+  ldp x25, x26, [sp], #16;
+  CFI_ADJUST_CFA_OFFSET(-16);
+  CFI_RESTORE(x25);
+  CFI_RESTORE(x26);
+  ldp x23, x24, [sp], #16;
+  CFI_ADJUST_CFA_OFFSET(-16);
+  CFI_RESTORE(x23);
+  CFI_RESTORE(x24);
+  ldp x21, x22, [sp], #16;
+  CFI_ADJUST_CFA_OFFSET(-16);
+  CFI_RESTORE(x21);
+  CFI_RESTORE(x22);
+  ldp x19, x20, [sp], #16;
+  CFI_ADJUST_CFA_OFFSET(-16);
+  CFI_RESTORE(x19);
+  CFI_RESTORE(x20);
+  ldp x28, x29, [sp], #16;
+  CFI_ADJUST_CFA_OFFSET(-16);
+  CFI_RESTORE(x28);
+  CFI_RESTORE(x29);
+  ret_spec_stop
+  CFI_ENDPROC();
+ELF(.size _gcry_sm3_transform_aarch64, .-_gcry_sm3_transform_aarch64;)
+
+#endif
diff --git a/cipher/sm3-avx-bmi2-amd64.S b/cipher/sm3-avx-bmi2-amd64.S
new file mode 100644 (file)
index 0000000..d9b6206
--- /dev/null
@@ -0,0 +1,553 @@
+/* sm3-avx-bmi2-amd64.S - Intel AVX/BMI2 accelerated SM3 transform function
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef __x86_64__
+#include <config.h>
+
+#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
+    defined(HAVE_GCC_INLINE_ASM_AVX) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \
+    defined(USE_SM3)
+
+#include "asm-common-amd64.h"
+
+
+/* Context structure */
+
+#define state_h0 0
+#define state_h1 4
+#define state_h2 8
+#define state_h3 12
+#define state_h4 16
+#define state_h5 20
+#define state_h6 24
+#define state_h7 28
+
+/* Constants */
+
+.text
+.align 16
+ELF(.type _gcry_sm3_avx2_consts,@object)
+_gcry_sm3_avx2_consts:
+.Lbe32mask:
+  .long 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f
+ELF(.size _gcry_sm3_avx2_consts,.-_gcry_sm3_avx2_consts)
+
+/* Round constant macros */
+
+#define K0   2043430169  /* 0x79cc4519 */
+#define K1   -208106958  /* 0xf3988a32 */
+#define K2   -416213915  /* 0xe7311465 */
+#define K3   -832427829  /* 0xce6228cb */
+#define K4  -1664855657  /* 0x9cc45197 */
+#define K5    965255983  /* 0x3988a32f */
+#define K6   1930511966  /* 0x7311465e */
+#define K7   -433943364  /* 0xe6228cbc */
+#define K8   -867886727  /* 0xcc451979 */
+#define K9  -1735773453  /* 0x988a32f3 */
+#define K10   823420391  /* 0x311465e7 */
+#define K11  1646840782  /* 0x6228cbce */
+#define K12 -1001285732  /* 0xc451979c */
+#define K13 -2002571463  /* 0x88a32f39 */
+#define K14   289824371  /* 0x11465e73 */
+#define K15   579648742  /* 0x228cbce6 */
+#define K16 -1651869049  /* 0x9d8a7a87 */
+#define K17   991229199  /* 0x3b14f50f */
+#define K18  1982458398  /* 0x7629ea1e */
+#define K19  -330050500  /* 0xec53d43c */
+#define K20  -660100999  /* 0xd8a7a879 */
+#define K21 -1320201997  /* 0xb14f50f3 */
+#define K22  1654563303  /* 0x629ea1e7 */
+#define K23  -985840690  /* 0xc53d43ce */
+#define K24 -1971681379  /* 0x8a7a879d */
+#define K25   351604539  /* 0x14f50f3b */
+#define K26   703209078  /* 0x29ea1e76 */
+#define K27  1406418156  /* 0x53d43cec */
+#define K28 -1482130984  /* 0xa7a879d8 */
+#define K29  1330705329  /* 0x4f50f3b1 */
+#define K30 -1633556638  /* 0x9ea1e762 */
+#define K31  1027854021  /* 0x3d43cec5 */
+#define K32  2055708042  /* 0x7a879d8a */
+#define K33  -183551212  /* 0xf50f3b14 */
+#define K34  -367102423  /* 0xea1e7629 */
+#define K35  -734204845  /* 0xd43cec53 */
+#define K36 -1468409689  /* 0xa879d8a7 */
+#define K37  1358147919  /* 0x50f3b14f */
+#define K38 -1578671458  /* 0xa1e7629e */
+#define K39  1137624381  /* 0x43cec53d */
+#define K40 -2019718534  /* 0x879d8a7a */
+#define K41   255530229  /* 0x0f3b14f5 */
+#define K42   511060458  /* 0x1e7629ea */
+#define K43  1022120916  /* 0x3cec53d4 */
+#define K44  2044241832  /* 0x79d8a7a8 */
+#define K45  -206483632  /* 0xf3b14f50 */
+#define K46  -412967263  /* 0xe7629ea1 */
+#define K47  -825934525  /* 0xcec53d43 */
+#define K48 -1651869049  /* 0x9d8a7a87 */
+#define K49   991229199  /* 0x3b14f50f */
+#define K50  1982458398  /* 0x7629ea1e */
+#define K51  -330050500  /* 0xec53d43c */
+#define K52  -660100999  /* 0xd8a7a879 */
+#define K53 -1320201997  /* 0xb14f50f3 */
+#define K54  1654563303  /* 0x629ea1e7 */
+#define K55  -985840690  /* 0xc53d43ce */
+#define K56 -1971681379  /* 0x8a7a879d */
+#define K57   351604539  /* 0x14f50f3b */
+#define K58   703209078  /* 0x29ea1e76 */
+#define K59  1406418156  /* 0x53d43cec */
+#define K60 -1482130984  /* 0xa7a879d8 */
+#define K61  1330705329  /* 0x4f50f3b1 */
+#define K62 -1633556638  /* 0x9ea1e762 */
+#define K63  1027854021  /* 0x3d43cec5 */
+
+/* Register macros */
+
+#define RSTATE %rdi
+#define RDATA  %rsi
+#define RNBLKS %rdx
+
+#define t0 %eax
+#define t1 %ebx
+#define t2 %ecx
+
+#define a %r8d
+#define b %r9d
+#define c %r10d
+#define d %r11d
+#define e %r12d
+#define f %r13d
+#define g %r14d
+#define h %r15d
+
+#define W0 %xmm0
+#define W1 %xmm1
+#define W2 %xmm2
+#define W3 %xmm3
+#define W4 %xmm4
+#define W5 %xmm5
+
+#define XTMP0 %xmm6
+#define XTMP1 %xmm7
+#define XTMP2 %xmm8
+#define XTMP3 %xmm9
+#define XTMP4 %xmm10
+#define XTMP5 %xmm11
+#define XTMP6 %xmm12
+
+#define BSWAP_REG %xmm15
+
+/* Stack structure */
+
+#define STACK_W_SIZE        (32 * 2 * 3)
+#define STACK_REG_SAVE_SIZE (64)
+
+#define STACK_W             (0)
+#define STACK_REG_SAVE      (STACK_W + STACK_W_SIZE)
+#define STACK_SIZE          (STACK_REG_SAVE + STACK_REG_SAVE_SIZE)
+
+/* Instruction helpers. */
+
+#define roll2(v, reg) \
+        roll $(v), reg;
+
+#define roll3mov(v, src, dst) \
+        movl src, dst; \
+        roll $(v), dst;
+
+#define roll3(v, src, dst) \
+        rorxl $(32-(v)), src, dst;
+
+#define addl2(a, out) \
+        leal (a, out), out;
+
+/* Round function macros. */
+
+#define GG1(x, y, z, o, t) \
+        movl x, o; \
+        xorl y, o; \
+        xorl z, o;
+
+#define FF1(x, y, z, o, t) GG1(x, y, z, o, t)
+
+#define GG2(x, y, z, o, t) \
+        andnl z, x, o; \
+        movl y, t; \
+        andl x, t; \
+        addl2(t, o);
+
+#define FF2(x, y, z, o, t) \
+        movl y, o; \
+        xorl x, o; \
+        movl y, t; \
+        andl x, t; \
+        andl z, o; \
+        xorl t, o;
+
+#define R(i, a, b, c, d, e, f, g, h, round, widx, wtype) \
+        /* rol(a, 12) => t0 */ \
+          roll3mov(12, a, t0); /* rorxl here would reduce perf by 6% on zen3 */ \
+        /* rol (t0 + e + t), 7) => t1 */ \
+          leal K##round(t0, e, 1), t1; \
+          roll2(7, t1); \
+        /* h + w1 => h */ \
+          addl wtype##_W1_ADDR(round, widx), h; \
+        /* h + t1 => h */ \
+          addl2(t1, h); \
+        /* t1 ^ t0 => t0 */ \
+          xorl t1, t0; \
+        /* w1w2 + d => d */ \
+          addl wtype##_W1W2_ADDR(round, widx), d; \
+        /* FF##i(a,b,c) => t1 */ \
+          FF##i(a, b, c, t1, t2); \
+        /* d + t1 => d */ \
+          addl2(t1, d); \
+        /* GG#i(e,f,g) => t2 */ \
+          GG##i(e, f, g, t2, t1); \
+        /* h + t2 => h */ \
+          addl2(t2, h); \
+        /* rol (f, 19) => f */ \
+          roll2(19, f); \
+        /* d + t0 => d */ \
+          addl2(t0, d); \
+        /* rol (b, 9) => b */ \
+          roll2(9, b); \
+        /* P0(h) => h */ \
+          roll3(9, h, t2); \
+          roll3(17, h, t1); \
+          xorl t2, h; \
+          xorl t1, h;
+
+#define R1(a, b, c, d, e, f, g, h, round, widx, wtype) \
+        R(1, a, b, c, d, e, f, g, h, round, widx, wtype)
+
+#define R2(a, b, c, d, e, f, g, h, round, widx, wtype) \
+        R(2, a, b, c, d, e, f, g, h, round, widx, wtype)
+
+/* Input expansion macros. */
+
+/* Byte-swapped input address. */
+#define IW_W_ADDR(round, widx, offs) \
+        (STACK_W + ((round) / 4) * 64 + (offs) + ((widx) * 4))(%rsp)
+
+/* Expanded input address. */
+#define XW_W_ADDR(round, widx, offs) \
+        (STACK_W + ((((round) / 3) - 4) % 2) * 64 + (offs) + ((widx) * 4))(%rsp)
+
+/* Rounds 1-12, byte-swapped input block addresses. */
+#define IW_W1_ADDR(round, widx)   IW_W_ADDR(round, widx, 0)
+#define IW_W1W2_ADDR(round, widx) IW_W_ADDR(round, widx, 32)
+
+/* Rounds 1-12, expanded input block addresses. */
+#define XW_W1_ADDR(round, widx)   XW_W_ADDR(round, widx, 0)
+#define XW_W1W2_ADDR(round, widx) XW_W_ADDR(round, widx, 32)
+
+/* Input block loading. */
+#define LOAD_W_XMM_1() \
+        vmovdqu 0*16(RDATA), XTMP0; /* XTMP0: w3, w2, w1, w0 */ \
+        vmovdqu 1*16(RDATA), XTMP1; /* XTMP1: w7, w6, w5, w4 */ \
+        vmovdqu 2*16(RDATA), XTMP2; /* XTMP2: w11, w10, w9, w8 */ \
+        vmovdqu 3*16(RDATA), XTMP3; /* XTMP3: w15, w14, w13, w12 */\
+        vpshufb BSWAP_REG, XTMP0, XTMP0; \
+        vpshufb BSWAP_REG, XTMP1, XTMP1; \
+        vpshufb BSWAP_REG, XTMP2, XTMP2; \
+        vpshufb BSWAP_REG, XTMP3, XTMP3; \
+        vpxor XTMP0, XTMP1, XTMP4; \
+        vpxor XTMP1, XTMP2, XTMP5; \
+        vpxor XTMP2, XTMP3, XTMP6; \
+        leaq 64(RDATA), RDATA; \
+        vmovdqa XTMP0, IW_W1_ADDR(0, 0); \
+        vmovdqa XTMP4, IW_W1W2_ADDR(0, 0); \
+        vmovdqa XTMP1, IW_W1_ADDR(4, 0); \
+        vmovdqa XTMP5, IW_W1W2_ADDR(4, 0);
+
+#define LOAD_W_XMM_2() \
+        vmovdqa XTMP2, IW_W1_ADDR(8, 0); \
+        vmovdqa XTMP6, IW_W1W2_ADDR(8, 0);
+
+#define LOAD_W_XMM_3() \
+        vpshufd $0b00000000, XTMP0, W0; /* W0: xx, w0, xx, xx */ \
+        vpshufd $0b11111001, XTMP0, W1; /* W1: xx, w3, w2, w1 */ \
+        vmovdqa XTMP1, W2;              /* W2: xx, w6, w5, w4 */ \
+        vpalignr $12, XTMP1, XTMP2, W3; /* W3: xx, w9, w8, w7 */ \
+        vpalignr $8, XTMP2, XTMP3, W4;  /* W4: xx, w12, w11, w10 */ \
+        vpshufd $0b11111001, XTMP3, W5; /* W5: xx, w15, w14, w13 */
+
+/* Message scheduling. Note: 3 words per XMM register. */
+#define SCHED_W_0(round, w0, w1, w2, w3, w4, w5) \
+        /* Load (w[i - 16]) => XTMP0 */ \
+        vpshufd $0b10111111, w0, XTMP0; \
+        vpalignr $12, XTMP0, w1, XTMP0; /* XTMP0: xx, w2, w1, w0 */ \
+        /* Load (w[i - 13]) => XTMP1 */ \
+        vpshufd $0b10111111, w1, XTMP1; \
+        vpalignr $12, XTMP1, w2, XTMP1; \
+        /* w[i - 9] == w3 */ \
+        /* XMM3 ^ XTMP0 => XTMP0 */ \
+        vpxor w3, XTMP0, XTMP0;
+
+#define SCHED_W_1(round, w0, w1, w2, w3, w4, w5) \
+        /* w[i - 3] == w5 */ \
+        /* rol(XMM5, 15) ^ XTMP0 => XTMP0 */ \
+        vpslld $15, w5, XTMP2; \
+        vpsrld $(32-15), w5, XTMP3; \
+        vpxor XTMP2, XTMP3, XTMP3; \
+        vpxor XTMP3, XTMP0, XTMP0; \
+        /* rol(XTMP1, 7) => XTMP1 */ \
+        vpslld $7, XTMP1, XTMP5; \
+        vpsrld $(32-7), XTMP1, XTMP1; \
+        vpxor XTMP5, XTMP1, XTMP1; \
+        /* XMM4 ^ XTMP1 => XTMP1 */ \
+        vpxor w4, XTMP1, XTMP1; \
+        /* w[i - 6] == XMM4 */ \
+        /* P1(XTMP0) ^ XTMP1 => XMM0 */ \
+        vpslld $15, XTMP0, XTMP5; \
+        vpsrld $(32-15), XTMP0, XTMP6; \
+        vpslld $23, XTMP0, XTMP2; \
+        vpsrld $(32-23), XTMP0, XTMP3; \
+        vpxor XTMP0, XTMP1, XTMP1; \
+        vpxor XTMP6, XTMP5, XTMP5; \
+        vpxor XTMP3, XTMP2, XTMP2; \
+        vpxor XTMP2, XTMP5, XTMP5; \
+        vpxor XTMP5, XTMP1, w0;
+
+#define SCHED_W_2(round, w0, w1, w2, w3, w4, w5) \
+        /* W1 in XMM12 */ \
+        vpshufd $0b10111111, w4, XTMP4; \
+        vpalignr $12, XTMP4, w5, XTMP4; \
+        vmovdqa XTMP4, XW_W1_ADDR((round), 0); \
+        /* W1 ^ W2 => XTMP1 */ \
+        vpxor w0, XTMP4, XTMP1; \
+        vmovdqa XTMP1, XW_W1W2_ADDR((round), 0);
+
+/*
+ * Transform nblks*64 bytes (nblks*16 32-bit words) at DATA.
+ *
+ * unsigned int
+ * _gcry_sm3_transform_amd64_avx_bmi2 (void *ctx, const unsigned char *data,
+ *                                     size_t nblks)
+ */
+.globl _gcry_sm3_transform_amd64_avx_bmi2
+ELF(.type _gcry_sm3_transform_amd64_avx_bmi2,@function)
+.align 16
+_gcry_sm3_transform_amd64_avx_bmi2:
+  /* input:
+   *   %rdi: ctx, CTX
+   *   %rsi: data (64*nblks bytes)
+   *   %rdx: nblks
+   */
+  CFI_STARTPROC();
+
+  vzeroupper;
+
+  pushq %rbp;
+  CFI_PUSH(%rbp);
+  movq %rsp, %rbp;
+  CFI_DEF_CFA_REGISTER(%rbp);
+
+  movq %rdx, RNBLKS;
+
+  subq $STACK_SIZE, %rsp;
+  andq $(~63), %rsp;
+
+  movq %rbx, (STACK_REG_SAVE + 0 * 8)(%rsp);
+  CFI_REL_OFFSET(%rbx, STACK_REG_SAVE + 0 * 8);
+  movq %r15, (STACK_REG_SAVE + 1 * 8)(%rsp);
+  CFI_REL_OFFSET(%r15, STACK_REG_SAVE + 1 * 8);
+  movq %r14, (STACK_REG_SAVE + 2 * 8)(%rsp);
+  CFI_REL_OFFSET(%r14, STACK_REG_SAVE + 2 * 8);
+  movq %r13, (STACK_REG_SAVE + 3 * 8)(%rsp);
+  CFI_REL_OFFSET(%r13, STACK_REG_SAVE + 3 * 8);
+  movq %r12, (STACK_REG_SAVE + 4 * 8)(%rsp);
+  CFI_REL_OFFSET(%r12, STACK_REG_SAVE + 4 * 8);
+
+  vmovdqa .Lbe32mask rRIP, BSWAP_REG;
+
+  /* Get the values of the chaining variables. */
+  movl state_h0(RSTATE), a;
+  movl state_h1(RSTATE), b;
+  movl state_h2(RSTATE), c;
+  movl state_h3(RSTATE), d;
+  movl state_h4(RSTATE), e;
+  movl state_h5(RSTATE), f;
+  movl state_h6(RSTATE), g;
+  movl state_h7(RSTATE), h;
+
+.align 16
+.Loop:
+  /* Load data part1. */
+  LOAD_W_XMM_1();
+
+  leaq -1(RNBLKS), RNBLKS;
+
+  /* Transform 0-3 + Load data part2. */
+  R1(a, b, c, d, e, f, g, h, 0, 0, IW); LOAD_W_XMM_2();
+  R1(d, a, b, c, h, e, f, g, 1, 1, IW);
+  R1(c, d, a, b, g, h, e, f, 2, 2, IW);
+  R1(b, c, d, a, f, g, h, e, 3, 3, IW); LOAD_W_XMM_3();
+
+  /* Transform 4-7 + Precalc 12-14. */
+  R1(a, b, c, d, e, f, g, h, 4, 0, IW);
+  R1(d, a, b, c, h, e, f, g, 5, 1, IW);
+  R1(c, d, a, b, g, h, e, f, 6, 2, IW); SCHED_W_0(12, W0, W1, W2, W3, W4, W5);
+  R1(b, c, d, a, f, g, h, e, 7, 3, IW); SCHED_W_1(12, W0, W1, W2, W3, W4, W5);
+
+  /* Transform 8-11 + Precalc 12-17. */
+  R1(a, b, c, d, e, f, g, h, 8, 0, IW); SCHED_W_2(12, W0, W1, W2, W3, W4, W5);
+  R1(d, a, b, c, h, e, f, g, 9, 1, IW); SCHED_W_0(15, W1, W2, W3, W4, W5, W0);
+  R1(c, d, a, b, g, h, e, f, 10, 2, IW); SCHED_W_1(15, W1, W2, W3, W4, W5, W0);
+  R1(b, c, d, a, f, g, h, e, 11, 3, IW); SCHED_W_2(15, W1, W2, W3, W4, W5, W0);
+
+  /* Transform 12-14 + Precalc 18-20 */
+  R1(a, b, c, d, e, f, g, h, 12, 0, XW); SCHED_W_0(18, W2, W3, W4, W5, W0, W1);
+  R1(d, a, b, c, h, e, f, g, 13, 1, XW); SCHED_W_1(18, W2, W3, W4, W5, W0, W1);
+  R1(c, d, a, b, g, h, e, f, 14, 2, XW); SCHED_W_2(18, W2, W3, W4, W5, W0, W1);
+
+  /* Transform 15-17 + Precalc 21-23 */
+  R1(b, c, d, a, f, g, h, e, 15, 0, XW); SCHED_W_0(21, W3, W4, W5, W0, W1, W2);
+  R2(a, b, c, d, e, f, g, h, 16, 1, XW); SCHED_W_1(21, W3, W4, W5, W0, W1, W2);
+  R2(d, a, b, c, h, e, f, g, 17, 2, XW); SCHED_W_2(21, W3, W4, W5, W0, W1, W2);
+
+  /* Transform 18-20 + Precalc 24-26 */
+  R2(c, d, a, b, g, h, e, f, 18, 0, XW); SCHED_W_0(24, W4, W5, W0, W1, W2, W3);
+  R2(b, c, d, a, f, g, h, e, 19, 1, XW); SCHED_W_1(24, W4, W5, W0, W1, W2, W3);
+  R2(a, b, c, d, e, f, g, h, 20, 2, XW); SCHED_W_2(24, W4, W5, W0, W1, W2, W3);
+
+  /* Transform 21-23 + Precalc 27-29 */
+  R2(d, a, b, c, h, e, f, g, 21, 0, XW); SCHED_W_0(27, W5, W0, W1, W2, W3, W4);
+  R2(c, d, a, b, g, h, e, f, 22, 1, XW); SCHED_W_1(27, W5, W0, W1, W2, W3, W4);
+  R2(b, c, d, a, f, g, h, e, 23, 2, XW); SCHED_W_2(27, W5, W0, W1, W2, W3, W4);
+
+  /* Transform 24-26 + Precalc 30-32 */
+  R2(a, b, c, d, e, f, g, h, 24, 0, XW); SCHED_W_0(30, W0, W1, W2, W3, W4, W5);
+  R2(d, a, b, c, h, e, f, g, 25, 1, XW); SCHED_W_1(30, W0, W1, W2, W3, W4, W5);
+  R2(c, d, a, b, g, h, e, f, 26, 2, XW); SCHED_W_2(30, W0, W1, W2, W3, W4, W5);
+
+  /* Transform 27-29 + Precalc 33-35 */
+  R2(b, c, d, a, f, g, h, e, 27, 0, XW); SCHED_W_0(33, W1, W2, W3, W4, W5, W0);
+  R2(a, b, c, d, e, f, g, h, 28, 1, XW); SCHED_W_1(33, W1, W2, W3, W4, W5, W0);
+  R2(d, a, b, c, h, e, f, g, 29, 2, XW); SCHED_W_2(33, W1, W2, W3, W4, W5, W0);
+
+  /* Transform 30-32 + Precalc 36-38 */
+  R2(c, d, a, b, g, h, e, f, 30, 0, XW); SCHED_W_0(36, W2, W3, W4, W5, W0, W1);
+  R2(b, c, d, a, f, g, h, e, 31, 1, XW); SCHED_W_1(36, W2, W3, W4, W5, W0, W1);
+  R2(a, b, c, d, e, f, g, h, 32, 2, XW); SCHED_W_2(36, W2, W3, W4, W5, W0, W1);
+
+  /* Transform 33-35 + Precalc 39-41 */
+  R2(d, a, b, c, h, e, f, g, 33, 0, XW); SCHED_W_0(39, W3, W4, W5, W0, W1, W2);
+  R2(c, d, a, b, g, h, e, f, 34, 1, XW); SCHED_W_1(39, W3, W4, W5, W0, W1, W2);
+  R2(b, c, d, a, f, g, h, e, 35, 2, XW); SCHED_W_2(39, W3, W4, W5, W0, W1, W2);
+
+  /* Transform 36-38 + Precalc 42-44 */
+  R2(a, b, c, d, e, f, g, h, 36, 0, XW); SCHED_W_0(42, W4, W5, W0, W1, W2, W3);
+  R2(d, a, b, c, h, e, f, g, 37, 1, XW); SCHED_W_1(42, W4, W5, W0, W1, W2, W3);
+  R2(c, d, a, b, g, h, e, f, 38, 2, XW); SCHED_W_2(42, W4, W5, W0, W1, W2, W3);
+
+  /* Transform 39-41 + Precalc 45-47 */
+  R2(b, c, d, a, f, g, h, e, 39, 0, XW); SCHED_W_0(45, W5, W0, W1, W2, W3, W4);
+  R2(a, b, c, d, e, f, g, h, 40, 1, XW); SCHED_W_1(45, W5, W0, W1, W2, W3, W4);
+  R2(d, a, b, c, h, e, f, g, 41, 2, XW); SCHED_W_2(45, W5, W0, W1, W2, W3, W4);
+
+  /* Transform 42-44 + Precalc 48-50 */
+  R2(c, d, a, b, g, h, e, f, 42, 0, XW); SCHED_W_0(48, W0, W1, W2, W3, W4, W5);
+  R2(b, c, d, a, f, g, h, e, 43, 1, XW); SCHED_W_1(48, W0, W1, W2, W3, W4, W5);
+  R2(a, b, c, d, e, f, g, h, 44, 2, XW); SCHED_W_2(48, W0, W1, W2, W3, W4, W5);
+
+  /* Transform 45-47 + Precalc 51-53 */
+  R2(d, a, b, c, h, e, f, g, 45, 0, XW); SCHED_W_0(51, W1, W2, W3, W4, W5, W0);
+  R2(c, d, a, b, g, h, e, f, 46, 1, XW); SCHED_W_1(51, W1, W2, W3, W4, W5, W0);
+  R2(b, c, d, a, f, g, h, e, 47, 2, XW); SCHED_W_2(51, W1, W2, W3, W4, W5, W0);
+
+  /* Transform 48-50 + Precalc 54-56 */
+  R2(a, b, c, d, e, f, g, h, 48, 0, XW); SCHED_W_0(54, W2, W3, W4, W5, W0, W1);
+  R2(d, a, b, c, h, e, f, g, 49, 1, XW); SCHED_W_1(54, W2, W3, W4, W5, W0, W1);
+  R2(c, d, a, b, g, h, e, f, 50, 2, XW); SCHED_W_2(54, W2, W3, W4, W5, W0, W1);
+
+  /* Transform 51-53 + Precalc 57-59 */
+  R2(b, c, d, a, f, g, h, e, 51, 0, XW); SCHED_W_0(57, W3, W4, W5, W0, W1, W2);
+  R2(a, b, c, d, e, f, g, h, 52, 1, XW); SCHED_W_1(57, W3, W4, W5, W0, W1, W2);
+  R2(d, a, b, c, h, e, f, g, 53, 2, XW); SCHED_W_2(57, W3, W4, W5, W0, W1, W2);
+
+  /* Transform 54-56 + Precalc 60-62 */
+  R2(c, d, a, b, g, h, e, f, 54, 0, XW); SCHED_W_0(60, W4, W5, W0, W1, W2, W3);
+  R2(b, c, d, a, f, g, h, e, 55, 1, XW); SCHED_W_1(60, W4, W5, W0, W1, W2, W3);
+  R2(a, b, c, d, e, f, g, h, 56, 2, XW); SCHED_W_2(60, W4, W5, W0, W1, W2, W3);
+
+  /* Transform 57-59 + Precalc 63 */
+  R2(d, a, b, c, h, e, f, g, 57, 0, XW); SCHED_W_0(63, W5, W0, W1, W2, W3, W4);
+  R2(c, d, a, b, g, h, e, f, 58, 1, XW);
+  R2(b, c, d, a, f, g, h, e, 59, 2, XW); SCHED_W_1(63, W5, W0, W1, W2, W3, W4);
+
+  /* Transform 60-62 + Precalc 63 */
+  R2(a, b, c, d, e, f, g, h, 60, 0, XW);
+  R2(d, a, b, c, h, e, f, g, 61, 1, XW); SCHED_W_2(63, W5, W0, W1, W2, W3, W4);
+  R2(c, d, a, b, g, h, e, f, 62, 2, XW);
+
+  /* Transform 63 */
+  R2(b, c, d, a, f, g, h, e, 63, 0, XW);
+
+  /* Update the chaining variables. */
+  xorl state_h0(RSTATE), a;
+  xorl state_h1(RSTATE), b;
+  xorl state_h2(RSTATE), c;
+  xorl state_h3(RSTATE), d;
+  movl a, state_h0(RSTATE);
+  movl b, state_h1(RSTATE);
+  movl c, state_h2(RSTATE);
+  movl d, state_h3(RSTATE);
+  xorl state_h4(RSTATE), e;
+  xorl state_h5(RSTATE), f;
+  xorl state_h6(RSTATE), g;
+  xorl state_h7(RSTATE), h;
+  movl e, state_h4(RSTATE);
+  movl f, state_h5(RSTATE);
+  movl g, state_h6(RSTATE);
+  movl h, state_h7(RSTATE);
+
+  cmpq $0, RNBLKS;
+  jne .Loop;
+
+  vzeroall;
+
+  movq (STACK_REG_SAVE + 0 * 8)(%rsp), %rbx;
+  CFI_RESTORE(%rbx);
+  movq (STACK_REG_SAVE + 1 * 8)(%rsp), %r15;
+  CFI_RESTORE(%r15);
+  movq (STACK_REG_SAVE + 2 * 8)(%rsp), %r14;
+  CFI_RESTORE(%r14);
+  movq (STACK_REG_SAVE + 3 * 8)(%rsp), %r13;
+  CFI_RESTORE(%r13);
+  movq (STACK_REG_SAVE + 4 * 8)(%rsp), %r12;
+  CFI_RESTORE(%r12);
+
+  vmovdqa %xmm0, IW_W1_ADDR(0, 0);
+  vmovdqa %xmm0, IW_W1W2_ADDR(0, 0);
+  vmovdqa %xmm0, IW_W1_ADDR(4, 0);
+  vmovdqa %xmm0, IW_W1W2_ADDR(4, 0);
+  vmovdqa %xmm0, IW_W1_ADDR(8, 0);
+  vmovdqa %xmm0, IW_W1W2_ADDR(8, 0);
+  xorl %eax, %eax; /* stack burned */
+
+  leave;
+  CFI_LEAVE();
+  ret_spec_stop;
+  CFI_ENDPROC();
+ELF(.size _gcry_sm3_transform_amd64_avx_bmi2,
+          .-_gcry_sm3_transform_amd64_avx_bmi2;)
+
+#endif
+#endif
diff --git a/cipher/sm3.c b/cipher/sm3.c
new file mode 100644 (file)
index 0000000..0ab5f50
--- /dev/null
@@ -0,0 +1,537 @@
+/* sm3.c - SM3 hash function
+ * Copyright (C) 2017 Jia Zhang
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+/*  Test vectors:
+
+    "abc"
+    SM3: 66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0
+
+    "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"
+    SM3: debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732
+
+    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+    SM3: 639b6cc5 e64d9e37 a390b192 df4fa1ea 0720ab74 7ff692b9 f38c4e66 ad7b8c05
+
+    "a" one million times
+    SM3: c8aaf894 29554029 e231941a 2acc0ad6 1ff2a5ac d8fadd25 847a3a73 2b3b02c3
+
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "g10lib.h"
+#include "bithelp.h"
+#include "bufhelp.h"
+#include "cipher.h"
+#include "hash-common.h"
+
+
+/* USE_AVX_BMI2 indicates whether to compile with Intel AVX/BMI2 code. */
+#undef USE_AVX_BMI2
+#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_AVX) && \
+    defined(HAVE_GCC_INLINE_ASM_BMI2) && \
+    (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+# define USE_AVX_BMI2 1
+#endif
+
+/* USE_AARCH64_SIMD indicates whether to enable ARMv8 SIMD assembly
+ * code. */
+#undef USE_AARCH64_SIMD
+#ifdef ENABLE_NEON_SUPPORT
+# if defined(__AARCH64EL__) \
+       && defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) \
+       && defined(HAVE_GCC_INLINE_ASM_AARCH64_NEON)
+#  define USE_AARCH64_SIMD 1
+# endif
+#endif
+
+
+typedef struct {
+  gcry_md_block_ctx_t bctx;
+  u32 h[8];
+} SM3_CONTEXT;
+
+
+/* AMD64 assembly implementations use SystemV ABI, ABI conversion and additional
+ * stack to store XMM6-XMM15 needed on Win64. */
+#undef ASM_FUNC_ABI
+#undef ASM_EXTRA_STACK
+#if defined(USE_AVX_BMI2)
+# ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
+#  define ASM_FUNC_ABI __attribute__((sysv_abi))
+#  define ASM_EXTRA_STACK (10 * 16 + 4 * sizeof(void *))
+# else
+#  define ASM_FUNC_ABI
+#  define ASM_EXTRA_STACK 0
+# endif
+#endif
+
+
+#ifdef USE_AVX_BMI2
+unsigned int _gcry_sm3_transform_amd64_avx_bmi2(void *state,
+                                                const void *input_data,
+                                                size_t num_blks) ASM_FUNC_ABI;
+
+static unsigned int
+do_sm3_transform_amd64_avx_bmi2(void *context, const unsigned char *data,
+                                size_t nblks)
+{
+  SM3_CONTEXT *hd = context;
+  unsigned int nburn = _gcry_sm3_transform_amd64_avx_bmi2 (hd->h, data, nblks);
+  nburn += nburn ? ASM_EXTRA_STACK : 0;
+  return nburn;
+}
+#endif /* USE_AVX_BMI2 */
+
+#ifdef USE_AARCH64_SIMD
+unsigned int _gcry_sm3_transform_aarch64(void *state, const void *input_data,
+                                         size_t num_blks);
+
+static unsigned int
+do_sm3_transform_aarch64(void *context, const unsigned char *data, size_t nblks)
+{
+  SM3_CONTEXT *hd = context;
+  return _gcry_sm3_transform_aarch64 (hd->h, data, nblks);
+}
+#endif /* USE_AARCH64_SIMD */
+
+
+static unsigned int
+transform (void *c, const unsigned char *data, size_t nblks);
+
+
+static void
+sm3_init (void *context, unsigned int flags)
+{
+  SM3_CONTEXT *hd = context;
+  unsigned int features = _gcry_get_hw_features ();
+
+  (void)flags;
+
+  hd->h[0] = 0x7380166f;
+  hd->h[1] = 0x4914b2b9;
+  hd->h[2] = 0x172442d7;
+  hd->h[3] = 0xda8a0600;
+  hd->h[4] = 0xa96f30bc;
+  hd->h[5] = 0x163138aa;
+  hd->h[6] = 0xe38dee4d;
+  hd->h[7] = 0xb0fb0e4e;
+
+  hd->bctx.nblocks = 0;
+  hd->bctx.nblocks_high = 0;
+  hd->bctx.count = 0;
+  hd->bctx.blocksize_shift = _gcry_ctz(64);
+  hd->bctx.bwrite = transform;
+
+#ifdef USE_AVX_BMI2
+  if ((features & HWF_INTEL_AVX2) && (features & HWF_INTEL_BMI2))
+    hd->bctx.bwrite = do_sm3_transform_amd64_avx_bmi2;
+#endif
+#ifdef USE_AARCH64_SIMD
+  if (features & HWF_ARM_NEON)
+    hd->bctx.bwrite = do_sm3_transform_aarch64;
+#endif
+
+  (void)features;
+}
+
+
+/*
+  Transform the message X which consists of 16 32-bit-words. See
+  GM/T 004-2012 for details.  */
+#define R(i,a,b,c,d,e,f,g,h,t,w1,w2) do                               \
+          {                                                           \
+            ss1 = rol ((rol ((a), 12) + (e) + (t)), 7);               \
+            ss2 = ss1 ^ rol ((a), 12);                                \
+            d += FF##i(a,b,c) + ss2 + ((w1) ^ (w2));                  \
+            h += GG##i(e,f,g) + ss1 + (w1);                           \
+            b = rol ((b), 9);                                         \
+            f = rol ((f), 19);                                        \
+            h = P0 ((h));                                             \
+          } while (0)
+
+#define R1(a,b,c,d,e,f,g,h,t,w1,w2) R(1,a,b,c,d,e,f,g,h,t,w1,w2)
+#define R2(a,b,c,d,e,f,g,h,t,w1,w2) R(2,a,b,c,d,e,f,g,h,t,w1,w2)
+
+#define FF1(x, y, z)  (x ^ y ^ z)
+
+#define FF2(x, y, z)  ((x & y) | (x & z) | (y & z))
+
+#define GG1(x, y, z)  (x ^ y ^ z)
+
+#define GG2(x, y, z)  ((x & y) | ( ~x & z))
+
+/* Message expansion */
+#define P0(x) ((x) ^ rol ((x), 9) ^ rol ((x), 17))
+#define P1(x) ((x) ^ rol ((x), 15) ^ rol ((x), 23))
+#define I(i)  ( w[i] = buf_get_be32(data + i * 4) )
+#define W1(i) ( w[i&0x0f] )
+#define W2(i) ( w[i&0x0f] =   P1(w[i    &0x0f] \
+                               ^ w[(i-9)&0x0f] \
+                               ^ rol (w[(i-3)&0x0f], 15)) \
+                            ^ rol (w[(i-13)&0x0f], 7) \
+                            ^ w[(i-6)&0x0f] )
+
+static unsigned int
+transform_blk (void *ctx, const unsigned char *data)
+{
+  SM3_CONTEXT *hd = ctx;
+  static const u32 K[64] = {
+    0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb,
+    0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc,
+    0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce,
+    0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6,
+    0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c,
+    0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce,
+    0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec,
+    0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5,
+    0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53,
+    0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d,
+    0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4,
+    0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43,
+    0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c,
+    0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce,
+    0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec,
+    0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5
+  };
+
+  u32 a,b,c,d,e,f,g,h,ss1,ss2;
+  u32 w[16];
+
+  a = hd->h[0];
+  b = hd->h[1];
+  c = hd->h[2];
+  d = hd->h[3];
+  e = hd->h[4];
+  f = hd->h[5];
+  g = hd->h[6];
+  h = hd->h[7];
+
+  R1(a, b, c, d, e, f, g, h, K[0], I(0), I(4));
+  R1(d, a, b, c, h, e, f, g, K[1], I(1), I(5));
+  R1(c, d, a, b, g, h, e, f, K[2], I(2), I(6));
+  R1(b, c, d, a, f, g, h, e, K[3], I(3), I(7));
+  R1(a, b, c, d, e, f, g, h, K[4], W1(4), I(8));
+  R1(d, a, b, c, h, e, f, g, K[5], W1(5), I(9));
+  R1(c, d, a, b, g, h, e, f, K[6], W1(6), I(10));
+  R1(b, c, d, a, f, g, h, e, K[7], W1(7), I(11));
+  R1(a, b, c, d, e, f, g, h, K[8], W1(8), I(12));
+  R1(d, a, b, c, h, e, f, g, K[9], W1(9), I(13));
+  R1(c, d, a, b, g, h, e, f, K[10], W1(10), I(14));
+  R1(b, c, d, a, f, g, h, e, K[11], W1(11), I(15));
+  R1(a, b, c, d, e, f, g, h, K[12], W1(12), W2(16));
+  R1(d, a, b, c, h, e, f, g, K[13], W1(13), W2(17));
+  R1(c, d, a, b, g, h, e, f, K[14], W1(14), W2(18));
+  R1(b, c, d, a, f, g, h, e, K[15], W1(15), W2(19));
+
+  R2(a, b, c, d, e, f, g, h, K[16], W1(16), W2(20));
+  R2(d, a, b, c, h, e, f, g, K[17], W1(17), W2(21));
+  R2(c, d, a, b, g, h, e, f, K[18], W1(18), W2(22));
+  R2(b, c, d, a, f, g, h, e, K[19], W1(19), W2(23));
+  R2(a, b, c, d, e, f, g, h, K[20], W1(20), W2(24));
+  R2(d, a, b, c, h, e, f, g, K[21], W1(21), W2(25));
+  R2(c, d, a, b, g, h, e, f, K[22], W1(22), W2(26));
+  R2(b, c, d, a, f, g, h, e, K[23], W1(23), W2(27));
+  R2(a, b, c, d, e, f, g, h, K[24], W1(24), W2(28));
+  R2(d, a, b, c, h, e, f, g, K[25], W1(25), W2(29));
+  R2(c, d, a, b, g, h, e, f, K[26], W1(26), W2(30));
+  R2(b, c, d, a, f, g, h, e, K[27], W1(27), W2(31));
+  R2(a, b, c, d, e, f, g, h, K[28], W1(28), W2(32));
+  R2(d, a, b, c, h, e, f, g, K[29], W1(29), W2(33));
+  R2(c, d, a, b, g, h, e, f, K[30], W1(30), W2(34));
+  R2(b, c, d, a, f, g, h, e, K[31], W1(31), W2(35));
+
+  R2(a, b, c, d, e, f, g, h, K[32], W1(32), W2(36));
+  R2(d, a, b, c, h, e, f, g, K[33], W1(33), W2(37));
+  R2(c, d, a, b, g, h, e, f, K[34], W1(34), W2(38));
+  R2(b, c, d, a, f, g, h, e, K[35], W1(35), W2(39));
+  R2(a, b, c, d, e, f, g, h, K[36], W1(36), W2(40));
+  R2(d, a, b, c, h, e, f, g, K[37], W1(37), W2(41));
+  R2(c, d, a, b, g, h, e, f, K[38], W1(38), W2(42));
+  R2(b, c, d, a, f, g, h, e, K[39], W1(39), W2(43));
+  R2(a, b, c, d, e, f, g, h, K[40], W1(40), W2(44));
+  R2(d, a, b, c, h, e, f, g, K[41], W1(41), W2(45));
+  R2(c, d, a, b, g, h, e, f, K[42], W1(42), W2(46));
+  R2(b, c, d, a, f, g, h, e, K[43], W1(43), W2(47));
+  R2(a, b, c, d, e, f, g, h, K[44], W1(44), W2(48));
+  R2(d, a, b, c, h, e, f, g, K[45], W1(45), W2(49));
+  R2(c, d, a, b, g, h, e, f, K[46], W1(46), W2(50));
+  R2(b, c, d, a, f, g, h, e, K[47], W1(47), W2(51));
+
+  R2(a, b, c, d, e, f, g, h, K[48], W1(48), W2(52));
+  R2(d, a, b, c, h, e, f, g, K[49], W1(49), W2(53));
+  R2(c, d, a, b, g, h, e, f, K[50], W1(50), W2(54));
+  R2(b, c, d, a, f, g, h, e, K[51], W1(51), W2(55));
+  R2(a, b, c, d, e, f, g, h, K[52], W1(52), W2(56));
+  R2(d, a, b, c, h, e, f, g, K[53], W1(53), W2(57));
+  R2(c, d, a, b, g, h, e, f, K[54], W1(54), W2(58));
+  R2(b, c, d, a, f, g, h, e, K[55], W1(55), W2(59));
+  R2(a, b, c, d, e, f, g, h, K[56], W1(56), W2(60));
+  R2(d, a, b, c, h, e, f, g, K[57], W1(57), W2(61));
+  R2(c, d, a, b, g, h, e, f, K[58], W1(58), W2(62));
+  R2(b, c, d, a, f, g, h, e, K[59], W1(59), W2(63));
+  R2(a, b, c, d, e, f, g, h, K[60], W1(60), W2(64));
+  R2(d, a, b, c, h, e, f, g, K[61], W1(61), W2(65));
+  R2(c, d, a, b, g, h, e, f, K[62], W1(62), W2(66));
+  R2(b, c, d, a, f, g, h, e, K[63], W1(63), W2(67));
+
+  hd->h[0] ^= a;
+  hd->h[1] ^= b;
+  hd->h[2] ^= c;
+  hd->h[3] ^= d;
+  hd->h[4] ^= e;
+  hd->h[5] ^= f;
+  hd->h[6] ^= g;
+  hd->h[7] ^= h;
+
+  return /*burn_stack*/ 26*4+32;
+}
+#undef P0
+#undef P1
+#undef R
+#undef R1
+#undef R2
+
+static unsigned int
+transform (void *ctx, const unsigned char *data, size_t nblks)
+{
+  SM3_CONTEXT *hd = ctx;
+  unsigned int burn;
+
+  do
+    {
+      burn = transform_blk (hd, data);
+      data += 64;
+    }
+  while (--nblks);
+
+  return burn;
+}
+
+
+/*
+   The routine finally terminates the computation and returns the
+   digest.  The handle is prepared for a new cycle, but adding bytes
+   to the handle will the destroy the returned buffer.  Returns: 32
+   bytes with the message the digest.  */
+static void
+sm3_final(void *context)
+{
+  SM3_CONTEXT *hd = context;
+  u32 t, th, msb, lsb;
+  byte *p;
+  unsigned int burn;
+
+  t = hd->bctx.nblocks;
+  if (sizeof t == sizeof hd->bctx.nblocks)
+    th = hd->bctx.nblocks_high;
+  else
+    th = hd->bctx.nblocks >> 32;
+
+  /* multiply by 64 to make a byte count */
+  lsb = t << 6;
+  msb = (th << 6) | (t >> 26);
+  /* add the count */
+  t = lsb;
+  if ((lsb += hd->bctx.count) < t)
+    msb++;
+  /* multiply by 8 to make a bit count */
+  t = lsb;
+  lsb <<= 3;
+  msb <<= 3;
+  msb |= t >> 29;
+
+  if (hd->bctx.count < 56)  /* enough room */
+    {
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad */
+      if (hd->bctx.count < 56)
+       memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count);
+
+      /* append the 64 bit count */
+      buf_put_be32(hd->bctx.buf + 56, msb);
+      buf_put_be32(hd->bctx.buf + 60, lsb);
+      burn = (*hd->bctx.bwrite) ( hd, hd->bctx.buf, 1 );
+    }
+  else  /* need one extra block */
+    {
+      hd->bctx.buf[hd->bctx.count++] = 0x80; /* pad character */
+      /* fill pad and next block with zeroes */
+      memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56);
+
+      /* append the 64 bit count */
+      buf_put_be32(hd->bctx.buf + 64 + 56, msb);
+      buf_put_be32(hd->bctx.buf + 64 + 60, lsb);
+      burn = (*hd->bctx.bwrite) ( hd, hd->bctx.buf, 2 );
+    }
+
+  p = hd->bctx.buf;
+#define X(a) do { buf_put_be32(p, hd->h[a]); p += 4; } while(0)
+  X(0);
+  X(1);
+  X(2);
+  X(3);
+  X(4);
+  X(5);
+  X(6);
+  X(7);
+#undef X
+
+  hd->bctx.count = 0;
+
+  _gcry_burn_stack (burn);
+}
+
+static byte *
+sm3_read (void *context)
+{
+  SM3_CONTEXT *hd = context;
+
+  return hd->bctx.buf;
+}
+
+
+/* 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, 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,
+                          (const char*)iov[0].data + iov[0].off, iov[0].len);
+  sm3_final (&hd);
+  memcpy (outbuf, hd.bctx.buf, 32);
+}
+
+
+\f
+/*
+     Self-test section.
+ */
+
+
+static gpg_err_code_t
+selftests_sm3 (int extended, selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+
+  what = "short string (spec example 1)";
+  errtxt = _gcry_hash_selftest_check_one
+    (GCRY_MD_SM3, 0,
+     "abc", 3,
+     "\x66\xc7\xf0\xf4\x62\xee\xed\xd9\xd1\xf2\xd4\x6b\xdc\x10\xe4\xe2"
+     "\x41\x67\xc4\x87\x5c\xf2\xf7\xa2\x29\x7d\xa0\x2b\x8f\x4b\xa8\xe0", 32);
+  if (errtxt)
+    goto failed;
+
+  if (extended)
+    {
+      what = "long string (spec example 2)";
+      errtxt = _gcry_hash_selftest_check_one
+        (GCRY_MD_SM3, 0,
+         "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", 64,
+         "\xde\xbe\x9f\xf9\x22\x75\xb8\xa1\x38\x60\x48\x89\xc1\x8e\x5a\x4d"
+         "\x6f\xdb\x70\xe5\x38\x7e\x57\x65\x29\x3d\xcb\xa3\x9c\x0c\x57\x32",
+         32);
+      if (errtxt)
+        goto failed;
+
+      what = "long string";
+      errtxt = _gcry_hash_selftest_check_one
+        (GCRY_MD_SM3, 0,
+         "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
+         "\x63\x9b\x6c\xc5\xe6\x4d\x9e\x37\xa3\x90\xb1\x92\xdf\x4f\xa1\xea"
+         "\x07\x20\xab\x74\x7f\xf6\x92\xb9\xf3\x8c\x4e\x66\xad\x7b\x8c\x05",
+         32);
+      if (errtxt)
+        goto failed;
+
+      what = "one million \"a\"";
+      errtxt = _gcry_hash_selftest_check_one
+        (GCRY_MD_SM3, 1,
+         NULL, 0,
+         "\xc8\xaa\xf8\x94\x29\x55\x40\x29\xe2\x31\x94\x1a\x2a\xcc\x0a\xd6"
+         "\x1f\xf2\xa5\xac\xd8\xfa\xdd\x25\x84\x7a\x3a\x73\x2b\x3b\x02\xc3",
+         32);
+      if (errtxt)
+        goto failed;
+    }
+
+  return 0; /* Succeeded. */
+
+ failed:
+  if (report)
+    report ("digest", GCRY_MD_SM3, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+/* Run a full self-test for ALGO and return 0 on success.  */
+static gpg_err_code_t
+run_selftests (int algo, int extended, selftest_report_func_t report)
+{
+  gpg_err_code_t ec;
+
+  switch (algo)
+    {
+    case GCRY_MD_SM3:
+      ec = selftests_sm3 (extended, report);
+      break;
+    default:
+      ec = GPG_ERR_DIGEST_ALGO;
+      break;
+
+    }
+  return ec;
+}
+
+static const byte asn_sm3[] = /* Object ID is 1.2.156.10197.401 */
+  { 0x30, 0x2F, 0x30, 0x0B, 0x06, 0x07, 0x2A, 0x81,
+    0x1C, 0xCF, 0x55, 0x83, 0x11, 0x05, 0x00, 0x04,
+    0x20 };
+
+static const gcry_md_oid_spec_t oid_spec_sm3[] =
+  {
+    /* China Electronics Standardization Instutute,
+       OID White paper (2015), Table 6 */
+    { "1.2.156.10197.401" },
+    { NULL },
+  };
+
+const 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_buffers,
+    sizeof (SM3_CONTEXT),
+    run_selftests
+  };
diff --git a/cipher/sm4-aesni-avx-amd64.S b/cipher/sm4-aesni-avx-amd64.S
new file mode 100644 (file)
index 0000000..7a99e07
--- /dev/null
@@ -0,0 +1,987 @@
+/* sm4-avx-aesni-amd64.S  -  AES-NI/AVX implementation of SM4 cipher
+ *
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* Based on SM4 AES-NI work by Markku-Juhani O. Saarinen at:
+ *  https://github.com/mjosaarinen/sm4ni
+ */
+
+#include <config.h>
+
+#ifdef __x86_64
+#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
+    defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)
+
+#include "asm-common-amd64.h"
+
+/* vector registers */
+#define RX0          %xmm0
+#define RX1          %xmm1
+#define MASK_4BIT    %xmm2
+#define RTMP0        %xmm3
+#define RTMP1        %xmm4
+#define RTMP2        %xmm5
+#define RTMP3        %xmm6
+#define RTMP4        %xmm7
+
+#define RA0          %xmm8
+#define RA1          %xmm9
+#define RA2          %xmm10
+#define RA3          %xmm11
+
+#define RB0          %xmm12
+#define RB1          %xmm13
+#define RB2          %xmm14
+#define RB3          %xmm15
+
+#define RNOT         %xmm0
+#define RBSWAP       %xmm1
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+
+/* Transpose four 32-bit words between 128-bit vectors. */
+#define transpose_4x4(x0, x1, x2, x3, t1, t2) \
+       vpunpckhdq x1, x0, t2; \
+       vpunpckldq x1, x0, x0; \
+       \
+       vpunpckldq x3, x2, t1; \
+       vpunpckhdq x3, x2, x2; \
+       \
+       vpunpckhqdq t1, x0, x1; \
+       vpunpcklqdq t1, x0, x0; \
+       \
+       vpunpckhqdq x2, t2, x3; \
+       vpunpcklqdq x2, t2, x2;
+
+/* post-SubByte transform. */
+#define transform_pre(x, lo_t, hi_t, mask4bit, tmp0) \
+       vpand x, mask4bit, tmp0; \
+       vpandn x, mask4bit, x; \
+       vpsrld $4, x, x; \
+       \
+       vpshufb tmp0, lo_t, tmp0; \
+       vpshufb x, hi_t, x; \
+       vpxor tmp0, x, x;
+
+/* post-SubByte transform. Note: x has been XOR'ed with mask4bit by
+ * 'vaeslastenc' instruction. */
+#define transform_post(x, lo_t, hi_t, mask4bit, tmp0) \
+       vpandn mask4bit, x, tmp0; \
+       vpsrld $4, x, x; \
+       vpand x, mask4bit, x; \
+       \
+       vpshufb tmp0, lo_t, tmp0; \
+       vpshufb x, hi_t, x; \
+       vpxor tmp0, x, x;
+
+/**********************************************************************
+  4-way && 8-way SM4 with AES-NI and AVX
+ **********************************************************************/
+
+.text
+.align 16
+
+/*
+ * Following four affine transform look-up tables are from work by
+ * Markku-Juhani O. Saarinen, at https://github.com/mjosaarinen/sm4ni
+ *
+ * These allow exposing SM4 S-Box from AES SubByte.
+ */
+
+/* pre-SubByte affine transform, from SM4 field to AES field. */
+.Lpre_tf_lo_s:
+       .quad 0x9197E2E474720701, 0xC7C1B4B222245157
+.Lpre_tf_hi_s:
+       .quad 0xE240AB09EB49A200, 0xF052B91BF95BB012
+
+/* post-SubByte affine transform, from AES field to SM4 field. */
+.Lpost_tf_lo_s:
+       .quad 0x5B67F2CEA19D0834, 0xEDD14478172BBE82
+.Lpost_tf_hi_s:
+       .quad 0xAE7201DD73AFDC00, 0x11CDBE62CC1063BF
+
+/* For isolating SubBytes from AESENCLAST, inverse shift row */
+.Linv_shift_row:
+       .byte 0x00, 0x0d, 0x0a, 0x07, 0x04, 0x01, 0x0e, 0x0b
+       .byte 0x08, 0x05, 0x02, 0x0f, 0x0c, 0x09, 0x06, 0x03
+
+/* Inverse shift row + Rotate left by 8 bits on 32-bit words with vpshufb */
+.Linv_shift_row_rol_8:
+       .byte 0x07, 0x00, 0x0d, 0x0a, 0x0b, 0x04, 0x01, 0x0e
+       .byte 0x0f, 0x08, 0x05, 0x02, 0x03, 0x0c, 0x09, 0x06
+
+/* Inverse shift row + Rotate left by 16 bits on 32-bit words with vpshufb */
+.Linv_shift_row_rol_16:
+       .byte 0x0a, 0x07, 0x00, 0x0d, 0x0e, 0x0b, 0x04, 0x01
+       .byte 0x02, 0x0f, 0x08, 0x05, 0x06, 0x03, 0x0c, 0x09
+
+/* Inverse shift row + Rotate left by 24 bits on 32-bit words with vpshufb */
+.Linv_shift_row_rol_24:
+       .byte 0x0d, 0x0a, 0x07, 0x00, 0x01, 0x0e, 0x0b, 0x04
+       .byte 0x05, 0x02, 0x0f, 0x08, 0x09, 0x06, 0x03, 0x0c
+
+/* For CTR-mode IV byteswap */
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
+/* For input word byte-swap */
+.Lbswap32_mask:
+       .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+
+.align 4
+/* 4-bit mask */
+.L0f0f0f0f:
+       .long 0x0f0f0f0f
+
+.align 8
+.globl _gcry_sm4_aesni_avx_expand_key
+ELF(.type   _gcry_sm4_aesni_avx_expand_key,@function;)
+_gcry_sm4_aesni_avx_expand_key:
+       /* input:
+        *      %rdi: 128-bit key
+        *      %rsi: rkey_enc
+        *      %rdx: rkey_dec
+        *      %rcx: fk array
+        *      %r8: ck array
+        */
+       CFI_STARTPROC();
+
+       vmovd 0*4(%rdi), RA0;
+       vmovd 1*4(%rdi), RA1;
+       vmovd 2*4(%rdi), RA2;
+       vmovd 3*4(%rdi), RA3;
+
+       vmovdqa .Lbswap32_mask rRIP, RTMP2;
+       vpshufb RTMP2, RA0, RA0;
+       vpshufb RTMP2, RA1, RA1;
+       vpshufb RTMP2, RA2, RA2;
+       vpshufb RTMP2, RA3, RA3;
+
+       vmovd 0*4(%rcx), RB0;
+       vmovd 1*4(%rcx), RB1;
+       vmovd 2*4(%rcx), RB2;
+       vmovd 3*4(%rcx), RB3;
+       vpxor RB0, RA0, RA0;
+       vpxor RB1, RA1, RA1;
+       vpxor RB2, RA2, RA2;
+       vpxor RB3, RA3, RA3;
+
+       vbroadcastss .L0f0f0f0f rRIP, MASK_4BIT;
+       vmovdqa .Lpre_tf_lo_s rRIP, RTMP4;
+       vmovdqa .Lpre_tf_hi_s rRIP, RB0;
+       vmovdqa .Lpost_tf_lo_s rRIP, RB1;
+       vmovdqa .Lpost_tf_hi_s rRIP, RB2;
+       vmovdqa .Linv_shift_row rRIP, RB3;
+
+#define ROUND(round, s0, s1, s2, s3) \
+       vbroadcastss (4*(round))(%r8), RX0; \
+       vpxor s1, RX0, RX0; \
+       vpxor s2, RX0, RX0; \
+       vpxor s3, RX0, RX0; /* s1 ^ s2 ^ s3 ^ rk */ \
+       \
+       /* sbox, non-linear part */ \
+       transform_pre(RX0, RTMP4, RB0, MASK_4BIT, RTMP0); \
+       vaesenclast MASK_4BIT, RX0, RX0; \
+       transform_post(RX0, RB1, RB2, MASK_4BIT, RTMP0); \
+       \
+       /* linear part */ \
+       vpshufb RB3, RX0, RX0; \
+       vpxor RX0, s0, s0; /* s0 ^ x */ \
+       vpslld $13, RX0, RTMP0; \
+       vpsrld $19, RX0, RTMP1; \
+       vpslld $23, RX0, RTMP2; \
+       vpsrld $9, RX0, RTMP3; \
+       vpxor RTMP0, RTMP1, RTMP1;  \
+       vpxor RTMP2, RTMP3, RTMP3;  \
+       vpxor RTMP1, s0, s0; /* s0 ^ x ^ rol(x,13) */ \
+       vpxor RTMP3, s0, s0; /* s0 ^ x ^ rol(x,13) ^ rol(x,23) */
+
+       leaq (32*4)(%r8), %rax;
+       leaq (32*4)(%rdx), %rdx;
+.align 16
+.Lroundloop_expand_key:
+       leaq (-4*4)(%rdx), %rdx;
+       ROUND(0, RA0, RA1, RA2, RA3);
+       ROUND(1, RA1, RA2, RA3, RA0);
+       ROUND(2, RA2, RA3, RA0, RA1);
+       ROUND(3, RA3, RA0, RA1, RA2);
+       leaq (4*4)(%r8), %r8;
+       vmovd RA0, (0*4)(%rsi);
+       vmovd RA1, (1*4)(%rsi);
+       vmovd RA2, (2*4)(%rsi);
+       vmovd RA3, (3*4)(%rsi);
+       vmovd RA0, (3*4)(%rdx);
+       vmovd RA1, (2*4)(%rdx);
+       vmovd RA2, (1*4)(%rdx);
+       vmovd RA3, (0*4)(%rdx);
+       leaq (4*4)(%rsi), %rsi;
+       cmpq %rax, %r8;
+       jne .Lroundloop_expand_key;
+
+#undef ROUND
+
+       vzeroall;
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx_expand_key,.-_gcry_sm4_aesni_avx_expand_key;)
+
+.align 8
+ELF(.type   sm4_aesni_avx_crypt_blk1_4,@function;)
+sm4_aesni_avx_crypt_blk1_4:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      %rsi: dst (1..4 blocks)
+        *      %rdx: src (1..4 blocks)
+        *      %rcx: num blocks (1..4)
+        */
+       CFI_STARTPROC();
+
+       vmovdqu 0*16(%rdx), RA0;
+       vmovdqa RA0, RA1;
+       vmovdqa RA0, RA2;
+       vmovdqa RA0, RA3;
+       cmpq $2, %rcx;
+       jb .Lblk4_load_input_done;
+       vmovdqu 1*16(%rdx), RA1;
+       je .Lblk4_load_input_done;
+       vmovdqu 2*16(%rdx), RA2;
+       cmpq $3, %rcx;
+       je .Lblk4_load_input_done;
+       vmovdqu 3*16(%rdx), RA3;
+
+.Lblk4_load_input_done:
+
+       vmovdqa .Lbswap32_mask rRIP, RTMP2;
+       vpshufb RTMP2, RA0, RA0;
+       vpshufb RTMP2, RA1, RA1;
+       vpshufb RTMP2, RA2, RA2;
+       vpshufb RTMP2, RA3, RA3;
+
+       vbroadcastss .L0f0f0f0f rRIP, MASK_4BIT;
+       vmovdqa .Lpre_tf_lo_s rRIP, RTMP4;
+       vmovdqa .Lpre_tf_hi_s rRIP, RB0;
+       vmovdqa .Lpost_tf_lo_s rRIP, RB1;
+       vmovdqa .Lpost_tf_hi_s rRIP, RB2;
+       vmovdqa .Linv_shift_row rRIP, RB3;
+       vmovdqa .Linv_shift_row_rol_8 rRIP, RTMP2;
+       vmovdqa .Linv_shift_row_rol_16 rRIP, RTMP3;
+       transpose_4x4(RA0, RA1, RA2, RA3, RTMP0, RTMP1);
+
+#define ROUND(round, s0, s1, s2, s3) \
+       vbroadcastss (4*(round))(%rdi), RX0; \
+       vpxor s1, RX0, RX0; \
+       vpxor s2, RX0, RX0; \
+       vpxor s3, RX0, RX0; /* s1 ^ s2 ^ s3 ^ rk */ \
+       \
+       /* sbox, non-linear part */ \
+       transform_pre(RX0, RTMP4, RB0, MASK_4BIT, RTMP0); \
+       vaesenclast MASK_4BIT, RX0, RX0; \
+       transform_post(RX0, RB1, RB2, MASK_4BIT, RTMP0); \
+       \
+       /* linear part */ \
+       vpshufb RB3, RX0, RTMP0; \
+       vpxor RTMP0, s0, s0; /* s0 ^ x */ \
+       vpshufb RTMP2, RX0, RTMP1; \
+       vpxor RTMP1, RTMP0, RTMP0; /* x ^ rol(x,8) */ \
+       vpshufb RTMP3, RX0, RTMP1; \
+       vpxor RTMP1, RTMP0, RTMP0; /* x ^ rol(x,8) ^ rol(x,16) */ \
+       vpshufb .Linv_shift_row_rol_24 rRIP, RX0, RTMP1; \
+       vpxor RTMP1, s0, s0; /* s0 ^ x ^ rol(x,24) */ \
+       vpslld $2, RTMP0, RTMP1; \
+       vpsrld $30, RTMP0, RTMP0; \
+       vpxor RTMP0, s0, s0;  \
+       vpxor RTMP1, s0, s0; /* s0 ^ x ^ rol(x,2) ^ rol(x,10) ^ rol(x,18) ^ rol(x,24) */
+
+       leaq (32*4)(%rdi), %rax;
+.align 16
+.Lroundloop_blk4:
+       ROUND(0, RA0, RA1, RA2, RA3);
+       ROUND(1, RA1, RA2, RA3, RA0);
+       ROUND(2, RA2, RA3, RA0, RA1);
+       ROUND(3, RA3, RA0, RA1, RA2);
+       leaq (4*4)(%rdi), %rdi;
+       cmpq %rax, %rdi;
+       jne .Lroundloop_blk4;
+
+#undef ROUND
+
+       vmovdqa .Lbswap128_mask rRIP, RTMP2;
+
+       transpose_4x4(RA0, RA1, RA2, RA3, RTMP0, RTMP1);
+       vpshufb RTMP2, RA0, RA0;
+       vpshufb RTMP2, RA1, RA1;
+       vpshufb RTMP2, RA2, RA2;
+       vpshufb RTMP2, RA3, RA3;
+
+       vmovdqu RA0, 0*16(%rsi);
+       cmpq $2, %rcx;
+       jb .Lblk4_store_output_done;
+       vmovdqu RA1, 1*16(%rsi);
+       je .Lblk4_store_output_done;
+       vmovdqu RA2, 2*16(%rsi);
+       cmpq $3, %rcx;
+       je .Lblk4_store_output_done;
+       vmovdqu RA3, 3*16(%rsi);
+
+.Lblk4_store_output_done:
+       vzeroall;
+       xorl %eax, %eax;
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size sm4_aesni_avx_crypt_blk1_4,.-sm4_aesni_avx_crypt_blk1_4;)
+
+.align 8
+ELF(.type __sm4_crypt_blk8,@function;)
+__sm4_crypt_blk8:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: eight parallel
+        *                                              ciphertext blocks
+        * output:
+        *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: eight parallel plaintext
+        *                                              blocks
+        */
+       CFI_STARTPROC();
+
+       vmovdqa .Lbswap32_mask rRIP, RTMP2;
+       vpshufb RTMP2, RA0, RA0;
+       vpshufb RTMP2, RA1, RA1;
+       vpshufb RTMP2, RA2, RA2;
+       vpshufb RTMP2, RA3, RA3;
+       vpshufb RTMP2, RB0, RB0;
+       vpshufb RTMP2, RB1, RB1;
+       vpshufb RTMP2, RB2, RB2;
+       vpshufb RTMP2, RB3, RB3;
+
+       vbroadcastss .L0f0f0f0f rRIP, MASK_4BIT;
+       transpose_4x4(RA0, RA1, RA2, RA3, RTMP0, RTMP1);
+       transpose_4x4(RB0, RB1, RB2, RB3, RTMP0, RTMP1);
+
+#define ROUND(round, s0, s1, s2, s3, r0, r1, r2, r3) \
+       vbroadcastss (4*(round))(%rdi), RX0; \
+       vmovdqa .Lpre_tf_lo_s rRIP, RTMP4; \
+       vmovdqa .Lpre_tf_hi_s rRIP, RTMP1; \
+       vmovdqa RX0, RX1; \
+       vpxor s1, RX0, RX0; \
+       vpxor s2, RX0, RX0; \
+       vpxor s3, RX0, RX0; /* s1 ^ s2 ^ s3 ^ rk */ \
+           vmovdqa .Lpost_tf_lo_s rRIP, RTMP2; \
+           vmovdqa .Lpost_tf_hi_s rRIP, RTMP3; \
+           vpxor r1, RX1, RX1; \
+           vpxor r2, RX1, RX1; \
+           vpxor r3, RX1, RX1; /* r1 ^ r2 ^ r3 ^ rk */ \
+       \
+       /* sbox, non-linear part */ \
+       transform_pre(RX0, RTMP4, RTMP1, MASK_4BIT, RTMP0); \
+           transform_pre(RX1, RTMP4, RTMP1, MASK_4BIT, RTMP0); \
+           vmovdqa .Linv_shift_row rRIP, RTMP4; \
+       vaesenclast MASK_4BIT, RX0, RX0; \
+           vaesenclast MASK_4BIT, RX1, RX1; \
+       transform_post(RX0, RTMP2, RTMP3, MASK_4BIT, RTMP0); \
+           transform_post(RX1, RTMP2, RTMP3, MASK_4BIT, RTMP0); \
+       \
+       /* linear part */ \
+       vpshufb RTMP4, RX0, RTMP0; \
+       vpxor RTMP0, s0, s0; /* s0 ^ x */ \
+           vpshufb RTMP4, RX1, RTMP2; \
+           vmovdqa .Linv_shift_row_rol_8 rRIP, RTMP4; \
+           vpxor RTMP2, r0, r0; /* r0 ^ x */ \
+       vpshufb RTMP4, RX0, RTMP1; \
+       vpxor RTMP1, RTMP0, RTMP0; /* x ^ rol(x,8) */ \
+           vpshufb RTMP4, RX1, RTMP3; \
+           vmovdqa .Linv_shift_row_rol_16 rRIP, RTMP4; \
+           vpxor RTMP3, RTMP2, RTMP2; /* x ^ rol(x,8) */ \
+       vpshufb RTMP4, RX0, RTMP1; \
+       vpxor RTMP1, RTMP0, RTMP0; /* x ^ rol(x,8) ^ rol(x,16) */ \
+           vpshufb RTMP4, RX1, RTMP3; \
+           vmovdqa .Linv_shift_row_rol_24 rRIP, RTMP4; \
+           vpxor RTMP3, RTMP2, RTMP2; /* x ^ rol(x,8) ^ rol(x,16) */ \
+       vpshufb RTMP4, RX0, RTMP1; \
+       vpxor RTMP1, s0, s0; /* s0 ^ x ^ rol(x,24) */ \
+       vpslld $2, RTMP0, RTMP1; \
+       vpsrld $30, RTMP0, RTMP0; \
+       vpxor RTMP0, s0, s0;  \
+       vpxor RTMP1, s0, s0; /* s0 ^ x ^ rol(x,2) ^ rol(x,10) ^ rol(x,18) ^ rol(x,24) */ \
+           vpshufb RTMP4, RX1, RTMP3; \
+           vpxor RTMP3, r0, r0; /* r0 ^ x ^ rol(x,24) */ \
+           vpslld $2, RTMP2, RTMP3; \
+           vpsrld $30, RTMP2, RTMP2; \
+           vpxor RTMP2, r0, r0;  \
+           vpxor RTMP3, r0, r0; /* r0 ^ x ^ rol(x,2) ^ rol(x,10) ^ rol(x,18) ^ rol(x,24) */
+
+       leaq (32*4)(%rdi), %rax;
+.align 16
+.Lroundloop_blk8:
+       ROUND(0, RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3);
+       ROUND(1, RA1, RA2, RA3, RA0, RB1, RB2, RB3, RB0);
+       ROUND(2, RA2, RA3, RA0, RA1, RB2, RB3, RB0, RB1);
+       ROUND(3, RA3, RA0, RA1, RA2, RB3, RB0, RB1, RB2);
+       leaq (4*4)(%rdi), %rdi;
+       cmpq %rax, %rdi;
+       jne .Lroundloop_blk8;
+
+#undef ROUND
+
+       vmovdqa .Lbswap128_mask rRIP, RTMP2;
+
+       transpose_4x4(RA0, RA1, RA2, RA3, RTMP0, RTMP1);
+       transpose_4x4(RB0, RB1, RB2, RB3, RTMP0, RTMP1);
+       vpshufb RTMP2, RA0, RA0;
+       vpshufb RTMP2, RA1, RA1;
+       vpshufb RTMP2, RA2, RA2;
+       vpshufb RTMP2, RA3, RA3;
+       vpshufb RTMP2, RB0, RB0;
+       vpshufb RTMP2, RB1, RB1;
+       vpshufb RTMP2, RB2, RB2;
+       vpshufb RTMP2, RB3, RB3;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size __sm4_crypt_blk8,.-__sm4_crypt_blk8;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx_crypt_blk1_8
+ELF(.type   _gcry_sm4_aesni_avx_crypt_blk1_8,@function;)
+_gcry_sm4_aesni_avx_crypt_blk1_8:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      %rsi: dst (1..8 blocks)
+        *      %rdx: src (1..8 blocks)
+        *      %rcx: num blocks (1..8)
+        */
+       CFI_STARTPROC();
+
+       cmpq $5, %rcx;
+       jb sm4_aesni_avx_crypt_blk1_4;
+       vmovdqu (0 * 16)(%rdx), RA0;
+       vmovdqu (1 * 16)(%rdx), RA1;
+       vmovdqu (2 * 16)(%rdx), RA2;
+       vmovdqu (3 * 16)(%rdx), RA3;
+       vmovdqu (4 * 16)(%rdx), RB0;
+       vmovdqa RB0, RB1;
+       vmovdqa RB0, RB2;
+       vmovdqa RB0, RB3;
+       je .Lblk8_load_input_done;
+       vmovdqu (5 * 16)(%rdx), RB1;
+       cmpq $7, %rcx;
+       jb .Lblk8_load_input_done;
+       vmovdqu (6 * 16)(%rdx), RB2;
+       je .Lblk8_load_input_done;
+       vmovdqu (7 * 16)(%rdx), RB3;
+
+.Lblk8_load_input_done:
+       call __sm4_crypt_blk8;
+
+       cmpq $6, %rcx;
+       vmovdqu RA0, (0 * 16)(%rsi);
+       vmovdqu RA1, (1 * 16)(%rsi);
+       vmovdqu RA2, (2 * 16)(%rsi);
+       vmovdqu RA3, (3 * 16)(%rsi);
+       vmovdqu RB0, (4 * 16)(%rsi);
+       jb .Lblk8_store_output_done;
+       vmovdqu RB1, (5 * 16)(%rsi);
+       je .Lblk8_store_output_done;
+       vmovdqu RB2, (6 * 16)(%rsi);
+       cmpq $7, %rcx;
+       je .Lblk8_store_output_done;
+       vmovdqu RB3, (7 * 16)(%rsi);
+
+.Lblk8_store_output_done:
+       vzeroall;
+       xorl %eax, %eax;
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx_crypt_blk1_8,.-_gcry_sm4_aesni_avx_crypt_blk1_8;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx_ctr_enc
+ELF(.type   _gcry_sm4_aesni_avx_ctr_enc,@function;)
+_gcry_sm4_aesni_avx_ctr_enc:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      %rsi: dst (8 blocks)
+        *      %rdx: src (8 blocks)
+        *      %rcx: iv (big endian, 128bit)
+        */
+       CFI_STARTPROC();
+
+       /* load IV and byteswap */
+       vmovdqu (%rcx), RA0;
+
+       vmovdqa .Lbswap128_mask rRIP, RBSWAP;
+       vpshufb RBSWAP, RA0, RTMP0; /* be => le */
+
+       vpcmpeqd RNOT, RNOT, RNOT;
+       vpsrldq $8, RNOT, RNOT; /* low: -1, high: 0 */
+
+#define inc_le128(x, minus_one, tmp) \
+       vpcmpeqq minus_one, x, tmp; \
+       vpsubq minus_one, x, x; \
+       vpslldq $8, tmp, tmp; \
+       vpsubq tmp, x, x;
+
+       /* construct IVs */
+       inc_le128(RTMP0, RNOT, RTMP2); /* +1 */
+       vpshufb RBSWAP, RTMP0, RA1;
+       inc_le128(RTMP0, RNOT, RTMP2); /* +2 */
+       vpshufb RBSWAP, RTMP0, RA2;
+       inc_le128(RTMP0, RNOT, RTMP2); /* +3 */
+       vpshufb RBSWAP, RTMP0, RA3;
+       inc_le128(RTMP0, RNOT, RTMP2); /* +4 */
+       vpshufb RBSWAP, RTMP0, RB0;
+       inc_le128(RTMP0, RNOT, RTMP2); /* +5 */
+       vpshufb RBSWAP, RTMP0, RB1;
+       inc_le128(RTMP0, RNOT, RTMP2); /* +6 */
+       vpshufb RBSWAP, RTMP0, RB2;
+       inc_le128(RTMP0, RNOT, RTMP2); /* +7 */
+       vpshufb RBSWAP, RTMP0, RB3;
+       inc_le128(RTMP0, RNOT, RTMP2); /* +8 */
+       vpshufb RBSWAP, RTMP0, RTMP1;
+
+       /* store new IV */
+       vmovdqu RTMP1, (%rcx);
+
+       call __sm4_crypt_blk8;
+
+       vpxor (0 * 16)(%rdx), RA0, RA0;
+       vpxor (1 * 16)(%rdx), RA1, RA1;
+       vpxor (2 * 16)(%rdx), RA2, RA2;
+       vpxor (3 * 16)(%rdx), RA3, RA3;
+       vpxor (4 * 16)(%rdx), RB0, RB0;
+       vpxor (5 * 16)(%rdx), RB1, RB1;
+       vpxor (6 * 16)(%rdx), RB2, RB2;
+       vpxor (7 * 16)(%rdx), RB3, RB3;
+
+       vmovdqu RA0, (0 * 16)(%rsi);
+       vmovdqu RA1, (1 * 16)(%rsi);
+       vmovdqu RA2, (2 * 16)(%rsi);
+       vmovdqu RA3, (3 * 16)(%rsi);
+       vmovdqu RB0, (4 * 16)(%rsi);
+       vmovdqu RB1, (5 * 16)(%rsi);
+       vmovdqu RB2, (6 * 16)(%rsi);
+       vmovdqu RB3, (7 * 16)(%rsi);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx_ctr_enc,.-_gcry_sm4_aesni_avx_ctr_enc;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx_cbc_dec
+ELF(.type   _gcry_sm4_aesni_avx_cbc_dec,@function;)
+_gcry_sm4_aesni_avx_cbc_dec:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      %rsi: dst (8 blocks)
+        *      %rdx: src (8 blocks)
+        *      %rcx: iv
+        */
+       CFI_STARTPROC();
+
+       vmovdqu (0 * 16)(%rdx), RA0;
+       vmovdqu (1 * 16)(%rdx), RA1;
+       vmovdqu (2 * 16)(%rdx), RA2;
+       vmovdqu (3 * 16)(%rdx), RA3;
+       vmovdqu (4 * 16)(%rdx), RB0;
+       vmovdqu (5 * 16)(%rdx), RB1;
+       vmovdqu (6 * 16)(%rdx), RB2;
+       vmovdqu (7 * 16)(%rdx), RB3;
+
+       call __sm4_crypt_blk8;
+
+       vmovdqu (7 * 16)(%rdx), RNOT;
+       vpxor (%rcx), RA0, RA0;
+       vpxor (0 * 16)(%rdx), RA1, RA1;
+       vpxor (1 * 16)(%rdx), RA2, RA2;
+       vpxor (2 * 16)(%rdx), RA3, RA3;
+       vpxor (3 * 16)(%rdx), RB0, RB0;
+       vpxor (4 * 16)(%rdx), RB1, RB1;
+       vpxor (5 * 16)(%rdx), RB2, RB2;
+       vpxor (6 * 16)(%rdx), RB3, RB3;
+       vmovdqu RNOT, (%rcx); /* store new IV */
+
+       vmovdqu RA0, (0 * 16)(%rsi);
+       vmovdqu RA1, (1 * 16)(%rsi);
+       vmovdqu RA2, (2 * 16)(%rsi);
+       vmovdqu RA3, (3 * 16)(%rsi);
+       vmovdqu RB0, (4 * 16)(%rsi);
+       vmovdqu RB1, (5 * 16)(%rsi);
+       vmovdqu RB2, (6 * 16)(%rsi);
+       vmovdqu RB3, (7 * 16)(%rsi);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx_cbc_dec,.-_gcry_sm4_aesni_avx_cbc_dec;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx_cfb_dec
+ELF(.type   _gcry_sm4_aesni_avx_cfb_dec,@function;)
+_gcry_sm4_aesni_avx_cfb_dec:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      %rsi: dst (8 blocks)
+        *      %rdx: src (8 blocks)
+        *      %rcx: iv
+        */
+       CFI_STARTPROC();
+
+       /* Load input */
+       vmovdqu (%rcx), RA0;
+       vmovdqu 0 * 16(%rdx), RA1;
+       vmovdqu 1 * 16(%rdx), RA2;
+       vmovdqu 2 * 16(%rdx), RA3;
+       vmovdqu 3 * 16(%rdx), RB0;
+       vmovdqu 4 * 16(%rdx), RB1;
+       vmovdqu 5 * 16(%rdx), RB2;
+       vmovdqu 6 * 16(%rdx), RB3;
+
+       /* Update IV */
+       vmovdqu 7 * 16(%rdx), RNOT;
+       vmovdqu RNOT, (%rcx);
+
+       call __sm4_crypt_blk8;
+
+       vpxor (0 * 16)(%rdx), RA0, RA0;
+       vpxor (1 * 16)(%rdx), RA1, RA1;
+       vpxor (2 * 16)(%rdx), RA2, RA2;
+       vpxor (3 * 16)(%rdx), RA3, RA3;
+       vpxor (4 * 16)(%rdx), RB0, RB0;
+       vpxor (5 * 16)(%rdx), RB1, RB1;
+       vpxor (6 * 16)(%rdx), RB2, RB2;
+       vpxor (7 * 16)(%rdx), RB3, RB3;
+
+       vmovdqu RA0, (0 * 16)(%rsi);
+       vmovdqu RA1, (1 * 16)(%rsi);
+       vmovdqu RA2, (2 * 16)(%rsi);
+       vmovdqu RA3, (3 * 16)(%rsi);
+       vmovdqu RB0, (4 * 16)(%rsi);
+       vmovdqu RB1, (5 * 16)(%rsi);
+       vmovdqu RB2, (6 * 16)(%rsi);
+       vmovdqu RB3, (7 * 16)(%rsi);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx_cfb_dec,.-_gcry_sm4_aesni_avx_cfb_dec;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx_ocb_enc
+ELF(.type _gcry_sm4_aesni_avx_ocb_enc,@function;)
+
+_gcry_sm4_aesni_avx_ocb_enc:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      %rsi: dst (8 blocks)
+        *      %rdx: src (8 blocks)
+        *      %rcx: offset
+        *      %r8 : checksum
+        *      %r9 : L pointers (void *L[8])
+        */
+       CFI_STARTPROC();
+
+       subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
+
+       movq %r10, (0 * 8)(%rsp);
+       movq %r11, (1 * 8)(%rsp);
+       movq %r12, (2 * 8)(%rsp);
+       movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+
+       vmovdqu (%rcx), RTMP0;
+       vmovdqu (%r8), RTMP1;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* Checksum_i = Checksum_{i-1} xor P_i  */
+       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+
+#define OCB_INPUT(n, lreg, xreg) \
+         vmovdqu (n * 16)(%rdx), xreg; \
+         vpxor (lreg), RTMP0, RTMP0; \
+         vpxor xreg, RTMP1, RTMP1; \
+         vpxor RTMP0, xreg, xreg; \
+         vmovdqu RTMP0, (n * 16)(%rsi);
+       movq (0 * 8)(%r9), %r10;
+       movq (1 * 8)(%r9), %r11;
+       movq (2 * 8)(%r9), %r12;
+       movq (3 * 8)(%r9), %r13;
+       OCB_INPUT(0, %r10, RA0);
+       OCB_INPUT(1, %r11, RA1);
+       OCB_INPUT(2, %r12, RA2);
+       OCB_INPUT(3, %r13, RA3);
+       movq (4 * 8)(%r9), %r10;
+       movq (5 * 8)(%r9), %r11;
+       movq (6 * 8)(%r9), %r12;
+       movq (7 * 8)(%r9), %r13;
+       OCB_INPUT(4, %r10, RB0);
+       OCB_INPUT(5, %r11, RB1);
+       OCB_INPUT(6, %r12, RB2);
+       OCB_INPUT(7, %r13, RB3);
+#undef OCB_INPUT
+
+       vmovdqu RTMP0, (%rcx);
+       vmovdqu RTMP1, (%r8);
+
+       movq (0 * 8)(%rsp), %r10;
+       CFI_RESTORE(%r10);
+       movq (1 * 8)(%rsp), %r11;
+       CFI_RESTORE(%r11);
+       movq (2 * 8)(%rsp), %r12;
+       CFI_RESTORE(%r12);
+       movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r13);
+
+       call __sm4_crypt_blk8;
+
+       addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
+
+       vpxor (0 * 16)(%rsi), RA0, RA0;
+       vpxor (1 * 16)(%rsi), RA1, RA1;
+       vpxor (2 * 16)(%rsi), RA2, RA2;
+       vpxor (3 * 16)(%rsi), RA3, RA3;
+       vpxor (4 * 16)(%rsi), RB0, RB0;
+       vpxor (5 * 16)(%rsi), RB1, RB1;
+       vpxor (6 * 16)(%rsi), RB2, RB2;
+       vpxor (7 * 16)(%rsi), RB3, RB3;
+
+       vmovdqu RA0, (0 * 16)(%rsi);
+       vmovdqu RA1, (1 * 16)(%rsi);
+       vmovdqu RA2, (2 * 16)(%rsi);
+       vmovdqu RA3, (3 * 16)(%rsi);
+       vmovdqu RB0, (4 * 16)(%rsi);
+       vmovdqu RB1, (5 * 16)(%rsi);
+       vmovdqu RB2, (6 * 16)(%rsi);
+       vmovdqu RB3, (7 * 16)(%rsi);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx_ocb_enc,.-_gcry_sm4_aesni_avx_ocb_enc;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx_ocb_dec
+ELF(.type _gcry_sm4_aesni_avx_ocb_dec,@function;)
+
+_gcry_sm4_aesni_avx_ocb_dec:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      %rsi: dst (8 blocks)
+        *      %rdx: src (8 blocks)
+        *      %rcx: offset
+        *      %r8 : checksum
+        *      %r9 : L pointers (void *L[8])
+        */
+       CFI_STARTPROC();
+
+       subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
+
+       movq %r10, (0 * 8)(%rsp);
+       movq %r11, (1 * 8)(%rsp);
+       movq %r12, (2 * 8)(%rsp);
+       movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+
+       movdqu (%rcx), RTMP0;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i)  */
+
+#define OCB_INPUT(n, lreg, xreg) \
+         vmovdqu (n * 16)(%rdx), xreg; \
+         vpxor (lreg), RTMP0, RTMP0; \
+         vpxor RTMP0, xreg, xreg; \
+         vmovdqu RTMP0, (n * 16)(%rsi);
+       movq (0 * 8)(%r9), %r10;
+       movq (1 * 8)(%r9), %r11;
+       movq (2 * 8)(%r9), %r12;
+       movq (3 * 8)(%r9), %r13;
+       OCB_INPUT(0, %r10, RA0);
+       OCB_INPUT(1, %r11, RA1);
+       OCB_INPUT(2, %r12, RA2);
+       OCB_INPUT(3, %r13, RA3);
+       movq (4 * 8)(%r9), %r10;
+       movq (5 * 8)(%r9), %r11;
+       movq (6 * 8)(%r9), %r12;
+       movq (7 * 8)(%r9), %r13;
+       OCB_INPUT(4, %r10, RB0);
+       OCB_INPUT(5, %r11, RB1);
+       OCB_INPUT(6, %r12, RB2);
+       OCB_INPUT(7, %r13, RB3);
+#undef OCB_INPUT
+
+       vmovdqu RTMP0, (%rcx);
+
+       movq (0 * 8)(%rsp), %r10;
+       CFI_RESTORE(%r10);
+       movq (1 * 8)(%rsp), %r11;
+       CFI_RESTORE(%r11);
+       movq (2 * 8)(%rsp), %r12;
+       CFI_RESTORE(%r12);
+       movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r13);
+
+       call __sm4_crypt_blk8;
+
+       addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
+
+       vmovdqu (%r8), RTMP0;
+
+       vpxor (0 * 16)(%rsi), RA0, RA0;
+       vpxor (1 * 16)(%rsi), RA1, RA1;
+       vpxor (2 * 16)(%rsi), RA2, RA2;
+       vpxor (3 * 16)(%rsi), RA3, RA3;
+       vpxor (4 * 16)(%rsi), RB0, RB0;
+       vpxor (5 * 16)(%rsi), RB1, RB1;
+       vpxor (6 * 16)(%rsi), RB2, RB2;
+       vpxor (7 * 16)(%rsi), RB3, RB3;
+
+       /* Checksum_i = Checksum_{i-1} xor P_i  */
+
+       vmovdqu RA0, (0 * 16)(%rsi);
+       vpxor RA0, RTMP0, RTMP0;
+       vmovdqu RA1, (1 * 16)(%rsi);
+       vpxor RA1, RTMP0, RTMP0;
+       vmovdqu RA2, (2 * 16)(%rsi);
+       vpxor RA2, RTMP0, RTMP0;
+       vmovdqu RA3, (3 * 16)(%rsi);
+       vpxor RA3, RTMP0, RTMP0;
+       vmovdqu RB0, (4 * 16)(%rsi);
+       vpxor RB0, RTMP0, RTMP0;
+       vmovdqu RB1, (5 * 16)(%rsi);
+       vpxor RB1, RTMP0, RTMP0;
+       vmovdqu RB2, (6 * 16)(%rsi);
+       vpxor RB2, RTMP0, RTMP0;
+       vmovdqu RB3, (7 * 16)(%rsi);
+       vpxor RB3, RTMP0, RTMP0;
+
+       vmovdqu RTMP0, (%r8);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx_ocb_dec,.-_gcry_sm4_aesni_avx_ocb_dec;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx_ocb_auth
+ELF(.type _gcry_sm4_aesni_avx_ocb_auth,@function;)
+
+_gcry_sm4_aesni_avx_ocb_auth:
+       /* input:
+        *      %rdi: round key array, CTX
+        *      %rsi: abuf (8 blocks)
+        *      %rdx: offset
+        *      %rcx: checksum
+        *      %r8 : L pointers (void *L[8])
+        */
+       CFI_STARTPROC();
+
+       subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
+
+       movq %r10, (0 * 8)(%rsp);
+       movq %r11, (1 * 8)(%rsp);
+       movq %r12, (2 * 8)(%rsp);
+       movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+
+       vmovdqu (%rdx), RTMP0;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
+
+#define OCB_INPUT(n, lreg, xreg) \
+         vmovdqu (n * 16)(%rsi), xreg; \
+         vpxor (lreg), RTMP0, RTMP0; \
+         vpxor RTMP0, xreg, xreg;
+       movq (0 * 8)(%r8), %r10;
+       movq (1 * 8)(%r8), %r11;
+       movq (2 * 8)(%r8), %r12;
+       movq (3 * 8)(%r8), %r13;
+       OCB_INPUT(0, %r10, RA0);
+       OCB_INPUT(1, %r11, RA1);
+       OCB_INPUT(2, %r12, RA2);
+       OCB_INPUT(3, %r13, RA3);
+       movq (4 * 8)(%r8), %r10;
+       movq (5 * 8)(%r8), %r11;
+       movq (6 * 8)(%r8), %r12;
+       movq (7 * 8)(%r8), %r13;
+       OCB_INPUT(4, %r10, RB0);
+       OCB_INPUT(5, %r11, RB1);
+       OCB_INPUT(6, %r12, RB2);
+       OCB_INPUT(7, %r13, RB3);
+#undef OCB_INPUT
+
+       vmovdqu RTMP0, (%rdx);
+
+       movq (0 * 8)(%rsp), %r10;
+       CFI_RESTORE(%r10);
+       movq (1 * 8)(%rsp), %r11;
+       CFI_RESTORE(%r11);
+       movq (2 * 8)(%rsp), %r12;
+       CFI_RESTORE(%r12);
+       movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r13);
+
+       call __sm4_crypt_blk8;
+
+       addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
+
+       vmovdqu (%rcx), RTMP0;
+       vpxor RB0, RA0, RA0;
+       vpxor RB1, RA1, RA1;
+       vpxor RB2, RA2, RA2;
+       vpxor RB3, RA3, RA3;
+
+       vpxor RTMP0, RA3, RA3;
+       vpxor RA2, RA0, RA0;
+       vpxor RA3, RA1, RA1;
+
+       vpxor RA1, RA0, RA0;
+       vmovdqu RA0, (%rcx);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx_ocb_auth,.-_gcry_sm4_aesni_avx_ocb_auth;)
+
+#endif /*defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)*/
+#endif /*__x86_64*/
diff --git a/cipher/sm4-aesni-avx2-amd64.S b/cipher/sm4-aesni-avx2-amd64.S
new file mode 100644 (file)
index 0000000..7a8b955
--- /dev/null
@@ -0,0 +1,851 @@
+/* sm4-avx2-amd64.S  -  AVX2 implementation of SM4 cipher
+ *
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/* Based on SM4 AES-NI work by Markku-Juhani O. Saarinen at:
+ *  https://github.com/mjosaarinen/sm4ni
+ */
+
+#include <config.h>
+
+#ifdef __x86_64
+#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \
+    defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT)
+
+#include "asm-common-amd64.h"
+
+/* vector registers */
+#define RX0          %ymm0
+#define RX1          %ymm1
+#define MASK_4BIT    %ymm2
+#define RTMP0        %ymm3
+#define RTMP1        %ymm4
+#define RTMP2        %ymm5
+#define RTMP3        %ymm6
+#define RTMP4        %ymm7
+
+#define RA0          %ymm8
+#define RA1          %ymm9
+#define RA2          %ymm10
+#define RA3          %ymm11
+
+#define RB0          %ymm12
+#define RB1          %ymm13
+#define RB2          %ymm14
+#define RB3          %ymm15
+
+#define RNOT         %ymm0
+#define RBSWAP       %ymm1
+
+#define RX0x         %xmm0
+#define RX1x         %xmm1
+#define MASK_4BITx   %xmm2
+
+#define RNOTx        %xmm0
+#define RBSWAPx      %xmm1
+
+#define RTMP0x       %xmm3
+#define RTMP1x       %xmm4
+#define RTMP2x       %xmm5
+#define RTMP3x       %xmm6
+#define RTMP4x       %xmm7
+
+/**********************************************************************
+  helper macros
+ **********************************************************************/
+
+/* Transpose four 32-bit words between 128-bit vector lanes. */
+#define transpose_4x4(x0, x1, x2, x3, t1, t2) \
+       vpunpckhdq x1, x0, t2; \
+       vpunpckldq x1, x0, x0; \
+       \
+       vpunpckldq x3, x2, t1; \
+       vpunpckhdq x3, x2, x2; \
+       \
+       vpunpckhqdq t1, x0, x1; \
+       vpunpcklqdq t1, x0, x0; \
+       \
+       vpunpckhqdq x2, t2, x3; \
+       vpunpcklqdq x2, t2, x2;
+
+/* post-SubByte transform. */
+#define transform_pre(x, lo_t, hi_t, mask4bit, tmp0) \
+       vpand x, mask4bit, tmp0; \
+       vpandn x, mask4bit, x; \
+       vpsrld $4, x, x; \
+       \
+       vpshufb tmp0, lo_t, tmp0; \
+       vpshufb x, hi_t, x; \
+       vpxor tmp0, x, x;
+
+/* post-SubByte transform. Note: x has been XOR'ed with mask4bit by
+ * 'vaeslastenc' instruction. */
+#define transform_post(x, lo_t, hi_t, mask4bit, tmp0) \
+       vpandn mask4bit, x, tmp0; \
+       vpsrld $4, x, x; \
+       vpand x, mask4bit, x; \
+       \
+       vpshufb tmp0, lo_t, tmp0; \
+       vpshufb x, hi_t, x; \
+       vpxor tmp0, x, x;
+
+/**********************************************************************
+  16-way SM4 with AES-NI and AVX
+ **********************************************************************/
+
+.text
+.align 16
+
+/*
+ * Following four affine transform look-up tables are from work by
+ * Markku-Juhani O. Saarinen, at https://github.com/mjosaarinen/sm4ni
+ *
+ * These allow exposing SM4 S-Box from AES SubByte.
+ */
+
+/* pre-SubByte affine transform, from SM4 field to AES field. */
+.Lpre_tf_lo_s:
+       .quad 0x9197E2E474720701, 0xC7C1B4B222245157
+.Lpre_tf_hi_s:
+       .quad 0xE240AB09EB49A200, 0xF052B91BF95BB012
+
+/* post-SubByte affine transform, from AES field to SM4 field. */
+.Lpost_tf_lo_s:
+       .quad 0x5B67F2CEA19D0834, 0xEDD14478172BBE82
+.Lpost_tf_hi_s:
+       .quad 0xAE7201DD73AFDC00, 0x11CDBE62CC1063BF
+
+/* For isolating SubBytes from AESENCLAST, inverse shift row */
+.Linv_shift_row:
+       .byte 0x00, 0x0d, 0x0a, 0x07, 0x04, 0x01, 0x0e, 0x0b
+       .byte 0x08, 0x05, 0x02, 0x0f, 0x0c, 0x09, 0x06, 0x03
+
+/* Inverse shift row + Rotate left by 8 bits on 32-bit words with vpshufb */
+.Linv_shift_row_rol_8:
+       .byte 0x07, 0x00, 0x0d, 0x0a, 0x0b, 0x04, 0x01, 0x0e
+       .byte 0x0f, 0x08, 0x05, 0x02, 0x03, 0x0c, 0x09, 0x06
+
+/* Inverse shift row + Rotate left by 16 bits on 32-bit words with vpshufb */
+.Linv_shift_row_rol_16:
+       .byte 0x0a, 0x07, 0x00, 0x0d, 0x0e, 0x0b, 0x04, 0x01
+       .byte 0x02, 0x0f, 0x08, 0x05, 0x06, 0x03, 0x0c, 0x09
+
+/* Inverse shift row + Rotate left by 24 bits on 32-bit words with vpshufb */
+.Linv_shift_row_rol_24:
+       .byte 0x0d, 0x0a, 0x07, 0x00, 0x01, 0x0e, 0x0b, 0x04
+       .byte 0x05, 0x02, 0x0f, 0x08, 0x09, 0x06, 0x03, 0x0c
+
+/* For CTR-mode IV byteswap */
+.Lbswap128_mask:
+       .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
+/* For input word byte-swap */
+.Lbswap32_mask:
+       .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+
+.align 4
+/* 4-bit mask */
+.L0f0f0f0f:
+       .long 0x0f0f0f0f
+
+.align 8
+ELF(.type   __sm4_crypt_blk16,@function;)
+__sm4_crypt_blk16:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
+        *                                              plaintext blocks
+        * output:
+        *      RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3: sixteen parallel
+        *                                              ciphertext blocks
+        */
+       CFI_STARTPROC();
+
+       vbroadcasti128 .Lbswap32_mask rRIP, RTMP2;
+       vpshufb RTMP2, RA0, RA0;
+       vpshufb RTMP2, RA1, RA1;
+       vpshufb RTMP2, RA2, RA2;
+       vpshufb RTMP2, RA3, RA3;
+       vpshufb RTMP2, RB0, RB0;
+       vpshufb RTMP2, RB1, RB1;
+       vpshufb RTMP2, RB2, RB2;
+       vpshufb RTMP2, RB3, RB3;
+
+       vpbroadcastd .L0f0f0f0f rRIP, MASK_4BIT;
+       transpose_4x4(RA0, RA1, RA2, RA3, RTMP0, RTMP1);
+       transpose_4x4(RB0, RB1, RB2, RB3, RTMP0, RTMP1);
+
+#define ROUND(round, s0, s1, s2, s3, r0, r1, r2, r3) \
+       vpbroadcastd (4*(round))(%rdi), RX0; \
+       vbroadcasti128 .Lpre_tf_lo_s rRIP, RTMP4; \
+       vbroadcasti128 .Lpre_tf_hi_s rRIP, RTMP1; \
+       vmovdqa RX0, RX1; \
+       vpxor s1, RX0, RX0; \
+       vpxor s2, RX0, RX0; \
+       vpxor s3, RX0, RX0; /* s1 ^ s2 ^ s3 ^ rk */ \
+           vbroadcasti128 .Lpost_tf_lo_s rRIP, RTMP2; \
+           vbroadcasti128 .Lpost_tf_hi_s rRIP, RTMP3; \
+           vpxor r1, RX1, RX1; \
+           vpxor r2, RX1, RX1; \
+           vpxor r3, RX1, RX1; /* r1 ^ r2 ^ r3 ^ rk */ \
+       \
+       /* sbox, non-linear part */ \
+       transform_pre(RX0, RTMP4, RTMP1, MASK_4BIT, RTMP0); \
+           transform_pre(RX1, RTMP4, RTMP1, MASK_4BIT, RTMP0); \
+       vextracti128 $1, RX0, RTMP4x; \
+           vextracti128 $1, RX1, RTMP0x; \
+       vaesenclast MASK_4BITx, RX0x, RX0x; \
+       vaesenclast MASK_4BITx, RTMP4x, RTMP4x; \
+           vaesenclast MASK_4BITx, RX1x, RX1x; \
+           vaesenclast MASK_4BITx, RTMP0x, RTMP0x; \
+       vinserti128 $1, RTMP4x, RX0, RX0; \
+       vbroadcasti128 .Linv_shift_row rRIP, RTMP4; \
+           vinserti128 $1, RTMP0x, RX1, RX1; \
+       transform_post(RX0, RTMP2, RTMP3, MASK_4BIT, RTMP0); \
+           transform_post(RX1, RTMP2, RTMP3, MASK_4BIT, RTMP0); \
+       \
+       /* linear part */ \
+       vpshufb RTMP4, RX0, RTMP0; \
+       vpxor RTMP0, s0, s0; /* s0 ^ x */ \
+           vpshufb RTMP4, RX1, RTMP2; \
+           vbroadcasti128 .Linv_shift_row_rol_8 rRIP, RTMP4; \
+           vpxor RTMP2, r0, r0; /* r0 ^ x */ \
+       vpshufb RTMP4, RX0, RTMP1; \
+       vpxor RTMP1, RTMP0, RTMP0; /* x ^ rol(x,8) */ \
+           vpshufb RTMP4, RX1, RTMP3; \
+           vbroadcasti128 .Linv_shift_row_rol_16 rRIP, RTMP4; \
+           vpxor RTMP3, RTMP2, RTMP2; /* x ^ rol(x,8) */ \
+       vpshufb RTMP4, RX0, RTMP1; \
+       vpxor RTMP1, RTMP0, RTMP0; /* x ^ rol(x,8) ^ rol(x,16) */ \
+           vpshufb RTMP4, RX1, RTMP3; \
+           vbroadcasti128 .Linv_shift_row_rol_24 rRIP, RTMP4; \
+           vpxor RTMP3, RTMP2, RTMP2; /* x ^ rol(x,8) ^ rol(x,16) */ \
+       vpshufb RTMP4, RX0, RTMP1; \
+       vpxor RTMP1, s0, s0; /* s0 ^ x ^ rol(x,24) */ \
+       vpslld $2, RTMP0, RTMP1; \
+       vpsrld $30, RTMP0, RTMP0; \
+       vpxor RTMP0, s0, s0;  \
+       vpxor RTMP1, s0, s0; /* s0 ^ x ^ rol(x,2) ^ rol(x,10) ^ rol(x,18) ^ rol(x,24) */ \
+           vpshufb RTMP4, RX1, RTMP3; \
+           vpxor RTMP3, r0, r0; /* r0 ^ x ^ rol(x,24) */ \
+           vpslld $2, RTMP2, RTMP3; \
+           vpsrld $30, RTMP2, RTMP2; \
+           vpxor RTMP2, r0, r0;  \
+           vpxor RTMP3, r0, r0; /* r0 ^ x ^ rol(x,2) ^ rol(x,10) ^ rol(x,18) ^ rol(x,24) */
+
+       leaq (32*4)(%rdi), %rax;
+.align 16
+.Lroundloop_blk8:
+       ROUND(0, RA0, RA1, RA2, RA3, RB0, RB1, RB2, RB3);
+       ROUND(1, RA1, RA2, RA3, RA0, RB1, RB2, RB3, RB0);
+       ROUND(2, RA2, RA3, RA0, RA1, RB2, RB3, RB0, RB1);
+       ROUND(3, RA3, RA0, RA1, RA2, RB3, RB0, RB1, RB2);
+       leaq (4*4)(%rdi), %rdi;
+       cmpq %rax, %rdi;
+       jne .Lroundloop_blk8;
+
+#undef ROUND
+
+       vbroadcasti128 .Lbswap128_mask rRIP, RTMP2;
+
+       transpose_4x4(RA0, RA1, RA2, RA3, RTMP0, RTMP1);
+       transpose_4x4(RB0, RB1, RB2, RB3, RTMP0, RTMP1);
+       vpshufb RTMP2, RA0, RA0;
+       vpshufb RTMP2, RA1, RA1;
+       vpshufb RTMP2, RA2, RA2;
+       vpshufb RTMP2, RA3, RA3;
+       vpshufb RTMP2, RB0, RB0;
+       vpshufb RTMP2, RB1, RB1;
+       vpshufb RTMP2, RB2, RB2;
+       vpshufb RTMP2, RB3, RB3;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size __sm4_crypt_blk16,.-__sm4_crypt_blk16;)
+
+#define inc_le128(x, minus_one, tmp) \
+       vpcmpeqq minus_one, x, tmp; \
+       vpsubq minus_one, x, x; \
+       vpslldq $8, tmp, tmp; \
+       vpsubq tmp, x, x;
+
+.align 8
+.globl _gcry_sm4_aesni_avx2_ctr_enc
+ELF(.type   _gcry_sm4_aesni_avx2_ctr_enc,@function;)
+_gcry_sm4_aesni_avx2_ctr_enc:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        *      %rcx: iv (big endian, 128bit)
+        */
+       CFI_STARTPROC();
+
+       movq 8(%rcx), %rax;
+       bswapq %rax;
+
+       vzeroupper;
+
+       vbroadcasti128 .Lbswap128_mask rRIP, RTMP3;
+       vpcmpeqd RNOT, RNOT, RNOT;
+       vpsrldq $8, RNOT, RNOT;   /* ab: -1:0 ; cd: -1:0 */
+       vpaddq RNOT, RNOT, RTMP2; /* ab: -2:0 ; cd: -2:0 */
+
+       /* load IV and byteswap */
+       vmovdqu (%rcx), RTMP4x;
+       vpshufb RTMP3x, RTMP4x, RTMP4x;
+       vmovdqa RTMP4x, RTMP0x;
+       inc_le128(RTMP4x, RNOTx, RTMP1x);
+       vinserti128 $1, RTMP4x, RTMP0, RTMP0;
+       vpshufb RTMP3, RTMP0, RA0; /* +1 ; +0 */
+
+       /* check need for handling 64-bit overflow and carry */
+       cmpq $(0xffffffffffffffff - 16), %rax;
+       ja .Lhandle_ctr_carry;
+
+       /* construct IVs */
+       vpsubq RTMP2, RTMP0, RTMP0; /* +3 ; +2 */
+       vpshufb RTMP3, RTMP0, RA1;
+       vpsubq RTMP2, RTMP0, RTMP0; /* +5 ; +4 */
+       vpshufb RTMP3, RTMP0, RA2;
+       vpsubq RTMP2, RTMP0, RTMP0; /* +7 ; +6 */
+       vpshufb RTMP3, RTMP0, RA3;
+       vpsubq RTMP2, RTMP0, RTMP0; /* +9 ; +8 */
+       vpshufb RTMP3, RTMP0, RB0;
+       vpsubq RTMP2, RTMP0, RTMP0; /* +11 ; +10 */
+       vpshufb RTMP3, RTMP0, RB1;
+       vpsubq RTMP2, RTMP0, RTMP0; /* +13 ; +12 */
+       vpshufb RTMP3, RTMP0, RB2;
+       vpsubq RTMP2, RTMP0, RTMP0; /* +15 ; +14 */
+       vpshufb RTMP3, RTMP0, RB3;
+       vpsubq RTMP2, RTMP0, RTMP0; /* +16 */
+       vpshufb RTMP3x, RTMP0x, RTMP0x;
+
+       jmp .Lctr_carry_done;
+
+.Lhandle_ctr_carry:
+       /* construct IVs */
+       inc_le128(RTMP0, RNOT, RTMP1);
+       inc_le128(RTMP0, RNOT, RTMP1);
+       vpshufb RTMP3, RTMP0, RA1; /* +3 ; +2 */
+       inc_le128(RTMP0, RNOT, RTMP1);
+       inc_le128(RTMP0, RNOT, RTMP1);
+       vpshufb RTMP3, RTMP0, RA2; /* +5 ; +4 */
+       inc_le128(RTMP0, RNOT, RTMP1);
+       inc_le128(RTMP0, RNOT, RTMP1);
+       vpshufb RTMP3, RTMP0, RA3; /* +7 ; +6 */
+       inc_le128(RTMP0, RNOT, RTMP1);
+       inc_le128(RTMP0, RNOT, RTMP1);
+       vpshufb RTMP3, RTMP0, RB0; /* +9 ; +8 */
+       inc_le128(RTMP0, RNOT, RTMP1);
+       inc_le128(RTMP0, RNOT, RTMP1);
+       vpshufb RTMP3, RTMP0, RB1; /* +11 ; +10 */
+       inc_le128(RTMP0, RNOT, RTMP1);
+       inc_le128(RTMP0, RNOT, RTMP1);
+       vpshufb RTMP3, RTMP0, RB2; /* +13 ; +12 */
+       inc_le128(RTMP0, RNOT, RTMP1);
+       inc_le128(RTMP0, RNOT, RTMP1);
+       vpshufb RTMP3, RTMP0, RB3; /* +15 ; +14 */
+       inc_le128(RTMP0, RNOT, RTMP1);
+       vextracti128 $1, RTMP0, RTMP0x;
+       vpshufb RTMP3x, RTMP0x, RTMP0x; /* +16 */
+
+.align 4
+.Lctr_carry_done:
+       /* store new IV */
+       vmovdqu RTMP0x, (%rcx);
+
+       call __sm4_crypt_blk16;
+
+       vpxor (0 * 32)(%rdx), RA0, RA0;
+       vpxor (1 * 32)(%rdx), RA1, RA1;
+       vpxor (2 * 32)(%rdx), RA2, RA2;
+       vpxor (3 * 32)(%rdx), RA3, RA3;
+       vpxor (4 * 32)(%rdx), RB0, RB0;
+       vpxor (5 * 32)(%rdx), RB1, RB1;
+       vpxor (6 * 32)(%rdx), RB2, RB2;
+       vpxor (7 * 32)(%rdx), RB3, RB3;
+
+       vmovdqu RA0, (0 * 32)(%rsi);
+       vmovdqu RA1, (1 * 32)(%rsi);
+       vmovdqu RA2, (2 * 32)(%rsi);
+       vmovdqu RA3, (3 * 32)(%rsi);
+       vmovdqu RB0, (4 * 32)(%rsi);
+       vmovdqu RB1, (5 * 32)(%rsi);
+       vmovdqu RB2, (6 * 32)(%rsi);
+       vmovdqu RB3, (7 * 32)(%rsi);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx2_ctr_enc,.-_gcry_sm4_aesni_avx2_ctr_enc;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx2_cbc_dec
+ELF(.type   _gcry_sm4_aesni_avx2_cbc_dec,@function;)
+_gcry_sm4_aesni_avx2_cbc_dec:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        *      %rcx: iv
+        */
+       CFI_STARTPROC();
+
+       vzeroupper;
+
+       vmovdqu (0 * 32)(%rdx), RA0;
+       vmovdqu (1 * 32)(%rdx), RA1;
+       vmovdqu (2 * 32)(%rdx), RA2;
+       vmovdqu (3 * 32)(%rdx), RA3;
+       vmovdqu (4 * 32)(%rdx), RB0;
+       vmovdqu (5 * 32)(%rdx), RB1;
+       vmovdqu (6 * 32)(%rdx), RB2;
+       vmovdqu (7 * 32)(%rdx), RB3;
+
+       call __sm4_crypt_blk16;
+
+       vmovdqu (%rcx), RNOTx;
+       vinserti128 $1, (%rdx), RNOT, RNOT;
+       vpxor RNOT, RA0, RA0;
+       vpxor (0 * 32 + 16)(%rdx), RA1, RA1;
+       vpxor (1 * 32 + 16)(%rdx), RA2, RA2;
+       vpxor (2 * 32 + 16)(%rdx), RA3, RA3;
+       vpxor (3 * 32 + 16)(%rdx), RB0, RB0;
+       vpxor (4 * 32 + 16)(%rdx), RB1, RB1;
+       vpxor (5 * 32 + 16)(%rdx), RB2, RB2;
+       vpxor (6 * 32 + 16)(%rdx), RB3, RB3;
+       vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
+       vmovdqu RNOTx, (%rcx); /* store new IV */
+
+       vmovdqu RA0, (0 * 32)(%rsi);
+       vmovdqu RA1, (1 * 32)(%rsi);
+       vmovdqu RA2, (2 * 32)(%rsi);
+       vmovdqu RA3, (3 * 32)(%rsi);
+       vmovdqu RB0, (4 * 32)(%rsi);
+       vmovdqu RB1, (5 * 32)(%rsi);
+       vmovdqu RB2, (6 * 32)(%rsi);
+       vmovdqu RB3, (7 * 32)(%rsi);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx2_cbc_dec,.-_gcry_sm4_aesni_avx2_cbc_dec;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx2_cfb_dec
+ELF(.type   _gcry_sm4_aesni_avx2_cfb_dec,@function;)
+_gcry_sm4_aesni_avx2_cfb_dec:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        *      %rcx: iv
+        */
+       CFI_STARTPROC();
+
+       vzeroupper;
+
+       /* Load input */
+       vmovdqu (%rcx), RNOTx;
+       vinserti128 $1, (%rdx), RNOT, RA0;
+       vmovdqu (0 * 32 + 16)(%rdx), RA1;
+       vmovdqu (1 * 32 + 16)(%rdx), RA2;
+       vmovdqu (2 * 32 + 16)(%rdx), RA3;
+       vmovdqu (3 * 32 + 16)(%rdx), RB0;
+       vmovdqu (4 * 32 + 16)(%rdx), RB1;
+       vmovdqu (5 * 32 + 16)(%rdx), RB2;
+       vmovdqu (6 * 32 + 16)(%rdx), RB3;
+
+       /* Update IV */
+       vmovdqu (7 * 32 + 16)(%rdx), RNOTx;
+       vmovdqu RNOTx, (%rcx);
+
+       call __sm4_crypt_blk16;
+
+       vpxor (0 * 32)(%rdx), RA0, RA0;
+       vpxor (1 * 32)(%rdx), RA1, RA1;
+       vpxor (2 * 32)(%rdx), RA2, RA2;
+       vpxor (3 * 32)(%rdx), RA3, RA3;
+       vpxor (4 * 32)(%rdx), RB0, RB0;
+       vpxor (5 * 32)(%rdx), RB1, RB1;
+       vpxor (6 * 32)(%rdx), RB2, RB2;
+       vpxor (7 * 32)(%rdx), RB3, RB3;
+
+       vmovdqu RA0, (0 * 32)(%rsi);
+       vmovdqu RA1, (1 * 32)(%rsi);
+       vmovdqu RA2, (2 * 32)(%rsi);
+       vmovdqu RA3, (3 * 32)(%rsi);
+       vmovdqu RB0, (4 * 32)(%rsi);
+       vmovdqu RB1, (5 * 32)(%rsi);
+       vmovdqu RB2, (6 * 32)(%rsi);
+       vmovdqu RB3, (7 * 32)(%rsi);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx2_cfb_dec,.-_gcry_sm4_aesni_avx2_cfb_dec;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx2_ocb_enc
+ELF(.type _gcry_sm4_aesni_avx2_ocb_enc,@function;)
+
+_gcry_sm4_aesni_avx2_ocb_enc:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        *      %rcx: offset
+        *      %r8 : checksum
+        *      %r9 : L pointers (void *L[16])
+        */
+       CFI_STARTPROC();
+
+       vzeroupper;
+
+       subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
+
+       movq %r10, (0 * 8)(%rsp);
+       movq %r11, (1 * 8)(%rsp);
+       movq %r12, (2 * 8)(%rsp);
+       movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+
+       vmovdqu (%rcx), RTMP0x;
+       vmovdqu (%r8), RTMP1x;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* Checksum_i = Checksum_{i-1} xor P_i  */
+       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+
+#define OCB_INPUT(n, l0reg, l1reg, yreg) \
+         vmovdqu (n * 32)(%rdx), yreg; \
+         vpxor (l0reg), RTMP0x, RNOTx; \
+         vpxor (l1reg), RNOTx, RTMP0x; \
+         vinserti128 $1, RTMP0x, RNOT, RNOT; \
+         vpxor yreg, RTMP1, RTMP1; \
+         vpxor yreg, RNOT, yreg; \
+         vmovdqu RNOT, (n * 32)(%rsi);
+
+       movq (0 * 8)(%r9), %r10;
+       movq (1 * 8)(%r9), %r11;
+       movq (2 * 8)(%r9), %r12;
+       movq (3 * 8)(%r9), %r13;
+       OCB_INPUT(0, %r10, %r11, RA0);
+       OCB_INPUT(1, %r12, %r13, RA1);
+       movq (4 * 8)(%r9), %r10;
+       movq (5 * 8)(%r9), %r11;
+       movq (6 * 8)(%r9), %r12;
+       movq (7 * 8)(%r9), %r13;
+       OCB_INPUT(2, %r10, %r11, RA2);
+       OCB_INPUT(3, %r12, %r13, RA3);
+       movq (8 * 8)(%r9), %r10;
+       movq (9 * 8)(%r9), %r11;
+       movq (10 * 8)(%r9), %r12;
+       movq (11 * 8)(%r9), %r13;
+       OCB_INPUT(4, %r10, %r11, RB0);
+       OCB_INPUT(5, %r12, %r13, RB1);
+       movq (12 * 8)(%r9), %r10;
+       movq (13 * 8)(%r9), %r11;
+       movq (14 * 8)(%r9), %r12;
+       movq (15 * 8)(%r9), %r13;
+       OCB_INPUT(6, %r10, %r11, RB2);
+       OCB_INPUT(7, %r12, %r13, RB3);
+#undef OCB_INPUT
+
+       vextracti128 $1, RTMP1, RNOTx;
+       vmovdqu RTMP0x, (%rcx);
+       vpxor RNOTx, RTMP1x, RTMP1x;
+       vmovdqu RTMP1x, (%r8);
+
+       movq (0 * 8)(%rsp), %r10;
+       movq (1 * 8)(%rsp), %r11;
+       movq (2 * 8)(%rsp), %r12;
+       movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+
+       call __sm4_crypt_blk16;
+
+       addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
+
+       vpxor (0 * 32)(%rsi), RA0, RA0;
+       vpxor (1 * 32)(%rsi), RA1, RA1;
+       vpxor (2 * 32)(%rsi), RA2, RA2;
+       vpxor (3 * 32)(%rsi), RA3, RA3;
+       vpxor (4 * 32)(%rsi), RB0, RB0;
+       vpxor (5 * 32)(%rsi), RB1, RB1;
+       vpxor (6 * 32)(%rsi), RB2, RB2;
+       vpxor (7 * 32)(%rsi), RB3, RB3;
+
+       vmovdqu RA0, (0 * 32)(%rsi);
+       vmovdqu RA1, (1 * 32)(%rsi);
+       vmovdqu RA2, (2 * 32)(%rsi);
+       vmovdqu RA3, (3 * 32)(%rsi);
+       vmovdqu RB0, (4 * 32)(%rsi);
+       vmovdqu RB1, (5 * 32)(%rsi);
+       vmovdqu RB2, (6 * 32)(%rsi);
+       vmovdqu RB3, (7 * 32)(%rsi);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx2_ocb_enc,.-_gcry_sm4_aesni_avx2_ocb_enc;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx2_ocb_dec
+ELF(.type _gcry_sm4_aesni_avx2_ocb_dec,@function;)
+
+_gcry_sm4_aesni_avx2_ocb_dec:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: dst (16 blocks)
+        *      %rdx: src (16 blocks)
+        *      %rcx: offset
+        *      %r8 : checksum
+        *      %r9 : L pointers (void *L[16])
+        */
+       CFI_STARTPROC();
+
+       vzeroupper;
+
+       subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
+
+       movq %r10, (0 * 8)(%rsp);
+       movq %r11, (1 * 8)(%rsp);
+       movq %r12, (2 * 8)(%rsp);
+       movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+
+       vmovdqu (%rcx), RTMP0x;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+
+#define OCB_INPUT(n, l0reg, l1reg, yreg) \
+         vmovdqu (n * 32)(%rdx), yreg; \
+         vpxor (l0reg), RTMP0x, RNOTx; \
+         vpxor (l1reg), RNOTx, RTMP0x; \
+         vinserti128 $1, RTMP0x, RNOT, RNOT; \
+         vpxor yreg, RNOT, yreg; \
+         vmovdqu RNOT, (n * 32)(%rsi);
+
+       movq (0 * 8)(%r9), %r10;
+       movq (1 * 8)(%r9), %r11;
+       movq (2 * 8)(%r9), %r12;
+       movq (3 * 8)(%r9), %r13;
+       OCB_INPUT(0, %r10, %r11, RA0);
+       OCB_INPUT(1, %r12, %r13, RA1);
+       movq (4 * 8)(%r9), %r10;
+       movq (5 * 8)(%r9), %r11;
+       movq (6 * 8)(%r9), %r12;
+       movq (7 * 8)(%r9), %r13;
+       OCB_INPUT(2, %r10, %r11, RA2);
+       OCB_INPUT(3, %r12, %r13, RA3);
+       movq (8 * 8)(%r9), %r10;
+       movq (9 * 8)(%r9), %r11;
+       movq (10 * 8)(%r9), %r12;
+       movq (11 * 8)(%r9), %r13;
+       OCB_INPUT(4, %r10, %r11, RB0);
+       OCB_INPUT(5, %r12, %r13, RB1);
+       movq (12 * 8)(%r9), %r10;
+       movq (13 * 8)(%r9), %r11;
+       movq (14 * 8)(%r9), %r12;
+       movq (15 * 8)(%r9), %r13;
+       OCB_INPUT(6, %r10, %r11, RB2);
+       OCB_INPUT(7, %r12, %r13, RB3);
+#undef OCB_INPUT
+
+       vmovdqu RTMP0x, (%rcx);
+
+       movq (0 * 8)(%rsp), %r10;
+       movq (1 * 8)(%rsp), %r11;
+       movq (2 * 8)(%rsp), %r12;
+       movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+
+       call __sm4_crypt_blk16;
+
+       addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
+
+       vmovdqu (%r8), RTMP1x;
+
+       vpxor (0 * 32)(%rsi), RA0, RA0;
+       vpxor (1 * 32)(%rsi), RA1, RA1;
+       vpxor (2 * 32)(%rsi), RA2, RA2;
+       vpxor (3 * 32)(%rsi), RA3, RA3;
+       vpxor (4 * 32)(%rsi), RB0, RB0;
+       vpxor (5 * 32)(%rsi), RB1, RB1;
+       vpxor (6 * 32)(%rsi), RB2, RB2;
+       vpxor (7 * 32)(%rsi), RB3, RB3;
+
+       /* Checksum_i = Checksum_{i-1} xor P_i  */
+
+       vmovdqu RA0, (0 * 32)(%rsi);
+       vpxor RA0, RTMP1, RTMP1;
+       vmovdqu RA1, (1 * 32)(%rsi);
+       vpxor RA1, RTMP1, RTMP1;
+       vmovdqu RA2, (2 * 32)(%rsi);
+       vpxor RA2, RTMP1, RTMP1;
+       vmovdqu RA3, (3 * 32)(%rsi);
+       vpxor RA3, RTMP1, RTMP1;
+       vmovdqu RB0, (4 * 32)(%rsi);
+       vpxor RB0, RTMP1, RTMP1;
+       vmovdqu RB1, (5 * 32)(%rsi);
+       vpxor RB1, RTMP1, RTMP1;
+       vmovdqu RB2, (6 * 32)(%rsi);
+       vpxor RB2, RTMP1, RTMP1;
+       vmovdqu RB3, (7 * 32)(%rsi);
+       vpxor RB3, RTMP1, RTMP1;
+
+       vextracti128 $1, RTMP1, RNOTx;
+       vpxor RNOTx, RTMP1x, RTMP1x;
+       vmovdqu RTMP1x, (%r8);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx2_ocb_dec,.-_gcry_sm4_aesni_avx2_ocb_dec;)
+
+.align 8
+.globl _gcry_sm4_aesni_avx2_ocb_auth
+ELF(.type _gcry_sm4_aesni_avx2_ocb_auth,@function;)
+
+_gcry_sm4_aesni_avx2_ocb_auth:
+       /* input:
+        *      %rdi: ctx, CTX
+        *      %rsi: abuf (16 blocks)
+        *      %rdx: offset
+        *      %rcx: checksum
+        *      %r8 : L pointers (void *L[16])
+        */
+       CFI_STARTPROC();
+
+       vzeroupper;
+
+       subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
+
+       movq %r10, (0 * 8)(%rsp);
+       movq %r11, (1 * 8)(%rsp);
+       movq %r12, (2 * 8)(%rsp);
+       movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+
+       vmovdqu (%rdx), RTMP0x;
+
+       /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+       /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i)  */
+
+#define OCB_INPUT(n, l0reg, l1reg, yreg) \
+         vmovdqu (n * 32)(%rsi), yreg; \
+         vpxor (l0reg), RTMP0x, RNOTx; \
+         vpxor (l1reg), RNOTx, RTMP0x; \
+         vinserti128 $1, RTMP0x, RNOT, RNOT; \
+         vpxor yreg, RNOT, yreg;
+
+       movq (0 * 8)(%r8), %r10;
+       movq (1 * 8)(%r8), %r11;
+       movq (2 * 8)(%r8), %r12;
+       movq (3 * 8)(%r8), %r13;
+       OCB_INPUT(0, %r10, %r11, RA0);
+       OCB_INPUT(1, %r12, %r13, RA1);
+       movq (4 * 8)(%r8), %r10;
+       movq (5 * 8)(%r8), %r11;
+       movq (6 * 8)(%r8), %r12;
+       movq (7 * 8)(%r8), %r13;
+       OCB_INPUT(2, %r10, %r11, RA2);
+       OCB_INPUT(3, %r12, %r13, RA3);
+       movq (8 * 8)(%r8), %r10;
+       movq (9 * 8)(%r8), %r11;
+       movq (10 * 8)(%r8), %r12;
+       movq (11 * 8)(%r8), %r13;
+       OCB_INPUT(4, %r10, %r11, RB0);
+       OCB_INPUT(5, %r12, %r13, RB1);
+       movq (12 * 8)(%r8), %r10;
+       movq (13 * 8)(%r8), %r11;
+       movq (14 * 8)(%r8), %r12;
+       movq (15 * 8)(%r8), %r13;
+       OCB_INPUT(6, %r10, %r11, RB2);
+       OCB_INPUT(7, %r12, %r13, RB3);
+#undef OCB_INPUT
+
+       vmovdqu RTMP0x, (%rdx);
+
+       movq (0 * 8)(%rsp), %r10;
+       movq (1 * 8)(%rsp), %r11;
+       movq (2 * 8)(%rsp), %r12;
+       movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+
+       call __sm4_crypt_blk16;
+
+       addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
+
+       vpxor RA0, RB0, RA0;
+       vpxor RA1, RB1, RA1;
+       vpxor RA2, RB2, RA2;
+       vpxor RA3, RB3, RA3;
+
+       vpxor RA1, RA0, RA0;
+       vpxor RA3, RA2, RA2;
+
+       vpxor RA2, RA0, RTMP1;
+
+       vextracti128 $1, RTMP1, RNOTx;
+       vpxor (%rcx), RTMP1x, RTMP1x;
+       vpxor RNOTx, RTMP1x, RTMP1x;
+       vmovdqu RTMP1x, (%rcx);
+
+       vzeroall;
+
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_sm4_aesni_avx2_ocb_auth,.-_gcry_sm4_aesni_avx2_ocb_auth;)
+
+#endif /*defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)*/
+#endif /*__x86_64*/
diff --git a/cipher/sm4.c b/cipher/sm4.c
new file mode 100644 (file)
index 0000000..8166298
--- /dev/null
@@ -0,0 +1,1251 @@
+/* sm4.c  -  SM4 Cipher Algorithm
+ * Copyright (C) 2020 Alibaba Group.
+ * Copyright (C) 2020 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "types.h"  /* for byte and u32 typedefs */
+#include "bithelp.h"
+#include "g10lib.h"
+#include "cipher.h"
+#include "bufhelp.h"
+#include "cipher-internal.h"
+#include "cipher-selftest.h"
+
+/* Helper macro to force alignment to 64 bytes.  */
+#ifdef HAVE_GCC_ATTRIBUTE_ALIGNED
+# define ATTR_ALIGNED_64  __attribute__ ((aligned (64)))
+#else
+# define ATTR_ALIGNED_64
+#endif
+
+/* USE_AESNI_AVX inidicates whether to compile with Intel AES-NI/AVX code. */
+#undef USE_AESNI_AVX
+#if defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)
+# if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+#  define USE_AESNI_AVX 1
+# endif
+#endif
+
+/* USE_AESNI_AVX inidicates whether to compile with Intel AES-NI/AVX2 code. */
+#undef USE_AESNI_AVX2
+#if defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX2_SUPPORT)
+# if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+#  define USE_AESNI_AVX2 1
+# endif
+#endif
+
+/* Assembly implementations use SystemV ABI, ABI conversion and additional
+ * stack to store XMM6-XMM15 needed on Win64. */
+#undef ASM_FUNC_ABI
+#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2)
+# ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
+#  define ASM_FUNC_ABI __attribute__((sysv_abi))
+# else
+#  define ASM_FUNC_ABI
+# endif
+#endif
+
+static const char *sm4_selftest (void);
+
+static void _gcry_sm4_ctr_enc (void *context, unsigned char *ctr,
+                              void *outbuf_arg, const void *inbuf_arg,
+                              size_t nblocks);
+static void _gcry_sm4_cbc_dec (void *context, unsigned char *iv,
+                              void *outbuf_arg, const void *inbuf_arg,
+                              size_t nblocks);
+static void _gcry_sm4_cfb_dec (void *context, unsigned char *iv,
+                              void *outbuf_arg, const void *inbuf_arg,
+                              size_t nblocks);
+static size_t _gcry_sm4_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                  const void *inbuf_arg, size_t nblocks,
+                                  int encrypt);
+static size_t _gcry_sm4_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
+                                 size_t nblocks);
+
+typedef struct
+{
+  u32 rkey_enc[32];
+  u32 rkey_dec[32];
+#ifdef USE_AESNI_AVX
+  unsigned int use_aesni_avx:1;
+#endif
+#ifdef USE_AESNI_AVX2
+  unsigned int use_aesni_avx2:1;
+#endif
+} SM4_context;
+
+static const u32 fk[4] =
+{
+  0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc
+};
+
+static struct
+{
+  volatile u32 counter_head;
+  u32 cacheline_align[64 / 4 - 1];
+  byte S[256];
+  volatile u32 counter_tail;
+} sbox_table ATTR_ALIGNED_64 =
+  {
+    0,
+    { 0, },
+    {
+      0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
+      0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
+      0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3,
+      0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
+      0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a,
+      0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
+      0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95,
+      0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
+      0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba,
+      0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
+      0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b,
+      0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
+      0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2,
+      0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
+      0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52,
+      0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
+      0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5,
+      0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
+      0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,
+      0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
+      0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60,
+      0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
+      0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f,
+      0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
+      0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f,
+      0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
+      0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd,
+      0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
+      0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e,
+      0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
+      0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20,
+      0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
+    },
+    0
+  };
+
+static const u32 ck[] =
+{
+  0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
+  0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
+  0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
+  0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
+  0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
+  0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
+  0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
+  0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
+};
+
+#ifdef USE_AESNI_AVX
+extern void _gcry_sm4_aesni_avx_expand_key(const byte *key, u32 *rk_enc,
+                                          u32 *rk_dec, const u32 *fk,
+                                          const u32 *ck) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx_ctr_enc(const u32 *rk_enc, byte *out,
+                                       const byte *in, byte *ctr) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx_cbc_dec(const u32 *rk_dec, byte *out,
+                                       const byte *in, byte *iv) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx_cfb_dec(const u32 *rk_enc, byte *out,
+                                       const byte *in, byte *iv) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx_ocb_enc(const u32 *rk_enc,
+                                       unsigned char *out,
+                                       const unsigned char *in,
+                                       unsigned char *offset,
+                                       unsigned char *checksum,
+                                       const u64 Ls[8]) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx_ocb_dec(const u32 *rk_dec,
+                                       unsigned char *out,
+                                       const unsigned char *in,
+                                       unsigned char *offset,
+                                       unsigned char *checksum,
+                                       const u64 Ls[8]) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx_ocb_auth(const u32 *rk_enc,
+                                        const unsigned char *abuf,
+                                        unsigned char *offset,
+                                        unsigned char *checksum,
+                                        const u64 Ls[8]) ASM_FUNC_ABI;
+
+extern unsigned int
+_gcry_sm4_aesni_avx_crypt_blk1_8(const u32 *rk, byte *out, const byte *in,
+                                unsigned int num_blks) ASM_FUNC_ABI;
+
+static inline unsigned int
+sm4_aesni_avx_crypt_blk1_8(const u32 *rk, byte *out, const byte *in,
+                          unsigned int num_blks)
+{
+  return _gcry_sm4_aesni_avx_crypt_blk1_8(rk, out, in, num_blks);
+}
+
+#endif /* USE_AESNI_AVX */
+
+#ifdef USE_AESNI_AVX2
+extern void _gcry_sm4_aesni_avx2_ctr_enc(const u32 *rk_enc, byte *out,
+                                        const byte *in,
+                                        byte *ctr) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx2_cbc_dec(const u32 *rk_dec, byte *out,
+                                        const byte *in,
+                                        byte *iv) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx2_cfb_dec(const u32 *rk_enc, byte *out,
+                                        const byte *in,
+                                        byte *iv) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx2_ocb_enc(const u32 *rk_enc,
+                                        unsigned char *out,
+                                        const unsigned char *in,
+                                        unsigned char *offset,
+                                        unsigned char *checksum,
+                                        const u64 Ls[16]) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx2_ocb_dec(const u32 *rk_dec,
+                                        unsigned char *out,
+                                        const unsigned char *in,
+                                        unsigned char *offset,
+                                        unsigned char *checksum,
+                                        const u64 Ls[16]) ASM_FUNC_ABI;
+
+extern void _gcry_sm4_aesni_avx2_ocb_auth(const u32 *rk_enc,
+                                         const unsigned char *abuf,
+                                         unsigned char *offset,
+                                         unsigned char *checksum,
+                                         const u64 Ls[16]) ASM_FUNC_ABI;
+#endif /* USE_AESNI_AVX2 */
+
+static inline void prefetch_sbox_table(void)
+{
+  const volatile byte *vtab = (void *)&sbox_table;
+
+  /* Modify counters to trigger copy-on-write and unsharing if physical pages
+   * of look-up table are shared between processes.  Modifying counters also
+   * causes checksums for pages to change and hint same-page merging algorithm
+   * that these pages are frequently changing.  */
+  sbox_table.counter_head++;
+  sbox_table.counter_tail++;
+
+  /* Prefetch look-up table to cache.  */
+  (void)vtab[0 * 32];
+  (void)vtab[1 * 32];
+  (void)vtab[2 * 32];
+  (void)vtab[3 * 32];
+  (void)vtab[4 * 32];
+  (void)vtab[5 * 32];
+  (void)vtab[6 * 32];
+  (void)vtab[7 * 32];
+  (void)vtab[8 * 32 - 1];
+}
+
+static inline u32 sm4_t_non_lin_sub(u32 x)
+{
+  u32 out;
+
+  out  = (u32)sbox_table.S[(x >> 0) & 0xff] << 0;
+  out |= (u32)sbox_table.S[(x >> 8) & 0xff] << 8;
+  out |= (u32)sbox_table.S[(x >> 16) & 0xff] << 16;
+  out |= (u32)sbox_table.S[(x >> 24) & 0xff] << 24;
+
+  return out;
+}
+
+static inline u32 sm4_key_lin_sub(u32 x)
+{
+  return x ^ rol(x, 13) ^ rol(x, 23);
+}
+
+static inline u32 sm4_enc_lin_sub(u32 x)
+{
+  u32 xrol2 = rol(x, 2);
+  return x ^ xrol2 ^ rol(xrol2, 8) ^ rol(xrol2, 16) ^ rol(x, 24);
+}
+
+static inline u32 sm4_key_sub(u32 x)
+{
+  return sm4_key_lin_sub(sm4_t_non_lin_sub(x));
+}
+
+static inline u32 sm4_enc_sub(u32 x)
+{
+  return sm4_enc_lin_sub(sm4_t_non_lin_sub(x));
+}
+
+static inline u32
+sm4_round(const u32 x0, const u32 x1, const u32 x2, const u32 x3, const u32 rk)
+{
+  return x0 ^ sm4_enc_sub(x1 ^ x2 ^ x3 ^ rk);
+}
+
+static void
+sm4_expand_key (SM4_context *ctx, const byte *key)
+{
+  u32 rk[4];
+  int i;
+
+#ifdef USE_AESNI_AVX
+  if (ctx->use_aesni_avx)
+    {
+      _gcry_sm4_aesni_avx_expand_key (key, ctx->rkey_enc, ctx->rkey_dec,
+                                     fk, ck);
+      return;
+    }
+#endif
+
+  rk[0] = buf_get_be32(key + 4 * 0) ^ fk[0];
+  rk[1] = buf_get_be32(key + 4 * 1) ^ fk[1];
+  rk[2] = buf_get_be32(key + 4 * 2) ^ fk[2];
+  rk[3] = buf_get_be32(key + 4 * 3) ^ fk[3];
+
+  for (i = 0; i < 32; i += 4)
+    {
+      rk[0] = rk[0] ^ sm4_key_sub(rk[1] ^ rk[2] ^ rk[3] ^ ck[i + 0]);
+      rk[1] = rk[1] ^ sm4_key_sub(rk[2] ^ rk[3] ^ rk[0] ^ ck[i + 1]);
+      rk[2] = rk[2] ^ sm4_key_sub(rk[3] ^ rk[0] ^ rk[1] ^ ck[i + 2]);
+      rk[3] = rk[3] ^ sm4_key_sub(rk[0] ^ rk[1] ^ rk[2] ^ ck[i + 3]);
+      ctx->rkey_enc[i + 0] = rk[0];
+      ctx->rkey_enc[i + 1] = rk[1];
+      ctx->rkey_enc[i + 2] = rk[2];
+      ctx->rkey_enc[i + 3] = rk[3];
+      ctx->rkey_dec[31 - i - 0] = rk[0];
+      ctx->rkey_dec[31 - i - 1] = rk[1];
+      ctx->rkey_dec[31 - i - 2] = rk[2];
+      ctx->rkey_dec[31 - i - 3] = rk[3];
+    }
+
+  wipememory (rk, sizeof(rk));
+}
+
+static gcry_err_code_t
+sm4_setkey (void *context, const byte *key, const unsigned keylen,
+            cipher_bulk_ops_t *bulk_ops)
+{
+  SM4_context *ctx = context;
+  static int init = 0;
+  static const char *selftest_failed = NULL;
+  unsigned int hwf = _gcry_get_hw_features ();
+
+  (void)hwf;
+
+  if (!init)
+    {
+      init = 1;
+      selftest_failed = sm4_selftest();
+      if (selftest_failed)
+       log_error("%s\n", selftest_failed);
+    }
+  if (selftest_failed)
+    return GPG_ERR_SELFTEST_FAILED;
+
+  if (keylen != 16)
+    return GPG_ERR_INV_KEYLEN;
+
+#ifdef USE_AESNI_AVX
+  ctx->use_aesni_avx = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX);
+#endif
+#ifdef USE_AESNI_AVX2
+  ctx->use_aesni_avx2 = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX2);
+#endif
+
+  /* Setup bulk encryption routines.  */
+  memset (bulk_ops, 0, sizeof(*bulk_ops));
+  bulk_ops->cbc_dec = _gcry_sm4_cbc_dec;
+  bulk_ops->cfb_dec = _gcry_sm4_cfb_dec;
+  bulk_ops->ctr_enc = _gcry_sm4_ctr_enc;
+  bulk_ops->ocb_crypt = _gcry_sm4_ocb_crypt;
+  bulk_ops->ocb_auth  = _gcry_sm4_ocb_auth;
+
+  sm4_expand_key (ctx, key);
+  return 0;
+}
+
+static unsigned int
+sm4_do_crypt (const u32 *rk, byte *out, const byte *in)
+{
+  u32 x[4];
+  int i;
+
+  x[0] = buf_get_be32(in + 0 * 4);
+  x[1] = buf_get_be32(in + 1 * 4);
+  x[2] = buf_get_be32(in + 2 * 4);
+  x[3] = buf_get_be32(in + 3 * 4);
+
+  for (i = 0; i < 32; i += 4)
+    {
+      x[0] = sm4_round(x[0], x[1], x[2], x[3], rk[i + 0]);
+      x[1] = sm4_round(x[1], x[2], x[3], x[0], rk[i + 1]);
+      x[2] = sm4_round(x[2], x[3], x[0], x[1], rk[i + 2]);
+      x[3] = sm4_round(x[3], x[0], x[1], x[2], rk[i + 3]);
+    }
+
+  buf_put_be32(out + 0 * 4, x[3 - 0]);
+  buf_put_be32(out + 1 * 4, x[3 - 1]);
+  buf_put_be32(out + 2 * 4, x[3 - 2]);
+  buf_put_be32(out + 3 * 4, x[3 - 3]);
+
+  return /*burn_stack*/ 4*6+sizeof(void*)*4;
+}
+
+static unsigned int
+sm4_encrypt (void *context, byte *outbuf, const byte *inbuf)
+{
+  SM4_context *ctx = context;
+
+  prefetch_sbox_table ();
+
+  return sm4_do_crypt (ctx->rkey_enc, outbuf, inbuf);
+}
+
+static unsigned int
+sm4_decrypt (void *context, byte *outbuf, const byte *inbuf)
+{
+  SM4_context *ctx = context;
+
+  prefetch_sbox_table ();
+
+  return sm4_do_crypt (ctx->rkey_dec, outbuf, inbuf);
+}
+
+static unsigned int
+sm4_do_crypt_blks2 (const u32 *rk, byte *out, const byte *in)
+{
+  u32 x[4];
+  u32 y[4];
+  u32 k;
+  int i;
+
+  /* Encrypts/Decrypts two blocks for higher instruction level
+   * parallelism. */
+
+  x[0] = buf_get_be32(in + 0 * 4);
+  x[1] = buf_get_be32(in + 1 * 4);
+  x[2] = buf_get_be32(in + 2 * 4);
+  x[3] = buf_get_be32(in + 3 * 4);
+  y[0] = buf_get_be32(in + 4 * 4);
+  y[1] = buf_get_be32(in + 5 * 4);
+  y[2] = buf_get_be32(in + 6 * 4);
+  y[3] = buf_get_be32(in + 7 * 4);
+
+  for (i = 0; i < 32; i += 4)
+    {
+      k = rk[i + 0];
+      x[0] = sm4_round(x[0], x[1], x[2], x[3], k);
+      y[0] = sm4_round(y[0], y[1], y[2], y[3], k);
+      k = rk[i + 1];
+      x[1] = sm4_round(x[1], x[2], x[3], x[0], k);
+      y[1] = sm4_round(y[1], y[2], y[3], y[0], k);
+      k = rk[i + 2];
+      x[2] = sm4_round(x[2], x[3], x[0], x[1], k);
+      y[2] = sm4_round(y[2], y[3], y[0], y[1], k);
+      k = rk[i + 3];
+      x[3] = sm4_round(x[3], x[0], x[1], x[2], k);
+      y[3] = sm4_round(y[3], y[0], y[1], y[2], k);
+    }
+
+  buf_put_be32(out + 0 * 4, x[3 - 0]);
+  buf_put_be32(out + 1 * 4, x[3 - 1]);
+  buf_put_be32(out + 2 * 4, x[3 - 2]);
+  buf_put_be32(out + 3 * 4, x[3 - 3]);
+  buf_put_be32(out + 4 * 4, y[3 - 0]);
+  buf_put_be32(out + 5 * 4, y[3 - 1]);
+  buf_put_be32(out + 6 * 4, y[3 - 2]);
+  buf_put_be32(out + 7 * 4, y[3 - 3]);
+
+  return /*burn_stack*/ 4*10+sizeof(void*)*4;
+}
+
+static unsigned int
+sm4_crypt_blocks (const u32 *rk, byte *out, const byte *in,
+                 unsigned int num_blks)
+{
+  unsigned int burn_depth = 0;
+  unsigned int nburn;
+
+  while (num_blks >= 2)
+    {
+      nburn = sm4_do_crypt_blks2 (rk, out, in);
+      burn_depth = nburn > burn_depth ? nburn : burn_depth;
+      out += 2 * 16;
+      in += 2 * 16;
+      num_blks -= 2;
+    }
+
+  while (num_blks)
+    {
+      nburn = sm4_do_crypt (rk, out, in);
+      burn_depth = nburn > burn_depth ? nburn : burn_depth;
+      out += 16;
+      in += 16;
+      num_blks--;
+    }
+
+  if (burn_depth)
+    burn_depth += sizeof(void *) * 5;
+  return burn_depth;
+}
+
+/* Bulk encryption of complete blocks in CTR mode.  This function is only
+   intended for the bulk encryption feature of cipher.c.  CTR is expected to be
+   of size 16. */
+static void
+_gcry_sm4_ctr_enc(void *context, unsigned char *ctr,
+                  void *outbuf_arg, const void *inbuf_arg,
+                  size_t nblocks)
+{
+  SM4_context *ctx = context;
+  byte *outbuf = outbuf_arg;
+  const byte *inbuf = inbuf_arg;
+  int burn_stack_depth = 0;
+
+#ifdef USE_AESNI_AVX2
+  if (ctx->use_aesni_avx2)
+    {
+      /* Process data in 16 block chunks. */
+      while (nblocks >= 16)
+        {
+          _gcry_sm4_aesni_avx2_ctr_enc(ctx->rkey_enc, outbuf, inbuf, ctr);
+
+          nblocks -= 16;
+          outbuf += 16 * 16;
+          inbuf += 16 * 16;
+        }
+    }
+#endif
+
+#ifdef USE_AESNI_AVX
+  if (ctx->use_aesni_avx)
+    {
+      /* Process data in 8 block chunks. */
+      while (nblocks >= 8)
+        {
+          _gcry_sm4_aesni_avx_ctr_enc(ctx->rkey_enc, outbuf, inbuf, ctr);
+
+          nblocks -= 8;
+          outbuf += 8 * 16;
+          inbuf += 8 * 16;
+        }
+    }
+#endif
+
+  /* Process remaining blocks. */
+  if (nblocks)
+    {
+      unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in,
+                                  unsigned int num_blks);
+      byte tmpbuf[16 * 8];
+      unsigned int tmp_used = 16;
+
+      if (0)
+       ;
+#ifdef USE_AESNI_AVX
+      else if (ctx->use_aesni_avx)
+       {
+         crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8;
+       }
+#endif
+      else
+       {
+         prefetch_sbox_table ();
+         crypt_blk1_8 = sm4_crypt_blocks;
+       }
+
+      /* Process remaining blocks. */
+      while (nblocks)
+       {
+         size_t curr_blks = nblocks > 8 ? 8 : nblocks;
+         size_t i;
+
+         if (curr_blks * 16 > tmp_used)
+           tmp_used = curr_blks * 16;
+
+         cipher_block_cpy (tmpbuf + 0 * 16, ctr, 16);
+         for (i = 1; i < curr_blks; i++)
+           {
+             cipher_block_cpy (&tmpbuf[i * 16], ctr, 16);
+             cipher_block_add (&tmpbuf[i * 16], i, 16);
+           }
+         cipher_block_add (ctr, curr_blks, 16);
+
+         burn_stack_depth = crypt_blk1_8 (ctx->rkey_enc, tmpbuf, tmpbuf,
+                                          curr_blks);
+
+         for (i = 0; i < curr_blks; i++)
+           {
+             cipher_block_xor (outbuf, &tmpbuf[i * 16], inbuf, 16);
+             outbuf += 16;
+             inbuf += 16;
+           }
+
+         nblocks -= curr_blks;
+       }
+
+      wipememory(tmpbuf, tmp_used);
+    }
+
+  if (burn_stack_depth)
+    _gcry_burn_stack(burn_stack_depth);
+}
+
+/* Bulk decryption of complete blocks in CBC mode.  This function is only
+   intended for the bulk encryption feature of cipher.c. */
+static void
+_gcry_sm4_cbc_dec(void *context, unsigned char *iv,
+                  void *outbuf_arg, const void *inbuf_arg,
+                  size_t nblocks)
+{
+  SM4_context *ctx = context;
+  unsigned char *outbuf = outbuf_arg;
+  const unsigned char *inbuf = inbuf_arg;
+  int burn_stack_depth = 0;
+
+#ifdef USE_AESNI_AVX2
+  if (ctx->use_aesni_avx2)
+    {
+      /* Process data in 16 block chunks. */
+      while (nblocks >= 16)
+        {
+          _gcry_sm4_aesni_avx2_cbc_dec(ctx->rkey_dec, outbuf, inbuf, iv);
+
+          nblocks -= 16;
+          outbuf += 16 * 16;
+          inbuf += 16 * 16;
+        }
+    }
+#endif
+
+#ifdef USE_AESNI_AVX
+  if (ctx->use_aesni_avx)
+    {
+      /* Process data in 8 block chunks. */
+      while (nblocks >= 8)
+        {
+          _gcry_sm4_aesni_avx_cbc_dec(ctx->rkey_dec, outbuf, inbuf, iv);
+
+          nblocks -= 8;
+          outbuf += 8 * 16;
+          inbuf += 8 * 16;
+        }
+    }
+#endif
+
+  /* Process remaining blocks. */
+  if (nblocks)
+    {
+      unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in,
+                                  unsigned int num_blks);
+      unsigned char savebuf[16 * 8];
+      unsigned int tmp_used = 16;
+
+      if (0)
+       ;
+#ifdef USE_AESNI_AVX
+      else if (ctx->use_aesni_avx)
+       {
+         crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8;
+       }
+#endif
+      else
+       {
+         prefetch_sbox_table ();
+         crypt_blk1_8 = sm4_crypt_blocks;
+       }
+
+      /* Process remaining blocks. */
+      while (nblocks)
+       {
+         size_t curr_blks = nblocks > 8 ? 8 : nblocks;
+         size_t i;
+
+         if (curr_blks * 16 > tmp_used)
+           tmp_used = curr_blks * 16;
+
+         burn_stack_depth = crypt_blk1_8 (ctx->rkey_dec, savebuf, inbuf,
+                                          curr_blks);
+
+         for (i = 0; i < curr_blks; i++)
+           {
+             cipher_block_xor_n_copy_2(outbuf, &savebuf[i * 16], iv, inbuf,
+                                       16);
+             outbuf += 16;
+             inbuf += 16;
+           }
+
+         nblocks -= curr_blks;
+       }
+
+      wipememory(savebuf, tmp_used);
+    }
+
+  if (burn_stack_depth)
+    _gcry_burn_stack(burn_stack_depth);
+}
+
+/* Bulk decryption of complete blocks in CFB mode.  This function is only
+   intended for the bulk encryption feature of cipher.c. */
+static void
+_gcry_sm4_cfb_dec(void *context, unsigned char *iv,
+                  void *outbuf_arg, const void *inbuf_arg,
+                  size_t nblocks)
+{
+  SM4_context *ctx = context;
+  unsigned char *outbuf = outbuf_arg;
+  const unsigned char *inbuf = inbuf_arg;
+  int burn_stack_depth = 0;
+
+#ifdef USE_AESNI_AVX2
+  if (ctx->use_aesni_avx2)
+    {
+      /* Process data in 16 block chunks. */
+      while (nblocks >= 16)
+        {
+          _gcry_sm4_aesni_avx2_cfb_dec(ctx->rkey_enc, outbuf, inbuf, iv);
+
+          nblocks -= 16;
+          outbuf += 16 * 16;
+          inbuf += 16 * 16;
+        }
+    }
+#endif
+
+#ifdef USE_AESNI_AVX
+  if (ctx->use_aesni_avx)
+    {
+      /* Process data in 8 block chunks. */
+      while (nblocks >= 8)
+        {
+          _gcry_sm4_aesni_avx_cfb_dec(ctx->rkey_enc, outbuf, inbuf, iv);
+
+          nblocks -= 8;
+          outbuf += 8 * 16;
+          inbuf += 8 * 16;
+        }
+    }
+#endif
+
+  /* Process remaining blocks. */
+  if (nblocks)
+    {
+      unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in,
+                                  unsigned int num_blks);
+      unsigned char ivbuf[16 * 8];
+      unsigned int tmp_used = 16;
+
+      if (0)
+       ;
+#ifdef USE_AESNI_AVX
+      else if (ctx->use_aesni_avx)
+       {
+         crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8;
+       }
+#endif
+      else
+       {
+         prefetch_sbox_table ();
+         crypt_blk1_8 = sm4_crypt_blocks;
+       }
+
+      /* Process remaining blocks. */
+      while (nblocks)
+       {
+         size_t curr_blks = nblocks > 8 ? 8 : nblocks;
+         size_t i;
+
+         if (curr_blks * 16 > tmp_used)
+           tmp_used = curr_blks * 16;
+
+         cipher_block_cpy (&ivbuf[0 * 16], iv, 16);
+         for (i = 1; i < curr_blks; i++)
+           cipher_block_cpy (&ivbuf[i * 16], &inbuf[(i - 1) * 16], 16);
+         cipher_block_cpy (iv, &inbuf[(i - 1) * 16], 16);
+
+         burn_stack_depth = crypt_blk1_8 (ctx->rkey_enc, ivbuf, ivbuf,
+                                          curr_blks);
+
+         for (i = 0; i < curr_blks; i++)
+           {
+             cipher_block_xor (outbuf, inbuf, &ivbuf[i * 16], 16);
+             outbuf += 16;
+             inbuf += 16;
+           }
+
+         nblocks -= curr_blks;
+       }
+
+      wipememory(ivbuf, tmp_used);
+    }
+
+  if (burn_stack_depth)
+    _gcry_burn_stack(burn_stack_depth);
+}
+
+/* Bulk encryption/decryption of complete blocks in OCB mode. */
+static size_t
+_gcry_sm4_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                    const void *inbuf_arg, size_t nblocks, int encrypt)
+{
+  SM4_context *ctx = (void *)&c->context.c;
+  unsigned char *outbuf = outbuf_arg;
+  const unsigned char *inbuf = inbuf_arg;
+  u64 blkn = c->u_mode.ocb.data_nblocks;
+  int burn_stack_depth = 0;
+
+#ifdef USE_AESNI_AVX2
+  if (ctx->use_aesni_avx2)
+    {
+      u64 Ls[16];
+      unsigned int n = 16 - (blkn % 16);
+      u64 *l;
+      int i;
+
+      if (nblocks >= 16)
+       {
+         for (i = 0; i < 16; i += 8)
+           {
+             /* Use u64 to store pointers for x32 support (assembly function
+              * assumes 64-bit pointers). */
+             Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+             Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
+             Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+             Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
+             Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+             Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
+             Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+           }
+
+         Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
+         l = &Ls[(15 + n) % 16];
+
+         /* Process data in 16 block chunks. */
+         while (nblocks >= 16)
+           {
+             blkn += 16;
+             *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16);
+
+             if (encrypt)
+               _gcry_sm4_aesni_avx2_ocb_enc(ctx->rkey_enc, outbuf, inbuf,
+                                            c->u_iv.iv, c->u_ctr.ctr, Ls);
+             else
+               _gcry_sm4_aesni_avx2_ocb_dec(ctx->rkey_dec, outbuf, inbuf,
+                                            c->u_iv.iv, c->u_ctr.ctr, Ls);
+
+             nblocks -= 16;
+             outbuf += 16 * 16;
+             inbuf += 16 * 16;
+           }
+       }
+    }
+#endif
+
+#ifdef USE_AESNI_AVX
+  if (ctx->use_aesni_avx)
+    {
+      u64 Ls[8];
+      unsigned int n = 8 - (blkn % 8);
+      u64 *l;
+
+      if (nblocks >= 8)
+       {
+         /* Use u64 to store pointers for x32 support (assembly function
+          * assumes 64-bit pointers). */
+         Ls[(0 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+         Ls[(1 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
+         Ls[(2 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+         Ls[(3 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
+         Ls[(4 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+         Ls[(5 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
+         Ls[(6 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+         Ls[(7 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
+         l = &Ls[(7 + n) % 8];
+
+         /* Process data in 8 block chunks. */
+         while (nblocks >= 8)
+           {
+             blkn += 8;
+             *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 8);
+
+             if (encrypt)
+               _gcry_sm4_aesni_avx_ocb_enc(ctx->rkey_enc, outbuf, inbuf,
+                                           c->u_iv.iv, c->u_ctr.ctr, Ls);
+             else
+               _gcry_sm4_aesni_avx_ocb_dec(ctx->rkey_dec, outbuf, inbuf,
+                                           c->u_iv.iv, c->u_ctr.ctr, Ls);
+
+             nblocks -= 8;
+             outbuf += 8 * 16;
+             inbuf += 8 * 16;
+           }
+       }
+    }
+#endif
+
+  if (nblocks)
+    {
+      unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in,
+                                  unsigned int num_blks);
+      const u32 *rk = encrypt ? ctx->rkey_enc : ctx->rkey_dec;
+      unsigned char tmpbuf[16 * 8];
+      unsigned int tmp_used = 16;
+
+      if (0)
+       ;
+#ifdef USE_AESNI_AVX
+      else if (ctx->use_aesni_avx)
+       {
+         crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8;
+       }
+#endif
+      else
+       {
+         prefetch_sbox_table ();
+         crypt_blk1_8 = sm4_crypt_blocks;
+       }
+
+      while (nblocks)
+       {
+         size_t curr_blks = nblocks > 8 ? 8 : nblocks;
+         size_t i;
+
+         if (curr_blks * 16 > tmp_used)
+           tmp_used = curr_blks * 16;
+
+         for (i = 0; i < curr_blks; i++)
+           {
+             const unsigned char *l = ocb_get_l(c, ++blkn);
+
+             /* Checksum_i = Checksum_{i-1} xor P_i  */
+             if (encrypt)
+               cipher_block_xor_1(c->u_ctr.ctr, &inbuf[i * 16], 16);
+
+             /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+             cipher_block_xor_2dst (&tmpbuf[i * 16], c->u_iv.iv, l, 16);
+             cipher_block_xor (&outbuf[i * 16], &inbuf[i * 16],
+                               c->u_iv.iv, 16);
+           }
+
+         /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+         crypt_blk1_8 (rk, outbuf, outbuf, curr_blks);
+
+         for (i = 0; i < curr_blks; i++)
+           {
+             cipher_block_xor_1 (&outbuf[i * 16], &tmpbuf[i * 16], 16);
+
+             /* Checksum_i = Checksum_{i-1} xor P_i  */
+             if (!encrypt)
+                 cipher_block_xor_1(c->u_ctr.ctr, &outbuf[i * 16], 16);
+           }
+
+         outbuf += curr_blks * 16;
+         inbuf  += curr_blks * 16;
+         nblocks -= curr_blks;
+       }
+
+      wipememory(tmpbuf, tmp_used);
+    }
+
+  c->u_mode.ocb.data_nblocks = blkn;
+
+  if (burn_stack_depth)
+    _gcry_burn_stack(burn_stack_depth);
+
+  return 0;
+}
+
+/* Bulk authentication of complete blocks in OCB mode. */
+static size_t
+_gcry_sm4_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks)
+{
+  SM4_context *ctx = (void *)&c->context.c;
+  const unsigned char *abuf = abuf_arg;
+  u64 blkn = c->u_mode.ocb.aad_nblocks;
+
+#ifdef USE_AESNI_AVX2
+  if (ctx->use_aesni_avx2)
+    {
+      u64 Ls[16];
+      unsigned int n = 16 - (blkn % 16);
+      u64 *l;
+      int i;
+
+      if (nblocks >= 16)
+       {
+         for (i = 0; i < 16; i += 8)
+           {
+             /* Use u64 to store pointers for x32 support (assembly function
+              * assumes 64-bit pointers). */
+             Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+             Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
+             Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+             Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
+             Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+             Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
+             Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+           }
+
+         Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
+         l = &Ls[(15 + n) % 16];
+
+         /* Process data in 16 block chunks. */
+         while (nblocks >= 16)
+           {
+             blkn += 16;
+             *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16);
+
+             _gcry_sm4_aesni_avx2_ocb_auth(ctx->rkey_enc, abuf,
+                                           c->u_mode.ocb.aad_offset,
+                                           c->u_mode.ocb.aad_sum, Ls);
+
+             nblocks -= 16;
+             abuf += 16 * 16;
+           }
+       }
+    }
+#endif
+
+#ifdef USE_AESNI_AVX
+  if (ctx->use_aesni_avx)
+    {
+      u64 Ls[8];
+      unsigned int n = 8 - (blkn % 8);
+      u64 *l;
+
+      if (nblocks >= 8)
+       {
+         /* Use u64 to store pointers for x32 support (assembly function
+           * assumes 64-bit pointers). */
+         Ls[(0 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+         Ls[(1 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
+         Ls[(2 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+         Ls[(3 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
+         Ls[(4 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+         Ls[(5 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
+         Ls[(6 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
+         Ls[(7 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
+         l = &Ls[(7 + n) % 8];
+
+         /* Process data in 8 block chunks. */
+         while (nblocks >= 8)
+           {
+             blkn += 8;
+             *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 8);
+
+             _gcry_sm4_aesni_avx_ocb_auth(ctx->rkey_enc, abuf,
+                                          c->u_mode.ocb.aad_offset,
+                                          c->u_mode.ocb.aad_sum, Ls);
+
+             nblocks -= 8;
+             abuf += 8 * 16;
+           }
+       }
+    }
+#endif
+
+  if (nblocks)
+    {
+      unsigned int (*crypt_blk1_8)(const u32 *rk, byte *out, const byte *in,
+                                  unsigned int num_blks);
+      unsigned char tmpbuf[16 * 8];
+      unsigned int tmp_used = 16;
+
+      if (0)
+       ;
+#ifdef USE_AESNI_AVX
+      else if (ctx->use_aesni_avx)
+       {
+         crypt_blk1_8 = sm4_aesni_avx_crypt_blk1_8;
+       }
+#endif
+      else
+       {
+         prefetch_sbox_table ();
+         crypt_blk1_8 = sm4_crypt_blocks;
+       }
+
+      while (nblocks)
+       {
+         size_t curr_blks = nblocks > 8 ? 8 : nblocks;
+         size_t i;
+
+         if (curr_blks * 16 > tmp_used)
+           tmp_used = curr_blks * 16;
+
+         for (i = 0; i < curr_blks; i++)
+           {
+             const unsigned char *l = ocb_get_l(c, ++blkn);
+
+             /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+             cipher_block_xor_2dst (&tmpbuf[i * 16],
+                                    c->u_mode.ocb.aad_offset, l, 16);
+             cipher_block_xor_1 (&tmpbuf[i * 16], &abuf[i * 16], 16);
+           }
+
+         /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i)  */
+         crypt_blk1_8 (ctx->rkey_enc, tmpbuf, tmpbuf, curr_blks);
+
+         for (i = 0; i < curr_blks; i++)
+           {
+             cipher_block_xor_1 (c->u_mode.ocb.aad_sum, &tmpbuf[i * 16], 16);
+           }
+
+         abuf += curr_blks * 16;
+         nblocks -= curr_blks;
+       }
+
+      wipememory(tmpbuf, tmp_used);
+    }
+
+  c->u_mode.ocb.aad_nblocks = blkn;
+
+  return 0;
+}
+
+/* Run the self-tests for SM4-CTR, tests IV increment of bulk CTR
+   encryption.  Returns NULL on success. */
+static const char*
+selftest_ctr_128 (void)
+{
+  const int nblocks = 16 - 1;
+  const int blocksize = 16;
+  const int context_size = sizeof(SM4_context);
+
+  return _gcry_selftest_helper_ctr("SM4", &sm4_setkey,
+           &sm4_encrypt, nblocks, blocksize, context_size);
+}
+
+/* Run the self-tests for SM4-CBC, tests bulk CBC decryption.
+   Returns NULL on success. */
+static const char*
+selftest_cbc_128 (void)
+{
+  const int nblocks = 16 - 1;
+  const int blocksize = 16;
+  const int context_size = sizeof(SM4_context);
+
+  return _gcry_selftest_helper_cbc("SM4", &sm4_setkey,
+           &sm4_encrypt, nblocks, blocksize, context_size);
+}
+
+/* Run the self-tests for SM4-CFB, tests bulk CFB decryption.
+   Returns NULL on success. */
+static const char*
+selftest_cfb_128 (void)
+{
+  const int nblocks = 16 - 1;
+  const int blocksize = 16;
+  const int context_size = sizeof(SM4_context);
+
+  return _gcry_selftest_helper_cfb("SM4", &sm4_setkey,
+           &sm4_encrypt, nblocks, blocksize, context_size);
+}
+
+static const char *
+sm4_selftest (void)
+{
+  SM4_context ctx;
+  byte scratch[16];
+  const char *r;
+
+  static const byte plaintext[16] = {
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+  };
+  static const byte key[16] = {
+    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+  };
+  static const byte ciphertext[16] = {
+    0x68, 0x1E, 0xDF, 0x34, 0xD2, 0x06, 0x96, 0x5E,
+    0x86, 0xB3, 0xE9, 0x4F, 0x53, 0x6E, 0x42, 0x46
+  };
+
+  memset (&ctx, 0, sizeof(ctx));
+
+  sm4_expand_key (&ctx, key);
+  sm4_encrypt (&ctx, scratch, plaintext);
+  if (memcmp (scratch, ciphertext, sizeof (ciphertext)))
+    return "SM4 test encryption failed.";
+  sm4_decrypt (&ctx, scratch, scratch);
+  if (memcmp (scratch, plaintext, sizeof (plaintext)))
+    return "SM4 test decryption failed.";
+
+  if ( (r = selftest_ctr_128 ()) )
+    return r;
+
+  if ( (r = selftest_cbc_128 ()) )
+    return r;
+
+  if ( (r = selftest_cfb_128 ()) )
+    return r;
+
+  return NULL;
+}
+
+static gpg_err_code_t
+run_selftests (int algo, int extended, selftest_report_func_t report)
+{
+  const char *what;
+  const char *errtxt;
+
+  (void)extended;
+
+  if (algo != GCRY_CIPHER_SM4)
+    return GPG_ERR_CIPHER_ALGO;
+
+  what = "selftest";
+  errtxt = sm4_selftest ();
+  if (errtxt)
+    goto failed;
+
+  return 0;
+
+ failed:
+  if (report)
+    report ("cipher", GCRY_CIPHER_SM4, what, errtxt);
+  return GPG_ERR_SELFTEST_FAILED;
+}
+
+
+static const gcry_cipher_oid_spec_t sm4_oids[] =
+  {
+    { "1.2.156.10197.1.104.1", GCRY_CIPHER_MODE_ECB },
+    { "1.2.156.10197.1.104.2", GCRY_CIPHER_MODE_CBC },
+    { "1.2.156.10197.1.104.3", GCRY_CIPHER_MODE_OFB },
+    { "1.2.156.10197.1.104.4", GCRY_CIPHER_MODE_CFB },
+    { "1.2.156.10197.1.104.7", GCRY_CIPHER_MODE_CTR },
+    { NULL }
+  };
+
+gcry_cipher_spec_t _gcry_cipher_spec_sm4 =
+  {
+    GCRY_CIPHER_SM4, {0, 0},
+    "SM4", NULL, sm4_oids, 16, 128,
+    sizeof (SM4_context),
+    sm4_setkey, sm4_encrypt, sm4_decrypt,
+    NULL, NULL,
+    run_selftests
+  };
index 7b6e330..21e385a 100644 (file)
@@ -1206,7 +1206,7 @@ stribog_init_512 (void *context, unsigned int flags)
 
   memset (hd, 0, sizeof (*hd));
 
-  hd->bctx.blocksize = 64;
+  hd->bctx.blocksize_shift = _gcry_ctz(64);
   hd->bctx.bwrite = transform;
 }
 
@@ -1223,7 +1223,7 @@ static void
 transform_bits (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count)
 {
   u64 M[8];
-  u64 l;
+  u64 l, cf;
   int i;
 
   for (i = 0; i < 8; i++)
@@ -1243,11 +1243,13 @@ transform_bits (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count)
     }
 
   hd->Sigma[0] += M[0];
+  cf = 0;
   for (i = 1; i < 8; i++)
-    if (hd->Sigma[i-1] < M[i-1])
-      hd->Sigma[i] += M[i] + 1;
-    else
-      hd->Sigma[i] += M[i];
+    {
+      if (hd->Sigma[i-1] != M[i-1])
+       cf = (hd->Sigma[i-1] < M[i-1]);
+      hd->Sigma[i] += M[i] + cf;
+    }
 }
 
 static unsigned int
@@ -1287,13 +1289,13 @@ stribog_final (void *context)
   u64 Z[8] = {};
   int i;
 
-  _gcry_md_block_write (context, NULL, 0); /* flush */ ;
   /* PAD. It does not count towards message length */
   i = hd->bctx.count;
   /* After flush we have at least one byte free) */
   hd->bctx.buf[i++] = 1;
-  while (i < 64)
-    hd->bctx.buf[i++] = 0;
+  if (i < 64)
+    memset (&hd->bctx.buf[i], 0, 64 - i);
+  i = 64;
   transform_bits (hd, hd->bctx.buf, hd->bctx.count * 8);
 
   g (hd->h, hd->N, Z);
@@ -1302,6 +1304,8 @@ stribog_final (void *context)
   for (i = 0; i < 8; i++)
     hd->h[i] = le_bswap64(hd->h[i]);
 
+  hd->bctx.count = 0;
+
   _gcry_burn_stack (768);
 }
 
@@ -1321,7 +1325,7 @@ stribog_read_256 (void *context)
   return hd->result + 32;
 }
 
-static gcry_md_oid_spec_t oid_spec_stribog256[] =
+static const gcry_md_oid_spec_t oid_spec_stribog256[] =
   {
     /* id-tc26-signwithdigest-gost3410-12-256 */
     { "1.2.643.7.1.1.3.2" },
@@ -1330,7 +1334,7 @@ static gcry_md_oid_spec_t oid_spec_stribog256[] =
     { NULL },
   };
 
-static gcry_md_oid_spec_t oid_spec_stribog512[] =
+static const gcry_md_oid_spec_t oid_spec_stribog512[] =
   {
     /* id-tc26-signwithdigest-gost3410-12-512 */
     { "1.2.643.7.1.1.3.3" },
@@ -1339,20 +1343,20 @@ static gcry_md_oid_spec_t oid_spec_stribog512[] =
     { NULL },
   };
 
-gcry_md_spec_t _gcry_digest_spec_stribog_256 =
+const 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,
     sizeof (STRIBOG_CONTEXT)
   };
 
-gcry_md_spec_t _gcry_digest_spec_stribog_512 =
+const 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,
     sizeof (STRIBOG_CONTEXT)
   };
diff --git a/cipher/test-getrusage.c b/cipher/test-getrusage.c
new file mode 100644 (file)
index 0000000..7f586dd
--- /dev/null
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+
+int
+main (int argc, char **argv)
+{
+  struct rusage buf;
+
+  if (argc > 1)
+    {
+      system (argv[1]);
+
+      if (getrusage (RUSAGE_CHILDREN, &buf ))
+        {
+          perror ("getrusage");
+          return 1;
+        }
+    }
+  else
+    {
+      if (getrusage (RUSAGE_SELF, &buf ))
+        {
+          perror ("getrusage");
+          return 1;
+        }
+    }
+
+  printf ("ru_utime   = %ld.%06ld\n",
+          buf.ru_utime.tv_sec, buf.ru_utime.tv_usec);
+  printf ("ru_stime   = %ld.%06ld\n",
+          buf.ru_stime.tv_sec, buf.ru_stime.tv_usec);
+  printf ("ru_maxrss  = %ld\n", buf.ru_maxrss   );
+  printf ("ru_ixrss   = %ld\n", buf.ru_ixrss    );
+  printf ("ru_idrss   = %ld\n", buf.ru_idrss    );
+  printf ("ru_isrss   = %ld\n", buf.ru_isrss    );
+  printf ("ru_minflt  = %ld\n", buf.ru_minflt   );
+  printf ("ru_majflt  = %ld\n", buf.ru_majflt   );
+  printf ("ru_nswap   = %ld\n", buf.ru_nswap    );
+  printf ("ru_inblock = %ld\n", buf.ru_inblock  );
+  printf ("ru_oublock = %ld\n", buf.ru_oublock  );
+  printf ("ru_msgsnd  = %ld\n", buf.ru_msgsnd   );
+  printf ("ru_msgrcv  = %ld\n", buf.ru_msgrcv   );
+  printf ("ru_nsignals= %ld\n", buf.ru_nsignals );
+  printf ("ru_nvcsw   = %ld\n", buf.ru_nvcsw    );
+  printf ("ru_nivcsw  = %ld\n", buf.ru_nivcsw   );
+
+  return 0;
+}
+
+
+/* Codesnippet for debugging in random.c. */
+#if 0
+static void
+collect_rusage_stats (struct rusage *rb)
+{
+  static int idx;
+  static struct rusage buf[100];
+
+  if (!rb)
+    {
+      int i;
+
+      fprintf (stderr, "ru_utime   ru_stime   ru_minflt  ru_nvcsw  ru_nivcsw\n");
+      for (i=0; i < idx; i++)
+        fprintf (stderr, "%ld.%06ld   %ld.%06ld %5ld       %5ld      %5ld\n",
+                 buf[i].ru_utime.tv_sec, buf[i].ru_utime.tv_usec,
+                 buf[i].ru_stime.tv_sec, buf[i].ru_stime.tv_usec,
+                 buf[i].ru_minflt,
+                 buf[i].ru_nvcsw,
+                 buf[i].ru_nivcsw);
+    }
+  else if (idx < DIM(buf))
+    {
+      buf[idx++] = *rb;
+    }
+}
+#endif
+/*
+ void
+ _gcry_random_dump_stats()
+ {
+@@ -233,8 +261,11 @@
+                  rndstats.naddbytes, rndstats.addbytes,
+        rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1,
+                    rndstats.ngetbytes2, rndstats.getbytes2 );
++
++    collect_rusage_stats (NULL);
+ }
+
+========
+
+     getrusage (RUSAGE_SELF, &buf );
++    collect_rusage_stats (&buf);
+     add_randomness( &buf, sizeof buf, 1 );
+     memset( &buf, 0, sizeof buf );
+   }
+
+*/
index b60ec16..ae55359 100644 (file)
@@ -601,7 +601,7 @@ do_init (void *context, int variant)
   hd->bctx.nblocks = 0;
   hd->bctx.nblocks_high = 0;
   hd->bctx.count = 0;
-  hd->bctx.blocksize = 64;
+  hd->bctx.blocksize_shift = _gcry_ctz(64);
   hd->bctx.bwrite = transform;
   hd->variant = variant;
 }
@@ -736,8 +736,6 @@ tiger_final( void *context )
   unsigned int burn;
   byte pad = hd->variant == 2? 0x80 : 0x01;
 
-  _gcry_md_block_write(hd, NULL, 0); /* flush */;
-
   t = hd->bctx.nblocks;
   if (sizeof t == sizeof hd->bctx.nblocks)
     th = hd->bctx.nblocks_high;
@@ -760,22 +758,25 @@ tiger_final( void *context )
   if( hd->bctx.count < 56 )  /* enough room */
     {
       hd->bctx.buf[hd->bctx.count++] = pad;
-      while( hd->bctx.count < 56 )
-        hd->bctx.buf[hd->bctx.count++] = 0;  /* pad */
+      if (hd->bctx.count < 56)
+       memset (&hd->bctx.buf[hd->bctx.count], 0, 56 - hd->bctx.count);
+
+      /* append the 64 bit count */
+      buf_put_le32(hd->bctx.buf + 56, lsb);
+      buf_put_le32(hd->bctx.buf + 60, msb);
+      burn = transform( hd, hd->bctx.buf, 1 );
     }
   else  /* need one extra block */
     {
       hd->bctx.buf[hd->bctx.count++] = pad; /* pad character */
-      while( hd->bctx.count < 64 )
-        hd->bctx.buf[hd->bctx.count++] = 0;
-      _gcry_md_block_write(hd, NULL, 0);  /* flush */;
-      memset(hd->bctx.buf, 0, 56 ); /* fill next block with zeroes */
+      /* fill pad and next block with zeroes */
+      memset (&hd->bctx.buf[hd->bctx.count], 0, 64 - hd->bctx.count + 56);
+
+      /* append the 64 bit count */
+      buf_put_le32(hd->bctx.buf + 64 + 56, lsb);
+      buf_put_le32(hd->bctx.buf + 64 + 60, msb);
+      burn = transform( hd, hd->bctx.buf, 2 );
     }
-  /* append the 64 bit count */
-  buf_put_le32(hd->bctx.buf + 56, lsb);
-  buf_put_le32(hd->bctx.buf + 60, msb);
-  burn = transform( hd, hd->bctx.buf, 1 );
-  _gcry_burn_stack (burn);
 
   p = hd->bctx.buf;
 #define X(a) do { buf_put_be64(p, hd->a); p += 8; } while(0)
@@ -794,6 +795,10 @@ tiger_final( void *context )
     }
 #undef X
 #undef Y
+
+  hd->bctx.count = 0;
+
+  _gcry_burn_stack (burn);
 }
 
 static byte *
@@ -809,44 +814,47 @@ tiger_read( void *context )
 /* This is the old TIGER variant based on the unfixed reference
    implementation.  IT was used in GnupG up to 1.3.2.  We don't provide
    an OID anymore because that would not be correct.  */
-gcry_md_spec_t _gcry_digest_spec_tiger =
+const 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,
     sizeof (TIGER_CONTEXT)
   };
 
 
 \f
 /* This is the fixed TIGER implementation.  */
-static byte asn1[19] = /* Object ID is 1.3.6.1.4.1.11591.12.2 */
+static const byte asn1[19] = /* Object ID is 1.3.6.1.4.1.11591.12.2 */
   { 0x30, 0x29, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06,
     0x01, 0x04, 0x01, 0xda, 0x47, 0x0c, 0x02,
     0x05, 0x00, 0x04, 0x18 };
 
-static gcry_md_oid_spec_t oid_spec_tiger1[] =
+static const gcry_md_oid_spec_t oid_spec_tiger1[] =
   {
     /* GNU.digestAlgorithm TIGER */
     { "1.3.6.1.4.1.11591.12.2" },
     { NULL }
   };
 
-gcry_md_spec_t _gcry_digest_spec_tiger1 =
+const 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,
     sizeof (TIGER_CONTEXT)
   };
 
 
 \f
 /* This is TIGER2 which usues a changed padding algorithm.  */
-gcry_md_spec_t _gcry_digest_spec_tiger2 =
+const 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,
     sizeof (TIGER_CONTEXT)
   };
index 99c4675..7941fe3 100644 (file)
@@ -18,7 +18,7 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "asm-common-aarch64.h"
 
 #if defined(__AARCH64EL__)
 #ifdef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
        ror1(RD);
 
 .globl _gcry_twofish_arm_encrypt_block
-.type   _gcry_twofish_arm_encrypt_block,%function;
+ELF(.type   _gcry_twofish_arm_encrypt_block,%function;)
 
 _gcry_twofish_arm_encrypt_block:
        /* input:
@@ -225,6 +225,7 @@ _gcry_twofish_arm_encrypt_block:
         *      x1: dst
         *      x2: src
         */
+       CFI_STARTPROC();
 
        add CTXw, CTX, #(w);
 
@@ -261,12 +262,13 @@ _gcry_twofish_arm_encrypt_block:
 
        str_output_le(RDST, RC, RD, RA, RB, RT0, RT1);
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 .ltorg
-.size _gcry_twofish_arm_encrypt_block,.-_gcry_twofish_arm_encrypt_block;
+ELF(.size _gcry_twofish_arm_encrypt_block,.-_gcry_twofish_arm_encrypt_block;)
 
 .globl _gcry_twofish_arm_decrypt_block
-.type   _gcry_twofish_arm_decrypt_block,%function;
+ELF(.type   _gcry_twofish_arm_decrypt_block,%function;)
 
 _gcry_twofish_arm_decrypt_block:
        /* input:
@@ -274,6 +276,7 @@ _gcry_twofish_arm_decrypt_block:
         *      %r1: dst
         *      %r2: src
         */
+       CFI_STARTPROC();
 
        add CTXw, CTX, #(w);
 
@@ -310,8 +313,9 @@ _gcry_twofish_arm_decrypt_block:
 
        str_output_le(RDST, RA, RB, RC, RD, RT0, RT1);
 
-       ret;
-.size _gcry_twofish_arm_decrypt_block,.-_gcry_twofish_arm_decrypt_block;
+       ret_spec_stop;
+       CFI_ENDPROC();
+ELF(.size _gcry_twofish_arm_decrypt_block,.-_gcry_twofish_arm_decrypt_block;)
 
 #endif /*HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS*/
 #endif /*__AARCH64EL__*/
index aa964e0..a7a6055 100644 (file)
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_TWOFISH)
 
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-#ifdef __PIC__
-#  define RIP %rip
-#else
-#  define RIP
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -181,10 +171,16 @@ _gcry_twofish_amd64_encrypt_block:
         *      %rsi: dst
         *      %rdx: src
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        subq $(3 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(3 * 8);
        movq %rsi, (0 * 8)(%rsp);
        movq %rbp, (1 * 8)(%rsp);
        movq %rbx, (2 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 1 * 8);
+       CFI_REL_OFFSET(%rbx, 2 * 8);
 
        movq %rdx, RX;
        inpack(RX, 0, RAd, 0);
@@ -209,9 +205,14 @@ _gcry_twofish_amd64_encrypt_block:
 
        movq (2 * 8)(%rsp), %rbx;
        movq (1 * 8)(%rsp), %rbp;
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%rbp);
        addq $(3 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-3 * 8);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_amd64_encrypt_block,.-_gcry_twofish_amd64_encrypt_block;)
 
 .align 8
@@ -224,10 +225,16 @@ _gcry_twofish_amd64_decrypt_block:
         *      %rsi: dst
         *      %rdx: src
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        subq $(3 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(3 * 8);
        movq %rsi, (0 * 8)(%rsp);
        movq %rbp, (1 * 8)(%rsp);
        movq %rbx, (2 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 1 * 8);
+       CFI_REL_OFFSET(%rbx, 2 * 8);
 
        movq %rdx, RX;
        inpack(RX, 0, RCd, 4);
@@ -252,9 +259,14 @@ _gcry_twofish_amd64_decrypt_block:
 
        movq (2 * 8)(%rsp), %rbx;
        movq (1 * 8)(%rsp), %rbp;
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%rbp);
        addq $(3 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-3 * 8);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_amd64_encrypt_block,.-_gcry_twofish_amd64_encrypt_block;)
 
 #undef CTX
@@ -372,15 +384,21 @@ ELF(.size _gcry_twofish_amd64_encrypt_block,.-_gcry_twofish_amd64_encrypt_block;
        /* G1,2 && G2,2 */ \
        do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
        do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
-       xchgq cd ## 0, ab ## 0; \
+       movq ab ## 0, RT0; \
+       movq cd ## 0, ab ## 0; \
+       movq RT0, cd ## 0; \
        \
        do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
        do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
-       xchgq cd ## 1, ab ## 1; \
+       movq ab ## 1, RT0; \
+       movq cd ## 1, ab ## 1; \
+       movq RT0, cd ## 1; \
        \
        do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
        do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
-       xchgq cd ## 2, ab ## 2;
+       movq ab ## 2, RT0; \
+       movq cd ## 2, ab ## 2; \
+       movq RT0, cd ## 2;
 
 #define enc_round_end(ab, x, y, n) \
        addl y ## d,                    x ## d; \
@@ -478,6 +496,8 @@ __twofish_enc_blk3:
         * output:
         *      RCD0,RAB0,RCD1,RAB1,RCD2,RAB2: three ciphertext blocks
         */
+       CFI_STARTPROC();
+
        inpack_enc3();
 
        encrypt_cycle3(RAB, RCD, 0);
@@ -491,7 +511,8 @@ __twofish_enc_blk3:
 
        outunpack_enc3();
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __twofish_enc_blk3,.-__twofish_enc_blk3;)
 
 .align 8
@@ -504,6 +525,8 @@ __twofish_dec_blk3:
         * output:
         *      RCD0,RAB0,RCD1,RAB1,RCD2,RAB2: three plaintext blocks
         */
+       CFI_STARTPROC();
+
        inpack_dec3();
 
        decrypt_cycle3(RAB, RCD, 7);
@@ -517,7 +540,8 @@ __twofish_dec_blk3:
 
        outunpack_dec3();
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __twofish_dec_blk3,.-__twofish_dec_blk3;)
 
 .align 8
@@ -530,13 +554,23 @@ _gcry_twofish_amd64_ctr_enc:
         *      %rdx: src (3 blocks)
         *      %rcx: iv (big endian, 128bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        subq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(8 * 8);
        movq %rbp, (0 * 8)(%rsp);
        movq %rbx, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
        movq %r14, (4 * 8)(%rsp);
        movq %r15, (5 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 0 * 8);
+       CFI_REL_OFFSET(%rbx, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+       CFI_REL_OFFSET(%r14, 4 * 8);
+       CFI_REL_OFFSET(%r15, 5 * 8);
 
        movq %rsi, (6 * 8)(%rsp);
        movq %rdx, (7 * 8)(%rsp);
@@ -597,9 +631,18 @@ _gcry_twofish_amd64_ctr_enc:
        movq (3 * 8)(%rsp), %r13;
        movq (4 * 8)(%rsp), %r14;
        movq (5 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbp);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
        addq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-8 * 8);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_amd64_ctr_enc,.-_gcry_twofish_amd64_ctr_enc;)
 
 .align 8
@@ -612,13 +655,23 @@ _gcry_twofish_amd64_cbc_dec:
         *      %rdx: src (3 blocks)
         *      %rcx: iv (128bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        subq $(9 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(9 * 8);
        movq %rbp, (0 * 8)(%rsp);
        movq %rbx, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
        movq %r14, (4 * 8)(%rsp);
        movq %r15, (5 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 0 * 8);
+       CFI_REL_OFFSET(%rbx, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+       CFI_REL_OFFSET(%r14, 4 * 8);
+       CFI_REL_OFFSET(%r15, 5 * 8);
 
        movq %rsi, (6 * 8)(%rsp);
        movq %rdx, (7 * 8)(%rsp);
@@ -663,9 +716,18 @@ _gcry_twofish_amd64_cbc_dec:
        movq (3 * 8)(%rsp), %r13;
        movq (4 * 8)(%rsp), %r14;
        movq (5 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbp);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
        addq $(9 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-9 * 8);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_amd64_cbc_dec,.-_gcry_twofish_amd64_cbc_dec;)
 
 .align 8
@@ -678,13 +740,23 @@ _gcry_twofish_amd64_cfb_dec:
         *      %rdx: src (3 blocks)
         *      %rcx: iv (128bit)
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_0_4
+
        subq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(8 * 8);
        movq %rbp, (0 * 8)(%rsp);
        movq %rbx, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
        movq %r14, (4 * 8)(%rsp);
        movq %r15, (5 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 0 * 8);
+       CFI_REL_OFFSET(%rbx, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+       CFI_REL_OFFSET(%r14, 4 * 8);
+       CFI_REL_OFFSET(%r15, 5 * 8);
 
        movq %rsi, (6 * 8)(%rsp);
        movq %rdx, (7 * 8)(%rsp);
@@ -729,9 +801,18 @@ _gcry_twofish_amd64_cfb_dec:
        movq (3 * 8)(%rsp), %r13;
        movq (4 * 8)(%rsp), %r14;
        movq (5 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbp);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
        addq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-8 * 8);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_amd64_cfb_dec,.-_gcry_twofish_amd64_cfb_dec;)
 
 .align 8
@@ -746,13 +827,23 @@ _gcry_twofish_amd64_ocb_enc:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[3])
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_6
+
        subq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(8 * 8);
        movq %rbp, (0 * 8)(%rsp);
        movq %rbx, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
        movq %r14, (4 * 8)(%rsp);
        movq %r15, (5 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 0 * 8);
+       CFI_REL_OFFSET(%rbx, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+       CFI_REL_OFFSET(%r14, 4 * 8);
+       CFI_REL_OFFSET(%r15, 5 * 8);
 
        movq %rsi, (6 * 8)(%rsp);
        movq %rdx, RX0;
@@ -836,9 +927,18 @@ _gcry_twofish_amd64_ocb_enc:
        movq (3 * 8)(%rsp), %r13;
        movq (4 * 8)(%rsp), %r14;
        movq (5 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbp);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
        addq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-8 * 8);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_amd64_ocb_enc,.-_gcry_twofish_amd64_ocb_enc;)
 
 .align 8
@@ -853,13 +953,23 @@ _gcry_twofish_amd64_ocb_dec:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[3])
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_6
+
        subq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(8 * 8);
        movq %rbp, (0 * 8)(%rsp);
        movq %rbx, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
        movq %r14, (4 * 8)(%rsp);
        movq %r15, (5 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 0 * 8);
+       CFI_REL_OFFSET(%rbx, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+       CFI_REL_OFFSET(%r14, 4 * 8);
+       CFI_REL_OFFSET(%r15, 5 * 8);
 
        movq %rsi, (6 * 8)(%rsp);
        movq %r8,  (7 * 8)(%rsp);
@@ -951,9 +1061,18 @@ _gcry_twofish_amd64_ocb_dec:
        movq (3 * 8)(%rsp), %r13;
        movq (4 * 8)(%rsp), %r14;
        movq (5 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbp);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
        addq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-8 * 8);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_amd64_ocb_dec,.-_gcry_twofish_amd64_ocb_dec;)
 
 .align 8
@@ -967,13 +1086,23 @@ _gcry_twofish_amd64_ocb_auth:
         *      %rcx: checksum
         *      %r8 : L pointers (void *L[3])
         */
+       CFI_STARTPROC();
+       ENTER_SYSV_FUNC_PARAMS_5
+
        subq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(8 * 8);
        movq %rbp, (0 * 8)(%rsp);
        movq %rbx, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
        movq %r14, (4 * 8)(%rsp);
        movq %r15, (5 * 8)(%rsp);
+       CFI_REL_OFFSET(%rbp, 0 * 8);
+       CFI_REL_OFFSET(%rbx, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
+       CFI_REL_OFFSET(%r14, 4 * 8);
+       CFI_REL_OFFSET(%r15, 5 * 8);
 
        movq %rcx, (6 * 8)(%rsp);
        movq %rsi, RX0;
@@ -1037,9 +1166,18 @@ _gcry_twofish_amd64_ocb_auth:
        movq (3 * 8)(%rsp), %r13;
        movq (4 * 8)(%rsp), %r14;
        movq (5 * 8)(%rsp), %r15;
+       CFI_RESTORE(%rbp);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
        addq $(8 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-8 * 8);
 
-       ret;
+       EXIT_SYSV_FUNC
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_amd64_ocb_auth,.-_gcry_twofish_amd64_ocb_auth;)
 
 #endif /*USE_TWOFISH*/
index db6e218..930ac79 100644 (file)
     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_TWOFISH) && \
     defined(ENABLE_AVX2_SUPPORT)
 
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
-
-#ifdef __PIC__
-#  define RIP (%rip)
-#else
-#  define RIP
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -423,6 +413,7 @@ __twofish_enc_blk16:
         *      RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
         *                                              ciphertext blocks
         */
+       CFI_STARTPROC();
        init_round_constants();
 
        transpose4x4_16(RA, RB, RC, RD);
@@ -440,7 +431,8 @@ __twofish_enc_blk16:
        outunpack_enc16(RA, RB, RC, RD);
        transpose4x4_16(RA, RB, RC, RD);
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __twofish_enc_blk16,.-__twofish_enc_blk16;)
 
 .align 8
@@ -454,6 +446,7 @@ __twofish_dec_blk16:
         *      RA0, RB0, RC0, RD0, RA1, RB1, RC1, RD1: sixteen parallel
         *                                              ciphertext blocks
         */
+       CFI_STARTPROC();
        init_round_constants();
 
        transpose4x4_16(RA, RB, RC, RD);
@@ -471,7 +464,8 @@ __twofish_dec_blk16:
        outunpack_dec16(RA, RB, RC, RD);
        transpose4x4_16(RA, RB, RC, RD);
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size __twofish_dec_blk16,.-__twofish_dec_blk16;)
 
 #define inc_le128(x, minus_one, tmp) \
@@ -490,13 +484,14 @@ _gcry_twofish_avx2_ctr_enc:
         *      %rdx: src (16 blocks)
         *      %rcx: iv (big endian, 128bit)
         */
+       CFI_STARTPROC();
 
        movq 8(%rcx), %rax;
        bswapq %rax;
 
        vzeroupper;
 
-       vbroadcasti128 .Lbswap128_mask RIP, RTMP3;
+       vbroadcasti128 .Lbswap128_mask rRIP, RTMP3;
        vpcmpeqd RNOT, RNOT, RNOT;
        vpsrldq $8, RNOT, RNOT;   /* ab: -1:0 ; cd: -1:0 */
        vpaddq RNOT, RNOT, RTMP2; /* ab: -2:0 ; cd: -2:0 */
@@ -587,7 +582,8 @@ _gcry_twofish_avx2_ctr_enc:
 
        vzeroall;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_avx2_ctr_enc,.-_gcry_twofish_avx2_ctr_enc;)
 
 .align 8
@@ -600,6 +596,7 @@ _gcry_twofish_avx2_cbc_dec:
         *      %rdx: src (16 blocks)
         *      %rcx: iv
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
@@ -638,7 +635,8 @@ _gcry_twofish_avx2_cbc_dec:
 
        vzeroall;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_avx2_cbc_dec,.-_gcry_twofish_avx2_cbc_dec;)
 
 .align 8
@@ -651,6 +649,7 @@ _gcry_twofish_avx2_cfb_dec:
         *      %rdx: src (16 blocks)
         *      %rcx: iv
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
@@ -691,7 +690,8 @@ _gcry_twofish_avx2_cfb_dec:
 
        vzeroall;
 
-       ret
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_avx2_cfb_dec,.-_gcry_twofish_avx2_cfb_dec;)
 
 .align 8
@@ -707,15 +707,21 @@ _gcry_twofish_avx2_ocb_enc:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        vmovdqu (%rcx), RTMP0x;
        vmovdqu (%r8), RTMP1x;
@@ -768,10 +774,15 @@ _gcry_twofish_avx2_ocb_enc:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __twofish_enc_blk16;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        vpxor (0 * 32)(%rsi), RA0, RA0;
        vpxor (1 * 32)(%rsi), RB0, RB0;
@@ -793,7 +804,8 @@ _gcry_twofish_avx2_ocb_enc:
 
        vzeroall;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_avx2_ocb_enc,.-_gcry_twofish_avx2_ocb_enc;)
 
 .align 8
@@ -809,15 +821,21 @@ _gcry_twofish_avx2_ocb_dec:
         *      %r8 : checksum
         *      %r9 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        vmovdqu (%rcx), RTMP0x;
 
@@ -865,6 +883,10 @@ _gcry_twofish_avx2_ocb_dec:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __twofish_dec_blk16;
 
@@ -880,6 +902,7 @@ _gcry_twofish_avx2_ocb_dec:
        vpxor (7 * 32)(%rsi), RD1, RD1;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        /* Checksum_i = Checksum_{i-1} xor P_i  */
 
@@ -906,7 +929,8 @@ _gcry_twofish_avx2_ocb_dec:
 
        vzeroall;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_avx2_ocb_dec,.-_gcry_twofish_avx2_ocb_dec;)
 
 .align 8
@@ -921,15 +945,21 @@ _gcry_twofish_avx2_ocb_auth:
         *      %rcx: checksum
         *      %r8 : L pointers (void *L[16])
         */
+       CFI_STARTPROC();
 
        vzeroupper;
 
        subq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(4 * 8);
 
        movq %r10, (0 * 8)(%rsp);
        movq %r11, (1 * 8)(%rsp);
        movq %r12, (2 * 8)(%rsp);
        movq %r13, (3 * 8)(%rsp);
+       CFI_REL_OFFSET(%r10, 0 * 8);
+       CFI_REL_OFFSET(%r11, 1 * 8);
+       CFI_REL_OFFSET(%r12, 2 * 8);
+       CFI_REL_OFFSET(%r13, 3 * 8);
 
        vmovdqu (%rdx), RTMP0x;
 
@@ -975,6 +1005,10 @@ _gcry_twofish_avx2_ocb_auth:
        movq (1 * 8)(%rsp), %r11;
        movq (2 * 8)(%rsp), %r12;
        movq (3 * 8)(%rsp), %r13;
+       CFI_RESTORE(%r10);
+       CFI_RESTORE(%r11);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
 
        call __twofish_enc_blk16;
 
@@ -987,6 +1021,7 @@ _gcry_twofish_avx2_ocb_auth:
        vpxor RA1, RC1, RA1;
 
        addq $(4 * 8), %rsp;
+       CFI_ADJUST_CFA_OFFSET(-4 * 8);
 
        vpxor RA1, RA0, RTMP1;
 
@@ -997,7 +1032,8 @@ _gcry_twofish_avx2_ocb_auth:
 
        vzeroall;
 
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_twofish_avx2_ocb_auth,.-_gcry_twofish_avx2_ocb_auth;)
 
 .align 16
index 942e8d4..d19e079 100644 (file)
 /* Prototype for the self-test function. */
 static const char *selftest(void);
 
+
+/* Prototypes for the bulk functions. */
+static void _gcry_twofish_ctr_enc (void *context, unsigned char *ctr,
+                                  void *outbuf_arg, const void *inbuf_arg,
+                                  size_t nblocks);
+static void _gcry_twofish_cbc_dec (void *context, unsigned char *iv,
+                                  void *outbuf_arg, const void *inbuf_arg,
+                                  size_t nblocks);
+static void _gcry_twofish_cfb_dec (void *context, unsigned char *iv,
+                                  void *outbuf_arg, const void *inbuf_arg,
+                                  size_t nblocks);
+static size_t _gcry_twofish_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
+                                      const void *inbuf_arg, size_t nblocks,
+                                      int encrypt);
+static size_t _gcry_twofish_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
+                                     size_t nblocks);
+
+
 /* Structure for an expanded Twofish key.  s contains the key-dependent
  * S-boxes composed with the MDS matrix; w contains the eight "whitening"
  * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys.  Note
@@ -734,7 +752,8 @@ do_twofish_setkey (TWOFISH_context *ctx, const byte *key, const unsigned keylen)
 }
 
 static gcry_err_code_t
-twofish_setkey (void *context, const byte *key, unsigned int keylen)
+twofish_setkey (void *context, const byte *key, unsigned int keylen,
+                cipher_bulk_ops_t *bulk_ops)
 {
   TWOFISH_context *ctx = context;
   unsigned int hwfeatures = _gcry_get_hw_features ();
@@ -750,6 +769,14 @@ twofish_setkey (void *context, const byte *key, unsigned int keylen)
     }
 #endif
 
+  /* Setup bulk encryption routines.  */
+  memset (bulk_ops, 0, sizeof(*bulk_ops));
+  bulk_ops->cbc_dec = _gcry_twofish_cbc_dec;
+  bulk_ops->cfb_dec = _gcry_twofish_cfb_dec;
+  bulk_ops->ctr_enc = _gcry_twofish_ctr_enc;
+  bulk_ops->ocb_crypt = _gcry_twofish_ocb_crypt;
+  bulk_ops->ocb_auth  = _gcry_twofish_ocb_auth;
+
   (void)hwfeatures;
 
   _gcry_burn_stack (23+6*sizeof(void*));
@@ -829,145 +856,58 @@ extern void _gcry_twofish_amd64_ocb_auth(const TWOFISH_context *ctx,
                                         const byte *abuf, byte *offset,
                                         byte *checksum, const u64 Ls[3]);
 
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-static inline void
-call_sysv_fn (const void *fn, const void *arg1, const void *arg2,
-              const void *arg3, const void *arg4)
-{
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  asm volatile ("callq *%0\n\t"
-                : "+a" (fn),
-                  "+D" (arg1),
-                  "+S" (arg2),
-                  "+d" (arg3),
-                  "+c" (arg4)
-                :
-                : "cc", "memory", "r8", "r9", "r10", "r11");
-}
-
-static inline void
-call_sysv_fn5 (const void *fn, const void *arg1, const void *arg2,
-               const void *arg3, const void *arg4, const void *arg5)
-{
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  asm volatile ("movq %[arg5], %%r8\n\t"
-               "callq *%0\n\t"
-               : "+a" (fn),
-                 "+D" (arg1),
-                 "+S" (arg2),
-                 "+d" (arg3),
-                 "+c" (arg4)
-               : [arg5] "g" (arg5)
-               : "cc", "memory", "r8", "r9", "r10", "r11");
-}
-
-static inline void
-call_sysv_fn6 (const void *fn, const void *arg1, const void *arg2,
-               const void *arg3, const void *arg4, const void *arg5,
-              const void *arg6)
-{
-  /* Call SystemV ABI function without storing non-volatile XMM registers,
-   * as target function does not use vector instruction sets. */
-  asm volatile ("movq %[arg5], %%r8\n\t"
-               "movq %[arg6], %%r9\n\t"
-               "callq *%0\n\t"
-               : "+a" (fn),
-                 "+D" (arg1),
-                 "+S" (arg2),
-                 "+d" (arg3),
-                 "+c" (arg4)
-               : [arg5] "g" (arg5),
-                 [arg6] "g" (arg6)
-               : "cc", "memory", "r8", "r9", "r10", "r11");
-}
-#endif
-
 static inline void
 twofish_amd64_encrypt_block(const TWOFISH_context *c, byte *out, const byte *in)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn(_gcry_twofish_amd64_encrypt_block, c, out, in, NULL);
-#else
   _gcry_twofish_amd64_encrypt_block(c, out, in);
-#endif
 }
 
 static inline void
 twofish_amd64_decrypt_block(const TWOFISH_context *c, byte *out, const byte *in)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn(_gcry_twofish_amd64_decrypt_block, c, out, in, NULL);
-#else
   _gcry_twofish_amd64_decrypt_block(c, out, in);
-#endif
 }
 
 static inline void
 twofish_amd64_ctr_enc(const TWOFISH_context *c, byte *out, const byte *in,
                       byte *ctr)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn(_gcry_twofish_amd64_ctr_enc, c, out, in, ctr);
-#else
   _gcry_twofish_amd64_ctr_enc(c, out, in, ctr);
-#endif
 }
 
 static inline void
 twofish_amd64_cbc_dec(const TWOFISH_context *c, byte *out, const byte *in,
                       byte *iv)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn(_gcry_twofish_amd64_cbc_dec, c, out, in, iv);
-#else
   _gcry_twofish_amd64_cbc_dec(c, out, in, iv);
-#endif
 }
 
 static inline void
 twofish_amd64_cfb_dec(const TWOFISH_context *c, byte *out, const byte *in,
                       byte *iv)
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn(_gcry_twofish_amd64_cfb_dec, c, out, in, iv);
-#else
   _gcry_twofish_amd64_cfb_dec(c, out, in, iv);
-#endif
 }
 
 static inline void
 twofish_amd64_ocb_enc(const TWOFISH_context *ctx, byte *out, const byte *in,
                      byte *offset, byte *checksum, const u64 Ls[3])
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn6(_gcry_twofish_amd64_ocb_enc, ctx, out, in, offset, checksum, Ls);
-#else
   _gcry_twofish_amd64_ocb_enc(ctx, out, in, offset, checksum, Ls);
-#endif
 }
 
 static inline void
 twofish_amd64_ocb_dec(const TWOFISH_context *ctx, byte *out, const byte *in,
                      byte *offset, byte *checksum, const u64 Ls[3])
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn6(_gcry_twofish_amd64_ocb_dec, ctx, out, in, offset, checksum, Ls);
-#else
   _gcry_twofish_amd64_ocb_dec(ctx, out, in, offset, checksum, Ls);
-#endif
 }
 
 static inline void
 twofish_amd64_ocb_auth(const TWOFISH_context *ctx, const byte *abuf,
                       byte *offset, byte *checksum, const u64 Ls[3])
 {
-#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-  call_sysv_fn5(_gcry_twofish_amd64_ocb_auth, ctx, abuf, offset, checksum, Ls);
-#else
   _gcry_twofish_amd64_ocb_auth(ctx, abuf, offset, checksum, Ls);
-#endif
 }
 
 #elif defined(USE_ARM_ASM)
@@ -1180,7 +1120,7 @@ twofish_decrypt (void *context, byte *out, const byte *in)
 /* Bulk encryption of complete blocks in CTR mode.  This function is only
    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
    of size TWOFISH_BLOCKSIZE. */
-void
+static void
 _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
                      const void *inbuf_arg, size_t nblocks)
 {
@@ -1189,7 +1129,6 @@ _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
   const unsigned char *inbuf = inbuf_arg;
   unsigned char tmpbuf[TWOFISH_BLOCKSIZE];
   unsigned int burn, burn_stack_depth = 0;
-  int i;
 
 #ifdef USE_AVX2
   if (ctx->use_avx2)
@@ -1245,16 +1184,11 @@ _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
         burn_stack_depth = burn;
 
       /* XOR the input with the encrypted counter and store in output.  */
-      buf_xor(outbuf, tmpbuf, inbuf, TWOFISH_BLOCKSIZE);
+      cipher_block_xor(outbuf, tmpbuf, inbuf, TWOFISH_BLOCKSIZE);
       outbuf += TWOFISH_BLOCKSIZE;
       inbuf  += TWOFISH_BLOCKSIZE;
       /* Increment the counter.  */
-      for (i = TWOFISH_BLOCKSIZE; i > 0; i--)
-        {
-          ctr[i-1]++;
-          if (ctr[i-1])
-            break;
-        }
+      cipher_block_add(ctr, 1, TWOFISH_BLOCKSIZE);
     }
 
   wipememory(tmpbuf, sizeof(tmpbuf));
@@ -1264,7 +1198,7 @@ _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg,
 
 /* Bulk decryption of complete blocks in CBC mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
                      const void *inbuf_arg, size_t nblocks)
 {
@@ -1327,7 +1261,7 @@ _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
       if (burn > burn_stack_depth)
         burn_stack_depth = burn;
 
-      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, TWOFISH_BLOCKSIZE);
+      cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, TWOFISH_BLOCKSIZE);
       inbuf += TWOFISH_BLOCKSIZE;
       outbuf += TWOFISH_BLOCKSIZE;
     }
@@ -1339,7 +1273,7 @@ _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
 
 /* Bulk decryption of complete blocks in CFB mode.  This function is only
    intended for the bulk encryption feature of cipher.c. */
-void
+static void
 _gcry_twofish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
                    const void *inbuf_arg, size_t nblocks)
 {
@@ -1399,7 +1333,7 @@ _gcry_twofish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
       if (burn > burn_stack_depth)
         burn_stack_depth = burn;
 
-      buf_xor_n_copy(outbuf, iv, inbuf, TWOFISH_BLOCKSIZE);
+      cipher_block_xor_n_copy(outbuf, iv, inbuf, TWOFISH_BLOCKSIZE);
       outbuf += TWOFISH_BLOCKSIZE;
       inbuf += TWOFISH_BLOCKSIZE;
     }
@@ -1408,7 +1342,7 @@ _gcry_twofish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg,
 }
 
 /* Bulk encryption/decryption of complete blocks in OCB mode. */
-size_t
+static size_t
 _gcry_twofish_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
                        const void *inbuf_arg, size_t nblocks, int encrypt)
 {
@@ -1522,7 +1456,7 @@ _gcry_twofish_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
 }
 
 /* Bulk authentication of complete blocks in OCB mode. */
-size_t
+static size_t
 _gcry_twofish_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
                        size_t nblocks)
 {
@@ -1636,8 +1570,7 @@ selftest_ctr (void)
   const int context_size = sizeof(TWOFISH_context);
 
   return _gcry_selftest_helper_ctr("TWOFISH", &twofish_setkey,
-           &twofish_encrypt, &_gcry_twofish_ctr_enc, nblocks, blocksize,
-          context_size);
+           &twofish_encrypt, nblocks, blocksize, context_size);
 }
 
 /* Run the self-tests for TWOFISH-CBC, tests bulk CBC decryption.
@@ -1650,8 +1583,7 @@ selftest_cbc (void)
   const int context_size = sizeof(TWOFISH_context);
 
   return _gcry_selftest_helper_cbc("TWOFISH", &twofish_setkey,
-           &twofish_encrypt, &_gcry_twofish_cbc_dec, nblocks, blocksize,
-          context_size);
+           &twofish_encrypt, nblocks, blocksize, context_size);
 }
 
 /* Run the self-tests for TWOFISH-CFB, tests bulk CBC decryption.
@@ -1664,8 +1596,7 @@ selftest_cfb (void)
   const int context_size = sizeof(TWOFISH_context);
 
   return _gcry_selftest_helper_cfb("TWOFISH", &twofish_setkey,
-           &twofish_encrypt, &_gcry_twofish_cfb_dec, nblocks, blocksize,
-          context_size);
+           &twofish_encrypt, nblocks, blocksize, context_size);
 }
 
 \f
@@ -1675,7 +1606,8 @@ static const char*
 selftest (void)
 {
   TWOFISH_context ctx; /* Expanded key. */
-  byte scratch[16];    /* Encryption/decryption result buffer. */
+  byte scratch[16];    /* Encryption/decryption result buffer. */
+  cipher_bulk_ops_t bulk_ops;
   const char *r;
 
   /* Test vectors for single encryption/decryption.  Note that I am using
@@ -1710,7 +1642,7 @@ selftest (void)
     0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA
   };
 
-  twofish_setkey (&ctx, key, sizeof(key));
+  twofish_setkey (&ctx, key, sizeof(key), &bulk_ops);
   twofish_encrypt (&ctx, scratch, plaintext);
   if (memcmp (scratch, ciphertext, sizeof (ciphertext)))
     return "Twofish-128 test encryption failed.";
@@ -1718,7 +1650,7 @@ selftest (void)
   if (memcmp (scratch, plaintext, sizeof (plaintext)))
     return "Twofish-128 test decryption failed.";
 
-  twofish_setkey (&ctx, key_256, sizeof(key_256));
+  twofish_setkey (&ctx, key_256, sizeof(key_256), &bulk_ops);
   twofish_encrypt (&ctx, scratch, plaintext_256);
   if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256)))
     return "Twofish-256 test encryption failed.";
@@ -1753,7 +1685,8 @@ int
 main()
 {
   TWOFISH_context ctx;     /* Expanded key. */
-  int i, j;                /* Loop counters. */
+  int i, j;                /* Loop counters. */
+  cipher_bulk_ops_t bulk_ops;
 
   const char *encrypt_msg; /* Message to print regarding encryption test;
                             * the printf is done outside the loop to avoid
@@ -1800,13 +1733,13 @@ main()
   /* Encryption test. */
   for (i = 0; i < 125; i++)
     {
-      twofish_setkey (&ctx, buffer[0], sizeof (buffer[0]));
+      twofish_setkey (&ctx, buffer[0], sizeof (buffer[0]), &bulk_ops);
       for (j = 0; j < 1000; j++)
         twofish_encrypt (&ctx, buffer[2], buffer[2]);
-      twofish_setkey (&ctx, buffer[1], sizeof (buffer[1]));
+      twofish_setkey (&ctx, buffer[1], sizeof (buffer[1]), &bulk_ops);
       for (j = 0; j < 1000; j++)
         twofish_encrypt (&ctx, buffer[3], buffer[3]);
-      twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2);
+      twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2, &bulk_ops);
       for (j = 0; j < 1000; j++) {
         twofish_encrypt (&ctx, buffer[0], buffer[0]);
         twofish_encrypt (&ctx, buffer[1], buffer[1]);
@@ -1818,15 +1751,15 @@ main()
   /* Decryption test. */
   for (i = 0; i < 125; i++)
     {
-      twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2);
+      twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2, &bulk_ops);
       for (j = 0; j < 1000; j++) {
         twofish_decrypt (&ctx, buffer[0], buffer[0]);
         twofish_decrypt (&ctx, buffer[1], buffer[1]);
       }
-      twofish_setkey (&ctx, buffer[1], sizeof (buffer[1]));
+      twofish_setkey (&ctx, buffer[1], sizeof (buffer[1]), &bulk_ops);
       for (j = 0; j < 1000; j++)
         twofish_decrypt (&ctx, buffer[3], buffer[3]);
-      twofish_setkey (&ctx, buffer[0], sizeof (buffer[0]));
+      twofish_setkey (&ctx, buffer[0], sizeof (buffer[0]), &bulk_ops);
       for (j = 0; j < 1000; j++)
         twofish_decrypt (&ctx, buffer[2], buffer[2]);
     }
index e98b831..37648fa 100644 (file)
 #if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && defined(USE_WHIRLPOOL)
 
-#ifdef __PIC__
-#  define RIP %rip
-#else
-#  define RIP
-#endif
-
-#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-# define ELF(...) __VA_ARGS__
-#else
-# define ELF(...) /*_*/
-#endif
+#include "asm-common-amd64.h"
 
 .text
 
@@ -173,16 +163,24 @@ _gcry_whirlpool_transform_amd64:
         *      %rdx: nblks
         *      %rcx: look-up tables
         */
+       CFI_STARTPROC();
        cmp $0, %rdx;
        je .Lskip;
 
        subq $STACK_MAX, %rsp;
+       CFI_ADJUST_CFA_OFFSET(STACK_MAX);
        movq %rbp, STACK_RBP(%rsp);
        movq %rbx, STACK_RBX(%rsp);
        movq %r12, STACK_R12(%rsp);
        movq %r13, STACK_R13(%rsp);
        movq %r14, STACK_R14(%rsp);
        movq %r15, STACK_R15(%rsp);
+       CFI_REL_OFFSET(%rbp, STACK_RBP);
+       CFI_REL_OFFSET(%rbx, STACK_RBX);
+       CFI_REL_OFFSET(%r12, STACK_R12);
+       CFI_REL_OFFSET(%r13, STACK_R13);
+       CFI_REL_OFFSET(%r14, STACK_R14);
+       CFI_REL_OFFSET(%r15, STACK_R15);
 
        movq %rdx, STACK_NBLKS(%rsp);
        movq %rdi, STACK_STATEP(%rsp);
@@ -332,10 +330,18 @@ _gcry_whirlpool_transform_amd64:
        movq STACK_R13(%rsp), %r13;
        movq STACK_R14(%rsp), %r14;
        movq STACK_R15(%rsp), %r15;
+       CFI_RESTORE(%rbp);
+       CFI_RESTORE(%rbx);
+       CFI_RESTORE(%r12);
+       CFI_RESTORE(%r13);
+       CFI_RESTORE(%r14);
+       CFI_RESTORE(%r15);
        addq $STACK_MAX, %rsp;
+       CFI_ADJUST_CFA_OFFSET(-STACK_MAX);
 .Lskip:
        movl $(STACK_MAX + 8), %eax;
-       ret;
+       ret_spec_stop;
+       CFI_ENDPROC();
 ELF(.size _gcry_whirlpool_transform_amd64,.-_gcry_whirlpool_transform_amd64;)
 
 #endif
index 8a06939..ecb9a41 100644 (file)
@@ -1179,7 +1179,7 @@ whirlpool_init (void *ctx, unsigned int flags)
 
   memset (context, 0, sizeof (*context));
 
-  context->bctx.blocksize = BLOCK_SIZE;
+  context->bctx.blocksize_shift = _gcry_ctz(BLOCK_SIZE);
   context->bctx.bwrite = whirlpool_transform;
   if ((flags & GCRY_MD_FLAG_BUGEMU1))
     {
@@ -1494,12 +1494,16 @@ whirlpool_final (void *ctx)
   if (context->bctx.count > 32)
     {
       /* An extra block is necessary.  */
-      while (context->bctx.count < 64)
-       context->bctx.buf[context->bctx.count++] = 0;
+      if (context->bctx.count < 64)
+       memset (&context->bctx.buf[context->bctx.count], 0,
+               64 - context->bctx.count);
+      context->bctx.count = 64;
       whirlpool_write (context, NULL, 0);
     }
-  while (context->bctx.count < 32)
-    context->bctx.buf[context->bctx.count++] = 0;
+  if (context->bctx.count < 32)
+    memset (&context->bctx.buf[context->bctx.count], 0,
+           32 - context->bctx.count);
+  context->bctx.count = 32;
 
   /* Add length of message.  */
   length = context->bctx.buf + context->bctx.count;
@@ -1521,10 +1525,11 @@ whirlpool_read (void *ctx)
   return context->bctx.buf;
 }
 
-gcry_md_spec_t _gcry_digest_spec_whirlpool =
+const 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,
     sizeof (whirlpool_context_t)
   };
diff --git a/compat/Makefile.in b/compat/Makefile.in
deleted file mode 100644 (file)
index 3a2d403..0000000
+++ /dev/null
@@ -1,667 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Makefile for compat directory
-# Copyright (C) 2010 Free Software Foundation, Inc.
-#
-# 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 <http://www.gnu.org/licenses/>.
-
-# Process this file with automake to produce Makefile.in
-
-# We use this libcompat to work around problems with LIBOBJ stuff.
-# For example, we need some of the compat files also in tests/ but the
-# suggested way to do this (using the automake option subdir-objects)
-# leads to problems with "make distclean": The distclean target in
-# tests is run before the one src and it removes the deps files of the
-# libobj files which are in src.  Now when it comes to run make in src
-# the icnluded files are gone - bummer.  Instead of try to fix this
-# issue it seems better not to use subdir-objects but build them all
-# into a compat library and always link against that library.  This
-# also avoids the problem that a dependency on LTLIBOBJ is not setup
-# if -- disable-static was used.
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = compat
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am clock.c \
-       getpid.c $(top_srcdir)/build-aux/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-LTLIBRARIES = $(noinst_LTLIBRARIES)
-am_libcompat_la_OBJECTS = compat.lo
-libcompat_la_OBJECTS = $(am_libcompat_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-       $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(libcompat_la_SOURCES)
-DIST_SOURCES = $(libcompat_la_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-
-# Need to include ../src in addition to top_srcdir because gcrypt.h is
-# a built header.
-AM_CPPFLAGS = -I../src -I$(top_srcdir)/src $(GPG_ERROR_CFLAGS)
-noinst_LTLIBRARIES = libcompat.la
-
-# We only need one file so that the library is guaranteed to have at
-# least one member.
-libcompat_la_SOURCES = compat.c libcompat.h
-libcompat_la_DEPENDENCIES = @LTLIBOBJS@
-libcompat_la_LIBADD = @LTLIBOBJS@
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-               && { if test -f $@; then exit 0; else break; fi; }; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu compat/Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu compat/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-clean-noinstLTLIBRARIES:
-       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-       @list='$(noinst_LTLIBRARIES)'; \
-       locs=`for p in $$list; do echo $$p; done | \
-             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-             sort -u`; \
-       test -z "$$locs" || { \
-         echo rm -f $${locs}; \
-         rm -f $${locs}; \
-       }
-
-libcompat.la: $(libcompat_la_OBJECTS) $(libcompat_la_DEPENDENCIES) $(EXTRA_libcompat_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(LINK)  $(libcompat_la_OBJECTS) $(libcompat_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-       -rm -f *.$(OBJEXT)
-
-distclean-compile:
-       -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/clock.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getpid.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat.Plo@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-       $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       set x; \
-       here=`pwd`; \
-       $(am__define_uniq_tagged_files); \
-       shift; \
-       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-         test -n "$$unique" || unique=$$empty_fix; \
-         if test $$# -gt 0; then \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             "$$@" $$unique; \
-         else \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             $$unique; \
-         fi; \
-       fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       $(am__define_uniq_tagged_files); \
-       test -z "$(CTAGS_ARGS)$$unique" \
-         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$unique
-
-GTAGS:
-       here=`$(am__cd) $(top_builddir) && pwd` \
-         && $(am__cd) $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-       list='$(am__tagged_files)'; \
-       case "$(srcdir)" in \
-         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-         *) sdir=$(subdir)/$(srcdir) ;; \
-       esac; \
-       for i in $$list; do \
-         if test -f "$$i"; then \
-           echo "$(subdir)/$$i"; \
-         else \
-           echo "$$sdir/$$i"; \
-         fi; \
-       done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LTLIBRARIES)
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-       mostlyclean-am
-
-distclean: distclean-am
-       -rm -rf $(DEPDIR) ./$(DEPDIR)
-       -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-       distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -rf $(DEPDIR) ./$(DEPDIR)
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
-       clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
-       ctags-am distclean distclean-compile distclean-generic \
-       distclean-libtool distclean-tags distdir dvi dvi-am html \
-       html-am info info-am install install-am install-data \
-       install-data-am install-dvi install-dvi-am install-exec \
-       install-exec-am install-html install-html-am install-info \
-       install-info-am install-man install-pdf install-pdf-am \
-       install-ps install-ps-am install-strip installcheck \
-       installcheck-am installdirs maintainer-clean \
-       maintainer-clean-generic mostlyclean mostlyclean-compile \
-       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-       tags tags-am uninstall uninstall-am
-
-
-# AC_LIBOBJ files are:
-#    getpid.c
-#    clock.c
-#
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
index 8b001de..d7ca1b5 100644 (file)
@@ -30,9 +30,9 @@ _gcry_compat_identification (void)
   static const char blurb[] =
     "\n\n"
     "This is Libgcrypt " PACKAGE_VERSION " - The GNU Crypto Library\n"
+    "Copyright (C) 2012-2022 g10 Code GmbH\n"
+    "Copyright (C) 2013-2022 Jussi Kivilinna\n"
     "Copyright (C) 2000-2018 Free Software Foundation, Inc.\n"
-    "Copyright (C) 2012-2018 g10 Code GmbH\n"
-    "Copyright (C) 2013-2018 Jussi Kivilinna\n"
     "\n"
     "(" BUILD_REVISION " " BUILD_TIMESTAMP ")\n"
     "\n\n";
diff --git a/config.h.in b/config.h.in
deleted file mode 100644 (file)
index 24f9120..0000000
+++ /dev/null
@@ -1,673 +0,0 @@
-/* config.h.in.  Generated from configure.ac by autoheader.  */
-
-
-#ifndef _GCRYPT_CONFIG_H_INCLUDED
-#define _GCRYPT_CONFIG_H_INCLUDED
-
-/* Enable gpg-error's strerror macro for W32CE.  */
-#define GPG_ERR_ENABLE_ERRNO_MACROS 1
-
-
-/* Define if building universal (internal helper macro) */
-#undef AC_APPLE_UNIVERSAL_BUILD
-
-/* GIT commit id revision used to build this package */
-#undef BUILD_REVISION
-
-/* The time this package was configured for a build */
-#undef BUILD_TIMESTAMP
-
-/* configure did not test for endianness */
-#undef DISABLED_ENDIAN_CHECK
-
-/* Define if you don't want the default EGD socket name. For details see
-   cipher/rndegd.c */
-#undef EGD_SOCKET_NAME
-
-/* Enable support for Intel AES-NI instructions. */
-#undef ENABLE_AESNI_SUPPORT
-
-/* Enable support for ARMv8 Crypto Extension instructions. */
-#undef ENABLE_ARM_CRYPTO_SUPPORT
-
-/* Enable support for Intel AVX2 instructions. */
-#undef ENABLE_AVX2_SUPPORT
-
-/* Enable support for Intel AVX instructions. */
-#undef ENABLE_AVX_SUPPORT
-
-/* Enable support for Intel DRNG (RDRAND instruction). */
-#undef ENABLE_DRNG_SUPPORT
-
-/* Define to support an HMAC based integrity check */
-#undef ENABLE_HMAC_BINARY_CHECK
-
-/* Enable support for the jitter entropy collector. */
-#undef ENABLE_JENT_SUPPORT
-
-/* Enable support for ARM NEON instructions. */
-#undef ENABLE_NEON_SUPPORT
-
-/* Enable support for the PadLock engine. */
-#undef ENABLE_PADLOCK_SUPPORT
-
-/* Enable support for Intel PCLMUL instructions. */
-#undef ENABLE_PCLMUL_SUPPORT
-
-/* Enable support for Intel SSE4.1 instructions. */
-#undef ENABLE_SSE41_SUPPORT
-
-/* Define to use the GNU C visibility attribute. */
-#undef GCRY_USE_VISIBILITY
-
-/* The default error source for libgcrypt. */
-#undef GPG_ERR_SOURCE_DEFAULT
-
-/* Defined if ARM architecture is v6 or newer */
-#undef HAVE_ARM_ARCH_V6
-
-/* Define to 1 if you have the `atexit' function. */
-#undef HAVE_ATEXIT
-
-/* Defined if the mlock() call does not work */
-#undef HAVE_BROKEN_MLOCK
-
-/* Defined if compiler has '__builtin_bswap32' intrinsic */
-#undef HAVE_BUILTIN_BSWAP32
-
-/* Defined if compiler has '__builtin_bswap64' intrinsic */
-#undef HAVE_BUILTIN_BSWAP64
-
-/* Defined if compiler has '__builtin_ctz' intrinsic */
-#undef HAVE_BUILTIN_CTZ
-
-/* Defined if a `byte' is typedef'd */
-#undef HAVE_BYTE_TYPEDEF
-
-/* Define to 1 if you have the `clock' function. */
-#undef HAVE_CLOCK
-
-/* Define to 1 if you have the `clock_gettime' function. */
-#undef HAVE_CLOCK_GETTIME
-
-/* Defined if underlying assembler is compatible with ARMv8/Aarch64 assembly
-   implementations */
-#undef HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS
-
-/* Defined if underlying assembler is compatible with amd64 assembly
-   implementations */
-#undef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
-
-/* Defined if underlying assembler is compatible with ARM assembly
-   implementations */
-#undef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS
-
-/* Defined if underlying assembler is compatible with WIN64 assembly
-   implementations */
-#undef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
-
-/* Defined for Alpha platforms */
-#undef HAVE_CPU_ARCH_ALPHA
-
-/* Defined for ARM AArch64 platforms */
-#undef HAVE_CPU_ARCH_ARM
-
-/* Defined for M68k platforms */
-#undef HAVE_CPU_ARCH_M68K
-
-/* Defined for MIPS platforms */
-#undef HAVE_CPU_ARCH_MIPS
-
-/* Defined for PPC platforms */
-#undef HAVE_CPU_ARCH_PPC
-
-/* Defined for SPARC platforms */
-#undef HAVE_CPU_ARCH_SPARC
-
-/* Defined for the x86 platforms */
-#undef HAVE_CPU_ARCH_X86
-
-/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you
-   don't. */
-#undef HAVE_DECL_SYS_SIGLIST
-
-/* defined if the system supports a random device */
-#undef HAVE_DEV_RANDOM
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-#undef HAVE_DOPRNT
-
-/* defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2)
-   with special properties like no file modes */
-#undef HAVE_DOSISH_SYSTEM
-
-/* defined if we must run on a stupid file system */
-#undef HAVE_DRIVE_LETTERS
-
-/* Define to 1 if you have the `fcntl' function. */
-#undef HAVE_FCNTL
-
-/* Define to 1 if you have the `flockfile' function. */
-#undef HAVE_FLOCKFILE
-
-/* Define to 1 if you have the `ftruncate' function. */
-#undef HAVE_FTRUNCATE
-
-/* Define if inline asm memory barrier is supported */
-#undef HAVE_GCC_ASM_VOLATILE_MEMORY
-
-/* Defined if a GCC style "__attribute__ ((aligned (n))" is supported */
-#undef HAVE_GCC_ATTRIBUTE_ALIGNED
-
-/* Defined if a GCC style "__attribute__ ((may_alias))" is supported */
-#undef HAVE_GCC_ATTRIBUTE_MAY_ALIAS
-
-/* Defined if compiler supports "__attribute__ ((ms_abi))" function attribute
-   */
-#undef HAVE_GCC_ATTRIBUTE_MS_ABI
-
-/* Defined if a GCC style "__attribute__ ((packed))" is supported */
-#undef HAVE_GCC_ATTRIBUTE_PACKED
-
-/* Defined if compiler supports "__attribute__ ((sysv_abi))" function
-   attribute */
-#undef HAVE_GCC_ATTRIBUTE_SYSV_ABI
-
-/* Defined if default calling convention is 'ms_abi' */
-#undef HAVE_GCC_DEFAULT_ABI_IS_MS_ABI
-
-/* Defined if default calling convention is 'sysv_abi' */
-#undef HAVE_GCC_DEFAULT_ABI_IS_SYSV_ABI
-
-/* Defined if inline assembler supports AArch32 Crypto Extension instructions
-   */
-#undef HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO
-
-/* Defined if inline assembler supports AArch64 Crypto Extension instructions
-   */
-#undef HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO
-
-/* Defined if inline assembler supports AArch64 NEON instructions */
-#undef HAVE_GCC_INLINE_ASM_AARCH64_NEON
-
-/* Defined if inline assembler supports AVX instructions */
-#undef HAVE_GCC_INLINE_ASM_AVX
-
-/* Defined if inline assembler supports AVX2 instructions */
-#undef HAVE_GCC_INLINE_ASM_AVX2
-
-/* Defined if inline assembler supports BMI2 instructions */
-#undef HAVE_GCC_INLINE_ASM_BMI2
-
-/* Defined if inline assembler supports NEON instructions */
-#undef HAVE_GCC_INLINE_ASM_NEON
-
-/* Defined if inline assembler supports PCLMUL instructions */
-#undef HAVE_GCC_INLINE_ASM_PCLMUL
-
-/* Defined if inline assembler supports SSE4.1 instructions */
-#undef HAVE_GCC_INLINE_ASM_SSE41
-
-/* Defined if inline assembler supports SSSE3 instructions */
-#undef HAVE_GCC_INLINE_ASM_SSSE3
-
-/* Define to 1 if you have the `gethrtime' function. */
-#undef HAVE_GETHRTIME
-
-/* Define to 1 if you have the `getpagesize' function. */
-#undef HAVE_GETPAGESIZE
-
-/* Define to 1 if you have the `getpid' function. */
-#undef HAVE_GETPID
-
-/* Define to 1 if you have the `getrusage' function. */
-#undef HAVE_GETRUSAGE
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#undef HAVE_GETTIMEOFDAY
-
-/* Defined if underlying assembler is compatible with Intel syntax assembly
-   implementations */
-#undef HAVE_INTEL_SYNTAX_PLATFORM_AS
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-#undef HAVE_LIBRT
-
-/* Define to 1 if you have the `memmove' function. */
-#undef HAVE_MEMMOVE
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Defined if the system supports an mlock() call */
-#undef HAVE_MLOCK
-
-/* Define to 1 if you have the `mmap' function. */
-#undef HAVE_MMAP
-
-/* Defined if the GNU Pth is available */
-#undef HAVE_PTH
-
-/* Define if we have pthread. */
-#undef HAVE_PTHREAD
-
-/* Define to 1 if you have the `raise' function. */
-#undef HAVE_RAISE
-
-/* Define to 1 if you have the `rand' function. */
-#undef HAVE_RAND
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `stpcpy' function. */
-#undef HAVE_STPCPY
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#undef HAVE_STRCASECMP
-
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
-/* Define to 1 if you have the `stricmp' function. */
-#undef HAVE_STRICMP
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strtoul' function. */
-#undef HAVE_STRTOUL
-
-/* Define to 1 if you have the `syscall' function. */
-#undef HAVE_SYSCALL
-
-/* Define to 1 if you have the `sysconf' function. */
-#undef HAVE_SYSCONF
-
-/* Define to 1 if you have the `syslog' function. */
-#undef HAVE_SYSLOG
-
-/* Define to 1 if you have the <sys/capability.h> header file. */
-#undef HAVE_SYS_CAPABILITY_H
-
-/* Define to 1 if you have the <sys/mman.h> header file. */
-#undef HAVE_SYS_MMAN_H
-
-/* Define to 1 if you have the <sys/msg.h> header file. */
-#undef HAVE_SYS_MSG_H
-
-/* Define to 1 if you have the <sys/select.h> header file. */
-#undef HAVE_SYS_SELECT_H
-
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Defined if a `u16' is typedef'd */
-#undef HAVE_U16_TYPEDEF
-
-/* Defined if a `u32' is typedef'd */
-#undef HAVE_U32_TYPEDEF
-
-/* Define to 1 if the system has the type `uintptr_t'. */
-#undef HAVE_UINTPTR_T
-
-/* Defined if a `ulong' is typedef'd */
-#undef HAVE_ULONG_TYPEDEF
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Defined if a `ushort' is typedef'd */
-#undef HAVE_USHORT_TYPEDEF
-
-/* Defined if variable length arrays are supported */
-#undef HAVE_VLA
-
-/* Define to 1 if you have the `vprintf' function. */
-#undef HAVE_VPRINTF
-
-/* Defined if we run on WindowsCE */
-#undef HAVE_W32CE_SYSTEM
-
-/* Defined if we run on a W32 API based system */
-#undef HAVE_W32_SYSTEM
-
-/* Define to 1 if you have the `wait4' function. */
-#undef HAVE_WAIT4
-
-/* Define to 1 if you have the `waitpid' function. */
-#undef HAVE_WAITPID
-
-/* Define to 1 if you have the <winsock2.h> header file. */
-#undef HAVE_WINSOCK2_H
-
-/* Define to 1 if you have the <ws2tcpip.h> header file. */
-#undef HAVE_WS2TCPIP_H
-
-/* Defined if this is not a regular release */
-#undef IS_DEVELOPMENT_VERSION
-
-/* List of available cipher algorithms */
-#undef LIBGCRYPT_CIPHERS
-
-/* List of available digest algorithms */
-#undef LIBGCRYPT_DIGESTS
-
-/* List of available KDF algorithms */
-#undef LIBGCRYPT_KDFS
-
-/* List of available public key cipher algorithms */
-#undef LIBGCRYPT_PUBKEY_CIPHERS
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
-   */
-#undef LT_OBJDIR
-
-/* Define to use the (obsolete) malloc guarding feature */
-#undef M_GUARD
-
-/* defined to the name of the strong random device */
-#undef NAME_OF_DEV_RANDOM
-
-/* defined to the name of the weaker random device */
-#undef NAME_OF_DEV_URANDOM
-
-/* Name of this package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the home page for this package. */
-#undef PACKAGE_URL
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* A human readable text with the name of the OS */
-#undef PRINTABLE_OS_NAME
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#undef RETSIGTYPE
-
-/* The size of `uint64_t', as computed by sizeof. */
-#undef SIZEOF_UINT64_T
-
-/* The size of `unsigned int', as computed by sizeof. */
-#undef SIZEOF_UNSIGNED_INT
-
-/* The size of `unsigned long', as computed by sizeof. */
-#undef SIZEOF_UNSIGNED_LONG
-
-/* The size of `unsigned long long', as computed by sizeof. */
-#undef SIZEOF_UNSIGNED_LONG_LONG
-
-/* The size of `unsigned short', as computed by sizeof. */
-#undef SIZEOF_UNSIGNED_SHORT
-
-/* The size of `void *', as computed by sizeof. */
-#undef SIZEOF_VOID_P
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Defined if this module should be included */
-#undef USE_AES
-
-/* Defined if this module should be included */
-#undef USE_ARCFOUR
-
-/* Defined if this module should be included */
-#undef USE_BLAKE2
-
-/* Defined if this module should be included */
-#undef USE_BLOWFISH
-
-/* Defined if this module should be included */
-#undef USE_CAMELLIA
-
-/* define if capabilities should be used */
-#undef USE_CAPABILITIES
-
-/* Defined if this module should be included */
-#undef USE_CAST5
-
-/* Defined if this module should be included */
-#undef USE_CHACHA20
-
-/* Defined if this module should be included */
-#undef USE_CRC
-
-/* Defined if this module should be included */
-#undef USE_DES
-
-/* Defined if this module should be included */
-#undef USE_DSA
-
-/* Defined if this module should be included */
-#undef USE_ECC
-
-/* Defined if this module should be included */
-#undef USE_ELGAMAL
-
-/* Defined if the GNU Portable Thread Library should be used */
-#undef USE_GNU_PTH
-
-/* Defined if this module should be included */
-#undef USE_GOST28147
-
-/* Defined if this module should be included */
-#undef USE_GOST_R_3411_12
-
-/* Defined if this module should be included */
-#undef USE_GOST_R_3411_94
-
-/* Defined if this module should be included */
-#undef USE_IDEA
-
-/* Defined if this module should be included */
-#undef USE_MD2
-
-/* Defined if this module should be included */
-#undef USE_MD4
-
-/* Defined if this module should be included */
-#undef USE_MD5
-
-/* set this to limit filenames to the 8.3 format */
-#undef USE_ONLY_8DOT3
-
-/* Define to support the experimental random daemon */
-#undef USE_RANDOM_DAEMON
-
-/* Defined if this module should be included */
-#undef USE_RFC2268
-
-/* Defined if this module should be included */
-#undef USE_RMD160
-
-/* Defined if the EGD based RNG should be used. */
-#undef USE_RNDEGD
-
-/* Defined if the /dev/random RNG should be used. */
-#undef USE_RNDLINUX
-
-/* Defined if the default Unix RNG should be used. */
-#undef USE_RNDUNIX
-
-/* Defined if the Windows specific RNG should be used. */
-#undef USE_RNDW32
-
-/* Defined if the WindowsCE specific RNG should be used. */
-#undef USE_RNDW32CE
-
-/* Defined if this module should be included */
-#undef USE_RSA
-
-/* Defined if this module should be included */
-#undef USE_SALSA20
-
-/* Defined if this module should be included */
-#undef USE_SCRYPT
-
-/* Defined if this module should be included */
-#undef USE_SEED
-
-/* Defined if this module should be included */
-#undef USE_SERPENT
-
-/* Defined if this module should be included */
-#undef USE_SHA1
-
-/* Defined if this module should be included */
-#undef USE_SHA256
-
-/* Defined if this module should be included */
-#undef USE_SHA3
-
-/* Defined if this module should be included */
-#undef USE_SHA512
-
-/* Enable extensions on AIX 3, Interix.  */
-#ifndef _ALL_SOURCE
-# undef _ALL_SOURCE
-#endif
-/* Enable GNU extensions on systems that have them.  */
-#ifndef _GNU_SOURCE
-# undef _GNU_SOURCE
-#endif
-/* Enable threading extensions on Solaris.  */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# undef _POSIX_PTHREAD_SEMANTICS
-#endif
-/* Enable extensions on HP NonStop.  */
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
-#endif
-/* Enable general extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-
-
-/* Defined if this module should be included */
-#undef USE_TIGER
-
-/* Defined if this module should be included */
-#undef USE_TWOFISH
-
-/* Defined if this module should be included */
-#undef USE_WHIRLPOOL
-
-/* Version of this package */
-#undef VERSION
-
-/* Defined if compiled symbols have a leading underscore */
-#undef WITH_SYMBOL_UNDERSCORE
-
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
-   significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-#  define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-#  undef WORDS_BIGENDIAN
-# endif
-#endif
-
-/* Expose all libc features (__DARWIN_C_FULL). */
-#undef _DARWIN_C_SOURCE
-
-/* Define to 1 if on MINIX. */
-#undef _MINIX
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
-   this defined. */
-#undef _POSIX_1_SOURCE
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-#undef _POSIX_SOURCE
-
-/* To allow the use of Libgcrypt in multithreaded programs we have to use
-    special features from the library. */
-#ifndef _REENTRANT
-# define _REENTRANT 1
-#endif
-
-
-/* Define to supported assembler block keyword, if plain 'asm' was not
-   supported */
-#undef asm
-
-/* Define to empty if `const' does not conform to ANSI C. */
-#undef const
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
-   calls it, or to nothing if 'inline' is not supported under any name.  */
-#ifndef __cplusplus
-#undef inline
-#endif
-
-/* Define to `int' if <sys/types.h> does not define. */
-#undef pid_t
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-#undef size_t
-
-/* type to use in place of socklen_t if not defined */
-#undef socklen_t
-
-/* Define to the type of an unsigned integer type wide enough to hold a
-   pointer, if such a type exists, and if the system does not define it. */
-#undef uintptr_t
-
-
-#define _GCRYPT_IN_LIBGCRYPT 1
-
-/* If the configure check for endianness has been disabled, get it from
-   OS macros.  This is intended for making fat binary builds on OS X.  */
-#ifdef DISABLED_ENDIAN_CHECK
-# if defined(__BIG_ENDIAN__)
-#  define WORDS_BIGENDIAN 1
-# elif defined(__LITTLE_ENDIAN__)
-#  undef WORDS_BIGENDIAN
-# else
-#  error "No endianness found"
-# endif
-#endif /*DISABLED_ENDIAN_CHECK*/
-
-/* We basically use the original Camellia source.  Make sure the symbols
-   properly prefixed.  */
-#define CAMELLIA_EXT_SYM_PREFIX _gcry_
-
-#endif /*_GCRYPT_CONFIG_H_INCLUDED*/
-
diff --git a/configure b/configure
deleted file mode 100755 (executable)
index 8e8ebff..0000000
--- a/configure
+++ /dev/null
@@ -1,21788 +0,0 @@
-#! /bin/sh
-# From configure.ac Revision.
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libgcrypt 1.8.4.
-#
-# Report bugs to <http://bugs.gnupg.org>.
-#
-#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
-#
-#
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## -------------------- ##
-## M4sh Initialization. ##
-## -------------------- ##
-
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
-  emulate sh
-  NULLCMD=:
-  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-  setopt NO_GLOB_SUBST
-else
-  case `(set -o) 2>/dev/null` in #(
-  *posix*) :
-    set -o posix ;; #(
-  *) :
-     ;;
-esac
-fi
-
-
-as_nl='
-'
-export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
-    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
-  as_echo='print -r --'
-  as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
-  as_echo='printf %s\n'
-  as_echo_n='printf %s'
-else
-  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
-    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
-    as_echo_n='/usr/ucb/echo -n'
-  else
-    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
-    as_echo_n_body='eval
-      arg=$1;
-      case $arg in #(
-      *"$as_nl"*)
-       expr "X$arg" : "X\\(.*\\)$as_nl";
-       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
-      esac;
-      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
-    '
-    export as_echo_n_body
-    as_echo_n='sh -c $as_echo_n_body as_echo'
-  fi
-  export as_echo_body
-  as_echo='sh -c $as_echo_body as_echo'
-fi
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  PATH_SEPARATOR=:
-  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
-    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
-      PATH_SEPARATOR=';'
-  }
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.  Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" ""       $as_nl"
-
-# Find who we are.  Look in the path if we contain no directory separator.
-as_myself=
-case $0 in #((
-  *[\\/]* ) as_myself=$0 ;;
-  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-  done
-IFS=$as_save_IFS
-
-     ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
-  as_myself=$0
-fi
-if test ! -f "$as_myself"; then
-  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
-  exit 1
-fi
-
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there.  '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
-  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-# Use a proper internal environment variable to ensure we don't fall
-  # into an infinite loop, continuously re-executing ourselves.
-  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
-    _as_can_reexec=no; export _as_can_reexec;
-    # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
-  *v*x* | *x*v* ) as_opts=-vx ;;
-  *v* ) as_opts=-v ;;
-  *x* ) as_opts=-x ;;
-  * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
-  fi
-  # We don't want this to propagate to other subprocesses.
-          { _as_can_reexec=; unset _as_can_reexec;}
-if test "x$CONFIG_SHELL" = x; then
-  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
-  emulate sh
-  NULLCMD=:
-  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '\${1+\"\$@\"}'='\"\$@\"'
-  setopt NO_GLOB_SUBST
-else
-  case \`(set -o) 2>/dev/null\` in #(
-  *posix*) :
-    set -o posix ;; #(
-  *) :
-     ;;
-esac
-fi
-"
-  as_required="as_fn_return () { (exit \$1); }
-as_fn_success () { as_fn_return 0; }
-as_fn_failure () { as_fn_return 1; }
-as_fn_ret_success () { return 0; }
-as_fn_ret_failure () { return 1; }
-
-exitcode=0
-as_fn_success || { exitcode=1; echo as_fn_success failed.; }
-as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
-as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
-as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
-
-else
-  exitcode=1; echo positional parameters were not saved.
-fi
-test x\$exitcode = x0 || exit 1
-test -x / || exit 1"
-  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
-  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
-  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
-  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
-test \$(( 1 + 1 )) = 2 || exit 1
-
-  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
-    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
-    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
-    PATH=/empty FPATH=/empty; export PATH FPATH
-    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
-      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1"
-  if (eval "$as_required") 2>/dev/null; then :
-  as_have_required=yes
-else
-  as_have_required=no
-fi
-  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
-
-else
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-as_found=false
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  as_found=:
-  case $as_dir in #(
-        /*)
-          for as_base in sh bash ksh sh5; do
-            # Try only shells that exist, to save several forks.
-            as_shell=$as_dir/$as_base
-            if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
-                   { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
-  CONFIG_SHELL=$as_shell as_have_required=yes
-                  if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
-  break 2
-fi
-fi
-          done;;
-       esac
-  as_found=false
-done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
-             { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
-  CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
-IFS=$as_save_IFS
-
-
-      if test "x$CONFIG_SHELL" != x; then :
-  export CONFIG_SHELL
-             # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
-  *v*x* | *x*v* ) as_opts=-vx ;;
-  *v* ) as_opts=-v ;;
-  *x* ) as_opts=-x ;;
-  * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-exit 255
-fi
-
-    if test x$as_have_required = xno; then :
-  $as_echo "$0: This script requires a shell more modern than all"
-  $as_echo "$0: the shells that I found on your system."
-  if test x${ZSH_VERSION+set} = xset ; then
-    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
-    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
-  else
-    $as_echo "$0: Please tell bug-autoconf@gnu.org and
-$0: http://bugs.gnupg.org about your system, including any
-$0: error possibly output before this message. Then install
-$0: a modern shell, or manually run the script under such a
-$0: shell if you do have one."
-  fi
-  exit 1
-fi
-fi
-fi
-SHELL=${CONFIG_SHELL-/bin/sh}
-export SHELL
-# Unset more variables known to interfere with behavior of common tools.
-CLICOLOR_FORCE= GREP_OPTIONS=
-unset CLICOLOR_FORCE GREP_OPTIONS
-
-## --------------------- ##
-## M4sh Shell Functions. ##
-## --------------------- ##
-# as_fn_unset VAR
-# ---------------
-# Portably unset VAR.
-as_fn_unset ()
-{
-  { eval $1=; unset $1;}
-}
-as_unset=as_fn_unset
-
-# as_fn_set_status STATUS
-# -----------------------
-# Set $? to STATUS, without forking.
-as_fn_set_status ()
-{
-  return $1
-} # as_fn_set_status
-
-# as_fn_exit STATUS
-# -----------------
-# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
-as_fn_exit ()
-{
-  set +e
-  as_fn_set_status $1
-  exit $1
-} # as_fn_exit
-
-# as_fn_mkdir_p
-# -------------
-# Create "$as_dir" as a directory, including parents if necessary.
-as_fn_mkdir_p ()
-{
-
-  case $as_dir in #(
-  -*) as_dir=./$as_dir;;
-  esac
-  test -d "$as_dir" || eval $as_mkdir_p || {
-    as_dirs=
-    while :; do
-      case $as_dir in #(
-      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
-      *) as_qdir=$as_dir;;
-      esac
-      as_dirs="'$as_qdir' $as_dirs"
-      as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$as_dir" : 'X\(//\)[^/]' \| \
-        X"$as_dir" : 'X\(//\)$' \| \
-        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-      test -d "$as_dir" && break
-    done
-    test -z "$as_dirs" || eval "mkdir $as_dirs"
-  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
-
-
-} # as_fn_mkdir_p
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
-  test -f "$1" && test -x "$1"
-} # as_fn_executable_p
-# as_fn_append VAR VALUE
-# ----------------------
-# Append the text in VALUE to the end of the definition contained in VAR. Take
-# advantage of any shell optimizations that allow amortized linear growth over
-# repeated appends, instead of the typical quadratic growth present in naive
-# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
-  eval 'as_fn_append ()
-  {
-    eval $1+=\$2
-  }'
-else
-  as_fn_append ()
-  {
-    eval $1=\$$1\$2
-  }
-fi # as_fn_append
-
-# as_fn_arith ARG...
-# ------------------
-# Perform arithmetic evaluation on the ARGs, and store the result in the
-# global $as_val. Take advantage of shells that can avoid forks. The arguments
-# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
-  eval 'as_fn_arith ()
-  {
-    as_val=$(( $* ))
-  }'
-else
-  as_fn_arith ()
-  {
-    as_val=`expr "$@" || test $? -eq 1`
-  }
-fi # as_fn_arith
-
-
-# as_fn_error STATUS ERROR [LINENO LOG_FD]
-# ----------------------------------------
-# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with STATUS, using 1 if that was 0.
-as_fn_error ()
-{
-  as_status=$1; test $as_status -eq 0 && as_status=1
-  if test "$4"; then
-    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
-  fi
-  $as_echo "$as_me: error: $2" >&2
-  as_fn_exit $as_status
-} # as_fn_error
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
-  as_dirname=dirname
-else
-  as_dirname=false
-fi
-
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{
-           s//\1/
-           q
-         }
-         /^X\/\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\/\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-
-  as_lineno_1=$LINENO as_lineno_1a=$LINENO
-  as_lineno_2=$LINENO as_lineno_2a=$LINENO
-  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
-  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
-  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
-  sed -n '
-    p
-    /[$]LINENO/=
-  ' <$as_myself |
-    sed '
-      s/[$]LINENO.*/&-/
-      t lineno
-      b
-      :lineno
-      N
-      :loop
-      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
-      t loop
-      s/-\n.*//
-    ' >$as_me.lineno &&
-  chmod +x "$as_me.lineno" ||
-    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
-
-  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
-  # already done that, so ensure we don't try to do so again and fall
-  # in an infinite loop.  This has already happened in practice.
-  _as_can_reexec=no; export _as_can_reexec
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensitive to this).
-  . "./$as_me.lineno"
-  # Exit status is that of the last command.
-  exit
-}
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in #(((((
--n*)
-  case `echo 'xy\c'` in
-  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
-  xy)  ECHO_C='\c';;
-  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
-       ECHO_T='        ';;
-  esac;;
-*)
-  ECHO_N='-n';;
-esac
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
-  rm -f conf$$.dir/conf$$.file
-else
-  rm -f conf$$.dir
-  mkdir conf$$.dir 2>/dev/null
-fi
-if (echo >conf$$.file) 2>/dev/null; then
-  if ln -s conf$$.file conf$$ 2>/dev/null; then
-    as_ln_s='ln -s'
-    # ... but there are two gotchas:
-    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
-    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -pR'.
-    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -pR'
-  elif ln conf$$.file conf$$ 2>/dev/null; then
-    as_ln_s=ln
-  else
-    as_ln_s='cp -pR'
-  fi
-else
-  as_ln_s='cp -pR'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p='mkdir -p "$as_dir"'
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-
-test -n "$DJDIR" || exec 7<&0 </dev/null
-exec 6>&1
-
-# Name of the host.
-# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_clean_files=
-ac_config_libobj_dir=.
-LIBOBJS=
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-
-# Identity of this package.
-PACKAGE_NAME='libgcrypt'
-PACKAGE_TARNAME='libgcrypt'
-PACKAGE_VERSION='1.8.4'
-PACKAGE_STRING='libgcrypt 1.8.4'
-PACKAGE_BUGREPORT='http://bugs.gnupg.org'
-PACKAGE_URL=''
-
-ac_unique_file="src/libgcrypt.vers"
-ac_config_libobj_dir=compat
-# Factoring default headers for most tests.
-ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-# endif
-#endif
-#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-#  include <memory.h>
-# endif
-# include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif"
-
-ac_subst_vars='am__EXEEXT_FALSE
-am__EXEEXT_TRUE
-LTLIBOBJS
-BUILD_TIMESTAMP
-BUILD_FILEVERSION
-BUILD_REVISION
-BUILD_DOC_FALSE
-BUILD_DOC_TRUE
-GCRYPT_HWF_MODULES
-LIBGCRYPT_DIGESTS
-LIBGCRYPT_PUBKEY_CIPHERS
-LIBGCRYPT_CIPHERS
-GCRYPT_RANDOM
-GCRYPT_KDFS
-GCRYPT_DIGESTS
-GCRYPT_PUBKEY_CIPHERS
-GCRYPT_CIPHERS
-LIBGCRYPT_THREAD_MODULES
-LIBGCRYPT_CONFIG_HOST
-LIBGCRYPT_CONFIG_CFLAGS
-LIBGCRYPT_CONFIG_LIBS
-LIBGCRYPT_CONFIG_API_VERSION
-NOEXECSTACK_FLAGS
-CROSS_COMPILING_FALSE
-CROSS_COMPILING_TRUE
-DL_LIBS
-LIBOBJS
-MPI_MOD_C_UDIV_QRNND_FALSE
-MPI_MOD_C_UDIV_QRNND_TRUE
-MPI_MOD_C_UDIV_FALSE
-MPI_MOD_C_UDIV_TRUE
-MPI_MOD_C_MPIH_RSHIFT_FALSE
-MPI_MOD_C_MPIH_RSHIFT_TRUE
-MPI_MOD_C_MPIH_LSHIFT_FALSE
-MPI_MOD_C_MPIH_LSHIFT_TRUE
-MPI_MOD_C_MPIH_MUL3_FALSE
-MPI_MOD_C_MPIH_MUL3_TRUE
-MPI_MOD_C_MPIH_MUL2_FALSE
-MPI_MOD_C_MPIH_MUL2_TRUE
-MPI_MOD_C_MPIH_MUL1_FALSE
-MPI_MOD_C_MPIH_MUL1_TRUE
-MPI_MOD_C_MPIH_SUB1_FALSE
-MPI_MOD_C_MPIH_SUB1_TRUE
-MPI_MOD_C_MPIH_ADD1_FALSE
-MPI_MOD_C_MPIH_ADD1_TRUE
-MPI_MOD_ASM_UDIV_QRNND_FALSE
-MPI_MOD_ASM_UDIV_QRNND_TRUE
-MPI_MOD_ASM_UDIV_FALSE
-MPI_MOD_ASM_UDIV_TRUE
-MPI_MOD_ASM_MPIH_RSHIFT_FALSE
-MPI_MOD_ASM_MPIH_RSHIFT_TRUE
-MPI_MOD_ASM_MPIH_LSHIFT_FALSE
-MPI_MOD_ASM_MPIH_LSHIFT_TRUE
-MPI_MOD_ASM_MPIH_MUL3_FALSE
-MPI_MOD_ASM_MPIH_MUL3_TRUE
-MPI_MOD_ASM_MPIH_MUL2_FALSE
-MPI_MOD_ASM_MPIH_MUL2_TRUE
-MPI_MOD_ASM_MPIH_MUL1_FALSE
-MPI_MOD_ASM_MPIH_MUL1_TRUE
-MPI_MOD_ASM_MPIH_SUB1_FALSE
-MPI_MOD_ASM_MPIH_SUB1_TRUE
-MPI_MOD_ASM_MPIH_ADD1_FALSE
-MPI_MOD_ASM_MPIH_ADD1_TRUE
-MPI_SFLAGS
-FALLBACK_SOCKLEN_T
-SYS_SOCKET_H
-INSERT_SYS_SELECT_H
-PTH_LIBS
-PTH_CFLAGS
-PTH_CONFIG
-GPG_ERROR_MT_LIBS
-GPG_ERROR_MT_CFLAGS
-GPG_ERROR_LIBS
-GPG_ERROR_CFLAGS
-GPG_ERROR_CONFIG
-HAVE_LD_VERSION_SCRIPT_FALSE
-HAVE_LD_VERSION_SCRIPT_TRUE
-ENABLE_O_FLAG_MUNGING_FALSE
-ENABLE_O_FLAG_MUNGING_TRUE
-RUN_LARGE_DATA_TESTS
-USE_RANDOM_DAEMON_FALSE
-USE_RANDOM_DAEMON_TRUE
-emacs_local_vars_end
-emacs_local_vars_read_only
-emacs_local_vars_begin
-HAVE_W32CE_SYSTEM_FALSE
-HAVE_W32CE_SYSTEM_TRUE
-HAVE_W32_SYSTEM_FALSE
-HAVE_W32_SYSTEM_TRUE
-RC
-OTOOL64
-OTOOL
-LIPO
-NMEDIT
-DSYMUTIL
-MANIFEST_TOOL
-RANLIB
-ac_ct_AR
-AR
-LN_S
-NM
-ac_ct_DUMPBIN
-DUMPBIN
-LD
-FGREP
-SED
-LIBTOOL
-OBJDUMP
-DLLTOOL
-AS
-CC_FOR_BUILD
-EGREP
-GREP
-am__fastdepCCAS_FALSE
-am__fastdepCCAS_TRUE
-CCASDEPMODE
-CCASFLAGS
-CCAS
-CPP
-am__fastdepCC_FALSE
-am__fastdepCC_TRUE
-CCDEPMODE
-am__nodep
-AMDEPBACKSLASH
-AMDEP_FALSE
-AMDEP_TRUE
-am__quote
-am__include
-DEPDIR
-OBJEXT
-EXEEXT
-ac_ct_CC
-CPPFLAGS
-LDFLAGS
-CFLAGS
-CC
-VERSION_NUMBER
-LIBGCRYPT_LT_REVISION
-LIBGCRYPT_LT_AGE
-LIBGCRYPT_LT_CURRENT
-SYSROOT
-MAINT
-MAINTAINER_MODE_FALSE
-MAINTAINER_MODE_TRUE
-host_os
-host_vendor
-host_cpu
-host
-build_os
-build_vendor
-build_cpu
-build
-AM_BACKSLASH
-AM_DEFAULT_VERBOSITY
-AM_DEFAULT_V
-AM_V
-am__untar
-am__tar
-AMTAR
-am__leading_dot
-SET_MAKE
-AWK
-mkdir_p
-MKDIR_P
-INSTALL_STRIP_PROGRAM
-STRIP
-install_sh
-MAKEINFO
-AUTOHEADER
-AUTOMAKE
-AUTOCONF
-ACLOCAL
-VERSION
-PACKAGE
-CYGPATH_W
-am__isrc
-INSTALL_DATA
-INSTALL_SCRIPT
-INSTALL_PROGRAM
-target_alias
-host_alias
-build_alias
-LIBS
-ECHO_T
-ECHO_N
-ECHO_C
-DEFS
-mandir
-localedir
-libdir
-psdir
-pdfdir
-dvidir
-htmldir
-infodir
-docdir
-oldincludedir
-includedir
-localstatedir
-sharedstatedir
-sysconfdir
-datadir
-datarootdir
-libexecdir
-sbindir
-bindir
-program_transform_name
-prefix
-exec_prefix
-PACKAGE_URL
-PACKAGE_BUGREPORT
-PACKAGE_STRING
-PACKAGE_VERSION
-PACKAGE_TARNAME
-PACKAGE_NAME
-PATH_SEPARATOR
-SHELL'
-ac_subst_files=''
-ac_user_opts='
-enable_option_checking
-enable_silent_rules
-enable_maintainer_mode
-enable_dependency_tracking
-enable_static
-enable_shared
-with_pic
-enable_fast_install
-with_gnu_ld
-with_sysroot
-enable_libtool_lock
-enable_endian_check
-enable_ciphers
-enable_pubkey_ciphers
-enable_digests
-enable_kdfs
-enable_random
-enable_dev_random
-with_egd_socket
-enable_random_daemon
-enable_asm
-enable_m_guard
-enable_large_data_tests
-with_capabilities
-enable_hmac_binary_check
-enable_jent_support
-enable_padlock_support
-enable_aesni_support
-enable_pclmul_support
-enable_sse41_support
-enable_drng_support
-enable_avx_support
-enable_avx2_support
-enable_neon_support
-enable_arm_crypto_support
-enable_O_flag_munging
-enable_amd64_as_feature_detection
-enable_ld_version_script
-with_libgpg_error_prefix
-with_gpg_error_prefix
-with_pth_prefix
-enable_mpi_path
-enable_optimization
-enable_noexecstack
-enable_doc
-enable_build_timestamp
-'
-      ac_precious_vars='build_alias
-host_alias
-target_alias
-SYSROOT
-CC
-CFLAGS
-LDFLAGS
-LIBS
-CPPFLAGS
-CPP
-CCAS
-CCASFLAGS
-CC_FOR_BUILD'
-
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-ac_unrecognized_opts=
-ac_unrecognized_sep=
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-# (The list follows the same order as the GNU Coding Standards.)
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datarootdir='${prefix}/share'
-datadir='${datarootdir}'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
-infodir='${datarootdir}/info'
-htmldir='${docdir}'
-dvidir='${docdir}'
-pdfdir='${docdir}'
-psdir='${docdir}'
-libdir='${exec_prefix}/lib'
-localedir='${datarootdir}/locale'
-mandir='${datarootdir}/man'
-
-ac_prev=
-ac_dashdash=
-for ac_option
-do
-  # If the previous option needs an argument, assign it.
-  if test -n "$ac_prev"; then
-    eval $ac_prev=\$ac_option
-    ac_prev=
-    continue
-  fi
-
-  case $ac_option in
-  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
-  *=)   ac_optarg= ;;
-  *)    ac_optarg=yes ;;
-  esac
-
-  # Accept the important Cygnus configure options, so we can diagnose typos.
-
-  case $ac_dashdash$ac_option in
-  --)
-    ac_dashdash=yes ;;
-
-  -bindir | --bindir | --bindi | --bind | --bin | --bi)
-    ac_prev=bindir ;;
-  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
-    bindir=$ac_optarg ;;
-
-  -build | --build | --buil | --bui | --bu)
-    ac_prev=build_alias ;;
-  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
-    build_alias=$ac_optarg ;;
-
-  -cache-file | --cache-file | --cache-fil | --cache-fi \
-  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
-    ac_prev=cache_file ;;
-  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
-  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
-    cache_file=$ac_optarg ;;
-
-  --config-cache | -C)
-    cache_file=config.cache ;;
-
-  -datadir | --datadir | --datadi | --datad)
-    ac_prev=datadir ;;
-  -datadir=* | --datadir=* | --datadi=* | --datad=*)
-    datadir=$ac_optarg ;;
-
-  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
-  | --dataroo | --dataro | --datar)
-    ac_prev=datarootdir ;;
-  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
-  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
-    datarootdir=$ac_optarg ;;
-
-  -disable-* | --disable-*)
-    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
-      as_fn_error $? "invalid feature name: $ac_useropt"
-    ac_useropt_orig=$ac_useropt
-    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
-    case $ac_user_opts in
-      *"
-"enable_$ac_useropt"
-"*) ;;
-      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
-        ac_unrecognized_sep=', ';;
-    esac
-    eval enable_$ac_useropt=no ;;
-
-  -docdir | --docdir | --docdi | --doc | --do)
-    ac_prev=docdir ;;
-  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
-    docdir=$ac_optarg ;;
-
-  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
-    ac_prev=dvidir ;;
-  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
-    dvidir=$ac_optarg ;;
-
-  -enable-* | --enable-*)
-    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
-      as_fn_error $? "invalid feature name: $ac_useropt"
-    ac_useropt_orig=$ac_useropt
-    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
-    case $ac_user_opts in
-      *"
-"enable_$ac_useropt"
-"*) ;;
-      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
-        ac_unrecognized_sep=', ';;
-    esac
-    eval enable_$ac_useropt=\$ac_optarg ;;
-
-  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
-  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
-  | --exec | --exe | --ex)
-    ac_prev=exec_prefix ;;
-  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
-  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
-  | --exec=* | --exe=* | --ex=*)
-    exec_prefix=$ac_optarg ;;
-
-  -gas | --gas | --ga | --g)
-    # Obsolete; use --with-gas.
-    with_gas=yes ;;
-
-  -help | --help | --hel | --he | -h)
-    ac_init_help=long ;;
-  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
-    ac_init_help=recursive ;;
-  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
-    ac_init_help=short ;;
-
-  -host | --host | --hos | --ho)
-    ac_prev=host_alias ;;
-  -host=* | --host=* | --hos=* | --ho=*)
-    host_alias=$ac_optarg ;;
-
-  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
-    ac_prev=htmldir ;;
-  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
-  | --ht=*)
-    htmldir=$ac_optarg ;;
-
-  -includedir | --includedir | --includedi | --included | --include \
-  | --includ | --inclu | --incl | --inc)
-    ac_prev=includedir ;;
-  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
-  | --includ=* | --inclu=* | --incl=* | --inc=*)
-    includedir=$ac_optarg ;;
-
-  -infodir | --infodir | --infodi | --infod | --info | --inf)
-    ac_prev=infodir ;;
-  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
-    infodir=$ac_optarg ;;
-
-  -libdir | --libdir | --libdi | --libd)
-    ac_prev=libdir ;;
-  -libdir=* | --libdir=* | --libdi=* | --libd=*)
-    libdir=$ac_optarg ;;
-
-  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
-  | --libexe | --libex | --libe)
-    ac_prev=libexecdir ;;
-  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
-  | --libexe=* | --libex=* | --libe=*)
-    libexecdir=$ac_optarg ;;
-
-  -localedir | --localedir | --localedi | --localed | --locale)
-    ac_prev=localedir ;;
-  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
-    localedir=$ac_optarg ;;
-
-  -localstatedir | --localstatedir | --localstatedi | --localstated \
-  | --localstate | --localstat | --localsta | --localst | --locals)
-    ac_prev=localstatedir ;;
-  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
-  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
-    localstatedir=$ac_optarg ;;
-
-  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
-    ac_prev=mandir ;;
-  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
-    mandir=$ac_optarg ;;
-
-  -nfp | --nfp | --nf)
-    # Obsolete; use --without-fp.
-    with_fp=no ;;
-
-  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
-  | --no-cr | --no-c | -n)
-    no_create=yes ;;
-
-  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
-  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
-    no_recursion=yes ;;
-
-  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
-  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
-  | --oldin | --oldi | --old | --ol | --o)
-    ac_prev=oldincludedir ;;
-  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
-  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
-  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
-    oldincludedir=$ac_optarg ;;
-
-  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
-    ac_prev=prefix ;;
-  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
-    prefix=$ac_optarg ;;
-
-  -program-prefix | --program-prefix | --program-prefi | --program-pref \
-  | --program-pre | --program-pr | --program-p)
-    ac_prev=program_prefix ;;
-  -program-prefix=* | --program-prefix=* | --program-prefi=* \
-  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
-    program_prefix=$ac_optarg ;;
-
-  -program-suffix | --program-suffix | --program-suffi | --program-suff \
-  | --program-suf | --program-su | --program-s)
-    ac_prev=program_suffix ;;
-  -program-suffix=* | --program-suffix=* | --program-suffi=* \
-  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
-    program_suffix=$ac_optarg ;;
-
-  -program-transform-name | --program-transform-name \
-  | --program-transform-nam | --program-transform-na \
-  | --program-transform-n | --program-transform- \
-  | --program-transform | --program-transfor \
-  | --program-transfo | --program-transf \
-  | --program-trans | --program-tran \
-  | --progr-tra | --program-tr | --program-t)
-    ac_prev=program_transform_name ;;
-  -program-transform-name=* | --program-transform-name=* \
-  | --program-transform-nam=* | --program-transform-na=* \
-  | --program-transform-n=* | --program-transform-=* \
-  | --program-transform=* | --program-transfor=* \
-  | --program-transfo=* | --program-transf=* \
-  | --program-trans=* | --program-tran=* \
-  | --progr-tra=* | --program-tr=* | --program-t=*)
-    program_transform_name=$ac_optarg ;;
-
-  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
-    ac_prev=pdfdir ;;
-  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
-    pdfdir=$ac_optarg ;;
-
-  -psdir | --psdir | --psdi | --psd | --ps)
-    ac_prev=psdir ;;
-  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
-    psdir=$ac_optarg ;;
-
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil)
-    silent=yes ;;
-
-  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
-    ac_prev=sbindir ;;
-  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
-  | --sbi=* | --sb=*)
-    sbindir=$ac_optarg ;;
-
-  -sharedstatedir | --sharedstatedir | --sharedstatedi \
-  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
-  | --sharedst | --shareds | --shared | --share | --shar \
-  | --sha | --sh)
-    ac_prev=sharedstatedir ;;
-  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
-  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
-  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
-  | --sha=* | --sh=*)
-    sharedstatedir=$ac_optarg ;;
-
-  -site | --site | --sit)
-    ac_prev=site ;;
-  -site=* | --site=* | --sit=*)
-    site=$ac_optarg ;;
-
-  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
-    ac_prev=srcdir ;;
-  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
-    srcdir=$ac_optarg ;;
-
-  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
-  | --syscon | --sysco | --sysc | --sys | --sy)
-    ac_prev=sysconfdir ;;
-  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
-  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
-    sysconfdir=$ac_optarg ;;
-
-  -target | --target | --targe | --targ | --tar | --ta | --t)
-    ac_prev=target_alias ;;
-  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
-    target_alias=$ac_optarg ;;
-
-  -v | -verbose | --verbose | --verbos | --verbo | --verb)
-    verbose=yes ;;
-
-  -version | --version | --versio | --versi | --vers | -V)
-    ac_init_version=: ;;
-
-  -with-* | --with-*)
-    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
-      as_fn_error $? "invalid package name: $ac_useropt"
-    ac_useropt_orig=$ac_useropt
-    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
-    case $ac_user_opts in
-      *"
-"with_$ac_useropt"
-"*) ;;
-      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
-        ac_unrecognized_sep=', ';;
-    esac
-    eval with_$ac_useropt=\$ac_optarg ;;
-
-  -without-* | --without-*)
-    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
-      as_fn_error $? "invalid package name: $ac_useropt"
-    ac_useropt_orig=$ac_useropt
-    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
-    case $ac_user_opts in
-      *"
-"with_$ac_useropt"
-"*) ;;
-      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
-        ac_unrecognized_sep=', ';;
-    esac
-    eval with_$ac_useropt=no ;;
-
-  --x)
-    # Obsolete; use --with-x.
-    with_x=yes ;;
-
-  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
-  | --x-incl | --x-inc | --x-in | --x-i)
-    ac_prev=x_includes ;;
-  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
-  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
-    x_includes=$ac_optarg ;;
-
-  -x-libraries | --x-libraries | --x-librarie | --x-librari \
-  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
-    ac_prev=x_libraries ;;
-  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
-  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
-    x_libraries=$ac_optarg ;;
-
-  -*) as_fn_error $? "unrecognized option: \`$ac_option'
-Try \`$0 --help' for more information"
-    ;;
-
-  *=*)
-    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
-    # Reject names that are not valid shell variable names.
-    case $ac_envvar in #(
-      '' | [0-9]* | *[!_$as_cr_alnum]* )
-      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
-    esac
-    eval $ac_envvar=\$ac_optarg
-    export $ac_envvar ;;
-
-  *)
-    # FIXME: should be removed in autoconf 3.0.
-    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
-    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
-    ;;
-
-  esac
-done
-
-if test -n "$ac_prev"; then
-  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
-  as_fn_error $? "missing argument to $ac_option"
-fi
-
-if test -n "$ac_unrecognized_opts"; then
-  case $enable_option_checking in
-    no) ;;
-    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
-    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
-  esac
-fi
-
-# Check all directory arguments for consistency.
-for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
-               datadir sysconfdir sharedstatedir localstatedir includedir \
-               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-               libdir localedir mandir
-do
-  eval ac_val=\$$ac_var
-  # Remove trailing slashes.
-  case $ac_val in
-    */ )
-      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
-      eval $ac_var=\$ac_val;;
-  esac
-  # Be sure to have absolute directory names.
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* )  continue;;
-    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
-  esac
-  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
-  if test "x$build_alias" = x; then
-    cross_compiling=maybe
-  elif test "x$build_alias" != "x$host_alias"; then
-    cross_compiling=yes
-  fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-ac_pwd=`pwd` && test -n "$ac_pwd" &&
-ac_ls_di=`ls -di .` &&
-ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
-  as_fn_error $? "working directory cannot be determined"
-test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
-  as_fn_error $? "pwd does not report name of working directory"
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
-  ac_srcdir_defaulted=yes
-  # Try the directory containing this script, then the parent directory.
-  ac_confdir=`$as_dirname -- "$as_myself" ||
-$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$as_myself" : 'X\(//\)[^/]' \| \
-        X"$as_myself" : 'X\(//\)$' \| \
-        X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-  srcdir=$ac_confdir
-  if test ! -r "$srcdir/$ac_unique_file"; then
-    srcdir=..
-  fi
-else
-  ac_srcdir_defaulted=no
-fi
-if test ! -r "$srcdir/$ac_unique_file"; then
-  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
-  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
-fi
-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
-ac_abs_confdir=`(
-       cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
-       pwd)`
-# When building in place, set srcdir=.
-if test "$ac_abs_confdir" = "$ac_pwd"; then
-  srcdir=.
-fi
-# Remove unnecessary trailing slashes from srcdir.
-# Double slashes in file names in object file debugging info
-# mess up M-x gdb in Emacs.
-case $srcdir in
-*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
-esac
-for ac_var in $ac_precious_vars; do
-  eval ac_env_${ac_var}_set=\${${ac_var}+set}
-  eval ac_env_${ac_var}_value=\$${ac_var}
-  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
-  eval ac_cv_env_${ac_var}_value=\$${ac_var}
-done
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
-  # Omit some internal or obsolete options to make the list less imposing.
-  # This message is too long to be a string in the A/UX 3.1 sh.
-  cat <<_ACEOF
-\`configure' configures libgcrypt 1.8.4 to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE.  See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
-  -h, --help              display this help and exit
-      --help=short        display options specific to this package
-      --help=recursive    display the short help of all the included packages
-  -V, --version           display version information and exit
-  -q, --quiet, --silent   do not print \`checking ...' messages
-      --cache-file=FILE   cache test results in FILE [disabled]
-  -C, --config-cache      alias for \`--cache-file=config.cache'
-  -n, --no-create         do not create output files
-      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
-
-Installation directories:
-  --prefix=PREFIX         install architecture-independent files in PREFIX
-                          [$ac_default_prefix]
-  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
-                          [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
-  --bindir=DIR            user executables [EPREFIX/bin]
-  --sbindir=DIR           system admin executables [EPREFIX/sbin]
-  --libexecdir=DIR        program executables [EPREFIX/libexec]
-  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
-  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
-  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
-  --libdir=DIR            object code libraries [EPREFIX/lib]
-  --includedir=DIR        C header files [PREFIX/include]
-  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
-  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
-  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
-  --infodir=DIR           info documentation [DATAROOTDIR/info]
-  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
-  --mandir=DIR            man documentation [DATAROOTDIR/man]
-  --docdir=DIR            documentation root [DATAROOTDIR/doc/libgcrypt]
-  --htmldir=DIR           html documentation [DOCDIR]
-  --dvidir=DIR            dvi documentation [DOCDIR]
-  --pdfdir=DIR            pdf documentation [DOCDIR]
-  --psdir=DIR             ps documentation [DOCDIR]
-_ACEOF
-
-  cat <<\_ACEOF
-
-Program names:
-  --program-prefix=PREFIX            prepend PREFIX to installed program names
-  --program-suffix=SUFFIX            append SUFFIX to installed program names
-  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
-
-System types:
-  --build=BUILD     configure for building on BUILD [guessed]
-  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
-  case $ac_init_help in
-     short | recursive ) echo "Configuration of libgcrypt 1.8.4:";;
-   esac
-  cat <<\_ACEOF
-
-Optional Features:
-  --disable-option-checking  ignore unrecognized --enable/--with options
-  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
-  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
-  --enable-silent-rules   less verbose build output (undo: "make V=1")
-  --disable-silent-rules  verbose build output (undo: "make V=0")
-  --enable-maintainer-mode
-                          enable make rules and dependencies not useful (and
-                          sometimes confusing) to the casual installer
-  --enable-dependency-tracking
-                          do not reject slow dependency extractors
-  --disable-dependency-tracking
-                          speeds up one-time build
-  --enable-static[=PKGS]  build static libraries [default=no]
-  --enable-shared[=PKGS]  build shared libraries [default=yes]
-  --enable-fast-install[=PKGS]
-                          optimize for fast installation [default=yes]
-  --disable-libtool-lock  avoid locking (might break parallel builds)
-  --disable-endian-check  disable the endian check and trust the OS provided
-                          macros
-  --enable-ciphers=ciphers
-                          select the symmetric ciphers to include
-  --enable-pubkey-ciphers=ciphers
-                          select the public-key ciphers to include
-  --enable-digests=digests
-                          select the message digests to include
-  --enable-kfds=kdfs      select the KDFs to include
-  --enable-random=name    select which random number generator to use
-  --disable-dev-random    disable the use of dev random
-  --enable-random-daemon  Build and support the experimental gcryptrnd
-  --disable-asm           Disable MPI assembler modules
-  --enable-m-guard        Enable memory guard facility
-  --enable-large-data-tests
-                          Enable the real long ruinning large data tests
-  --enable-hmac-binary-check
-                          Enable library integrity check
-  --disable-jent-support  Disable support for the Jitter entropy collector
-  --disable-padlock-support
-                          Disable support for the PadLock Engine of VIA
-                          processors
-  --disable-aesni-support Disable support for the Intel AES-NI instructions
-  --disable-pclmul-support
-                          Disable support for the Intel PCLMUL instructions
-  --disable-sse41-support Disable support for the Intel SSE4.1 instructions
-  --disable-drng-support  Disable support for the Intel DRNG (RDRAND
-                          instruction)
-  --disable-avx-support   Disable support for the Intel AVX instructions
-  --disable-avx2-support  Disable support for the Intel AVX2 instructions
-  --disable-neon-support  Disable support for the ARM NEON instructions
-  --disable-arm-crypto-support
-                          Disable support for the ARMv8 Crypto Extension
-                          instructions
-  --disable-O-flag-munging
-                          Disable modification of the cc -O flag
-  --disable-amd64-as-feature-detection
-                          Disable the auto-detection of AMD64 as(1) features
-  --enable-ld-version-script
-                          enable/disable use of linker version script.
-                          (default is system dependent)
-  --enable-mpi-path=EXTRA_PATH
-                          prepend EXTRA_PATH to list of CPU specific
-                          optimizations
-  --disable-optimization  disable compiler optimization
-  --disable-noexecstack   disable non executable stack support
-  --disable-doc           do not build the documentation
-  --enable-build-timestamp
-                          set an explicit build timestamp for reproducibility.
-                          (default is the current time in ISO-8601 format)
-
-Optional Packages:
-  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
-  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
-  --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
-                          both]
-  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
-  --with-sysroot=DIR Search for dependent libraries within DIR
-                        (or the compiler's sysroot if not specified).
-  --with-egd-socket=NAME  Use NAME for the EGD socket)
-  --with-capabilities     Use linux capabilities [default=no]
-  --with-libgpg-error-prefix=PFX
-                          prefix where GPG Error is installed (optional)
-
-  --with-pth-prefix=PFX   prefix where GNU Pth is installed (optional)
-
-Some influential environment variables:
-  SYSROOT     locate config scripts also below that directory
-  CC          C compiler command
-  CFLAGS      C compiler flags
-  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
-              nonstandard directory <lib dir>
-  LIBS        libraries to pass to the linker, e.g. -l<library>
-  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
-              you have headers in a nonstandard directory <include dir>
-  CPP         C preprocessor
-  CCAS        assembler compiler command (defaults to CC)
-  CCASFLAGS   assembler compiler flags (defaults to CFLAGS)
-  CC_FOR_BUILD
-              build system C compiler
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-Report bugs to <http://bugs.gnupg.org>.
-_ACEOF
-ac_status=$?
-fi
-
-if test "$ac_init_help" = "recursive"; then
-  # If there are subdirs, report their specific --help.
-  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
-    test -d "$ac_dir" ||
-      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
-      continue
-    ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
-  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
-  # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
-  case $ac_top_builddir_sub in
-  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
-  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
-  esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
-  .)  # We are building in place.
-    ac_srcdir=.
-    ac_top_srcdir=$ac_top_builddir_sub
-    ac_abs_top_srcdir=$ac_pwd ;;
-  [\\/]* | ?:[\\/]* )  # Absolute name.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir
-    ac_abs_top_srcdir=$srcdir ;;
-  *) # Relative name.
-    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_build_prefix$srcdir
-    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
-    cd "$ac_dir" || { ac_status=$?; continue; }
-    # Check for guested configure.
-    if test -f "$ac_srcdir/configure.gnu"; then
-      echo &&
-      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
-    elif test -f "$ac_srcdir/configure"; then
-      echo &&
-      $SHELL "$ac_srcdir/configure" --help=recursive
-    else
-      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
-    fi || ac_status=$?
-    cd "$ac_pwd" || { ac_status=$?; break; }
-  done
-fi
-
-test -n "$ac_init_help" && exit $ac_status
-if $ac_init_version; then
-  cat <<\_ACEOF
-libgcrypt configure 1.8.4
-generated by GNU Autoconf 2.69
-
-Copyright (C) 2012 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
-  exit
-fi
-
-## ------------------------ ##
-## Autoconf initialization. ##
-## ------------------------ ##
-
-# ac_fn_c_try_compile LINENO
-# --------------------------
-# Try to compile conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_compile ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  rm -f conftest.$ac_objext
-  if { { ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_compile") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    grep -v '^ *+' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-    mv -f conftest.er1 conftest.err
-  fi
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then :
-  ac_retval=0
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-       ac_retval=1
-fi
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-  as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_compile
-
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    grep -v '^ *+' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-    mv -f conftest.er1 conftest.err
-  fi
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } > conftest.i && {
-        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       }; then :
-  ac_retval=0
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-    ac_retval=1
-fi
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-  as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_try_link LINENO
-# -----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_link ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  rm -f conftest.$ac_objext conftest$ac_exeext
-  if { { ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_link") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    grep -v '^ *+' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-    mv -f conftest.er1 conftest.err
-  fi
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest$ac_exeext && {
-        test "$cross_compiling" = yes ||
-        test -x conftest$ac_exeext
-       }; then :
-  ac_retval=0
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-       ac_retval=1
-fi
-  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
-  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
-  # interfere with the next link command; also delete a directory that is
-  # left behind by Apple's compiler.  We do this before executing the actions.
-  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-  as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_link
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if eval \${$3+:} false; then :
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_header_compiler=yes
-else
-  ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-  ac_header_preproc=yes
-else
-  ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
-  yes:no: )
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-    ;;
-  no:yes:* )
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-( $as_echo "## ------------------------------------ ##
-## Report this to http://bugs.gnupg.org ##
-## ------------------------------------ ##"
-     ) | sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
-# ac_fn_c_try_run LINENO
-# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
-ac_fn_c_try_run ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if { { ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
-  { { case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; }; then :
-  ac_retval=0
-else
-  $as_echo "$as_me: program exited with status $ac_status" >&5
-       $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-       ac_retval=$ac_status
-fi
-  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-  as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_run
-
-# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists and can be compiled using the include files in
-# INCLUDES, setting the cache variable VAR accordingly.
-ac_fn_c_check_header_compile ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  eval "$3=yes"
-else
-  eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_compile
-
-# ac_fn_c_check_func LINENO FUNC VAR
-# ----------------------------------
-# Tests whether FUNC exists, setting the cache variable VAR accordingly
-ac_fn_c_check_func ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define $2 innocuous_$2
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $2 (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $2
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $2 ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined __stub_$2 || defined __stub___$2
-choke me
-#endif
-
-int
-main ()
-{
-return $2 ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  eval "$3=yes"
-else
-  eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_func
-
-# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
-# --------------------------------------------
-# Tries to find the compile-time value of EXPR in a program that includes
-# INCLUDES, setting VAR accordingly. Returns whether the value could be
-# computed
-ac_fn_c_compute_int ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if test "$cross_compiling" = yes; then
-    # Depending upon the size, compute the lo and hi bounds.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) >= 0)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_lo=0 ac_mid=0
-  while :; do
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_hi=$ac_mid; break
-else
-  as_fn_arith $ac_mid + 1 && ac_lo=$as_val
-                       if test $ac_lo -le $ac_mid; then
-                         ac_lo= ac_hi=
-                         break
-                       fi
-                       as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  done
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) < 0)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_hi=-1 ac_mid=-1
-  while :; do
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) >= $ac_mid)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_lo=$ac_mid; break
-else
-  as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
-                       if test $ac_mid -le $ac_hi; then
-                         ac_lo= ac_hi=
-                         break
-                       fi
-                       as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  done
-else
-  ac_lo= ac_hi=
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-# Binary search between lo and hi bounds.
-while test "x$ac_lo" != "x$ac_hi"; do
-  as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_hi=$ac_mid
-else
-  as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-case $ac_lo in #((
-?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
-'') ac_retval=1 ;;
-esac
-  else
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
-#include <stdio.h>
-#include <stdlib.h>
-int
-main ()
-{
-
-  FILE *f = fopen ("conftest.val", "w");
-  if (! f)
-    return 1;
-  if (($2) < 0)
-    {
-      long int i = longval ();
-      if (i != ($2))
-       return 1;
-      fprintf (f, "%ld", i);
-    }
-  else
-    {
-      unsigned long int i = ulongval ();
-      if (i != ($2))
-       return 1;
-      fprintf (f, "%lu", i);
-    }
-  /* Do not output a trailing newline, as this causes \r\n confusion
-     on some platforms.  */
-  return ferror (f) || fclose (f) != 0;
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
-  ac_retval=1
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-rm -f conftest.val
-
-  fi
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-  as_fn_set_status $ac_retval
-
-} # ac_fn_c_compute_int
-
-# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
-# -------------------------------------------
-# Tests whether TYPE exists after having included INCLUDES, setting cache
-# variable VAR accordingly.
-ac_fn_c_check_type ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  eval "$3=no"
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-if (sizeof ($2))
-        return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-if (sizeof (($2)))
-           return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
-  eval "$3=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_type
-
-# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
-# ---------------------------------------------
-# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
-# accordingly.
-ac_fn_c_check_decl ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  as_decl_name=`echo $2|sed 's/ *(.*//'`
-  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
-$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-#ifndef $as_decl_name
-#ifdef __cplusplus
-  (void) $as_decl_use;
-#else
-  (void) $as_decl_name;
-#endif
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  eval "$3=yes"
-else
-  eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_decl
-cat >config.log <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by libgcrypt $as_me 1.8.4, which was
-generated by GNU Autoconf 2.69.  Invocation command line was
-
-  $ $0 $@
-
-_ACEOF
-exec 5>>config.log
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
-
-/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
-/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
-/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
-/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
-/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    $as_echo "PATH: $as_dir"
-  done
-IFS=$as_save_IFS
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
-  for ac_arg
-  do
-    case $ac_arg in
-    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-    | -silent | --silent | --silen | --sile | --sil)
-      continue ;;
-    *\'*)
-      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
-    esac
-    case $ac_pass in
-    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
-    2)
-      as_fn_append ac_configure_args1 " '$ac_arg'"
-      if test $ac_must_keep_next = true; then
-       ac_must_keep_next=false # Got value, back to normal.
-      else
-       case $ac_arg in
-         *=* | --config-cache | -C | -disable-* | --disable-* \
-         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
-         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
-         | -with-* | --with-* | -without-* | --without-* | --x)
-           case "$ac_configure_args0 " in
-             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
-           esac
-           ;;
-         -* ) ac_must_keep_next=true ;;
-       esac
-      fi
-      as_fn_append ac_configure_args " '$ac_arg'"
-      ;;
-    esac
-  done
-done
-{ ac_configure_args0=; unset ac_configure_args0;}
-{ ac_configure_args1=; unset ac_configure_args1;}
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log.  We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Use '\'' to represent an apostrophe within the trap.
-# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
-trap 'exit_status=$?
-  # Save into config.log some information that might help in debugging.
-  {
-    echo
-
-    $as_echo "## ---------------- ##
-## Cache variables. ##
-## ---------------- ##"
-    echo
-    # The following way of writing the cache mishandles newlines in values,
-(
-  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
-    eval ac_val=\$$ac_var
-    case $ac_val in #(
-    *${as_nl}*)
-      case $ac_var in #(
-      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
-      esac
-      case $ac_var in #(
-      _ | IFS | as_nl) ;; #(
-      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
-      *) { eval $ac_var=; unset $ac_var;} ;;
-      esac ;;
-    esac
-  done
-  (set) 2>&1 |
-    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
-    *${as_nl}ac_space=\ *)
-      sed -n \
-       "s/'\''/'\''\\\\'\'''\''/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
-      ;; #(
-    *)
-      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
-      ;;
-    esac |
-    sort
-)
-    echo
-
-    $as_echo "## ----------------- ##
-## Output variables. ##
-## ----------------- ##"
-    echo
-    for ac_var in $ac_subst_vars
-    do
-      eval ac_val=\$$ac_var
-      case $ac_val in
-      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
-      esac
-      $as_echo "$ac_var='\''$ac_val'\''"
-    done | sort
-    echo
-
-    if test -n "$ac_subst_files"; then
-      $as_echo "## ------------------- ##
-## File substitutions. ##
-## ------------------- ##"
-      echo
-      for ac_var in $ac_subst_files
-      do
-       eval ac_val=\$$ac_var
-       case $ac_val in
-       *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
-       esac
-       $as_echo "$ac_var='\''$ac_val'\''"
-      done | sort
-      echo
-    fi
-
-    if test -s confdefs.h; then
-      $as_echo "## ----------- ##
-## confdefs.h. ##
-## ----------- ##"
-      echo
-      cat confdefs.h
-      echo
-    fi
-    test "$ac_signal" != 0 &&
-      $as_echo "$as_me: caught signal $ac_signal"
-    $as_echo "$as_me: exit $exit_status"
-  } >&5
-  rm -f core *.core core.conftest.* &&
-    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
-    exit $exit_status
-' 0
-for ac_signal in 1 2 13 15; do
-  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -f -r conftest* confdefs.h
-
-$as_echo "/* confdefs.h */" > confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
-if test -n "$CONFIG_SITE"; then
-  # We do not want a PATH search for config.site.
-  case $CONFIG_SITE in #((
-    -*)  ac_site_file1=./$CONFIG_SITE;;
-    */*) ac_site_file1=$CONFIG_SITE;;
-    *)   ac_site_file1=./$CONFIG_SITE;;
-  esac
-elif test "x$prefix" != xNONE; then
-  ac_site_file1=$prefix/share/config.site
-  ac_site_file2=$prefix/etc/config.site
-else
-  ac_site_file1=$ac_default_prefix/share/config.site
-  ac_site_file2=$ac_default_prefix/etc/config.site
-fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
-do
-  test "x$ac_site_file" = xNONE && continue
-  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
-    sed 's/^/| /' "$ac_site_file" >&5
-    . "$ac_site_file" \
-      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "failed to load site script $ac_site_file
-See \`config.log' for more details" "$LINENO" 5; }
-  fi
-done
-
-if test -r "$cache_file"; then
-  # Some versions of bash will fail to source /dev/null (special files
-  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
-  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
-    case $cache_file in
-      [\\/]* | ?:[\\/]* ) . "$cache_file";;
-      *)                      . "./$cache_file";;
-    esac
-  fi
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
-  >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in $ac_precious_vars; do
-  eval ac_old_set=\$ac_cv_env_${ac_var}_set
-  eval ac_new_set=\$ac_env_${ac_var}_set
-  eval ac_old_val=\$ac_cv_env_${ac_var}_value
-  eval ac_new_val=\$ac_env_${ac_var}_value
-  case $ac_old_set,$ac_new_set in
-    set,)
-      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,set)
-      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,);;
-    *)
-      if test "x$ac_old_val" != "x$ac_new_val"; then
-       # differences in whitespace do not lead to failure.
-       ac_old_val_w=`echo x $ac_old_val`
-       ac_new_val_w=`echo x $ac_new_val`
-       if test "$ac_old_val_w" != "$ac_new_val_w"; then
-         { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
-         ac_cache_corrupted=:
-       else
-         { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
-         eval $ac_var=\$ac_old_val
-       fi
-       { $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
-$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
-       { $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
-$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
-      fi;;
-  esac
-  # Pass precious variables to config.status.
-  if test "$ac_new_set" = set; then
-    case $ac_new_val in
-    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
-    *) ac_arg=$ac_var=$ac_new_val ;;
-    esac
-    case " $ac_configure_args " in
-      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
-      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
-    esac
-  fi
-done
-if $ac_cache_corrupted; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
-  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
-fi
-## -------------------- ##
-## Main body of script. ##
-## -------------------- ##
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-# LT Version numbers, remember to change them just *before* a release.
-#   (Interfaces removed:    CURRENT++, AGE=0, REVISION=0)
-#   (Interfaces added:      CURRENT++, AGE++, REVISION=0)
-#   (No interfaces changed:                   REVISION++)
-LIBGCRYPT_LT_CURRENT=22
-LIBGCRYPT_LT_AGE=2
-LIBGCRYPT_LT_REVISION=4
-
-
-# If the API is changed in an incompatible way: increment the next counter.
-#
-# 1.6: ABI and API change but the change is to most users irrelevant
-#      and thus the API version number has not been incremented.
-LIBGCRYPT_CONFIG_API_VERSION=1
-
-# If you change the required gpg-error version, please remove
-# unnecessary error code defines in src/gcrypt-int.h.
-NEED_GPG_ERROR_VERSION=1.25
-
-PACKAGE=$PACKAGE_NAME
-VERSION=$PACKAGE_VERSION
-
-ac_aux_dir=
-for ac_dir in build-aux "$srcdir"/build-aux; do
-  if test -f "$ac_dir/install-sh"; then
-    ac_aux_dir=$ac_dir
-    ac_install_sh="$ac_aux_dir/install-sh -c"
-    break
-  elif test -f "$ac_dir/install.sh"; then
-    ac_aux_dir=$ac_dir
-    ac_install_sh="$ac_aux_dir/install.sh -c"
-    break
-  elif test -f "$ac_dir/shtool"; then
-    ac_aux_dir=$ac_dir
-    ac_install_sh="$ac_aux_dir/shtool install -c"
-    break
-  fi
-done
-if test -z "$ac_aux_dir"; then
-  as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5
-fi
-
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
-
-
-
-am__api_version='1.14'
-
-# Find a good install program.  We prefer a C program (faster),
-# so one script is as good as another.  But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AmigaOS /C/install, which installs bootblocks on floppy discs
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# OS/2's system install, which has a completely different semantic
-# ./install, which can be erroneously created by make from ./install.sh.
-# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
-if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
-  ./ | .// | /[cC]/* | \
-  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
-  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
-  /usr/ucb/* ) ;;
-  *)
-    # OSF1 and SCO ODT 3.0 have their own names for install.
-    # Don't use installbsd from OSF since it installs stuff as root
-    # by default.
-    for ac_prog in ginstall scoinst install; do
-      for ac_exec_ext in '' $ac_executable_extensions; do
-       if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
-         if test $ac_prog = install &&
-           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
-           # AIX install.  It has an incompatible calling convention.
-           :
-         elif test $ac_prog = install &&
-           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
-           # program-specific install script used by HP pwplus--don't use.
-           :
-         else
-           rm -rf conftest.one conftest.two conftest.dir
-           echo one > conftest.one
-           echo two > conftest.two
-           mkdir conftest.dir
-           if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
-             test -s conftest.one && test -s conftest.two &&
-             test -s conftest.dir/conftest.one &&
-             test -s conftest.dir/conftest.two
-           then
-             ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
-             break 3
-           fi
-         fi
-       fi
-      done
-    done
-    ;;
-esac
-
-  done
-IFS=$as_save_IFS
-
-rm -rf conftest.one conftest.two conftest.dir
-
-fi
-  if test "${ac_cv_path_install+set}" = set; then
-    INSTALL=$ac_cv_path_install
-  else
-    # As a last resort, use the slow shell script.  Don't cache a
-    # value for INSTALL within a source directory, because that will
-    # break other packages using the cache if that directory is
-    # removed, or if the value is a relative name.
-    INSTALL=$ac_install_sh
-  fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
-$as_echo_n "checking whether build environment is sane... " >&6; }
-# Reject unsafe characters in $srcdir or the absolute working directory
-# name.  Accept space and tab only in the latter.
-am_lf='
-'
-case `pwd` in
-  *[\\\"\#\$\&\'\`$am_lf]*)
-    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
-esac
-case $srcdir in
-  *[\\\"\#\$\&\'\`$am_lf\ \    ]*)
-    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
-esac
-
-# Do 'set' in a subshell so we don't clobber the current shell's
-# arguments.  Must try -L first in case configure is actually a
-# symlink; some systems play weird games with the mod time of symlinks
-# (eg FreeBSD returns the mod time of the symlink's containing
-# directory).
-if (
-   am_has_slept=no
-   for am_try in 1 2; do
-     echo "timestamp, slept: $am_has_slept" > conftest.file
-     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
-     if test "$*" = "X"; then
-       # -L didn't work.
-       set X `ls -t "$srcdir/configure" conftest.file`
-     fi
-     if test "$*" != "X $srcdir/configure conftest.file" \
-       && test "$*" != "X conftest.file $srcdir/configure"; then
-
-       # If neither matched, then we have a broken ls.  This can happen
-       # if, for instance, CONFIG_SHELL is bash and it inherits a
-       # broken ls alias from the environment.  This has actually
-       # happened.  Such a system could not be considered "sane".
-       as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
-  alias in your environment" "$LINENO" 5
-     fi
-     if test "$2" = conftest.file || test $am_try -eq 2; then
-       break
-     fi
-     # Just in case.
-     sleep 1
-     am_has_slept=yes
-   done
-   test "$2" = conftest.file
-   )
-then
-   # Ok.
-   :
-else
-   as_fn_error $? "newly created file is older than distributed files!
-Check your system clock" "$LINENO" 5
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-# If we didn't sleep, we still need to ensure time stamps of config.status and
-# generated files are strictly newer.
-am_sleep_pid=
-if grep 'slept: no' conftest.file >/dev/null 2>&1; then
-  ( sleep 1 ) &
-  am_sleep_pid=$!
-fi
-
-rm -f conftest.file
-
-test "$program_prefix" != NONE &&
-  program_transform_name="s&^&$program_prefix&;$program_transform_name"
-# Use a double $ so make ignores it.
-test "$program_suffix" != NONE &&
-  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
-# Double any \ or $.
-# By default was `s,x,x', remove it if useless.
-ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
-program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
-
-# Expand $ac_aux_dir to an absolute path.
-am_aux_dir=`cd "$ac_aux_dir" && pwd`
-
-if test x"${MISSING+set}" != xset; then
-  case $am_aux_dir in
-  *\ * | *\    *)
-    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
-  *)
-    MISSING="\${SHELL} $am_aux_dir/missing" ;;
-  esac
-fi
-# Use eval to expand $SHELL
-if eval "$MISSING --is-lightweight"; then
-  am_missing_run="$MISSING "
-else
-  am_missing_run=
-  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
-$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
-fi
-
-if test x"${install_sh}" != xset; then
-  case $am_aux_dir in
-  *\ * | *\    *)
-    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
-  *)
-    install_sh="\${SHELL} $am_aux_dir/install-sh"
-  esac
-fi
-
-# Installed binaries are usually stripped using 'strip' when the user
-# run "make install-strip".  However 'strip' might not be the right
-# tool to use in cross-compilation environments, therefore Automake
-# will honor the 'STRIP' environment variable to overrule this program.
-if test "$cross_compiling" != no; then
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
-set dummy ${ac_tool_prefix}strip; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_STRIP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$STRIP"; then
-  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-STRIP=$ac_cv_prog_STRIP
-if test -n "$STRIP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
-$as_echo "$STRIP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_STRIP"; then
-  ac_ct_STRIP=$STRIP
-  # Extract the first word of "strip", so it can be a program name with args.
-set dummy strip; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_STRIP"; then
-  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_STRIP="strip"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
-if test -n "$ac_ct_STRIP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
-$as_echo "$ac_ct_STRIP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_STRIP" = x; then
-    STRIP=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    STRIP=$ac_ct_STRIP
-  fi
-else
-  STRIP="$ac_cv_prog_STRIP"
-fi
-
-fi
-INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
-$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
-if test -z "$MKDIR_P"; then
-  if ${ac_cv_path_mkdir+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_prog in mkdir gmkdir; do
-        for ac_exec_ext in '' $ac_executable_extensions; do
-          as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
-          case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
-            'mkdir (GNU coreutils) '* | \
-            'mkdir (coreutils) '* | \
-            'mkdir (fileutils) '4.1*)
-              ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
-              break 3;;
-          esac
-        done
-       done
-  done
-IFS=$as_save_IFS
-
-fi
-
-  test -d ./--version && rmdir ./--version
-  if test "${ac_cv_path_mkdir+set}" = set; then
-    MKDIR_P="$ac_cv_path_mkdir -p"
-  else
-    # As a last resort, use the slow shell script.  Don't cache a
-    # value for MKDIR_P within a source directory, because that will
-    # break other packages using the cache if that directory is
-    # removed, or if the value is a relative name.
-    MKDIR_P="$ac_install_sh -d"
-  fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
-$as_echo "$MKDIR_P" >&6; }
-
-for ac_prog in gawk mawk nawk awk
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AWK+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$AWK"; then
-  ac_cv_prog_AWK="$AWK" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_AWK="$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-AWK=$ac_cv_prog_AWK
-if test -n "$AWK"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
-$as_echo "$AWK" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$AWK" && break
-done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
-$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
-set x ${MAKE-make}
-ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
-if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat >conftest.make <<\_ACEOF
-SHELL = /bin/sh
-all:
-       @echo '@@@%%%=$(MAKE)=@@@%%%'
-_ACEOF
-# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
-case `${MAKE-make} -f conftest.make 2>/dev/null` in
-  *@@@%%%=?*=@@@%%%*)
-    eval ac_cv_prog_make_${ac_make}_set=yes;;
-  *)
-    eval ac_cv_prog_make_${ac_make}_set=no;;
-esac
-rm -f conftest.make
-fi
-if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-  SET_MAKE=
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-  SET_MAKE="MAKE=${MAKE-make}"
-fi
-
-rm -rf .tst 2>/dev/null
-mkdir .tst 2>/dev/null
-if test -d .tst; then
-  am__leading_dot=.
-else
-  am__leading_dot=_
-fi
-rmdir .tst 2>/dev/null
-
-# Check whether --enable-silent-rules was given.
-if test "${enable_silent_rules+set}" = set; then :
-  enableval=$enable_silent_rules;
-fi
-
-case $enable_silent_rules in # (((
-  yes) AM_DEFAULT_VERBOSITY=0;;
-   no) AM_DEFAULT_VERBOSITY=1;;
-    *) AM_DEFAULT_VERBOSITY=1;;
-esac
-am_make=${MAKE-make}
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
-$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
-if ${am_cv_make_support_nested_variables+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if $as_echo 'TRUE=$(BAR$(V))
-BAR0=false
-BAR1=true
-V=1
-am__doit:
-       @$(TRUE)
-.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
-  am_cv_make_support_nested_variables=yes
-else
-  am_cv_make_support_nested_variables=no
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
-$as_echo "$am_cv_make_support_nested_variables" >&6; }
-if test $am_cv_make_support_nested_variables = yes; then
-    AM_V='$(V)'
-  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
-else
-  AM_V=$AM_DEFAULT_VERBOSITY
-  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
-fi
-AM_BACKSLASH='\'
-
-if test "`cd $srcdir && pwd`" != "`pwd`"; then
-  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
-  # is not polluted with repeated "-I."
-  am__isrc=' -I$(srcdir)'
-  # test to see if srcdir already configured
-  if test -f $srcdir/config.status; then
-    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
-  fi
-fi
-
-# test whether we have cygpath
-if test -z "$CYGPATH_W"; then
-  if (cygpath --version) >/dev/null 2>/dev/null; then
-    CYGPATH_W='cygpath -w'
-  else
-    CYGPATH_W=echo
-  fi
-fi
-
-
-# Define the identity of the package.
- PACKAGE='libgcrypt'
- VERSION='1.8.4'
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE "$PACKAGE"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define VERSION "$VERSION"
-_ACEOF
-
-# Some tools Automake needs.
-
-ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
-
-
-AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
-
-
-AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
-
-
-AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
-
-
-MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
-
-# For better backward compatibility.  To be removed once Automake 1.9.x
-# dies out for good.  For more background, see:
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
-mkdir_p='$(MKDIR_P)'
-
-# We need awk for the "check" target.  The system "awk" is bad on
-# some platforms.
-# Always define AMTAR for backward compatibility.  Yes, it's still used
-# in the wild :-(  We should find a proper way to deprecate it ...
-AMTAR='$${TAR-tar}'
-
-
-# We'll loop over all known methods to create a tar archive until one works.
-_am_tools='gnutar  pax cpio none'
-
-am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
-
-
-
-
-
-
-# POSIX will say in a future version that running "rm -f" with no argument
-# is OK; and we want to be able to make that assumption in our Makefile
-# recipes.  So use an aggressive probe to check that the usage we want is
-# actually supported "in the wild" to an acceptable degree.
-# See automake bug#10828.
-# To make any issue more visible, cause the running configure to be aborted
-# by default if the 'rm' program in use doesn't match our expectations; the
-# user can still override this though.
-if rm -f && rm -fr && rm -rf; then : OK; else
-  cat >&2 <<'END'
-Oops!
-
-Your 'rm' program seems unable to run without file operands specified
-on the command line, even when the '-f' option is present.  This is contrary
-to the behaviour of most rm programs out there, and not conforming with
-the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
-
-Please tell bug-automake@gnu.org about your system, including the value
-of your $PATH and any error possibly output before this message.  This
-can help us improve future automake versions.
-
-END
-  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
-    echo 'Configuration will proceed anyway, since you have set the' >&2
-    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
-    echo >&2
-  else
-    cat >&2 <<'END'
-Aborting the configuration process, to ensure you take notice of the issue.
-
-You can download and install GNU coreutils to get an 'rm' implementation
-that behaves properly: <http://www.gnu.org/software/coreutils/>.
-
-If you want to complete the configuration process using your problematic
-'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
-to "yes", and re-run configure.
-
-END
-    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
-  fi
-fi
-
-ac_config_headers="$ac_config_headers config.h"
-
-
-
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
-  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
-  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
-  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
-  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
-esac
-build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "x$host_alias" = x; then
-  ac_cv_host=$ac_cv_build
-else
-  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
-    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
-$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
-    # Check whether --enable-maintainer-mode was given.
-if test "${enable_maintainer_mode+set}" = set; then :
-  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
-else
-  USE_MAINTAINER_MODE=no
-fi
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
-$as_echo "$USE_MAINTAINER_MODE" >&6; }
-   if test $USE_MAINTAINER_MODE = yes; then
-  MAINTAINER_MODE_TRUE=
-  MAINTAINER_MODE_FALSE='#'
-else
-  MAINTAINER_MODE_TRUE='#'
-  MAINTAINER_MODE_FALSE=
-fi
-
-  MAINT=$MAINTAINER_MODE_TRUE
-
-
-# Check whether --enable-silent-rules was given.
-if test "${enable_silent_rules+set}" = set; then :
-  enableval=$enable_silent_rules;
-fi
-
-case $enable_silent_rules in # (((
-  yes) AM_DEFAULT_VERBOSITY=0;;
-   no) AM_DEFAULT_VERBOSITY=1;;
-    *) AM_DEFAULT_VERBOSITY=1;;
-esac
-am_make=${MAKE-make}
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
-$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
-if ${am_cv_make_support_nested_variables+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if $as_echo 'TRUE=$(BAR$(V))
-BAR0=false
-BAR1=true
-V=1
-am__doit:
-       @$(TRUE)
-.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
-  am_cv_make_support_nested_variables=yes
-else
-  am_cv_make_support_nested_variables=no
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
-$as_echo "$am_cv_make_support_nested_variables" >&6; }
-if test $am_cv_make_support_nested_variables = yes; then
-    AM_V='$(V)'
-  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
-else
-  AM_V=$AM_DEFAULT_VERBOSITY
-  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
-fi
-AM_BACKSLASH='\'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE "$PACKAGE"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define VERSION "$VERSION"
-_ACEOF
-
-VERSION_NUMBER=0x010804
-
-
-
-######################
-##  Basic checks.  ### (we need some results later on (e.g. $GCC)
-######################
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
-$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
-set x ${MAKE-make}
-ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
-if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat >conftest.make <<\_ACEOF
-SHELL = /bin/sh
-all:
-       @echo '@@@%%%=$(MAKE)=@@@%%%'
-_ACEOF
-# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
-case `${MAKE-make} -f conftest.make 2>/dev/null` in
-  *@@@%%%=?*=@@@%%%*)
-    eval ac_cv_prog_make_${ac_make}_set=yes;;
-  *)
-    eval ac_cv_prog_make_${ac_make}_set=no;;
-esac
-rm -f conftest.make
-fi
-if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-  SET_MAKE=
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-  SET_MAKE="MAKE=${MAKE-make}"
-fi
-
-missing_dir=`cd $ac_aux_dir && pwd`
-
-ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal"}
-
-
-AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
-
-
-AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake"}
-
-
-AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
-
-# AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
-          if test -n "$ac_tool_prefix"; then
-    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  fi
-fi
-if test -z "$CC"; then
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-  ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
-       ac_prog_rejected=yes
-       continue
-     fi
-    ac_cv_prog_CC="cc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-if test $ac_prog_rejected = yes; then
-  # We found a bogon in the path, so make sure we never use it.
-  set dummy $ac_cv_prog_CC
-  shift
-  if test $# != 0; then
-    # We chose a different compiler from the bogus one.
-    # However, it has the same basename, so the bogon will be chosen
-    # first if we set CC to just the basename; use the full file name.
-    shift
-    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
-  fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl.exe
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-    test -n "$CC" && break
-  done
-fi
-if test -z "$CC"; then
-  ac_ct_CC=$CC
-  for ac_prog in cl.exe
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$ac_ct_CC" && break
-done
-
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
-fi
-
-fi
-
-
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
-
-# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
-set X $ac_compile
-ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
-  { { ac_try="$ac_compiler $ac_option >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    sed '10a\
-... rest of stderr output deleted ...
-         10q' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-  fi
-  rm -f conftest.er1 conftest.err
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }
-done
-
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-
-# The possible output files:
-ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
-
-ac_rmfiles=
-for ac_file in $ac_files
-do
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
-    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
-  esac
-done
-rm -f $ac_rmfiles
-
-if { { ac_try="$ac_link_default"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_link_default") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then :
-  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
-# in a Makefile.  We should not override ac_cv_exeext if it was cached,
-# so that the user can short-circuit this test for compilers unknown to
-# Autoconf.
-for ac_file in $ac_files ''
-do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
-       ;;
-    [ab].out )
-       # We found the default executable, but exeext='' is most
-       # certainly right.
-       break;;
-    *.* )
-       if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
-       then :; else
-          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-       fi
-       # We set ac_cv_exeext here because the later test for it is not
-       # safe: cross compilers may not add the suffix if given an `-o'
-       # argument, so we may need to know it at that point already.
-       # Even if this section looks crufty: it has the advantage of
-       # actually working.
-       break;;
-    * )
-       break;;
-  esac
-done
-test "$ac_cv_exeext" = no && ac_cv_exeext=
-
-else
-  ac_file=''
-fi
-if test -z "$ac_file"; then :
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "C compiler cannot create executables
-See \`config.log' for more details" "$LINENO" 5; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
-ac_exeext=$ac_cv_exeext
-
-rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
-if { { ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then :
-  # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
-    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-         break;;
-    * ) break;;
-  esac
-done
-else
-  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <stdio.h>
-int
-main ()
-{
-FILE *f = fopen ("conftest.out", "w");
- return ferror (f) || fclose (f) != 0;
-
-  ;
-  return 0;
-}
-_ACEOF
-ac_clean_files="$ac_clean_files conftest.out"
-# Check that the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
-if test "$cross_compiling" != yes; then
-  { { ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }
-  if { ac_try='./conftest$ac_cv_exeext'
-  { { case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; }; then
-    cross_compiling=no
-  else
-    if test "$cross_compiling" = maybe; then
-       cross_compiling=yes
-    else
-       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details" "$LINENO" 5; }
-    fi
-  fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
-
-rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
-ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { { ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_compile") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then :
-  for ac_file in conftest.o conftest.obj conftest.*; do
-  test -f "$ac_file" || continue;
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
-    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
-       break;;
-  esac
-done
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot compute suffix of object files: cannot compile
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_compiler_gnu=yes
-else
-  ac_compiler_gnu=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
-if test $ac_compiler_gnu = yes; then
-  GCC=yes
-else
-  GCC=
-fi
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_save_c_werror_flag=$ac_c_werror_flag
-   ac_c_werror_flag=yes
-   ac_cv_prog_cc_g=no
-   CFLAGS="-g"
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_g=yes
-else
-  CFLAGS=""
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
-  ac_c_werror_flag=$ac_save_c_werror_flag
-        CFLAGS="-g"
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_g=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-   ac_c_werror_flag=$ac_save_c_werror_flag
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
-  CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
-  if test "$GCC" = yes; then
-    CFLAGS="-g -O2"
-  else
-    CFLAGS="-g"
-  fi
-else
-  if test "$GCC" = yes; then
-    CFLAGS="-O2"
-  else
-    CFLAGS=
-  fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
-     char **p;
-     int i;
-{
-  return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
-  char *s;
-  va_list v;
-  va_start (v,p);
-  s = g (p, va_arg (v,int));
-  va_end (v);
-  return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
-   function prototypes and stuff, but not '\xHH' hex character constants.
-   These don't provoke an error unfortunately, instead are silently treated
-   as 'x'.  The following induces an error, until -std is added to get
-   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
-   array size at least.  It's necessary to write '\x00'==0 to get something
-   that's true only with -std.  */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
-   inside strings and character constants.  */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
-  ;
-  return 0;
-}
-_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
-       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
-  CC="$ac_save_CC $ac_arg"
-  if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_c89=$ac_arg
-fi
-rm -f core conftest.err conftest.$ac_objext
-  test "x$ac_cv_prog_cc_c89" != "xno" && break
-done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
-  x)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
-  xno)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
-  *)
-    CC="$CC $ac_cv_prog_cc_c89"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
-
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
-$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
-if ${am_cv_prog_cc_c_o+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-  # Make sure it works both with $CC and with simple cc.
-  # Following AC_PROG_CC_C_O, we do the test twice because some
-  # compilers refuse to overwrite an existing .o file with -o,
-  # though they will create one.
-  am_cv_prog_cc_c_o=yes
-  for am_i in 1 2; do
-    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
-   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
-   ac_status=$?
-   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-   (exit $ac_status); } \
-         && test -f conftest2.$ac_objext; then
-      : OK
-    else
-      am_cv_prog_cc_c_o=no
-      break
-    fi
-  done
-  rm -f core conftest*
-  unset am_i
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
-$as_echo "$am_cv_prog_cc_c_o" >&6; }
-if test "$am_cv_prog_cc_c_o" != yes; then
-   # Losing compiler, so override with the script.
-   # FIXME: It is wrong to rewrite CC.
-   # But if we don't then we get into trouble of one sort or another.
-   # A longer-term fix would be to have automake use am__CC in this case,
-   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
-   CC="$am_aux_dir/compile $CC"
-fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-DEPDIR="${am__leading_dot}deps"
-
-ac_config_commands="$ac_config_commands depfiles"
-
-
-am_make=${MAKE-make}
-cat > confinc << 'END'
-am__doit:
-       @echo this is the am__doit target
-.PHONY: am__doit
-END
-# If we don't find an include directive, just comment out the code.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
-$as_echo_n "checking for style of include used by $am_make... " >&6; }
-am__include="#"
-am__quote=
-_am_result=none
-# First try GNU make style include.
-echo "include confinc" > confmf
-# Ignore all kinds of additional output from 'make'.
-case `$am_make -s -f confmf 2> /dev/null` in #(
-*the\ am__doit\ target*)
-  am__include=include
-  am__quote=
-  _am_result=GNU
-  ;;
-esac
-# Now try BSD make style include.
-if test "$am__include" = "#"; then
-   echo '.include "confinc"' > confmf
-   case `$am_make -s -f confmf 2> /dev/null` in #(
-   *the\ am__doit\ target*)
-     am__include=.include
-     am__quote="\""
-     _am_result=BSD
-     ;;
-   esac
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
-$as_echo "$_am_result" >&6; }
-rm -f confinc confmf
-
-# Check whether --enable-dependency-tracking was given.
-if test "${enable_dependency_tracking+set}" = set; then :
-  enableval=$enable_dependency_tracking;
-fi
-
-if test "x$enable_dependency_tracking" != xno; then
-  am_depcomp="$ac_aux_dir/depcomp"
-  AMDEPBACKSLASH='\'
-  am__nodep='_no'
-fi
- if test "x$enable_dependency_tracking" != xno; then
-  AMDEP_TRUE=
-  AMDEP_FALSE='#'
-else
-  AMDEP_TRUE='#'
-  AMDEP_FALSE=
-fi
-
-
-
-depcc="$CC"   am_compiler_list=
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
-$as_echo_n "checking dependency style of $depcc... " >&6; }
-if ${am_cv_CC_dependencies_compiler_type+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
-  # We make a subdir and do the tests there.  Otherwise we can end up
-  # making bogus files that we don't know about and never remove.  For
-  # instance it was reported that on HP-UX the gcc test will end up
-  # making a dummy file named 'D' -- because '-MD' means "put the output
-  # in D".
-  rm -rf conftest.dir
-  mkdir conftest.dir
-  # Copy depcomp to subdir because otherwise we won't find it if we're
-  # using a relative directory.
-  cp "$am_depcomp" conftest.dir
-  cd conftest.dir
-  # We will build objects and dependencies in a subdirectory because
-  # it helps to detect inapplicable dependency modes.  For instance
-  # both Tru64's cc and ICC support -MD to output dependencies as a
-  # side effect of compilation, but ICC will put the dependencies in
-  # the current directory while Tru64 will put them in the object
-  # directory.
-  mkdir sub
-
-  am_cv_CC_dependencies_compiler_type=none
-  if test "$am_compiler_list" = ""; then
-     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
-  fi
-  am__universal=false
-  case " $depcc " in #(
-     *\ -arch\ *\ -arch\ *) am__universal=true ;;
-     esac
-
-  for depmode in $am_compiler_list; do
-    # Setup a source with many dependencies, because some compilers
-    # like to wrap large dependency lists on column 80 (with \), and
-    # we should not choose a depcomp mode which is confused by this.
-    #
-    # We need to recreate these files for each test, as the compiler may
-    # overwrite some of them when testing with obscure command lines.
-    # This happens at least with the AIX C compiler.
-    : > sub/conftest.c
-    for i in 1 2 3 4 5 6; do
-      echo '#include "conftst'$i'.h"' >> sub/conftest.c
-      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
-      # Solaris 10 /bin/sh.
-      echo '/* dummy */' > sub/conftst$i.h
-    done
-    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
-
-    # We check with '-c' and '-o' for the sake of the "dashmstdout"
-    # mode.  It turns out that the SunPro C++ compiler does not properly
-    # handle '-M -o', and we need to detect this.  Also, some Intel
-    # versions had trouble with output in subdirs.
-    am__obj=sub/conftest.${OBJEXT-o}
-    am__minus_obj="-o $am__obj"
-    case $depmode in
-    gcc)
-      # This depmode causes a compiler race in universal mode.
-      test "$am__universal" = false || continue
-      ;;
-    nosideeffect)
-      # After this tag, mechanisms are not by side-effect, so they'll
-      # only be used when explicitly requested.
-      if test "x$enable_dependency_tracking" = xyes; then
-       continue
-      else
-       break
-      fi
-      ;;
-    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
-      # This compiler won't grok '-c -o', but also, the minuso test has
-      # not run yet.  These depmodes are late enough in the game, and
-      # so weak that their functioning should not be impacted.
-      am__obj=conftest.${OBJEXT-o}
-      am__minus_obj=
-      ;;
-    none) break ;;
-    esac
-    if depmode=$depmode \
-       source=sub/conftest.c object=$am__obj \
-       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
-       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
-         >/dev/null 2>conftest.err &&
-       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
-       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
-       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
-       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
-      # icc doesn't choke on unknown options, it will just issue warnings
-      # or remarks (even with -Werror).  So we grep stderr for any message
-      # that says an option was ignored or not supported.
-      # When given -MP, icc 7.0 and 7.1 complain thusly:
-      #   icc: Command line warning: ignoring option '-M'; no argument required
-      # The diagnosis changed in icc 8.0:
-      #   icc: Command line remark: option '-MP' not supported
-      if (grep 'ignoring option' conftest.err ||
-          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
-        am_cv_CC_dependencies_compiler_type=$depmode
-        break
-      fi
-    fi
-  done
-
-  cd ..
-  rm -rf conftest.dir
-else
-  am_cv_CC_dependencies_compiler_type=none
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
-$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
-CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
-
- if
-  test "x$enable_dependency_tracking" != xno \
-  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
-  am__fastdepCC_TRUE=
-  am__fastdepCC_FALSE='#'
-else
-  am__fastdepCC_TRUE='#'
-  am__fastdepCC_FALSE=
-fi
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if ${ac_cv_prog_CPP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-      # Double quotes because CPP needs to be expanded
-    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
-  # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-  # Broken: success on invalid input.
-continue
-else
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-  break
-fi
-
-    done
-    ac_cv_prog_CPP=$CPP
-
-fi
-  CPP=$ac_cv_prog_CPP
-else
-  ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
-  # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-  # Broken: success on invalid input.
-continue
-else
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
-  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-# By default we simply use the C compiler to build assembly code.
-
-test "${CCAS+set}" = set || CCAS=$CC
-test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
-
-
-
-depcc="$CCAS"   am_compiler_list=
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
-$as_echo_n "checking dependency style of $depcc... " >&6; }
-if ${am_cv_CCAS_dependencies_compiler_type+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
-  # We make a subdir and do the tests there.  Otherwise we can end up
-  # making bogus files that we don't know about and never remove.  For
-  # instance it was reported that on HP-UX the gcc test will end up
-  # making a dummy file named 'D' -- because '-MD' means "put the output
-  # in D".
-  rm -rf conftest.dir
-  mkdir conftest.dir
-  # Copy depcomp to subdir because otherwise we won't find it if we're
-  # using a relative directory.
-  cp "$am_depcomp" conftest.dir
-  cd conftest.dir
-  # We will build objects and dependencies in a subdirectory because
-  # it helps to detect inapplicable dependency modes.  For instance
-  # both Tru64's cc and ICC support -MD to output dependencies as a
-  # side effect of compilation, but ICC will put the dependencies in
-  # the current directory while Tru64 will put them in the object
-  # directory.
-  mkdir sub
-
-  am_cv_CCAS_dependencies_compiler_type=none
-  if test "$am_compiler_list" = ""; then
-     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
-  fi
-  am__universal=false
-
-
-  for depmode in $am_compiler_list; do
-    # Setup a source with many dependencies, because some compilers
-    # like to wrap large dependency lists on column 80 (with \), and
-    # we should not choose a depcomp mode which is confused by this.
-    #
-    # We need to recreate these files for each test, as the compiler may
-    # overwrite some of them when testing with obscure command lines.
-    # This happens at least with the AIX C compiler.
-    : > sub/conftest.c
-    for i in 1 2 3 4 5 6; do
-      echo '#include "conftst'$i'.h"' >> sub/conftest.c
-      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
-      # Solaris 10 /bin/sh.
-      echo '/* dummy */' > sub/conftst$i.h
-    done
-    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
-
-    # We check with '-c' and '-o' for the sake of the "dashmstdout"
-    # mode.  It turns out that the SunPro C++ compiler does not properly
-    # handle '-M -o', and we need to detect this.  Also, some Intel
-    # versions had trouble with output in subdirs.
-    am__obj=sub/conftest.${OBJEXT-o}
-    am__minus_obj="-o $am__obj"
-    case $depmode in
-    gcc)
-      # This depmode causes a compiler race in universal mode.
-      test "$am__universal" = false || continue
-      ;;
-    nosideeffect)
-      # After this tag, mechanisms are not by side-effect, so they'll
-      # only be used when explicitly requested.
-      if test "x$enable_dependency_tracking" = xyes; then
-       continue
-      else
-       break
-      fi
-      ;;
-    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
-      # This compiler won't grok '-c -o', but also, the minuso test has
-      # not run yet.  These depmodes are late enough in the game, and
-      # so weak that their functioning should not be impacted.
-      am__obj=conftest.${OBJEXT-o}
-      am__minus_obj=
-      ;;
-    none) break ;;
-    esac
-    if depmode=$depmode \
-       source=sub/conftest.c object=$am__obj \
-       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
-       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
-         >/dev/null 2>conftest.err &&
-       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
-       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
-       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
-       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
-      # icc doesn't choke on unknown options, it will just issue warnings
-      # or remarks (even with -Werror).  So we grep stderr for any message
-      # that says an option was ignored or not supported.
-      # When given -MP, icc 7.0 and 7.1 complain thusly:
-      #   icc: Command line warning: ignoring option '-M'; no argument required
-      # The diagnosis changed in icc 8.0:
-      #   icc: Command line remark: option '-MP' not supported
-      if (grep 'ignoring option' conftest.err ||
-          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
-        am_cv_CCAS_dependencies_compiler_type=$depmode
-        break
-      fi
-    fi
-  done
-
-  cd ..
-  rm -rf conftest.dir
-else
-  am_cv_CCAS_dependencies_compiler_type=none
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5
-$as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; }
-CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type
-
- if
-  test "x$enable_dependency_tracking" != xno \
-  && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then
-  am__fastdepCCAS_TRUE=
-  am__fastdepCCAS_FALSE='#'
-else
-  am__fastdepCCAS_TRUE='#'
-  am__fastdepCCAS_FALSE=
-fi
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5
-$as_echo_n "checking for library containing strerror... " >&6; }
-if ${ac_cv_search_strerror+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char strerror ();
-int
-main ()
-{
-return strerror ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' cposix; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_strerror=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_strerror+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_strerror+:} false; then :
-
-else
-  ac_cv_search_strerror=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5
-$as_echo "$ac_cv_search_strerror" >&6; }
-ac_res=$ac_cv_search_strerror
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-
-for ac_prog in gawk mawk nawk awk
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AWK+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$AWK"; then
-  ac_cv_prog_AWK="$AWK" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_AWK="$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-AWK=$ac_cv_prog_AWK
-if test -n "$AWK"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
-$as_echo "$AWK" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$AWK" && break
-done
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -z "$GREP"; then
-  ac_path_GREP_found=false
-  # Loop through the user's path and test for each of PROGNAME-LIST
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_prog in grep ggrep; do
-    for ac_exec_ext in '' $ac_executable_extensions; do
-      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
-  # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
-  ac_count=0
-  $as_echo_n 0123456789 >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    $as_echo 'GREP' >> "conftest.nl"
-    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    as_fn_arith $ac_count + 1 && ac_count=$as_val
-    if test $ac_count -gt ${ac_path_GREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_GREP="$ac_path_GREP"
-      ac_path_GREP_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-      $ac_path_GREP_found && break 3
-    done
-  done
-  done
-IFS=$as_save_IFS
-  if test -z "$ac_cv_path_GREP"; then
-    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
-  fi
-else
-  ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
-   then ac_cv_path_EGREP="$GREP -E"
-   else
-     if test -z "$EGREP"; then
-  ac_path_EGREP_found=false
-  # Loop through the user's path and test for each of PROGNAME-LIST
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_prog in egrep; do
-    for ac_exec_ext in '' $ac_executable_extensions; do
-      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
-  # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
-  ac_count=0
-  $as_echo_n 0123456789 >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    $as_echo 'EGREP' >> "conftest.nl"
-    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    as_fn_arith $ac_count + 1 && ac_count=$as_val
-    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_EGREP="$ac_path_EGREP"
-      ac_path_EGREP_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-      $ac_path_EGREP_found && break 3
-    done
-  done
-  done
-IFS=$as_save_IFS
-  if test -z "$ac_cv_path_EGREP"; then
-    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
-  fi
-else
-  ac_cv_path_EGREP=$EGREP
-fi
-
-   fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_header_stdc=yes
-else
-  ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
-  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "free" >/dev/null 2>&1; then :
-
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-  if test "$cross_compiling" = yes; then :
-  :
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
-                  (('a' <= (c) && (c) <= 'i') \
-                    || ('j' <= (c) && (c) <= 'r') \
-                    || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
-  int i;
-  for (i = 0; i < 256; i++)
-    if (XOR (islower (i), ISLOWER (i))
-       || toupper (i) != TOUPPER (i))
-      return 2;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
-  ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
-                 inttypes.h stdint.h unistd.h
-do :
-  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-
-  ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
-if test "x$ac_cv_header_minix_config_h" = xyes; then :
-  MINIX=yes
-else
-  MINIX=
-fi
-
-
-  if test "$MINIX" = yes; then
-
-$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
-
-
-$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
-
-
-$as_echo "#define _MINIX 1" >>confdefs.h
-
-  fi
-
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
-$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
-if ${ac_cv_safe_to_define___extensions__+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-#         define __EXTENSIONS__ 1
-          $ac_includes_default
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_safe_to_define___extensions__=yes
-else
-  ac_cv_safe_to_define___extensions__=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
-$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
-  test $ac_cv_safe_to_define___extensions__ = yes &&
-    $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
-
-  $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
-
-  $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
-
-  $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
-
-  $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
-
-
-
-
-# We need to compile and run a program on the build machine.  A
-# comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in
-# the AC archive is broken for autoconf 2.57.  Given that there is no
-# newer version of that macro, we assume that it is also broken for
-# autoconf 2.61 and thus we use a simple but usually sufficient
-# approach.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cc for build" >&5
-$as_echo_n "checking for cc for build... " >&6; }
-if test "$cross_compiling" = "yes"; then
-  CC_FOR_BUILD="${CC_FOR_BUILD-cc}"
-else
-  CC_FOR_BUILD="${CC_FOR_BUILD-$CC}"
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC_FOR_BUILD" >&5
-$as_echo "$CC_FOR_BUILD" >&6; }
-
-
-
-
-case `pwd` in
-  *\ * | *\    *)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
-$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
-esac
-
-
-
-macro_version='2.4.2'
-macro_revision='1.3337'
-
-
-
-
-
-
-
-
-
-
-
-
-
-ltmain="$ac_aux_dir/ltmain.sh"
-
-# Backslashify metacharacters that are still active within
-# double-quoted strings.
-sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\(["`\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# Sed substitution to delay expansion of an escaped single quote.
-delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
-
-# Sed substitution to avoid accidental globbing in evaled expressions
-no_glob_subst='s/\*/\\\*/g'
-
-ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
-ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
-$as_echo_n "checking how to print strings... " >&6; }
-# Test print first, because it will be a builtin if present.
-if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
-   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
-  ECHO='print -r --'
-elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
-  ECHO='printf %s\n'
-else
-  # Use this function as a fallback that always works.
-  func_fallback_echo ()
-  {
-    eval 'cat <<_LTECHO_EOF
-$1
-_LTECHO_EOF'
-  }
-  ECHO='func_fallback_echo'
-fi
-
-# func_echo_all arg...
-# Invoke $ECHO with all args, space-separated.
-func_echo_all ()
-{
-    $ECHO ""
-}
-
-case "$ECHO" in
-  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
-$as_echo "printf" >&6; } ;;
-  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
-$as_echo "print -r" >&6; } ;;
-  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
-$as_echo "cat" >&6; } ;;
-esac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
-$as_echo_n "checking for a sed that does not truncate output... " >&6; }
-if ${ac_cv_path_SED+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
-     for ac_i in 1 2 3 4 5 6 7; do
-       ac_script="$ac_script$as_nl$ac_script"
-     done
-     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
-     { ac_script=; unset ac_script;}
-     if test -z "$SED"; then
-  ac_path_SED_found=false
-  # Loop through the user's path and test for each of PROGNAME-LIST
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_prog in sed gsed; do
-    for ac_exec_ext in '' $ac_executable_extensions; do
-      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
-      as_fn_executable_p "$ac_path_SED" || continue
-# Check for GNU ac_path_SED and select it if it is found.
-  # Check for GNU $ac_path_SED
-case `"$ac_path_SED" --version 2>&1` in
-*GNU*)
-  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
-*)
-  ac_count=0
-  $as_echo_n 0123456789 >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    $as_echo '' >> "conftest.nl"
-    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    as_fn_arith $ac_count + 1 && ac_count=$as_val
-    if test $ac_count -gt ${ac_path_SED_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_SED="$ac_path_SED"
-      ac_path_SED_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-      $ac_path_SED_found && break 3
-    done
-  done
-  done
-IFS=$as_save_IFS
-  if test -z "$ac_cv_path_SED"; then
-    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
-  fi
-else
-  ac_cv_path_SED=$SED
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
-$as_echo "$ac_cv_path_SED" >&6; }
- SED="$ac_cv_path_SED"
-  rm -f conftest.sed
-
-test -z "$SED" && SED=sed
-Xsed="$SED -e 1s/^X//"
-
-
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
-$as_echo_n "checking for fgrep... " >&6; }
-if ${ac_cv_path_FGREP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
-   then ac_cv_path_FGREP="$GREP -F"
-   else
-     if test -z "$FGREP"; then
-  ac_path_FGREP_found=false
-  # Loop through the user's path and test for each of PROGNAME-LIST
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_prog in fgrep; do
-    for ac_exec_ext in '' $ac_executable_extensions; do
-      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
-      as_fn_executable_p "$ac_path_FGREP" || continue
-# Check for GNU ac_path_FGREP and select it if it is found.
-  # Check for GNU $ac_path_FGREP
-case `"$ac_path_FGREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
-*)
-  ac_count=0
-  $as_echo_n 0123456789 >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    $as_echo 'FGREP' >> "conftest.nl"
-    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    as_fn_arith $ac_count + 1 && ac_count=$as_val
-    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_FGREP="$ac_path_FGREP"
-      ac_path_FGREP_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-      $ac_path_FGREP_found && break 3
-    done
-  done
-  done
-IFS=$as_save_IFS
-  if test -z "$ac_cv_path_FGREP"; then
-    as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
-  fi
-else
-  ac_cv_path_FGREP=$FGREP
-fi
-
-   fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
-$as_echo "$ac_cv_path_FGREP" >&6; }
- FGREP="$ac_cv_path_FGREP"
-
-
-test -z "$GREP" && GREP=grep
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Check whether --with-gnu-ld was given.
-if test "${with_gnu_ld+set}" = set; then :
-  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
-else
-  with_gnu_ld=no
-fi
-
-ac_prog=ld
-if test "$GCC" = yes; then
-  # Check if gcc -print-prog-name=ld gives a path.
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
-$as_echo_n "checking for ld used by $CC... " >&6; }
-  case $host in
-  *-*-mingw*)
-    # gcc leaves a trailing carriage return which upsets mingw
-    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
-  *)
-    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
-  esac
-  case $ac_prog in
-    # Accept absolute paths.
-    [\\/]* | ?:[\\/]*)
-      re_direlt='/[^/][^/]*/\.\./'
-      # Canonicalize the pathname of ld
-      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
-      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
-       ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
-      done
-      test -z "$LD" && LD="$ac_prog"
-      ;;
-  "")
-    # If it fails, then pretend we aren't using GCC.
-    ac_prog=ld
-    ;;
-  *)
-    # If it is relative, then search for the first ld in PATH.
-    with_gnu_ld=unknown
-    ;;
-  esac
-elif test "$with_gnu_ld" = yes; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
-$as_echo_n "checking for GNU ld... " >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
-$as_echo_n "checking for non-GNU ld... " >&6; }
-fi
-if ${lt_cv_path_LD+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -z "$LD"; then
-  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-  for ac_dir in $PATH; do
-    IFS="$lt_save_ifs"
-    test -z "$ac_dir" && ac_dir=.
-    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
-      lt_cv_path_LD="$ac_dir/$ac_prog"
-      # Check to see if the program is GNU ld.  I'd rather use --version,
-      # but apparently some variants of GNU ld only accept -v.
-      # Break only if it was the GNU/non-GNU ld that we prefer.
-      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
-      *GNU* | *'with BFD'*)
-       test "$with_gnu_ld" != no && break
-       ;;
-      *)
-       test "$with_gnu_ld" != yes && break
-       ;;
-      esac
-    fi
-  done
-  IFS="$lt_save_ifs"
-else
-  lt_cv_path_LD="$LD" # Let the user override the test with a path.
-fi
-fi
-
-LD="$lt_cv_path_LD"
-if test -n "$LD"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
-$as_echo "$LD" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
-$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
-if ${lt_cv_prog_gnu_ld+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  # I'd rather use --version here, but apparently some GNU lds only accept -v.
-case `$LD -v 2>&1 </dev/null` in
-*GNU* | *'with BFD'*)
-  lt_cv_prog_gnu_ld=yes
-  ;;
-*)
-  lt_cv_prog_gnu_ld=no
-  ;;
-esac
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
-$as_echo "$lt_cv_prog_gnu_ld" >&6; }
-with_gnu_ld=$lt_cv_prog_gnu_ld
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
-$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
-if ${lt_cv_path_NM+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$NM"; then
-  # Let the user override the test.
-  lt_cv_path_NM="$NM"
-else
-  lt_nm_to_check="${ac_tool_prefix}nm"
-  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
-    lt_nm_to_check="$lt_nm_to_check nm"
-  fi
-  for lt_tmp_nm in $lt_nm_to_check; do
-    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
-      IFS="$lt_save_ifs"
-      test -z "$ac_dir" && ac_dir=.
-      tmp_nm="$ac_dir/$lt_tmp_nm"
-      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
-       # Check to see if the nm accepts a BSD-compat flag.
-       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
-       #   nm: unknown option "B" ignored
-       # Tru64's nm complains that /dev/null is an invalid object file
-       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
-       */dev/null* | *'Invalid file or object type'*)
-         lt_cv_path_NM="$tmp_nm -B"
-         break
-         ;;
-       *)
-         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
-         */dev/null*)
-           lt_cv_path_NM="$tmp_nm -p"
-           break
-           ;;
-         *)
-           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
-           continue # so that we can try to find one that supports BSD flags
-           ;;
-         esac
-         ;;
-       esac
-      fi
-    done
-    IFS="$lt_save_ifs"
-  done
-  : ${lt_cv_path_NM=no}
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
-$as_echo "$lt_cv_path_NM" >&6; }
-if test "$lt_cv_path_NM" != "no"; then
-  NM="$lt_cv_path_NM"
-else
-  # Didn't find any BSD compatible name lister, look for dumpbin.
-  if test -n "$DUMPBIN"; then :
-    # Let the user override the test.
-  else
-    if test -n "$ac_tool_prefix"; then
-  for ac_prog in dumpbin "link -dump"
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DUMPBIN+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$DUMPBIN"; then
-  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-DUMPBIN=$ac_cv_prog_DUMPBIN
-if test -n "$DUMPBIN"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
-$as_echo "$DUMPBIN" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-    test -n "$DUMPBIN" && break
-  done
-fi
-if test -z "$DUMPBIN"; then
-  ac_ct_DUMPBIN=$DUMPBIN
-  for ac_prog in dumpbin "link -dump"
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_DUMPBIN"; then
-  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
-if test -n "$ac_ct_DUMPBIN"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
-$as_echo "$ac_ct_DUMPBIN" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$ac_ct_DUMPBIN" && break
-done
-
-  if test "x$ac_ct_DUMPBIN" = x; then
-    DUMPBIN=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    DUMPBIN=$ac_ct_DUMPBIN
-  fi
-fi
-
-    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
-    *COFF*)
-      DUMPBIN="$DUMPBIN -symbols"
-      ;;
-    *)
-      DUMPBIN=:
-      ;;
-    esac
-  fi
-
-  if test "$DUMPBIN" != ":"; then
-    NM="$DUMPBIN"
-  fi
-fi
-test -z "$NM" && NM=nm
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
-$as_echo_n "checking the name lister ($NM) interface... " >&6; }
-if ${lt_cv_nm_interface+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_nm_interface="BSD nm"
-  echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
-  (eval "$ac_compile" 2>conftest.err)
-  cat conftest.err >&5
-  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
-  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
-  cat conftest.err >&5
-  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
-  cat conftest.out >&5
-  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
-    lt_cv_nm_interface="MS dumpbin"
-  fi
-  rm -f conftest*
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
-$as_echo "$lt_cv_nm_interface" >&6; }
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
-$as_echo_n "checking whether ln -s works... " >&6; }
-LN_S=$as_ln_s
-if test "$LN_S" = "ln -s"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
-$as_echo "no, using $LN_S" >&6; }
-fi
-
-# find the maximum length of command line arguments
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
-$as_echo_n "checking the maximum length of command line arguments... " >&6; }
-if ${lt_cv_sys_max_cmd_len+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-    i=0
-  teststring="ABCD"
-
-  case $build_os in
-  msdosdjgpp*)
-    # On DJGPP, this test can blow up pretty badly due to problems in libc
-    # (any single argument exceeding 2000 bytes causes a buffer overrun
-    # during glob expansion).  Even if it were fixed, the result of this
-    # check would be larger than it should be.
-    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
-    ;;
-
-  gnu*)
-    # Under GNU Hurd, this test is not required because there is
-    # no limit to the length of command line arguments.
-    # Libtool will interpret -1 as no limit whatsoever
-    lt_cv_sys_max_cmd_len=-1;
-    ;;
-
-  cygwin* | mingw* | cegcc*)
-    # On Win9x/ME, this test blows up -- it succeeds, but takes
-    # about 5 minutes as the teststring grows exponentially.
-    # Worse, since 9x/ME are not pre-emptively multitasking,
-    # you end up with a "frozen" computer, even though with patience
-    # the test eventually succeeds (with a max line length of 256k).
-    # Instead, let's just punt: use the minimum linelength reported by
-    # all of the supported platforms: 8192 (on NT/2K/XP).
-    lt_cv_sys_max_cmd_len=8192;
-    ;;
-
-  mint*)
-    # On MiNT this can take a long time and run out of memory.
-    lt_cv_sys_max_cmd_len=8192;
-    ;;
-
-  amigaos*)
-    # On AmigaOS with pdksh, this test takes hours, literally.
-    # So we just punt and use a minimum line length of 8192.
-    lt_cv_sys_max_cmd_len=8192;
-    ;;
-
-  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
-    # This has been around since 386BSD, at least.  Likely further.
-    if test -x /sbin/sysctl; then
-      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
-    elif test -x /usr/sbin/sysctl; then
-      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
-    else
-      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
-    fi
-    # And add a safety zone
-    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
-    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
-    ;;
-
-  interix*)
-    # We know the value 262144 and hardcode it with a safety zone (like BSD)
-    lt_cv_sys_max_cmd_len=196608
-    ;;
-
-  os2*)
-    # The test takes a long time on OS/2.
-    lt_cv_sys_max_cmd_len=8192
-    ;;
-
-  osf*)
-    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
-    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
-    # nice to cause kernel panics so lets avoid the loop below.
-    # First set a reasonable default.
-    lt_cv_sys_max_cmd_len=16384
-    #
-    if test -x /sbin/sysconfig; then
-      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
-        *1*) lt_cv_sys_max_cmd_len=-1 ;;
-      esac
-    fi
-    ;;
-  sco3.2v5*)
-    lt_cv_sys_max_cmd_len=102400
-    ;;
-  sysv5* | sco5v6* | sysv4.2uw2*)
-    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
-    if test -n "$kargmax"; then
-      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[         ]//'`
-    else
-      lt_cv_sys_max_cmd_len=32768
-    fi
-    ;;
-  *)
-    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
-    if test -n "$lt_cv_sys_max_cmd_len"; then
-      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
-      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
-    else
-      # Make teststring a little bigger before we do anything with it.
-      # a 1K string should be a reasonable start.
-      for i in 1 2 3 4 5 6 7 8 ; do
-        teststring=$teststring$teststring
-      done
-      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
-      # If test is not a shell built-in, we'll probably end up computing a
-      # maximum length that is only half of the actual maximum length, but
-      # we can't tell.
-      while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \
-                = "X$teststring$teststring"; } >/dev/null 2>&1 &&
-             test $i != 17 # 1/2 MB should be enough
-      do
-        i=`expr $i + 1`
-        teststring=$teststring$teststring
-      done
-      # Only check the string length outside the loop.
-      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
-      teststring=
-      # Add a significant safety factor because C++ compilers can tack on
-      # massive amounts of additional arguments before passing them to the
-      # linker.  It appears as though 1/2 is a usable value.
-      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
-    fi
-    ;;
-  esac
-
-fi
-
-if test -n $lt_cv_sys_max_cmd_len ; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
-$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
-$as_echo "none" >&6; }
-fi
-max_cmd_len=$lt_cv_sys_max_cmd_len
-
-
-
-
-
-
-: ${CP="cp -f"}
-: ${MV="mv -f"}
-: ${RM="rm -f"}
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
-$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
-# Try some XSI features
-xsi_shell=no
-( _lt_dummy="a/b/c"
-  test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
-      = c,a/b,b/c, \
-    && eval 'test $(( 1 + 1 )) -eq 2 \
-    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
-  && xsi_shell=yes
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
-$as_echo "$xsi_shell" >&6; }
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
-$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
-lt_shell_append=no
-( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
-    >/dev/null 2>&1 \
-  && lt_shell_append=yes
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
-$as_echo "$lt_shell_append" >&6; }
-
-
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  lt_unset=unset
-else
-  lt_unset=false
-fi
-
-
-
-
-
-# test EBCDIC or ASCII
-case `echo X|tr X '\101'` in
- A) # ASCII based system
-    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
-  lt_SP2NL='tr \040 \012'
-  lt_NL2SP='tr \015\012 \040\040'
-  ;;
- *) # EBCDIC based system
-  lt_SP2NL='tr \100 \n'
-  lt_NL2SP='tr \r\n \100\100'
-  ;;
-esac
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
-$as_echo_n "checking how to convert $build file names to $host format... " >&6; }
-if ${lt_cv_to_host_file_cmd+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $host in
-  *-*-mingw* )
-    case $build in
-      *-*-mingw* ) # actually msys
-        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
-        ;;
-      *-*-cygwin* )
-        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
-        ;;
-      * ) # otherwise, assume *nix
-        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
-        ;;
-    esac
-    ;;
-  *-*-cygwin* )
-    case $build in
-      *-*-mingw* ) # actually msys
-        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
-        ;;
-      *-*-cygwin* )
-        lt_cv_to_host_file_cmd=func_convert_file_noop
-        ;;
-      * ) # otherwise, assume *nix
-        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
-        ;;
-    esac
-    ;;
-  * ) # unhandled hosts (and "normal" native builds)
-    lt_cv_to_host_file_cmd=func_convert_file_noop
-    ;;
-esac
-
-fi
-
-to_host_file_cmd=$lt_cv_to_host_file_cmd
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
-$as_echo "$lt_cv_to_host_file_cmd" >&6; }
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
-$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; }
-if ${lt_cv_to_tool_file_cmd+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  #assume ordinary cross tools, or native build.
-lt_cv_to_tool_file_cmd=func_convert_file_noop
-case $host in
-  *-*-mingw* )
-    case $build in
-      *-*-mingw* ) # actually msys
-        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
-        ;;
-    esac
-    ;;
-esac
-
-fi
-
-to_tool_file_cmd=$lt_cv_to_tool_file_cmd
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
-$as_echo "$lt_cv_to_tool_file_cmd" >&6; }
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
-$as_echo_n "checking for $LD option to reload object files... " >&6; }
-if ${lt_cv_ld_reload_flag+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_ld_reload_flag='-r'
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
-$as_echo "$lt_cv_ld_reload_flag" >&6; }
-reload_flag=$lt_cv_ld_reload_flag
-case $reload_flag in
-"" | " "*) ;;
-*) reload_flag=" $reload_flag" ;;
-esac
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-case $host_os in
-  cygwin* | mingw* | pw32* | cegcc*)
-    if test "$GCC" != yes; then
-      reload_cmds=false
-    fi
-    ;;
-  darwin*)
-    if test "$GCC" = yes; then
-      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
-    else
-      reload_cmds='$LD$reload_flag -o $output$reload_objs'
-    fi
-    ;;
-esac
-
-
-
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
-set dummy ${ac_tool_prefix}objdump; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_OBJDUMP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$OBJDUMP"; then
-  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-OBJDUMP=$ac_cv_prog_OBJDUMP
-if test -n "$OBJDUMP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
-$as_echo "$OBJDUMP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_OBJDUMP"; then
-  ac_ct_OBJDUMP=$OBJDUMP
-  # Extract the first word of "objdump", so it can be a program name with args.
-set dummy objdump; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_OBJDUMP"; then
-  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_OBJDUMP="objdump"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
-if test -n "$ac_ct_OBJDUMP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
-$as_echo "$ac_ct_OBJDUMP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_OBJDUMP" = x; then
-    OBJDUMP="false"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    OBJDUMP=$ac_ct_OBJDUMP
-  fi
-else
-  OBJDUMP="$ac_cv_prog_OBJDUMP"
-fi
-
-test -z "$OBJDUMP" && OBJDUMP=objdump
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
-$as_echo_n "checking how to recognize dependent libraries... " >&6; }
-if ${lt_cv_deplibs_check_method+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_file_magic_cmd='$MAGIC_CMD'
-lt_cv_file_magic_test_file=
-lt_cv_deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [[regex]]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given extended regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-
-case $host_os in
-aix[4-9]*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-beos*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-bsdi[45]*)
-  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
-  lt_cv_file_magic_cmd='/usr/bin/file -L'
-  lt_cv_file_magic_test_file=/shlib/libc.so
-  ;;
-
-cygwin*)
-  # func_win32_libid is a shell function defined in ltmain.sh
-  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
-  lt_cv_file_magic_cmd='func_win32_libid'
-  ;;
-
-mingw* | pw32*)
-  # Base MSYS/MinGW do not provide the 'file' command needed by
-  # func_win32_libid shell function, so use a weaker test based on 'objdump',
-  # unless we find 'file', for example because we are cross-compiling.
-  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
-  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
-    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
-    lt_cv_file_magic_cmd='func_win32_libid'
-  else
-    # Keep this pattern in sync with the one in func_win32_libid.
-    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
-    lt_cv_file_magic_cmd='$OBJDUMP -f'
-  fi
-  ;;
-
-cegcc*)
-  # use the weaker test based on 'objdump'. See mingw*.
-  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
-  lt_cv_file_magic_cmd='$OBJDUMP -f'
-  ;;
-
-darwin* | rhapsody*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-freebsd* | dragonfly*)
-  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
-    case $host_cpu in
-    i*86 )
-      # Not sure whether the presence of OpenBSD here was a mistake.
-      # Let's accept both of them until this is cleared up.
-      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
-      lt_cv_file_magic_cmd=/usr/bin/file
-      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
-      ;;
-    esac
-  else
-    lt_cv_deplibs_check_method=pass_all
-  fi
-  ;;
-
-gnu*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-haiku*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-hpux10.20* | hpux11*)
-  lt_cv_file_magic_cmd=/usr/bin/file
-  case $host_cpu in
-  ia64*)
-    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
-    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
-    ;;
-  hppa*64*)
-    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
-    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
-    ;;
-  *)
-    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
-    lt_cv_file_magic_test_file=/usr/lib/libc.sl
-    ;;
-  esac
-  ;;
-
-interix[3-9]*)
-  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
-  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
-  ;;
-
-irix5* | irix6* | nonstopux*)
-  case $LD in
-  *-32|*"-32 ") libmagic=32-bit;;
-  *-n32|*"-n32 ") libmagic=N32;;
-  *-64|*"-64 ") libmagic=64-bit;;
-  *) libmagic=never-match;;
-  esac
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-netbsd* | netbsdelf*-gnu)
-  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
-    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
-  else
-    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
-  fi
-  ;;
-
-newos6*)
-  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
-  lt_cv_file_magic_cmd=/usr/bin/file
-  lt_cv_file_magic_test_file=/usr/lib/libnls.so
-  ;;
-
-*nto* | *qnx*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-openbsd*)
-  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
-    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
-  else
-    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
-  fi
-  ;;
-
-osf3* | osf4* | osf5*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-rdos*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-solaris*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-
-sysv4 | sysv4.3*)
-  case $host_vendor in
-  motorola)
-    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
-    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
-    ;;
-  ncr)
-    lt_cv_deplibs_check_method=pass_all
-    ;;
-  sequent)
-    lt_cv_file_magic_cmd='/bin/file'
-    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
-    ;;
-  sni)
-    lt_cv_file_magic_cmd='/bin/file'
-    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
-    lt_cv_file_magic_test_file=/lib/libc.so
-    ;;
-  siemens)
-    lt_cv_deplibs_check_method=pass_all
-    ;;
-  pc)
-    lt_cv_deplibs_check_method=pass_all
-    ;;
-  esac
-  ;;
-
-tpf*)
-  lt_cv_deplibs_check_method=pass_all
-  ;;
-esac
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
-$as_echo "$lt_cv_deplibs_check_method" >&6; }
-
-file_magic_glob=
-want_nocaseglob=no
-if test "$build" = "$host"; then
-  case $host_os in
-  mingw* | pw32*)
-    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
-      want_nocaseglob=yes
-    else
-      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
-    fi
-    ;;
-  esac
-fi
-
-file_magic_cmd=$lt_cv_file_magic_cmd
-deplibs_check_method=$lt_cv_deplibs_check_method
-test -z "$deplibs_check_method" && deplibs_check_method=unknown
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
-set dummy ${ac_tool_prefix}dlltool; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DLLTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$DLLTOOL"; then
-  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-DLLTOOL=$ac_cv_prog_DLLTOOL
-if test -n "$DLLTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
-$as_echo "$DLLTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_DLLTOOL"; then
-  ac_ct_DLLTOOL=$DLLTOOL
-  # Extract the first word of "dlltool", so it can be a program name with args.
-set dummy dlltool; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_DLLTOOL"; then
-  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
-if test -n "$ac_ct_DLLTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
-$as_echo "$ac_ct_DLLTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_DLLTOOL" = x; then
-    DLLTOOL="false"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    DLLTOOL=$ac_ct_DLLTOOL
-  fi
-else
-  DLLTOOL="$ac_cv_prog_DLLTOOL"
-fi
-
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
-$as_echo_n "checking how to associate runtime and link libraries... " >&6; }
-if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_sharedlib_from_linklib_cmd='unknown'
-
-case $host_os in
-cygwin* | mingw* | pw32* | cegcc*)
-  # two different shell functions defined in ltmain.sh
-  # decide which to use based on capabilities of $DLLTOOL
-  case `$DLLTOOL --help 2>&1` in
-  *--identify-strict*)
-    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
-    ;;
-  *)
-    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
-    ;;
-  esac
-  ;;
-*)
-  # fallback: assume linklib IS sharedlib
-  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
-  ;;
-esac
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
-$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
-sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
-test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
-
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
-  for ac_prog in ar
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AR+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$AR"; then
-  ac_cv_prog_AR="$AR" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-AR=$ac_cv_prog_AR
-if test -n "$AR"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-    test -n "$AR" && break
-  done
-fi
-if test -z "$AR"; then
-  ac_ct_AR=$AR
-  for ac_prog in ar
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_AR+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_AR"; then
-  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_AR="$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_AR=$ac_cv_prog_ac_ct_AR
-if test -n "$ac_ct_AR"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
-$as_echo "$ac_ct_AR" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$ac_ct_AR" && break
-done
-
-  if test "x$ac_ct_AR" = x; then
-    AR="false"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    AR=$ac_ct_AR
-  fi
-fi
-
-: ${AR=ar}
-: ${AR_FLAGS=cru}
-
-
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
-$as_echo_n "checking for archiver @FILE support... " >&6; }
-if ${lt_cv_ar_at_file+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_ar_at_file=no
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  echo conftest.$ac_objext > conftest.lst
-      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
-      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
-  (eval $lt_ar_try) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }
-      if test "$ac_status" -eq 0; then
-       # Ensure the archiver fails upon bogus file names.
-       rm -f conftest.$ac_objext libconftest.a
-       { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
-  (eval $lt_ar_try) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }
-       if test "$ac_status" -ne 0; then
-          lt_cv_ar_at_file=@
-        fi
-      fi
-      rm -f conftest.* libconftest.a
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
-$as_echo "$lt_cv_ar_at_file" >&6; }
-
-if test "x$lt_cv_ar_at_file" = xno; then
-  archiver_list_spec=
-else
-  archiver_list_spec=$lt_cv_ar_at_file
-fi
-
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
-set dummy ${ac_tool_prefix}strip; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_STRIP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$STRIP"; then
-  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-STRIP=$ac_cv_prog_STRIP
-if test -n "$STRIP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
-$as_echo "$STRIP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_STRIP"; then
-  ac_ct_STRIP=$STRIP
-  # Extract the first word of "strip", so it can be a program name with args.
-set dummy strip; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_STRIP"; then
-  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_STRIP="strip"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
-if test -n "$ac_ct_STRIP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
-$as_echo "$ac_ct_STRIP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_STRIP" = x; then
-    STRIP=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    STRIP=$ac_ct_STRIP
-  fi
-else
-  STRIP="$ac_cv_prog_STRIP"
-fi
-
-test -z "$STRIP" && STRIP=:
-
-
-
-
-
-
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$RANLIB"; then
-  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
-  ac_ct_RANLIB=$RANLIB
-  # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_RANLIB"; then
-  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_RANLIB="ranlib"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_RANLIB" = x; then
-    RANLIB=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    RANLIB=$ac_ct_RANLIB
-  fi
-else
-  RANLIB="$ac_cv_prog_RANLIB"
-fi
-
-test -z "$RANLIB" && RANLIB=:
-
-
-
-
-
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-if test -n "$RANLIB"; then
-  case $host_os in
-  openbsd*)
-    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
-    ;;
-  *)
-    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
-    ;;
-  esac
-  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
-fi
-
-case $host_os in
-  darwin*)
-    lock_old_archive_extraction=yes ;;
-  *)
-    lock_old_archive_extraction=no ;;
-esac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
-$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
-if ${lt_cv_sys_global_symbol_pipe+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[BCDEGRST]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
-
-# Define system-specific variables.
-case $host_os in
-aix*)
-  symcode='[BCDT]'
-  ;;
-cygwin* | mingw* | pw32* | cegcc*)
-  symcode='[ABCDGISTW]'
-  ;;
-hpux*)
-  if test "$host_cpu" = ia64; then
-    symcode='[ABCDEGRST]'
-  fi
-  ;;
-irix* | nonstopux*)
-  symcode='[BCDEGRST]'
-  ;;
-osf*)
-  symcode='[BCDEGQRST]'
-  ;;
-solaris*)
-  symcode='[BDRT]'
-  ;;
-sco3.2v5*)
-  symcode='[DT]'
-  ;;
-sysv4.2uw2*)
-  symcode='[DT]'
-  ;;
-sysv5* | sco5v6* | unixware* | OpenUNIX*)
-  symcode='[ABDT]'
-  ;;
-sysv4)
-  symcode='[DFNSTU]'
-  ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-case `$NM -V 2>&1` in
-*GNU* | *'with BFD'*)
-  symcode='[ABCDGIRSTW]' ;;
-esac
-
-# Transform an extracted symbol line into a proper C declaration.
-# Some systems (esp. on ia64) link data and code symbols differently,
-# so use this general approach.
-lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
-
-# Transform an extracted symbol line into symbol name and symbol address
-lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
-
-# Handle CRLF in mingw tool chain
-opt_cr=
-case $build_os in
-mingw*)
-  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
-  ;;
-esac
-
-# Try without a prefix underscore, then with it.
-for ac_symprfx in "" "_"; do
-
-  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
-  symxfrm="\\1 $ac_symprfx\\2 \\2"
-
-  # Write the raw and C identifiers.
-  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
-    # Fake it for dumpbin and say T for any non-static function
-    # and D for any global variable.
-    # Also find C++ and __fastcall symbols from MSVC++,
-    # which start with @ or ?.
-    lt_cv_sys_global_symbol_pipe="$AWK '"\
-"     {last_section=section; section=\$ 3};"\
-"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
-"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
-"     \$ 0!~/External *\|/{next};"\
-"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
-"     {if(hide[section]) next};"\
-"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
-"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
-"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
-"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
-"     ' prfx=^$ac_symprfx"
-  else
-    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[     ]\($symcode$symcode*\)[         ][      ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
-  fi
-  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
-
-  # Check to see that the pipe works correctly.
-  pipe_works=no
-
-  rm -f conftest*
-  cat > conftest.$ac_ext <<_LT_EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(void);
-void nm_test_func(void){}
-#ifdef __cplusplus
-}
-#endif
-int main(){nm_test_var='a';nm_test_func();return(0);}
-_LT_EOF
-
-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-    # Now try to grab the symbols.
-    nlist=conftest.nm
-    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
-  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && test -s "$nlist"; then
-      # Try sorting and uniquifying the output.
-      if sort "$nlist" | uniq > "$nlist"T; then
-       mv -f "$nlist"T "$nlist"
-      else
-       rm -f "$nlist"T
-      fi
-
-      # Make sure that we snagged all the symbols we need.
-      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
-       if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
-         cat <<_LT_EOF > conftest.$ac_ext
-/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
-#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
-/* DATA imports from DLLs on WIN32 con't be const, because runtime
-   relocations are performed -- see ld's documentation on pseudo-relocs.  */
-# define LT_DLSYM_CONST
-#elif defined(__osf__)
-/* This system does not cope well with relocations in const data.  */
-# define LT_DLSYM_CONST
-#else
-# define LT_DLSYM_CONST const
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-_LT_EOF
-         # Now generate the symbol file.
-         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
-
-         cat <<_LT_EOF >> conftest.$ac_ext
-
-/* The mapping between symbol names and symbols.  */
-LT_DLSYM_CONST struct {
-  const char *name;
-  void       *address;
-}
-lt__PROGRAM__LTX_preloaded_symbols[] =
-{
-  { "@PROGRAM@", (void *) 0 },
-_LT_EOF
-         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
-         cat <<\_LT_EOF >> conftest.$ac_ext
-  {0, (void *) 0}
-};
-
-/* This works around a problem in FreeBSD linker */
-#ifdef FREEBSD_WORKAROUND
-static const void *lt_preloaded_setup() {
-  return lt__PROGRAM__LTX_preloaded_symbols;
-}
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-_LT_EOF
-         # Now try linking the two files.
-         mv conftest.$ac_objext conftstm.$ac_objext
-         lt_globsym_save_LIBS=$LIBS
-         lt_globsym_save_CFLAGS=$CFLAGS
-         LIBS="conftstm.$ac_objext"
-         CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
-         if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
-           pipe_works=yes
-         fi
-         LIBS=$lt_globsym_save_LIBS
-         CFLAGS=$lt_globsym_save_CFLAGS
-       else
-         echo "cannot find nm_test_func in $nlist" >&5
-       fi
-      else
-       echo "cannot find nm_test_var in $nlist" >&5
-      fi
-    else
-      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
-    fi
-  else
-    echo "$progname: failed program was:" >&5
-    cat conftest.$ac_ext >&5
-  fi
-  rm -rf conftest* conftst*
-
-  # Do not use the global_symbol_pipe unless it works.
-  if test "$pipe_works" = yes; then
-    break
-  else
-    lt_cv_sys_global_symbol_pipe=
-  fi
-done
-
-fi
-
-if test -z "$lt_cv_sys_global_symbol_pipe"; then
-  lt_cv_sys_global_symbol_to_cdecl=
-fi
-if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
-$as_echo "failed" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
-$as_echo "ok" >&6; }
-fi
-
-# Response file support.
-if test "$lt_cv_nm_interface" = "MS dumpbin"; then
-  nm_file_list_spec='@'
-elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
-  nm_file_list_spec='@'
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
-$as_echo_n "checking for sysroot... " >&6; }
-
-# Check whether --with-sysroot was given.
-if test "${with_sysroot+set}" = set; then :
-  withval=$with_sysroot;
-else
-  with_sysroot=no
-fi
-
-
-lt_sysroot=
-case ${with_sysroot} in #(
- yes)
-   if test "$GCC" = yes; then
-     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
-   fi
-   ;; #(
- /*)
-   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
-   ;; #(
- no|'')
-   ;; #(
- *)
-   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5
-$as_echo "${with_sysroot}" >&6; }
-   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
-   ;;
-esac
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
-$as_echo "${lt_sysroot:-no}" >&6; }
-
-
-
-
-
-# Check whether --enable-libtool-lock was given.
-if test "${enable_libtool_lock+set}" = set; then :
-  enableval=$enable_libtool_lock;
-fi
-
-test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
-
-# Some flags need to be propagated to the compiler or linker for good
-# libtool support.
-case $host in
-ia64-*-hpux*)
-  # Find out which ABI we are using.
-  echo 'int i;' > conftest.$ac_ext
-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-    case `/usr/bin/file conftest.$ac_objext` in
-      *ELF-32*)
-       HPUX_IA64_MODE="32"
-       ;;
-      *ELF-64*)
-       HPUX_IA64_MODE="64"
-       ;;
-    esac
-  fi
-  rm -rf conftest*
-  ;;
-*-*-irix6*)
-  # Find out which ABI we are using.
-  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-    if test "$lt_cv_prog_gnu_ld" = yes; then
-      case `/usr/bin/file conftest.$ac_objext` in
-       *32-bit*)
-         LD="${LD-ld} -melf32bsmip"
-         ;;
-       *N32*)
-         LD="${LD-ld} -melf32bmipn32"
-         ;;
-       *64-bit*)
-         LD="${LD-ld} -melf64bmip"
-       ;;
-      esac
-    else
-      case `/usr/bin/file conftest.$ac_objext` in
-       *32-bit*)
-         LD="${LD-ld} -32"
-         ;;
-       *N32*)
-         LD="${LD-ld} -n32"
-         ;;
-       *64-bit*)
-         LD="${LD-ld} -64"
-         ;;
-      esac
-    fi
-  fi
-  rm -rf conftest*
-  ;;
-
-x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
-s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
-  # Find out which ABI we are using.
-  echo 'int i;' > conftest.$ac_ext
-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-    case `/usr/bin/file conftest.o` in
-      *32-bit*)
-       case $host in
-         x86_64-*kfreebsd*-gnu)
-           LD="${LD-ld} -m elf_i386_fbsd"
-           ;;
-         x86_64-*linux*)
-           LD="${LD-ld} -m elf_i386"
-           ;;
-         powerpc64le-*)
-           LD="${LD-ld} -m elf32lppclinux"
-           ;;
-         powerpc64-*)
-           LD="${LD-ld} -m elf32ppclinux"
-           ;;
-         s390x-*linux*)
-           LD="${LD-ld} -m elf_s390"
-           ;;
-         sparc64-*linux*)
-           LD="${LD-ld} -m elf32_sparc"
-           ;;
-       esac
-       ;;
-      *64-bit*)
-       case $host in
-         x86_64-*kfreebsd*-gnu)
-           LD="${LD-ld} -m elf_x86_64_fbsd"
-           ;;
-         x86_64-*linux*)
-           LD="${LD-ld} -m elf_x86_64"
-           ;;
-         powerpcle-*)
-           LD="${LD-ld} -m elf64lppc"
-           ;;
-         powerpc-*)
-           LD="${LD-ld} -m elf64ppc"
-           ;;
-         s390*-*linux*|s390*-*tpf*)
-           LD="${LD-ld} -m elf64_s390"
-           ;;
-         sparc*-*linux*)
-           LD="${LD-ld} -m elf64_sparc"
-           ;;
-       esac
-       ;;
-    esac
-  fi
-  rm -rf conftest*
-  ;;
-
-*-*-sco3.2v5*)
-  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
-  SAVE_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -belf"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
-$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
-if ${lt_cv_cc_needs_belf+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  lt_cv_cc_needs_belf=yes
-else
-  lt_cv_cc_needs_belf=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-     ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
-$as_echo "$lt_cv_cc_needs_belf" >&6; }
-  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
-    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
-    CFLAGS="$SAVE_CFLAGS"
-  fi
-  ;;
-*-*solaris*)
-  # Find out which ABI we are using.
-  echo 'int i;' > conftest.$ac_ext
-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-    case `/usr/bin/file conftest.o` in
-    *64-bit*)
-      case $lt_cv_prog_gnu_ld in
-      yes*)
-        case $host in
-        i?86-*-solaris*)
-          LD="${LD-ld} -m elf_x86_64"
-          ;;
-        sparc*-*-solaris*)
-          LD="${LD-ld} -m elf64_sparc"
-          ;;
-        esac
-        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
-        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
-          LD="${LD-ld}_sol2"
-        fi
-        ;;
-      *)
-       if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
-         LD="${LD-ld} -64"
-       fi
-       ;;
-      esac
-      ;;
-    esac
-  fi
-  rm -rf conftest*
-  ;;
-esac
-
-need_locks="$enable_libtool_lock"
-
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
-set dummy ${ac_tool_prefix}mt; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$MANIFEST_TOOL"; then
-  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
-if test -n "$MANIFEST_TOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
-$as_echo "$MANIFEST_TOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
-  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
-  # Extract the first word of "mt", so it can be a program name with args.
-set dummy mt; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_MANIFEST_TOOL"; then
-  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
-if test -n "$ac_ct_MANIFEST_TOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
-$as_echo "$ac_ct_MANIFEST_TOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_MANIFEST_TOOL" = x; then
-    MANIFEST_TOOL=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
-  fi
-else
-  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
-fi
-
-test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
-$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
-if ${lt_cv_path_mainfest_tool+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_path_mainfest_tool=no
-  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
-  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
-  cat conftest.err >&5
-  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
-    lt_cv_path_mainfest_tool=yes
-  fi
-  rm -f conftest*
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
-$as_echo "$lt_cv_path_mainfest_tool" >&6; }
-if test "x$lt_cv_path_mainfest_tool" != xyes; then
-  MANIFEST_TOOL=:
-fi
-
-
-
-
-
-
-  case $host_os in
-    rhapsody* | darwin*)
-    if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
-set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DSYMUTIL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$DSYMUTIL"; then
-  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-DSYMUTIL=$ac_cv_prog_DSYMUTIL
-if test -n "$DSYMUTIL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
-$as_echo "$DSYMUTIL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_DSYMUTIL"; then
-  ac_ct_DSYMUTIL=$DSYMUTIL
-  # Extract the first word of "dsymutil", so it can be a program name with args.
-set dummy dsymutil; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_DSYMUTIL"; then
-  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
-if test -n "$ac_ct_DSYMUTIL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
-$as_echo "$ac_ct_DSYMUTIL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_DSYMUTIL" = x; then
-    DSYMUTIL=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    DSYMUTIL=$ac_ct_DSYMUTIL
-  fi
-else
-  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
-fi
-
-    if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
-set dummy ${ac_tool_prefix}nmedit; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_NMEDIT+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$NMEDIT"; then
-  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-NMEDIT=$ac_cv_prog_NMEDIT
-if test -n "$NMEDIT"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
-$as_echo "$NMEDIT" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_NMEDIT"; then
-  ac_ct_NMEDIT=$NMEDIT
-  # Extract the first word of "nmedit", so it can be a program name with args.
-set dummy nmedit; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_NMEDIT"; then
-  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_NMEDIT="nmedit"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
-if test -n "$ac_ct_NMEDIT"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
-$as_echo "$ac_ct_NMEDIT" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_NMEDIT" = x; then
-    NMEDIT=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    NMEDIT=$ac_ct_NMEDIT
-  fi
-else
-  NMEDIT="$ac_cv_prog_NMEDIT"
-fi
-
-    if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
-set dummy ${ac_tool_prefix}lipo; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_LIPO+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$LIPO"; then
-  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-LIPO=$ac_cv_prog_LIPO
-if test -n "$LIPO"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
-$as_echo "$LIPO" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_LIPO"; then
-  ac_ct_LIPO=$LIPO
-  # Extract the first word of "lipo", so it can be a program name with args.
-set dummy lipo; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_LIPO"; then
-  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_LIPO="lipo"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
-if test -n "$ac_ct_LIPO"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
-$as_echo "$ac_ct_LIPO" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_LIPO" = x; then
-    LIPO=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    LIPO=$ac_ct_LIPO
-  fi
-else
-  LIPO="$ac_cv_prog_LIPO"
-fi
-
-    if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
-set dummy ${ac_tool_prefix}otool; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_OTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$OTOOL"; then
-  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-OTOOL=$ac_cv_prog_OTOOL
-if test -n "$OTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
-$as_echo "$OTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_OTOOL"; then
-  ac_ct_OTOOL=$OTOOL
-  # Extract the first word of "otool", so it can be a program name with args.
-set dummy otool; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_OTOOL"; then
-  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_OTOOL="otool"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
-if test -n "$ac_ct_OTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
-$as_echo "$ac_ct_OTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_OTOOL" = x; then
-    OTOOL=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    OTOOL=$ac_ct_OTOOL
-  fi
-else
-  OTOOL="$ac_cv_prog_OTOOL"
-fi
-
-    if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
-set dummy ${ac_tool_prefix}otool64; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_OTOOL64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$OTOOL64"; then
-  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-OTOOL64=$ac_cv_prog_OTOOL64
-if test -n "$OTOOL64"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
-$as_echo "$OTOOL64" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_OTOOL64"; then
-  ac_ct_OTOOL64=$OTOOL64
-  # Extract the first word of "otool64", so it can be a program name with args.
-set dummy otool64; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_OTOOL64"; then
-  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_OTOOL64="otool64"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
-if test -n "$ac_ct_OTOOL64"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
-$as_echo "$ac_ct_OTOOL64" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_OTOOL64" = x; then
-    OTOOL64=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    OTOOL64=$ac_ct_OTOOL64
-  fi
-else
-  OTOOL64="$ac_cv_prog_OTOOL64"
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
-$as_echo_n "checking for -single_module linker flag... " >&6; }
-if ${lt_cv_apple_cc_single_mod+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_apple_cc_single_mod=no
-      if test -z "${LT_MULTI_MODULE}"; then
-       # By default we will add the -single_module flag. You can override
-       # by either setting the environment variable LT_MULTI_MODULE
-       # non-empty at configure time, or by adding -multi_module to the
-       # link flags.
-       rm -rf libconftest.dylib*
-       echo "int foo(void){return 1;}" > conftest.c
-       echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
--dynamiclib -Wl,-single_module conftest.c" >&5
-       $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
-         -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
-        _lt_result=$?
-       # If there is a non-empty error log, and "single_module"
-       # appears in it, assume the flag caused a linker warning
-        if test -s conftest.err && $GREP single_module conftest.err; then
-         cat conftest.err >&5
-       # Otherwise, if the output was created with a 0 exit code from
-       # the compiler, it worked.
-       elif test -f libconftest.dylib && test $_lt_result -eq 0; then
-         lt_cv_apple_cc_single_mod=yes
-       else
-         cat conftest.err >&5
-       fi
-       rm -rf libconftest.dylib*
-       rm -f conftest.*
-      fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
-$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
-$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
-if ${lt_cv_ld_exported_symbols_list+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_ld_exported_symbols_list=no
-      save_LDFLAGS=$LDFLAGS
-      echo "_main" > conftest.sym
-      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  lt_cv_ld_exported_symbols_list=yes
-else
-  lt_cv_ld_exported_symbols_list=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-       LDFLAGS="$save_LDFLAGS"
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
-$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
-$as_echo_n "checking for -force_load linker flag... " >&6; }
-if ${lt_cv_ld_force_load+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_ld_force_load=no
-      cat > conftest.c << _LT_EOF
-int forced_loaded() { return 2;}
-_LT_EOF
-      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
-      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
-      echo "$AR cru libconftest.a conftest.o" >&5
-      $AR cru libconftest.a conftest.o 2>&5
-      echo "$RANLIB libconftest.a" >&5
-      $RANLIB libconftest.a 2>&5
-      cat > conftest.c << _LT_EOF
-int main() { return 0;}
-_LT_EOF
-      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
-      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
-      _lt_result=$?
-      if test -s conftest.err && $GREP force_load conftest.err; then
-       cat conftest.err >&5
-      elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then
-       lt_cv_ld_force_load=yes
-      else
-       cat conftest.err >&5
-      fi
-        rm -f conftest.err libconftest.a conftest conftest.c
-        rm -rf conftest.dSYM
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
-$as_echo "$lt_cv_ld_force_load" >&6; }
-    case $host_os in
-    rhapsody* | darwin1.[012])
-      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
-    darwin1.*)
-      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
-    darwin*) # darwin 5.x on
-      # if running on 10.5 or later, the deployment target defaults
-      # to the OS version, if on x86, and 10.4, the deployment
-      # target defaults to 10.4. Don't you love it?
-      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
-       10.0,*86*-darwin8*|10.0,*-darwin[91]*)
-         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
-       10.[012]*)
-         _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
-       10.*)
-         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
-      esac
-    ;;
-  esac
-    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
-      _lt_dar_single_mod='$single_module'
-    fi
-    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
-      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
-    else
-      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
-    fi
-    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
-      _lt_dsymutil='~$DSYMUTIL $lib || :'
-    else
-      _lt_dsymutil=
-    fi
-    ;;
-  esac
-
-for ac_header in dlfcn.h
-do :
-  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
-"
-if test "x$ac_cv_header_dlfcn_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_DLFCN_H 1
-_ACEOF
-
-fi
-
-done
-
-
-
-
-
-# Set options
-enable_win32_dll=yes
-
-case $host in
-*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
-set dummy ${ac_tool_prefix}as; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AS+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$AS"; then
-  ac_cv_prog_AS="$AS" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_AS="${ac_tool_prefix}as"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-AS=$ac_cv_prog_AS
-if test -n "$AS"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5
-$as_echo "$AS" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_AS"; then
-  ac_ct_AS=$AS
-  # Extract the first word of "as", so it can be a program name with args.
-set dummy as; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_AS+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_AS"; then
-  ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_AS="as"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_AS=$ac_cv_prog_ac_ct_AS
-if test -n "$ac_ct_AS"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5
-$as_echo "$ac_ct_AS" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_AS" = x; then
-    AS="false"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    AS=$ac_ct_AS
-  fi
-else
-  AS="$ac_cv_prog_AS"
-fi
-
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
-set dummy ${ac_tool_prefix}dlltool; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_DLLTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$DLLTOOL"; then
-  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-DLLTOOL=$ac_cv_prog_DLLTOOL
-if test -n "$DLLTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
-$as_echo "$DLLTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_DLLTOOL"; then
-  ac_ct_DLLTOOL=$DLLTOOL
-  # Extract the first word of "dlltool", so it can be a program name with args.
-set dummy dlltool; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_DLLTOOL"; then
-  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
-if test -n "$ac_ct_DLLTOOL"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
-$as_echo "$ac_ct_DLLTOOL" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_DLLTOOL" = x; then
-    DLLTOOL="false"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    DLLTOOL=$ac_ct_DLLTOOL
-  fi
-else
-  DLLTOOL="$ac_cv_prog_DLLTOOL"
-fi
-
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
-set dummy ${ac_tool_prefix}objdump; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_OBJDUMP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$OBJDUMP"; then
-  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-OBJDUMP=$ac_cv_prog_OBJDUMP
-if test -n "$OBJDUMP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
-$as_echo "$OBJDUMP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_OBJDUMP"; then
-  ac_ct_OBJDUMP=$OBJDUMP
-  # Extract the first word of "objdump", so it can be a program name with args.
-set dummy objdump; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_OBJDUMP"; then
-  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_OBJDUMP="objdump"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
-if test -n "$ac_ct_OBJDUMP"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
-$as_echo "$ac_ct_OBJDUMP" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_OBJDUMP" = x; then
-    OBJDUMP="false"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    OBJDUMP=$ac_ct_OBJDUMP
-  fi
-else
-  OBJDUMP="$ac_cv_prog_OBJDUMP"
-fi
-
-  ;;
-esac
-
-test -z "$AS" && AS=as
-
-
-
-
-
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-
-
-
-
-
-test -z "$OBJDUMP" && OBJDUMP=objdump
-
-
-
-
-# Check whether --enable-static was given.
-if test "${enable_static+set}" = set; then :
-  enableval=$enable_static; p=${PACKAGE-default}
-    case $enableval in
-    yes) enable_static=yes ;;
-    no) enable_static=no ;;
-    *)
-     enable_static=no
-      # Look at the argument we got.  We use all the common list separators.
-      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
-      for pkg in $enableval; do
-       IFS="$lt_save_ifs"
-       if test "X$pkg" = "X$p"; then
-         enable_static=yes
-       fi
-      done
-      IFS="$lt_save_ifs"
-      ;;
-    esac
-else
-  enable_static=no
-fi
-
-
-
-
-
-
-
-
-
-
-        enable_dlopen=no
-
-
-
-            # Check whether --enable-shared was given.
-if test "${enable_shared+set}" = set; then :
-  enableval=$enable_shared; p=${PACKAGE-default}
-    case $enableval in
-    yes) enable_shared=yes ;;
-    no) enable_shared=no ;;
-    *)
-      enable_shared=no
-      # Look at the argument we got.  We use all the common list separators.
-      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
-      for pkg in $enableval; do
-       IFS="$lt_save_ifs"
-       if test "X$pkg" = "X$p"; then
-         enable_shared=yes
-       fi
-      done
-      IFS="$lt_save_ifs"
-      ;;
-    esac
-else
-  enable_shared=yes
-fi
-
-
-
-
-
-
-
-
-
-
-
-# Check whether --with-pic was given.
-if test "${with_pic+set}" = set; then :
-  withval=$with_pic; lt_p=${PACKAGE-default}
-    case $withval in
-    yes|no) pic_mode=$withval ;;
-    *)
-      pic_mode=default
-      # Look at the argument we got.  We use all the common list separators.
-      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
-      for lt_pkg in $withval; do
-       IFS="$lt_save_ifs"
-       if test "X$lt_pkg" = "X$lt_p"; then
-         pic_mode=yes
-       fi
-      done
-      IFS="$lt_save_ifs"
-      ;;
-    esac
-else
-  pic_mode=default
-fi
-
-
-test -z "$pic_mode" && pic_mode=default
-
-
-
-
-
-
-
-  # Check whether --enable-fast-install was given.
-if test "${enable_fast_install+set}" = set; then :
-  enableval=$enable_fast_install; p=${PACKAGE-default}
-    case $enableval in
-    yes) enable_fast_install=yes ;;
-    no) enable_fast_install=no ;;
-    *)
-      enable_fast_install=no
-      # Look at the argument we got.  We use all the common list separators.
-      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
-      for pkg in $enableval; do
-       IFS="$lt_save_ifs"
-       if test "X$pkg" = "X$p"; then
-         enable_fast_install=yes
-       fi
-      done
-      IFS="$lt_save_ifs"
-      ;;
-    esac
-else
-  enable_fast_install=yes
-fi
-
-
-
-
-
-
-
-
-
-
-
-# This can be used to rebuild libtool when needed
-LIBTOOL_DEPS="$ltmain"
-
-# Always use our own libtool.
-LIBTOOL='$(SHELL) $(top_builddir)/libtool'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-test -z "$LN_S" && LN_S="ln -s"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-if test -n "${ZSH_VERSION+set}" ; then
-   setopt NO_GLOB_SUBST
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
-$as_echo_n "checking for objdir... " >&6; }
-if ${lt_cv_objdir+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
-  lt_cv_objdir=.libs
-else
-  # MS-DOS does not allow filenames that begin with a dot.
-  lt_cv_objdir=_libs
-fi
-rmdir .libs 2>/dev/null
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
-$as_echo "$lt_cv_objdir" >&6; }
-objdir=$lt_cv_objdir
-
-
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define LT_OBJDIR "$lt_cv_objdir/"
-_ACEOF
-
-
-
-
-case $host_os in
-aix3*)
-  # AIX sometimes has problems with the GCC collect2 program.  For some
-  # reason, if we set the COLLECT_NAMES environment variable, the problems
-  # vanish in a puff of smoke.
-  if test "X${COLLECT_NAMES+set}" != Xset; then
-    COLLECT_NAMES=
-    export COLLECT_NAMES
-  fi
-  ;;
-esac
-
-# Global variables:
-ofile=libtool
-can_build_shared=yes
-
-# All known linkers require a `.a' archive for static linking (except MSVC,
-# which needs '.lib').
-libext=a
-
-with_gnu_ld="$lt_cv_prog_gnu_ld"
-
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-
-# Set sane defaults for various variables
-test -z "$CC" && CC=cc
-test -z "$LTCC" && LTCC=$CC
-test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
-test -z "$LD" && LD=ld
-test -z "$ac_objext" && ac_objext=o
-
-for cc_temp in $compiler""; do
-  case $cc_temp in
-    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
-    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
-    \-*) ;;
-    *) break;;
-  esac
-done
-cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
-
-
-# Only perform the check for file, if the check method requires it
-test -z "$MAGIC_CMD" && MAGIC_CMD=file
-case $deplibs_check_method in
-file_magic*)
-  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
-$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
-if ${lt_cv_path_MAGIC_CMD+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $MAGIC_CMD in
-[\\/*] |  ?:[\\/]*)
-  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
-  ;;
-*)
-  lt_save_MAGIC_CMD="$MAGIC_CMD"
-  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
-  for ac_dir in $ac_dummy; do
-    IFS="$lt_save_ifs"
-    test -z "$ac_dir" && ac_dir=.
-    if test -f $ac_dir/${ac_tool_prefix}file; then
-      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
-      if test -n "$file_magic_test_file"; then
-       case $deplibs_check_method in
-       "file_magic "*)
-         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
-         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
-           $EGREP "$file_magic_regex" > /dev/null; then
-           :
-         else
-           cat <<_LT_EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such.  This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem.  Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-_LT_EOF
-         fi ;;
-       esac
-      fi
-      break
-    fi
-  done
-  IFS="$lt_save_ifs"
-  MAGIC_CMD="$lt_save_MAGIC_CMD"
-  ;;
-esac
-fi
-
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
-$as_echo "$MAGIC_CMD" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-
-
-
-if test -z "$lt_cv_path_MAGIC_CMD"; then
-  if test -n "$ac_tool_prefix"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
-$as_echo_n "checking for file... " >&6; }
-if ${lt_cv_path_MAGIC_CMD+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $MAGIC_CMD in
-[\\/*] |  ?:[\\/]*)
-  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
-  ;;
-*)
-  lt_save_MAGIC_CMD="$MAGIC_CMD"
-  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
-  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
-  for ac_dir in $ac_dummy; do
-    IFS="$lt_save_ifs"
-    test -z "$ac_dir" && ac_dir=.
-    if test -f $ac_dir/file; then
-      lt_cv_path_MAGIC_CMD="$ac_dir/file"
-      if test -n "$file_magic_test_file"; then
-       case $deplibs_check_method in
-       "file_magic "*)
-         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
-         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
-           $EGREP "$file_magic_regex" > /dev/null; then
-           :
-         else
-           cat <<_LT_EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such.  This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem.  Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-_LT_EOF
-         fi ;;
-       esac
-      fi
-      break
-    fi
-  done
-  IFS="$lt_save_ifs"
-  MAGIC_CMD="$lt_save_MAGIC_CMD"
-  ;;
-esac
-fi
-
-MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
-if test -n "$MAGIC_CMD"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
-$as_echo "$MAGIC_CMD" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  else
-    MAGIC_CMD=:
-  fi
-fi
-
-  fi
-  ;;
-esac
-
-# Use C for the default configuration in the libtool script
-
-lt_save_CC="$CC"
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-# Source file extension for C test sources.
-ac_ext=c
-
-# Object file extension for compiled C test sources.
-objext=o
-objext=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code="int some_variable = 0;"
-
-# Code to be used in simple link tests
-lt_simple_link_test_code='int main(){return(0);}'
-
-
-
-
-
-
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-# Save the default compiler, since it gets overwritten when the other
-# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
-compiler_DEFAULT=$CC
-
-# save warnings/boilerplate of simple test code
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$RM conftest*
-
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$RM -r conftest*
-
-
-## CAVEAT EMPTOR:
-## There is no encapsulation within the following macros, do not change
-## the running order or otherwise move them around unless you know exactly
-## what you are doing...
-if test -n "$compiler"; then
-
-lt_prog_compiler_no_builtin_flag=
-
-if test "$GCC" = yes; then
-  case $cc_basename in
-  nvcc*)
-    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
-  *)
-    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
-  esac
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
-if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_prog_compiler_rtti_exceptions=no
-   ac_outfile=conftest.$ac_objext
-   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-   lt_compiler_flag="-fno-rtti -fno-exceptions"
-   # Insert the option either (1) after the last *FLAGS variable, or
-   # (2) before a word containing "conftest.", or (3) at the end.
-   # Note that $ac_compile itself does not contain backslashes and begins
-   # with a dollar sign (not a hyphen), so the echo should work correctly.
-   # The option is referenced via a variable to avoid confusing sed.
-   lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-   -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
-   (eval "$lt_compile" 2>conftest.err)
-   ac_status=$?
-   cat conftest.err >&5
-   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-   if (exit $ac_status) && test -s "$ac_outfile"; then
-     # The compiler can only warn and ignore the option if not recognized
-     # So say no if there are warnings other than the usual output.
-     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
-     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
-     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
-       lt_cv_prog_compiler_rtti_exceptions=yes
-     fi
-   fi
-   $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
-$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
-
-if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
-    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
-else
-    :
-fi
-
-fi
-
-
-
-
-
-
-  lt_prog_compiler_wl=
-lt_prog_compiler_pic=
-lt_prog_compiler_static=
-
-
-  if test "$GCC" = yes; then
-    lt_prog_compiler_wl='-Wl,'
-    lt_prog_compiler_static='-static'
-
-    case $host_os in
-      aix*)
-      # All AIX code is PIC.
-      if test "$host_cpu" = ia64; then
-       # AIX 5 now supports IA64 processor
-       lt_prog_compiler_static='-Bstatic'
-      fi
-      ;;
-
-    amigaos*)
-      case $host_cpu in
-      powerpc)
-            # see comment about AmigaOS4 .so support
-            lt_prog_compiler_pic='-fPIC'
-        ;;
-      m68k)
-            # FIXME: we need at least 68020 code to build shared libraries, but
-            # adding the `-m68020' flag to GCC prevents building anything better,
-            # like `-m68040'.
-            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
-        ;;
-      esac
-      ;;
-
-    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
-      # PIC is the default for these OSes.
-      ;;
-
-    mingw* | cygwin* | pw32* | os2* | cegcc*)
-      # This hack is so that the source file can tell whether it is being
-      # built for inclusion in a dll (and should export symbols for example).
-      # Although the cygwin gcc ignores -fPIC, still need this for old-style
-      # (--disable-auto-import) libraries
-      lt_prog_compiler_pic='-DDLL_EXPORT'
-      ;;
-
-    darwin* | rhapsody*)
-      # PIC is the default on this platform
-      # Common symbols not allowed in MH_DYLIB files
-      lt_prog_compiler_pic='-fno-common'
-      ;;
-
-    haiku*)
-      # PIC is the default for Haiku.
-      # The "-static" flag exists, but is broken.
-      lt_prog_compiler_static=
-      ;;
-
-    hpux*)
-      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
-      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
-      # sets the default TLS model and affects inlining.
-      case $host_cpu in
-      hppa*64*)
-       # +Z the default
-       ;;
-      *)
-       lt_prog_compiler_pic='-fPIC'
-       ;;
-      esac
-      ;;
-
-    interix[3-9]*)
-      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
-      # Instead, we relocate shared libraries at runtime.
-      ;;
-
-    msdosdjgpp*)
-      # Just because we use GCC doesn't mean we suddenly get shared libraries
-      # on systems that don't support them.
-      lt_prog_compiler_can_build_shared=no
-      enable_shared=no
-      ;;
-
-    *nto* | *qnx*)
-      # QNX uses GNU C++, but need to define -shared option too, otherwise
-      # it will coredump.
-      lt_prog_compiler_pic='-fPIC -shared'
-      ;;
-
-    sysv4*MP*)
-      if test -d /usr/nec; then
-       lt_prog_compiler_pic=-Kconform_pic
-      fi
-      ;;
-
-    *)
-      lt_prog_compiler_pic='-fPIC'
-      ;;
-    esac
-
-    case $cc_basename in
-    nvcc*) # Cuda Compiler Driver 2.2
-      lt_prog_compiler_wl='-Xlinker '
-      if test -n "$lt_prog_compiler_pic"; then
-        lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
-      fi
-      ;;
-    esac
-  else
-    # PORTME Check for flag to pass linker flags through the system compiler.
-    case $host_os in
-    aix*)
-      lt_prog_compiler_wl='-Wl,'
-      if test "$host_cpu" = ia64; then
-       # AIX 5 now supports IA64 processor
-       lt_prog_compiler_static='-Bstatic'
-      else
-       lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
-      fi
-      ;;
-
-    mingw* | cygwin* | pw32* | os2* | cegcc*)
-      # This hack is so that the source file can tell whether it is being
-      # built for inclusion in a dll (and should export symbols for example).
-      lt_prog_compiler_pic='-DDLL_EXPORT'
-      ;;
-
-    hpux9* | hpux10* | hpux11*)
-      lt_prog_compiler_wl='-Wl,'
-      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
-      # not for PA HP-UX.
-      case $host_cpu in
-      hppa*64*|ia64*)
-       # +Z the default
-       ;;
-      *)
-       lt_prog_compiler_pic='+Z'
-       ;;
-      esac
-      # Is there a better lt_prog_compiler_static that works with the bundled CC?
-      lt_prog_compiler_static='${wl}-a ${wl}archive'
-      ;;
-
-    irix5* | irix6* | nonstopux*)
-      lt_prog_compiler_wl='-Wl,'
-      # PIC (with -KPIC) is the default.
-      lt_prog_compiler_static='-non_shared'
-      ;;
-
-    linux* | k*bsd*-gnu | kopensolaris*-gnu)
-      case $cc_basename in
-      # old Intel for x86_64 which still supported -KPIC.
-      ecc*)
-       lt_prog_compiler_wl='-Wl,'
-       lt_prog_compiler_pic='-KPIC'
-       lt_prog_compiler_static='-static'
-        ;;
-      # icc used to be incompatible with GCC.
-      # ICC 10 doesn't accept -KPIC any more.
-      icc* | ifort*)
-       lt_prog_compiler_wl='-Wl,'
-       lt_prog_compiler_pic='-fPIC'
-       lt_prog_compiler_static='-static'
-        ;;
-      # Lahey Fortran 8.1.
-      lf95*)
-       lt_prog_compiler_wl='-Wl,'
-       lt_prog_compiler_pic='--shared'
-       lt_prog_compiler_static='--static'
-       ;;
-      nagfor*)
-       # NAG Fortran compiler
-       lt_prog_compiler_wl='-Wl,-Wl,,'
-       lt_prog_compiler_pic='-PIC'
-       lt_prog_compiler_static='-Bstatic'
-       ;;
-      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
-        # Portland Group compilers (*not* the Pentium gcc compiler,
-       # which looks to be a dead project)
-       lt_prog_compiler_wl='-Wl,'
-       lt_prog_compiler_pic='-fpic'
-       lt_prog_compiler_static='-Bstatic'
-        ;;
-      ccc*)
-        lt_prog_compiler_wl='-Wl,'
-        # All Alpha code is PIC.
-        lt_prog_compiler_static='-non_shared'
-        ;;
-      xl* | bgxl* | bgf* | mpixl*)
-       # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
-       lt_prog_compiler_wl='-Wl,'
-       lt_prog_compiler_pic='-qpic'
-       lt_prog_compiler_static='-qstaticlink'
-       ;;
-      *)
-       case `$CC -V 2>&1 | sed 5q` in
-       *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
-         # Sun Fortran 8.3 passes all unrecognized flags to the linker
-         lt_prog_compiler_pic='-KPIC'
-         lt_prog_compiler_static='-Bstatic'
-         lt_prog_compiler_wl=''
-         ;;
-       *Sun\ F* | *Sun*Fortran*)
-         lt_prog_compiler_pic='-KPIC'
-         lt_prog_compiler_static='-Bstatic'
-         lt_prog_compiler_wl='-Qoption ld '
-         ;;
-       *Sun\ C*)
-         # Sun C 5.9
-         lt_prog_compiler_pic='-KPIC'
-         lt_prog_compiler_static='-Bstatic'
-         lt_prog_compiler_wl='-Wl,'
-         ;;
-        *Intel*\ [CF]*Compiler*)
-         lt_prog_compiler_wl='-Wl,'
-         lt_prog_compiler_pic='-fPIC'
-         lt_prog_compiler_static='-static'
-         ;;
-       *Portland\ Group*)
-         lt_prog_compiler_wl='-Wl,'
-         lt_prog_compiler_pic='-fpic'
-         lt_prog_compiler_static='-Bstatic'
-         ;;
-       esac
-       ;;
-      esac
-      ;;
-
-    newsos6)
-      lt_prog_compiler_pic='-KPIC'
-      lt_prog_compiler_static='-Bstatic'
-      ;;
-
-    *nto* | *qnx*)
-      # QNX uses GNU C++, but need to define -shared option too, otherwise
-      # it will coredump.
-      lt_prog_compiler_pic='-fPIC -shared'
-      ;;
-
-    osf3* | osf4* | osf5*)
-      lt_prog_compiler_wl='-Wl,'
-      # All OSF/1 code is PIC.
-      lt_prog_compiler_static='-non_shared'
-      ;;
-
-    rdos*)
-      lt_prog_compiler_static='-non_shared'
-      ;;
-
-    solaris*)
-      lt_prog_compiler_pic='-KPIC'
-      lt_prog_compiler_static='-Bstatic'
-      case $cc_basename in
-      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
-       lt_prog_compiler_wl='-Qoption ld ';;
-      *)
-       lt_prog_compiler_wl='-Wl,';;
-      esac
-      ;;
-
-    sunos4*)
-      lt_prog_compiler_wl='-Qoption ld '
-      lt_prog_compiler_pic='-PIC'
-      lt_prog_compiler_static='-Bstatic'
-      ;;
-
-    sysv4 | sysv4.2uw2* | sysv4.3*)
-      lt_prog_compiler_wl='-Wl,'
-      lt_prog_compiler_pic='-KPIC'
-      lt_prog_compiler_static='-Bstatic'
-      ;;
-
-    sysv4*MP*)
-      if test -d /usr/nec ;then
-       lt_prog_compiler_pic='-Kconform_pic'
-       lt_prog_compiler_static='-Bstatic'
-      fi
-      ;;
-
-    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
-      lt_prog_compiler_wl='-Wl,'
-      lt_prog_compiler_pic='-KPIC'
-      lt_prog_compiler_static='-Bstatic'
-      ;;
-
-    unicos*)
-      lt_prog_compiler_wl='-Wl,'
-      lt_prog_compiler_can_build_shared=no
-      ;;
-
-    uts4*)
-      lt_prog_compiler_pic='-pic'
-      lt_prog_compiler_static='-Bstatic'
-      ;;
-
-    *)
-      lt_prog_compiler_can_build_shared=no
-      ;;
-    esac
-  fi
-
-case $host_os in
-  # For platforms which do not support PIC, -DPIC is meaningless:
-  *djgpp*)
-    lt_prog_compiler_pic=
-    ;;
-  *)
-    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
-    ;;
-esac
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
-$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
-if ${lt_cv_prog_compiler_pic+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
-$as_echo "$lt_cv_prog_compiler_pic" >&6; }
-lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
-
-#
-# Check to make sure the PIC flag actually works.
-#
-if test -n "$lt_prog_compiler_pic"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
-$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
-if ${lt_cv_prog_compiler_pic_works+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_prog_compiler_pic_works=no
-   ac_outfile=conftest.$ac_objext
-   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
-   # Insert the option either (1) after the last *FLAGS variable, or
-   # (2) before a word containing "conftest.", or (3) at the end.
-   # Note that $ac_compile itself does not contain backslashes and begins
-   # with a dollar sign (not a hyphen), so the echo should work correctly.
-   # The option is referenced via a variable to avoid confusing sed.
-   lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-   -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
-   (eval "$lt_compile" 2>conftest.err)
-   ac_status=$?
-   cat conftest.err >&5
-   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-   if (exit $ac_status) && test -s "$ac_outfile"; then
-     # The compiler can only warn and ignore the option if not recognized
-     # So say no if there are warnings other than the usual output.
-     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
-     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
-     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
-       lt_cv_prog_compiler_pic_works=yes
-     fi
-   fi
-   $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
-$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
-
-if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
-    case $lt_prog_compiler_pic in
-     "" | " "*) ;;
-     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
-     esac
-else
-    lt_prog_compiler_pic=
-     lt_prog_compiler_can_build_shared=no
-fi
-
-fi
-
-
-
-
-
-
-
-
-
-
-
-#
-# Check to make sure the static flag actually works.
-#
-wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
-if ${lt_cv_prog_compiler_static_works+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_prog_compiler_static_works=no
-   save_LDFLAGS="$LDFLAGS"
-   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
-   echo "$lt_simple_link_test_code" > conftest.$ac_ext
-   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
-     # The linker can only warn and ignore the option if not recognized
-     # So say no if there are warnings
-     if test -s conftest.err; then
-       # Append any errors to the config.log.
-       cat conftest.err 1>&5
-       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
-       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
-       if diff conftest.exp conftest.er2 >/dev/null; then
-         lt_cv_prog_compiler_static_works=yes
-       fi
-     else
-       lt_cv_prog_compiler_static_works=yes
-     fi
-   fi
-   $RM -r conftest*
-   LDFLAGS="$save_LDFLAGS"
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
-$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
-
-if test x"$lt_cv_prog_compiler_static_works" = xyes; then
-    :
-else
-    lt_prog_compiler_static=
-fi
-
-
-
-
-
-
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
-$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if ${lt_cv_prog_compiler_c_o+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_prog_compiler_c_o=no
-   $RM -r conftest 2>/dev/null
-   mkdir conftest
-   cd conftest
-   mkdir out
-   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
-   lt_compiler_flag="-o out/conftest2.$ac_objext"
-   # Insert the option either (1) after the last *FLAGS variable, or
-   # (2) before a word containing "conftest.", or (3) at the end.
-   # Note that $ac_compile itself does not contain backslashes and begins
-   # with a dollar sign (not a hyphen), so the echo should work correctly.
-   lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-   -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
-   (eval "$lt_compile" 2>out/conftest.err)
-   ac_status=$?
-   cat out/conftest.err >&5
-   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-   if (exit $ac_status) && test -s out/conftest2.$ac_objext
-   then
-     # The compiler can only warn and ignore the option if not recognized
-     # So say no if there are warnings
-     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
-     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
-     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
-       lt_cv_prog_compiler_c_o=yes
-     fi
-   fi
-   chmod u+w . 2>&5
-   $RM conftest*
-   # SGI C++ compiler will create directory out/ii_files/ for
-   # template instantiation
-   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
-   $RM out/* && rmdir out
-   cd ..
-   $RM -r conftest
-   $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
-$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
-
-
-
-
-
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
-$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
-if ${lt_cv_prog_compiler_c_o+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_prog_compiler_c_o=no
-   $RM -r conftest 2>/dev/null
-   mkdir conftest
-   cd conftest
-   mkdir out
-   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
-   lt_compiler_flag="-o out/conftest2.$ac_objext"
-   # Insert the option either (1) after the last *FLAGS variable, or
-   # (2) before a word containing "conftest.", or (3) at the end.
-   # Note that $ac_compile itself does not contain backslashes and begins
-   # with a dollar sign (not a hyphen), so the echo should work correctly.
-   lt_compile=`echo "$ac_compile" | $SED \
-   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-   -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
-   (eval "$lt_compile" 2>out/conftest.err)
-   ac_status=$?
-   cat out/conftest.err >&5
-   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-   if (exit $ac_status) && test -s out/conftest2.$ac_objext
-   then
-     # The compiler can only warn and ignore the option if not recognized
-     # So say no if there are warnings
-     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
-     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
-     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
-       lt_cv_prog_compiler_c_o=yes
-     fi
-   fi
-   chmod u+w . 2>&5
-   $RM conftest*
-   # SGI C++ compiler will create directory out/ii_files/ for
-   # template instantiation
-   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
-   $RM out/* && rmdir out
-   cd ..
-   $RM -r conftest
-   $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
-$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
-
-
-
-
-hard_links="nottested"
-if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
-  # do not overwrite the value of need_locks provided by the user
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
-$as_echo_n "checking if we can lock with hard links... " >&6; }
-  hard_links=yes
-  $RM conftest*
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  touch conftest.a
-  ln conftest.a conftest.b 2>&5 || hard_links=no
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
-$as_echo "$hard_links" >&6; }
-  if test "$hard_links" = no; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
-$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
-    need_locks=warn
-  fi
-else
-  need_locks=no
-fi
-
-
-
-
-
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
-
-  runpath_var=
-  allow_undefined_flag=
-  always_export_symbols=no
-  archive_cmds=
-  archive_expsym_cmds=
-  compiler_needs_object=no
-  enable_shared_with_static_runtimes=no
-  export_dynamic_flag_spec=
-  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
-  hardcode_automatic=no
-  hardcode_direct=no
-  hardcode_direct_absolute=no
-  hardcode_libdir_flag_spec=
-  hardcode_libdir_separator=
-  hardcode_minus_L=no
-  hardcode_shlibpath_var=unsupported
-  inherit_rpath=no
-  link_all_deplibs=unknown
-  module_cmds=
-  module_expsym_cmds=
-  old_archive_from_new_cmds=
-  old_archive_from_expsyms_cmds=
-  thread_safe_flag_spec=
-  whole_archive_flag_spec=
-  # include_expsyms should be a list of space-separated symbols to be *always*
-  # included in the symbol list
-  include_expsyms=
-  # exclude_expsyms can be an extended regexp of symbols to exclude
-  # it will be wrapped by ` (' and `)$', so one must not match beginning or
-  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
-  # as well as any symbol that contains `d'.
-  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
-  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
-  # platforms (ab)use it in PIC code, but their linkers get confused if
-  # the symbol is explicitly referenced.  Since portable code cannot
-  # rely on this symbol name, it's probably fine to never include it in
-  # preloaded symbol tables.
-  # Exclude shared library initialization/finalization symbols.
-  extract_expsyms_cmds=
-
-  case $host_os in
-  cygwin* | mingw* | pw32* | cegcc*)
-    # FIXME: the MSVC++ port hasn't been tested in a loooong time
-    # When not using gcc, we currently assume that we are using
-    # Microsoft Visual C++.
-    if test "$GCC" != yes; then
-      with_gnu_ld=no
-    fi
-    ;;
-  interix*)
-    # we just hope/assume this is gcc and not c89 (= MSVC++)
-    with_gnu_ld=yes
-    ;;
-  openbsd*)
-    with_gnu_ld=no
-    ;;
-  linux* | k*bsd*-gnu | gnu*)
-    link_all_deplibs=no
-    ;;
-  esac
-
-  ld_shlibs=yes
-
-  # On some targets, GNU ld is compatible enough with the native linker
-  # that we're better off using the native interface for both.
-  lt_use_gnu_ld_interface=no
-  if test "$with_gnu_ld" = yes; then
-    case $host_os in
-      aix*)
-       # The AIX port of GNU ld has always aspired to compatibility
-       # with the native linker.  However, as the warning in the GNU ld
-       # block says, versions before 2.19.5* couldn't really create working
-       # shared libraries, regardless of the interface used.
-       case `$LD -v 2>&1` in
-         *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
-         *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
-         *\ \(GNU\ Binutils\)\ [3-9]*) ;;
-         *)
-           lt_use_gnu_ld_interface=yes
-           ;;
-       esac
-       ;;
-      *)
-       lt_use_gnu_ld_interface=yes
-       ;;
-    esac
-  fi
-
-  if test "$lt_use_gnu_ld_interface" = yes; then
-    # If archive_cmds runs LD, not CC, wlarc should be empty
-    wlarc='${wl}'
-
-    # Set some defaults for GNU ld with shared library support. These
-    # are reset later if shared libraries are not supported. Putting them
-    # here allows them to be overridden if necessary.
-    runpath_var=LD_RUN_PATH
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    export_dynamic_flag_spec='${wl}--export-dynamic'
-    # ancient GNU ld didn't support --whole-archive et. al.
-    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
-      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
-    else
-      whole_archive_flag_spec=
-    fi
-    supports_anon_versioning=no
-    case `$LD -v 2>&1` in
-      *GNU\ gold*) supports_anon_versioning=yes ;;
-      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
-      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
-      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
-      *\ 2.11.*) ;; # other 2.11 versions
-      *) supports_anon_versioning=yes ;;
-    esac
-
-    # See if GNU ld supports shared libraries.
-    case $host_os in
-    aix[3-9]*)
-      # On AIX/PPC, the GNU linker is very broken
-      if test "$host_cpu" != ia64; then
-       ld_shlibs=no
-       cat <<_LT_EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.19, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support.  If you
-*** really care for shared libraries, you may want to install binutils
-*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
-*** You will then need to restart the configuration process.
-
-_LT_EOF
-      fi
-      ;;
-
-    amigaos*)
-      case $host_cpu in
-      powerpc)
-            # see comment about AmigaOS4 .so support
-            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-            archive_expsym_cmds=''
-        ;;
-      m68k)
-            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
-            hardcode_libdir_flag_spec='-L$libdir'
-            hardcode_minus_L=yes
-        ;;
-      esac
-      ;;
-
-    beos*)
-      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
-       allow_undefined_flag=unsupported
-       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
-       # support --undefined.  This deserves some investigation.  FIXME
-       archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-      else
-       ld_shlibs=no
-      fi
-      ;;
-
-    cygwin* | mingw* | pw32* | cegcc*)
-      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
-      # as there is no search path for DLLs.
-      hardcode_libdir_flag_spec='-L$libdir'
-      export_dynamic_flag_spec='${wl}--export-all-symbols'
-      allow_undefined_flag=unsupported
-      always_export_symbols=no
-      enable_shared_with_static_runtimes=yes
-      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
-      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
-
-      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
-        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
-       # If the export-symbols file already is a .def file (1st line
-       # is EXPORTS), use it as is; otherwise, prepend...
-       archive_expsym_cmds='if test "x`$SED \"$sed_uncomment_deffile\" $export_symbols | $SED 1q`" = xEXPORTS; then
-         cp $export_symbols $output_objdir/$soname.def;
-       else
-         echo EXPORTS > $output_objdir/$soname.def;
-         cat $export_symbols >> $output_objdir/$soname.def;
-       fi~
-       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
-      else
-       ld_shlibs=no
-      fi
-      ;;
-
-    haiku*)
-      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-      link_all_deplibs=yes
-      ;;
-
-    interix[3-9]*)
-      hardcode_direct=no
-      hardcode_shlibpath_var=no
-      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
-      export_dynamic_flag_spec='${wl}-E'
-      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
-      # Instead, shared libraries are loaded at an image base (0x10000000 by
-      # default) and relocated if they conflict, which is a slow very memory
-      # consuming and fragmenting process.  To avoid this, we pick a random,
-      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
-      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
-      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
-      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
-      ;;
-
-    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
-      tmp_diet=no
-      if test "$host_os" = linux-dietlibc; then
-       case $cc_basename in
-         diet\ *) tmp_diet=yes;;       # linux-dietlibc with static linking (!diet-dyn)
-       esac
-      fi
-      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
-        && test "$tmp_diet" = no
-      then
-       tmp_addflag=' $pic_flag'
-       tmp_sharedflag='-shared'
-       case $cc_basename,$host_cpu in
-        pgcc*)                         # Portland Group C compiler
-         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
-         tmp_addflag=' $pic_flag'
-         ;;
-       pgf77* | pgf90* | pgf95* | pgfortran*)
-                                       # Portland Group f77 and f90 compilers
-         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
-         tmp_addflag=' $pic_flag -Mnomain' ;;
-       ecc*,ia64* | icc*,ia64*)        # Intel C compiler on ia64
-         tmp_addflag=' -i_dynamic' ;;
-       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
-         tmp_addflag=' -i_dynamic -nofor_main' ;;
-       ifc* | ifort*)                  # Intel Fortran compiler
-         tmp_addflag=' -nofor_main' ;;
-       lf95*)                          # Lahey Fortran 8.1
-         whole_archive_flag_spec=
-         tmp_sharedflag='--shared' ;;
-       xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
-         tmp_sharedflag='-qmkshrobj'
-         tmp_addflag= ;;
-       nvcc*)  # Cuda Compiler Driver 2.2
-         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
-         compiler_needs_object=yes
-         ;;
-       esac
-       case `$CC -V 2>&1 | sed 5q` in
-       *Sun\ C*)                       # Sun C 5.9
-         whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
-         compiler_needs_object=yes
-         tmp_sharedflag='-G' ;;
-       *Sun\ F*)                       # Sun Fortran 8.3
-         tmp_sharedflag='-G' ;;
-       esac
-       archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-
-        if test "x$supports_anon_versioning" = xyes; then
-          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
-           cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
-           echo "local: *; };" >> $output_objdir/$libname.ver~
-           $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
-        fi
-
-       case $cc_basename in
-       xlf* | bgf* | bgxlf* | mpixlf*)
-         # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
-         whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
-         hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-         archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
-         if test "x$supports_anon_versioning" = xyes; then
-           archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
-             cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
-             echo "local: *; };" >> $output_objdir/$libname.ver~
-             $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
-         fi
-         ;;
-       esac
-      else
-        ld_shlibs=no
-      fi
-      ;;
-
-    netbsd* | netbsdelf*-gnu)
-      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
-       archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
-       wlarc=
-      else
-       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-      fi
-      ;;
-
-    solaris*)
-      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
-       ld_shlibs=no
-       cat <<_LT_EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems.  Therefore, libtool
-*** is disabling shared libraries support.  We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer.  Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
-      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
-       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-      else
-       ld_shlibs=no
-      fi
-      ;;
-
-    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
-      case `$LD -v 2>&1` in
-        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
-       ld_shlibs=no
-       cat <<_LT_EOF 1>&2
-
-*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
-*** reliably create shared libraries on SCO systems.  Therefore, libtool
-*** is disabling shared libraries support.  We urge you to upgrade GNU
-*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-_LT_EOF
-       ;;
-       *)
-         # For security reasons, it is highly recommended that you always
-         # use absolute paths for naming shared libraries, and exclude the
-         # DT_RUNPATH tag from executables and libraries.  But doing so
-         # requires that you compile everything twice, which is a pain.
-         if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
-           hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-           archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-           archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-         else
-           ld_shlibs=no
-         fi
-       ;;
-      esac
-      ;;
-
-    sunos4*)
-      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
-      wlarc=
-      hardcode_direct=yes
-      hardcode_shlibpath_var=no
-      ;;
-
-    *)
-      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
-       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-      else
-       ld_shlibs=no
-      fi
-      ;;
-    esac
-
-    if test "$ld_shlibs" = no; then
-      runpath_var=
-      hardcode_libdir_flag_spec=
-      export_dynamic_flag_spec=
-      whole_archive_flag_spec=
-    fi
-  else
-    # PORTME fill in a description of your system's linker (not GNU ld)
-    case $host_os in
-    aix3*)
-      allow_undefined_flag=unsupported
-      always_export_symbols=yes
-      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
-      # Note: this linker hardcodes the directories in LIBPATH if there
-      # are no directories specified by -L.
-      hardcode_minus_L=yes
-      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
-       # Neither direct hardcoding nor static linking is supported with a
-       # broken collect2.
-       hardcode_direct=unsupported
-      fi
-      ;;
-
-    aix[4-9]*)
-      if test "$host_cpu" = ia64; then
-       # On IA64, the linker does run time linking by default, so we don't
-       # have to do anything special.
-       aix_use_runtimelinking=no
-       exp_sym_flag='-Bexport'
-       no_entry_flag=""
-      else
-       # If we're using GNU nm, then we don't want the "-C" option.
-       # -C means demangle to AIX nm, but means don't demangle with GNU nm
-       # Also, AIX nm treats weak defined symbols like other global
-       # defined symbols, whereas GNU nm marks them as "W".
-       if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
-         export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
-       else
-         export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
-       fi
-       aix_use_runtimelinking=no
-
-       # Test if we are trying to use run time linking or normal
-       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
-       # need to do runtime linking.
-       case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
-         for ld_flag in $LDFLAGS; do
-         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
-           aix_use_runtimelinking=yes
-           break
-         fi
-         done
-         ;;
-       esac
-
-       exp_sym_flag='-bexport'
-       no_entry_flag='-bnoentry'
-      fi
-
-      # When large executables or shared objects are built, AIX ld can
-      # have problems creating the table of contents.  If linking a library
-      # or program results in "error TOC overflow" add -mminimal-toc to
-      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
-      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
-
-      archive_cmds=''
-      hardcode_direct=yes
-      hardcode_direct_absolute=yes
-      hardcode_libdir_separator=':'
-      link_all_deplibs=yes
-      file_list_spec='${wl}-f,'
-
-      if test "$GCC" = yes; then
-       case $host_os in aix4.[012]|aix4.[012].*)
-       # We only want to do this on AIX 4.2 and lower, the check
-       # below for broken collect2 doesn't work under 4.3+
-         collect2name=`${CC} -print-prog-name=collect2`
-         if test -f "$collect2name" &&
-          strings "$collect2name" | $GREP resolve_lib_name >/dev/null
-         then
-         # We have reworked collect2
-         :
-         else
-         # We have old collect2
-         hardcode_direct=unsupported
-         # It fails to find uninstalled libraries when the uninstalled
-         # path is not listed in the libpath.  Setting hardcode_minus_L
-         # to unsupported forces relinking
-         hardcode_minus_L=yes
-         hardcode_libdir_flag_spec='-L$libdir'
-         hardcode_libdir_separator=
-         fi
-         ;;
-       esac
-       shared_flag='-shared'
-       if test "$aix_use_runtimelinking" = yes; then
-         shared_flag="$shared_flag "'${wl}-G'
-       fi
-       link_all_deplibs=no
-      else
-       # not using gcc
-       if test "$host_cpu" = ia64; then
-       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
-       # chokes on -Wl,-G. The following line is correct:
-         shared_flag='-G'
-       else
-         if test "$aix_use_runtimelinking" = yes; then
-           shared_flag='${wl}-G'
-         else
-           shared_flag='${wl}-bM:SRE'
-         fi
-       fi
-      fi
-
-      export_dynamic_flag_spec='${wl}-bexpall'
-      # It seems that -bexpall does not export symbols beginning with
-      # underscore (_), so it is better to generate a list of symbols to export.
-      always_export_symbols=yes
-      if test "$aix_use_runtimelinking" = yes; then
-       # Warning - without using the other runtime loading flags (-brtl),
-       # -berok will link without error, but may produce a broken library.
-       allow_undefined_flag='-berok'
-        # Determine the default libpath from the value encoded in an
-        # empty executable.
-        if test "${lt_cv_aix_libpath+set}" = set; then
-  aix_libpath=$lt_cv_aix_libpath
-else
-  if ${lt_cv_aix_libpath_+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-
-  lt_aix_libpath_sed='
-      /Import File Strings/,/^$/ {
-         /^0/ {
-             s/^0  *\([^ ]*\) *$/\1/
-             p
-         }
-      }'
-  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-  # Check for a 64-bit object if we didn't find anything.
-  if test -z "$lt_cv_aix_libpath_"; then
-    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-  fi
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-  if test -z "$lt_cv_aix_libpath_"; then
-    lt_cv_aix_libpath_="/usr/lib:/lib"
-  fi
-
-fi
-
-  aix_libpath=$lt_cv_aix_libpath_
-fi
-
-        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
-        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
-      else
-       if test "$host_cpu" = ia64; then
-         hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
-         allow_undefined_flag="-z nodefs"
-         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
-       else
-        # Determine the default libpath from the value encoded in an
-        # empty executable.
-        if test "${lt_cv_aix_libpath+set}" = set; then
-  aix_libpath=$lt_cv_aix_libpath
-else
-  if ${lt_cv_aix_libpath_+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-
-  lt_aix_libpath_sed='
-      /Import File Strings/,/^$/ {
-         /^0/ {
-             s/^0  *\([^ ]*\) *$/\1/
-             p
-         }
-      }'
-  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-  # Check for a 64-bit object if we didn't find anything.
-  if test -z "$lt_cv_aix_libpath_"; then
-    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
-  fi
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-  if test -z "$lt_cv_aix_libpath_"; then
-    lt_cv_aix_libpath_="/usr/lib:/lib"
-  fi
-
-fi
-
-  aix_libpath=$lt_cv_aix_libpath_
-fi
-
-        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
-         # Warning - without using the other run time loading flags,
-         # -berok will link without error, but may produce a broken library.
-         no_undefined_flag=' ${wl}-bernotok'
-         allow_undefined_flag=' ${wl}-berok'
-         if test "$with_gnu_ld" = yes; then
-           # We only use this code for GNU lds that support --whole-archive.
-           whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
-         else
-           # Exported symbols can be pulled into shared objects from archives
-           whole_archive_flag_spec='$convenience'
-         fi
-         archive_cmds_need_lc=yes
-         # This is similar to how AIX traditionally builds its shared libraries.
-         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
-       fi
-      fi
-      ;;
-
-    amigaos*)
-      case $host_cpu in
-      powerpc)
-            # see comment about AmigaOS4 .so support
-            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
-            archive_expsym_cmds=''
-        ;;
-      m68k)
-            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
-            hardcode_libdir_flag_spec='-L$libdir'
-            hardcode_minus_L=yes
-        ;;
-      esac
-      ;;
-
-    bsdi[45]*)
-      export_dynamic_flag_spec=-rdynamic
-      ;;
-
-    cygwin* | mingw* | pw32* | cegcc*)
-      # When not using gcc, we currently assume that we are using
-      # Microsoft Visual C++.
-      # hardcode_libdir_flag_spec is actually meaningless, as there is
-      # no search path for DLLs.
-      case $cc_basename in
-      cl*)
-       # Native MSVC
-       hardcode_libdir_flag_spec=' '
-       allow_undefined_flag=unsupported
-       always_export_symbols=yes
-       file_list_spec='@'
-       # Tell ltmain to make .lib files, not .a files.
-       libext=lib
-       # Tell ltmain to make .dll files, not .so files.
-       shrext_cmds=".dll"
-       # FIXME: Setting linknames here is a bad hack.
-       archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
-       archive_expsym_cmds='if test "x`$SED \"$sed_uncomment_deffile\" $export_symbols | $SED 1q`" = xEXPORTS; then
-           sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
-         else
-           sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
-         fi~
-         $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
-         linknames='
-       # The linker will not automatically build a static lib if we build a DLL.
-       # _LT_TAGVAR(old_archive_from_new_cmds, )='true'
-       enable_shared_with_static_runtimes=yes
-       exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
-       export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
-       # Don't use ranlib
-       old_postinstall_cmds='chmod 644 $oldlib'
-       postlink_cmds='lt_outputfile="@OUTPUT@"~
-         lt_tool_outputfile="@TOOL_OUTPUT@"~
-         case $lt_outputfile in
-           *.exe|*.EXE) ;;
-           *)
-             lt_outputfile="$lt_outputfile.exe"
-             lt_tool_outputfile="$lt_tool_outputfile.exe"
-             ;;
-         esac~
-         if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
-           $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
-           $RM "$lt_outputfile.manifest";
-         fi'
-       ;;
-      *)
-       # Assume MSVC wrapper
-       hardcode_libdir_flag_spec=' '
-       allow_undefined_flag=unsupported
-       # Tell ltmain to make .lib files, not .a files.
-       libext=lib
-       # Tell ltmain to make .dll files, not .so files.
-       shrext_cmds=".dll"
-       # FIXME: Setting linknames here is a bad hack.
-       archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
-       # The linker will automatically build a .lib file if we build a DLL.
-       old_archive_from_new_cmds='true'
-       # FIXME: Should let the user specify the lib program.
-       old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
-       enable_shared_with_static_runtimes=yes
-       ;;
-      esac
-      ;;
-
-    darwin* | rhapsody*)
-
-
-  archive_cmds_need_lc=no
-  hardcode_direct=no
-  hardcode_automatic=yes
-  hardcode_shlibpath_var=unsupported
-  if test "$lt_cv_ld_force_load" = "yes"; then
-    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
-
-  else
-    whole_archive_flag_spec=''
-  fi
-  link_all_deplibs=yes
-  allow_undefined_flag="$_lt_dar_allow_undefined"
-  case $cc_basename in
-     ifort*) _lt_dar_can_shared=yes ;;
-     *) _lt_dar_can_shared=$GCC ;;
-  esac
-  if test "$_lt_dar_can_shared" = "yes"; then
-    output_verbose_link_cmd=func_echo_all
-    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
-    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
-    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
-    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
-
-  else
-  ld_shlibs=no
-  fi
-
-      ;;
-
-    dgux*)
-      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_libdir_flag_spec='-L$libdir'
-      hardcode_shlibpath_var=no
-      ;;
-
-    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
-    # support.  Future versions do this automatically, but an explicit c++rt0.o
-    # does not break anything, and helps significantly (at the cost of a little
-    # extra space).
-    freebsd2.2*)
-      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
-      hardcode_libdir_flag_spec='-R$libdir'
-      hardcode_direct=yes
-      hardcode_shlibpath_var=no
-      ;;
-
-    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
-    freebsd2.*)
-      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_direct=yes
-      hardcode_minus_L=yes
-      hardcode_shlibpath_var=no
-      ;;
-
-    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-    freebsd* | dragonfly*)
-      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
-      hardcode_libdir_flag_spec='-R$libdir'
-      hardcode_direct=yes
-      hardcode_shlibpath_var=no
-      ;;
-
-    hpux9*)
-      if test "$GCC" = yes; then
-       archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
-      else
-       archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
-      fi
-      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
-      hardcode_libdir_separator=:
-      hardcode_direct=yes
-
-      # hardcode_minus_L: Not really in the search PATH,
-      # but as the default location of the library.
-      hardcode_minus_L=yes
-      export_dynamic_flag_spec='${wl}-E'
-      ;;
-
-    hpux10*)
-      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
-       archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
-      else
-       archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
-      fi
-      if test "$with_gnu_ld" = no; then
-       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
-       hardcode_libdir_separator=:
-       hardcode_direct=yes
-       hardcode_direct_absolute=yes
-       export_dynamic_flag_spec='${wl}-E'
-       # hardcode_minus_L: Not really in the search PATH,
-       # but as the default location of the library.
-       hardcode_minus_L=yes
-      fi
-      ;;
-
-    hpux11*)
-      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
-       case $host_cpu in
-       hppa*64*)
-         archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
-         ;;
-       ia64*)
-         archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
-         ;;
-       *)
-         archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
-         ;;
-       esac
-      else
-       case $host_cpu in
-       hppa*64*)
-         archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
-         ;;
-       ia64*)
-         archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
-         ;;
-       *)
-
-         # Older versions of the 11.00 compiler do not understand -b yet
-         # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
-         { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
-$as_echo_n "checking if $CC understands -b... " >&6; }
-if ${lt_cv_prog_compiler__b+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_prog_compiler__b=no
-   save_LDFLAGS="$LDFLAGS"
-   LDFLAGS="$LDFLAGS -b"
-   echo "$lt_simple_link_test_code" > conftest.$ac_ext
-   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
-     # The linker can only warn and ignore the option if not recognized
-     # So say no if there are warnings
-     if test -s conftest.err; then
-       # Append any errors to the config.log.
-       cat conftest.err 1>&5
-       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
-       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
-       if diff conftest.exp conftest.er2 >/dev/null; then
-         lt_cv_prog_compiler__b=yes
-       fi
-     else
-       lt_cv_prog_compiler__b=yes
-     fi
-   fi
-   $RM -r conftest*
-   LDFLAGS="$save_LDFLAGS"
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
-$as_echo "$lt_cv_prog_compiler__b" >&6; }
-
-if test x"$lt_cv_prog_compiler__b" = xyes; then
-    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
-else
-    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
-fi
-
-         ;;
-       esac
-      fi
-      if test "$with_gnu_ld" = no; then
-       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
-       hardcode_libdir_separator=:
-
-       case $host_cpu in
-       hppa*64*|ia64*)
-         hardcode_direct=no
-         hardcode_shlibpath_var=no
-         ;;
-       *)
-         hardcode_direct=yes
-         hardcode_direct_absolute=yes
-         export_dynamic_flag_spec='${wl}-E'
-
-         # hardcode_minus_L: Not really in the search PATH,
-         # but as the default location of the library.
-         hardcode_minus_L=yes
-         ;;
-       esac
-      fi
-      ;;
-
-    irix5* | irix6* | nonstopux*)
-      if test "$GCC" = yes; then
-       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-       # Try to use the -exported_symbol ld option, if it does not
-       # work, assume that -exports_file does not work either and
-       # implicitly export all symbols.
-       # This should be the same for all languages, so no per-tag cache variable.
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
-$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
-if ${lt_cv_irix_exported_symbol+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  save_LDFLAGS="$LDFLAGS"
-          LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-int foo (void) { return 0; }
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  lt_cv_irix_exported_symbol=yes
-else
-  lt_cv_irix_exported_symbol=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-           LDFLAGS="$save_LDFLAGS"
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
-$as_echo "$lt_cv_irix_exported_symbol" >&6; }
-       if test "$lt_cv_irix_exported_symbol" = yes; then
-          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
-       fi
-      else
-       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
-       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
-      fi
-      archive_cmds_need_lc='no'
-      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-      hardcode_libdir_separator=:
-      inherit_rpath=yes
-      link_all_deplibs=yes
-      ;;
-
-    netbsd* | netbsdelf*-gnu)
-      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
-       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
-      else
-       archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
-      fi
-      hardcode_libdir_flag_spec='-R$libdir'
-      hardcode_direct=yes
-      hardcode_shlibpath_var=no
-      ;;
-
-    newsos6)
-      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_direct=yes
-      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-      hardcode_libdir_separator=:
-      hardcode_shlibpath_var=no
-      ;;
-
-    *nto* | *qnx*)
-      ;;
-
-    openbsd*)
-      if test -f /usr/libexec/ld.so; then
-       hardcode_direct=yes
-       hardcode_shlibpath_var=no
-       hardcode_direct_absolute=yes
-       if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
-         archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
-         archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
-         hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
-         export_dynamic_flag_spec='${wl}-E'
-       else
-         case $host_os in
-          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
-            archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
-            hardcode_libdir_flag_spec='-R$libdir'
-            ;;
-          *)
-            archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
-            hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
-            ;;
-         esac
-       fi
-      else
-       ld_shlibs=no
-      fi
-      ;;
-
-    os2*)
-      hardcode_libdir_flag_spec='-L$libdir'
-      hardcode_minus_L=yes
-      allow_undefined_flag=unsupported
-      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
-      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
-      ;;
-
-    osf3*)
-      if test "$GCC" = yes; then
-       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-      else
-       allow_undefined_flag=' -expect_unresolved \*'
-       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
-      fi
-      archive_cmds_need_lc='no'
-      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-      hardcode_libdir_separator=:
-      ;;
-
-    osf4* | osf5*)     # as osf3* with the addition of -msym flag
-      if test "$GCC" = yes; then
-       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-       archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
-       hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-      else
-       allow_undefined_flag=' -expect_unresolved \*'
-       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
-       archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
-       $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
-
-       # Both c and cxx compiler support -rpath directly
-       hardcode_libdir_flag_spec='-rpath $libdir'
-      fi
-      archive_cmds_need_lc='no'
-      hardcode_libdir_separator=:
-      ;;
-
-    solaris*)
-      no_undefined_flag=' -z defs'
-      if test "$GCC" = yes; then
-       wlarc='${wl}'
-       archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
-       archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-         $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
-      else
-       case `$CC -V 2>&1` in
-       *"Compilers 5.0"*)
-         wlarc=''
-         archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
-         archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-         $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
-         ;;
-       *)
-         wlarc='${wl}'
-         archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
-         archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-         $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
-         ;;
-       esac
-      fi
-      hardcode_libdir_flag_spec='-R$libdir'
-      hardcode_shlibpath_var=no
-      case $host_os in
-      solaris2.[0-5] | solaris2.[0-5].*) ;;
-      *)
-       # The compiler driver will combine and reorder linker options,
-       # but understands `-z linker_flag'.  GCC discards it without `$wl',
-       # but is careful enough not to reorder.
-       # Supported since Solaris 2.6 (maybe 2.5.1?)
-       if test "$GCC" = yes; then
-         whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
-       else
-         whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
-       fi
-       ;;
-      esac
-      link_all_deplibs=yes
-      ;;
-
-    sunos4*)
-      if test "x$host_vendor" = xsequent; then
-       # Use $CC to link under sequent, because it throws in some extra .o
-       # files that make .init and .fini sections work.
-       archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
-      else
-       archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
-      fi
-      hardcode_libdir_flag_spec='-L$libdir'
-      hardcode_direct=yes
-      hardcode_minus_L=yes
-      hardcode_shlibpath_var=no
-      ;;
-
-    sysv4)
-      case $host_vendor in
-       sni)
-         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-         hardcode_direct=yes # is this really true???
-       ;;
-       siemens)
-         ## LD is ld it makes a PLAMLIB
-         ## CC just makes a GrossModule.
-         archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
-         reload_cmds='$CC -r -o $output$reload_objs'
-         hardcode_direct=no
-        ;;
-       motorola)
-         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-         hardcode_direct=no #Motorola manual says yes, but my tests say they lie
-       ;;
-      esac
-      runpath_var='LD_RUN_PATH'
-      hardcode_shlibpath_var=no
-      ;;
-
-    sysv4.3*)
-      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_shlibpath_var=no
-      export_dynamic_flag_spec='-Bexport'
-      ;;
-
-    sysv4*MP*)
-      if test -d /usr/nec; then
-       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-       hardcode_shlibpath_var=no
-       runpath_var=LD_RUN_PATH
-       hardcode_runpath_var=yes
-       ld_shlibs=yes
-      fi
-      ;;
-
-    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
-      no_undefined_flag='${wl}-z,text'
-      archive_cmds_need_lc=no
-      hardcode_shlibpath_var=no
-      runpath_var='LD_RUN_PATH'
-
-      if test "$GCC" = yes; then
-       archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
-       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
-      else
-       archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
-       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
-      fi
-      ;;
-
-    sysv5* | sco3.2v5* | sco5v6*)
-      # Note: We can NOT use -z defs as we might desire, because we do not
-      # link with -lc, and that would cause any symbols used from libc to
-      # always be unresolved, which means just about no library would
-      # ever link correctly.  If we're not using GNU ld we use -z text
-      # though, which does catch some bad symbols but isn't as heavy-handed
-      # as -z defs.
-      no_undefined_flag='${wl}-z,text'
-      allow_undefined_flag='${wl}-z,nodefs'
-      archive_cmds_need_lc=no
-      hardcode_shlibpath_var=no
-      hardcode_libdir_flag_spec='${wl}-R,$libdir'
-      hardcode_libdir_separator=':'
-      link_all_deplibs=yes
-      export_dynamic_flag_spec='${wl}-Bexport'
-      runpath_var='LD_RUN_PATH'
-
-      if test "$GCC" = yes; then
-       archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
-       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
-      else
-       archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
-       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
-      fi
-      ;;
-
-    uts4*)
-      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
-      hardcode_libdir_flag_spec='-L$libdir'
-      hardcode_shlibpath_var=no
-      ;;
-
-    *)
-      ld_shlibs=no
-      ;;
-    esac
-
-    if test x$host_vendor = xsni; then
-      case $host in
-      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-       export_dynamic_flag_spec='${wl}-Blargedynsym'
-       ;;
-      esac
-    fi
-  fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
-$as_echo "$ld_shlibs" >&6; }
-test "$ld_shlibs" = no && can_build_shared=no
-
-with_gnu_ld=$with_gnu_ld
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#
-# Do we need to explicitly link libc?
-#
-case "x$archive_cmds_need_lc" in
-x|xyes)
-  # Assume -lc should be added
-  archive_cmds_need_lc=yes
-
-  if test "$enable_shared" = yes && test "$GCC" = yes; then
-    case $archive_cmds in
-    *'~'*)
-      # FIXME: we may have to deal with multi-command sequences.
-      ;;
-    '$CC '*)
-      # Test whether the compiler implicitly links with -lc since on some
-      # systems, -lgcc has to come before -lc. If gcc already passes -lc
-      # to ld, don't add -lc before -lgcc.
-      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
-$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
-if ${lt_cv_archive_cmds_need_lc+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  $RM conftest*
-       echo "$lt_simple_compile_test_code" > conftest.$ac_ext
-
-       if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } 2>conftest.err; then
-         soname=conftest
-         lib=conftest
-         libobjs=conftest.$ac_objext
-         deplibs=
-         wl=$lt_prog_compiler_wl
-         pic_flag=$lt_prog_compiler_pic
-         compiler_flags=-v
-         linker_flags=-v
-         verstring=
-         output_objdir=.
-         libname=conftest
-         lt_save_allow_undefined_flag=$allow_undefined_flag
-         allow_undefined_flag=
-         if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
-  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }
-         then
-           lt_cv_archive_cmds_need_lc=no
-         else
-           lt_cv_archive_cmds_need_lc=yes
-         fi
-         allow_undefined_flag=$lt_save_allow_undefined_flag
-       else
-         cat conftest.err 1>&5
-       fi
-       $RM conftest*
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
-$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
-      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
-      ;;
-    esac
-  fi
-  ;;
-esac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
-$as_echo_n "checking dynamic linker characteristics... " >&6; }
-
-if test "$GCC" = yes; then
-  case $host_os in
-    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
-    *) lt_awk_arg="/^libraries:/" ;;
-  esac
-  case $host_os in
-    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
-    *) lt_sed_strip_eq="s,=/,/,g" ;;
-  esac
-  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
-  case $lt_search_path_spec in
-  *\;*)
-    # if the path contains ";" then we assume it to be the separator
-    # otherwise default to the standard path separator (i.e. ":") - it is
-    # assumed that no part of a normal pathname contains ";" but that should
-    # okay in the real world where ";" in dirpaths is itself problematic.
-    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
-    ;;
-  *)
-    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
-    ;;
-  esac
-  # Ok, now we have the path, separated by spaces, we can step through it
-  # and add multilib dir if necessary.
-  lt_tmp_lt_search_path_spec=
-  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
-  for lt_sys_path in $lt_search_path_spec; do
-    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
-      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
-    else
-      test -d "$lt_sys_path" && \
-       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
-    fi
-  done
-  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
-BEGIN {RS=" "; FS="/|\n";} {
-  lt_foo="";
-  lt_count=0;
-  for (lt_i = NF; lt_i > 0; lt_i--) {
-    if ($lt_i != "" && $lt_i != ".") {
-      if ($lt_i == "..") {
-        lt_count++;
-      } else {
-        if (lt_count == 0) {
-          lt_foo="/" $lt_i lt_foo;
-        } else {
-          lt_count--;
-        }
-      }
-    }
-  }
-  if (lt_foo != "") { lt_freq[lt_foo]++; }
-  if (lt_freq[lt_foo] == 1) { print lt_foo; }
-}'`
-  # AWK program above erroneously prepends '/' to C:/dos/paths
-  # for these hosts.
-  case $host_os in
-    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
-      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
-  esac
-  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
-else
-  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-fi
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-shrext_cmds=".so"
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-need_lib_prefix=unknown
-hardcode_into_libs=no
-
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-need_version=unknown
-
-case $host_os in
-aix3*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
-  shlibpath_var=LIBPATH
-
-  # AIX 3 has no versioning support, so we append a major version to the name.
-  soname_spec='${libname}${release}${shared_ext}$major'
-  ;;
-
-aix[4-9]*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_lib_prefix=no
-  need_version=no
-  hardcode_into_libs=yes
-  if test "$host_cpu" = ia64; then
-    # AIX 5 supports IA64
-    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
-    shlibpath_var=LD_LIBRARY_PATH
-  else
-    # With GCC up to 2.95.x, collect2 would create an import file
-    # for dependence libraries.  The import file would start with
-    # the line `#! .'.  This would cause the generated library to
-    # depend on `.', always an invalid library.  This was fixed in
-    # development snapshots of GCC prior to 3.0.
-    case $host_os in
-      aix4 | aix4.[01] | aix4.[01].*)
-      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
-          echo ' yes '
-          echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
-       :
-      else
-       can_build_shared=no
-      fi
-      ;;
-    esac
-    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
-    # soname into executable. Probably we can add versioning support to
-    # collect2, so additional links can be useful in future.
-    if test "$aix_use_runtimelinking" = yes; then
-      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
-      # instead of lib<name>.a to let people know that these are not
-      # typical AIX shared libraries.
-      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-    else
-      # We preserve .a as extension for shared libraries through AIX4.2
-      # and later when we are not doing run time linking.
-      library_names_spec='${libname}${release}.a $libname.a'
-      soname_spec='${libname}${release}${shared_ext}$major'
-    fi
-    shlibpath_var=LIBPATH
-  fi
-  ;;
-
-amigaos*)
-  case $host_cpu in
-  powerpc)
-    # Since July 2007 AmigaOS4 officially supports .so libraries.
-    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
-    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-    ;;
-  m68k)
-    library_names_spec='$libname.ixlibrary $libname.a'
-    # Create ${libname}_ixlibrary.a entries in /sys/libs.
-    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
-    ;;
-  esac
-  ;;
-
-beos*)
-  library_names_spec='${libname}${shared_ext}'
-  dynamic_linker="$host_os ld.so"
-  shlibpath_var=LIBRARY_PATH
-  ;;
-
-bsdi[45]*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
-  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
-  # the default ld.so.conf also contains /usr/contrib/lib and
-  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
-  # libtool to hard-code these into programs
-  ;;
-
-cygwin* | mingw* | pw32* | cegcc*)
-  version_type=windows
-  shrext_cmds=".dll"
-  need_version=no
-  need_lib_prefix=no
-
-  case $GCC,$cc_basename in
-  yes,*)
-    # gcc
-    library_names_spec='$libname.dll.a'
-    # DLL is installed to $(libdir)/../bin by postinstall_cmds
-    postinstall_cmds='base_file=`basename \${file}`~
-      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
-      dldir=$destdir/`dirname \$dlpath`~
-      test -d \$dldir || mkdir -p \$dldir~
-      $install_prog $dir/$dlname \$dldir/$dlname~
-      chmod a+x \$dldir/$dlname~
-      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
-        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
-      fi'
-    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
-      dlpath=$dir/\$dldll~
-       $RM \$dlpath'
-    shlibpath_overrides_runpath=yes
-
-    case $host_os in
-    cygwin*)
-      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
-      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
-
-      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
-      ;;
-    mingw* | cegcc*)
-      # MinGW DLLs use traditional 'lib' prefix
-      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
-      ;;
-    pw32*)
-      # pw32 DLLs use 'pw' prefix rather than 'lib'
-      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
-      ;;
-    esac
-    dynamic_linker='Win32 ld.exe'
-    ;;
-
-  *,cl*)
-    # Native MSVC
-    libname_spec='$name'
-    soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
-    library_names_spec='${libname}.dll.lib'
-
-    case $build_os in
-    mingw*)
-      sys_lib_search_path_spec=
-      lt_save_ifs=$IFS
-      IFS=';'
-      for lt_path in $LIB
-      do
-        IFS=$lt_save_ifs
-        # Let DOS variable expansion print the short 8.3 style file name.
-        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
-        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
-      done
-      IFS=$lt_save_ifs
-      # Convert to MSYS style.
-      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
-      ;;
-    cygwin*)
-      # Convert to unix form, then to dos form, then back to unix form
-      # but this time dos style (no spaces!) so that the unix form looks
-      # like /cygdrive/c/PROGRA~1:/cygdr...
-      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
-      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
-      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
-      ;;
-    *)
-      sys_lib_search_path_spec="$LIB"
-      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
-        # It is most probably a Windows format PATH.
-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
-      else
-        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
-      fi
-      # FIXME: find the short name or the path components, as spaces are
-      # common. (e.g. "Program Files" -> "PROGRA~1")
-      ;;
-    esac
-
-    # DLL is installed to $(libdir)/../bin by postinstall_cmds
-    postinstall_cmds='base_file=`basename \${file}`~
-      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
-      dldir=$destdir/`dirname \$dlpath`~
-      test -d \$dldir || mkdir -p \$dldir~
-      $install_prog $dir/$dlname \$dldir/$dlname'
-    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
-      dlpath=$dir/\$dldll~
-       $RM \$dlpath'
-    shlibpath_overrides_runpath=yes
-    dynamic_linker='Win32 link.exe'
-    ;;
-
-  *)
-    # Assume MSVC wrapper
-    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
-    dynamic_linker='Win32 ld.exe'
-    ;;
-  esac
-  # FIXME: first we should search . and the directory the executable is in
-  shlibpath_var=PATH
-  ;;
-
-darwin* | rhapsody*)
-  dynamic_linker="$host_os dyld"
-  version_type=darwin
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
-  soname_spec='${libname}${release}${major}$shared_ext'
-  shlibpath_overrides_runpath=yes
-  shlibpath_var=DYLD_LIBRARY_PATH
-  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
-
-  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
-  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
-  ;;
-
-dgux*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-freebsd* | dragonfly*)
-  # DragonFly does not have aout.  When/if they implement a new
-  # versioning mechanism, adjust this.
-  if test -x /usr/bin/objformat; then
-    objformat=`/usr/bin/objformat`
-  else
-    case $host_os in
-    freebsd[23].*) objformat=aout ;;
-    *) objformat=elf ;;
-    esac
-  fi
-  version_type=freebsd-$objformat
-  case $version_type in
-    freebsd-elf*)
-      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
-      need_version=no
-      need_lib_prefix=no
-      ;;
-    freebsd-*)
-      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
-      need_version=yes
-      ;;
-  esac
-  shlibpath_var=LD_LIBRARY_PATH
-  case $host_os in
-  freebsd2.*)
-    shlibpath_overrides_runpath=yes
-    ;;
-  freebsd3.[01]* | freebsdelf3.[01]*)
-    shlibpath_overrides_runpath=yes
-    hardcode_into_libs=yes
-    ;;
-  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
-  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
-    shlibpath_overrides_runpath=no
-    hardcode_into_libs=yes
-    ;;
-  *) # from 4.6 on, and DragonFly
-    shlibpath_overrides_runpath=yes
-    hardcode_into_libs=yes
-    ;;
-  esac
-  ;;
-
-gnu*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  ;;
-
-haiku*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_lib_prefix=no
-  need_version=no
-  dynamic_linker="$host_os runtime_loader"
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
-  hardcode_into_libs=yes
-  ;;
-
-hpux9* | hpux10* | hpux11*)
-  # Give a soname corresponding to the major version so that dld.sl refuses to
-  # link against other versions.
-  version_type=sunos
-  need_lib_prefix=no
-  need_version=no
-  case $host_cpu in
-  ia64*)
-    shrext_cmds='.so'
-    hardcode_into_libs=yes
-    dynamic_linker="$host_os dld.so"
-    shlibpath_var=LD_LIBRARY_PATH
-    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
-    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-    soname_spec='${libname}${release}${shared_ext}$major'
-    if test "X$HPUX_IA64_MODE" = X32; then
-      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
-    else
-      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
-    fi
-    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
-    ;;
-  hppa*64*)
-    shrext_cmds='.sl'
-    hardcode_into_libs=yes
-    dynamic_linker="$host_os dld.sl"
-    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
-    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
-    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-    soname_spec='${libname}${release}${shared_ext}$major'
-    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
-    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
-    ;;
-  *)
-    shrext_cmds='.sl'
-    dynamic_linker="$host_os dld.sl"
-    shlibpath_var=SHLIB_PATH
-    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
-    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-    soname_spec='${libname}${release}${shared_ext}$major'
-    ;;
-  esac
-  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
-  postinstall_cmds='chmod 555 $lib'
-  # or fails outright, so override atomically:
-  install_override_mode=555
-  ;;
-
-interix[3-9]*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  ;;
-
-irix5* | irix6* | nonstopux*)
-  case $host_os in
-    nonstopux*) version_type=nonstopux ;;
-    *)
-       if test "$lt_cv_prog_gnu_ld" = yes; then
-               version_type=linux # correct to gnu/linux during the next big refactor
-       else
-               version_type=irix
-       fi ;;
-  esac
-  need_lib_prefix=no
-  need_version=no
-  soname_spec='${libname}${release}${shared_ext}$major'
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
-  case $host_os in
-  irix5* | nonstopux*)
-    libsuff= shlibsuff=
-    ;;
-  *)
-    case $LD in # libtool.m4 will add one of these switches to LD
-    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
-      libsuff= shlibsuff= libmagic=32-bit;;
-    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
-      libsuff=32 shlibsuff=N32 libmagic=N32;;
-    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
-      libsuff=64 shlibsuff=64 libmagic=64-bit;;
-    *) libsuff= shlibsuff= libmagic=never-match;;
-    esac
-    ;;
-  esac
-  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
-  shlibpath_overrides_runpath=no
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
-  hardcode_into_libs=yes
-  ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux*oldld* | linux*aout* | linux*coff*)
-  dynamic_linker=no
-  ;;
-
-linux*android*)
-  version_type=none # Android doesn't support versioned libraries.
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='$libname$release$shared_ext'
-  soname_spec='$libname$release$shared_ext'
-  finish_cmds=
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-
-  # This implies no fast_install, which is unacceptable.
-  # Some rework will be needed to allow for fast_install
-  # before this can be enabled.
-  hardcode_into_libs=yes
-
-  dynamic_linker='Android linker'
-  # Don't embed -rpath directories since the linker doesn't support them.
-  hardcode_libdir_flag_spec='-L$libdir'
-  ;;
-
-# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-
-  # Some binutils ld are patched to set DT_RUNPATH
-  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  lt_cv_shlibpath_overrides_runpath=no
-    save_LDFLAGS=$LDFLAGS
-    save_libdir=$libdir
-    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
-        LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
-  lt_cv_shlibpath_overrides_runpath=yes
-fi
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-    LDFLAGS=$save_LDFLAGS
-    libdir=$save_libdir
-
-fi
-
-  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
-
-  # This implies no fast_install, which is unacceptable.
-  # Some rework will be needed to allow for fast_install
-  # before this can be enabled.
-  hardcode_into_libs=yes
-
-  # Append ld.so.conf contents to the search path
-  if test -f /etc/ld.so.conf; then
-    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[      ]*hwcap[        ]/d;s/[:,      ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
-  fi
-
-  # We used to test for /lib/ld.so.1 and disable shared libraries on
-  # powerpc, because MkLinux only supported shared libraries with the
-  # GNU dynamic linker.  Since this was broken with cross compilers,
-  # most powerpc-linux boxes support dynamic linking these days and
-  # people can always --disable-shared, the test was removed, and we
-  # assume the GNU/Linux dynamic linker is in use.
-  dynamic_linker='GNU/Linux ld.so'
-  ;;
-
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
-netbsd*)
-  version_type=sunos
-  need_lib_prefix=no
-  need_version=no
-  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
-    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
-    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-    dynamic_linker='NetBSD (a.out) ld.so'
-  else
-    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-    soname_spec='${libname}${release}${shared_ext}$major'
-    dynamic_linker='NetBSD ld.elf_so'
-  fi
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  hardcode_into_libs=yes
-  ;;
-
-newsos6)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  ;;
-
-*nto* | *qnx*)
-  version_type=qnx
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='ldqnx.so'
-  ;;
-
-openbsd*)
-  version_type=sunos
-  sys_lib_dlsearch_path_spec="/usr/lib"
-  need_lib_prefix=no
-  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
-  case $host_os in
-    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
-    *)                         need_version=no  ;;
-  esac
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
-    case $host_os in
-      openbsd2.[89] | openbsd2.[89].*)
-       shlibpath_overrides_runpath=no
-       ;;
-      *)
-       shlibpath_overrides_runpath=yes
-       ;;
-      esac
-  else
-    shlibpath_overrides_runpath=yes
-  fi
-  ;;
-
-os2*)
-  libname_spec='$name'
-  shrext_cmds=".dll"
-  need_lib_prefix=no
-  library_names_spec='$libname${shared_ext} $libname.a'
-  dynamic_linker='OS/2 ld.exe'
-  shlibpath_var=LIBPATH
-  ;;
-
-osf3* | osf4* | osf5*)
-  version_type=osf
-  need_lib_prefix=no
-  need_version=no
-  soname_spec='${libname}${release}${shared_ext}$major'
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  shlibpath_var=LD_LIBRARY_PATH
-  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
-  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
-  ;;
-
-rdos*)
-  dynamic_linker=no
-  ;;
-
-solaris*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  hardcode_into_libs=yes
-  # ldd complains unless libraries are executable
-  postinstall_cmds='chmod +x $lib'
-  ;;
-
-sunos4*)
-  version_type=sunos
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
-  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  if test "$with_gnu_ld" = yes; then
-    need_lib_prefix=no
-  fi
-  need_version=yes
-  ;;
-
-sysv4 | sysv4.3*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  case $host_vendor in
-    sni)
-      shlibpath_overrides_runpath=no
-      need_lib_prefix=no
-      runpath_var=LD_RUN_PATH
-      ;;
-    siemens)
-      need_lib_prefix=no
-      ;;
-    motorola)
-      need_lib_prefix=no
-      need_version=no
-      shlibpath_overrides_runpath=no
-      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
-      ;;
-  esac
-  ;;
-
-sysv4*MP*)
-  if test -d /usr/nec ;then
-    version_type=linux # correct to gnu/linux during the next big refactor
-    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
-    soname_spec='$libname${shared_ext}.$major'
-    shlibpath_var=LD_LIBRARY_PATH
-  fi
-  ;;
-
-sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
-  version_type=freebsd-elf
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  hardcode_into_libs=yes
-  if test "$with_gnu_ld" = yes; then
-    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
-  else
-    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
-    case $host_os in
-      sco3.2v5*)
-        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
-       ;;
-    esac
-  fi
-  sys_lib_dlsearch_path_spec='/usr/lib'
-  ;;
-
-tpf*)
-  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
-  version_type=linux # correct to gnu/linux during the next big refactor
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  ;;
-
-uts4*)
-  version_type=linux # correct to gnu/linux during the next big refactor
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-*)
-  dynamic_linker=no
-  ;;
-esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
-$as_echo "$dynamic_linker" >&6; }
-test "$dynamic_linker" = no && can_build_shared=no
-
-variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
-if test "$GCC" = yes; then
-  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
-fi
-
-if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
-  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
-fi
-if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
-  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
-$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" ||
-   test -n "$runpath_var" ||
-   test "X$hardcode_automatic" = "Xyes" ; then
-
-  # We can hardcode non-existent directories.
-  if test "$hardcode_direct" != no &&
-     # If the only mechanism to avoid hardcoding is shlibpath_var, we
-     # have to relink, otherwise we might link with an installed library
-     # when we should be linking with a yet-to-be-installed one
-     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
-     test "$hardcode_minus_L" != no; then
-    # Linking always hardcodes the temporary library directory.
-    hardcode_action=relink
-  else
-    # We can link without hardcoding, and we can hardcode nonexisting dirs.
-    hardcode_action=immediate
-  fi
-else
-  # We cannot hardcode anything, or else we can only hardcode existing
-  # directories.
-  hardcode_action=unsupported
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
-$as_echo "$hardcode_action" >&6; }
-
-if test "$hardcode_action" = relink ||
-   test "$inherit_rpath" = yes; then
-  # Fast installation is not supported
-  enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
-     test "$enable_shared" = no; then
-  # Fast installation is not necessary
-  enable_fast_install=needless
-fi
-
-
-
-
-
-
-  if test "x$enable_dlopen" != xyes; then
-  enable_dlopen=unknown
-  enable_dlopen_self=unknown
-  enable_dlopen_self_static=unknown
-else
-  lt_cv_dlopen=no
-  lt_cv_dlopen_libs=
-
-  case $host_os in
-  beos*)
-    lt_cv_dlopen="load_add_on"
-    lt_cv_dlopen_libs=
-    lt_cv_dlopen_self=yes
-    ;;
-
-  mingw* | pw32* | cegcc*)
-    lt_cv_dlopen="LoadLibrary"
-    lt_cv_dlopen_libs=
-    ;;
-
-  cygwin*)
-    lt_cv_dlopen="dlopen"
-    lt_cv_dlopen_libs=
-    ;;
-
-  darwin*)
-  # if libdl is installed we need to link against it
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
-$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if ${ac_cv_lib_dl_dlopen+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_dl_dlopen=yes
-else
-  ac_cv_lib_dl_dlopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
-$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
-  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
-
-    lt_cv_dlopen="dyld"
-    lt_cv_dlopen_libs=
-    lt_cv_dlopen_self=yes
-
-fi
-
-    ;;
-
-  *)
-    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
-if test "x$ac_cv_func_shl_load" = xyes; then :
-  lt_cv_dlopen="shl_load"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
-$as_echo_n "checking for shl_load in -ldld... " >&6; }
-if ${ac_cv_lib_dld_shl_load+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldld  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load ();
-int
-main ()
-{
-return shl_load ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_dld_shl_load=yes
-else
-  ac_cv_lib_dld_shl_load=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
-$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
-if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
-  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
-else
-  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
-if test "x$ac_cv_func_dlopen" = xyes; then :
-  lt_cv_dlopen="dlopen"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
-$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if ${ac_cv_lib_dl_dlopen+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_dl_dlopen=yes
-else
-  ac_cv_lib_dl_dlopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
-$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
-  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
-$as_echo_n "checking for dlopen in -lsvld... " >&6; }
-if ${ac_cv_lib_svld_dlopen+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsvld  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_svld_dlopen=yes
-else
-  ac_cv_lib_svld_dlopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
-$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
-if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
-  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
-$as_echo_n "checking for dld_link in -ldld... " >&6; }
-if ${ac_cv_lib_dld_dld_link+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldld  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dld_link ();
-int
-main ()
-{
-return dld_link ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_dld_dld_link=yes
-else
-  ac_cv_lib_dld_dld_link=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
-$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
-if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
-  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-
-fi
-
-    ;;
-  esac
-
-  if test "x$lt_cv_dlopen" != xno; then
-    enable_dlopen=yes
-  else
-    enable_dlopen=no
-  fi
-
-  case $lt_cv_dlopen in
-  dlopen)
-    save_CPPFLAGS="$CPPFLAGS"
-    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-
-    save_LDFLAGS="$LDFLAGS"
-    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-
-    save_LIBS="$LIBS"
-    LIBS="$lt_cv_dlopen_libs $LIBS"
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
-$as_echo_n "checking whether a program can dlopen itself... " >&6; }
-if ${lt_cv_dlopen_self+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-         if test "$cross_compiling" = yes; then :
-  lt_cv_dlopen_self=cross
-else
-  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
-  lt_status=$lt_dlunknown
-  cat > conftest.$ac_ext <<_LT_EOF
-#line $LINENO "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-#  define LT_DLGLOBAL          RTLD_GLOBAL
-#else
-#  ifdef DL_GLOBAL
-#    define LT_DLGLOBAL                DL_GLOBAL
-#  else
-#    define LT_DLGLOBAL                0
-#  endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-#  ifdef RTLD_LAZY
-#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
-#  else
-#    ifdef DL_LAZY
-#      define LT_DLLAZY_OR_NOW         DL_LAZY
-#    else
-#      ifdef RTLD_NOW
-#        define LT_DLLAZY_OR_NOW       RTLD_NOW
-#      else
-#        ifdef DL_NOW
-#          define LT_DLLAZY_OR_NOW     DL_NOW
-#        else
-#          define LT_DLLAZY_OR_NOW     0
-#        endif
-#      endif
-#    endif
-#  endif
-#endif
-
-/* When -fvisbility=hidden is used, assume the code has been annotated
-   correspondingly for the symbols needed.  */
-#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
-int fnord () __attribute__((visibility("default")));
-#endif
-
-int fnord () { return 42; }
-int main ()
-{
-  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
-  int status = $lt_dlunknown;
-
-  if (self)
-    {
-      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
-      else
-        {
-         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
-          else puts (dlerror ());
-       }
-      /* dlclose (self); */
-    }
-  else
-    puts (dlerror ());
-
-  return status;
-}
-_LT_EOF
-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) >&5 2>/dev/null
-    lt_status=$?
-    case x$lt_status in
-      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
-      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
-      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
-    esac
-  else :
-    # compilation failed
-    lt_cv_dlopen_self=no
-  fi
-fi
-rm -fr conftest*
-
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
-$as_echo "$lt_cv_dlopen_self" >&6; }
-
-    if test "x$lt_cv_dlopen_self" = xyes; then
-      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
-      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
-$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
-if ${lt_cv_dlopen_self_static+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-         if test "$cross_compiling" = yes; then :
-  lt_cv_dlopen_self_static=cross
-else
-  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
-  lt_status=$lt_dlunknown
-  cat > conftest.$ac_ext <<_LT_EOF
-#line $LINENO "configure"
-#include "confdefs.h"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-#  define LT_DLGLOBAL          RTLD_GLOBAL
-#else
-#  ifdef DL_GLOBAL
-#    define LT_DLGLOBAL                DL_GLOBAL
-#  else
-#    define LT_DLGLOBAL                0
-#  endif
-#endif
-
-/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
-#ifndef LT_DLLAZY_OR_NOW
-#  ifdef RTLD_LAZY
-#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
-#  else
-#    ifdef DL_LAZY
-#      define LT_DLLAZY_OR_NOW         DL_LAZY
-#    else
-#      ifdef RTLD_NOW
-#        define LT_DLLAZY_OR_NOW       RTLD_NOW
-#      else
-#        ifdef DL_NOW
-#          define LT_DLLAZY_OR_NOW     DL_NOW
-#        else
-#          define LT_DLLAZY_OR_NOW     0
-#        endif
-#      endif
-#    endif
-#  endif
-#endif
-
-/* When -fvisbility=hidden is used, assume the code has been annotated
-   correspondingly for the symbols needed.  */
-#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
-int fnord () __attribute__((visibility("default")));
-#endif
-
-int fnord () { return 42; }
-int main ()
-{
-  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
-  int status = $lt_dlunknown;
-
-  if (self)
-    {
-      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
-      else
-        {
-         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
-          else puts (dlerror ());
-       }
-      /* dlclose (self); */
-    }
-  else
-    puts (dlerror ());
-
-  return status;
-}
-_LT_EOF
-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
-    (./conftest; exit; ) >&5 2>/dev/null
-    lt_status=$?
-    case x$lt_status in
-      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
-      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
-      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
-    esac
-  else :
-    # compilation failed
-    lt_cv_dlopen_self_static=no
-  fi
-fi
-rm -fr conftest*
-
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
-$as_echo "$lt_cv_dlopen_self_static" >&6; }
-    fi
-
-    CPPFLAGS="$save_CPPFLAGS"
-    LDFLAGS="$save_LDFLAGS"
-    LIBS="$save_LIBS"
-    ;;
-  esac
-
-  case $lt_cv_dlopen_self in
-  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
-  *) enable_dlopen_self=unknown ;;
-  esac
-
-  case $lt_cv_dlopen_self_static in
-  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
-  *) enable_dlopen_self_static=unknown ;;
-  esac
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-striplib=
-old_striplib=
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
-$as_echo_n "checking whether stripping libraries is possible... " >&6; }
-if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
-  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
-  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-else
-# FIXME - insert some real tests, host_os isn't really good enough
-  case $host_os in
-  darwin*)
-    if test -n "$STRIP" ; then
-      striplib="$STRIP -x"
-      old_striplib="$STRIP -S"
-      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-    else
-      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-    fi
-    ;;
-  *)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-    ;;
-  esac
-fi
-
-
-
-
-
-
-
-
-
-
-
-
-  # Report which library types will actually be built
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
-$as_echo_n "checking if libtool supports shared libraries... " >&6; }
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
-$as_echo "$can_build_shared" >&6; }
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
-$as_echo_n "checking whether to build shared libraries... " >&6; }
-  test "$can_build_shared" = "no" && enable_shared=no
-
-  # On AIX, shared libraries and static libraries use the same namespace, and
-  # are all built from PIC.
-  case $host_os in
-  aix3*)
-    test "$enable_shared" = yes && enable_static=no
-    if test -n "$RANLIB"; then
-      archive_cmds="$archive_cmds~\$RANLIB \$lib"
-      postinstall_cmds='$RANLIB $lib'
-    fi
-    ;;
-
-  aix[4-9]*)
-    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
-      test "$enable_shared" = yes && enable_static=no
-    fi
-    ;;
-  esac
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
-$as_echo "$enable_shared" >&6; }
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
-$as_echo_n "checking whether to build static libraries... " >&6; }
-  # Make sure either enable_shared or enable_static is yes.
-  test "$enable_shared" = yes || enable_static=yes
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
-$as_echo "$enable_static" >&6; }
-
-
-
-
-fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-CC="$lt_save_CC"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-        ac_config_commands="$ac_config_commands libtool"
-
-
-
-
-# Only expand once:
-
-
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args.
-set dummy ${ac_tool_prefix}windres; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$RC"; then
-  ac_cv_prog_RC="$RC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_RC="${ac_tool_prefix}windres"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-RC=$ac_cv_prog_RC
-if test -n "$RC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5
-$as_echo "$RC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RC"; then
-  ac_ct_RC=$RC
-  # Extract the first word of "windres", so it can be a program name with args.
-set dummy windres; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_RC"; then
-  ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_RC="windres"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_RC=$ac_cv_prog_ac_ct_RC
-if test -n "$ac_ct_RC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5
-$as_echo "$ac_ct_RC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_RC" = x; then
-    RC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    RC=$ac_ct_RC
-  fi
-else
-  RC="$ac_cv_prog_RC"
-fi
-
-
-
-
-# Source file extension for RC test sources.
-ac_ext=rc
-
-# Object file extension for compiled RC test sources.
-objext=o
-objext_RC=$objext
-
-# Code to be used in simple compile tests
-lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
-
-# Code to be used in simple link tests
-lt_simple_link_test_code="$lt_simple_compile_test_code"
-
-# ltmain only uses $CC for tagged configurations so make sure $CC is set.
-
-
-
-
-
-
-# If no C compiler was specified, use CC.
-LTCC=${LTCC-"$CC"}
-
-# If no C compiler flags were specified, use CFLAGS.
-LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
-
-# Allow CC to be a program name with arguments.
-compiler=$CC
-
-
-# save warnings/boilerplate of simple test code
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_compile_test_code" >conftest.$ac_ext
-eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_compiler_boilerplate=`cat conftest.err`
-$RM conftest*
-
-ac_outfile=conftest.$ac_objext
-echo "$lt_simple_link_test_code" >conftest.$ac_ext
-eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
-_lt_linker_boilerplate=`cat conftest.err`
-$RM -r conftest*
-
-
-# Allow CC to be a program name with arguments.
-lt_save_CC="$CC"
-lt_save_CFLAGS=$CFLAGS
-lt_save_GCC=$GCC
-GCC=
-CC=${RC-"windres"}
-CFLAGS=
-compiler=$CC
-compiler_RC=$CC
-for cc_temp in $compiler""; do
-  case $cc_temp in
-    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
-    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
-    \-*) ;;
-    *) break;;
-  esac
-done
-cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
-
-lt_cv_prog_compiler_c_o_RC=yes
-
-if test -n "$compiler"; then
-  :
-
-
-
-fi
-
-GCC=$lt_save_GCC
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-CC=$lt_save_CC
-CFLAGS=$lt_save_CFLAGS
-
-
-
-##########################
-## General definitions. ##
-##########################
-
-# Used by libgcrypt-config
-LIBGCRYPT_CONFIG_LIBS="-lgcrypt"
-LIBGCRYPT_CONFIG_CFLAGS=""
-LIBGCRYPT_CONFIG_HOST="$host"
-
-# Definitions for symmetric ciphers.
-available_ciphers="arcfour blowfish cast5 des aes twofish serpent rfc2268 seed"
-available_ciphers="$available_ciphers camellia idea salsa20 gost28147 chacha20"
-enabled_ciphers=""
-
-# Definitions for public-key ciphers.
-available_pubkey_ciphers="dsa elgamal rsa ecc"
-enabled_pubkey_ciphers=""
-
-# Definitions for message digests.
-available_digests="crc gostr3411-94 md2 md4 md5 rmd160 sha1 sha256 sha512"
-available_digests="$available_digests sha3 tiger whirlpool stribog blake2"
-enabled_digests=""
-
-# Definitions for kdfs (optional ones)
-available_kdfs="s2k pkdf2 scrypt"
-enabled_kdfs=""
-
-# Definitions for random modules.
-available_random_modules="linux egd unix"
-auto_random_modules="$available_random_modules"
-
-# Supported thread backends.
-LIBGCRYPT_THREAD_MODULES=""
-
-# Other definitions.
-have_w32_system=no
-have_w32ce_system=no
-have_pthread=no
-
-
-# Setup some stuff depending on host.
-case "${host}" in
-    *-*-mingw32*)
-      ac_cv_have_dev_random=no
-      have_w32_system=yes
-      case "${host}" in
-        *-mingw32ce*)
-            have_w32ce_system=yes
-            available_random_modules="w32ce"
-            ;;
-        *)
-            available_random_modules="w32"
-            ;;
-      esac
-
-$as_echo "#define USE_ONLY_8DOT3 1" >>confdefs.h
-
-
-$as_echo "#define HAVE_DRIVE_LETTERS 1" >>confdefs.h
-
-
-$as_echo "#define HAVE_DOSISH_SYSTEM 1" >>confdefs.h
-
-      ;;
-
-    i?86-emx-os2 | i?86-*-os2*emx)
-        # OS/2 with the EMX environment
-        ac_cv_have_dev_random=no
-        $as_echo "#define HAVE_DRIVE_LETTERS 1" >>confdefs.h
-
-        $as_echo "#define HAVE_DOSISH_SYSTEM 1" >>confdefs.h
-
-        ;;
-
-    i?86-*-msdosdjgpp*)
-        # DOS with the DJGPP environment
-        ac_cv_have_dev_random=no
-        $as_echo "#define HAVE_DRIVE_LETTERS 1" >>confdefs.h
-
-        $as_echo "#define HAVE_DOSISH_SYSTEM 1" >>confdefs.h
-
-        ;;
-
-    *-*-hpux*)
-        if test -z "$GCC" ; then
-            CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE"
-        fi
-        ;;
-    *-dec-osf4*)
-        if test -z "$GCC" ; then
-            # Suppress all warnings
-            # to get rid of the unsigned/signed char mismatch warnings.
-            CFLAGS="$CFLAGS -w"
-        fi
-        ;;
-    m68k-atari-mint)
-        ;;
-    *-apple-darwin*)
-
-$as_echo "#define _DARWIN_C_SOURCE 900000L" >>confdefs.h
-
-        ;;
-    *)
-      ;;
-esac
-
-if test "$have_w32_system" = yes; then
-
-$as_echo "#define HAVE_W32_SYSTEM 1" >>confdefs.h
-
-   if test "$have_w32ce_system" = yes; then
-
-$as_echo "#define HAVE_W32CE_SYSTEM 1" >>confdefs.h
-
-   fi
-fi
- if test "$have_w32_system" = yes; then
-  HAVE_W32_SYSTEM_TRUE=
-  HAVE_W32_SYSTEM_FALSE='#'
-else
-  HAVE_W32_SYSTEM_TRUE='#'
-  HAVE_W32_SYSTEM_FALSE=
-fi
-
- if test "$have_w32ce_system" = yes; then
-  HAVE_W32CE_SYSTEM_TRUE=
-  HAVE_W32CE_SYSTEM_FALSE='#'
-else
-  HAVE_W32CE_SYSTEM_TRUE='#'
-  HAVE_W32CE_SYSTEM_FALSE=
-fi
-
-
-
-
-# A printable OS Name is sometimes useful.
-case "${host}" in
-    *-*-mingw32ce*)
-        PRINTABLE_OS_NAME="W32CE"
-        ;;
-
-    *-*-mingw32*)
-        PRINTABLE_OS_NAME="W32"
-        ;;
-
-    i?86-emx-os2 | i?86-*-os2*emx )
-        PRINTABLE_OS_NAME="OS/2"
-        ;;
-
-    i?86-*-msdosdjgpp*)
-        PRINTABLE_OS_NAME="MSDOS/DJGPP"
-        ;;
-
-    *-linux*)
-        PRINTABLE_OS_NAME="GNU/Linux"
-        ;;
-
-    *)
-        PRINTABLE_OS_NAME=`uname -s || echo "Unknown"`
-        ;;
-esac
-
-NAME_OF_DEV_RANDOM="/dev/random"
-NAME_OF_DEV_URANDOM="/dev/urandom"
-
-# Check whether --enable-endian-check was given.
-if test "${enable_endian_check+set}" = set; then :
-  enableval=$enable_endian_check; endiancheck=$enableval
-else
-  endiancheck=yes
-fi
-
-if test x"$endiancheck" = xyes ; then
-   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
-$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
-if ${ac_cv_c_bigendian+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_cv_c_bigendian=unknown
-    # See if we're dealing with a universal compiler.
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#ifndef __APPLE_CC__
-              not a universal capable compiler
-            #endif
-            typedef int dummy;
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-       # Check for potential -arch flags.  It is not universal unless
-       # there are at least two -arch flags with different values.
-       ac_arch=
-       ac_prev=
-       for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
-        if test -n "$ac_prev"; then
-          case $ac_word in
-            i?86 | x86_64 | ppc | ppc64)
-              if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
-                ac_arch=$ac_word
-              else
-                ac_cv_c_bigendian=universal
-                break
-              fi
-              ;;
-          esac
-          ac_prev=
-        elif test "x$ac_word" = "x-arch"; then
-          ac_prev=arch
-        fi
-       done
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-    if test $ac_cv_c_bigendian = unknown; then
-      # See if sys/param.h defines the BYTE_ORDER macro.
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <sys/types.h>
-            #include <sys/param.h>
-
-int
-main ()
-{
-#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
-                    && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
-                    && LITTLE_ENDIAN)
-             bogus endian macros
-            #endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  # It does; now see whether it defined to BIG_ENDIAN or not.
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <sys/types.h>
-               #include <sys/param.h>
-
-int
-main ()
-{
-#if BYTE_ORDER != BIG_ENDIAN
-                not big endian
-               #endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_c_bigendian=yes
-else
-  ac_cv_c_bigendian=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-    fi
-    if test $ac_cv_c_bigendian = unknown; then
-      # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <limits.h>
-
-int
-main ()
-{
-#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
-             bogus endian macros
-            #endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  # It does; now see whether it defined to _BIG_ENDIAN or not.
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <limits.h>
-
-int
-main ()
-{
-#ifndef _BIG_ENDIAN
-                not big endian
-               #endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_c_bigendian=yes
-else
-  ac_cv_c_bigendian=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-    fi
-    if test $ac_cv_c_bigendian = unknown; then
-      # Compile a test program.
-      if test "$cross_compiling" = yes; then :
-  # Try to guess by grepping values from an object file.
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-short int ascii_mm[] =
-                 { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
-               short int ascii_ii[] =
-                 { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
-               int use_ascii (int i) {
-                 return ascii_mm[i] + ascii_ii[i];
-               }
-               short int ebcdic_ii[] =
-                 { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
-               short int ebcdic_mm[] =
-                 { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
-               int use_ebcdic (int i) {
-                 return ebcdic_mm[i] + ebcdic_ii[i];
-               }
-               extern int foo;
-
-int
-main ()
-{
-return use_ascii (foo) == use_ebcdic (foo);
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
-             ac_cv_c_bigendian=yes
-           fi
-           if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
-             if test "$ac_cv_c_bigendian" = unknown; then
-               ac_cv_c_bigendian=no
-             else
-               # finding both strings is unlikely to happen, but who knows?
-               ac_cv_c_bigendian=unknown
-             fi
-           fi
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-
-            /* Are we little or big endian?  From Harbison&Steele.  */
-            union
-            {
-              long int l;
-              char c[sizeof (long int)];
-            } u;
-            u.l = 1;
-            return u.c[sizeof (long int) - 1] == 1;
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  ac_cv_c_bigendian=no
-else
-  ac_cv_c_bigendian=yes
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-    fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
-$as_echo "$ac_cv_c_bigendian" >&6; }
- case $ac_cv_c_bigendian in #(
-   yes)
-     $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
-;; #(
-   no)
-      ;; #(
-   universal)
-
-$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
-
-     ;; #(
-   *)
-     as_fn_error $? "unknown endianness
- presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
- esac
-
-else
-
-$as_echo "#define DISABLED_ENDIAN_CHECK 1" >>confdefs.h
-
-fi
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned short" >&5
-$as_echo_n "checking size of unsigned short... " >&6; }
-if ${ac_cv_sizeof_unsigned_short+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned short))" "ac_cv_sizeof_unsigned_short"        "$ac_includes_default"; then :
-
-else
-  if test "$ac_cv_type_unsigned_short" = yes; then
-     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (unsigned short)
-See \`config.log' for more details" "$LINENO" 5; }
-   else
-     ac_cv_sizeof_unsigned_short=0
-   fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_short" >&5
-$as_echo "$ac_cv_sizeof_unsigned_short" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_UNSIGNED_SHORT $ac_cv_sizeof_unsigned_short
-_ACEOF
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned int" >&5
-$as_echo_n "checking size of unsigned int... " >&6; }
-if ${ac_cv_sizeof_unsigned_int+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned int))" "ac_cv_sizeof_unsigned_int"        "$ac_includes_default"; then :
-
-else
-  if test "$ac_cv_type_unsigned_int" = yes; then
-     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (unsigned int)
-See \`config.log' for more details" "$LINENO" 5; }
-   else
-     ac_cv_sizeof_unsigned_int=0
-   fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_int" >&5
-$as_echo "$ac_cv_sizeof_unsigned_int" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int
-_ACEOF
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5
-$as_echo_n "checking size of unsigned long... " >&6; }
-if ${ac_cv_sizeof_unsigned_long+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long"        "$ac_includes_default"; then :
-
-else
-  if test "$ac_cv_type_unsigned_long" = yes; then
-     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (unsigned long)
-See \`config.log' for more details" "$LINENO" 5; }
-   else
-     ac_cv_sizeof_unsigned_long=0
-   fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5
-$as_echo "$ac_cv_sizeof_unsigned_long" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long
-_ACEOF
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5
-$as_echo_n "checking size of unsigned long long... " >&6; }
-if ${ac_cv_sizeof_unsigned_long_long+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long"        "$ac_includes_default"; then :
-
-else
-  if test "$ac_cv_type_unsigned_long_long" = yes; then
-     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (unsigned long long)
-See \`config.log' for more details" "$LINENO" 5; }
-   else
-     ac_cv_sizeof_unsigned_long_long=0
-   fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5
-$as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long
-_ACEOF
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p"        "$ac_includes_default"; then :
-
-else
-  if test "$ac_cv_type_void_p" = yes; then
-     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (void *)
-See \`config.log' for more details" "$LINENO" 5; }
-   else
-     ac_cv_sizeof_void_p=0
-   fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
-
-
-
-
-  ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
-if test "x$ac_cv_type_uintptr_t" = xyes; then :
-
-$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h
-
-else
-  for ac_type in 'unsigned int' 'unsigned long int' \
-       'unsigned long long int'; do
-       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($ac_type))];
-test_array [0] = 0;
-return test_array [0];
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-cat >>confdefs.h <<_ACEOF
-#define uintptr_t $ac_type
-_ACEOF
-
-         ac_type=
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-       test -z "$ac_type" && break
-     done
-fi
-
-
-
-if test "$ac_cv_sizeof_unsigned_short" = "0" \
-   || test "$ac_cv_sizeof_unsigned_int" = "0" \
-   || test "$ac_cv_sizeof_unsigned_long" = "0"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Hmmm, something is wrong with the sizes - using defaults" >&5
-$as_echo "$as_me: WARNING: Hmmm, something is wrong with the sizes - using defaults" >&2;};
-fi
-
-# Ensure that we have UINT64_C before we bother to check for uint64_t
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for UINT64_C" >&5
-$as_echo_n "checking for UINT64_C... " >&6; }
-if ${gnupg_cv_uint64_c_works+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <inttypes.h>
-int
-main ()
-{
-uint64_t foo=UINT64_C(42);
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gnupg_cv_uint64_c_works=yes
-else
-  gnupg_cv_uint64_c_works=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gnupg_cv_uint64_c_works" >&5
-$as_echo "$gnupg_cv_uint64_c_works" >&6; }
-if test "$gnupg_cv_uint64_c_works" = "yes" ; then
-   # The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of uint64_t" >&5
-$as_echo_n "checking size of uint64_t... " >&6; }
-if ${ac_cv_sizeof_uint64_t+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (uint64_t))" "ac_cv_sizeof_uint64_t"        "$ac_includes_default"; then :
-
-else
-  if test "$ac_cv_type_uint64_t" = yes; then
-     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (uint64_t)
-See \`config.log' for more details" "$LINENO" 5; }
-   else
-     ac_cv_sizeof_uint64_t=0
-   fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_uint64_t" >&5
-$as_echo "$ac_cv_sizeof_uint64_t" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_UINT64_T $ac_cv_sizeof_uint64_t
-_ACEOF
-
-
-fi
-
-# Do we have any 64-bit data types?
-if test "$ac_cv_sizeof_unsigned_int" != "8" \
-   && test "$ac_cv_sizeof_unsigned_long" != "8" \
-   && test "$ac_cv_sizeof_unsigned_long_long" != "8" \
-   && test "$ac_cv_sizeof_uint64_t" != "8"; then
-    as_fn_error $? "
-***
-*** No 64-bit integer type available.
-*** It is not possible to build Libgcrypt on this platform.
-***" "$LINENO" 5
-fi
-
-
-# If not specified otherwise, all available algorithms will be
-# included.
-default_ciphers="$available_ciphers"
-default_pubkey_ciphers="$available_pubkey_ciphers"
-default_digests="$available_digests"
-default_kdfs="$available_kdfs"
-# Blacklist MD2 by default
-default_digests=`echo $default_digests | sed -e 's/md2//g'`
-
-# Substitutions to set generated files in a Emacs buffer to read-only.
-emacs_local_vars_begin='Local Variables:'
-
-emacs_local_vars_read_only='buffer-read-only: t'
-
-emacs_local_vars_end='End:'
-
-
-############################
-## Command line switches. ##
-############################
-
-# Implementation of the --enable-ciphers switch.
-# Check whether --enable-ciphers was given.
-if test "${enable_ciphers+set}" = set; then :
-  enableval=$enable_ciphers; enabled_ciphers=`echo $enableval | tr ',:' '  ' | tr 'A-Z' 'a-z'`
-else
-  enabled_ciphers=""
-fi
-
-if test "x$enabled_ciphers" = "x" \
-   -o "$enabled_ciphers" = "yes"  \
-   -o "$enabled_ciphers" = "no"; then
-   enabled_ciphers=$default_ciphers
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which symmetric ciphers to include" >&5
-$as_echo_n "checking which symmetric ciphers to include... " >&6; }
-for cipher in $enabled_ciphers; do
-
-name=$cipher
-list=$available_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-    if test "$found" = "0"; then
-       as_fn_error $? "unsupported cipher \"$cipher\" specified" "$LINENO" 5
-    fi
-done
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enabled_ciphers" >&5
-$as_echo "$enabled_ciphers" >&6; }
-
-# Implementation of the --enable-pubkey-ciphers switch.
-# Check whether --enable-pubkey-ciphers was given.
-if test "${enable_pubkey_ciphers+set}" = set; then :
-  enableval=$enable_pubkey_ciphers; enabled_pubkey_ciphers=`echo $enableval | tr ',:' '  ' | tr 'A-Z' 'a-z'`
-else
-  enabled_pubkey_ciphers=""
-fi
-
-if test "x$enabled_pubkey_ciphers" = "x" \
-   -o "$enabled_pubkey_ciphers" = "yes"  \
-   -o "$enabled_pubkey_ciphers" = "no"; then
-   enabled_pubkey_ciphers=$default_pubkey_ciphers
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which public-key ciphers to include" >&5
-$as_echo_n "checking which public-key ciphers to include... " >&6; }
-for cipher in $enabled_pubkey_ciphers; do
-
-name=$cipher
-list=$available_pubkey_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-    if test "$found" = "0"; then
-       as_fn_error $? "unsupported public-key cipher specified" "$LINENO" 5
-    fi
-done
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enabled_pubkey_ciphers" >&5
-$as_echo "$enabled_pubkey_ciphers" >&6; }
-
-# Implementation of the --enable-digests switch.
-# Check whether --enable-digests was given.
-if test "${enable_digests+set}" = set; then :
-  enableval=$enable_digests; enabled_digests=`echo $enableval | tr ',:' '  ' | tr 'A-Z' 'a-z'`
-else
-  enabled_digests=""
-fi
-
-if test "x$enabled_digests" = "x" \
-   -o "$enabled_digests" = "yes"  \
-   -o "$enabled_digests" = "no"; then
-   enabled_digests=$default_digests
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which message digests to include" >&5
-$as_echo_n "checking which message digests to include... " >&6; }
-for digest in $enabled_digests; do
-
-name=$digest
-list=$available_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-    if test "$found" = "0"; then
-       as_fn_error $? "unsupported message digest specified" "$LINENO" 5
-    fi
-done
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enabled_digests" >&5
-$as_echo "$enabled_digests" >&6; }
-
-# Implementation of the --enable-kdfs switch.
-# Check whether --enable-kdfs was given.
-if test "${enable_kdfs+set}" = set; then :
-  enableval=$enable_kdfs; enabled_kdfs=`echo $enableval | tr ',:' '  ' | tr 'A-Z' 'a-z'`
-else
-  enabled_kdfs=""
-fi
-
-if test "x$enabled_kdfs" = "x" \
-   -o "$enabled_kdfs" = "yes"  \
-   -o "$enabled_kdfs" = "no"; then
-   enabled_kdfs=$default_kdfs
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which key derivation functions to include" >&5
-$as_echo_n "checking which key derivation functions to include... " >&6; }
-for kdf in $enabled_kdfs; do
-
-name=$kdf
-list=$available_kdfs
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-    if test "$found" = "0"; then
-       as_fn_error $? "unsupported key derivation function specified" "$LINENO" 5
-    fi
-done
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enabled_kdfs" >&5
-$as_echo "$enabled_kdfs" >&6; }
-
-# Implementation of the --enable-random switch.
-# Check whether --enable-random was given.
-if test "${enable_random+set}" = set; then :
-  enableval=$enable_random; random=`echo $enableval | tr 'A-Z' 'a-z'`
-fi
-
-if test "x$random" = "x" -o "$random" = "yes" -o "$random" = "no"; then
-    random=default
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which random module to use" >&5
-$as_echo_n "checking which random module to use... " >&6; }
-if test "$random" != "default" -a "$random" != "auto"; then
-
-name=$random
-list=$available_random_modules
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-    if test "$found" = "0"; then
-       as_fn_error $? "unsupported random module specified" "$LINENO" 5
-    fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $random" >&5
-$as_echo "$random" >&6; }
-
-# Implementation of the --disable-dev-random switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether use of /dev/random is requested" >&5
-$as_echo_n "checking whether use of /dev/random is requested... " >&6; }
-# Check whether --enable-dev-random was given.
-if test "${enable_dev_random+set}" = set; then :
-  enableval=$enable_dev_random; try_dev_random=$enableval
-else
-  try_dev_random=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $try_dev_random" >&5
-$as_echo "$try_dev_random" >&6; }
-
-# Implementation of the --with-egd-socket switch.
-
-# Check whether --with-egd-socket was given.
-if test "${with_egd_socket+set}" = set; then :
-  withval=$with_egd_socket; egd_socket_name="$withval"
-else
-  egd_socket_name=""
-fi
-
-
-cat >>confdefs.h <<_ACEOF
-#define EGD_SOCKET_NAME "$egd_socket_name"
-_ACEOF
-
-
-# Implementation of the --enable-random-daemon
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the experimental random daemon is requested" >&5
-$as_echo_n "checking whether the experimental random daemon is requested... " >&6; }
-# Check whether --enable-random-daemon was given.
-if test "${enable_random_daemon+set}" = set; then :
-  enableval=$enable_random_daemon; use_random_daemon=$enableval
-else
-  use_random_daemon=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_random_daemon" >&5
-$as_echo "$use_random_daemon" >&6; }
-if test x$use_random_daemon = xyes ; then
-
-$as_echo "#define USE_RANDOM_DAEMON 1" >>confdefs.h
-
-fi
- if test x$use_random_daemon = xyes; then
-  USE_RANDOM_DAEMON_TRUE=
-  USE_RANDOM_DAEMON_FALSE='#'
-else
-  USE_RANDOM_DAEMON_TRUE='#'
-  USE_RANDOM_DAEMON_FALSE=
-fi
-
-
-
-# Implementation of --disable-asm.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether MPI assembler modules are requested" >&5
-$as_echo_n "checking whether MPI assembler modules are requested... " >&6; }
-# Check whether --enable-asm was given.
-if test "${enable_asm+set}" = set; then :
-  enableval=$enable_asm; try_asm_modules=$enableval
-else
-  try_asm_modules=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $try_asm_modules" >&5
-$as_echo "$try_asm_modules" >&6; }
-
-# Implementation of the --enable-m-guard switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether memory guard is requested" >&5
-$as_echo_n "checking whether memory guard is requested... " >&6; }
-# Check whether --enable-m-guard was given.
-if test "${enable_m_guard+set}" = set; then :
-  enableval=$enable_m_guard; use_m_guard=$enableval
-else
-  use_m_guard=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_m_guard" >&5
-$as_echo "$use_m_guard" >&6; }
-if test "$use_m_guard" = yes ; then
-
-$as_echo "#define M_GUARD 1" >>confdefs.h
-
-fi
-
-# Implementation of the --enable-large-data-tests switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to run large data tests" >&5
-$as_echo_n "checking whether to run large data tests... " >&6; }
-# Check whether --enable-large-data-tests was given.
-if test "${enable_large_data_tests+set}" = set; then :
-  enableval=$enable_large_data_tests; large_data_tests=$enableval
-else
-  large_data_tests=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $large_data_tests" >&5
-$as_echo "$large_data_tests" >&6; }
-RUN_LARGE_DATA_TESTS=$large_data_tests
-
-
-
-# Implementation of the --with-capabilities switch.
-# Check whether we want to use Linux capabilities
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether use of capabilities is requested" >&5
-$as_echo_n "checking whether use of capabilities is requested... " >&6; }
-
-# Check whether --with-capabilities was given.
-if test "${with_capabilities+set}" = set; then :
-  withval=$with_capabilities; use_capabilities="$withval"
-else
-  use_capabilities=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_capabilities" >&5
-$as_echo "$use_capabilities" >&6; }
-
-# Implementation of the --enable-hmac-binary-check.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a HMAC binary check is requested" >&5
-$as_echo_n "checking whether a HMAC binary check is requested... " >&6; }
-# Check whether --enable-hmac-binary-check was given.
-if test "${enable_hmac_binary_check+set}" = set; then :
-  enableval=$enable_hmac_binary_check; use_hmac_binary_check=$enableval
-else
-  use_hmac_binary_check=no
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_hmac_binary_check" >&5
-$as_echo "$use_hmac_binary_check" >&6; }
-if test "$use_hmac_binary_check" = yes ; then
-
-$as_echo "#define ENABLE_HMAC_BINARY_CHECK 1" >>confdefs.h
-
-fi
-
-
-# Implementation of the --disable-jent-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether jitter entropy support is requested" >&5
-$as_echo_n "checking whether jitter entropy support is requested... " >&6; }
-# Check whether --enable-jent-support was given.
-if test "${enable_jent_support+set}" = set; then :
-  enableval=$enable_jent_support; jentsupport=$enableval
-else
-  jentsupport=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $jentsupport" >&5
-$as_echo "$jentsupport" >&6; }
-
-# Implementation of the --disable-padlock-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether padlock support is requested" >&5
-$as_echo_n "checking whether padlock support is requested... " >&6; }
-# Check whether --enable-padlock-support was given.
-if test "${enable_padlock_support+set}" = set; then :
-  enableval=$enable_padlock_support; padlocksupport=$enableval
-else
-  padlocksupport=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $padlocksupport" >&5
-$as_echo "$padlocksupport" >&6; }
-
-# Implementation of the --disable-aesni-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether AESNI support is requested" >&5
-$as_echo_n "checking whether AESNI support is requested... " >&6; }
-# Check whether --enable-aesni-support was given.
-if test "${enable_aesni_support+set}" = set; then :
-  enableval=$enable_aesni_support; aesnisupport=$enableval
-else
-  aesnisupport=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $aesnisupport" >&5
-$as_echo "$aesnisupport" >&6; }
-
-# Implementation of the --disable-pclmul-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether PCLMUL support is requested" >&5
-$as_echo_n "checking whether PCLMUL support is requested... " >&6; }
-# Check whether --enable-pclmul-support was given.
-if test "${enable_pclmul_support+set}" = set; then :
-  enableval=$enable_pclmul_support; pclmulsupport=$enableval
-else
-  pclmulsupport=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $pclmulsupport" >&5
-$as_echo "$pclmulsupport" >&6; }
-
-# Implementation of the --disable-sse41-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSE4.1 support is requested" >&5
-$as_echo_n "checking whether SSE4.1 support is requested... " >&6; }
-# Check whether --enable-sse41-support was given.
-if test "${enable_sse41_support+set}" = set; then :
-  enableval=$enable_sse41_support; sse41support=$enableval
-else
-  sse41support=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $sse41support" >&5
-$as_echo "$sse41support" >&6; }
-
-# Implementation of the --disable-drng-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether DRNG support is requested" >&5
-$as_echo_n "checking whether DRNG support is requested... " >&6; }
-# Check whether --enable-drng-support was given.
-if test "${enable_drng_support+set}" = set; then :
-  enableval=$enable_drng_support; drngsupport=$enableval
-else
-  drngsupport=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $drngsupport" >&5
-$as_echo "$drngsupport" >&6; }
-
-# Implementation of the --disable-avx-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether AVX support is requested" >&5
-$as_echo_n "checking whether AVX support is requested... " >&6; }
-# Check whether --enable-avx-support was given.
-if test "${enable_avx_support+set}" = set; then :
-  enableval=$enable_avx_support; avxsupport=$enableval
-else
-  avxsupport=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $avxsupport" >&5
-$as_echo "$avxsupport" >&6; }
-
-# Implementation of the --disable-avx2-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether AVX2 support is requested" >&5
-$as_echo_n "checking whether AVX2 support is requested... " >&6; }
-# Check whether --enable-avx2-support was given.
-if test "${enable_avx2_support+set}" = set; then :
-  enableval=$enable_avx2_support; avx2support=$enableval
-else
-  avx2support=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $avx2support" >&5
-$as_echo "$avx2support" >&6; }
-
-# Implementation of the --disable-neon-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NEON support is requested" >&5
-$as_echo_n "checking whether NEON support is requested... " >&6; }
-# Check whether --enable-neon-support was given.
-if test "${enable_neon_support+set}" = set; then :
-  enableval=$enable_neon_support; neonsupport=$enableval
-else
-  neonsupport=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $neonsupport" >&5
-$as_echo "$neonsupport" >&6; }
-
-# Implementation of the --disable-arm-crypto-support switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ARMv8 Crypto Extension support is requested" >&5
-$as_echo_n "checking whether ARMv8 Crypto Extension support is requested... " >&6; }
-# Check whether --enable-arm-crypto-support was given.
-if test "${enable_arm_crypto_support+set}" = set; then :
-  enableval=$enable_arm_crypto_support; armcryptosupport=$enableval
-else
-  armcryptosupport=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $armcryptosupport" >&5
-$as_echo "$armcryptosupport" >&6; }
-
-# Implementation of the --disable-O-flag-munging switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a -O flag munging is requested" >&5
-$as_echo_n "checking whether a -O flag munging is requested... " >&6; }
-# Check whether --enable-O-flag-munging was given.
-if test "${enable_O_flag_munging+set}" = set; then :
-  enableval=$enable_O_flag_munging; enable_o_flag_munging=$enableval
-else
-  enable_o_flag_munging=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_o_flag_munging" >&5
-$as_echo "$enable_o_flag_munging" >&6; }
- if test "$enable_o_flag_munging" = "yes"; then
-  ENABLE_O_FLAG_MUNGING_TRUE=
-  ENABLE_O_FLAG_MUNGING_FALSE='#'
-else
-  ENABLE_O_FLAG_MUNGING_TRUE='#'
-  ENABLE_O_FLAG_MUNGING_FALSE=
-fi
-
-
-# Implementation of the --disable-amd64-as-feature-detection switch.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable AMD64 as(1) feature detection" >&5
-$as_echo_n "checking whether to enable AMD64 as(1) feature detection... " >&6; }
-# Check whether --enable-amd64-as-feature-detection was given.
-if test "${enable_amd64_as_feature_detection+set}" = set; then :
-  enableval=$enable_amd64_as_feature_detection; amd64_as_feature_detection=$enableval
-else
-  amd64_as_feature_detection=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $amd64_as_feature_detection" >&5
-$as_echo "$amd64_as_feature_detection" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define PRINTABLE_OS_NAME "$PRINTABLE_OS_NAME"
-_ACEOF
-
-
-# For some systems we know that we have ld_version scripts.
-# Use it then as default.
-have_ld_version_script=no
-case "${host}" in
-    *-*-linux*)
-       have_ld_version_script=yes
-        ;;
-    *-*-gnu*)
-       have_ld_version_script=yes
-        ;;
-esac
-# Check whether --enable-ld-version-script was given.
-if test "${enable_ld_version_script+set}" = set; then :
-  enableval=$enable_ld_version_script; have_ld_version_script=$enableval
-else
-   :
-fi
-
- if test "$have_ld_version_script" = "yes"; then
-  HAVE_LD_VERSION_SCRIPT_TRUE=
-  HAVE_LD_VERSION_SCRIPT_FALSE='#'
-else
-  HAVE_LD_VERSION_SCRIPT_TRUE='#'
-  HAVE_LD_VERSION_SCRIPT_FALSE=
-fi
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define NAME_OF_DEV_RANDOM "$NAME_OF_DEV_RANDOM"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define NAME_OF_DEV_URANDOM "$NAME_OF_DEV_URANDOM"
-_ACEOF
-
-
-
-###############################
-#### Checks for libraries. ####
-###############################
-
-#
-# gpg-error is required.
-#
-
-  gpg_error_config_prefix=""
-
-# Check whether --with-libgpg-error-prefix was given.
-if test "${with_libgpg_error_prefix+set}" = set; then :
-  withval=$with_libgpg_error_prefix; gpg_error_config_prefix="$withval"
-fi
-
-
-
-# Check whether --with-gpg-error-prefix was given.
-if test "${with_gpg_error_prefix+set}" = set; then :
-  withval=$with_gpg_error_prefix; gpg_error_config_prefix="$withval"
-fi
-
-
-  if test x"${GPG_ERROR_CONFIG}" = x ; then
-     if test x"${gpg_error_config_prefix}" != x ; then
-        GPG_ERROR_CONFIG="${gpg_error_config_prefix}/bin/gpg-error-config"
-     else
-       case "${SYSROOT}" in
-         /*)
-           if test -x "${SYSROOT}/bin/gpg-error-config" ; then
-             GPG_ERROR_CONFIG="${SYSROOT}/bin/gpg-error-config"
-           fi
-           ;;
-         '')
-           ;;
-          *)
-           { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring \$SYSROOT as it is not an absolute path." >&5
-$as_echo "$as_me: WARNING: Ignoring \$SYSROOT as it is not an absolute path." >&2;}
-           ;;
-       esac
-     fi
-  fi
-
-  # Extract the first word of "gpg-error-config", so it can be a program name with args.
-set dummy gpg-error-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_GPG_ERROR_CONFIG+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $GPG_ERROR_CONFIG in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_GPG_ERROR_CONFIG="$GPG_ERROR_CONFIG" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_GPG_ERROR_CONFIG="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  test -z "$ac_cv_path_GPG_ERROR_CONFIG" && ac_cv_path_GPG_ERROR_CONFIG="no"
-  ;;
-esac
-fi
-GPG_ERROR_CONFIG=$ac_cv_path_GPG_ERROR_CONFIG
-if test -n "$GPG_ERROR_CONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GPG_ERROR_CONFIG" >&5
-$as_echo "$GPG_ERROR_CONFIG" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  min_gpg_error_version="$NEED_GPG_ERROR_VERSION"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GPG Error - version >= $min_gpg_error_version" >&5
-$as_echo_n "checking for GPG Error - version >= $min_gpg_error_version... " >&6; }
-  ok=no
-  if test "$GPG_ERROR_CONFIG" != "no" \
-     && test -f "$GPG_ERROR_CONFIG" ; then
-    req_major=`echo $min_gpg_error_version | \
-               sed 's/\([0-9]*\)\.\([0-9]*\)/\1/'`
-    req_minor=`echo $min_gpg_error_version | \
-               sed 's/\([0-9]*\)\.\([0-9]*\)/\2/'`
-    gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version`
-    major=`echo $gpg_error_config_version | \
-               sed 's/\([0-9]*\)\.\([0-9]*\).*/\1/'`
-    minor=`echo $gpg_error_config_version | \
-               sed 's/\([0-9]*\)\.\([0-9]*\).*/\2/'`
-    if test "$major" -gt "$req_major"; then
-        ok=yes
-    else
-        if test "$major" -eq "$req_major"; then
-            if test "$minor" -ge "$req_minor"; then
-               ok=yes
-            fi
-        fi
-    fi
-  fi
-  if test $ok = yes; then
-    GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags`
-    GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs`
-    GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --cflags 2>/dev/null`
-    GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --libs 2>/dev/null`
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($gpg_error_config_version)" >&5
-$as_echo "yes ($gpg_error_config_version)" >&6; }
-    :
-    gpg_error_config_host=`$GPG_ERROR_CONFIG $gpg_error_config_args --host 2>/dev/null || echo none`
-    if test x"$gpg_error_config_host" != xnone ; then
-      if test x"$gpg_error_config_host" != x"$host" ; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
-***
-*** The config script $GPG_ERROR_CONFIG was
-*** built for $gpg_error_config_host and thus may not match the
-*** used host $host.
-*** You may want to use the configure option --with-gpg-error-prefix
-*** to specify a matching config script or use \$SYSROOT.
-***" >&5
-$as_echo "$as_me: WARNING:
-***
-*** The config script $GPG_ERROR_CONFIG was
-*** built for $gpg_error_config_host and thus may not match the
-*** used host $host.
-*** You may want to use the configure option --with-gpg-error-prefix
-*** to specify a matching config script or use \$SYSROOT.
-***" >&2;}
-        gpg_config_script_warn="$gpg_config_script_warn libgpg-error"
-      fi
-    fi
-  else
-    GPG_ERROR_CFLAGS=""
-    GPG_ERROR_LIBS=""
-    GPG_ERROR_MT_CFLAGS=""
-    GPG_ERROR_MT_LIBS=""
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-    :
-  fi
-
-
-
-
-
-if test "x$GPG_ERROR_LIBS" = "x"; then
-  as_fn_error $? "libgpg-error is needed.
-                See ftp://ftp.gnupg.org/gcrypt/libgpg-error/ ." "$LINENO" 5
-fi
-
-
-$as_echo "#define GPG_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GCRYPT" >>confdefs.h
-
-
-#
-# Check whether the GNU Pth library is available.  We require this
-# to build the optional gcryptrnd program.
-#
-
-# Check whether --with-pth-prefix was given.
-if test "${with_pth_prefix+set}" = set; then :
-  withval=$with_pth_prefix; pth_config_prefix="$withval"
-else
-  pth_config_prefix=""
-fi
-
-if test x$pth_config_prefix != x ; then
-   PTH_CONFIG="$pth_config_prefix/bin/pth-config"
-fi
-if test "$use_random_daemon" = "yes"; then
-  # Extract the first word of "pth-config", so it can be a program name with args.
-set dummy pth-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_PTH_CONFIG+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $PTH_CONFIG in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_PTH_CONFIG="$PTH_CONFIG" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_PTH_CONFIG="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  test -z "$ac_cv_path_PTH_CONFIG" && ac_cv_path_PTH_CONFIG="no"
-  ;;
-esac
-fi
-PTH_CONFIG=$ac_cv_path_PTH_CONFIG
-if test -n "$PTH_CONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTH_CONFIG" >&5
-$as_echo "$PTH_CONFIG" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  if test "$PTH_CONFIG" = "no"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
-***
-*** To build the Libgcrypt's random number daemon
-*** we need the support of the GNU Portable Threads Library.
-*** Download it from ftp://ftp.gnu.org/gnu/pth/
-*** On a Debian GNU/Linux system you might want to try
-***   apt-get install libpth-dev
-***" >&5
-$as_echo "$as_me: WARNING:
-***
-*** To build the Libgcrypt's random number daemon
-*** we need the support of the GNU Portable Threads Library.
-*** Download it from ftp://ftp.gnu.org/gnu/pth/
-*** On a Debian GNU/Linux system you might want to try
-***   apt-get install libpth-dev
-***" >&2;}
-  else
-
-    _pth_version=`$PTH_CONFIG --version | awk 'NR==1 {print $3}'`
-    _req_version="1.3.7"
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTH - version >= $_req_version" >&5
-$as_echo_n "checking for PTH - version >= $_req_version... " >&6; }
-    for _var in _pth_version _req_version; do
-        eval "_val=\"\$${_var}\""
-        _major=`echo $_val | sed 's/\([0-9]*\)\.\([0-9]*\)\([ab.]\)\([0-9]*\)/\1/'`
-        _minor=`echo $_val | sed 's/\([0-9]*\)\.\([0-9]*\)\([ab.]\)\([0-9]*\)/\2/'`
-        _rtype=`echo $_val | sed 's/\([0-9]*\)\.\([0-9]*\)\([ab.]\)\([0-9]*\)/\3/'`
-        _micro=`echo $_val | sed 's/\([0-9]*\)\.\([0-9]*\)\([ab.]\)\([0-9]*\)/\4/'`
-        case $_rtype in
-            "a" ) _rtype=0 ;;
-            "b" ) _rtype=1 ;;
-            "." ) _rtype=2 ;;
-        esac
-        _hex=`echo dummy | awk '{ printf("%d%02d%1d%02d", major, minor, rtype, micro); }' \
-              "major=$_major" "minor=$_minor" "rtype=$_rtype" "micro=$_micro"`
-        eval "${_var}_hex=\"\$_hex\""
-    done
-    have_pth=no
-    if test ".$_pth_version_hex" != .; then
-        if test ".$_req_version_hex" != .; then
-            if test $_pth_version_hex -ge $_req_version_hex; then
-                have_pth=yes
-            fi
-        fi
-    fi
-    if test $have_pth = yes; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether PTH installation is sane" >&5
-$as_echo_n "checking whether PTH installation is sane... " >&6; }
-       if ${gnupg_cv_pth_is_sane+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-         _gnupg_pth_save_cflags=$CFLAGS
-         _gnupg_pth_save_ldflags=$LDFLAGS
-         _gnupg_pth_save_libs=$LIBS
-         CFLAGS="$CFLAGS `$PTH_CONFIG --cflags`"
-         LDFLAGS="$LDFLAGS `$PTH_CONFIG --ldflags`"
-         LIBS="$LIBS `$PTH_CONFIG --libs`"
-         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <pth.h>
-
-int
-main ()
-{
- pth_init ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  gnupg_cv_pth_is_sane=yes
-else
-  gnupg_cv_pth_is_sane=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-         CFLAGS=$_gnupg_pth_save_cflags
-         LDFLAGS=$_gnupg_pth_save_ldflags
-         LIBS=$_gnupg_pth_save_libs
-
-fi
-
-       if test $gnupg_cv_pth_is_sane != yes; then
-          have_pth=no
-       fi
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gnupg_cv_pth_is_sane" >&5
-$as_echo "$gnupg_cv_pth_is_sane" >&6; }
-    else
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-    fi
-
-    if test $have_pth = yes; then
-       PTH_CFLAGS=`$PTH_CONFIG --cflags`
-       PTH_LIBS=`$PTH_CONFIG --ldflags`
-       PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs --all`"
-
-$as_echo "#define USE_GNU_PTH 1" >>confdefs.h
-
-
-$as_echo "#define HAVE_PTH 1" >>confdefs.h
-
-    fi
-  fi
-fi
-
-
-
-#
-# Check whether pthreads is available
-#
-if test "$have_w32_system" != yes; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
-$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
-if ${ac_cv_lib_pthread_pthread_create+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpthread  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pthread_create ();
-int
-main ()
-{
-return pthread_create ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_pthread_pthread_create=yes
-else
-  ac_cv_lib_pthread_pthread_create=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
-$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
-if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
-  have_pthread=yes
-fi
-
-  if test "$have_pthread" = yes; then
-
-$as_echo "#define HAVE_PTHREAD 1 " >>confdefs.h
-
-  fi
-fi
-
-
-# Solaris needs -lsocket and -lnsl. Unisys system includes
-# gethostbyname in libsocket but needs libnsl for socket.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setsockopt" >&5
-$as_echo_n "checking for library containing setsockopt... " >&6; }
-if ${ac_cv_search_setsockopt+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char setsockopt ();
-int
-main ()
-{
-return setsockopt ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' socket; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_setsockopt=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_setsockopt+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_setsockopt+:} false; then :
-
-else
-  ac_cv_search_setsockopt=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setsockopt" >&5
-$as_echo "$ac_cv_search_setsockopt" >&6; }
-ac_res=$ac_cv_search_setsockopt
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setsockopt" >&5
-$as_echo_n "checking for library containing setsockopt... " >&6; }
-if ${ac_cv_search_setsockopt+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char setsockopt ();
-int
-main ()
-{
-return setsockopt ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' socket; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib -lnsl $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_setsockopt=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_setsockopt+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_setsockopt+:} false; then :
-
-else
-  ac_cv_search_setsockopt=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setsockopt" >&5
-$as_echo "$ac_cv_search_setsockopt" >&6; }
-ac_res=$ac_cv_search_setsockopt
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setsockopt" >&5
-$as_echo_n "checking for library containing setsockopt... " >&6; }
-if ${ac_cv_search_setsockopt+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char setsockopt ();
-int
-main ()
-{
-return setsockopt ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' nsl; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_setsockopt=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_setsockopt+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_setsockopt+:} false; then :
-
-else
-  ac_cv_search_setsockopt=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setsockopt" >&5
-$as_echo "$ac_cv_search_setsockopt" >&6; }
-ac_res=$ac_cv_search_setsockopt
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-
-##################################
-#### Checks for header files. ####
-##################################
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_header_stdc=yes
-else
-  ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
-  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "free" >/dev/null 2>&1; then :
-
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-  if test "$cross_compiling" = yes; then :
-  :
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
-                  (('a' <= (c) && (c) <= 'i') \
-                    || ('j' <= (c) && (c) <= 'r') \
-                    || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
-  int i;
-  for (i = 0; i < 256; i++)
-    if (XOR (islower (i), ISLOWER (i))
-       || toupper (i) != TOUPPER (i))
-      return 2;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
-  ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
-for ac_header in unistd.h sys/select.h sys/msg.h
-do :
-  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-INSERT_SYS_SELECT_H=
-if test x"$ac_cv_header_sys_select_h" = xyes; then
-  INSERT_SYS_SELECT_H=" include <sys/select.h>"
-fi
-
-
-
-##########################################
-#### Checks for typedefs, structures, ####
-####  and compiler characteristics.   ####
-##########################################
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
-$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
-if ${ac_cv_c_const+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-#ifndef __cplusplus
-  /* Ultrix mips cc rejects this sort of thing.  */
-  typedef int charset[2];
-  const charset cs = { 0, 0 };
-  /* SunOS 4.1.1 cc rejects this.  */
-  char const *const *pcpcc;
-  char **ppc;
-  /* NEC SVR4.0.2 mips cc rejects this.  */
-  struct point {int x, y;};
-  static struct point const zero = {0,0};
-  /* AIX XL C 1.02.0.0 rejects this.
-     It does not let you subtract one const X* pointer from another in
-     an arm of an if-expression whose if-part is not a constant
-     expression */
-  const char *g = "string";
-  pcpcc = &g + (g ? g-g : 0);
-  /* HPUX 7.0 cc rejects these. */
-  ++pcpcc;
-  ppc = (char**) pcpcc;
-  pcpcc = (char const *const *) ppc;
-  { /* SCO 3.2v4 cc rejects this sort of thing.  */
-    char tx;
-    char *t = &tx;
-    char const *s = 0 ? (char *) 0 : (char const *) 0;
-
-    *t++ = 0;
-    if (s) return 0;
-  }
-  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
-    int x[] = {25, 17};
-    const int *foo = &x[0];
-    ++foo;
-  }
-  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
-    typedef const int *iptr;
-    iptr p = 0;
-    ++p;
-  }
-  { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
-       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
-    struct s { int j; const int *ap[3]; } bx;
-    struct s *b = &bx; b->j = 5;
-  }
-  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
-    const int foo = 10;
-    if (!foo) return 0;
-  }
-  return !cs[0] && !zero.x;
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_c_const=yes
-else
-  ac_cv_c_const=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
-$as_echo "$ac_cv_c_const" >&6; }
-if test $ac_cv_c_const = no; then
-
-$as_echo "#define const /**/" >>confdefs.h
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
-$as_echo_n "checking for inline... " >&6; }
-if ${ac_cv_c_inline+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_cv_c_inline=no
-for ac_kw in inline __inline__ __inline; do
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#ifndef __cplusplus
-typedef int foo_t;
-static $ac_kw foo_t static_foo () {return 0; }
-$ac_kw foo_t foo () {return 0; }
-#endif
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_c_inline=$ac_kw
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  test "$ac_cv_c_inline" != no && break
-done
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
-$as_echo "$ac_cv_c_inline" >&6; }
-
-case $ac_cv_c_inline in
-  inline | yes) ;;
-  *)
-    case $ac_cv_c_inline in
-      no) ac_val=;;
-      *) ac_val=$ac_cv_c_inline;;
-    esac
-    cat >>confdefs.h <<_ACEOF
-#ifndef __cplusplus
-#define inline $ac_val
-#endif
-_ACEOF
-    ;;
-esac
-
-ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
-if test "x$ac_cv_type_size_t" = xyes; then :
-
-else
-
-cat >>confdefs.h <<_ACEOF
-#define size_t unsigned int
-_ACEOF
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5
-$as_echo_n "checking return type of signal handlers... " >&6; }
-if ${ac_cv_type_signal+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <sys/types.h>
-#include <signal.h>
-
-int
-main ()
-{
-return *(signal (0, 0)) (0) == 1;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_type_signal=int
-else
-  ac_cv_type_signal=void
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5
-$as_echo "$ac_cv_type_signal" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define RETSIGTYPE $ac_cv_type_signal
-_ACEOF
-
-
-ac_fn_c_check_decl "$LINENO" "sys_siglist" "ac_cv_have_decl_sys_siglist" "#include <signal.h>
-/* NetBSD declares sys_siglist in unistd.h.  */
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-"
-if test "x$ac_cv_have_decl_sys_siglist" = xyes; then :
-  ac_have_decl=1
-else
-  ac_have_decl=0
-fi
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_DECL_SYS_SIGLIST $ac_have_decl
-_ACEOF
-
-
-ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
-if test "x$ac_cv_type_pid_t" = xyes; then :
-
-else
-
-cat >>confdefs.h <<_ACEOF
-#define pid_t int
-_ACEOF
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for byte typedef" >&5
-$as_echo_n "checking for byte typedef... " >&6; }
-    if ${gnupg_cv_typedef_byte+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-    #include <stdlib.h>
-    #include <sys/types.h>
-int
-main ()
-{
-
-    #undef byte
-    int a = sizeof(byte);
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gnupg_cv_typedef_byte=yes
-else
-  gnupg_cv_typedef_byte=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gnupg_cv_typedef_byte" >&5
-$as_echo "$gnupg_cv_typedef_byte" >&6; }
-    if test "$gnupg_cv_typedef_byte" = yes; then
-
-$as_echo "#define HAVE_BYTE_TYPEDEF 1" >>confdefs.h
-
-    fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ushort typedef" >&5
-$as_echo_n "checking for ushort typedef... " >&6; }
-    if ${gnupg_cv_typedef_ushort+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-    #include <stdlib.h>
-    #include <sys/types.h>
-int
-main ()
-{
-
-    #undef ushort
-    int a = sizeof(ushort);
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gnupg_cv_typedef_ushort=yes
-else
-  gnupg_cv_typedef_ushort=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gnupg_cv_typedef_ushort" >&5
-$as_echo "$gnupg_cv_typedef_ushort" >&6; }
-    if test "$gnupg_cv_typedef_ushort" = yes; then
-
-$as_echo "#define HAVE_USHORT_TYPEDEF 1" >>confdefs.h
-
-    fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ulong typedef" >&5
-$as_echo_n "checking for ulong typedef... " >&6; }
-    if ${gnupg_cv_typedef_ulong+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-    #include <stdlib.h>
-    #include <sys/types.h>
-int
-main ()
-{
-
-    #undef ulong
-    int a = sizeof(ulong);
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gnupg_cv_typedef_ulong=yes
-else
-  gnupg_cv_typedef_ulong=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gnupg_cv_typedef_ulong" >&5
-$as_echo "$gnupg_cv_typedef_ulong" >&6; }
-    if test "$gnupg_cv_typedef_ulong" = yes; then
-
-$as_echo "#define HAVE_ULONG_TYPEDEF 1" >>confdefs.h
-
-    fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for u16 typedef" >&5
-$as_echo_n "checking for u16 typedef... " >&6; }
-    if ${gnupg_cv_typedef_u16+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-    #include <stdlib.h>
-    #include <sys/types.h>
-int
-main ()
-{
-
-    #undef u16
-    int a = sizeof(u16);
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gnupg_cv_typedef_u16=yes
-else
-  gnupg_cv_typedef_u16=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gnupg_cv_typedef_u16" >&5
-$as_echo "$gnupg_cv_typedef_u16" >&6; }
-    if test "$gnupg_cv_typedef_u16" = yes; then
-
-$as_echo "#define HAVE_U16_TYPEDEF 1" >>confdefs.h
-
-    fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for u32 typedef" >&5
-$as_echo_n "checking for u32 typedef... " >&6; }
-    if ${gnupg_cv_typedef_u32+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#define _GNU_SOURCE 1
-    #include <stdlib.h>
-    #include <sys/types.h>
-int
-main ()
-{
-
-    #undef u32
-    int a = sizeof(u32);
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gnupg_cv_typedef_u32=yes
-else
-  gnupg_cv_typedef_u32=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gnupg_cv_typedef_u32" >&5
-$as_echo "$gnupg_cv_typedef_u32" >&6; }
-    if test "$gnupg_cv_typedef_u32" = yes; then
-
-$as_echo "#define HAVE_U32_TYPEDEF 1" >>confdefs.h
-
-    fi
-
-
-
-      for ac_header in sys/socket.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_socket_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_SOCKET_H 1
-_ACEOF
-
-fi
-
-done
-
-
-
-
-  :
-
-
-
-
-
-  if test $ac_cv_header_sys_socket_h = yes; then
-    SYS_SOCKET_H=''
-  else
-                    for ac_header in winsock2.h ws2tcpip.h
-do :
-  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-    SYS_SOCKET_H='sys/socket.h'
-  fi
-
-
-   ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include <sys/types.h>
-      #if HAVE_SYS_SOCKET_H
-      # include <sys/socket.h>
-      #elif HAVE_WS2TCPIP_H
-      # include <ws2tcpip.h>
-      #endif
-"
-if test "x$ac_cv_type_socklen_t" = xyes; then :
-
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t equivalent" >&5
-$as_echo_n "checking for socklen_t equivalent... " >&6; }
-      if ${gl_cv_gl_cv_socklen_t_equiv+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  # Systems have either "struct sockaddr *" or
-        # "void *" as the second argument to getpeername
-        gl_cv_socklen_t_equiv=
-        for arg2 in "struct sockaddr" void; do
-          for t in int size_t "unsigned int" "long int" "unsigned long int"; do
-            cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <sys/types.h>
-               #include <sys/socket.h>
-
-               int getpeername (int, $arg2 *, $t *);
-int
-main ()
-{
-$t len;
-               getpeername (0, 0, &len);
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gl_cv_socklen_t_equiv="$t"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-            test "$gl_cv_socklen_t_equiv" != "" && break
-          done
-          test "$gl_cv_socklen_t_equiv" != "" && break
-        done
-
-fi
-
-      if test "$gl_cv_socklen_t_equiv" = ""; then
-       as_fn_error $? "Cannot find a type to use in place of socklen_t" "$LINENO" 5
-      fi
-      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_socklen_t_equiv" >&5
-$as_echo "$gl_cv_socklen_t_equiv" >&6; }
-
-cat >>confdefs.h <<_ACEOF
-#define socklen_t $gl_cv_socklen_t_equiv
-_ACEOF
-
-fi
-
-case "${host}" in
-  *-*-mingw32*)
-    # socklen_t may or may not be defined depending on what headers
-    # are included.  To be safe we use int as this is the actual type.
-    FALLBACK_SOCKLEN_T="typedef int gcry_socklen_t;"
-    ;;
-  *)
-    if test ".$gl_cv_socklen_t_equiv" = "."; then
-      FALLBACK_SOCKLEN_T="typedef socklen_t gcry_socklen_t;"
-    else
-      FALLBACK_SOCKLEN_T="typedef ${gl_cv_socklen_t_equiv} gcry_socklen_t;"
-    fi
-esac
-
-
-
-#
-# Check for __builtin_bswap32 intrinsic.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_bswap32" >&5
-$as_echo_n "checking for __builtin_bswap32... " >&6; }
-if ${gcry_cv_have_builtin_bswap32+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_have_builtin_bswap32=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-int x = 0; int y = __builtin_bswap32(x); return y;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  gcry_cv_have_builtin_bswap32=yes
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_have_builtin_bswap32" >&5
-$as_echo "$gcry_cv_have_builtin_bswap32" >&6; }
-if test "$gcry_cv_have_builtin_bswap32" = "yes" ; then
-
-$as_echo "#define HAVE_BUILTIN_BSWAP32 1" >>confdefs.h
-
-fi
-
-
-#
-# Check for __builtin_bswap64 intrinsic.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_bswap64" >&5
-$as_echo_n "checking for __builtin_bswap64... " >&6; }
-if ${gcry_cv_have_builtin_bswap64+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_have_builtin_bswap64=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-long long x = 0; long long y = __builtin_bswap64(x); return y;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  gcry_cv_have_builtin_bswap64=yes
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_have_builtin_bswap64" >&5
-$as_echo "$gcry_cv_have_builtin_bswap64" >&6; }
-if test "$gcry_cv_have_builtin_bswap64" = "yes" ; then
-
-$as_echo "#define HAVE_BUILTIN_BSWAP64 1" >>confdefs.h
-
-fi
-
-
-#
-# Check for __builtin_ctz intrinsic.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_ctz" >&5
-$as_echo_n "checking for __builtin_ctz... " >&6; }
-if ${gcry_cv_have_builtin_ctz+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_have_builtin_ctz=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-unsigned int x = 0; int y = __builtin_ctz(x); return y;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  gcry_cv_have_builtin_ctz=yes
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_have_builtin_ctz" >&5
-$as_echo "$gcry_cv_have_builtin_ctz" >&6; }
-if test "$gcry_cv_have_builtin_ctz" = "yes" ; then
-
-$as_echo "#define HAVE_BUILTIN_CTZ 1" >>confdefs.h
-
-fi
-
-
-#
-# Check for VLA support (variable length arrays).
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the variable length arrays are supported" >&5
-$as_echo_n "checking whether the variable length arrays are supported... " >&6; }
-if ${gcry_cv_have_vla+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_have_vla=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void f1(char *, int);
-            char foo(int i) {
-              char b[(i < 0 ? 0 : i) + 1];
-              f1(b, sizeof b); return b[0];}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_have_vla=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_have_vla" >&5
-$as_echo "$gcry_cv_have_vla" >&6; }
-if test "$gcry_cv_have_vla" = "yes" ; then
-
-$as_echo "#define HAVE_VLA 1" >>confdefs.h
-
-fi
-
-
-#
-# Check for ELF visibility support.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the visibility attribute is supported" >&5
-$as_echo_n "checking whether the visibility attribute is supported... " >&6; }
-if ${gcry_cv_visibility_attribute+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_visibility_attribute=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-int foo __attribute__ ((visibility ("hidden"))) = 1;
-            int bar __attribute__ ((visibility ("protected"))) = 1;
-
-_ACEOF
-
-        if ${CC-cc} -Werror -S conftest.c -o conftest.s \
-                  1>&5 2>&5 ; then
-            if grep '\.hidden.*foo' conftest.s >/dev/null 2>&1 ; then
-                if grep '\.protected.*bar' conftest.s >/dev/null 2>&1; then
-                    gcry_cv_visibility_attribute=yes
-                fi
-            fi
-        fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_visibility_attribute" >&5
-$as_echo "$gcry_cv_visibility_attribute" >&6; }
-if test "$gcry_cv_visibility_attribute" = "yes"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken visibility attribute" >&5
-$as_echo_n "checking for broken visibility attribute... " >&6; }
-if ${gcry_cv_broken_visibility_attribute+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_broken_visibility_attribute=yes
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-int foo (int x);
-            int bar (int x) __asm__ ("foo")
-                            __attribute__ ((visibility ("hidden")));
-            int bar (int x) { return x; }
-
-_ACEOF
-
-        if ${CC-cc} -Werror -S conftest.c -o conftest.s \
-                  1>&5 2>&5 ; then
-           if grep '\.hidden[  _]foo' conftest.s >/dev/null 2>&1;
-            then
-               gcry_cv_broken_visibility_attribute=no
-           fi
-        fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_broken_visibility_attribute" >&5
-$as_echo "$gcry_cv_broken_visibility_attribute" >&6; }
-fi
-if test "$gcry_cv_visibility_attribute" = "yes"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken alias attribute" >&5
-$as_echo_n "checking for broken alias attribute... " >&6; }
-if ${gcry_cv_broken_alias_attribute+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_broken_alias_attribute=yes
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-extern int foo (int x) __asm ("xyzzy");
-            int bar (int x) { return x; }
-            extern __typeof (bar) foo __attribute ((weak, alias ("bar")));
-            extern int dfoo;
-            extern __typeof (dfoo) dfoo __asm ("abccb");
-            int dfoo = 1;
-
-_ACEOF
-
-        if ${CC-cc} -Werror -S conftest.c -o conftest.s \
-                  1>&5 2>&5 ; then
-           if grep 'xyzzy' conftest.s >/dev/null 2>&1 && \
-              grep 'abccb' conftest.s >/dev/null 2>&1; then
-              gcry_cv_broken_alias_attribute=no
-           fi
-        fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_broken_alias_attribute" >&5
-$as_echo "$gcry_cv_broken_alias_attribute" >&6; }
-fi
-if test "$gcry_cv_visibility_attribute" = "yes"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if gcc supports -fvisibility=hidden" >&5
-$as_echo_n "checking if gcc supports -fvisibility=hidden... " >&6; }
-if ${gcry_cv_gcc_has_f_visibility+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_has_f_visibility=no
-        _gcc_cflags_save=$CFLAGS
-        CFLAGS="-fvisibility=hidden"
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_has_f_visibility=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        CFLAGS=$_gcc_cflags_save;
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_has_f_visibility" >&5
-$as_echo "$gcry_cv_gcc_has_f_visibility" >&6; }
-fi
-if test "$gcry_cv_visibility_attribute" = "yes" \
-   && test "$gcry_cv_broken_visibility_attribute" != "yes" \
-   && test "$gcry_cv_broken_alias_attribute" != "yes" \
-   && test "$gcry_cv_gcc_has_f_visibility" = "yes"
- then
-
-$as_echo "#define GCRY_USE_VISIBILITY 1" >>confdefs.h
-
-   CFLAGS="$CFLAGS -fvisibility=hidden"
-fi
-
-
-# Following attribute tests depend on warnings to cause compile to fail,
-# so set -Werror temporarily.
-_gcc_cflags_save=$CFLAGS
-CFLAGS="$CFLAGS -Werror"
-
-
-#
-# Check whether the compiler supports the GCC style aligned attribute
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the GCC style aligned attribute is supported" >&5
-$as_echo_n "checking whether the GCC style aligned attribute is supported... " >&6; }
-if ${gcry_cv_gcc_attribute_aligned+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_attribute_aligned=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-struct { int a; } foo __attribute__ ((aligned (16)));
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_attribute_aligned=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_attribute_aligned" >&5
-$as_echo "$gcry_cv_gcc_attribute_aligned" >&6; }
-if test "$gcry_cv_gcc_attribute_aligned" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_ATTRIBUTE_ALIGNED 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether the compiler supports the GCC style packed attribute
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the GCC style packed attribute is supported" >&5
-$as_echo_n "checking whether the GCC style packed attribute is supported... " >&6; }
-if ${gcry_cv_gcc_attribute_packed+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_attribute_packed=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-struct foolong_s { long b; } __attribute__ ((packed));
-            struct foo_s { char a; struct foolong_s b; }
-              __attribute__ ((packed));
-            enum bar {
-              FOO = 1 / (sizeof(struct foo_s) == (sizeof(char) + sizeof(long))),
-            };
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_attribute_packed=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_attribute_packed" >&5
-$as_echo "$gcry_cv_gcc_attribute_packed" >&6; }
-if test "$gcry_cv_gcc_attribute_packed" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_ATTRIBUTE_PACKED 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether the compiler supports the GCC style may_alias attribute
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the GCC style may_alias attribute is supported" >&5
-$as_echo_n "checking whether the GCC style may_alias attribute is supported... " >&6; }
-if ${gcry_cv_gcc_attribute_may_alias+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_attribute_may_alias=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-typedef struct foo_s { int a; }
-            __attribute__ ((may_alias)) foo_t;
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_attribute_may_alias=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_attribute_may_alias" >&5
-$as_echo "$gcry_cv_gcc_attribute_may_alias" >&6; }
-if test "$gcry_cv_gcc_attribute_may_alias" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_ATTRIBUTE_MAY_ALIAS 1" >>confdefs.h
-
-fi
-
-
-# Restore flags.
-CFLAGS=$_gcc_cflags_save;
-
-
-#
-# Check whether the compiler supports 'asm' or '__asm__' keyword for
-# assembler blocks.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether 'asm' assembler keyword is supported" >&5
-$as_echo_n "checking whether 'asm' assembler keyword is supported... " >&6; }
-if ${gcry_cv_have_asm+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_have_asm=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void a(void) { asm("":::"memory"); }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_have_asm=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_have_asm" >&5
-$as_echo "$gcry_cv_have_asm" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether '__asm__' assembler keyword is supported" >&5
-$as_echo_n "checking whether '__asm__' assembler keyword is supported... " >&6; }
-if ${gcry_cv_have___asm__+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_have___asm__=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void a(void) { __asm__("":::"memory"); }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_have___asm__=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_have___asm__" >&5
-$as_echo "$gcry_cv_have___asm__" >&6; }
-if test "$gcry_cv_have_asm" = "no" ; then
-   if test "$gcry_cv_have___asm__" = "yes" ; then
-
-$as_echo "#define asm __asm__" >>confdefs.h
-
-   fi
-fi
-
-
-#
-# Check whether the compiler supports inline assembly memory barrier.
-#
-if test "$gcry_cv_have_asm" = "no" ; then
-   if test "$gcry_cv_have___asm__" = "yes" ; then
-      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether inline assembly memory barrier is supported" >&5
-$as_echo_n "checking whether inline assembly memory barrier is supported... " >&6; }
-if ${gcry_cv_have_asm_volatile_memory+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_have_asm_volatile_memory=no
-           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void a(void) { __asm__ volatile("":::"memory"); }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_have_asm_volatile_memory=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_have_asm_volatile_memory" >&5
-$as_echo "$gcry_cv_have_asm_volatile_memory" >&6; }
-   fi
-else
-   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether inline assembly memory barrier is supported" >&5
-$as_echo_n "checking whether inline assembly memory barrier is supported... " >&6; }
-if ${gcry_cv_have_asm_volatile_memory+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_have_asm_volatile_memory=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void a(void) { asm volatile("":::"memory"); }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_have_asm_volatile_memory=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_have_asm_volatile_memory" >&5
-$as_echo "$gcry_cv_have_asm_volatile_memory" >&6; }
-fi
-if test "$gcry_cv_have_asm_volatile_memory" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_ASM_VOLATILE_MEMORY 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC assembler supports features needed for our ARM
-# implementations.  This needs to be done before setting up the
-# assembler stuff.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC assembler is compatible for ARM assembly implementations" >&5
-$as_echo_n "checking whether GCC assembler is compatible for ARM assembly implementations... " >&6; }
-if ${gcry_cv_gcc_arm_platform_as_ok+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_arm_platform_as_ok=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-                /* Test if assembler supports UAL syntax.  */
-                ".syntax unified\n\t"
-                ".arm\n\t" /* our assembly code is in ARM mode  */
-                /* Following causes error if assembler ignored '.syntax unified'.  */
-                "asmfunc:\n\t"
-                "add %r0, %r0, %r4, ror #12;\n\t"
-
-                /* Test if '.type' and '.size' are supported.  */
-                ".size asmfunc,.-asmfunc;\n\t"
-                ".type asmfunc,%function;\n\t"
-            );
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_arm_platform_as_ok=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_arm_platform_as_ok" >&5
-$as_echo "$gcry_cv_gcc_arm_platform_as_ok" >&6; }
-if test "$gcry_cv_gcc_arm_platform_as_ok" = "yes" ; then
-
-$as_echo "#define HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC assembler supports features needed for our ARMv8/Aarch64
-# implementations.  This needs to be done before setting up the
-# assembler stuff.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC assembler is compatible for ARMv8/Aarch64 assembly implementations" >&5
-$as_echo_n "checking whether GCC assembler is compatible for ARMv8/Aarch64 assembly implementations... " >&6; }
-if ${gcry_cv_gcc_aarch64_platform_as_ok+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_aarch64_platform_as_ok=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-                "asmfunc:\n\t"
-                "eor x0, x0, x30, ror #12;\n\t"
-                "add x0, x0, x30, asr #12;\n\t"
-                "eor v0.16b, v0.16b, v31.16b;\n\t"
-
-                /* Test if '.type' and '.size' are supported.  */
-                ".size asmfunc,.-asmfunc;\n\t"
-                ".type asmfunc,@function;\n\t"
-            );
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_aarch64_platform_as_ok=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_aarch64_platform_as_ok" >&5
-$as_echo "$gcry_cv_gcc_aarch64_platform_as_ok" >&6; }
-if test "$gcry_cv_gcc_aarch64_platform_as_ok" = "yes" ; then
-
-$as_echo "#define HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether underscores in symbols are required.  This needs to be
-# done before setting up the assembler stuff.
-#
-
-tmp_do_check="no"
-case "${host}" in
-    i?86-mingw32* | i?86-*-mingw32*)
-        ac_cv_sys_symbol_underscore=yes
-        ;;
-    x86_64-*-mingw32*)
-        ac_cv_sys_symbol_underscore=no
-        ;;
-    i386-emx-os2 | i345686-pc-os2*emx | i386-pc-msdosdjgpp)
-        ac_cv_sys_symbol_underscore=yes
-        ;;
-    *)
-      if test "$cross_compiling" = yes; then
-        if test "x$ac_cv_sys_symbol_underscore" = x ; then
-           ac_cv_sys_symbol_underscore=yes
-        fi
-      else
-         tmp_do_check="yes"
-      fi
-       ;;
-esac
-if test "$tmp_do_check" = "yes"; then
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _ prefix in compiled symbols" >&5
-$as_echo_n "checking for _ prefix in compiled symbols... " >&6; }
-  if ${ac_cv_sys_symbol_underscore+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_cv_sys_symbol_underscore=no
-   cat > conftest.$ac_ext <<EOF
-      void nm_test_func(){}
-      int main(){nm_test_func;return 0;}
-EOF
-  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-    # Now try to grab the symbols.
-    ac_nlist=conftest.nm
-    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \| cut -d \' \' -f 2 \> $ac_nlist\""; } >&5
-  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \| cut -d \' \' -f 2 \> $ac_nlist) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; } && test -s "$ac_nlist"; then
-      # See whether the symbols have a leading underscore.
-      if egrep '^_nm_test_func' "$ac_nlist" >/dev/null; then
-        ac_cv_sys_symbol_underscore=yes
-      else
-        if egrep '^nm_test_func ' "$ac_nlist" >/dev/null; then
-          :
-        else
-          echo "configure: cannot find nm_test_func in $ac_nlist" >&5
-        fi
-      fi
-    else
-      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5
-    fi
-  else
-    echo "configure: failed program was:" >&5
-    cat conftest.c >&5
-  fi
-  rm -rf conftest*
-
-fi
-
-  else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _ prefix in compiled symbols" >&5
-$as_echo_n "checking for _ prefix in compiled symbols... " >&6; }
-  fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_symbol_underscore" >&5
-$as_echo "$ac_cv_sys_symbol_underscore" >&6; }
-if test x$ac_cv_sys_symbol_underscore = xyes; then
-
-$as_echo "#define WITH_SYMBOL_UNDERSCORE 1" >>confdefs.h
-
-fi
-
-
-
-#################################
-####                         ####
-#### Setup assembler stuff.  ####
-#### Define mpi_cpu_arch.    ####
-####                         ####
-#################################
-# Check whether --enable-mpi-path was given.
-if test "${enable_mpi_path+set}" = set; then :
-  enableval=$enable_mpi_path; mpi_extra_path="$enableval"
-else
-  mpi_extra_path=""
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking architecture and mpi assembler functions" >&5
-$as_echo_n "checking architecture and mpi assembler functions... " >&6; }
-if test -f $srcdir/mpi/config.links ; then
-    . $srcdir/mpi/config.links
-    ac_config_links="$ac_config_links "$mpi_ln_list""
-
-    ac_cv_mpi_sflags="$mpi_sflags"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mpi_cpu_arch" >&5
-$as_echo "$mpi_cpu_arch" >&6; }
-else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
-$as_echo "failed" >&6; }
-    as_fn_error $? "mpi/config.links missing!" "$LINENO" 5
-fi
-MPI_SFLAGS="$ac_cv_mpi_sflags"
-
-
- if test "$mpi_mod_asm_mpih_add1" = yes; then
-  MPI_MOD_ASM_MPIH_ADD1_TRUE=
-  MPI_MOD_ASM_MPIH_ADD1_FALSE='#'
-else
-  MPI_MOD_ASM_MPIH_ADD1_TRUE='#'
-  MPI_MOD_ASM_MPIH_ADD1_FALSE=
-fi
-
- if test "$mpi_mod_asm_mpih_sub1" = yes; then
-  MPI_MOD_ASM_MPIH_SUB1_TRUE=
-  MPI_MOD_ASM_MPIH_SUB1_FALSE='#'
-else
-  MPI_MOD_ASM_MPIH_SUB1_TRUE='#'
-  MPI_MOD_ASM_MPIH_SUB1_FALSE=
-fi
-
- if test "$mpi_mod_asm_mpih_mul1" = yes; then
-  MPI_MOD_ASM_MPIH_MUL1_TRUE=
-  MPI_MOD_ASM_MPIH_MUL1_FALSE='#'
-else
-  MPI_MOD_ASM_MPIH_MUL1_TRUE='#'
-  MPI_MOD_ASM_MPIH_MUL1_FALSE=
-fi
-
- if test "$mpi_mod_asm_mpih_mul2" = yes; then
-  MPI_MOD_ASM_MPIH_MUL2_TRUE=
-  MPI_MOD_ASM_MPIH_MUL2_FALSE='#'
-else
-  MPI_MOD_ASM_MPIH_MUL2_TRUE='#'
-  MPI_MOD_ASM_MPIH_MUL2_FALSE=
-fi
-
- if test "$mpi_mod_asm_mpih_mul3" = yes; then
-  MPI_MOD_ASM_MPIH_MUL3_TRUE=
-  MPI_MOD_ASM_MPIH_MUL3_FALSE='#'
-else
-  MPI_MOD_ASM_MPIH_MUL3_TRUE='#'
-  MPI_MOD_ASM_MPIH_MUL3_FALSE=
-fi
-
- if test "$mpi_mod_asm_mpih_lshift" = yes; then
-  MPI_MOD_ASM_MPIH_LSHIFT_TRUE=
-  MPI_MOD_ASM_MPIH_LSHIFT_FALSE='#'
-else
-  MPI_MOD_ASM_MPIH_LSHIFT_TRUE='#'
-  MPI_MOD_ASM_MPIH_LSHIFT_FALSE=
-fi
-
- if test "$mpi_mod_asm_mpih_rshift" = yes; then
-  MPI_MOD_ASM_MPIH_RSHIFT_TRUE=
-  MPI_MOD_ASM_MPIH_RSHIFT_FALSE='#'
-else
-  MPI_MOD_ASM_MPIH_RSHIFT_TRUE='#'
-  MPI_MOD_ASM_MPIH_RSHIFT_FALSE=
-fi
-
- if test "$mpi_mod_asm_udiv" = yes; then
-  MPI_MOD_ASM_UDIV_TRUE=
-  MPI_MOD_ASM_UDIV_FALSE='#'
-else
-  MPI_MOD_ASM_UDIV_TRUE='#'
-  MPI_MOD_ASM_UDIV_FALSE=
-fi
-
- if test "$mpi_mod_asm_udiv_qrnnd" = yes; then
-  MPI_MOD_ASM_UDIV_QRNND_TRUE=
-  MPI_MOD_ASM_UDIV_QRNND_FALSE='#'
-else
-  MPI_MOD_ASM_UDIV_QRNND_TRUE='#'
-  MPI_MOD_ASM_UDIV_QRNND_FALSE=
-fi
-
- if test "$mpi_mod_c_mpih_add1" = yes; then
-  MPI_MOD_C_MPIH_ADD1_TRUE=
-  MPI_MOD_C_MPIH_ADD1_FALSE='#'
-else
-  MPI_MOD_C_MPIH_ADD1_TRUE='#'
-  MPI_MOD_C_MPIH_ADD1_FALSE=
-fi
-
- if test "$mpi_mod_c_mpih_sub1" = yes; then
-  MPI_MOD_C_MPIH_SUB1_TRUE=
-  MPI_MOD_C_MPIH_SUB1_FALSE='#'
-else
-  MPI_MOD_C_MPIH_SUB1_TRUE='#'
-  MPI_MOD_C_MPIH_SUB1_FALSE=
-fi
-
- if test "$mpi_mod_c_mpih_mul1" = yes; then
-  MPI_MOD_C_MPIH_MUL1_TRUE=
-  MPI_MOD_C_MPIH_MUL1_FALSE='#'
-else
-  MPI_MOD_C_MPIH_MUL1_TRUE='#'
-  MPI_MOD_C_MPIH_MUL1_FALSE=
-fi
-
- if test "$mpi_mod_c_mpih_mul2" = yes; then
-  MPI_MOD_C_MPIH_MUL2_TRUE=
-  MPI_MOD_C_MPIH_MUL2_FALSE='#'
-else
-  MPI_MOD_C_MPIH_MUL2_TRUE='#'
-  MPI_MOD_C_MPIH_MUL2_FALSE=
-fi
-
- if test "$mpi_mod_c_mpih_mul3" = yes; then
-  MPI_MOD_C_MPIH_MUL3_TRUE=
-  MPI_MOD_C_MPIH_MUL3_FALSE='#'
-else
-  MPI_MOD_C_MPIH_MUL3_TRUE='#'
-  MPI_MOD_C_MPIH_MUL3_FALSE=
-fi
-
- if test "$mpi_mod_c_mpih_lshift" = yes; then
-  MPI_MOD_C_MPIH_LSHIFT_TRUE=
-  MPI_MOD_C_MPIH_LSHIFT_FALSE='#'
-else
-  MPI_MOD_C_MPIH_LSHIFT_TRUE='#'
-  MPI_MOD_C_MPIH_LSHIFT_FALSE=
-fi
-
- if test "$mpi_mod_c_mpih_rshift" = yes; then
-  MPI_MOD_C_MPIH_RSHIFT_TRUE=
-  MPI_MOD_C_MPIH_RSHIFT_FALSE='#'
-else
-  MPI_MOD_C_MPIH_RSHIFT_TRUE='#'
-  MPI_MOD_C_MPIH_RSHIFT_FALSE=
-fi
-
- if test "$mpi_mod_c_udiv" = yes; then
-  MPI_MOD_C_UDIV_TRUE=
-  MPI_MOD_C_UDIV_FALSE='#'
-else
-  MPI_MOD_C_UDIV_TRUE='#'
-  MPI_MOD_C_UDIV_FALSE=
-fi
-
- if test "$mpi_mod_c_udiv_qrnnd" = yes; then
-  MPI_MOD_C_UDIV_QRNND_TRUE=
-  MPI_MOD_C_UDIV_QRNND_FALSE='#'
-else
-  MPI_MOD_C_UDIV_QRNND_TRUE='#'
-  MPI_MOD_C_UDIV_QRNND_FALSE=
-fi
-
-
-# Reset non applicable feature flags.
-if test "$mpi_cpu_arch" != "x86" ; then
-   aesnisupport="n/a"
-   pclmulsupport="n/a"
-   sse41support="n/a"
-   avxsupport="n/a"
-   avx2support="n/a"
-   padlocksupport="n/a"
-   jentsupport="n/a"
-   drngsupport="n/a"
-fi
-
-if test "$mpi_cpu_arch" != "arm" ; then
-   if test "$mpi_cpu_arch" != "aarch64" ; then
-     neonsupport="n/a"
-     armcryptosupport="n/a"
-   fi
-fi
-
-
-#############################################
-####                                     ####
-#### Platform specific compiler checks.  ####
-####                                     ####
-#############################################
-
-
-# Following tests depend on warnings to cause compile to fail, so set -Werror
-# temporarily.
-_gcc_cflags_save=$CFLAGS
-CFLAGS="$CFLAGS -Werror"
-
-
-#
-# Check whether compiler supports 'ms_abi' function attribute.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports 'ms_abi' function attribute" >&5
-$as_echo_n "checking whether compiler supports 'ms_abi' function attribute... " >&6; }
-if ${gcry_cv_gcc_attribute_ms_abi+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_attribute_ms_abi=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-int __attribute__ ((ms_abi)) proto(int);
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_attribute_ms_abi=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_attribute_ms_abi" >&5
-$as_echo "$gcry_cv_gcc_attribute_ms_abi" >&6; }
-if test "$gcry_cv_gcc_attribute_ms_abi" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_ATTRIBUTE_MS_ABI 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether compiler supports 'sysv_abi' function attribute.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports 'sysv_abi' function attribute" >&5
-$as_echo_n "checking whether compiler supports 'sysv_abi' function attribute... " >&6; }
-if ${gcry_cv_gcc_attribute_sysv_abi+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_attribute_sysv_abi=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-int __attribute__ ((sysv_abi)) proto(int);
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_attribute_sysv_abi=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_attribute_sysv_abi" >&5
-$as_echo "$gcry_cv_gcc_attribute_sysv_abi" >&6; }
-if test "$gcry_cv_gcc_attribute_sysv_abi" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_ATTRIBUTE_SYSV_ABI 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether default calling convention is 'ms_abi'.
-#
-if test "$gcry_cv_gcc_attribute_ms_abi" = "yes" ; then
-   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether default calling convention is 'ms_abi'" >&5
-$as_echo_n "checking whether default calling convention is 'ms_abi'... " >&6; }
-if ${gcry_cv_gcc_default_abi_is_ms_abi+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_default_abi_is_ms_abi=no
-           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void *test(void) {
-                 void *(*def_func)(void) = test;
-                 void *__attribute__((ms_abi))(*msabi_func)(void);
-                 /* warning on SysV abi targets, passes on Windows based targets */
-                 msabi_func = def_func;
-                 return msabi_func;
-             }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_default_abi_is_ms_abi=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_default_abi_is_ms_abi" >&5
-$as_echo "$gcry_cv_gcc_default_abi_is_ms_abi" >&6; }
-   if test "$gcry_cv_gcc_default_abi_is_ms_abi" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_DEFAULT_ABI_IS_MS_ABI 1" >>confdefs.h
-
-   fi
-fi
-
-
-#
-# Check whether default calling convention is 'sysv_abi'.
-#
-if test "$gcry_cv_gcc_attribute_sysv_abi" = "yes" ; then
-   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether default calling convention is 'sysv_abi'" >&5
-$as_echo_n "checking whether default calling convention is 'sysv_abi'... " >&6; }
-if ${gcry_cv_gcc_default_abi_is_sysv_abi+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_default_abi_is_sysv_abi=no
-           cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void *test(void) {
-                 void *(*def_func)(void) = test;
-                 void *__attribute__((sysv_abi))(*sysvabi_func)(void);
-                 /* warning on MS ABI targets, passes on SysV ABI targets */
-                 sysvabi_func = def_func;
-                 return sysvabi_func;
-             }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_default_abi_is_sysv_abi=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_default_abi_is_sysv_abi" >&5
-$as_echo "$gcry_cv_gcc_default_abi_is_sysv_abi" >&6; }
-   if test "$gcry_cv_gcc_default_abi_is_sysv_abi" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_DEFAULT_ABI_IS_SYSV_ABI 1" >>confdefs.h
-
-   fi
-fi
-
-
-# Restore flags.
-CFLAGS=$_gcc_cflags_save;
-
-
-#
-# Check whether GCC inline assembler supports SSSE3 instructions
-# This is required for the AES-NI instructions.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports SSSE3 instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports SSSE3 instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_ssse3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "x86" ; then
-          gcry_cv_gcc_inline_asm_ssse3="n/a"
-        else
-          gcry_cv_gcc_inline_asm_ssse3=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-static unsigned char be_mask[16] __attribute__ ((aligned (16))) =
-              { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
-            void a(void) {
-              __asm__("pshufb %[mask], %%xmm2\n\t"::[mask]"m"(*be_mask):);
-            }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_ssse3=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_ssse3" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_ssse3" >&6; }
-if test "$gcry_cv_gcc_inline_asm_ssse3" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_SSSE3 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC inline assembler supports PCLMUL instructions.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports PCLMUL instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports PCLMUL instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_pclmul+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "x86" ; then
-          gcry_cv_gcc_inline_asm_pclmul="n/a"
-        else
-          gcry_cv_gcc_inline_asm_pclmul=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void a(void) {
-              __asm__("pclmulqdq \$0, %%xmm1, %%xmm3\n\t":::"cc");
-            }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_pclmul=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_pclmul" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_pclmul" >&6; }
-if test "$gcry_cv_gcc_inline_asm_pclmul" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_PCLMUL 1" >>confdefs.h
-
-fi
-
-#
-# Check whether GCC inline assembler supports SSE4.1 instructions.
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports SSE4.1 instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports SSE4.1 instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_sse41+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "x86" ; then
-          gcry_cv_gcc_inline_asm_sse41="n/a"
-        else
-          gcry_cv_gcc_inline_asm_sse41=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void a(void) {
-              int i;
-              __asm__("pextrd \$2, %%xmm0, %[out]\n\t" : [out] "=m" (i));
-            }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_sse41=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_sse41" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_sse41" >&6; }
-if test "$gcry_cv_gcc_inline_asm_sse41" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_SSE41 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC inline assembler supports AVX instructions
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports AVX instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports AVX instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_avx+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "x86" ; then
-          gcry_cv_gcc_inline_asm_avx="n/a"
-        else
-          gcry_cv_gcc_inline_asm_avx=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void a(void) {
-              __asm__("xgetbv; vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):);
-            }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_avx=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_avx" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_avx" >&6; }
-if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_AVX 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC inline assembler supports AVX2 instructions
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports AVX2 instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports AVX2 instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_avx2+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "x86" ; then
-          gcry_cv_gcc_inline_asm_avx2="n/a"
-        else
-          gcry_cv_gcc_inline_asm_avx2=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-void a(void) {
-              __asm__("xgetbv; vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc");
-            }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_avx2=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_avx2" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_avx2" >&6; }
-if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_AVX2 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC inline assembler supports BMI2 instructions
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports BMI2 instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports BMI2 instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_bmi2+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "x86" ; then
-          gcry_cv_gcc_inline_asm_bmi2="n/a"
-        else
-          gcry_cv_gcc_inline_asm_bmi2=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-unsigned int a(unsigned int x, unsigned int y) {
-              unsigned int tmp1, tmp2;
-              asm ("rorxl %2, %1, %0"
-                   : "=r" (tmp1)
-                   : "rm0" (x), "J" (32 - ((23) & 31)));
-              asm ("andnl %2, %1, %0"
-                   : "=r" (tmp2)
-                   : "r0" (x), "rm" (y));
-              return tmp1 + tmp2;
-            }
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_bmi2=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_bmi2" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_bmi2" >&6; }
-if test "$gcry_cv_gcc_inline_asm_bmi2" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_BMI2 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC assembler needs "-Wa,--divide" to correctly handle
-# constant division
-#
-if test $amd64_as_feature_detection = yes; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC assembler handles division correctly" >&5
-$as_echo_n "checking whether GCC assembler handles division correctly... " >&6; }
-if ${gcry_cv_gcc_as_const_division_ok+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_as_const_division_ok=no
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__("xorl \$(123456789/12345678), %ebp;\n\t");
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_as_const_division_ok=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_as_const_division_ok" >&5
-$as_echo "$gcry_cv_gcc_as_const_division_ok" >&6; }
-  if test "$gcry_cv_gcc_as_const_division_ok" = "no" ; then
-    #
-    # Add '-Wa,--divide' to CPPFLAGS and try check again.
-    #
-    _gcc_cppflags_save="$CPPFLAGS"
-    CPPFLAGS="$CPPFLAGS -Wa,--divide"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC assembler handles division correctly with \"-Wa,--divide\"" >&5
-$as_echo_n "checking whether GCC assembler handles division correctly with \"-Wa,--divide\"... " >&6; }
-if ${gcry_cv_gcc_as_const_division_with_wadivide_ok+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_as_const_division_with_wadivide_ok=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__("xorl \$(123456789/12345678), %ebp;\n\t");
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_as_const_division_with_wadivide_ok=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_as_const_division_with_wadivide_ok" >&5
-$as_echo "$gcry_cv_gcc_as_const_division_with_wadivide_ok" >&6; }
-    if test "$gcry_cv_gcc_as_const_division_with_wadivide_ok" = "no" ; then
-      # '-Wa,--divide' did not work, restore old flags.
-      CPPFLAGS="$_gcc_cppflags_save"
-    fi
-  fi
-fi
-
-
-#
-# Check whether GCC assembler supports features needed for our amd64
-# implementations
-#
-if test $amd64_as_feature_detection = yes; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC assembler is compatible for amd64 assembly implementations" >&5
-$as_echo_n "checking whether GCC assembler is compatible for amd64 assembly implementations... " >&6; }
-if ${gcry_cv_gcc_amd64_platform_as_ok+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "x86" ; then
-          gcry_cv_gcc_amd64_platform_as_ok="n/a"
-        else
-          gcry_cv_gcc_amd64_platform_as_ok=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-                /* Test if '.type' and '.size' are supported.  */
-                /* These work only on ELF targets. */
-               "asmfunc:\n\t"
-                ".size asmfunc,.-asmfunc;\n\t"
-                ".type asmfunc,@function;\n\t"
-               /* Test if assembler allows use of '/' for constant division
-                * (Solaris/x86 issue). If previous constant division check
-                * and "-Wa,--divide" workaround failed, this causes assembly
-                * to be disable on this machine. */
-               "xorl \$(123456789/12345678), %ebp;\n\t"
-            );
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_amd64_platform_as_ok=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_amd64_platform_as_ok" >&5
-$as_echo "$gcry_cv_gcc_amd64_platform_as_ok" >&6; }
-  if test "$gcry_cv_gcc_amd64_platform_as_ok" = "yes" ; then
-
-$as_echo "#define HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS 1" >>confdefs.h
-
-  fi
-  if test "$gcry_cv_gcc_amd64_platform_as_ok" = "no" &&
-     test "$gcry_cv_gcc_attribute_sysv_abi" = "yes" &&
-     test "$gcry_cv_gcc_default_abi_is_ms_abi" = "yes"; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC assembler is compatible for WIN64 assembly implementations" >&5
-$as_echo_n "checking whether GCC assembler is compatible for WIN64 assembly implementations... " >&6; }
-if ${gcry_cv_gcc_win64_platform_as_ok+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  gcry_cv_gcc_win64_platform_as_ok=no
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-              ".globl asmfunc\n\t"
-              "asmfunc:\n\t"
-              "xorq \$(1234), %rbp;\n\t"
-          );
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_win64_platform_as_ok=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_win64_platform_as_ok" >&5
-$as_echo "$gcry_cv_gcc_win64_platform_as_ok" >&6; }
-    if test "$gcry_cv_gcc_win64_platform_as_ok" = "yes" ; then
-
-$as_echo "#define HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS 1" >>confdefs.h
-
-    fi
-  fi
-fi
-
-
-#
-# Check whether GCC assembler supports features needed for assembly
-# implementations that use Intel syntax
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC assembler is compatible for Intel syntax assembly implementations" >&5
-$as_echo_n "checking whether GCC assembler is compatible for Intel syntax assembly implementations... " >&6; }
-if ${gcry_cv_gcc_platform_as_ok_for_intel_syntax+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "x86" ; then
-          gcry_cv_gcc_platform_as_ok_for_intel_syntax="n/a"
-        else
-          gcry_cv_gcc_platform_as_ok_for_intel_syntax=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-                ".intel_syntax noprefix\n\t"
-                "pxor xmm1, xmm7;\n\t"
-                /* Intel syntax implementation also use GAS macros, so check
-                 * for them here. */
-                "VAL_A = xmm4\n\t"
-                "VAL_B = xmm2\n\t"
-                ".macro SET_VAL_A p1\n\t"
-                "  VAL_A = \\\\p1 \n\t"
-                ".endm\n\t"
-                ".macro SET_VAL_B p1\n\t"
-                "  VAL_B = \\\\p1 \n\t"
-                ".endm\n\t"
-                "vmovdqa VAL_A, VAL_B;\n\t"
-                "SET_VAL_A eax\n\t"
-                "SET_VAL_B ebp\n\t"
-                "add VAL_A, VAL_B;\n\t"
-                "add VAL_B, 0b10101;\n\t"
-            );
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_platform_as_ok_for_intel_syntax=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_platform_as_ok_for_intel_syntax" >&5
-$as_echo "$gcry_cv_gcc_platform_as_ok_for_intel_syntax" >&6; }
-if test "$gcry_cv_gcc_platform_as_ok_for_intel_syntax" = "yes" ; then
-
-$as_echo "#define HAVE_INTEL_SYNTAX_PLATFORM_AS 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether compiler is configured for ARMv6 or newer architecture
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler is configured for ARMv6 or newer architecture" >&5
-$as_echo_n "checking whether compiler is configured for ARMv6 or newer architecture... " >&6; }
-if ${gcry_cv_cc_arm_arch_is_v6+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "arm" ; then
-          gcry_cv_cc_arm_arch_is_v6="n/a"
-        else
-          gcry_cv_cc_arm_arch_is_v6=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-           #if defined(__arm__) && \
-             ((defined(__ARM_ARCH) && __ARM_ARCH >= 6) \
-             || defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
-             || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
-             || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \
-             || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
-             || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
-             || defined(__ARM_ARCH_7EM__))
-             /* empty */
-           #else
-             /* fail compile if not ARMv6. */
-             not_armv6 not_armv6 = (not_armv6)not_armv6;
-           #endif
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_cc_arm_arch_is_v6=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_cc_arm_arch_is_v6" >&5
-$as_echo "$gcry_cv_cc_arm_arch_is_v6" >&6; }
-if test "$gcry_cv_cc_arm_arch_is_v6" = "yes" ; then
-
-$as_echo "#define HAVE_ARM_ARCH_V6 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC inline assembler supports NEON instructions
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports NEON instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports NEON instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_neon+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "arm" ; then
-          gcry_cv_gcc_inline_asm_neon="n/a"
-        else
-          gcry_cv_gcc_inline_asm_neon=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-                ".syntax unified\n\t"
-                ".arm\n\t"
-                ".fpu neon\n\t"
-                "vld1.64 {%q0-%q1}, [%r0]!;\n\t"
-                "vrev64.8 %q0, %q3;\n\t"
-                "vadd.u64 %q0, %q1;\n\t"
-                "vadd.s64 %d3, %d2, %d3;\n\t"
-                );
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_neon=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_neon" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_neon" >&6; }
-if test "$gcry_cv_gcc_inline_asm_neon" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_NEON 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC inline assembler supports AArch32 Crypto Extension instructions
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports AArch32 Crypto Extension instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports AArch32 Crypto Extension instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_aarch32_crypto+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "arm" ; then
-          gcry_cv_gcc_inline_asm_aarch32_crypto="n/a"
-        else
-          gcry_cv_gcc_inline_asm_aarch32_crypto=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-                ".syntax unified\n\t"
-                ".arch armv8-a\n\t"
-                ".arm\n\t"
-                ".fpu crypto-neon-fp-armv8\n\t"
-
-                "sha1h.32 q0, q0;\n\t"
-                "sha1c.32 q0, q0, q0;\n\t"
-                "sha1p.32 q0, q0, q0;\n\t"
-                "sha1su0.32 q0, q0, q0;\n\t"
-                "sha1su1.32 q0, q0;\n\t"
-
-                "sha256h.32 q0, q0, q0;\n\t"
-                "sha256h2.32 q0, q0, q0;\n\t"
-                "sha1p.32 q0, q0, q0;\n\t"
-                "sha256su0.32 q0, q0;\n\t"
-                "sha256su1.32 q0, q0, q15;\n\t"
-
-                "aese.8 q0, q0;\n\t"
-                "aesd.8 q0, q0;\n\t"
-                "aesmc.8 q0, q0;\n\t"
-                "aesimc.8 q0, q0;\n\t"
-
-                "vmull.p64 q0, d0, d0;\n\t"
-                );
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_aarch32_crypto=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_aarch32_crypto" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_aarch32_crypto" >&6; }
-if test "$gcry_cv_gcc_inline_asm_aarch32_crypto" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC inline assembler supports AArch64 NEON instructions
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports AArch64 NEON instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports AArch64 NEON instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_aarch64_neon+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "aarch64" ; then
-          gcry_cv_gcc_inline_asm_aarch64_neon="n/a"
-        else
-          gcry_cv_gcc_inline_asm_aarch64_neon=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-                ".cpu generic+simd\n\t"
-                "mov w0, \#42;\n\t"
-                "dup v0.8b, w0;\n\t"
-                "ld4 {v0.8b,v1.8b,v2.8b,v3.8b},[x0],\#32;\n\t"
-                );
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_aarch64_neon=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_aarch64_neon" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_aarch64_neon" >&6; }
-if test "$gcry_cv_gcc_inline_asm_aarch64_neon" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_AARCH64_NEON 1" >>confdefs.h
-
-fi
-
-
-#
-# Check whether GCC inline assembler supports AArch64 Crypto Extension instructions
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC inline assembler supports AArch64 Crypto Extension instructions" >&5
-$as_echo_n "checking whether GCC inline assembler supports AArch64 Crypto Extension instructions... " >&6; }
-if ${gcry_cv_gcc_inline_asm_aarch64_crypto+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$mpi_cpu_arch" != "aarch64" ; then
-          gcry_cv_gcc_inline_asm_aarch64_crypto="n/a"
-        else
-          gcry_cv_gcc_inline_asm_aarch64_crypto=no
-          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-__asm__(
-                ".cpu generic+simd+crypto\n\t"
-
-                "mov w0, \#42;\n\t"
-                "dup v0.8b, w0;\n\t"
-                "ld4 {v0.8b,v1.8b,v2.8b,v3.8b},[x0],\#32;\n\t"
-
-                "sha1h s0, s0;\n\t"
-                "sha1c q0, s0, v0.4s;\n\t"
-                "sha1p q0, s0, v0.4s;\n\t"
-                "sha1su0 v0.4s, v0.4s, v0.4s;\n\t"
-                "sha1su1 v0.4s, v0.4s;\n\t"
-
-                "sha256h q0, q0, v0.4s;\n\t"
-                "sha256h2 q0, q0, v0.4s;\n\t"
-                "sha1p q0, s0, v0.4s;\n\t"
-                "sha256su0 v0.4s, v0.4s;\n\t"
-                "sha256su1 v0.4s, v0.4s, v31.4s;\n\t"
-
-                "aese v0.16b, v0.16b;\n\t"
-                "aesd v0.16b, v0.16b;\n\t"
-                "aesmc v0.16b, v0.16b;\n\t"
-                "aesimc v0.16b, v0.16b;\n\t"
-
-                "pmull v0.1q, v0.1d, v31.1d;\n\t"
-                "pmull2 v0.1q, v0.2d, v31.2d;\n\t"
-                );
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gcry_cv_gcc_inline_asm_aarch64_crypto=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcry_cv_gcc_inline_asm_aarch64_crypto" >&5
-$as_echo "$gcry_cv_gcc_inline_asm_aarch64_crypto" >&6; }
-if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" = "yes" ; then
-
-$as_echo "#define HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO 1" >>confdefs.h
-
-fi
-
-
-#######################################
-#### Checks for library functions. ####
-#######################################
-
-for ac_func in vprintf
-do :
-  ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf"
-if test "x$ac_cv_func_vprintf" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_VPRINTF 1
-_ACEOF
-
-ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt"
-if test "x$ac_cv_func__doprnt" = xyes; then :
-
-$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h
-
-fi
-
-fi
-done
-
-
-# We have replacements for these in src/missing-string.c
-for ac_func in stpcpy strcasecmp
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-# We have replacements for these in src/g10lib.h
-for ac_func in strtoul memmove stricmp atexit raise
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-# Other checks
-for ac_func in strerror rand mmap getpagesize sysconf waitpid wait4
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in gettimeofday getrusage gethrtime clock_gettime syslog
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in syscall fcntl ftruncate flockfile
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
- for ac_func in mlock
-do :
-  ac_fn_c_check_func "$LINENO" "mlock" "ac_cv_func_mlock"
-if test "x$ac_cv_func_mlock" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_MLOCK 1
-_ACEOF
-
-fi
-done
-
-    if test "$ac_cv_func_mlock" = "no"; then
-        for ac_header in sys/mman.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_mman_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_MMAN_H 1
-_ACEOF
-
-fi
-
-done
-
-        if test "$ac_cv_header_sys_mman_h" = "yes"; then
-            # Add librt to LIBS:
-            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for memlk in -lrt" >&5
-$as_echo_n "checking for memlk in -lrt... " >&6; }
-if ${ac_cv_lib_rt_memlk+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lrt  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char memlk ();
-int
-main ()
-{
-return memlk ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_rt_memlk=yes
-else
-  ac_cv_lib_rt_memlk=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_memlk" >&5
-$as_echo "$ac_cv_lib_rt_memlk" >&6; }
-if test "x$ac_cv_lib_rt_memlk" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBRT 1
-_ACEOF
-
-  LIBS="-lrt $LIBS"
-
-fi
-
-            { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mlock is in sys/mman.h" >&5
-$as_echo_n "checking whether mlock is in sys/mman.h... " >&6; }
-if ${gnupg_cv_mlock_is_in_sys_mman+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-                    #include <assert.h>
-                    #ifdef HAVE_SYS_MMAN_H
-                    #include <sys/mman.h>
-                    #endif
-
-int
-main ()
-{
-
-int i;
-
-/* glibc defines this for functions which it implements
- * to always fail with ENOSYS.  Some functions are actually
- * named something starting with __ and the normal name
- * is an alias.  */
-#if defined (__stub_mlock) || defined (__stub___mlock)
-choke me
-#else
-mlock(&i, 4);
-#endif
-; return 0;
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  gnupg_cv_mlock_is_in_sys_mman=yes
-else
-  gnupg_cv_mlock_is_in_sys_mman=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gnupg_cv_mlock_is_in_sys_mman" >&5
-$as_echo "$gnupg_cv_mlock_is_in_sys_mman" >&6; }
-            if test "$gnupg_cv_mlock_is_in_sys_mman" = "yes"; then
-
-$as_echo "#define HAVE_MLOCK 1" >>confdefs.h
-
-            fi
-        fi
-    fi
-    if test "$ac_cv_func_mlock" = "yes"; then
-        for ac_func in sysconf getpagesize
-do :
-  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-        { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mlock is broken" >&5
-$as_echo_n "checking whether mlock is broken... " >&6; }
-          if ${gnupg_cv_have_broken_mlock+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test "$cross_compiling" = yes; then :
-  gnupg_cv_have_broken_mlock="assume-no"
-
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <fcntl.h>
-
-int main()
-{
-    char *pool;
-    int err;
-    long int pgsize;
-
-#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
-    pgsize = sysconf (_SC_PAGESIZE);
-#elif defined (HAVE_GETPAGESIZE)
-    pgsize = getpagesize();
-#else
-    pgsize = -1;
-#endif
-
-    if (pgsize == -1)
-      pgsize = 4096;
-
-    pool = malloc( 4096 + pgsize );
-    if( !pool )
-        return 2;
-    pool += (pgsize - ((long int)pool % pgsize));
-
-    err = mlock( pool, 4096 );
-    if( !err || errno == EPERM || errno == EAGAIN)
-        return 0; /* okay */
-
-    return 1;  /* hmmm */
-}
-
-
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-  gnupg_cv_have_broken_mlock="no"
-else
-  gnupg_cv_have_broken_mlock="yes"
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-  conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-
-fi
-
-         if test "$gnupg_cv_have_broken_mlock" = "yes"; then
-
-$as_echo "#define HAVE_BROKEN_MLOCK 1" >>confdefs.h
-
-             { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-         else
-            if test "$gnupg_cv_have_broken_mlock" = "no"; then
-                { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-            else
-                { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming no" >&5
-$as_echo "assuming no" >&6; }
-            fi
-         fi
-    fi
-
-
-#
-# Replacement functions.
-#
-ac_fn_c_check_func "$LINENO" "getpid" "ac_cv_func_getpid"
-if test "x$ac_cv_func_getpid" = xyes; then :
-  $as_echo "#define HAVE_GETPID 1" >>confdefs.h
-
-else
-  case " $LIBOBJS " in
-  *" getpid.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS getpid.$ac_objext"
- ;;
-esac
-
-fi
-
-ac_fn_c_check_func "$LINENO" "clock" "ac_cv_func_clock"
-if test "x$ac_cv_func_clock" = xyes; then :
-  $as_echo "#define HAVE_CLOCK 1" >>confdefs.h
-
-else
-  case " $LIBOBJS " in
-  *" clock.$ac_objext "* ) ;;
-  *) LIBOBJS="$LIBOBJS clock.$ac_objext"
- ;;
-esac
-
-fi
-
-
-
-
-#
-# Check whether it is necessary to link against libdl.
-#
-DL_LIBS=""
-if test "$use_hmac_binary_check" = yes ; then
-  _gcry_save_libs="$LIBS"
-  LIBS=""
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
-$as_echo_n "checking for library containing dlopen... " >&6; }
-if ${ac_cv_search_dlopen+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
-  ;
-  return 0;
-}
-_ACEOF
-for ac_lib in '' c dl; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_search_dlopen=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext
-  if ${ac_cv_search_dlopen+:} false; then :
-  break
-fi
-done
-if ${ac_cv_search_dlopen+:} false; then :
-
-else
-  ac_cv_search_dlopen=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
-$as_echo "$ac_cv_search_dlopen" >&6; }
-ac_res=$ac_cv_search_dlopen
-if test "$ac_res" != no; then :
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-fi
-
-  DL_LIBS=$LIBS
-  LIBS="$_gcry_save_libs"
-  LIBGCRYPT_CONFIG_LIBS="${LIBGCRYPT_CONFIG_LIBS} ${DL_LIBS}"
-fi
-
-
-
-#
-# Check whether we can use Linux capabilities as requested.
-#
-if test "$use_capabilities" = "yes" ; then
-use_capabilities=no
-for ac_header in sys/capability.h
-do :
-  ac_fn_c_check_header_mongrel "$LINENO" "sys/capability.h" "ac_cv_header_sys_capability_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_capability_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_CAPABILITY_H 1
-_ACEOF
-
-fi
-
-done
-
-if test "$ac_cv_header_sys_capability_h" = "yes" ; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_init in -lcap" >&5
-$as_echo_n "checking for cap_init in -lcap... " >&6; }
-if ${ac_cv_lib_cap_cap_init+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcap  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char cap_init ();
-int
-main ()
-{
-return cap_init ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_cap_cap_init=yes
-else
-  ac_cv_lib_cap_cap_init=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_cap_init" >&5
-$as_echo "$ac_cv_lib_cap_cap_init" >&6; }
-if test "x$ac_cv_lib_cap_cap_init" = xyes; then :
-  ac_need_libcap=1
-fi
-
-  if test "$ac_cv_lib_cap_cap_init" = "yes"; then
-
-$as_echo "#define USE_CAPABILITIES 1" >>confdefs.h
-
-     LIBS="$LIBS -lcap"
-     use_capabilities=yes
-  fi
-fi
-if test "$use_capabilities" = "no" ; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
-***
-*** The use of capabilities on this system is not possible.
-*** You need a recent Linux kernel and some patches:
-***   fcaps-2.2.9-990610.patch      (kernel patch for 2.2.9)
-***   fcap-module-990613.tar.gz     (kernel module)
-***   libcap-1.92.tar.gz            (user mode library and utilities)
-*** And you have to configure the kernel with CONFIG_VFS_CAP_PLUGIN
-*** set (filesystems menu). Be warned: This code is *really* ALPHA.
-***" >&5
-$as_echo "$as_me: WARNING:
-***
-*** The use of capabilities on this system is not possible.
-*** You need a recent Linux kernel and some patches:
-***   fcaps-2.2.9-990610.patch      (kernel patch for 2.2.9)
-***   fcap-module-990613.tar.gz     (kernel module)
-***   libcap-1.92.tar.gz            (user mode library and utilities)
-*** And you have to configure the kernel with CONFIG_VFS_CAP_PLUGIN
-*** set (filesystems menu). Be warned: This code is *really* ALPHA.
-***" >&2;}
-fi
-fi
-
-# Check whether a random device is available.
-if test "$try_dev_random" = yes ; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for random device" >&5
-$as_echo_n "checking for random device... " >&6; }
-if ${ac_cv_have_dev_random+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -r "$NAME_OF_DEV_RANDOM" && test -r "$NAME_OF_DEV_URANDOM" ; then
-      ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_dev_random" >&5
-$as_echo "$ac_cv_have_dev_random" >&6; }
-    if test "$ac_cv_have_dev_random" = yes; then
-
-$as_echo "#define HAVE_DEV_RANDOM 1" >>confdefs.h
-
-    fi
-else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for random device" >&5
-$as_echo_n "checking for random device... " >&6; }
-    ac_cv_have_dev_random=no
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: has been disabled" >&5
-$as_echo "has been disabled" >&6; }
-fi
-
-# Figure out the random modules for this configuration.
-if test "$random" = "default"; then
-
-    # Select default value.
-    if test "$ac_cv_have_dev_random" = yes; then
-        # Try Linuxish random device.
-        random_modules="linux"
-    else
-        case "${host}" in
-        *-*-mingw32ce*)
-          # WindowsCE random device.
-          random_modules="w32ce"
-          ;;
-        *-*-mingw32*|*-*-cygwin*)
-          # Windows random device.
-          random_modules="w32"
-          ;;
-        *)
-          # Build everything, allow to select at runtime.
-          random_modules="$auto_random_modules"
-          ;;
-        esac
-    fi
-else
-    if test "$random" = "auto"; then
-        # Build everything, allow to select at runtime.
-        random_modules="$auto_random_modules"
-    else
-        random_modules="$random"
-    fi
-fi
-
-
-#
-# Other defines
-#
-if test no = "yes"; then
-
-$as_echo "#define IS_DEVELOPMENT_VERSION 1" >>confdefs.h
-
-fi
-
-
- if test x$cross_compiling = xyes; then
-  CROSS_COMPILING_TRUE=
-  CROSS_COMPILING_FALSE='#'
-else
-  CROSS_COMPILING_TRUE='#'
-  CROSS_COMPILING_FALSE=
-fi
-
-
-
-# This is handy for debugging so the compiler doesn't rearrange
-# things and eliminate variables.
-# Check whether --enable-optimization was given.
-if test "${enable_optimization+set}" = set; then :
-  enableval=$enable_optimization; if test $enableval = no ; then
-                         CFLAGS=`echo $CFLAGS | sed 's/-O[0-9]//'`
-                       fi
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cc features" >&5
-$as_echo "$as_me: checking for cc features" >&6;}
-# CFLAGS mangling when using gcc.
-if test "$GCC" = yes; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if gcc supports -fno-delete-null-pointer-checks" >&5
-$as_echo_n "checking if gcc supports -fno-delete-null-pointer-checks... " >&6; }
-    _gcc_cflags_save=$CFLAGS
-    CFLAGS="-fno-delete-null-pointer-checks"
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  _gcc_wopt=yes
-else
-  _gcc_wopt=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_gcc_wopt" >&5
-$as_echo "$_gcc_wopt" >&6; }
-    CFLAGS=$_gcc_cflags_save;
-    if test x"$_gcc_wopt" = xyes ; then
-       CFLAGS="$CFLAGS -fno-delete-null-pointer-checks"
-    fi
-
-    CFLAGS="$CFLAGS -Wall"
-    if test "$USE_MAINTAINER_MODE" = "yes"; then
-        CFLAGS="$CFLAGS -Wcast-align -Wshadow -Wstrict-prototypes"
-        CFLAGS="$CFLAGS -Wformat -Wno-format-y2k -Wformat-security"
-
-        # If -Wno-missing-field-initializers is supported we can enable a
-        # a bunch of really useful warnings.
-        { $as_echo "$as_me:${as_lineno-$LINENO}: checking if gcc supports -Wno-missing-field-initializers" >&5
-$as_echo_n "checking if gcc supports -Wno-missing-field-initializers... " >&6; }
-        _gcc_cflags_save=$CFLAGS
-        CFLAGS="-Wno-missing-field-initializers"
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  _gcc_wopt=yes
-else
-  _gcc_wopt=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_gcc_wopt" >&5
-$as_echo "$_gcc_wopt" >&6; }
-        CFLAGS=$_gcc_cflags_save;
-        if test x"$_gcc_wopt" = xyes ; then
-          CFLAGS="$CFLAGS -W -Wextra -Wbad-function-cast"
-          CFLAGS="$CFLAGS -Wwrite-strings"
-          CFLAGS="$CFLAGS -Wdeclaration-after-statement"
-          CFLAGS="$CFLAGS -Wno-missing-field-initializers"
-          CFLAGS="$CFLAGS -Wno-sign-compare"
-        fi
-
-        { $as_echo "$as_me:${as_lineno-$LINENO}: checking if gcc supports -Wpointer-arith" >&5
-$as_echo_n "checking if gcc supports -Wpointer-arith... " >&6; }
-        _gcc_cflags_save=$CFLAGS
-        CFLAGS="-Wpointer-arith"
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  _gcc_wopt=yes
-else
-  _gcc_wopt=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_gcc_wopt" >&5
-$as_echo "$_gcc_wopt" >&6; }
-        CFLAGS=$_gcc_cflags_save;
-        if test x"$_gcc_wopt" = xyes ; then
-          CFLAGS="$CFLAGS -Wpointer-arith"
-        fi
-    fi
-fi
-
-# Check whether as(1) supports a noeexecstack feature.  This test
-# includes an override option.
-
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether non excutable stack support is requested" >&5
-$as_echo_n "checking whether non excutable stack support is requested... " >&6; }
-# Check whether --enable-noexecstack was given.
-if test "${enable_noexecstack+set}" = set; then :
-  enableval=$enable_noexecstack; noexecstack_support=$enableval
-else
-  noexecstack_support=yes
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $noexecstack_support" >&5
-$as_echo "$noexecstack_support" >&6; }
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether assembler supports --noexecstack option" >&5
-$as_echo_n "checking whether assembler supports --noexecstack option... " >&6; }
-if ${cl_cv_as_noexecstack+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-    cat > conftest.c <<EOF
-void foo() {}
-EOF
-  if { ac_try='${CC} $CFLAGS $CPPFLAGS
-                     -S -o conftest.s conftest.c >/dev/null'
-  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; } \
-     && grep .note.GNU-stack conftest.s >/dev/null \
-     && { ac_try='${CCAS} $CCASFLAGS $CPPFLAGS -Wa,--noexecstack
-                       -c -o conftest.o conftest.s >/dev/null'
-  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; }
-  then
-    cl_cv_as_noexecstack=yes
-  else
-    cl_cv_as_noexecstack=no
-  fi
-  rm -f conftest*
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cl_cv_as_noexecstack" >&5
-$as_echo "$cl_cv_as_noexecstack" >&6; }
-  if test "$noexecstack_support" = yes -a "$cl_cv_as_noexecstack" = yes; then
-       NOEXECSTACK_FLAGS="-Wa,--noexecstack"
-  else
-        NOEXECSTACK_FLAGS=
-  fi
-
-
-
-
-
-
-
-
-
-
-ac_config_commands="$ac_config_commands gcrypt-conf"
-
-
-#####################
-#### Conclusion. ####
-#####################
-
-# Check that requested feature can actually be used and define
-# ENABLE_foo_SUPPORT macros.
-
-if test x"$aesnisupport" = xyes ; then
-  if test "$gcry_cv_gcc_inline_asm_ssse3" != "yes" ; then
-    aesnisupport="no (unsupported by compiler)"
-  fi
-fi
-if test x"$pclmulsupport" = xyes ; then
-  if test "$gcry_cv_gcc_inline_asm_pclmul" != "yes" ; then
-    pclmulsupport="no (unsupported by compiler)"
-  fi
-fi
-if test x"$sse41support" = xyes ; then
-  if test "$gcry_cv_gcc_inline_asm_sse41" != "yes" ; then
-    sse41support="no (unsupported by compiler)"
-  fi
-fi
-if test x"$avxsupport" = xyes ; then
-  if test "$gcry_cv_gcc_inline_asm_avx" != "yes" ; then
-    avxsupport="no (unsupported by compiler)"
-  fi
-fi
-if test x"$avx2support" = xyes ; then
-  if test "$gcry_cv_gcc_inline_asm_avx2" != "yes" ; then
-    avx2support="no (unsupported by compiler)"
-  fi
-fi
-if test x"$neonsupport" = xyes ; then
-  if test "$gcry_cv_gcc_inline_asm_neon" != "yes" ; then
-    if test "$gcry_cv_gcc_inline_asm_aarch64_neon" != "yes" ; then
-      neonsupport="no (unsupported by compiler)"
-    fi
-  fi
-fi
-if test x"$armcryptosupport" = xyes ; then
-  if test "$gcry_cv_gcc_inline_asm_aarch32_crypto" != "yes" ; then
-    if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" != "yes" ; then
-      neonsupport="no (unsupported by compiler)"
-    fi
-  fi
-fi
-
-if test x"$aesnisupport" = xyes ; then
-
-$as_echo "#define ENABLE_AESNI_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$pclmulsupport" = xyes ; then
-
-$as_echo "#define ENABLE_PCLMUL_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$sse41support" = xyes ; then
-
-$as_echo "#define ENABLE_SSE41_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$avxsupport" = xyes ; then
-
-$as_echo "#define ENABLE_AVX_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$avx2support" = xyes ; then
-
-$as_echo "#define ENABLE_AVX2_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$neonsupport" = xyes ; then
-
-$as_echo "#define ENABLE_NEON_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$armcryptosupport" = xyes ; then
-
-$as_echo "#define ENABLE_ARM_CRYPTO_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$jentsupport" = xyes ; then
-
-$as_echo "#define ENABLE_JENT_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$padlocksupport" = xyes ; then
-
-$as_echo "#define ENABLE_PADLOCK_SUPPORT 1" >>confdefs.h
-
-fi
-if test x"$drngsupport" = xyes ; then
-
-$as_echo "#define ENABLE_DRNG_SUPPORT 1" >>confdefs.h
-
-fi
-
-
-# Define conditional sources and config.h symbols depending on the
-# selected ciphers, pubkey-ciphers, digests, kdfs, and random modules.
-
-
-name=arcfour
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1"; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour.lo"
-
-$as_echo "#define USE_ARCFOUR 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour-amd64.lo"
-      ;;
-   esac
-fi
-
-
-name=blowfish
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish.lo"
-
-$as_echo "#define USE_BLOWFISH 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish-amd64.lo"
-      ;;
-      arm*-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish-arm.lo"
-      ;;
-   esac
-fi
-
-
-name=cast5
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5.lo"
-
-$as_echo "#define USE_CAST5 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5-amd64.lo"
-      ;;
-      arm*-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5-arm.lo"
-      ;;
-   esac
-fi
-
-
-name=des
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS des.lo"
-
-$as_echo "#define USE_DES 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS des-amd64.lo"
-      ;;
-   esac
-fi
-
-
-name=aes
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael.lo"
-
-$as_echo "#define USE_AES 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-amd64.lo"
-
-         # Build with the SSSE3 implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ssse3-amd64.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ssse3-amd64-asm.lo"
-      ;;
-      arm*-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-arm.lo"
-
-         # Build with the ARMv8/AArch32 CE implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-ce.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-aarch32-ce.lo"
-      ;;
-      aarch64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-aarch64.lo"
-
-         # Build with the ARMv8/AArch64 CE implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-ce.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-aarch64-ce.lo"
-      ;;
-   esac
-
-   case "$mpi_cpu_arch" in
-     x86)
-         # Build with the AES-NI implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-aesni.lo"
-
-         # Build with the Padlock implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-padlock.lo"
-      ;;
-   esac
-fi
-
-
-name=twofish
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish.lo"
-
-$as_echo "#define USE_TWOFISH 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-amd64.lo"
-
-         if test x"$avx2support" = xyes ; then
-            # Build with the AVX2 implementation
-            GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-avx2-amd64.lo"
-         fi
-      ;;
-      arm*-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-arm.lo"
-      ;;
-      aarch64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-aarch64.lo"
-      ;;
-   esac
-fi
-
-
-name=serpent
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent.lo"
-
-$as_echo "#define USE_SERPENT 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the SSE2 implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-sse2-amd64.lo"
-      ;;
-   esac
-
-   if test x"$avx2support" = xyes ; then
-      # Build with the AVX2 implementation
-      GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-avx2-amd64.lo"
-   fi
-
-   if test x"$neonsupport" = xyes ; then
-      # Build with the NEON implementation
-      GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-armv7-neon.lo"
-   fi
-fi
-
-
-name=rfc2268
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS rfc2268.lo"
-
-$as_echo "#define USE_RFC2268 1" >>confdefs.h
-
-fi
-
-
-name=seed
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS seed.lo"
-
-$as_echo "#define USE_SEED 1" >>confdefs.h
-
-fi
-
-
-name=camellia
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia.lo camellia-glue.lo"
-
-$as_echo "#define USE_CAMELLIA 1" >>confdefs.h
-
-
-   case "${host}" in
-      arm*-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-arm.lo"
-      ;;
-      aarch64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aarch64.lo"
-      ;;
-   esac
-
-   if test x"$avxsupport" = xyes ; then
-      if test x"$aesnisupport" = xyes ; then
-        # Build with the AES-NI/AVX implementation
-        GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aesni-avx-amd64.lo"
-      fi
-   fi
-
-   if test x"$avx2support" = xyes ; then
-      if test x"$aesnisupport" = xyes ; then
-        # Build with the AES-NI/AVX2 implementation
-        GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aesni-avx2-amd64.lo"
-      fi
-   fi
-fi
-
-
-name=idea
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS idea.lo"
-
-$as_echo "#define USE_IDEA 1" >>confdefs.h
-
-fi
-
-
-name=salsa20
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20.lo"
-
-$as_echo "#define USE_SALSA20 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20-amd64.lo"
-      ;;
-   esac
-
-   if test x"$neonsupport" = xyes ; then
-     # Build with the NEON implementation
-     GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20-armv7-neon.lo"
-   fi
-fi
-
-
-name=gost28147
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS gost28147.lo"
-
-$as_echo "#define USE_GOST28147 1" >>confdefs.h
-
-fi
-
-
-name=chacha20
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20.lo"
-
-$as_echo "#define USE_CHACHA20 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-sse2-amd64.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ssse3-amd64.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-avx2-amd64.lo"
-      ;;
-   esac
-
-   if test x"$neonsupport" = xyes ; then
-     # Build with the NEON implementation
-     GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-armv7-neon.lo"
-   fi
-fi
-
-case "${host}" in
-   x86_64-*-*)
-      # Build with the assembly implementation
-      GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-sse2-amd64.lo"
-      GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-avx2-amd64.lo"
-   ;;
-esac
-
-if test x"$neonsupport" = xyes ; then
-   # Build with the NEON implementation
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-armv7-neon.lo"
-fi
-
-
-name=dsa
-list=$enabled_pubkey_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS dsa.lo"
-
-$as_echo "#define USE_DSA 1" >>confdefs.h
-
-fi
-
-
-name=rsa
-list=$enabled_pubkey_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS rsa.lo"
-
-$as_echo "#define USE_RSA 1" >>confdefs.h
-
-fi
-
-
-name=elgamal
-list=$enabled_pubkey_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS elgamal.lo"
-
-$as_echo "#define USE_ELGAMAL 1" >>confdefs.h
-
-fi
-
-
-name=ecc
-list=$enabled_pubkey_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS \
-                          ecc.lo ecc-curves.lo ecc-misc.lo \
-                          ecc-ecdsa.lo ecc-eddsa.lo ecc-gost.lo"
-
-$as_echo "#define USE_ECC 1" >>confdefs.h
-
-fi
-
-
-name=crc
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc.lo"
-
-$as_echo "#define USE_CRC 1" >>confdefs.h
-
-
-   case "${host}" in
-      i?86-*-* | x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc-intel-pclmul.lo"
-      ;;
-   esac
-fi
-
-
-name=gostr3411-94
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   # GOST R 34.11-94 internally uses GOST 28147-89
-
-name=gost28147
-list=$enabled_ciphers
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-   if test "$found" = "1" ; then
-      GCRYPT_DIGESTS="$GCRYPT_DIGESTS gostr3411-94.lo"
-
-$as_echo "#define USE_GOST_R_3411_94 1" >>confdefs.h
-
-   fi
-fi
-
-
-name=stribog
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS stribog.lo"
-
-$as_echo "#define USE_GOST_R_3411_12 1" >>confdefs.h
-
-fi
-
-
-name=md2
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS md2.lo"
-
-$as_echo "#define USE_MD2 1" >>confdefs.h
-
-fi
-
-
-name=md4
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS md4.lo"
-
-$as_echo "#define USE_MD4 1" >>confdefs.h
-
-fi
-
-
-name=md5
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS md5.lo"
-
-$as_echo "#define USE_MD5 1" >>confdefs.h
-
-fi
-
-
-name=rmd160
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS rmd160.lo"
-
-$as_echo "#define USE_RMD160 1" >>confdefs.h
-
-fi
-
-
-name=sha256
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256.lo"
-
-$as_echo "#define USE_SHA256 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-ssse3-amd64.lo"
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-avx-amd64.lo"
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-avx2-bmi2-amd64.lo"
-      ;;
-      arm*-*-*)
-         # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-armv8-aarch32-ce.lo"
-      ;;
-      aarch64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-armv8-aarch64-ce.lo"
-      ;;
-   esac
-fi
-
-
-name=sha512
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512.lo"
-
-$as_echo "#define USE_SHA512 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-ssse3-amd64.lo"
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx-amd64.lo"
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx2-bmi2-amd64.lo"
-      ;;
-      arm*-*-*)
-         # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-arm.lo"
-      ;;
-   esac
-
-   if test x"$neonsupport" = xyes ; then
-     # Build with the NEON implementation
-     GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-armv7-neon.lo"
-   fi
-fi
-
-
-name=sha3
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak.lo"
-
-$as_echo "#define USE_SHA3 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         :
-      ;;
-   esac
-
-   if test x"$neonsupport" = xyes ; then
-     # Build with the NEON implementation
-     GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak-armv7-neon.lo"
-   fi
-fi
-
-
-name=tiger
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS tiger.lo"
-
-$as_echo "#define USE_TIGER 1" >>confdefs.h
-
-fi
-
-
-name=whirlpool
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS whirlpool.lo"
-
-$as_echo "#define USE_WHIRLPOOL 1" >>confdefs.h
-
-
-   case "${host}" in
-      x86_64-*-*)
-         # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS whirlpool-sse2-amd64.lo"
-      ;;
-   esac
-fi
-
-
-name=blake2
-list=$enabled_digests
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_DIGESTS="$GCRYPT_DIGESTS blake2.lo"
-
-$as_echo "#define USE_BLAKE2 1" >>confdefs.h
-
-fi
-
-# SHA-1 needs to be included always for example because it is used by
-# random-csprng.c.
-GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1.lo"
-
-$as_echo "#define USE_SHA1 1" >>confdefs.h
-
-
-case "${host}" in
-  x86_64-*-*)
-    # Build with the assembly implementation
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-ssse3-amd64.lo"
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-avx-amd64.lo"
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-avx-bmi2-amd64.lo"
-  ;;
-  arm*-*-*)
-    # Build with the assembly implementation
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv7-neon.lo"
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv8-aarch32-ce.lo"
-  ;;
-  aarch64-*-*)
-    # Build with the assembly implementation
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv8-aarch64-ce.lo"
-  ;;
-esac
-
-
-name=scrypt
-list=$enabled_kdfs
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_KDFS="$GCRYPT_KDFS scrypt.lo"
-
-$as_echo "#define USE_SCRYPT 1" >>confdefs.h
-
-fi
-
-
-name=linux
-list=$random_modules
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_RANDOM="$GCRYPT_RANDOM rndlinux.lo"
-
-$as_echo "#define USE_RNDLINUX 1" >>confdefs.h
-
-fi
-
-
-name=unix
-list=$random_modules
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_RANDOM="$GCRYPT_RANDOM rndunix.lo"
-
-$as_echo "#define USE_RNDUNIX 1" >>confdefs.h
-
-fi
-
-
-name=egd
-list=$random_modules
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_RANDOM="$GCRYPT_RANDOM rndegd.lo"
-
-$as_echo "#define USE_RNDEGD 1" >>confdefs.h
-
-fi
-
-
-name=w32
-list=$random_modules
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32.lo"
-
-$as_echo "#define USE_RNDW32 1" >>confdefs.h
-
-fi
-
-
-name=w32ce
-list=$random_modules
-found=0
-
-for n in $list; do
-  if test "x$name" = "x$n"; then
-    found=1
-  fi
-done
-
-if test "$found" = "1" ; then
-   GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32ce.lo"
-
-$as_echo "#define USE_RNDW32CE 1" >>confdefs.h
-
-fi
-
-
-
-
-
-
-
-LIBGCRYPT_CIPHERS=$enabled_ciphers
-
-LIBGCRYPT_PUBKEY_CIPHERS=$enabled_pubkey_ciphers
-
-LIBGCRYPT_DIGESTS=$enabled_digests
-
-
-# For printing the configuration we need a colon separated list of
-# algorithm names.
-tmp=`echo "$enabled_ciphers" | tr ' ' : `
-
-cat >>confdefs.h <<_ACEOF
-#define LIBGCRYPT_CIPHERS "$tmp"
-_ACEOF
-
-tmp=`echo "$enabled_pubkey_ciphers" | tr ' ' : `
-
-cat >>confdefs.h <<_ACEOF
-#define LIBGCRYPT_PUBKEY_CIPHERS "$tmp"
-_ACEOF
-
-tmp=`echo "$enabled_digests" | tr ' ' : `
-
-cat >>confdefs.h <<_ACEOF
-#define LIBGCRYPT_DIGESTS "$tmp"
-_ACEOF
-
-tmp=`echo "$enabled_kdfs" | tr ' ' : `
-
-cat >>confdefs.h <<_ACEOF
-#define LIBGCRYPT_KDFS "$tmp"
-_ACEOF
-
-
-
-#
-# Define conditional sources depending on the used hardware platform.
-# Note that all possible modules must also be listed in
-# src/Makefile.am (EXTRA_libgcrypt_la_SOURCES).
-#
-GCRYPT_HWF_MODULES=
-case "$mpi_cpu_arch" in
-     x86)
-
-$as_echo "#define HAVE_CPU_ARCH_X86 1" >>confdefs.h
-
-        GCRYPT_HWF_MODULES="hwf-x86.lo"
-        ;;
-     alpha)
-
-$as_echo "#define HAVE_CPU_ARCH_ALPHA 1" >>confdefs.h
-
-        ;;
-     sparc)
-
-$as_echo "#define HAVE_CPU_ARCH_SPARC 1" >>confdefs.h
-
-        ;;
-     mips)
-
-$as_echo "#define HAVE_CPU_ARCH_MIPS 1" >>confdefs.h
-
-        ;;
-     m68k)
-
-$as_echo "#define HAVE_CPU_ARCH_M68K 1" >>confdefs.h
-
-        ;;
-     ppc)
-
-$as_echo "#define HAVE_CPU_ARCH_PPC 1" >>confdefs.h
-
-        ;;
-     arm)
-
-$as_echo "#define HAVE_CPU_ARCH_ARM 1" >>confdefs.h
-
-        GCRYPT_HWF_MODULES="hwf-arm.lo"
-        ;;
-     aarch64)
-
-$as_echo "#define HAVE_CPU_ARCH_ARM 1" >>confdefs.h
-
-        GCRYPT_HWF_MODULES="hwf-arm.lo"
-        ;;
-esac
-
-
-
-#
-# Option to disable building of doc file
-#
-build_doc=yes
-# Check whether --enable-doc was given.
-if test "${enable_doc+set}" = set; then :
-  enableval=$enable_doc; build_doc=$enableval
-else
-  build_doc=yes
-fi
-
- if test "x$build_doc" != xno; then
-  BUILD_DOC_TRUE=
-  BUILD_DOC_FALSE='#'
-else
-  BUILD_DOC_TRUE='#'
-  BUILD_DOC_FALSE=
-fi
-
-
-
-#
-# Provide information about the build.
-#
-BUILD_REVISION="93775172"
-
-
-cat >>confdefs.h <<_ACEOF
-#define BUILD_REVISION "$BUILD_REVISION"
-_ACEOF
-
-
-BUILD_FILEVERSION=`echo "$VERSION" | sed 's/\([0-9.]*\).*/\1./;s/\./,/g'`
-BUILD_FILEVERSION="${BUILD_FILEVERSION}37751"
-
-
-# Check whether --enable-build-timestamp was given.
-if test "${enable_build_timestamp+set}" = set; then :
-  enableval=$enable_build_timestamp; if test "$enableval" = "yes"; then
-        BUILD_TIMESTAMP=`date -u +%Y-%m-%dT%H:%M+0000 2>/dev/null || date`
-      else
-        BUILD_TIMESTAMP="$enableval"
-      fi
-else
-  BUILD_TIMESTAMP="<none>"
-fi
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define BUILD_TIMESTAMP "$BUILD_TIMESTAMP"
-_ACEOF
-
-
-
-# And create the files.
-ac_config_files="$ac_config_files Makefile m4/Makefile compat/Makefile mpi/Makefile cipher/Makefile random/Makefile doc/Makefile src/Makefile src/gcrypt.h src/libgcrypt-config src/versioninfo.rc tests/Makefile"
-
-ac_config_files="$ac_config_files tests/hashtest-256g"
-
-ac_config_files="$ac_config_files tests/basic-disable-all-hwf"
-
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems.  If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, we kill variables containing newlines.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(
-  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
-    eval ac_val=\$$ac_var
-    case $ac_val in #(
-    *${as_nl}*)
-      case $ac_var in #(
-      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
-      esac
-      case $ac_var in #(
-      _ | IFS | as_nl) ;; #(
-      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
-      *) { eval $ac_var=; unset $ac_var;} ;;
-      esac ;;
-    esac
-  done
-
-  (set) 2>&1 |
-    case $as_nl`(ac_space=' '; set) 2>&1` in #(
-    *${as_nl}ac_space=\ *)
-      # `set' does not quote correctly, so add quotes: double-quote
-      # substitution turns \\\\ into \\, and sed turns \\ into \.
-      sed -n \
-       "s/'/'\\\\''/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
-      ;; #(
-    *)
-      # `set' quotes correctly as required by POSIX, so do not add quotes.
-      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
-      ;;
-    esac |
-    sort
-) |
-  sed '
-     /^ac_cv_env_/b end
-     t clear
-     :clear
-     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
-     t end
-     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
-     :end' >>confcache
-if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
-  if test -w "$cache_file"; then
-    if test "x$cache_file" != "x/dev/null"; then
-      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
-      if test ! -f "$cache_file" || test -h "$cache_file"; then
-       cat confcache >"$cache_file"
-      else
-        case $cache_file in #(
-        */* | ?:*)
-         mv -f confcache "$cache_file"$$ &&
-         mv -f "$cache_file"$$ "$cache_file" ;; #(
-        *)
-         mv -f confcache "$cache_file" ;;
-       esac
-      fi
-    fi
-  else
-    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
-  fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-DEFS=-DHAVE_CONFIG_H
-
-ac_libobjs=
-ac_ltlibobjs=
-U=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
-  # 1. Remove the extension, and $U if already installed.
-  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
-  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
-  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
-  #    will be set to the directory where LIBOBJS objects are built.
-  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
-  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
-$as_echo_n "checking that generated files are newer than configure... " >&6; }
-   if test -n "$am_sleep_pid"; then
-     # Hide warnings about reused PIDs.
-     wait $am_sleep_pid 2>/dev/null
-   fi
-   { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
-$as_echo "done" >&6; }
- if test -n "$EXEEXT"; then
-  am__EXEEXT_TRUE=
-  am__EXEEXT_FALSE='#'
-else
-  am__EXEEXT_TRUE='#'
-  am__EXEEXT_FALSE=
-fi
-
-if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
-  as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
-  as_fn_error $? "conditional \"AMDEP\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
-  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then
-  as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${HAVE_W32_SYSTEM_TRUE}" && test -z "${HAVE_W32_SYSTEM_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_W32_SYSTEM\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${HAVE_W32CE_SYSTEM_TRUE}" && test -z "${HAVE_W32CE_SYSTEM_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_W32CE_SYSTEM\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-
-if test -z "${USE_RANDOM_DAEMON_TRUE}" && test -z "${USE_RANDOM_DAEMON_FALSE}"; then
-  as_fn_error $? "conditional \"USE_RANDOM_DAEMON\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${ENABLE_O_FLAG_MUNGING_TRUE}" && test -z "${ENABLE_O_FLAG_MUNGING_FALSE}"; then
-  as_fn_error $? "conditional \"ENABLE_O_FLAG_MUNGING\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${HAVE_LD_VERSION_SCRIPT_TRUE}" && test -z "${HAVE_LD_VERSION_SCRIPT_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_LD_VERSION_SCRIPT\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_MPIH_ADD1_TRUE}" && test -z "${MPI_MOD_ASM_MPIH_ADD1_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_MPIH_ADD1\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_MPIH_SUB1_TRUE}" && test -z "${MPI_MOD_ASM_MPIH_SUB1_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_MPIH_SUB1\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_MPIH_MUL1_TRUE}" && test -z "${MPI_MOD_ASM_MPIH_MUL1_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_MPIH_MUL1\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_MPIH_MUL2_TRUE}" && test -z "${MPI_MOD_ASM_MPIH_MUL2_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_MPIH_MUL2\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_MPIH_MUL3_TRUE}" && test -z "${MPI_MOD_ASM_MPIH_MUL3_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_MPIH_MUL3\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_MPIH_LSHIFT_TRUE}" && test -z "${MPI_MOD_ASM_MPIH_LSHIFT_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_MPIH_LSHIFT\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_MPIH_RSHIFT_TRUE}" && test -z "${MPI_MOD_ASM_MPIH_RSHIFT_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_MPIH_RSHIFT\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_UDIV_TRUE}" && test -z "${MPI_MOD_ASM_UDIV_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_UDIV\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_ASM_UDIV_QRNND_TRUE}" && test -z "${MPI_MOD_ASM_UDIV_QRNND_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_ASM_UDIV_QRNND\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_MPIH_ADD1_TRUE}" && test -z "${MPI_MOD_C_MPIH_ADD1_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_MPIH_ADD1\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_MPIH_SUB1_TRUE}" && test -z "${MPI_MOD_C_MPIH_SUB1_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_MPIH_SUB1\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_MPIH_MUL1_TRUE}" && test -z "${MPI_MOD_C_MPIH_MUL1_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_MPIH_MUL1\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_MPIH_MUL2_TRUE}" && test -z "${MPI_MOD_C_MPIH_MUL2_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_MPIH_MUL2\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_MPIH_MUL3_TRUE}" && test -z "${MPI_MOD_C_MPIH_MUL3_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_MPIH_MUL3\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_MPIH_LSHIFT_TRUE}" && test -z "${MPI_MOD_C_MPIH_LSHIFT_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_MPIH_LSHIFT\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_MPIH_RSHIFT_TRUE}" && test -z "${MPI_MOD_C_MPIH_RSHIFT_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_MPIH_RSHIFT\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_UDIV_TRUE}" && test -z "${MPI_MOD_C_UDIV_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_UDIV\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MPI_MOD_C_UDIV_QRNND_TRUE}" && test -z "${MPI_MOD_C_UDIV_QRNND_FALSE}"; then
-  as_fn_error $? "conditional \"MPI_MOD_C_UDIV_QRNND\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${CROSS_COMPILING_TRUE}" && test -z "${CROSS_COMPILING_FALSE}"; then
-  as_fn_error $? "conditional \"CROSS_COMPILING\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${BUILD_DOC_TRUE}" && test -z "${BUILD_DOC_FALSE}"; then
-  as_fn_error $? "conditional \"BUILD_DOC\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-
-: "${CONFIG_STATUS=./config.status}"
-ac_write_fail=0
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
-as_write_fail=0
-cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-
-SHELL=\${CONFIG_SHELL-$SHELL}
-export SHELL
-_ASEOF
-cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
-## -------------------- ##
-## M4sh Initialization. ##
-## -------------------- ##
-
-# Be more Bourne compatible
-DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
-  emulate sh
-  NULLCMD=:
-  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-  setopt NO_GLOB_SUBST
-else
-  case `(set -o) 2>/dev/null` in #(
-  *posix*) :
-    set -o posix ;; #(
-  *) :
-     ;;
-esac
-fi
-
-
-as_nl='
-'
-export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
-    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
-  as_echo='print -r --'
-  as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
-  as_echo='printf %s\n'
-  as_echo_n='printf %s'
-else
-  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
-    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
-    as_echo_n='/usr/ucb/echo -n'
-  else
-    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
-    as_echo_n_body='eval
-      arg=$1;
-      case $arg in #(
-      *"$as_nl"*)
-       expr "X$arg" : "X\\(.*\\)$as_nl";
-       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
-      esac;
-      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
-    '
-    export as_echo_n_body
-    as_echo_n='sh -c $as_echo_n_body as_echo'
-  fi
-  export as_echo_body
-  as_echo='sh -c $as_echo_body as_echo'
-fi
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  PATH_SEPARATOR=:
-  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
-    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
-      PATH_SEPARATOR=';'
-  }
-fi
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.  Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" ""       $as_nl"
-
-# Find who we are.  Look in the path if we contain no directory separator.
-as_myself=
-case $0 in #((
-  *[\\/]* ) as_myself=$0 ;;
-  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-  done
-IFS=$as_save_IFS
-
-     ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
-  as_myself=$0
-fi
-if test ! -f "$as_myself"; then
-  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
-  exit 1
-fi
-
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there.  '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
-  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-
-# as_fn_error STATUS ERROR [LINENO LOG_FD]
-# ----------------------------------------
-# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
-# script with STATUS, using 1 if that was 0.
-as_fn_error ()
-{
-  as_status=$1; test $as_status -eq 0 && as_status=1
-  if test "$4"; then
-    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
-  fi
-  $as_echo "$as_me: error: $2" >&2
-  as_fn_exit $as_status
-} # as_fn_error
-
-
-# as_fn_set_status STATUS
-# -----------------------
-# Set $? to STATUS, without forking.
-as_fn_set_status ()
-{
-  return $1
-} # as_fn_set_status
-
-# as_fn_exit STATUS
-# -----------------
-# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
-as_fn_exit ()
-{
-  set +e
-  as_fn_set_status $1
-  exit $1
-} # as_fn_exit
-
-# as_fn_unset VAR
-# ---------------
-# Portably unset VAR.
-as_fn_unset ()
-{
-  { eval $1=; unset $1;}
-}
-as_unset=as_fn_unset
-# as_fn_append VAR VALUE
-# ----------------------
-# Append the text in VALUE to the end of the definition contained in VAR. Take
-# advantage of any shell optimizations that allow amortized linear growth over
-# repeated appends, instead of the typical quadratic growth present in naive
-# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
-  eval 'as_fn_append ()
-  {
-    eval $1+=\$2
-  }'
-else
-  as_fn_append ()
-  {
-    eval $1=\$$1\$2
-  }
-fi # as_fn_append
-
-# as_fn_arith ARG...
-# ------------------
-# Perform arithmetic evaluation on the ARGs, and store the result in the
-# global $as_val. Take advantage of shells that can avoid forks. The arguments
-# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
-  eval 'as_fn_arith ()
-  {
-    as_val=$(( $* ))
-  }'
-else
-  as_fn_arith ()
-  {
-    as_val=`expr "$@" || test $? -eq 1`
-  }
-fi # as_fn_arith
-
-
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
-  as_dirname=dirname
-else
-  as_dirname=false
-fi
-
-as_me=`$as_basename -- "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{
-           s//\1/
-           q
-         }
-         /^X\/\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\/\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in #(((((
--n*)
-  case `echo 'xy\c'` in
-  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
-  xy)  ECHO_C='\c';;
-  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
-       ECHO_T='        ';;
-  esac;;
-*)
-  ECHO_N='-n';;
-esac
-
-rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
-  rm -f conf$$.dir/conf$$.file
-else
-  rm -f conf$$.dir
-  mkdir conf$$.dir 2>/dev/null
-fi
-if (echo >conf$$.file) 2>/dev/null; then
-  if ln -s conf$$.file conf$$ 2>/dev/null; then
-    as_ln_s='ln -s'
-    # ... but there are two gotchas:
-    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
-    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -pR'.
-    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -pR'
-  elif ln conf$$.file conf$$ 2>/dev/null; then
-    as_ln_s=ln
-  else
-    as_ln_s='cp -pR'
-  fi
-else
-  as_ln_s='cp -pR'
-fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
-
-
-# as_fn_mkdir_p
-# -------------
-# Create "$as_dir" as a directory, including parents if necessary.
-as_fn_mkdir_p ()
-{
-
-  case $as_dir in #(
-  -*) as_dir=./$as_dir;;
-  esac
-  test -d "$as_dir" || eval $as_mkdir_p || {
-    as_dirs=
-    while :; do
-      case $as_dir in #(
-      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
-      *) as_qdir=$as_dir;;
-      esac
-      as_dirs="'$as_qdir' $as_dirs"
-      as_dir=`$as_dirname -- "$as_dir" ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$as_dir" : 'X\(//\)[^/]' \| \
-        X"$as_dir" : 'X\(//\)$' \| \
-        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-      test -d "$as_dir" && break
-    done
-    test -z "$as_dirs" || eval "mkdir $as_dirs"
-  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
-
-
-} # as_fn_mkdir_p
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p='mkdir -p "$as_dir"'
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
-  test -f "$1" && test -x "$1"
-} # as_fn_executable_p
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-exec 6>&1
-## ----------------------------------- ##
-## Main body of $CONFIG_STATUS script. ##
-## ----------------------------------- ##
-_ASEOF
-test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# Save the log message, to keep $0 and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.
-ac_log="
-This file was extended by libgcrypt $as_me 1.8.4, which was
-generated by GNU Autoconf 2.69.  Invocation command line was
-
-  CONFIG_FILES    = $CONFIG_FILES
-  CONFIG_HEADERS  = $CONFIG_HEADERS
-  CONFIG_LINKS    = $CONFIG_LINKS
-  CONFIG_COMMANDS = $CONFIG_COMMANDS
-  $ $0 $@
-
-on `(hostname || uname -n) 2>/dev/null | sed 1q`
-"
-
-_ACEOF
-
-case $ac_config_files in *"
-"*) set x $ac_config_files; shift; ac_config_files=$*;;
-esac
-
-case $ac_config_headers in *"
-"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
-esac
-
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-# Files that config.status was made for.
-config_files="$ac_config_files"
-config_headers="$ac_config_headers"
-config_links="$ac_config_links"
-config_commands="$ac_config_commands"
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-ac_cs_usage="\
-\`$as_me' instantiates files and other configuration actions
-from templates according to the current configuration.  Unless the files
-and actions are specified as TAGs, all are instantiated by default.
-
-Usage: $0 [OPTION]... [TAG]...
-
-  -h, --help       print this help, then exit
-  -V, --version    print version number and configuration settings, then exit
-      --config     print configuration, then exit
-  -q, --quiet, --silent
-                   do not print progress messages
-  -d, --debug      don't remove temporary files
-      --recheck    update $as_me by reconfiguring in the same conditions
-      --file=FILE[:TEMPLATE]
-                   instantiate the configuration file FILE
-      --header=FILE[:TEMPLATE]
-                   instantiate the configuration header FILE
-
-Configuration files:
-$config_files
-
-Configuration headers:
-$config_headers
-
-Configuration links:
-$config_links
-
-Configuration commands:
-$config_commands
-
-Report bugs to <http://bugs.gnupg.org>."
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
-ac_cs_version="\\
-libgcrypt config.status 1.8.4
-configured by $0, generated by GNU Autoconf 2.69,
-  with options \\"\$ac_cs_config\\"
-
-Copyright (C) 2012 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-
-ac_pwd='$ac_pwd'
-srcdir='$srcdir'
-INSTALL='$INSTALL'
-MKDIR_P='$MKDIR_P'
-AWK='$AWK'
-test -n "\$AWK" || AWK=awk
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# The default lists apply if the user does not specify any file.
-ac_need_defaults=:
-while test $# != 0
-do
-  case $1 in
-  --*=?*)
-    ac_option=`expr "X$1" : 'X\([^=]*\)='`
-    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
-    ac_shift=:
-    ;;
-  --*=)
-    ac_option=`expr "X$1" : 'X\([^=]*\)='`
-    ac_optarg=
-    ac_shift=:
-    ;;
-  *)
-    ac_option=$1
-    ac_optarg=$2
-    ac_shift=shift
-    ;;
-  esac
-
-  case $ac_option in
-  # Handling of the options.
-  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
-    ac_cs_recheck=: ;;
-  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
-    $as_echo "$ac_cs_version"; exit ;;
-  --config | --confi | --conf | --con | --co | --c )
-    $as_echo "$ac_cs_config"; exit ;;
-  --debug | --debu | --deb | --de | --d | -d )
-    debug=: ;;
-  --file | --fil | --fi | --f )
-    $ac_shift
-    case $ac_optarg in
-    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
-    '') as_fn_error $? "missing file argument" ;;
-    esac
-    as_fn_append CONFIG_FILES " '$ac_optarg'"
-    ac_need_defaults=false;;
-  --header | --heade | --head | --hea )
-    $ac_shift
-    case $ac_optarg in
-    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
-    esac
-    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
-    ac_need_defaults=false;;
-  --he | --h)
-    # Conflict between --help and --header
-    as_fn_error $? "ambiguous option: \`$1'
-Try \`$0 --help' for more information.";;
-  --help | --hel | -h )
-    $as_echo "$ac_cs_usage"; exit ;;
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil | --si | --s)
-    ac_cs_silent=: ;;
-
-  # This is an error.
-  -*) as_fn_error $? "unrecognized option: \`$1'
-Try \`$0 --help' for more information." ;;
-
-  *) as_fn_append ac_config_targets " $1"
-     ac_need_defaults=false ;;
-
-  esac
-  shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
-  exec 6>/dev/null
-  ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-if \$ac_cs_recheck; then
-  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-  shift
-  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
-  CONFIG_SHELL='$SHELL'
-  export CONFIG_SHELL
-  exec "\$@"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-  $as_echo "$ac_log"
-} >&5
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-#
-# INIT-COMMANDS
-#
-AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
-
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-
-sed_quote_subst='$sed_quote_subst'
-double_quote_subst='$double_quote_subst'
-delay_variable_subst='$delay_variable_subst'
-macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
-macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
-AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`'
-DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
-OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
-enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
-enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
-pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
-enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
-SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
-ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
-PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
-host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
-host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
-host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
-build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
-build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
-build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
-SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
-Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
-GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
-EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
-FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
-LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
-NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
-LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
-max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
-ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
-exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
-lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
-lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
-lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
-lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
-lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
-reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
-reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
-deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
-file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
-file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
-want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
-sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
-AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
-AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
-archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
-STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
-RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
-old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
-old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
-old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
-lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
-CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
-CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
-compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
-GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
-nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
-lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
-objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
-MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
-lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
-need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
-MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
-DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
-NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
-LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
-OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
-OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
-libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
-shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
-extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
-archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
-enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
-export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
-whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
-compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
-old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
-old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
-archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
-archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
-module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
-module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
-with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
-allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
-no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
-hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
-hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
-hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
-hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
-hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
-hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
-inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
-link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
-always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
-export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
-exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
-include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
-prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
-postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
-file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
-variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
-need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
-need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
-version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
-runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
-shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
-shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
-libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
-library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
-soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
-install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
-postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
-postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
-finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
-finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
-hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
-sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
-sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
-hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
-enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
-enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
-enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
-old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
-striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
-LD_RC='`$ECHO "$LD_RC" | $SED "$delay_single_quote_subst"`'
-reload_flag_RC='`$ECHO "$reload_flag_RC" | $SED "$delay_single_quote_subst"`'
-reload_cmds_RC='`$ECHO "$reload_cmds_RC" | $SED "$delay_single_quote_subst"`'
-old_archive_cmds_RC='`$ECHO "$old_archive_cmds_RC" | $SED "$delay_single_quote_subst"`'
-compiler_RC='`$ECHO "$compiler_RC" | $SED "$delay_single_quote_subst"`'
-GCC_RC='`$ECHO "$GCC_RC" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_no_builtin_flag_RC='`$ECHO "$lt_prog_compiler_no_builtin_flag_RC" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_pic_RC='`$ECHO "$lt_prog_compiler_pic_RC" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_wl_RC='`$ECHO "$lt_prog_compiler_wl_RC" | $SED "$delay_single_quote_subst"`'
-lt_prog_compiler_static_RC='`$ECHO "$lt_prog_compiler_static_RC" | $SED "$delay_single_quote_subst"`'
-lt_cv_prog_compiler_c_o_RC='`$ECHO "$lt_cv_prog_compiler_c_o_RC" | $SED "$delay_single_quote_subst"`'
-archive_cmds_need_lc_RC='`$ECHO "$archive_cmds_need_lc_RC" | $SED "$delay_single_quote_subst"`'
-enable_shared_with_static_runtimes_RC='`$ECHO "$enable_shared_with_static_runtimes_RC" | $SED "$delay_single_quote_subst"`'
-export_dynamic_flag_spec_RC='`$ECHO "$export_dynamic_flag_spec_RC" | $SED "$delay_single_quote_subst"`'
-whole_archive_flag_spec_RC='`$ECHO "$whole_archive_flag_spec_RC" | $SED "$delay_single_quote_subst"`'
-compiler_needs_object_RC='`$ECHO "$compiler_needs_object_RC" | $SED "$delay_single_quote_subst"`'
-old_archive_from_new_cmds_RC='`$ECHO "$old_archive_from_new_cmds_RC" | $SED "$delay_single_quote_subst"`'
-old_archive_from_expsyms_cmds_RC='`$ECHO "$old_archive_from_expsyms_cmds_RC" | $SED "$delay_single_quote_subst"`'
-archive_cmds_RC='`$ECHO "$archive_cmds_RC" | $SED "$delay_single_quote_subst"`'
-archive_expsym_cmds_RC='`$ECHO "$archive_expsym_cmds_RC" | $SED "$delay_single_quote_subst"`'
-module_cmds_RC='`$ECHO "$module_cmds_RC" | $SED "$delay_single_quote_subst"`'
-module_expsym_cmds_RC='`$ECHO "$module_expsym_cmds_RC" | $SED "$delay_single_quote_subst"`'
-with_gnu_ld_RC='`$ECHO "$with_gnu_ld_RC" | $SED "$delay_single_quote_subst"`'
-allow_undefined_flag_RC='`$ECHO "$allow_undefined_flag_RC" | $SED "$delay_single_quote_subst"`'
-no_undefined_flag_RC='`$ECHO "$no_undefined_flag_RC" | $SED "$delay_single_quote_subst"`'
-hardcode_libdir_flag_spec_RC='`$ECHO "$hardcode_libdir_flag_spec_RC" | $SED "$delay_single_quote_subst"`'
-hardcode_libdir_separator_RC='`$ECHO "$hardcode_libdir_separator_RC" | $SED "$delay_single_quote_subst"`'
-hardcode_direct_RC='`$ECHO "$hardcode_direct_RC" | $SED "$delay_single_quote_subst"`'
-hardcode_direct_absolute_RC='`$ECHO "$hardcode_direct_absolute_RC" | $SED "$delay_single_quote_subst"`'
-hardcode_minus_L_RC='`$ECHO "$hardcode_minus_L_RC" | $SED "$delay_single_quote_subst"`'
-hardcode_shlibpath_var_RC='`$ECHO "$hardcode_shlibpath_var_RC" | $SED "$delay_single_quote_subst"`'
-hardcode_automatic_RC='`$ECHO "$hardcode_automatic_RC" | $SED "$delay_single_quote_subst"`'
-inherit_rpath_RC='`$ECHO "$inherit_rpath_RC" | $SED "$delay_single_quote_subst"`'
-link_all_deplibs_RC='`$ECHO "$link_all_deplibs_RC" | $SED "$delay_single_quote_subst"`'
-always_export_symbols_RC='`$ECHO "$always_export_symbols_RC" | $SED "$delay_single_quote_subst"`'
-export_symbols_cmds_RC='`$ECHO "$export_symbols_cmds_RC" | $SED "$delay_single_quote_subst"`'
-exclude_expsyms_RC='`$ECHO "$exclude_expsyms_RC" | $SED "$delay_single_quote_subst"`'
-include_expsyms_RC='`$ECHO "$include_expsyms_RC" | $SED "$delay_single_quote_subst"`'
-prelink_cmds_RC='`$ECHO "$prelink_cmds_RC" | $SED "$delay_single_quote_subst"`'
-postlink_cmds_RC='`$ECHO "$postlink_cmds_RC" | $SED "$delay_single_quote_subst"`'
-file_list_spec_RC='`$ECHO "$file_list_spec_RC" | $SED "$delay_single_quote_subst"`'
-hardcode_action_RC='`$ECHO "$hardcode_action_RC" | $SED "$delay_single_quote_subst"`'
-
-LTCC='$LTCC'
-LTCFLAGS='$LTCFLAGS'
-compiler='$compiler_DEFAULT'
-
-# A function that is used when there is no print builtin or printf.
-func_fallback_echo ()
-{
-  eval 'cat <<_LTECHO_EOF
-\$1
-_LTECHO_EOF'
-}
-
-# Quote evaled strings.
-for var in AS \
-DLLTOOL \
-OBJDUMP \
-SHELL \
-ECHO \
-PATH_SEPARATOR \
-SED \
-GREP \
-EGREP \
-FGREP \
-LD \
-NM \
-LN_S \
-lt_SP2NL \
-lt_NL2SP \
-reload_flag \
-deplibs_check_method \
-file_magic_cmd \
-file_magic_glob \
-want_nocaseglob \
-sharedlib_from_linklib_cmd \
-AR \
-AR_FLAGS \
-archiver_list_spec \
-STRIP \
-RANLIB \
-CC \
-CFLAGS \
-compiler \
-lt_cv_sys_global_symbol_pipe \
-lt_cv_sys_global_symbol_to_cdecl \
-lt_cv_sys_global_symbol_to_c_name_address \
-lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
-nm_file_list_spec \
-lt_prog_compiler_no_builtin_flag \
-lt_prog_compiler_pic \
-lt_prog_compiler_wl \
-lt_prog_compiler_static \
-lt_cv_prog_compiler_c_o \
-need_locks \
-MANIFEST_TOOL \
-DSYMUTIL \
-NMEDIT \
-LIPO \
-OTOOL \
-OTOOL64 \
-shrext_cmds \
-export_dynamic_flag_spec \
-whole_archive_flag_spec \
-compiler_needs_object \
-with_gnu_ld \
-allow_undefined_flag \
-no_undefined_flag \
-hardcode_libdir_flag_spec \
-hardcode_libdir_separator \
-exclude_expsyms \
-include_expsyms \
-file_list_spec \
-variables_saved_for_relink \
-libname_spec \
-library_names_spec \
-soname_spec \
-install_override_mode \
-finish_eval \
-old_striplib \
-striplib \
-LD_RC \
-reload_flag_RC \
-compiler_RC \
-lt_prog_compiler_no_builtin_flag_RC \
-lt_prog_compiler_pic_RC \
-lt_prog_compiler_wl_RC \
-lt_prog_compiler_static_RC \
-lt_cv_prog_compiler_c_o_RC \
-export_dynamic_flag_spec_RC \
-whole_archive_flag_spec_RC \
-compiler_needs_object_RC \
-with_gnu_ld_RC \
-allow_undefined_flag_RC \
-no_undefined_flag_RC \
-hardcode_libdir_flag_spec_RC \
-hardcode_libdir_separator_RC \
-exclude_expsyms_RC \
-include_expsyms_RC \
-file_list_spec_RC; do
-    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
-    *[\\\\\\\`\\"\\\$]*)
-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
-      ;;
-    *)
-      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
-      ;;
-    esac
-done
-
-# Double-quote double-evaled strings.
-for var in reload_cmds \
-old_postinstall_cmds \
-old_postuninstall_cmds \
-old_archive_cmds \
-extract_expsyms_cmds \
-old_archive_from_new_cmds \
-old_archive_from_expsyms_cmds \
-archive_cmds \
-archive_expsym_cmds \
-module_cmds \
-module_expsym_cmds \
-export_symbols_cmds \
-prelink_cmds \
-postlink_cmds \
-postinstall_cmds \
-postuninstall_cmds \
-finish_cmds \
-sys_lib_search_path_spec \
-sys_lib_dlsearch_path_spec \
-reload_cmds_RC \
-old_archive_cmds_RC \
-old_archive_from_new_cmds_RC \
-old_archive_from_expsyms_cmds_RC \
-archive_cmds_RC \
-archive_expsym_cmds_RC \
-module_cmds_RC \
-module_expsym_cmds_RC \
-export_symbols_cmds_RC \
-prelink_cmds_RC \
-postlink_cmds_RC; do
-    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
-    *[\\\\\\\`\\"\\\$]*)
-      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
-      ;;
-    *)
-      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
-      ;;
-    esac
-done
-
-ac_aux_dir='$ac_aux_dir'
-xsi_shell='$xsi_shell'
-lt_shell_append='$lt_shell_append'
-
-# See if we are running on zsh, and set the options which allow our
-# commands through without removal of \ escapes INIT.
-if test -n "\${ZSH_VERSION+set}" ; then
-   setopt NO_GLOB_SUBST
-fi
-
-
-    PACKAGE='$PACKAGE'
-    VERSION='$VERSION'
-    TIMESTAMP='$TIMESTAMP'
-    RM='$RM'
-    ofile='$ofile'
-
-
-
-
-
-
-prefix=$prefix
-exec_prefix=$exec_prefix
-libdir=$libdir
-datadir=$datadir
-DATADIRNAME=$DATADIRNAME
-
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-
-# Handling of arguments.
-for ac_config_target in $ac_config_targets
-do
-  case $ac_config_target in
-    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
-    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
-    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
-    ""$mpi_ln_list"") CONFIG_LINKS="$CONFIG_LINKS "$mpi_ln_list"" ;;
-    "gcrypt-conf") CONFIG_COMMANDS="$CONFIG_COMMANDS gcrypt-conf" ;;
-    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-    "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;;
-    "compat/Makefile") CONFIG_FILES="$CONFIG_FILES compat/Makefile" ;;
-    "mpi/Makefile") CONFIG_FILES="$CONFIG_FILES mpi/Makefile" ;;
-    "cipher/Makefile") CONFIG_FILES="$CONFIG_FILES cipher/Makefile" ;;
-    "random/Makefile") CONFIG_FILES="$CONFIG_FILES random/Makefile" ;;
-    "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
-    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
-    "src/gcrypt.h") CONFIG_FILES="$CONFIG_FILES src/gcrypt.h" ;;
-    "src/libgcrypt-config") CONFIG_FILES="$CONFIG_FILES src/libgcrypt-config" ;;
-    "src/versioninfo.rc") CONFIG_FILES="$CONFIG_FILES src/versioninfo.rc" ;;
-    "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
-    "tests/hashtest-256g") CONFIG_FILES="$CONFIG_FILES tests/hashtest-256g" ;;
-    "tests/basic-disable-all-hwf") CONFIG_FILES="$CONFIG_FILES tests/basic-disable-all-hwf" ;;
-
-  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
-  esac
-done
-
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used.  Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
-  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
-  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
-  test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
-  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
-fi
-
-# Have a temporary directory for convenience.  Make it in the build tree
-# simply because there is no reason against having it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Hook for its removal unless debugging.
-# Note that there is a small window in which the directory will not be cleaned:
-# after its creation but before its name has been assigned to `$tmp'.
-$debug ||
-{
-  tmp= ac_tmp=
-  trap 'exit_status=$?
-  : "${ac_tmp:=$tmp}"
-  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
-' 0
-  trap 'as_fn_exit 1' 1 2 13 15
-}
-# Create a (secure) tmp directory for tmp files.
-
-{
-  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
-  test -d "$tmp"
-}  ||
-{
-  tmp=./conf$$-$RANDOM
-  (umask 077 && mkdir "$tmp")
-} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
-ac_tmp=$tmp
-
-# Set up the scripts for CONFIG_FILES section.
-# No need to generate them if there are no CONFIG_FILES.
-# This happens for instance with `./config.status config.h'.
-if test -n "$CONFIG_FILES"; then
-
-
-ac_cr=`echo X | tr X '\015'`
-# On cygwin, bash can eat \r inside `` if the user requested igncr.
-# But we know of no other shell where ac_cr would be empty at this
-# point, so we can use a bashism as a fallback.
-if test "x$ac_cr" = x; then
-  eval ac_cr=\$\'\\r\'
-fi
-ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
-if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
-  ac_cs_awk_cr='\\r'
-else
-  ac_cs_awk_cr=$ac_cr
-fi
-
-echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
-_ACEOF
-
-
-{
-  echo "cat >conf$$subs.awk <<_ACEOF" &&
-  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
-  echo "_ACEOF"
-} >conf$$subs.sh ||
-  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
-ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
-  . ./conf$$subs.sh ||
-    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
-
-  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
-  if test $ac_delim_n = $ac_delim_num; then
-    break
-  elif $ac_last_try; then
-    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
-  else
-    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
-  fi
-done
-rm -f conf$$subs.sh
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
-_ACEOF
-sed -n '
-h
-s/^/S["/; s/!.*/"]=/
-p
-g
-s/^[^!]*!//
-:repl
-t repl
-s/'"$ac_delim"'$//
-t delim
-:nl
-h
-s/\(.\{148\}\)..*/\1/
-t more1
-s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
-p
-n
-b repl
-:more1
-s/["\\]/\\&/g; s/^/"/; s/$/"\\/
-p
-g
-s/.\{148\}//
-t nl
-:delim
-h
-s/\(.\{148\}\)..*/\1/
-t more2
-s/["\\]/\\&/g; s/^/"/; s/$/"/
-p
-b
-:more2
-s/["\\]/\\&/g; s/^/"/; s/$/"\\/
-p
-g
-s/.\{148\}//
-t delim
-' <conf$$subs.awk | sed '
-/^[^""]/{
-  N
-  s/\n//
-}
-' >>$CONFIG_STATUS || ac_write_fail=1
-rm -f conf$$subs.awk
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-_ACAWK
-cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
-  for (key in S) S_is_set[key] = 1
-  FS = "\a"
-
-}
-{
-  line = $ 0
-  nfields = split(line, field, "@")
-  substed = 0
-  len = length(field[1])
-  for (i = 2; i < nfields; i++) {
-    key = field[i]
-    keylen = length(key)
-    if (S_is_set[key]) {
-      value = S[key]
-      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
-      len += length(value) + length(field[++i])
-      substed = 1
-    } else
-      len += 1 + keylen
-  }
-
-  print line
-}
-
-_ACAWK
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
-  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
-else
-  cat
-fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
-  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
-_ACEOF
-
-# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
-# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
-  ac_vpsub='/^[         ]*VPATH[        ]*=[    ]*/{
-h
-s///
-s/^/:/
-s/[     ]*$/:/
-s/:\$(srcdir):/:/g
-s/:\${srcdir}:/:/g
-s/:@srcdir@:/:/g
-s/^:*//
-s/:*$//
-x
-s/\(=[  ]*\).*/\1/
-G
-s/\n//
-s/^[^=]*=[      ]*$//
-}'
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-fi # test -n "$CONFIG_FILES"
-
-# Set up the scripts for CONFIG_HEADERS section.
-# No need to generate them if there are no CONFIG_HEADERS.
-# This happens for instance with `./config.status Makefile'.
-if test -n "$CONFIG_HEADERS"; then
-cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
-BEGIN {
-_ACEOF
-
-# Transform confdefs.h into an awk script `defines.awk', embedded as
-# here-document in config.status, that substitutes the proper values into
-# config.h.in to produce config.h.
-
-# Create a delimiter string that does not exist in confdefs.h, to ease
-# handling of long lines.
-ac_delim='%!_!# '
-for ac_last_try in false false :; do
-  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
-  if test -z "$ac_tt"; then
-    break
-  elif $ac_last_try; then
-    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
-  else
-    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
-  fi
-done
-
-# For the awk script, D is an array of macro values keyed by name,
-# likewise P contains macro parameters if any.  Preserve backslash
-# newline sequences.
-
-ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
-sed -n '
-s/.\{148\}/&'"$ac_delim"'/g
-t rset
-:rset
-s/^[    ]*#[    ]*define[       ][      ]*/ /
-t def
-d
-:def
-s/\\$//
-t bsnl
-s/["\\]/\\&/g
-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
-D["\1"]=" \3"/p
-s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2"/p
-d
-:bsnl
-s/["\\]/\\&/g
-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
-D["\1"]=" \3\\\\\\n"\\/p
-t cont
-s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
-t cont
-d
-:cont
-n
-s/.\{148\}/&'"$ac_delim"'/g
-t clear
-:clear
-s/\\$//
-t bsnlc
-s/["\\]/\\&/g; s/^/"/; s/$/"/p
-d
-:bsnlc
-s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
-b cont
-' <confdefs.h | sed '
-s/'"$ac_delim"'/"\\\
-"/g' >>$CONFIG_STATUS || ac_write_fail=1
-
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-  for (key in D) D_is_set[key] = 1
-  FS = "\a"
-}
-/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
-  line = \$ 0
-  split(line, arg, " ")
-  if (arg[1] == "#") {
-    defundef = arg[2]
-    mac1 = arg[3]
-  } else {
-    defundef = substr(arg[1], 2)
-    mac1 = arg[2]
-  }
-  split(mac1, mac2, "(") #)
-  macro = mac2[1]
-  prefix = substr(line, 1, index(line, defundef) - 1)
-  if (D_is_set[macro]) {
-    # Preserve the white space surrounding the "#".
-    print prefix "define", macro P[macro] D[macro]
-    next
-  } else {
-    # Replace #undef with comments.  This is necessary, for example,
-    # in the case of _POSIX_SOURCE, which is predefined and required
-    # on some systems where configure will not decide to define it.
-    if (defundef == "undef") {
-      print "/*", prefix defundef, macro, "*/"
-      next
-    }
-  }
-}
-{ print }
-_ACAWK
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
-fi # test -n "$CONFIG_HEADERS"
-
-
-eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS  :L $CONFIG_LINKS  :C $CONFIG_COMMANDS"
-shift
-for ac_tag
-do
-  case $ac_tag in
-  :[FHLC]) ac_mode=$ac_tag; continue;;
-  esac
-  case $ac_mode$ac_tag in
-  :[FHL]*:*);;
-  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
-  :[FH]-) ac_tag=-:-;;
-  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
-  esac
-  ac_save_IFS=$IFS
-  IFS=:
-  set x $ac_tag
-  IFS=$ac_save_IFS
-  shift
-  ac_file=$1
-  shift
-
-  case $ac_mode in
-  :L) ac_source=$1;;
-  :[FH])
-    ac_file_inputs=
-    for ac_f
-    do
-      case $ac_f in
-      -) ac_f="$ac_tmp/stdin";;
-      *) # Look for the file first in the build tree, then in the source tree
-        # (if the path is not absolute).  The absolute path cannot be DOS-style,
-        # because $ac_f cannot contain `:'.
-        test -f "$ac_f" ||
-          case $ac_f in
-          [\\/$]*) false;;
-          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
-          esac ||
-          as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
-      esac
-      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
-      as_fn_append ac_file_inputs " '$ac_f'"
-    done
-
-    # Let's still pretend it is `configure' which instantiates (i.e., don't
-    # use $as_me), people would be surprised to read:
-    #    /* config.h.  Generated by config.status.  */
-    configure_input='Generated from '`
-         $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
-       `' by configure.'
-    if test x"$ac_file" != x-; then
-      configure_input="$ac_file.  $configure_input"
-      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
-    fi
-    # Neutralize special characters interpreted by sed in replacement strings.
-    case $configure_input in #(
-    *\&* | *\|* | *\\* )
-       ac_sed_conf_input=`$as_echo "$configure_input" |
-       sed 's/[\\\\&|]/\\\\&/g'`;; #(
-    *) ac_sed_conf_input=$configure_input;;
-    esac
-
-    case $ac_tag in
-    *:-:* | *:-) cat >"$ac_tmp/stdin" \
-      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
-    esac
-    ;;
-  esac
-
-  ac_dir=`$as_dirname -- "$ac_file" ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$ac_file" : 'X\(//\)[^/]' \| \
-        X"$ac_file" : 'X\(//\)$' \| \
-        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-  as_dir="$ac_dir"; as_fn_mkdir_p
-  ac_builddir=.
-
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
-  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
-  # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
-  case $ac_top_builddir_sub in
-  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
-  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
-  esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
-
-case $srcdir in
-  .)  # We are building in place.
-    ac_srcdir=.
-    ac_top_srcdir=$ac_top_builddir_sub
-    ac_abs_top_srcdir=$ac_pwd ;;
-  [\\/]* | ?:[\\/]* )  # Absolute name.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir
-    ac_abs_top_srcdir=$srcdir ;;
-  *) # Relative name.
-    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_build_prefix$srcdir
-    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
-esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
-
-  case $ac_mode in
-  :F)
-  #
-  # CONFIG_FILE
-  #
-
-  case $INSTALL in
-  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
-  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
-  esac
-  ac_MKDIR_P=$MKDIR_P
-  case $MKDIR_P in
-  [\\/$]* | ?:[\\/]* ) ;;
-  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
-  esac
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-# If the template does not know about datarootdir, expand it.
-# FIXME: This hack should be removed a few years after 2.60.
-ac_datarootdir_hack=; ac_datarootdir_seen=
-ac_sed_dataroot='
-/datarootdir/ {
-  p
-  q
-}
-/@datadir@/p
-/@docdir@/p
-/@infodir@/p
-/@localedir@/p
-/@mandir@/p'
-case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
-*datarootdir*) ac_datarootdir_seen=yes;;
-*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
-  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-  ac_datarootdir_hack='
-  s&@datadir@&$datadir&g
-  s&@docdir@&$docdir&g
-  s&@infodir@&$infodir&g
-  s&@localedir@&$localedir&g
-  s&@mandir@&$mandir&g
-  s&\\\${datarootdir}&$datarootdir&g' ;;
-esac
-_ACEOF
-
-# Neutralize VPATH when `$srcdir' = `.'.
-# Shell code in configure.ac might set extrasub.
-# FIXME: do we really want to maintain this feature?
-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_sed_extra="$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s|@configure_input@|$ac_sed_conf_input|;t t
-s&@top_builddir@&$ac_top_builddir_sub&;t t
-s&@top_build_prefix@&$ac_top_build_prefix&;t t
-s&@srcdir@&$ac_srcdir&;t t
-s&@abs_srcdir@&$ac_abs_srcdir&;t t
-s&@top_srcdir@&$ac_top_srcdir&;t t
-s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
-s&@builddir@&$ac_builddir&;t t
-s&@abs_builddir@&$ac_abs_builddir&;t t
-s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
-s&@INSTALL@&$ac_INSTALL&;t t
-s&@MKDIR_P@&$ac_MKDIR_P&;t t
-$ac_datarootdir_hack
-"
-eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
-  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
-
-test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
-  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
-  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' \
-      "$ac_tmp/out"`; test -z "$ac_out"; } &&
-  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined.  Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined.  Please make sure it is defined" >&2;}
-
-  rm -f "$ac_tmp/stdin"
-  case $ac_file in
-  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
-  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
-  esac \
-  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
- ;;
-  :H)
-  #
-  # CONFIG_HEADER
-  #
-  if test x"$ac_file" != x-; then
-    {
-      $as_echo "/* $configure_input  */" \
-      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
-    } >"$ac_tmp/config.h" \
-      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
-    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
-      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
-$as_echo "$as_me: $ac_file is unchanged" >&6;}
-    else
-      rm -f "$ac_file"
-      mv "$ac_tmp/config.h" "$ac_file" \
-       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
-    fi
-  else
-    $as_echo "/* $configure_input  */" \
-      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
-      || as_fn_error $? "could not create -" "$LINENO" 5
-  fi
-# Compute "$ac_file"'s index in $config_headers.
-_am_arg="$ac_file"
-_am_stamp_count=1
-for _am_header in $config_headers :; do
-  case $_am_header in
-    $_am_arg | $_am_arg:* )
-      break ;;
-    * )
-      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
-  esac
-done
-echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
-$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$_am_arg" : 'X\(//\)[^/]' \| \
-        X"$_am_arg" : 'X\(//\)$' \| \
-        X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$_am_arg" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`/stamp-h$_am_stamp_count
- ;;
-  :L)
-  #
-  # CONFIG_LINK
-  #
-
-  if test "$ac_source" = "$ac_file" && test "$srcdir" = '.'; then
-    :
-  else
-    # Prefer the file from the source tree if names are identical.
-    if test "$ac_source" = "$ac_file" || test ! -r "$ac_source"; then
-      ac_source=$srcdir/$ac_source
-    fi
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: linking $ac_source to $ac_file" >&5
-$as_echo "$as_me: linking $ac_source to $ac_file" >&6;}
-
-    if test ! -r "$ac_source"; then
-      as_fn_error $? "$ac_source: file not found" "$LINENO" 5
-    fi
-    rm -f "$ac_file"
-
-    # Try a relative symlink, then a hard link, then a copy.
-    case $ac_source in
-    [\\/$]* | ?:[\\/]* ) ac_rel_source=$ac_source ;;
-       *) ac_rel_source=$ac_top_build_prefix$ac_source ;;
-    esac
-    ln -s "$ac_rel_source" "$ac_file" 2>/dev/null ||
-      ln "$ac_source" "$ac_file" 2>/dev/null ||
-      cp -p "$ac_source" "$ac_file" ||
-      as_fn_error $? "cannot link or copy $ac_source to $ac_file" "$LINENO" 5
-  fi
- ;;
-  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
-$as_echo "$as_me: executing $ac_file commands" >&6;}
- ;;
-  esac
-
-
-  case $ac_file$ac_mode in
-    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
-  # Older Autoconf quotes --file arguments for eval, but not when files
-  # are listed without --file.  Let's play safe and only enable the eval
-  # if we detect the quoting.
-  case $CONFIG_FILES in
-  *\'*) eval set x "$CONFIG_FILES" ;;
-  *)   set x $CONFIG_FILES ;;
-  esac
-  shift
-  for mf
-  do
-    # Strip MF so we end up with the name of the file.
-    mf=`echo "$mf" | sed -e 's/:.*$//'`
-    # Check whether this is an Automake generated Makefile or not.
-    # We used to match only the files named 'Makefile.in', but
-    # some people rename them; so instead we look at the file content.
-    # Grep'ing the first line is not enough: some people post-process
-    # each Makefile.in and add a new line on top of each file to say so.
-    # Grep'ing the whole file is not good either: AIX grep has a line
-    # limit of 2048, but all sed's we know have understand at least 4000.
-    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
-      dirpart=`$as_dirname -- "$mf" ||
-$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$mf" : 'X\(//\)[^/]' \| \
-        X"$mf" : 'X\(//\)$' \| \
-        X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$mf" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-    else
-      continue
-    fi
-    # Extract the definition of DEPDIR, am__include, and am__quote
-    # from the Makefile without running 'make'.
-    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
-    test -z "$DEPDIR" && continue
-    am__include=`sed -n 's/^am__include = //p' < "$mf"`
-    test -z "$am__include" && continue
-    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
-    # Find all dependency output files, they are included files with
-    # $(DEPDIR) in their names.  We invoke sed twice because it is the
-    # simplest approach to changing $(DEPDIR) to its actual value in the
-    # expansion.
-    for file in `sed -n "
-      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
-        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
-      # Make sure the directory exists.
-      test -f "$dirpart/$file" && continue
-      fdir=`$as_dirname -- "$file" ||
-$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$file" : 'X\(//\)[^/]' \| \
-        X"$file" : 'X\(//\)$' \| \
-        X"$file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-      as_dir=$dirpart/$fdir; as_fn_mkdir_p
-      # echo "creating $dirpart/$file"
-      echo '# dummy' > "$dirpart/$file"
-    done
-  done
-}
- ;;
-    "libtool":C)
-
-    # See if we are running on zsh, and set the options which allow our
-    # commands through without removal of \ escapes.
-    if test -n "${ZSH_VERSION+set}" ; then
-      setopt NO_GLOB_SUBST
-    fi
-
-    cfgfile="${ofile}T"
-    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
-    $RM "$cfgfile"
-
-    cat <<_LT_EOF >> "$cfgfile"
-#! $SHELL
-
-# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
-# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-# NOTE: Changes made to this file will be lost: look at ltmain.sh.
-#
-#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
-#                 Foundation, Inc.
-#   Written by Gordon Matzigkeit, 1996
-#
-#   This file is part of GNU Libtool.
-#
-# GNU Libtool is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; either version 2 of
-# the License, or (at your option) any later version.
-#
-# As a special exception to the GNU General Public License,
-# if you distribute this file as part of a program or library that
-# is built using GNU Libtool, you may include this file under the
-# same distribution terms that you use for the rest of that program.
-#
-# GNU Libtool is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GNU Libtool; see the file COPYING.  If not, a copy
-# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
-# obtained by writing to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-
-# The names of the tagged configurations supported by this script.
-available_tags="RC "
-
-# ### BEGIN LIBTOOL CONFIG
-
-# Which release of libtool.m4 was used?
-macro_version=$macro_version
-macro_revision=$macro_revision
-
-# Assembler program.
-AS=$lt_AS
-
-# DLL creation program.
-DLLTOOL=$lt_DLLTOOL
-
-# Object dumper program.
-OBJDUMP=$lt_OBJDUMP
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# What type of objects to build.
-pic_mode=$pic_mode
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# Shell to use when invoking shell scripts.
-SHELL=$lt_SHELL
-
-# An echo program that protects backslashes.
-ECHO=$lt_ECHO
-
-# The PATH separator for the build system.
-PATH_SEPARATOR=$lt_PATH_SEPARATOR
-
-# The host system.
-host_alias=$host_alias
-host=$host
-host_os=$host_os
-
-# The build system.
-build_alias=$build_alias
-build=$build
-build_os=$build_os
-
-# A sed program that does not truncate output.
-SED=$lt_SED
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="\$SED -e 1s/^X//"
-
-# A grep program that handles long lines.
-GREP=$lt_GREP
-
-# An ERE matcher.
-EGREP=$lt_EGREP
-
-# A literal string matcher.
-FGREP=$lt_FGREP
-
-# A BSD- or MS-compatible name lister.
-NM=$lt_NM
-
-# Whether we need soft or hard links.
-LN_S=$lt_LN_S
-
-# What is the maximum length of a command?
-max_cmd_len=$max_cmd_len
-
-# Object file suffix (normally "o").
-objext=$ac_objext
-
-# Executable file suffix (normally "").
-exeext=$exeext
-
-# whether the shell understands "unset".
-lt_unset=$lt_unset
-
-# turn spaces into newlines.
-SP2NL=$lt_lt_SP2NL
-
-# turn newlines into spaces.
-NL2SP=$lt_lt_NL2SP
-
-# convert \$build file names to \$host format.
-to_host_file_cmd=$lt_cv_to_host_file_cmd
-
-# convert \$build files to toolchain format.
-to_tool_file_cmd=$lt_cv_to_tool_file_cmd
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$lt_deplibs_check_method
-
-# Command to use when deplibs_check_method = "file_magic".
-file_magic_cmd=$lt_file_magic_cmd
-
-# How to find potential files when deplibs_check_method = "file_magic".
-file_magic_glob=$lt_file_magic_glob
-
-# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
-want_nocaseglob=$lt_want_nocaseglob
-
-# Command to associate shared and link libraries.
-sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
-
-# The archiver.
-AR=$lt_AR
-
-# Flags to create an archive.
-AR_FLAGS=$lt_AR_FLAGS
-
-# How to feed a file listing to the archiver.
-archiver_list_spec=$lt_archiver_list_spec
-
-# A symbol stripping program.
-STRIP=$lt_STRIP
-
-# Commands used to install an old-style archive.
-RANLIB=$lt_RANLIB
-old_postinstall_cmds=$lt_old_postinstall_cmds
-old_postuninstall_cmds=$lt_old_postuninstall_cmds
-
-# Whether to use a lock for old archive extraction.
-lock_old_archive_extraction=$lock_old_archive_extraction
-
-# A C compiler.
-LTCC=$lt_CC
-
-# LTCC compiler flags.
-LTCFLAGS=$lt_CFLAGS
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration.
-global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
-
-# Transform the output of nm in a C name address pair.
-global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
-
-# Transform the output of nm in a C name address pair when lib prefix is needed.
-global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
-
-# Specify filename containing input files for \$NM.
-nm_file_list_spec=$lt_nm_file_list_spec
-
-# The root where to search for dependent libraries,and in which our libraries should be installed.
-lt_sysroot=$lt_sysroot
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# Used to examine libraries when file_magic_cmd begins with "file".
-MAGIC_CMD=$MAGIC_CMD
-
-# Must we lock files when doing compilation?
-need_locks=$lt_need_locks
-
-# Manifest tool.
-MANIFEST_TOOL=$lt_MANIFEST_TOOL
-
-# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
-DSYMUTIL=$lt_DSYMUTIL
-
-# Tool to change global to local symbols on Mac OS X.
-NMEDIT=$lt_NMEDIT
-
-# Tool to manipulate fat objects and archives on Mac OS X.
-LIPO=$lt_LIPO
-
-# ldd/readelf like tool for Mach-O binaries on Mac OS X.
-OTOOL=$lt_OTOOL
-
-# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
-OTOOL64=$lt_OTOOL64
-
-# Old archive suffix (normally "a").
-libext=$libext
-
-# Shared library suffix (normally ".so").
-shrext_cmds=$lt_shrext_cmds
-
-# The commands to extract the exported symbol list from a shared archive.
-extract_expsyms_cmds=$lt_extract_expsyms_cmds
-
-# Variables whose values should be saved in libtool wrapper scripts and
-# restored at link time.
-variables_saved_for_relink=$lt_variables_saved_for_relink
-
-# Do we need the "lib" prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Library versioning type.
-version_type=$version_type
-
-# Shared library runtime path variable.
-runpath_var=$runpath_var
-
-# Shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# Format of library name prefix.
-libname_spec=$lt_libname_spec
-
-# List of archive names.  First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME
-library_names_spec=$lt_library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$lt_soname_spec
-
-# Permission mode override for installation of shared libraries.
-install_override_mode=$lt_install_override_mode
-
-# Command to use after installation of a shared archive.
-postinstall_cmds=$lt_postinstall_cmds
-
-# Command to use after uninstallation of a shared archive.
-postuninstall_cmds=$lt_postuninstall_cmds
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$lt_finish_cmds
-
-# As "finish_cmds", except a single script fragment to be evaled but
-# not shown.
-finish_eval=$lt_finish_eval
-
-# Whether we should hardcode library paths into libraries.
-hardcode_into_libs=$hardcode_into_libs
-
-# Compile-time system search path for libraries.
-sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
-
-# Run-time system search path for libraries.
-sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
-
-# Whether dlopen is supported.
-dlopen_support=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Commands to strip libraries.
-old_striplib=$lt_old_striplib
-striplib=$lt_striplib
-
-
-# The linker used to build libraries.
-LD=$lt_LD
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag
-reload_cmds=$lt_reload_cmds
-
-# Commands used to build an old-style archive.
-old_archive_cmds=$lt_old_archive_cmds
-
-# A language specific compiler.
-CC=$lt_compiler
-
-# Is the compiler the GNU compiler?
-with_gcc=$GCC
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc
-
-# Whether or not to disallow shared libs when runtime libs are static.
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec
-
-# Whether the compiler copes with passing no objects directly.
-compiler_needs_object=$lt_compiler_needs_object
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
-
-# Commands used to build a shared archive.
-archive_cmds=$lt_archive_cmds
-archive_expsym_cmds=$lt_archive_expsym_cmds
-
-# Commands used to build a loadable module if different from building
-# a shared archive.
-module_cmds=$lt_module_cmds
-module_expsym_cmds=$lt_module_expsym_cmds
-
-# Whether we are building with GNU ld or not.
-with_gnu_ld=$lt_with_gnu_ld
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag
-
-# Flag that enforces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
-
-# Whether we need a single "-rpath" flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator
-
-# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
-# DIR into the resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
-# DIR into the resulting binary and the resulting library dependency is
-# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
-# library is relocated.
-hardcode_direct_absolute=$hardcode_direct_absolute
-
-# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
-# into the resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
-# into the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Set to "yes" if building a shared library automatically hardcodes DIR
-# into the library and all subsequent libraries and executables linked
-# against it.
-hardcode_automatic=$hardcode_automatic
-
-# Set to yes if linker adds runtime paths of dependent libraries
-# to runtime path list.
-inherit_rpath=$inherit_rpath
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs
-
-# Set to "yes" if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms
-
-# Commands necessary for linking programs (against libraries) with templates.
-prelink_cmds=$lt_prelink_cmds
-
-# Commands necessary for finishing linking programs.
-postlink_cmds=$lt_postlink_cmds
-
-# Specify filename containing input files.
-file_list_spec=$lt_file_list_spec
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# ### END LIBTOOL CONFIG
-
-_LT_EOF
-
-  case $host_os in
-  aix3*)
-    cat <<\_LT_EOF >> "$cfgfile"
-# AIX sometimes has problems with the GCC collect2 program.  For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
-  COLLECT_NAMES=
-  export COLLECT_NAMES
-fi
-_LT_EOF
-    ;;
-  esac
-
-
-ltmain="$ac_aux_dir/ltmain.sh"
-
-
-  # We use sed instead of cat because bash on DJGPP gets confused if
-  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
-  # text mode, it properly converts lines to CR/LF.  This bash problem
-  # is reportedly fixed, but why not run on old versions too?
-  sed '$q' "$ltmain" >> "$cfgfile" \
-     || (rm -f "$cfgfile"; exit 1)
-
-  if test x"$xsi_shell" = xyes; then
-  sed -e '/^func_dirname ()$/,/^} # func_dirname /c\
-func_dirname ()\
-{\
-\    case ${1} in\
-\      */*) func_dirname_result="${1%/*}${2}" ;;\
-\      *  ) func_dirname_result="${3}" ;;\
-\    esac\
-} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_basename ()$/,/^} # func_basename /c\
-func_basename ()\
-{\
-\    func_basename_result="${1##*/}"\
-} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\
-func_dirname_and_basename ()\
-{\
-\    case ${1} in\
-\      */*) func_dirname_result="${1%/*}${2}" ;;\
-\      *  ) func_dirname_result="${3}" ;;\
-\    esac\
-\    func_basename_result="${1##*/}"\
-} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_stripname ()$/,/^} # func_stripname /c\
-func_stripname ()\
-{\
-\    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\
-\    # positional parameters, so assign one to ordinary parameter first.\
-\    func_stripname_result=${3}\
-\    func_stripname_result=${func_stripname_result#"${1}"}\
-\    func_stripname_result=${func_stripname_result%"${2}"}\
-} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\
-func_split_long_opt ()\
-{\
-\    func_split_long_opt_name=${1%%=*}\
-\    func_split_long_opt_arg=${1#*=}\
-} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\
-func_split_short_opt ()\
-{\
-\    func_split_short_opt_arg=${1#??}\
-\    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\
-} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\
-func_lo2o ()\
-{\
-\    case ${1} in\
-\      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\
-\      *)    func_lo2o_result=${1} ;;\
-\    esac\
-} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_xform ()$/,/^} # func_xform /c\
-func_xform ()\
-{\
-    func_xform_result=${1%.*}.lo\
-} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_arith ()$/,/^} # func_arith /c\
-func_arith ()\
-{\
-    func_arith_result=$(( $* ))\
-} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_len ()$/,/^} # func_len /c\
-func_len ()\
-{\
-    func_len_result=${#1}\
-} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-fi
-
-if test x"$lt_shell_append" = xyes; then
-  sed -e '/^func_append ()$/,/^} # func_append /c\
-func_append ()\
-{\
-    eval "${1}+=\\${2}"\
-} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\
-func_append_quoted ()\
-{\
-\    func_quote_for_eval "${2}"\
-\    eval "${1}+=\\\\ \\$func_quote_for_eval_result"\
-} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \
-  && mv -f "$cfgfile.tmp" "$cfgfile" \
-    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-test 0 -eq $? || _lt_function_replace_fail=:
-
-
-  # Save a `func_append' function call where possible by direct use of '+='
-  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
-    && mv -f "$cfgfile.tmp" "$cfgfile" \
-      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-  test 0 -eq $? || _lt_function_replace_fail=:
-else
-  # Save a `func_append' function call even when '+=' is not available
-  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
-    && mv -f "$cfgfile.tmp" "$cfgfile" \
-      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
-  test 0 -eq $? || _lt_function_replace_fail=:
-fi
-
-if test x"$_lt_function_replace_fail" = x":"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5
-$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;}
-fi
-
-
-   mv -f "$cfgfile" "$ofile" ||
-    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
-  chmod +x "$ofile"
-
-
-    cat <<_LT_EOF >> "$ofile"
-
-# ### BEGIN LIBTOOL TAG CONFIG: RC
-
-# The linker used to build libraries.
-LD=$lt_LD_RC
-
-# How to create reloadable object files.
-reload_flag=$lt_reload_flag_RC
-reload_cmds=$lt_reload_cmds_RC
-
-# Commands used to build an old-style archive.
-old_archive_cmds=$lt_old_archive_cmds_RC
-
-# A language specific compiler.
-CC=$lt_compiler_RC
-
-# Is the compiler the GNU compiler?
-with_gcc=$GCC_RC
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
-
-# Additional compiler flags for building library objects.
-pic_flag=$lt_lt_prog_compiler_pic_RC
-
-# How to pass a linker flag through the compiler.
-wl=$lt_lt_prog_compiler_wl_RC
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$lt_lt_prog_compiler_static_RC
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
-
-# Whether or not to add -lc for building shared libraries.
-build_libtool_need_lc=$archive_cmds_need_lc_RC
-
-# Whether or not to disallow shared libs when runtime libs are static.
-allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
-
-# Whether the compiler copes with passing no objects directly.
-compiler_needs_object=$lt_compiler_needs_object_RC
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
-
-# Create a temporary old-style archive to link instead of a shared archive.
-old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
-
-# Commands used to build a shared archive.
-archive_cmds=$lt_archive_cmds_RC
-archive_expsym_cmds=$lt_archive_expsym_cmds_RC
-
-# Commands used to build a loadable module if different from building
-# a shared archive.
-module_cmds=$lt_module_cmds_RC
-module_expsym_cmds=$lt_module_expsym_cmds_RC
-
-# Whether we are building with GNU ld or not.
-with_gnu_ld=$lt_with_gnu_ld_RC
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$lt_allow_undefined_flag_RC
-
-# Flag that enforces no undefined symbols.
-no_undefined_flag=$lt_no_undefined_flag_RC
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist
-hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
-
-# Whether we need a single "-rpath" flag with a separated argument.
-hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
-
-# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
-# DIR into the resulting binary.
-hardcode_direct=$hardcode_direct_RC
-
-# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
-# DIR into the resulting binary and the resulting library dependency is
-# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
-# library is relocated.
-hardcode_direct_absolute=$hardcode_direct_absolute_RC
-
-# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
-# into the resulting binary.
-hardcode_minus_L=$hardcode_minus_L_RC
-
-# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
-# into the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
-
-# Set to "yes" if building a shared library automatically hardcodes DIR
-# into the library and all subsequent libraries and executables linked
-# against it.
-hardcode_automatic=$hardcode_automatic_RC
-
-# Set to yes if linker adds runtime paths of dependent libraries
-# to runtime path list.
-inherit_rpath=$inherit_rpath_RC
-
-# Whether libtool must link a program against all its dependency libraries.
-link_all_deplibs=$link_all_deplibs_RC
-
-# Set to "yes" if exported symbols are required.
-always_export_symbols=$always_export_symbols_RC
-
-# The commands to list exported symbols.
-export_symbols_cmds=$lt_export_symbols_cmds_RC
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$lt_exclude_expsyms_RC
-
-# Symbols that must always be exported.
-include_expsyms=$lt_include_expsyms_RC
-
-# Commands necessary for linking programs (against libraries) with templates.
-prelink_cmds=$lt_prelink_cmds_RC
-
-# Commands necessary for finishing linking programs.
-postlink_cmds=$lt_postlink_cmds_RC
-
-# Specify filename containing input files.
-file_list_spec=$lt_file_list_spec_RC
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action_RC
-
-# ### END LIBTOOL TAG CONFIG: RC
-_LT_EOF
-
- ;;
-    "gcrypt-conf":C)
-chmod +x src/libgcrypt-config
- ;;
-    "tests/hashtest-256g":F) chmod +x tests/hashtest-256g ;;
-    "tests/basic-disable-all-hwf":F) chmod +x tests/basic-disable-all-hwf ;;
-
-  esac
-done # for ac_tag
-
-
-as_fn_exit 0
-_ACEOF
-ac_clean_files=$ac_clean_files_save
-
-test $ac_write_fail = 0 ||
-  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded.  So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status.  When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
-  ac_cs_success=:
-  ac_config_status_args=
-  test "$silent" = yes &&
-    ac_config_status_args="$ac_config_status_args --quiet"
-  exec 5>/dev/null
-  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
-  exec 5>>config.log
-  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
-  # would make configure fail if this is the last instruction.
-  $ac_cs_success || as_fn_exit 1
-fi
-if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
-fi
-
-
-
-detection_module="${GCRYPT_HWF_MODULES%.lo}"
-test -n "$detection_module" || detection_module="none"
-
-# Give some feedback
-
-     echo "         " 1>&6
-
-
-     echo "        Libgcrypt v${VERSION} has been configured as follows:" 1>&6
-
-
-     echo "         " 1>&6
-
-
-     echo "        Platform:                  $PRINTABLE_OS_NAME ($host)" 1>&6
-
-
-     echo "        Hardware detection module: $detection_module" 1>&6
-
-
-    tmp="        Enabled cipher algorithms:"
-    tmpi="abc"
-    if test "${#tmpi}" -ne 3 >/dev/null 2>&1 ; then
-            echo "$tmp $enabled_ciphers" 1>&6
-    else
-      tmpi=`echo "$tmp"| sed 's/./ /g'`
-      echo $enabled_ciphers EOF | tr ' ' '\n' | \
-        while read word; do
-          if test "${#tmp}" -gt 70 ; then
-            echo "$tmp" 1>&6
-            tmp="$tmpi"
-          fi
-          if test "$word" = "EOF" ; then
-            echo "$tmp" 1>&6
-          else
-            tmp="$tmp $word"
-          fi
-        done
-    fi
-
-
-    tmp="        Enabled digest algorithms:"
-    tmpi="abc"
-    if test "${#tmpi}" -ne 3 >/dev/null 2>&1 ; then
-            echo "$tmp $enabled_digests" 1>&6
-    else
-      tmpi=`echo "$tmp"| sed 's/./ /g'`
-      echo $enabled_digests EOF | tr ' ' '\n' | \
-        while read word; do
-          if test "${#tmp}" -gt 70 ; then
-            echo "$tmp" 1>&6
-            tmp="$tmpi"
-          fi
-          if test "$word" = "EOF" ; then
-            echo "$tmp" 1>&6
-          else
-            tmp="$tmp $word"
-          fi
-        done
-    fi
-
-
-    tmp="        Enabled kdf algorithms:   "
-    tmpi="abc"
-    if test "${#tmpi}" -ne 3 >/dev/null 2>&1 ; then
-            echo "$tmp $enabled_kdfs" 1>&6
-    else
-      tmpi=`echo "$tmp"| sed 's/./ /g'`
-      echo $enabled_kdfs EOF | tr ' ' '\n' | \
-        while read word; do
-          if test "${#tmp}" -gt 70 ; then
-            echo "$tmp" 1>&6
-            tmp="$tmpi"
-          fi
-          if test "$word" = "EOF" ; then
-            echo "$tmp" 1>&6
-          else
-            tmp="$tmp $word"
-          fi
-        done
-    fi
-
-
-    tmp="        Enabled pubkey algorithms:"
-    tmpi="abc"
-    if test "${#tmpi}" -ne 3 >/dev/null 2>&1 ; then
-            echo "$tmp $enabled_pubkey_ciphers" 1>&6
-    else
-      tmpi=`echo "$tmp"| sed 's/./ /g'`
-      echo $enabled_pubkey_ciphers EOF | tr ' ' '\n' | \
-        while read word; do
-          if test "${#tmp}" -gt 70 ; then
-            echo "$tmp" 1>&6
-            tmp="$tmpi"
-          fi
-          if test "$word" = "EOF" ; then
-            echo "$tmp" 1>&6
-          else
-            tmp="$tmp $word"
-          fi
-        done
-    fi
-
-
-     echo "        Random number generator:   $random" 1>&6
-
-
-     echo "        Try using jitter entropy:  $jentsupport" 1>&6
-
-
-     echo "        Using linux capabilities:  $use_capabilities" 1>&6
-
-
-     echo "        Try using Padlock crypto:  $padlocksupport" 1>&6
-
-
-     echo "        Try using AES-NI crypto:   $aesnisupport" 1>&6
-
-
-     echo "        Try using Intel PCLMUL:    $pclmulsupport" 1>&6
-
-
-     echo "        Try using Intel SSE4.1:    $sse41support" 1>&6
-
-
-     echo "        Try using DRNG (RDRAND):   $drngsupport" 1>&6
-
-
-     echo "        Try using Intel AVX:       $avxsupport" 1>&6
-
-
-     echo "        Try using Intel AVX2:      $avx2support" 1>&6
-
-
-     echo "        Try using ARM NEON:        $neonsupport" 1>&6
-
-
-     echo "        Try using ARMv8 crypto:    $armcryptosupport" 1>&6
-
-
-     echo "         " 1>&6
-
-
-if test "x${gpg_config_script_warn}" != x; then
-cat <<G10EOF
-        Mismatches between the target platform and the to
-        be used libraries have been been detected for:
-         ${gpg_config_script_warn}
-        Please check above for warning messages.
-
-G10EOF
-fi
-
-if test "$gcry_cv_gcc_attribute_aligned" != "yes" ; then
-cat <<G10EOF
-   Please not that your compiler does not support the GCC style
-   aligned attribute. Using this software may evoke bus errors.
-
-G10EOF
-fi
-
-if test -n "$gpl"; then
-  echo "Please note that you are building a version of Libgcrypt with"
-  echo "  $gpl"
-  echo "included.  These parts are licensed under the GPL and thus the"
-  echo "use of this library has to comply with the conditions of the GPL."
-  echo ""
-fi
index ce11162..6ea38f5 100644 (file)
@@ -1,7 +1,7 @@
 # Configure.ac script for Libgcrypt
 # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006,
 #               2007, 2008, 2009, 2011 Free Software Foundation, Inc.
-# Copyright (C) 2012-2017  g10 Code GmbH
+# Copyright (C) 2012-2021  g10 Code GmbH
 #
 # This file is part of Libgcrypt.
 #
@@ -20,7 +20,7 @@
 
 # (Process this file with autoconf to produce a configure script.)
 AC_REVISION($Revision$)
-AC_PREREQ(2.60)
+AC_PREREQ([2.69])
 min_automake_version="1.14"
 
 # To build a release you need to create a tag with the version number
@@ -28,36 +28,41 @@ min_automake_version="1.14"
 # bump the version number immediately after the release and do another
 # commit and push so that the git magic is able to work.  See below
 # for the LT versions.
-m4_define(mym4_version_major, [1])
-m4_define(mym4_version_minor, [8])
-m4_define(mym4_version_micro, [4])
-
-# Below is m4 magic to extract and compute the revision number, the
-# decimalized short revision number, a beta version string, and a flag
-# indicating a development version (mym4_isgit). Note that the m4
-# processing is done by autoconf and not during the configure run.
-m4_define(mym4_version,
-          [mym4_version_major.mym4_version_minor.mym4_version_micro])
-m4_define([mym4_revision],
-          m4_esyscmd([git rev-parse --short HEAD | tr -d '\n\r']))
-m4_define([mym4_revision_dec],
-          m4_esyscmd_s([echo $((0x$(echo ]mym4_revision[|head -c 4)))]))
-m4_define([mym4_betastring],
-          m4_esyscmd_s([git describe --match 'libgcrypt-[0-9].*[0-9]' --long|\
-                        awk -F- '$3!=0{print"-beta"$3}']))
-m4_define([mym4_isgit],m4_if(mym4_betastring,[],[no],[yes]))
-m4_define([mym4_full_version],[mym4_version[]mym4_betastring])
-
-AC_INIT([libgcrypt],[mym4_full_version],[http://bugs.gnupg.org])
+m4_define([mym4_package],[libgcrypt])
+m4_define([mym4_major], [1])
+m4_define([mym4_minor], [10])
+m4_define([mym4_micro], [1])
+
+# Below is m4 magic to extract and compute the git revision number,
+# the decimalized short revision number, a beta version string and a
+# flag indicating a development version (mym4_isbeta).  Note that the
+# m4 processing is done by autoconf and not during the configure run.
+m4_define([mym4_verslist], m4_split(m4_esyscmd([./autogen.sh --find-version] \
+                           mym4_package mym4_major mym4_minor mym4_micro),[:]))
+m4_define([mym4_isbeta],       m4_argn(2, mym4_verslist))
+m4_define([mym4_version],      m4_argn(4, mym4_verslist))
+m4_define([mym4_revision],     m4_argn(7, mym4_verslist))
+m4_define([mym4_revision_dec], m4_argn(8, mym4_verslist))
+m4_esyscmd([echo ]mym4_version[>VERSION])
+AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
 
 # LT Version numbers, remember to change them just *before* a release.
+#   (Code changed:                     REVISION++)
+#   (Interfaces added/removed/changed: CURRENT++, REVISION=0)
+#   (Interfaces added:                 AGE++)
+#   (Interfaces removed:               AGE=0)
+#
 #   (Interfaces removed:    CURRENT++, AGE=0, REVISION=0)
 #   (Interfaces added:      CURRENT++, AGE++, REVISION=0)
 #   (No interfaces changed:                   REVISION++)
-LIBGCRYPT_LT_CURRENT=22
-LIBGCRYPT_LT_AGE=2
-LIBGCRYPT_LT_REVISION=4
+LIBGCRYPT_LT_CURRENT=24
+LIBGCRYPT_LT_AGE=4
+LIBGCRYPT_LT_REVISION=1
+################################################
 
+AC_SUBST(LIBGCRYPT_LT_CURRENT)
+AC_SUBST(LIBGCRYPT_LT_AGE)
+AC_SUBST(LIBGCRYPT_LT_REVISION)
 
 # If the API is changed in an incompatible way: increment the next counter.
 #
@@ -67,15 +72,12 @@ LIBGCRYPT_CONFIG_API_VERSION=1
 
 # If you change the required gpg-error version, please remove
 # unnecessary error code defines in src/gcrypt-int.h.
-NEED_GPG_ERROR_VERSION=1.25
-
-PACKAGE=$PACKAGE_NAME
-VERSION=$PACKAGE_VERSION
+NEED_GPG_ERROR_VERSION=1.27
 
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_SRCDIR([src/libgcrypt.vers])
 AM_INIT_AUTOMAKE([serial-tests dist-bzip2])
-AC_CONFIG_HEADER(config.h)
+AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_LIBOBJ_DIR([compat])
 AC_CANONICAL_HOST
@@ -95,6 +97,12 @@ AH_TOP([
 AH_BOTTOM([
 #define _GCRYPT_IN_LIBGCRYPT 1
 
+/* Add .note.gnu.property section for Intel CET in assembler sources
+   when CET is enabled.  */
+#if defined(__ASSEMBLER__) && defined(__CET__)
+# include <cet.h>
+#endif
+
 /* If the configure check for endianness has been disabled, get it from
    OS macros.  This is intended for making fat binary builds on OS X.  */
 #ifdef DISABLED_ENDIAN_CHECK
@@ -123,18 +131,6 @@ AH_VERBATIM([_REENTRANT],
 ])
 
 
-AC_SUBST(LIBGCRYPT_LT_CURRENT)
-AC_SUBST(LIBGCRYPT_LT_AGE)
-AC_SUBST(LIBGCRYPT_LT_REVISION)
-AC_SUBST(PACKAGE)
-AC_SUBST(VERSION)
-AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
-AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
-VERSION_NUMBER=m4_esyscmd(printf "0x%02x%02x%02x" mym4_version_major \
-                          mym4_version_minor mym4_version_micro)
-AC_SUBST(VERSION_NUMBER)
-
-
 ######################
 ##  Basic checks.  ### (we need some results later on (e.g. $GCC)
 ######################
@@ -150,26 +146,53 @@ AC_PROG_CC
 AC_PROG_CPP
 AM_PROG_CC_C_O
 AM_PROG_AS
-AC_ISC_POSIX
+AC_SEARCH_LIBS([strerror],[cposix])
 AC_PROG_INSTALL
 AC_PROG_AWK
 
-AC_GNU_SOURCE
-
-# We need to compile and run a program on the build machine.  A
-# comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in
-# the AC archive is broken for autoconf 2.57.  Given that there is no
-# newer version of that macro, we assume that it is also broken for
-# autoconf 2.61 and thus we use a simple but usually sufficient
-# approach.
-AC_MSG_CHECKING(for cc for build)
-if test "$cross_compiling" = "yes"; then
-  CC_FOR_BUILD="${CC_FOR_BUILD-cc}"
-else
-  CC_FOR_BUILD="${CC_FOR_BUILD-$CC}"
-fi
-AC_MSG_RESULT($CC_FOR_BUILD)
-AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler])
+AC_USE_SYSTEM_EXTENSIONS
+
+# Taken from mpfr-4.0.1, then modified for LDADD_FOR_TESTS_KLUDGE
+dnl Under Linux, make sure that the old dtags are used if LD_LIBRARY_PATH
+dnl is defined. The issue is that with the new dtags, LD_LIBRARY_PATH has
+dnl the precedence over the run path, so that if a compatible MPFR library
+dnl is installed in some directory from $LD_LIBRARY_PATH, then the tested
+dnl MPFR library will be this library instead of the MPFR library from the
+dnl build tree. Other OS with the same issue might be added later.
+dnl
+dnl References:
+dnl   https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=859732
+dnl   http://lists.gnu.org/archive/html/libtool/2017-05/msg00000.html
+dnl
+dnl We need to check whether --disable-new-dtags is supported as alternate
+dnl linkers may be used (e.g., with tcc: CC=tcc LD=tcc).
+dnl
+case $host in
+  *-*-linux*)
+    if test -n "$LD_LIBRARY_PATH"; then
+      saved_LDFLAGS="$LDFLAGS"
+      LDADD_FOR_TESTS_KLUDGE="-Wl,--disable-new-dtags"
+      LDFLAGS="$LDFLAGS $LDADD_FOR_TESTS_KLUDGE"
+      AC_MSG_CHECKING(whether --disable-new-dtags is supported by the linker)
+      AC_LINK_IFELSE([AC_LANG_SOURCE([[
+int main (void) { return 0; }
+      ]])],
+      [AC_MSG_RESULT(yes (use it since LD_LIBRARY_PATH is set))],
+      [AC_MSG_RESULT(no)
+       LDADD_FOR_TESTS_KLUDGE=""
+      ])
+      LDFLAGS="$saved_LDFLAGS"
+    fi
+    ;;
+esac
+AC_SUBST([LDADD_FOR_TESTS_KLUDGE])
+
+VERSION_NUMBER=m4_esyscmd(printf "0x%02x%02x%02x" mym4_major \
+                          mym4_minor mym4_micro)
+AC_SUBST(VERSION_NUMBER)
+
+# We need to compile and run a program on the build machine.
+AX_CC_FOR_BUILD
 
 
 LT_PREREQ([2.2.6])
@@ -189,6 +212,7 @@ LIBGCRYPT_CONFIG_HOST="$host"
 # Definitions for symmetric ciphers.
 available_ciphers="arcfour blowfish cast5 des aes twofish serpent rfc2268 seed"
 available_ciphers="$available_ciphers camellia idea salsa20 gost28147 chacha20"
+available_ciphers="$available_ciphers sm4"
 enabled_ciphers=""
 
 # Definitions for public-key ciphers.
@@ -198,6 +222,7 @@ enabled_pubkey_ciphers=""
 # Definitions for message digests.
 available_digests="crc gostr3411-94 md2 md4 md5 rmd160 sha1 sha256 sha512"
 available_digests="$available_digests sha3 tiger whirlpool stribog blake2"
+available_digests="$available_digests sm3"
 enabled_digests=""
 
 # Definitions for kdfs (optional ones)
@@ -205,7 +230,7 @@ available_kdfs="s2k pkdf2 scrypt"
 enabled_kdfs=""
 
 # Definitions for random modules.
-available_random_modules="linux egd unix"
+available_random_modules="getentropy linux egd unix"
 auto_random_modules="$available_random_modules"
 
 # Supported thread backends.
@@ -270,8 +295,11 @@ case "${host}" in
     m68k-atari-mint)
         ;;
     *-apple-darwin*)
-        AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
+        AC_DEFINE(_DARWIN_C_SOURCE, 1,
                   Expose all libc features (__DARWIN_C_FULL).)
+        AC_DEFINE(USE_POSIX_SPAWN_FOR_TESTS, 1,
+                  [defined if we use posix_spawn in test program])
+        AC_CHECK_HEADERS(spawn.h)
         ;;
     *)
       ;;
@@ -319,8 +347,8 @@ NAME_OF_DEV_RANDOM="/dev/random"
 NAME_OF_DEV_URANDOM="/dev/urandom"
 
 AC_ARG_ENABLE(endian-check,
-              AC_HELP_STRING([--disable-endian-check],
-             [disable the endian check and trust the OS provided macros]),
+              AS_HELP_STRING([--disable-endian-check],
+              [disable the endian check and trust the OS provided macros]),
              endiancheck=$enableval,endiancheck=yes)
 if test x"$endiancheck" = xyes ; then
   AC_C_BIGENDIAN
@@ -384,8 +412,8 @@ AC_SUBST(emacs_local_vars_end, ['End:'])
 
 # Implementation of the --enable-ciphers switch.
 AC_ARG_ENABLE(ciphers,
-             AC_HELP_STRING([--enable-ciphers=ciphers],
-                            [select the symmetric ciphers to include]),
+             AS_HELP_STRING([--enable-ciphers=ciphers],
+                             [select the symmetric ciphers to include]),
              [enabled_ciphers=`echo $enableval | tr ',:' '  ' | tr '[A-Z]' '[a-z]'`],
              [enabled_ciphers=""])
 if test "x$enabled_ciphers" = "x" \
@@ -404,8 +432,8 @@ AC_MSG_RESULT([$enabled_ciphers])
 
 # Implementation of the --enable-pubkey-ciphers switch.
 AC_ARG_ENABLE(pubkey-ciphers,
-             AC_HELP_STRING([--enable-pubkey-ciphers=ciphers],
-                            [select the public-key ciphers to include]),
+             AS_HELP_STRING([--enable-pubkey-ciphers=ciphers],
+                             [select the public-key ciphers to include]),
              [enabled_pubkey_ciphers=`echo $enableval | tr ',:' '  ' | tr '[A-Z]' '[a-z]'`],
              [enabled_pubkey_ciphers=""])
 if test "x$enabled_pubkey_ciphers" = "x" \
@@ -424,8 +452,8 @@ AC_MSG_RESULT([$enabled_pubkey_ciphers])
 
 # Implementation of the --enable-digests switch.
 AC_ARG_ENABLE(digests,
-             AC_HELP_STRING([--enable-digests=digests],
-                            [select the message digests to include]),
+             AS_HELP_STRING([--enable-digests=digests],
+                             [select the message digests to include]),
              [enabled_digests=`echo $enableval | tr ',:' '  ' | tr '[A-Z]' '[a-z]'`],
              [enabled_digests=""])
 if test "x$enabled_digests" = "x" \
@@ -444,8 +472,8 @@ AC_MSG_RESULT([$enabled_digests])
 
 # Implementation of the --enable-kdfs switch.
 AC_ARG_ENABLE(kdfs,
-      AC_HELP_STRING([--enable-kfds=kdfs],
-                    [select the KDFs to include]),
+      AS_HELP_STRING([--enable-kfds=kdfs],
+                     [select the KDFs to include]),
       [enabled_kdfs=`echo $enableval | tr ',:' '  ' | tr '[A-Z]' '[a-z]'`],
       [enabled_kdfs=""])
 if test "x$enabled_kdfs" = "x" \
@@ -464,8 +492,8 @@ AC_MSG_RESULT([$enabled_kdfs])
 
 # Implementation of the --enable-random switch.
 AC_ARG_ENABLE(random,
-             AC_HELP_STRING([--enable-random=name],
-                            [select which random number generator to use]),
+             AS_HELP_STRING([--enable-random=name],
+                             [select which random number generator to use]),
              [random=`echo $enableval | tr '[A-Z]' '[a-z]'`],
              [])
 if test "x$random" = "x" -o "$random" = "yes" -o "$random" = "no"; then
@@ -498,31 +526,30 @@ AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name",
 # Implementation of the --enable-random-daemon
 AC_MSG_CHECKING([whether the experimental random daemon is requested])
 AC_ARG_ENABLE([random-daemon],
-              AC_HELP_STRING([--enable-random-daemon],
-                             [Build and support the experimental gcryptrnd]),
-              [use_random_daemon=$enableval],
-              [use_random_daemon=no])
-AC_MSG_RESULT($use_random_daemon)
-if test x$use_random_daemon = xyes ; then
-    AC_DEFINE(USE_RANDOM_DAEMON,1,
-              [Define to support the experimental random daemon])
-fi
-AM_CONDITIONAL(USE_RANDOM_DAEMON, test x$use_random_daemon = xyes)
+              AS_HELP_STRING([--enable-random-daemon],
+                             [Build the experimental gcryptrnd]),
+              [enable_random_daemon=$enableval],
+              [enable_random_daemon=no])
+AC_MSG_RESULT($enable_random_daemon)
+AM_CONDITIONAL(ENABLE_RANDOM_DAEMON, test x$enable_random_daemon = xyes)
 
 
 # Implementation of --disable-asm.
-AC_MSG_CHECKING([whether MPI assembler modules are requested])
+AC_MSG_CHECKING([whether MPI and cipher assembler modules are requested])
 AC_ARG_ENABLE([asm],
-              AC_HELP_STRING([--disable-asm],
-                            [Disable MPI assembler modules]),
+              AS_HELP_STRING([--disable-asm],
+                             [Disable MPI and cipher assembler modules]),
               [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])
 AC_ARG_ENABLE(m-guard,
-              AC_HELP_STRING([--enable-m-guard],
+              AS_HELP_STRING([--enable-m-guard],
                              [Enable memory guard facility]),
               [use_m_guard=$enableval], [use_m_guard=no])
 AC_MSG_RESULT($use_m_guard)
@@ -533,18 +560,27 @@ fi
 # Implementation of the --enable-large-data-tests switch.
 AC_MSG_CHECKING([whether to run large data tests])
 AC_ARG_ENABLE(large-data-tests,
-              AC_HELP_STRING([--enable-large-data-tests],
+              AS_HELP_STRING([--enable-large-data-tests],
                  [Enable the real long ruinning large data tests]),
              large_data_tests=$enableval,large_data_tests=no)
 AC_MSG_RESULT($large_data_tests)
 AC_SUBST(RUN_LARGE_DATA_TESTS, $large_data_tests)
 
+# Implementation of --enable-force-soft-hwfeatures
+AC_MSG_CHECKING([whether 'soft' HW feature bits are forced on])
+AC_ARG_ENABLE([force-soft-hwfeatures],
+              AS_HELP_STRING([--enable-force-soft-hwfeatures],
+                             [Enable forcing 'soft' HW feature bits on]),
+              [force_soft_hwfeatures=$enableval],
+              [force_soft_hwfeatures=no])
+AC_MSG_RESULT($force_soft_hwfeatures)
+
 
 # Implementation of the --with-capabilities switch.
 # Check whether we want to use Linux capabilities
 AC_MSG_CHECKING([whether use of capabilities is requested])
 AC_ARG_WITH(capabilities,
-            AC_HELP_STRING([--with-capabilities],
+            AS_HELP_STRING([--with-capabilities],
                            [Use linux capabilities [default=no]]),
             [use_capabilities="$withval"],[use_capabilities=no])
 AC_MSG_RESULT($use_capabilities)
@@ -552,21 +588,37 @@ AC_MSG_RESULT($use_capabilities)
 # Implementation of the --enable-hmac-binary-check.
 AC_MSG_CHECKING([whether a HMAC binary check is requested])
 AC_ARG_ENABLE(hmac-binary-check,
-              AC_HELP_STRING([--enable-hmac-binary-check],
+              AS_HELP_STRING([--enable-hmac-binary-check],
                              [Enable library integrity check]),
-              [use_hmac_binary_check=$enableval],
+              [use_hmac_binary_check="$enableval"],
               [use_hmac_binary_check=no])
 AC_MSG_RESULT($use_hmac_binary_check)
-if test "$use_hmac_binary_check" = yes ; then
+if test "$use_hmac_binary_check" = no ; then
+    DEF_HMAC_BINARY_CHECK=''
+else
     AC_DEFINE(ENABLE_HMAC_BINARY_CHECK,1,
               [Define to support an HMAC based integrity check])
+    AC_CHECK_TOOL(OBJCOPY, [objcopy])
+    AC_CHECK_TOOL(READELF, [readelf])
+    if test "$use_hmac_binary_check" != yes ; then
+        DEF_HMAC_BINARY_CHECK=-DKEY_FOR_BINARY_CHECK="'\"$use_hmac_binary_check\"'"
+    fi
 fi
+AM_CONDITIONAL(USE_HMAC_BINARY_CHECK, test "x$use_hmac_binary_check" != xno)
+AC_SUBST(DEF_HMAC_BINARY_CHECK)
 
+# Implementation of the --with-fips-module-version.
+AC_ARG_WITH(fips-module-version,
+            AS_HELP_STRING([--with-fips-module-version=VERSION],
+                           [Specify the FIPS module version for the build]),
+            fips_module_version="$withval", fips_module_version="" )
+AC_DEFINE_UNQUOTED(FIPS_MODULE_VERSION, "$fips_module_version",
+                   [Define FIPS module version for certification])
 
 # Implementation of the --disable-jent-support switch.
 AC_MSG_CHECKING([whether jitter entropy support is requested])
 AC_ARG_ENABLE(jent-support,
-              AC_HELP_STRING([--disable-jent-support],
+              AS_HELP_STRING([--disable-jent-support],
                         [Disable support for the Jitter entropy collector]),
              jentsupport=$enableval,jentsupport=yes)
 AC_MSG_RESULT($jentsupport)
@@ -574,23 +626,31 @@ AC_MSG_RESULT($jentsupport)
 # Implementation of the --disable-padlock-support switch.
 AC_MSG_CHECKING([whether padlock support is requested])
 AC_ARG_ENABLE(padlock-support,
-              AC_HELP_STRING([--disable-padlock-support],
-                        [Disable support for the PadLock Engine of VIA processors]),
+              AS_HELP_STRING([--disable-padlock-support],
+                        [Disable support for the PadLock Engine of VIA processors]),
              padlocksupport=$enableval,padlocksupport=yes)
 AC_MSG_RESULT($padlocksupport)
 
 # Implementation of the --disable-aesni-support switch.
 AC_MSG_CHECKING([whether AESNI support is requested])
 AC_ARG_ENABLE(aesni-support,
-              AC_HELP_STRING([--disable-aesni-support],
+              AS_HELP_STRING([--disable-aesni-support],
                  [Disable support for the Intel AES-NI instructions]),
              aesnisupport=$enableval,aesnisupport=yes)
 AC_MSG_RESULT($aesnisupport)
 
+# Implementation of the --disable-shaext-support switch.
+AC_MSG_CHECKING([whether SHAEXT support is requested])
+AC_ARG_ENABLE(shaext-support,
+              AS_HELP_STRING([--disable-shaext-support],
+                 [Disable support for the Intel SHAEXT instructions]),
+              shaextsupport=$enableval,shaextsupport=yes)
+AC_MSG_RESULT($shaextsupport)
+
 # Implementation of the --disable-pclmul-support switch.
 AC_MSG_CHECKING([whether PCLMUL support is requested])
 AC_ARG_ENABLE(pclmul-support,
-              AC_HELP_STRING([--disable-pclmul-support],
+              AS_HELP_STRING([--disable-pclmul-support],
                  [Disable support for the Intel PCLMUL instructions]),
              pclmulsupport=$enableval,pclmulsupport=yes)
 AC_MSG_RESULT($pclmulsupport)
@@ -598,7 +658,7 @@ AC_MSG_RESULT($pclmulsupport)
 # Implementation of the --disable-sse41-support switch.
 AC_MSG_CHECKING([whether SSE4.1 support is requested])
 AC_ARG_ENABLE(sse41-support,
-              AC_HELP_STRING([--disable-sse41-support],
+              AS_HELP_STRING([--disable-sse41-support],
                  [Disable support for the Intel SSE4.1 instructions]),
              sse41support=$enableval,sse41support=yes)
 AC_MSG_RESULT($sse41support)
@@ -606,7 +666,7 @@ AC_MSG_RESULT($sse41support)
 # Implementation of the --disable-drng-support switch.
 AC_MSG_CHECKING([whether DRNG support is requested])
 AC_ARG_ENABLE(drng-support,
-              AC_HELP_STRING([--disable-drng-support],
+              AS_HELP_STRING([--disable-drng-support],
                  [Disable support for the Intel DRNG (RDRAND instruction)]),
              drngsupport=$enableval,drngsupport=yes)
 AC_MSG_RESULT($drngsupport)
@@ -614,7 +674,7 @@ AC_MSG_RESULT($drngsupport)
 # Implementation of the --disable-avx-support switch.
 AC_MSG_CHECKING([whether AVX support is requested])
 AC_ARG_ENABLE(avx-support,
-              AC_HELP_STRING([--disable-avx-support],
+              AS_HELP_STRING([--disable-avx-support],
                  [Disable support for the Intel AVX instructions]),
              avxsupport=$enableval,avxsupport=yes)
 AC_MSG_RESULT($avxsupport)
@@ -622,7 +682,7 @@ AC_MSG_RESULT($avxsupport)
 # Implementation of the --disable-avx2-support switch.
 AC_MSG_CHECKING([whether AVX2 support is requested])
 AC_ARG_ENABLE(avx2-support,
-              AC_HELP_STRING([--disable-avx2-support],
+              AS_HELP_STRING([--disable-avx2-support],
                  [Disable support for the Intel AVX2 instructions]),
              avx2support=$enableval,avx2support=yes)
 AC_MSG_RESULT($avx2support)
@@ -630,7 +690,7 @@ AC_MSG_RESULT($avx2support)
 # Implementation of the --disable-neon-support switch.
 AC_MSG_CHECKING([whether NEON support is requested])
 AC_ARG_ENABLE(neon-support,
-              AC_HELP_STRING([--disable-neon-support],
+              AS_HELP_STRING([--disable-neon-support],
                  [Disable support for the ARM NEON instructions]),
              neonsupport=$enableval,neonsupport=yes)
 AC_MSG_RESULT($neonsupport)
@@ -638,25 +698,44 @@ AC_MSG_RESULT($neonsupport)
 # Implementation of the --disable-arm-crypto-support switch.
 AC_MSG_CHECKING([whether ARMv8 Crypto Extension support is requested])
 AC_ARG_ENABLE(arm-crypto-support,
-              AC_HELP_STRING([--disable-arm-crypto-support],
+              AS_HELP_STRING([--disable-arm-crypto-support],
                  [Disable support for the ARMv8 Crypto Extension instructions]),
              armcryptosupport=$enableval,armcryptosupport=yes)
 AC_MSG_RESULT($armcryptosupport)
 
+# Implementation of the --disable-ppc-crypto-support switch.
+AC_MSG_CHECKING([whether PPC crypto support is requested])
+AC_ARG_ENABLE(ppc-crypto-support,
+              AS_HELP_STRING([--disable-ppc-crypto-support],
+                 [Disable support for the PPC crypto instructions introduced in POWER 8 (PowerISA 2.07)]),
+              ppccryptosupport=$enableval,ppccryptosupport=yes)
+AC_MSG_RESULT($ppccryptosupport)
+
 # Implementation of the --disable-O-flag-munging switch.
 AC_MSG_CHECKING([whether a -O flag munging is requested])
 AC_ARG_ENABLE([O-flag-munging],
-              AC_HELP_STRING([--disable-O-flag-munging],
+              AS_HELP_STRING([--disable-O-flag-munging],
                  [Disable modification of the cc -O flag]),
               [enable_o_flag_munging=$enableval],
               [enable_o_flag_munging=yes])
 AC_MSG_RESULT($enable_o_flag_munging)
 AM_CONDITIONAL(ENABLE_O_FLAG_MUNGING, test "$enable_o_flag_munging" = "yes")
 
+# Implementation of the --disable-instrumentation-munging switch.
+AC_MSG_CHECKING([whether a instrumentation (-fprofile, -fsanitize) munging is requested])
+AC_ARG_ENABLE([instrumentation-munging],
+              AS_HELP_STRING([--disable-instrumentation-munging],
+                 [Disable modification of the cc instrumentation options]),
+              [enable_instrumentation_munging=$enableval],
+              [enable_instrumentation_munging=yes])
+AC_MSG_RESULT($enable_instrumentation_munging)
+AM_CONDITIONAL(ENABLE_INSTRUMENTATION_MUNGING,
+              test "$enable_instrumentation_munging" = "yes")
+
 # Implementation of the --disable-amd64-as-feature-detection switch.
 AC_MSG_CHECKING([whether to enable AMD64 as(1) feature detection])
 AC_ARG_ENABLE(amd64-as-feature-detection,
-              AC_HELP_STRING([--disable-amd64-as-feature-detection],
+              AS_HELP_STRING([--disable-amd64-as-feature-detection],
                  [Disable the auto-detection of AMD64 as(1) features]),
              amd64_as_feature_detection=$enableval,
               amd64_as_feature_detection=yes)
@@ -678,7 +757,7 @@ case "${host}" in
         ;;
 esac
 AC_ARG_ENABLE([ld-version-script],
-              AC_HELP_STRING([--enable-ld-version-script],
+              AS_HELP_STRING([--enable-ld-version-script],
                              [enable/disable use of linker version script.
                               (default is system dependent)]),
               [have_ld_version_script=$enableval],
@@ -712,13 +791,13 @@ AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GCRYPT,
 # to build the optional gcryptrnd program.
 #
 AC_ARG_WITH(pth-prefix,
-            AC_HELP_STRING([--with-pth-prefix=PFX],
+            AS_HELP_STRING([--with-pth-prefix=PFX],
                            [prefix where GNU Pth is installed (optional)]),
      pth_config_prefix="$withval", pth_config_prefix="")
 if test x$pth_config_prefix != x ; then
    PTH_CONFIG="$pth_config_prefix/bin/pth-config"
 fi
-if test "$use_random_daemon" = "yes"; then
+if test "$enable_random_daemon" = "yes"; then
   AC_PATH_PROG(PTH_CONFIG, pth-config, no)
   if test "$PTH_CONFIG" = "no"; then
     AC_MSG_WARN([[
@@ -766,13 +845,7 @@ AC_SEARCH_LIBS(setsockopt, [nsl])
 #### Checks for header files. ####
 ##################################
 
-AC_HEADER_STDC
-AC_CHECK_HEADERS(unistd.h sys/select.h sys/msg.h)
-INSERT_SYS_SELECT_H=
-if test x"$ac_cv_header_sys_select_h" = xyes; then
-  INSERT_SYS_SELECT_H=" include <sys/select.h>"
-fi
-AC_SUBST(INSERT_SYS_SELECT_H)
+AC_CHECK_HEADERS(unistd.h sys/auxv.h sys/random.h)
 
 
 ##########################################
@@ -783,32 +856,11 @@ AC_SUBST(INSERT_SYS_SELECT_H)
 AC_C_CONST
 AC_C_INLINE
 AC_TYPE_SIZE_T
-AC_TYPE_SIGNAL
-AC_DECL_SYS_SIGLIST
 AC_TYPE_PID_T
 
-GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF)
-GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF)
-GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF)
-GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF)
-GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF)
+AC_CHECK_TYPES([byte, ushort, u16, u32, u64])
 
 gl_TYPE_SOCKLEN_T
-case "${host}" in
-  *-*-mingw32*)
-    # socklen_t may or may not be defined depending on what headers
-    # are included.  To be safe we use int as this is the actual type.
-    FALLBACK_SOCKLEN_T="typedef int gcry_socklen_t;"
-    ;;
-  *)
-    if test ".$gl_cv_socklen_t_equiv" = "."; then
-      FALLBACK_SOCKLEN_T="typedef socklen_t gcry_socklen_t;"
-    else
-      FALLBACK_SOCKLEN_T="typedef ${gl_cv_socklen_t_equiv} gcry_socklen_t;"
-    fi
-esac
-AC_SUBST(FALLBACK_SOCKLEN_T)
-
 
 #
 # Check for __builtin_bswap32 intrinsic.
@@ -856,6 +908,66 @@ fi
 
 
 #
+# Check for __builtin_ctzl intrinsic.
+#
+AC_CACHE_CHECK(for __builtin_ctzl,
+       [gcry_cv_have_builtin_ctzl],
+       [gcry_cv_have_builtin_ctzl=no
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([],
+          [unsigned long x = 0; long y = __builtin_ctzl(x); return y;])],
+          [gcry_cv_have_builtin_ctzl=yes])])
+if test "$gcry_cv_have_builtin_ctzl" = "yes" ; then
+   AC_DEFINE(HAVE_BUILTIN_CTZL, 1,
+             [Defined if compiler has '__builtin_ctzl' intrinsic])
+fi
+
+
+#
+# Check for __builtin_clz intrinsic.
+#
+AC_CACHE_CHECK(for __builtin_clz,
+       [gcry_cv_have_builtin_clz],
+       [gcry_cv_have_builtin_clz=no
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([],
+          [unsigned int x = 0; int y = __builtin_clz(x); return y;])],
+          [gcry_cv_have_builtin_clz=yes])])
+if test "$gcry_cv_have_builtin_clz" = "yes" ; then
+   AC_DEFINE(HAVE_BUILTIN_CLZ, 1,
+             [Defined if compiler has '__builtin_clz' intrinsic])
+fi
+
+
+#
+# Check for __builtin_clzl intrinsic.
+#
+AC_CACHE_CHECK(for __builtin_clzl,
+       [gcry_cv_have_builtin_clzl],
+       [gcry_cv_have_builtin_clzl=no
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([],
+          [unsigned long x = 0; long y = __builtin_clzl(x); return y;])],
+          [gcry_cv_have_builtin_clzl=yes])])
+if test "$gcry_cv_have_builtin_clzl" = "yes" ; then
+   AC_DEFINE(HAVE_BUILTIN_CLZL, 1,
+             [Defined if compiler has '__builtin_clzl' intrinsic])
+fi
+
+
+#
+# Check for __sync_synchronize intrinsic.
+#
+AC_CACHE_CHECK(for __sync_synchronize,
+       [gcry_cv_have_sync_synchronize],
+       [gcry_cv_have_sync_synchronize=no
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([],
+          [__sync_synchronize(); return 0;])],
+          [gcry_cv_have_sync_synchronize=yes])])
+if test "$gcry_cv_have_sync_synchronize" = "yes" ; then
+   AC_DEFINE(HAVE_SYNC_SYNCHRONIZE, 1,
+             [Defined if compiler has '__sync_synchronize' intrinsic])
+fi
+
+
+#
 # Check for VLA support (variable length arrays).
 #
 AC_CACHE_CHECK(whether the variable length arrays are supported,
@@ -1051,7 +1163,11 @@ if test "$gcry_cv_have_asm" = "no" ; then
           [gcry_cv_have_asm_volatile_memory],
           [gcry_cv_have_asm_volatile_memory=no
            AC_COMPILE_IFELSE([AC_LANG_SOURCE(
-             [[void a(void) { __asm__ volatile("":::"memory"); }]])],
+             [[void a(int x)
+               {
+                 __asm__ volatile("":::"memory");
+                 __asm__ volatile("":"+r"(x)::"memory");
+               }]])],
              [gcry_cv_have_asm_volatile_memory=yes])])
    fi
 else
@@ -1059,7 +1175,10 @@ else
        [gcry_cv_have_asm_volatile_memory],
        [gcry_cv_have_asm_volatile_memory=no
         AC_COMPILE_IFELSE([AC_LANG_SOURCE(
-          [[void a(void) { asm volatile("":::"memory"); }]])],
+          [[void a(int x)
+            {
+              asm volatile("":::"memory");
+              asm volatile("":"+r"(x)::"memory"); }]])],
           [gcry_cv_have_asm_volatile_memory=yes])])
 fi
 if test "$gcry_cv_have_asm_volatile_memory" = "yes" ; then
@@ -1075,12 +1194,16 @@ fi
 #
 AC_CACHE_CHECK([whether GCC assembler is compatible for ARM assembly implementations],
        [gcry_cv_gcc_arm_platform_as_ok],
-       [gcry_cv_gcc_arm_platform_as_ok=no
-        AC_COMPILE_IFELSE([AC_LANG_SOURCE(
-          [[__asm__(
+       [if test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_arm_platform_as_ok="n/a"
+        else
+          gcry_cv_gcc_arm_platform_as_ok=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+            [[__asm__(
                 /* Test if assembler supports UAL syntax.  */
                 ".syntax unified\n\t"
                 ".arm\n\t" /* our assembly code is in ARM mode  */
+                ".text\n\t"
                 /* Following causes error if assembler ignored '.syntax unified'.  */
                 "asmfunc:\n\t"
                 "add %r0, %r0, %r4, ror #12;\n\t"
@@ -1088,8 +1211,9 @@ AC_CACHE_CHECK([whether GCC assembler is compatible for ARM assembly implementat
                 /* Test if '.type' and '.size' are supported.  */
                 ".size asmfunc,.-asmfunc;\n\t"
                 ".type asmfunc,%function;\n\t"
-            );]])],
-          [gcry_cv_gcc_arm_platform_as_ok=yes])])
+              );]], [ asmfunc(); ] )],
+            [gcry_cv_gcc_arm_platform_as_ok=yes])
+        fi])
 if test "$gcry_cv_gcc_arm_platform_as_ok" = "yes" ; then
    AC_DEFINE(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS,1,
      [Defined if underlying assembler is compatible with ARM assembly implementations])
@@ -1103,24 +1227,74 @@ fi
 #
 AC_CACHE_CHECK([whether GCC assembler is compatible for ARMv8/Aarch64 assembly implementations],
        [gcry_cv_gcc_aarch64_platform_as_ok],
-       [gcry_cv_gcc_aarch64_platform_as_ok=no
-        AC_COMPILE_IFELSE([AC_LANG_SOURCE(
-          [[__asm__(
+       [if test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_aarch64_platform_as_ok="n/a"
+        else
+          gcry_cv_gcc_aarch64_platform_as_ok=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+            [[__asm__(
+                ".text\n\t"
                 "asmfunc:\n\t"
                 "eor x0, x0, x30, ror #12;\n\t"
                 "add x0, x0, x30, asr #12;\n\t"
                 "eor v0.16b, v0.16b, v31.16b;\n\t"
-
-                /* Test if '.type' and '.size' are supported.  */
-                ".size asmfunc,.-asmfunc;\n\t"
-                ".type asmfunc,@function;\n\t"
-            );]])],
-          [gcry_cv_gcc_aarch64_platform_as_ok=yes])])
+              );]], [ asmfunc(); ] )],
+            [gcry_cv_gcc_aarch64_platform_as_ok=yes])
+        fi])
 if test "$gcry_cv_gcc_aarch64_platform_as_ok" = "yes" ; then
    AC_DEFINE(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS,1,
      [Defined if underlying assembler is compatible with ARMv8/Aarch64 assembly implementations])
 fi
 
+#
+# Check whether GCC assembler supports for CFI directives.
+#
+AC_CACHE_CHECK([whether GCC assembler supports for CFI directives],
+       [gcry_cv_gcc_asm_cfi_directives],
+       [gcry_cv_gcc_asm_cfi_directives=no
+        AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[__asm__(
+                ".text\n\t"
+                "ac_test:\n\t"
+                ".cfi_startproc\n\t"
+                ".cfi_remember_state\n\t"
+                ".cfi_adjust_cfa_offset 8\n\t"
+                ".cfi_rel_offset 0, 8\n\t"
+                ".cfi_def_cfa_register 1\n\t"
+                ".cfi_register 2, 3\n\t"
+                ".cfi_restore 2\n\t"
+                ".cfi_escape 0x0f, 0x02, 0x11, 0x00\n\t"
+                ".cfi_restore_state\n\t"
+                ".long 0\n\t"
+                ".cfi_endproc\n\t"
+            );]])],
+          [gcry_cv_gcc_asm_cfi_directives=yes])])
+if test "$gcry_cv_gcc_asm_cfi_directives" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_ASM_CFI_DIRECTIVES,1,
+             [Defined if underlying assembler supports for CFI directives])
+fi
+
+
+#
+# Check whether GCC assembler supports for ELF directives.
+#
+AC_CACHE_CHECK([whether GCC assembler supports for ELF directives],
+       [gcry_cv_gcc_asm_elf_directives],
+       [gcry_cv_gcc_asm_elf_directives=no
+        AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[__asm__(
+                /* Test if ELF directives '.type' and '.size' are supported. */
+                ".text\n\t"
+                "asmfunc:\n\t"
+                ".size asmfunc,.-asmfunc;\n\t"
+                ".type asmfunc,STT_FUNC;\n\t"
+            );]])],
+          [gcry_cv_gcc_asm_elf_directives=yes])])
+if test "$gcry_cv_gcc_asm_elf_directives" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_ASM_ELF_DIRECTIVES,1,
+             [Defined if underlying assembler supports for ELF directives])
+fi
+
 
 #
 # Check whether underscores in symbols are required.  This needs to be
@@ -1136,8 +1310,8 @@ GNUPG_SYS_SYMBOL_UNDERSCORE()
 ####                         ####
 #################################
 AC_ARG_ENABLE(mpi-path,
-              AC_HELP_STRING([--enable-mpi-path=EXTRA_PATH],
-             [prepend EXTRA_PATH to list of CPU specific optimizations]),
+              AS_HELP_STRING([--enable-mpi-path=EXTRA_PATH],
+              [prepend EXTRA_PATH to list of CPU specific optimizations]),
              mpi_extra_path="$enableval",mpi_extra_path="")
 AC_MSG_CHECKING(architecture and mpi assembler functions)
 if test -f $srcdir/mpi/config.links ; then
@@ -1174,12 +1348,12 @@ AM_CONDITIONAL(MPI_MOD_C_UDIV_QRNND, test "$mpi_mod_c_udiv_qrnnd" = yes)
 # Reset non applicable feature flags.
 if test "$mpi_cpu_arch" != "x86" ; then
    aesnisupport="n/a"
+   shaextsupport="n/a"
    pclmulsupport="n/a"
    sse41support="n/a"
    avxsupport="n/a"
    avx2support="n/a"
    padlocksupport="n/a"
-   jentsupport="n/a"
    drngsupport="n/a"
 fi
 
@@ -1190,6 +1364,9 @@ if test "$mpi_cpu_arch" != "arm" ; then
    fi
 fi
 
+if test "$mpi_cpu_arch" != "ppc"; then
+   ppccryptosupport="n/a"
+fi
 
 #############################################
 ####                                     ####
@@ -1290,16 +1467,17 @@ CFLAGS=$_gcc_cflags_save;
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports SSSE3 instructions],
        [gcry_cv_gcc_inline_asm_ssse3],
-       [if test "$mpi_cpu_arch" != "x86" ; then
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_ssse3="n/a"
         else
           gcry_cv_gcc_inline_asm_ssse3=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[static unsigned char be_mask[16] __attribute__ ((aligned (16))) =
               { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
             void a(void) {
               __asm__("pshufb %[mask], %%xmm2\n\t"::[mask]"m"(*be_mask):);
-            }]])],
+            }]], [ a(); ] )],
           [gcry_cv_gcc_inline_asm_ssse3=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_ssse3" = "yes" ; then
@@ -1313,14 +1491,15 @@ fi
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports PCLMUL instructions],
        [gcry_cv_gcc_inline_asm_pclmul],
-       [if test "$mpi_cpu_arch" != "x86" ; then
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_pclmul="n/a"
         else
           gcry_cv_gcc_inline_asm_pclmul=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[void a(void) {
               __asm__("pclmulqdq \$0, %%xmm1, %%xmm3\n\t":::"cc");
-            }]])],
+            }]], [ a(); ] )],
           [gcry_cv_gcc_inline_asm_pclmul=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_pclmul" = "yes" ; then
@@ -1328,20 +1507,50 @@ if test "$gcry_cv_gcc_inline_asm_pclmul" = "yes" ; then
      [Defined if inline assembler supports PCLMUL instructions])
 fi
 
+
+#
+# Check whether GCC inline assembler supports SHA Extensions instructions.
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports SHA Extensions instructions],
+       [gcry_cv_gcc_inline_asm_shaext],
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_shaext="n/a"
+        else
+          gcry_cv_gcc_inline_asm_shaext=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[void a(void) {
+              __asm__("sha1rnds4 \$0, %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha1nexte %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha1msg1 %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha1msg2 %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha256rnds2 %%xmm0, %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha256msg1 %%xmm1, %%xmm3\n\t":::"cc");
+              __asm__("sha256msg2 %%xmm1, %%xmm3\n\t":::"cc");
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_shaext=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_shaext" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_SHAEXT,1,
+     [Defined if inline assembler supports SHA Extensions instructions])
+fi
+
+
 #
 # Check whether GCC inline assembler supports SSE4.1 instructions.
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports SSE4.1 instructions],
        [gcry_cv_gcc_inline_asm_sse41],
-       [if test "$mpi_cpu_arch" != "x86" ; then
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_sse41="n/a"
         else
           gcry_cv_gcc_inline_asm_sse41=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[void a(void) {
               int i;
               __asm__("pextrd \$2, %%xmm0, %[out]\n\t" : [out] "=m" (i));
-            }]])],
+            }]], [ a(); ] )],
           [gcry_cv_gcc_inline_asm_sse41=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_sse41" = "yes" ; then
@@ -1355,14 +1564,15 @@ fi
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports AVX instructions],
        [gcry_cv_gcc_inline_asm_avx],
-       [if test "$mpi_cpu_arch" != "x86" ; then
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_avx="n/a"
         else
           gcry_cv_gcc_inline_asm_avx=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[void a(void) {
               __asm__("xgetbv; vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):);
-            }]])],
+            }]], [ a(); ] )],
           [gcry_cv_gcc_inline_asm_avx=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then
@@ -1376,14 +1586,15 @@ fi
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports AVX2 instructions],
        [gcry_cv_gcc_inline_asm_avx2],
-       [if test "$mpi_cpu_arch" != "x86" ; then
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_avx2="n/a"
         else
           gcry_cv_gcc_inline_asm_avx2=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[void a(void) {
               __asm__("xgetbv; vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc");
-            }]])],
+            }]], [ a(); ] )],
           [gcry_cv_gcc_inline_asm_avx2=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then
@@ -1393,15 +1604,41 @@ fi
 
 
 #
+# Check whether GCC inline assembler supports VAES and VPCLMUL instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports VAES and VPCLMUL instructions],
+       [gcry_cv_gcc_inline_asm_vaes_vpclmul],
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_vaes_vpclmul="n/a"
+        else
+          gcry_cv_gcc_inline_asm_vaes_vpclmul=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[void a(void) {
+              __asm__("vaesenclast %%ymm7,%%ymm7,%%ymm1\n\t":::"cc");/*256-bit*/
+              __asm__("vaesenclast %%zmm7,%%zmm7,%%zmm1\n\t":::"cc");/*512-bit*/
+              __asm__("vpclmulqdq \$0,%%ymm7,%%ymm7,%%ymm1\n\t":::"cc");/*256-bit*/
+              __asm__("vpclmulqdq \$0,%%zmm7,%%zmm7,%%zmm1\n\t":::"cc");/*512-bit*/
+            }]], [ a(); ] )],
+          [gcry_cv_gcc_inline_asm_vaes_vpclmul=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_vaes_vpclmul" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_VAES_VPCLMUL,1,
+     [Defined if inline assembler supports VAES and VPCLMUL instructions])
+fi
+
+
+#
 # Check whether GCC inline assembler supports BMI2 instructions
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports BMI2 instructions],
        [gcry_cv_gcc_inline_asm_bmi2],
-       [if test "$mpi_cpu_arch" != "x86" ; then
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_bmi2="n/a"
         else
           gcry_cv_gcc_inline_asm_bmi2=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[unsigned int a(unsigned int x, unsigned int y) {
               unsigned int tmp1, tmp2;
               asm ("rorxl %2, %1, %0"
@@ -1411,7 +1648,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports BMI2 instructions],
                    : "=r" (tmp2)
                    : "r0" (x), "rm" (y));
               return tmp1 + tmp2;
-            }]])],
+            }]], [ a(1, 2); ] )],
           [gcry_cv_gcc_inline_asm_bmi2=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_bmi2" = "yes" ; then
@@ -1428,8 +1665,9 @@ if test $amd64_as_feature_detection = yes; then
   AC_CACHE_CHECK([whether GCC assembler handles division correctly],
        [gcry_cv_gcc_as_const_division_ok],
        [gcry_cv_gcc_as_const_division_ok=no
-        AC_COMPILE_IFELSE([AC_LANG_SOURCE(
-          [[__asm__("xorl \$(123456789/12345678), %ebp;\n\t");]])],
+        AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[__asm__(".text\n\tfn:\n\t xorl \$(123456789/12345678), %ebp;\n\t");]],
+            [fn();])],
           [gcry_cv_gcc_as_const_division_ok=yes])])
   if test "$gcry_cv_gcc_as_const_division_ok" = "no" ; then
     #
@@ -1440,8 +1678,9 @@ if test $amd64_as_feature_detection = yes; then
     AC_CACHE_CHECK([whether GCC assembler handles division correctly with "-Wa,--divide"],
          [gcry_cv_gcc_as_const_division_with_wadivide_ok],
          [gcry_cv_gcc_as_const_division_with_wadivide_ok=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
-            [[__asm__("xorl \$(123456789/12345678), %ebp;\n\t");]])],
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+            [[__asm__(".text\n\tfn:\n\t xorl \$(123456789/12345678), %ebp;\n\t");]],
+              [fn();])],
             [gcry_cv_gcc_as_const_division_with_wadivide_ok=yes])])
     if test "$gcry_cv_gcc_as_const_division_with_wadivide_ok" = "no" ; then
       # '-Wa,--divide' did not work, restore old flags.
@@ -1458,14 +1697,16 @@ fi
 if test $amd64_as_feature_detection = yes; then
   AC_CACHE_CHECK([whether GCC assembler is compatible for amd64 assembly implementations],
        [gcry_cv_gcc_amd64_platform_as_ok],
-       [if test "$mpi_cpu_arch" != "x86" ; then
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_amd64_platform_as_ok="n/a"
         else
           gcry_cv_gcc_amd64_platform_as_ok=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[__asm__(
                 /* Test if '.type' and '.size' are supported.  */
                 /* These work only on ELF targets. */
+                ".text\n\t"
                "asmfunc:\n\t"
                 ".size asmfunc,.-asmfunc;\n\t"
                 ".type asmfunc,@function;\n\t"
@@ -1474,7 +1715,7 @@ if test $amd64_as_feature_detection = yes; then
                 * and "-Wa,--divide" workaround failed, this causes assembly
                 * to be disable on this machine. */
                "xorl \$(123456789/12345678), %ebp;\n\t"
-            );]])],
+            );]], [ asmfunc(); ])],
           [gcry_cv_gcc_amd64_platform_as_ok=yes])
         fi])
   if test "$gcry_cv_gcc_amd64_platform_as_ok" = "yes" ; then
@@ -1487,12 +1728,13 @@ if test $amd64_as_feature_detection = yes; then
     AC_CACHE_CHECK([whether GCC assembler is compatible for WIN64 assembly implementations],
       [gcry_cv_gcc_win64_platform_as_ok],
       [gcry_cv_gcc_win64_platform_as_ok=no
-      AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+      AC_LINK_IFELSE([AC_LANG_PROGRAM(
         [[__asm__(
+              ".text\n\t"
               ".globl asmfunc\n\t"
               "asmfunc:\n\t"
               "xorq \$(1234), %rbp;\n\t"
-          );]])],
+          );]], [ asmfunc(); ])],
         [gcry_cv_gcc_win64_platform_as_ok=yes])])
     if test "$gcry_cv_gcc_win64_platform_as_ok" = "yes" ; then
       AC_DEFINE(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS,1,
@@ -1508,30 +1750,24 @@ fi
 #
 AC_CACHE_CHECK([whether GCC assembler is compatible for Intel syntax assembly implementations],
        [gcry_cv_gcc_platform_as_ok_for_intel_syntax],
-       [if test "$mpi_cpu_arch" != "x86" ; then
+       [if test "$mpi_cpu_arch" != "x86" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_platform_as_ok_for_intel_syntax="n/a"
         else
           gcry_cv_gcc_platform_as_ok_for_intel_syntax=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[__asm__(
                 ".intel_syntax noprefix\n\t"
+                ".text\n\t"
+                "actest:\n\t"
                 "pxor xmm1, xmm7;\n\t"
-                /* Intel syntax implementation also use GAS macros, so check
-                 * for them here. */
-                "VAL_A = xmm4\n\t"
-                "VAL_B = xmm2\n\t"
-                ".macro SET_VAL_A p1\n\t"
-                "  VAL_A = \\\\p1 \n\t"
-                ".endm\n\t"
-                ".macro SET_VAL_B p1\n\t"
-                "  VAL_B = \\\\p1 \n\t"
-                ".endm\n\t"
-                "vmovdqa VAL_A, VAL_B;\n\t"
-                "SET_VAL_A eax\n\t"
-                "SET_VAL_B ebp\n\t"
-                "add VAL_A, VAL_B;\n\t"
-                "add VAL_B, 0b10101;\n\t"
-            );]])],
+                "vperm2i128 ymm2, ymm3, ymm0, 1;\n\t"
+                "add eax, ebp;\n\t"
+                "rorx eax, ebp, 1;\n\t"
+                "sub eax, [esp + 4];\n\t"
+                "add dword ptr [esp + eax], 0b10101;\n\t"
+                ".att_syntax prefix\n\t"
+            );]], [ actest(); ])],
           [gcry_cv_gcc_platform_as_ok_for_intel_syntax=yes])
         fi])
 if test "$gcry_cv_gcc_platform_as_ok_for_intel_syntax" = "yes" ; then
@@ -1545,7 +1781,8 @@ fi
 #
 AC_CACHE_CHECK([whether compiler is configured for ARMv6 or newer architecture],
        [gcry_cv_cc_arm_arch_is_v6],
-       [if test "$mpi_cpu_arch" != "arm" ; then
+       [if test "$mpi_cpu_arch" != "arm" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_cc_arm_arch_is_v6="n/a"
         else
           gcry_cv_cc_arm_arch_is_v6=no
@@ -1578,21 +1815,24 @@ fi
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports NEON instructions],
        [gcry_cv_gcc_inline_asm_neon],
-       [if test "$mpi_cpu_arch" != "arm" ; then
+       [if test "$mpi_cpu_arch" != "arm" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_neon="n/a"
         else
           gcry_cv_gcc_inline_asm_neon=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[__asm__(
                 ".syntax unified\n\t"
                 ".arm\n\t"
                 ".fpu neon\n\t"
+                ".text\n\t"
+                "testfn:\n\t"
                 "vld1.64 {%q0-%q1}, [%r0]!;\n\t"
                 "vrev64.8 %q0, %q3;\n\t"
                 "vadd.u64 %q0, %q1;\n\t"
                 "vadd.s64 %d3, %d2, %d3;\n\t"
                 );
-            ]])],
+            ]], [ testfn(); ])],
           [gcry_cv_gcc_inline_asm_neon=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_neon" = "yes" ; then
@@ -1606,17 +1846,20 @@ fi
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports AArch32 Crypto Extension instructions],
        [gcry_cv_gcc_inline_asm_aarch32_crypto],
-       [if test "$mpi_cpu_arch" != "arm" ; then
+       [if test "$mpi_cpu_arch" != "arm" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_aarch32_crypto="n/a"
         else
           gcry_cv_gcc_inline_asm_aarch32_crypto=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[__asm__(
                 ".syntax unified\n\t"
                 ".arch armv8-a\n\t"
                 ".arm\n\t"
                 ".fpu crypto-neon-fp-armv8\n\t"
+                ".text\n\t"
 
+                "testfn:\n\t"
                 "sha1h.32 q0, q0;\n\t"
                 "sha1c.32 q0, q0, q0;\n\t"
                 "sha1p.32 q0, q0, q0;\n\t"
@@ -1636,7 +1879,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports AArch32 Crypto Extension i
 
                 "vmull.p64 q0, d0, d0;\n\t"
                 );
-            ]])],
+            ]], [ testfn(); ])],
           [gcry_cv_gcc_inline_asm_aarch32_crypto=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_aarch32_crypto" = "yes" ; then
@@ -1650,18 +1893,21 @@ fi
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports AArch64 NEON instructions],
        [gcry_cv_gcc_inline_asm_aarch64_neon],
-       [if test "$mpi_cpu_arch" != "aarch64" ; then
+       [if test "$mpi_cpu_arch" != "aarch64" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_aarch64_neon="n/a"
         else
           gcry_cv_gcc_inline_asm_aarch64_neon=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[__asm__(
                 ".cpu generic+simd\n\t"
+                ".text\n\t"
+                "testfn:\n\t"
                 "mov w0, \#42;\n\t"
                 "dup v0.8b, w0;\n\t"
                 "ld4 {v0.8b,v1.8b,v2.8b,v3.8b},[x0],\#32;\n\t"
                 );
-            ]])],
+            ]], [ testfn(); ])],
           [gcry_cv_gcc_inline_asm_aarch64_neon=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_aarch64_neon" = "yes" ; then
@@ -1675,14 +1921,16 @@ fi
 #
 AC_CACHE_CHECK([whether GCC inline assembler supports AArch64 Crypto Extension instructions],
        [gcry_cv_gcc_inline_asm_aarch64_crypto],
-       [if test "$mpi_cpu_arch" != "aarch64" ; then
+       [if test "$mpi_cpu_arch" != "aarch64" ||
+           test "$try_asm_modules" != "yes" ; then
           gcry_cv_gcc_inline_asm_aarch64_crypto="n/a"
         else
           gcry_cv_gcc_inline_asm_aarch64_crypto=no
-          AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
           [[__asm__(
                 ".cpu generic+simd+crypto\n\t"
-
+                ".text\n\t"
+                "testfn:\n\t"
                 "mov w0, \#42;\n\t"
                 "dup v0.8b, w0;\n\t"
                 "ld4 {v0.8b,v1.8b,v2.8b,v3.8b},[x0],\#32;\n\t"
@@ -1707,7 +1955,7 @@ AC_CACHE_CHECK([whether GCC inline assembler supports AArch64 Crypto Extension i
                 "pmull v0.1q, v0.1d, v31.1d;\n\t"
                 "pmull2 v0.1q, v0.2d, v31.2d;\n\t"
                 );
-            ]])],
+            ]], [ testfn(); ])],
           [gcry_cv_gcc_inline_asm_aarch64_crypto=yes])
         fi])
 if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" = "yes" ; then
@@ -1716,6 +1964,217 @@ if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" = "yes" ; then
 fi
 
 
+#
+# Check whether PowerPC AltiVec/VSX intrinsics
+#
+AC_CACHE_CHECK([whether compiler supports PowerPC AltiVec/VSX intrinsics],
+      [gcry_cv_cc_ppc_altivec],
+      [if test "$mpi_cpu_arch" != "ppc" ||
+         test "$try_asm_modules" != "yes" ; then
+       gcry_cv_cc_ppc_altivec="n/a"
+      else
+       gcry_cv_cc_ppc_altivec=no
+       AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+       [[#include <altivec.h>
+         typedef vector unsigned char block;
+         typedef vector unsigned int vecu32;
+         block fn(block in)
+         {
+           block t = vec_perm (in, in, vec_vsx_ld (0, (unsigned char*)0));
+           vecu32 y = vec_vsx_ld (0, (unsigned int*)0);
+           return vec_cipher_be (t, in) ^ (block)y;
+         }
+         ]])],
+       [gcry_cv_cc_ppc_altivec=yes])
+      fi])
+if test "$gcry_cv_cc_ppc_altivec" = "yes" ; then
+    AC_DEFINE(HAVE_COMPATIBLE_CC_PPC_ALTIVEC,1,
+           [Defined if underlying compiler supports PowerPC AltiVec/VSX/crypto intrinsics])
+fi
+
+_gcc_cflags_save=$CFLAGS
+CFLAGS="$CFLAGS -maltivec -mvsx -mcrypto"
+
+if test "$gcry_cv_cc_ppc_altivec" = "no" &&
+    test "$mpi_cpu_arch" = "ppc" &&
+    test "$try_asm_modules" == "yes" ; then
+  AC_CACHE_CHECK([whether compiler supports PowerPC AltiVec/VSX/crypto intrinsics with extra GCC flags],
+    [gcry_cv_cc_ppc_altivec_cflags],
+    [gcry_cv_cc_ppc_altivec_cflags=no
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+      [[#include <altivec.h>
+       typedef vector unsigned char block;
+       typedef vector unsigned int vecu32;
+       block fn(block in)
+       {
+         block t = vec_perm (in, in, vec_vsx_ld (0, (unsigned char*)0));
+         vecu32 y = vec_vsx_ld (0, (unsigned int*)0);
+         return vec_cipher_be (t, in) ^ (block)y;
+       }]])],
+      [gcry_cv_cc_ppc_altivec_cflags=yes])])
+  if test "$gcry_cv_cc_ppc_altivec_cflags" = "yes" ; then
+    AC_DEFINE(HAVE_COMPATIBLE_CC_PPC_ALTIVEC,1,
+             [Defined if underlying compiler supports PowerPC AltiVec/VSX/crypto intrinsics])
+    AC_DEFINE(HAVE_COMPATIBLE_CC_PPC_ALTIVEC_WITH_CFLAGS,1,
+             [Defined if underlying compiler supports PowerPC AltiVec/VSX/crypto intrinsics with extra GCC flags])
+  fi
+fi
+
+AM_CONDITIONAL(ENABLE_PPC_VCRYPTO_EXTRA_CFLAGS,
+              test "$gcry_cv_cc_ppc_altivec_cflags" = "yes")
+
+# Restore flags.
+CFLAGS=$_gcc_cflags_save;
+
+
+#
+# Check whether GCC inline assembler supports PowerPC AltiVec/VSX/crypto instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports PowerPC AltiVec/VSX/crypto instructions],
+       [gcry_cv_gcc_inline_asm_ppc_altivec],
+       [if test "$mpi_cpu_arch" != "ppc" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_ppc_altivec="n/a"
+        else
+          gcry_cv_gcc_inline_asm_ppc_altivec=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[__asm__(".globl testfn;\n"
+                    ".text\n\t"
+                   "testfn:\n"
+                   "stvx %v31,%r12,%r0;\n"
+                   "lvx  %v20,%r12,%r0;\n"
+                   "vcipher %v0, %v1, %v22;\n"
+                   "lxvw4x %vs32, %r0, %r1;\n"
+                   "vadduwm %v0, %v1, %v22;\n"
+                   "vshasigmaw %v0, %v1, 0, 15;\n"
+                   "vshasigmad %v0, %v1, 0, 15;\n"
+                   "vpmsumd %v11, %v11, %v11;\n"
+                 );
+            ]], [ testfn(); ] )],
+          [gcry_cv_gcc_inline_asm_ppc_altivec=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_ppc_altivec" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC,1,
+     [Defined if inline assembler supports PowerPC AltiVec/VSX/crypto instructions])
+fi
+
+
+#
+# Check whether GCC inline assembler supports PowerISA 3.00 instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports PowerISA 3.00 instructions],
+       [gcry_cv_gcc_inline_asm_ppc_arch_3_00],
+       [if test "$mpi_cpu_arch" != "ppc" ||
+           test "$try_asm_modules" != "yes" ; then
+          gcry_cv_gcc_inline_asm_ppc_arch_3_00="n/a"
+        else
+          gcry_cv_gcc_inline_asm_ppc_arch_3_00=no
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+          [[__asm__(".text\n\t"
+                   ".globl testfn;\n"
+                   "testfn:\n"
+                   "stxvb16x %r1,%v12,%v30;\n"
+                 );
+            ]], [ testfn(); ])],
+          [gcry_cv_gcc_inline_asm_ppc_arch_3_00=yes])
+        fi])
+if test "$gcry_cv_gcc_inline_asm_ppc_arch_3_00" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_PPC_ARCH_3_00,1,
+     [Defined if inline assembler supports PowerISA 3.00 instructions])
+fi
+
+
+#
+# Check whether GCC inline assembler supports zSeries instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports zSeries instructions],
+      [gcry_cv_gcc_inline_asm_s390x],
+      [if test "$mpi_cpu_arch" != "s390x" ||
+         test "$try_asm_modules" != "yes" ; then
+         gcry_cv_gcc_inline_asm_s390x="n/a"
+       else
+         gcry_cv_gcc_inline_asm_s390x=no
+         AC_LINK_IFELSE([AC_LANG_PROGRAM(
+         [[typedef unsigned int u128_t __attribute__ ((mode (TI)));
+           unsigned int testfunc(unsigned int x, void *y, unsigned int z)
+           {
+             unsigned long fac[8];
+             register unsigned long reg0 asm("0") = 0;
+             register unsigned long reg1 asm("1") = x;
+             u128_t r1 = ((u128_t)(unsigned long)y << 64) | (unsigned long)z;
+             u128_t r2 = 0;
+             u128_t r3 = 0;
+             asm volatile (".insn rre,0xb92e << 16, %[r1], %[r2]\n\t"
+                           : [r1] "+a" (r1), [r2] "+a" (r2)
+                           : "r" (reg0), "r" (reg1)
+                           : "cc", "memory");
+             asm volatile (".insn rrf,0xb929 << 16, %[r1], %[r2], %[r3], 0\n\t"
+                           : [r1] "+a" (r1), [r2] "+a" (r2), [r3] "+a" (r3)
+                           : "r" (reg0), "r" (reg1)
+                           : "cc", "memory");
+             reg0 = 8 - 1;
+             asm ("stfle %1\n\t"
+                  : "+d" (reg0), "=Q" (fac[0])
+                  :
+                  : "cc", "memory");
+             asm volatile ("mvc 0(16, %0), 0(%1)\n\t"
+                           :
+                           : "a" (y), "a" (fac)
+                           : "memory");
+             asm volatile ("xc 0(16, %0), 0(%0)\n\t"
+                           :
+                           : "a" (fac)
+                           : "memory");
+             asm volatile ("risbgn %%r11, %%r11, 0, 129, 0\n\t"
+                           :
+                           :
+                           : "memory", "r11");
+             asm volatile ("algrk %%r14, %%r14, %%r14\n\t"
+                           :
+                           :
+                           : "memory", "r14");
+             return (unsigned int)r1 ^ reg0;
+           }
+           ]] , [ testfunc(0, 0, 0); ])],
+         [gcry_cv_gcc_inline_asm_s390x=yes])
+       fi])
+if test "$gcry_cv_gcc_inline_asm_s390x" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_S390X,1,
+     [Defined if inline assembler supports zSeries instructions])
+fi
+
+
+#
+# Check whether GCC inline assembler supports zSeries vector instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports zSeries vector instructions],
+      [gcry_cv_gcc_inline_asm_s390x_vx],
+      [if test "$mpi_cpu_arch" != "s390x" ||
+         test "$try_asm_modules" != "yes" ; then
+         gcry_cv_gcc_inline_asm_s390x_vx="n/a"
+       else
+         gcry_cv_gcc_inline_asm_s390x_vx=no
+         if test "$gcry_cv_gcc_inline_asm_s390x" = "yes" ; then
+           AC_LINK_IFELSE([AC_LANG_PROGRAM(
+           [[void testfunc(void)
+             {
+               asm volatile (".machine \"z13+vx\"\n\t"
+                             "vx %%v0, %%v1, %%v31\n\t"
+                             "verllf %%v11, %%v11, (16)(0)\n\t"
+                             :
+                             :
+                             : "memory");
+             }
+             ]], [ testfunc(); ])],
+           [gcry_cv_gcc_inline_asm_s390x_vx=yes])
+         fi
+       fi])
+if test "$gcry_cv_gcc_inline_asm_s390x_vx" = "yes" ; then
+   AC_DEFINE(HAVE_GCC_INLINE_ASM_S390X_VX,1,
+     [Defined if inline assembler supports zSeries vector instructions])
+fi
+
+
 #######################################
 #### Checks for library functions. ####
 #######################################
@@ -1728,7 +2187,8 @@ AC_CHECK_FUNCS(strtoul memmove stricmp atexit raise)
 # Other checks
 AC_CHECK_FUNCS(strerror rand mmap getpagesize sysconf waitpid wait4)
 AC_CHECK_FUNCS(gettimeofday getrusage gethrtime clock_gettime syslog)
-AC_CHECK_FUNCS(syscall fcntl ftruncate flockfile)
+AC_CHECK_FUNCS(syscall fcntl ftruncate flockfile getauxval elf_aux_info)
+AC_CHECK_FUNCS(explicit_bzero explicit_memset getentropy)
 
 GNUPG_CHECK_MLOCK
 
@@ -1742,13 +2202,12 @@ AC_REPLACE_FUNCS([getpid clock])
 # Check whether it is necessary to link against libdl.
 #
 DL_LIBS=""
-if test "$use_hmac_binary_check" = yes ; then
+if test "$use_hmac_binary_check" != no ; then
   _gcry_save_libs="$LIBS"
   LIBS=""
   AC_SEARCH_LIBS(dlopen, c dl,,,)
   DL_LIBS=$LIBS
   LIBS="$_gcry_save_libs"
-  LIBGCRYPT_CONFIG_LIBS="${LIBGCRYPT_CONFIG_LIBS} ${DL_LIBS}"
 fi
 AC_SUBST(DL_LIBS)
 
@@ -1801,7 +2260,9 @@ fi
 if test "$random" = "default"; then
 
     # Select default value.
-    if test "$ac_cv_have_dev_random" = yes; then
+    if test "$ac_cv_func_getentropy" = yes; then
+        random_modules="getentropy"
+    elif test "$ac_cv_have_dev_random" = yes; then
         # Try Linuxish random device.
         random_modules="linux"
     else
@@ -1845,8 +2306,8 @@ AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes)
 # This is handy for debugging so the compiler doesn't rearrange
 # things and eliminate variables.
 AC_ARG_ENABLE(optimization,
-       AC_HELP_STRING([--disable-optimization],
-                     [disable compiler optimization]),
+       AS_HELP_STRING([--disable-optimization],
+                      [disable compiler optimization]),
                       [if test $enableval = no ; then
                          CFLAGS=`echo $CFLAGS | sed 's/-O[[0-9]]//'`
                        fi])
@@ -1930,6 +2391,11 @@ if test x"$aesnisupport" = xyes ; then
     aesnisupport="no (unsupported by compiler)"
   fi
 fi
+if test x"$shaextsupport" = xyes ; then
+  if test "$gcry_cv_gcc_inline_asm_shaext" != "yes" ; then
+    shaextsupport="no (unsupported by compiler)"
+  fi
+fi
 if test x"$pclmulsupport" = xyes ; then
   if test "$gcry_cv_gcc_inline_asm_pclmul" != "yes" ; then
     pclmulsupport="no (unsupported by compiler)"
@@ -1969,6 +2435,10 @@ if test x"$aesnisupport" = xyes ; then
   AC_DEFINE(ENABLE_AESNI_SUPPORT, 1,
             [Enable support for Intel AES-NI instructions.])
 fi
+if test x"$shaextsupport" = xyes ; then
+  AC_DEFINE(ENABLE_SHAEXT_SUPPORT, 1,
+            [Enable support for Intel SHAEXT instructions.])
+fi
 if test x"$pclmulsupport" = xyes ; then
   AC_DEFINE(ENABLE_PCLMUL_SUPPORT, 1,
             [Enable support for Intel PCLMUL instructions.])
@@ -1993,6 +2463,10 @@ if test x"$armcryptosupport" = xyes ; then
   AC_DEFINE(ENABLE_ARM_CRYPTO_SUPPORT,1,
             [Enable support for ARMv8 Crypto Extension instructions.])
 fi
+if test x"$ppccryptosupport" = xyes ; then
+  AC_DEFINE(ENABLE_PPC_CRYPTO_SUPPORT,1,
+            [Enable support for POWER 8 (PowerISA 2.07) crypto extension.])
+fi
 if test x"$jentsupport" = xyes ; then
   AC_DEFINE(ENABLE_JENT_SUPPORT, 1,
             [Enable support for the jitter entropy collector.])
@@ -2007,6 +2481,11 @@ if test x"$drngsupport" = xyes ; then
 fi
 
 
+if test x"$force_soft_hwfeatures" = xyes ; then
+  AC_DEFINE(ENABLE_FORCE_SOFT_HWFEATURES, 1,
+            [Enable forcing 'soft' HW feature bits on (for testing).])
+fi
+
 # Define conditional sources and config.h symbols depending on the
 # selected ciphers, pubkey-ciphers, digests, kdfs, and random modules.
 
@@ -2018,7 +2497,7 @@ if test "$found" = "1"; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS arcfour-amd64.lo"
       ;;
    esac
 fi
@@ -2031,11 +2510,11 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS blowfish-amd64.lo"
       ;;
       arm*-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish-arm.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS blowfish-arm.lo"
       ;;
    esac
 fi
@@ -2048,11 +2527,11 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS cast5-amd64.lo"
       ;;
       arm*-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5-arm.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS cast5-arm.lo"
       ;;
    esac
 fi
@@ -2065,7 +2544,7 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS des-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS des-amd64.lo"
       ;;
    esac
 fi
@@ -2078,37 +2557,68 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-amd64.lo"
 
          # Build with the SSSE3 implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ssse3-amd64.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ssse3-amd64-asm.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-ssse3-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-ssse3-amd64-asm.lo"
+
+         # Build with the VAES/AVX2 implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-vaes.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-vaes-avx2-amd64.lo"
       ;;
       arm*-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-arm.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-arm.lo"
 
          # Build with the ARMv8/AArch32 CE implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-ce.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-aarch32-ce.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-armv8-ce.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-armv8-aarch32-ce.lo"
       ;;
       aarch64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-aarch64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-aarch64.lo"
 
          # Build with the ARMv8/AArch64 CE implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-ce.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-aarch64-ce.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-armv8-ce.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-armv8-aarch64-ce.lo"
+      ;;
+      powerpc64le-*-*)
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-ppc.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-ppc9le.lo"
+
+         if test "$gcry_cv_gcc_inline_asm_ppc_altivec" = "yes" &&
+            test "$gcry_cv_gcc_inline_asm_ppc_arch_3_00" = "yes" ; then
+            # Build with AES-GCM bulk implementation for P10
+            GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-gcm-p10le.lo"
+            GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-p10le.lo"
+         fi
+      ;;
+      powerpc64-*-*)
+         # Big-Endian.
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-ppc.lo"
+      ;;
+      powerpc-*-*)
+         # Big-Endian.
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-ppc.lo"
+      ;;
+      s390x-*-*)
+         # Big-Endian.
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-s390x.lo"
       ;;
    esac
 
    case "$mpi_cpu_arch" in
      x86)
          # Build with the AES-NI implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-aesni.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-aesni.lo"
 
          # Build with the Padlock implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-padlock.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS rijndael-padlock.lo"
       ;;
    esac
 fi
@@ -2121,20 +2631,20 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS twofish-amd64.lo"
 
          if test x"$avx2support" = xyes ; then
             # Build with the AVX2 implementation
-            GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-avx2-amd64.lo"
+            GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS twofish-avx2-amd64.lo"
          fi
       ;;
       arm*-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-arm.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS twofish-arm.lo"
       ;;
       aarch64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-aarch64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS twofish-aarch64.lo"
       ;;
    esac
 fi
@@ -2147,18 +2657,18 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the SSE2 implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-sse2-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS serpent-sse2-amd64.lo"
       ;;
    esac
 
    if test x"$avx2support" = xyes ; then
       # Build with the AVX2 implementation
-      GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-avx2-amd64.lo"
+      GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS serpent-avx2-amd64.lo"
    fi
 
    if test x"$neonsupport" = xyes ; then
       # Build with the NEON implementation
-      GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-armv7-neon.lo"
+      GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS serpent-armv7-neon.lo"
    fi
 fi
 
@@ -2182,25 +2692,28 @@ if test "$found" = "1" ; then
    case "${host}" in
       arm*-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-arm.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS camellia-arm.lo"
       ;;
       aarch64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aarch64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS camellia-aarch64.lo"
       ;;
    esac
 
    if test x"$avxsupport" = xyes ; then
       if test x"$aesnisupport" = xyes ; then
         # Build with the AES-NI/AVX implementation
-        GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aesni-avx-amd64.lo"
+        GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS camellia-aesni-avx-amd64.lo"
       fi
    fi
 
    if test x"$avx2support" = xyes ; then
       if test x"$aesnisupport" = xyes ; then
         # Build with the AES-NI/AVX2 implementation
-        GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aesni-avx2-amd64.lo"
+        GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS camellia-aesni-avx2-amd64.lo"
+
+        # Build with the VAES/AVX2 implementation
+        GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS camellia-vaes-avx2-amd64.lo"
       fi
    fi
 fi
@@ -2219,13 +2732,13 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS salsa20-amd64.lo"
       ;;
    esac
 
    if test x"$neonsupport" = xyes ; then
      # Build with the NEON implementation
-     GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20-armv7-neon.lo"
+     GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS salsa20-armv7-neon.lo"
    fi
 fi
 
@@ -2243,29 +2756,49 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-sse2-amd64.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ssse3-amd64.lo"
-         GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-avx2-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS chacha20-amd64-ssse3.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS chacha20-amd64-avx2.lo"
+      ;;
+      aarch64-*-*)
+         # Build with the assembly implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS chacha20-aarch64.lo"
+      ;;
+      powerpc64le-*-*)
+         # Build with the ppc8 vector implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS chacha20-ppc.lo"
+      ;;
+      powerpc64-*-*)
+         # Build with the ppc8 vector implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS chacha20-ppc.lo"
+      ;;
+      powerpc-*-*)
+         # Build with the ppc8 vector implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS chacha20-ppc.lo"
+      ;;
+      s390x-*-*)
+         # Build with the s390x/zSeries vector implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS chacha20-s390x.lo"
       ;;
    esac
 
    if test x"$neonsupport" = xyes ; then
      # Build with the NEON implementation
-     GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-armv7-neon.lo"
+     GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS chacha20-armv7-neon.lo"
    fi
 fi
 
-case "${host}" in
-   x86_64-*-*)
-      # Build with the assembly implementation
-      GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-sse2-amd64.lo"
-      GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-avx2-amd64.lo"
-   ;;
-esac
+LIST_MEMBER(sm4, $enabled_ciphers)
+if test "$found" = "1" ; then
+   GCRYPT_CIPHERS="$GCRYPT_CIPHERS sm4.lo"
+   AC_DEFINE(USE_SM4, 1, [Defined if this module should be included])
 
-if test x"$neonsupport" = xyes ; then
-   # Build with the NEON implementation
-   GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-armv7-neon.lo"
+   case "${host}" in
+      x86_64-*-*)
+         # Build with the assembly implementation
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS sm4-aesni-avx-amd64.lo"
+         GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS sm4-aesni-avx2-amd64.lo"
+      ;;
+   esac
 fi
 
 LIST_MEMBER(dsa, $enabled_pubkey_ciphers)
@@ -2290,7 +2823,8 @@ LIST_MEMBER(ecc, $enabled_pubkey_ciphers)
 if test "$found" = "1" ; then
    GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS \
                           ecc.lo ecc-curves.lo ecc-misc.lo \
-                          ecc-ecdsa.lo ecc-eddsa.lo ecc-gost.lo"
+                          ecc-ecdh.lo ecc-ecdsa.lo ecc-eddsa.lo ecc-gost.lo \
+                          ecc-sm2.lo"
    AC_DEFINE(USE_ECC, 1, [Defined if this module should be included])
 fi
 
@@ -2302,7 +2836,21 @@ if test "$found" = "1" ; then
    case "${host}" in
       i?86-*-* | x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc-intel-pclmul.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS crc-intel-pclmul.lo"
+      ;;
+      aarch64-*-*)
+         # Build with the assembly implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS crc-armv8-ce.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS crc-armv8-aarch64-ce.lo"
+      ;;
+      powerpc64le-*-*)
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS crc-ppc.lo"
+      ;;
+      powerpc64-*-*)
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS crc-ppc.lo"
+      ;;
+      powerpc-*-*)
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS crc-ppc.lo"
       ;;
    esac
 fi
@@ -2355,18 +2903,38 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-ssse3-amd64.lo"
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-avx-amd64.lo"
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-avx2-bmi2-amd64.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-ssse3-amd64.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-avx-amd64.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-avx2-bmi2-amd64.lo"
       ;;
       arm*-*-*)
          # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-armv8-aarch32-ce.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-armv8-aarch32-ce.lo"
       ;;
       aarch64-*-*)
          # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-armv8-aarch64-ce.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-armv8-aarch64-ce.lo"
+      ;;
+      powerpc64le-*-*)
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-ppc.lo"
+      ;;
+      powerpc64-*-*)
+         # Big-Endian.
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-ppc.lo"
       ;;
+      powerpc-*-*)
+         # Big-Endian.
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-ppc.lo"
+   esac
+
+   case "$mpi_cpu_arch" in
+     x86)
+       # Build with the SHAEXT implementation
+       GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha256-intel-shaext.lo"
+     ;;
    esac
 fi
 
@@ -2378,19 +2946,36 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-ssse3-amd64.lo"
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx-amd64.lo"
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx2-bmi2-amd64.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-ssse3-amd64.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-avx-amd64.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-avx2-bmi2-amd64.lo"
+      ;;
+      i?86-*-*)
+         # Build with the assembly implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-ssse3-i386.lo"
       ;;
       arm*-*-*)
          # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-arm.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-arm.lo"
+      ;;
+      powerpc64le-*-*)
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-ppc.lo"
       ;;
+      powerpc64-*-*)
+         # Big-Endian.
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-ppc.lo"
+      ;;
+      powerpc-*-*)
+         # Big-Endian.
+         # Build with the crypto extension implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-ppc.lo"
    esac
 
    if test x"$neonsupport" = xyes ; then
      # Build with the NEON implementation
-     GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-armv7-neon.lo"
+     GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha512-armv7-neon.lo"
    fi
 fi
 
@@ -2408,7 +2993,7 @@ if test "$found" = "1" ; then
 
    if test x"$neonsupport" = xyes ; then
      # Build with the NEON implementation
-     GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak-armv7-neon.lo"
+     GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS keccak-armv7-neon.lo"
    fi
 fi
 
@@ -2426,7 +3011,7 @@ if test "$found" = "1" ; then
    case "${host}" in
       x86_64-*-*)
          # Build with the assembly implementation
-         GCRYPT_DIGESTS="$GCRYPT_DIGESTS whirlpool-sse2-amd64.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS whirlpool-sse2-amd64.lo"
       ;;
    esac
 fi
@@ -2435,6 +3020,31 @@ LIST_MEMBER(blake2, $enabled_digests)
 if test "$found" = "1" ; then
    GCRYPT_DIGESTS="$GCRYPT_DIGESTS blake2.lo"
    AC_DEFINE(USE_BLAKE2, 1, [Defined if this module should be included])
+
+   case "${host}" in
+      x86_64-*-*)
+         # Build with the assembly implementation
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS blake2b-amd64-avx2.lo"
+         GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS blake2s-amd64-avx.lo"
+      ;;
+   esac
+fi
+
+LIST_MEMBER(sm3, $enabled_digests)
+if test "$found" = "1" ; then
+   GCRYPT_DIGESTS="$GCRYPT_DIGESTS sm3.lo"
+   AC_DEFINE(USE_SM3, 1, [Defined if this module should be included])
+
+   case "${host}" in
+     x86_64-*-*)
+        # Build with the assembly implementation
+        GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sm3-avx-bmi2-amd64.lo"
+     ;;
+     aarch64-*-*)
+        # Build with the assembly implementation
+        GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sm3-aarch64.lo"
+     ;;
+   esac
 fi
 
 # SHA-1 needs to be included always for example because it is used by
@@ -2445,18 +3055,50 @@ AC_DEFINE(USE_SHA1, 1,   [Defined if this module should be included])
 case "${host}" in
   x86_64-*-*)
     # Build with the assembly implementation
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-ssse3-amd64.lo"
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-avx-amd64.lo"
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-avx-bmi2-amd64.lo"
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha1-ssse3-amd64.lo"
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha1-avx-amd64.lo"
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha1-avx-bmi2-amd64.lo"
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha1-avx2-bmi2-amd64.lo"
   ;;
   arm*-*-*)
     # Build with the assembly implementation
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv7-neon.lo"
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv8-aarch32-ce.lo"
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha1-armv7-neon.lo"
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha1-armv8-aarch32-ce.lo"
   ;;
   aarch64-*-*)
     # Build with the assembly implementation
-    GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv8-aarch64-ce.lo"
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha1-armv8-aarch64-ce.lo"
+  ;;
+esac
+
+case "$mpi_cpu_arch" in
+  x86)
+    # Build with the SHAEXT implementation
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS sha1-intel-shaext.lo"
+  ;;
+esac
+
+# Arch specific GCM implementations
+case "${host}" in
+  i?86-*-* | x86_64-*-*)
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS cipher-gcm-intel-pclmul.lo"
+  ;;
+  arm*-*-*)
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS cipher-gcm-armv7-neon.lo"
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS cipher-gcm-armv8-aarch32-ce.lo"
+  ;;
+  aarch64-*-*)
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS cipher-gcm-armv8-aarch64-ce.lo"
+  ;;
+  powerpc64le-*-* | powerpc64-*-* | powerpc-*-*)
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS cipher-gcm-ppc.lo"
+  ;;
+esac
+
+# Arch specific MAC implementations
+case "${host}" in
+  s390x-*-*)
+    GCRYPT_ASM_DIGESTS="$GCRYPT_ASM_DIGESTS poly1305-s390x.lo"
   ;;
 esac
 
@@ -2466,10 +3108,16 @@ if test "$found" = "1" ; then
    AC_DEFINE(USE_SCRYPT, 1, [Defined if this module should be included])
 fi
 
+LIST_MEMBER(getentropy, $random_modules)
+if test "$found" = "1" ; then
+   GCRYPT_RANDOM="$GCRYPT_RANDOM rndgetentropy.lo"
+   AC_DEFINE(USE_RNDGETENTROPY, 1, [Defined if the getentropy RNG should be used.])
+fi
+
 LIST_MEMBER(linux, $random_modules)
 if test "$found" = "1" ; then
-   GCRYPT_RANDOM="$GCRYPT_RANDOM rndlinux.lo"
-   AC_DEFINE(USE_RNDLINUX, 1, [Defined if the /dev/random RNG should be used.])
+   GCRYPT_RANDOM="$GCRYPT_RANDOM rndoldlinux.lo"
+   AC_DEFINE(USE_RNDOLDLINUX, 1, [Defined if the /dev/random RNG should be used.])
 fi
 
 LIST_MEMBER(unix, $random_modules)
@@ -2498,6 +3146,12 @@ if test "$found" = "1" ; then
              [Defined if the WindowsCE specific RNG should be used.])
 fi
 
+if test "$try_asm_modules" = yes ; then
+  # Build with assembly implementations
+  GCRYPT_CIPHERS="$GCRYPT_CIPHERS $GCRYPT_ASM_CIPHERS"
+  GCRYPT_DIGESTS="$GCRYPT_DIGESTS $GCRYPT_ASM_DIGESTS"
+fi
+
 AC_SUBST([GCRYPT_CIPHERS])
 AC_SUBST([GCRYPT_PUBKEY_CIPHERS])
 AC_SUBST([GCRYPT_DIGESTS])
@@ -2533,7 +3187,7 @@ GCRYPT_HWF_MODULES=
 case "$mpi_cpu_arch" in
      x86)
         AC_DEFINE(HAVE_CPU_ARCH_X86, 1,   [Defined for the x86 platforms])
-        GCRYPT_HWF_MODULES="hwf-x86.lo"
+        GCRYPT_HWF_MODULES="libgcrypt_la-hwf-x86.lo"
         ;;
      alpha)
         AC_DEFINE(HAVE_CPU_ARCH_ALPHA, 1, [Defined for Alpha platforms])
@@ -2549,14 +3203,19 @@ case "$mpi_cpu_arch" in
         ;;
      ppc)
         AC_DEFINE(HAVE_CPU_ARCH_PPC, 1,   [Defined for PPC platforms])
+        GCRYPT_HWF_MODULES="libgcrypt_la-hwf-ppc.lo"
         ;;
      arm)
         AC_DEFINE(HAVE_CPU_ARCH_ARM, 1,   [Defined for ARM platforms])
-        GCRYPT_HWF_MODULES="hwf-arm.lo"
+        GCRYPT_HWF_MODULES="libgcrypt_la-hwf-arm.lo"
         ;;
      aarch64)
         AC_DEFINE(HAVE_CPU_ARCH_ARM, 1,   [Defined for ARM AArch64 platforms])
-        GCRYPT_HWF_MODULES="hwf-arm.lo"
+        GCRYPT_HWF_MODULES="libgcrypt_la-hwf-arm.lo"
+        ;;
+     s390x)
+        AC_DEFINE(HAVE_CPU_ARCH_S390X, 1, [Defined for s390x/zSeries platforms])
+        GCRYPT_HWF_MODULES="libgcrypt_la-hwf-s390x.lo"
         ;;
 esac
 AC_SUBST([GCRYPT_HWF_MODULES])
@@ -2566,7 +3225,7 @@ AC_SUBST([GCRYPT_HWF_MODULES])
 # Option to disable building of doc file
 #
 build_doc=yes
-AC_ARG_ENABLE([doc], AC_HELP_STRING([--disable-doc],
+AC_ARG_ENABLE([doc], AS_HELP_STRING([--disable-doc],
                                     [do not build the documentation]),
                      build_doc=$enableval, build_doc=yes)
 AM_CONDITIONAL([BUILD_DOC], [test "x$build_doc" != xno])
@@ -2581,13 +3240,15 @@ AC_DEFINE_UNQUOTED(BUILD_REVISION, "$BUILD_REVISION",
                    [GIT commit id revision used to build this package])
 
 changequote(,)dnl
-BUILD_FILEVERSION=`echo "$VERSION" | sed 's/\([0-9.]*\).*/\1./;s/\./,/g'`
+BUILD_VERSION=`echo "$PACKAGE_VERSION" | sed 's/\([0-9.]*\).*/\1./'`
 changequote([,])dnl
-BUILD_FILEVERSION="${BUILD_FILEVERSION}mym4_revision_dec"
+BUILD_VERSION="${BUILD_VERSION}mym4_revision_dec"
+BUILD_FILEVERSION=`echo "${BUILD_VERSION}" | tr . ,`
+AC_SUBST(BUILD_VERSION)
 AC_SUBST(BUILD_FILEVERSION)
 
 AC_ARG_ENABLE([build-timestamp],
-  AC_HELP_STRING([--enable-build-timestamp],
+  AS_HELP_STRING([--enable-build-timestamp],
                  [set an explicit build timestamp for reproducibility.
                   (default is the current time in ISO-8601 format)]),
      [if test "$enableval" = "yes"; then
@@ -2613,6 +3274,7 @@ doc/Makefile
 src/Makefile
 src/gcrypt.h
 src/libgcrypt-config
+src/libgcrypt.pc
 src/versioninfo.rc
 tests/Makefile
 ])
@@ -2637,8 +3299,10 @@ GCRY_MSG_WRAP([Enabled pubkey algorithms:],[$enabled_pubkey_ciphers])
 GCRY_MSG_SHOW([Random number generator:  ],[$random])
 GCRY_MSG_SHOW([Try using jitter entropy: ],[$jentsupport])
 GCRY_MSG_SHOW([Using linux capabilities: ],[$use_capabilities])
+GCRY_MSG_SHOW([FIPS module version:      ],[$fips_module_version])
 GCRY_MSG_SHOW([Try using Padlock crypto: ],[$padlocksupport])
 GCRY_MSG_SHOW([Try using AES-NI crypto:  ],[$aesnisupport])
+GCRY_MSG_SHOW([Try using Intel SHAEXT:   ],[$shaextsupport])
 GCRY_MSG_SHOW([Try using Intel PCLMUL:   ],[$pclmulsupport])
 GCRY_MSG_SHOW([Try using Intel SSE4.1:   ],[$sse41support])
 GCRY_MSG_SHOW([Try using DRNG (RDRAND):  ],[$drngsupport])
@@ -2646,6 +3310,7 @@ GCRY_MSG_SHOW([Try using Intel AVX:      ],[$avxsupport])
 GCRY_MSG_SHOW([Try using Intel AVX2:     ],[$avx2support])
 GCRY_MSG_SHOW([Try using ARM NEON:       ],[$neonsupport])
 GCRY_MSG_SHOW([Try using ARMv8 crypto:   ],[$armcryptosupport])
+GCRY_MSG_SHOW([Try using PPC crypto:     ],[$ppccryptosupport])
 GCRY_MSG_SHOW([],[])
 
 if test "x${gpg_config_script_warn}" != x; then
index 6a7cc8e..706afdc 100644 (file)
@@ -18,7 +18,6 @@
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
 EXTRA_DIST = README.apichanges HACKING DCO \
-            libgcrypt-modules.eps fips-fsm.eps \
             libgcrypt-modules.png fips-fsm.png \
              libgcrypt-modules.pdf fips-fsm.pdf \
             yat2m.c
@@ -26,8 +25,7 @@ EXTRA_DIST = README.apichanges HACKING DCO \
 DISTCLEANFILES = gcrypt.cps yat2m-stamp.tmp yat2m-stamp $(myman_pages)
 CLEANFILES = yat2m
 
-BUILT_SOURCES = libgcrypt-modules.eps fips-fsm.eps \
-                libgcrypt-modules.png fips-fsm.png \
+BUILT_SOURCES = libgcrypt-modules.png fips-fsm.png \
                 libgcrypt-modules.pdf fips-fsm.pdf
 
 info_TEXINFOS = gcrypt.texi
@@ -42,7 +40,8 @@ myman_pages   = hmac256.1
 man_MANS = $(myman_pages)
 
 yat2m: yat2m.c
-       $(CC_FOR_BUILD) -o $@ $(srcdir)/yat2m.c
+       $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \
+           $(CPPFLAGS_FOR_BUILD) -o $@ $(srcdir)/yat2m.c
 
 .fig.png:
        fig2dev -L png `test -f '$<' || echo '$(srcdir)/'`$< $@
diff --git a/doc/Makefile.in b/doc/Makefile.in
deleted file mode 100644 (file)
index 89c3b30..0000000
+++ /dev/null
@@ -1,962 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Copyright (C) 2002 Free Software Foundation, Inc.
-#
-# 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = doc
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-       $(gcrypt_TEXINFOS) $(top_srcdir)/build-aux/mdate-sh \
-       $(srcdir)/version.texi $(srcdir)/stamp-vti \
-       $(top_srcdir)/build-aux/texinfo.tex
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-SOURCES =
-DIST_SOURCES =
-AM_V_DVIPS = $(am__v_DVIPS_@AM_V@)
-am__v_DVIPS_ = $(am__v_DVIPS_@AM_DEFAULT_V@)
-am__v_DVIPS_0 = @echo "  DVIPS   " $@;
-am__v_DVIPS_1 = 
-AM_V_MAKEINFO = $(am__v_MAKEINFO_@AM_V@)
-am__v_MAKEINFO_ = $(am__v_MAKEINFO_@AM_DEFAULT_V@)
-am__v_MAKEINFO_0 = @echo "  MAKEINFO" $@;
-am__v_MAKEINFO_1 = 
-AM_V_INFOHTML = $(am__v_INFOHTML_@AM_V@)
-am__v_INFOHTML_ = $(am__v_INFOHTML_@AM_DEFAULT_V@)
-am__v_INFOHTML_0 = @echo "  INFOHTML" $@;
-am__v_INFOHTML_1 = 
-AM_V_TEXI2DVI = $(am__v_TEXI2DVI_@AM_V@)
-am__v_TEXI2DVI_ = $(am__v_TEXI2DVI_@AM_DEFAULT_V@)
-am__v_TEXI2DVI_0 = @echo "  TEXI2DVI" $@;
-am__v_TEXI2DVI_1 = 
-AM_V_TEXI2PDF = $(am__v_TEXI2PDF_@AM_V@)
-am__v_TEXI2PDF_ = $(am__v_TEXI2PDF_@AM_DEFAULT_V@)
-am__v_TEXI2PDF_0 = @echo "  TEXI2PDF" $@;
-am__v_TEXI2PDF_1 = 
-AM_V_texinfo = $(am__v_texinfo_@AM_V@)
-am__v_texinfo_ = $(am__v_texinfo_@AM_DEFAULT_V@)
-am__v_texinfo_0 = -q
-am__v_texinfo_1 = 
-AM_V_texidevnull = $(am__v_texidevnull_@AM_V@)
-am__v_texidevnull_ = $(am__v_texidevnull_@AM_DEFAULT_V@)
-am__v_texidevnull_0 = > /dev/null
-am__v_texidevnull_1 = 
-INFO_DEPS = $(srcdir)/gcrypt.info
-TEXINFO_TEX = $(top_srcdir)/build-aux/texinfo.tex
-am__TEXINFO_TEX_DIR = $(top_srcdir)/build-aux
-DVIS = gcrypt.dvi
-PDFS = gcrypt.pdf
-PSS = gcrypt.ps
-HTMLS = gcrypt.html
-TEXINFOS = gcrypt.texi
-TEXI2DVI = texi2dvi
-TEXI2PDF = $(TEXI2DVI) --pdf --batch
-MAKEINFOHTML = $(MAKEINFO) --html
-AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS)
-DVIPS = dvips
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
-    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-    *) f=$$p;; \
-  esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
-  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
-  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
-  for p in $$list; do echo "$$p $$p"; done | \
-  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-    if (++n[$$2] == $(am__install_max)) \
-      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-    END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
-  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
-  test -z "$$files" \
-    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-         $(am__cd) "$$dir" && rm -f $$files; }; \
-  }
-man1dir = $(mandir)/man1
-NROFF = nroff
-MANS = $(man_MANS)
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-EXTRA_DIST = README.apichanges HACKING DCO \
-            libgcrypt-modules.eps fips-fsm.eps \
-            libgcrypt-modules.png fips-fsm.png \
-             libgcrypt-modules.pdf fips-fsm.pdf \
-            yat2m.c
-
-DISTCLEANFILES = gcrypt.cps yat2m-stamp.tmp yat2m-stamp $(myman_pages)
-CLEANFILES = yat2m
-BUILT_SOURCES = libgcrypt-modules.eps fips-fsm.eps \
-                libgcrypt-modules.png fips-fsm.png \
-                libgcrypt-modules.pdf fips-fsm.pdf
-
-info_TEXINFOS = gcrypt.texi
-gcrypt_TEXINFOS = lgpl.texi gpl.texi libgcrypt-modules.fig fips-fsm.fig
-YAT2M_OPTIONS = -I $(srcdir) \
-       --release "Libgcrypt @PACKAGE_VERSION@" --source "Libgcrypt"
-
-myman_sources = gcrypt.texi
-myman_pages = hmac256.1
-man_MANS = $(myman_pages)
-all: $(BUILT_SOURCES)
-       $(MAKE) $(AM_MAKEFLAGS) all-am
-
-.SUFFIXES:
-.SUFFIXES: .dvi .eps .fig .html .info .jpg .pdf .png .ps .texi
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-               && { if test -f $@; then exit 0; else break; fi; }; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu doc/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-
-.texi.info:
-       $(AM_V_MAKEINFO)restore=: && backupdir="$(am__leading_dot)am$$$$" && \
-       am__cwd=`pwd` && $(am__cd) $(srcdir) && \
-       rm -rf $$backupdir && mkdir $$backupdir && \
-       if ($(MAKEINFO) --version) >/dev/null 2>&1; then \
-         for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \
-           if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \
-         done; \
-       else :; fi && \
-       cd "$$am__cwd"; \
-       if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
-        -o $@ $<; \
-       then \
-         rc=0; \
-         $(am__cd) $(srcdir); \
-       else \
-         rc=$$?; \
-         $(am__cd) $(srcdir) && \
-         $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \
-       fi; \
-       rm -rf $$backupdir; exit $$rc
-
-.texi.dvi:
-       $(AM_V_TEXI2DVI)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
-       MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
-       $(TEXI2DVI) $(AM_V_texinfo) --build-dir=$(@:.dvi=.t2d) -o $@ $(AM_V_texidevnull) \
-       $<
-
-.texi.pdf:
-       $(AM_V_TEXI2PDF)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
-       MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
-       $(TEXI2PDF) $(AM_V_texinfo) --build-dir=$(@:.pdf=.t2p) -o $@ $(AM_V_texidevnull) \
-       $<
-
-.texi.html:
-       $(AM_V_MAKEINFO)rm -rf $(@:.html=.htp)
-       $(AM_V_at)if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \
-        -o $(@:.html=.htp) $<; \
-       then \
-         rm -rf $@ && mv $(@:.html=.htp) $@; \
-       else \
-         rm -rf $(@:.html=.htp); exit 1; \
-       fi
-$(srcdir)/gcrypt.info: gcrypt.texi $(srcdir)/version.texi $(gcrypt_TEXINFOS)
-gcrypt.dvi: gcrypt.texi $(srcdir)/version.texi $(gcrypt_TEXINFOS)
-gcrypt.pdf: gcrypt.texi $(srcdir)/version.texi $(gcrypt_TEXINFOS)
-gcrypt.html: gcrypt.texi $(srcdir)/version.texi $(gcrypt_TEXINFOS)
-$(srcdir)/version.texi: @MAINTAINER_MODE_TRUE@ $(srcdir)/stamp-vti
-$(srcdir)/stamp-vti: gcrypt.texi $(top_srcdir)/configure
-       @(dir=.; test -f ./gcrypt.texi || dir=$(srcdir); \
-       set `$(SHELL) $(top_srcdir)/build-aux/mdate-sh $$dir/gcrypt.texi`; \
-       echo "@set UPDATED $$1 $$2 $$3"; \
-       echo "@set UPDATED-MONTH $$2 $$3"; \
-       echo "@set EDITION $(VERSION)"; \
-       echo "@set VERSION $(VERSION)") > vti.tmp
-       @cmp -s vti.tmp $(srcdir)/version.texi \
-         || (echo "Updating $(srcdir)/version.texi"; \
-             cp vti.tmp $(srcdir)/version.texi)
-       -@rm -f vti.tmp
-       @cp $(srcdir)/version.texi $@
-
-mostlyclean-vti:
-       -rm -f vti.tmp
-
-maintainer-clean-vti:
-@MAINTAINER_MODE_TRUE@ -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi
-.dvi.ps:
-       $(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
-       $(DVIPS) $(AM_V_texinfo) -o $@ $<
-
-uninstall-dvi-am:
-       @$(NORMAL_UNINSTALL)
-       @list='$(DVIS)'; test -n "$(dvidir)" || list=; \
-       for p in $$list; do \
-         $(am__strip_dir) \
-         echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \
-         rm -f "$(DESTDIR)$(dvidir)/$$f"; \
-       done
-
-uninstall-html-am:
-       @$(NORMAL_UNINSTALL)
-       @list='$(HTMLS)'; test -n "$(htmldir)" || list=; \
-       for p in $$list; do \
-         $(am__strip_dir) \
-         echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \
-         rm -rf "$(DESTDIR)$(htmldir)/$$f"; \
-       done
-
-uninstall-info-am:
-       @$(PRE_UNINSTALL)
-       @if test -d '$(DESTDIR)$(infodir)' && $(am__can_run_installinfo); then \
-         list='$(INFO_DEPS)'; \
-         for file in $$list; do \
-           relfile=`echo "$$file" | sed 's|^.*/||'`; \
-           echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \
-           if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \
-           then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \
-         done; \
-       else :; fi
-       @$(NORMAL_UNINSTALL)
-       @list='$(INFO_DEPS)'; \
-       for file in $$list; do \
-         relfile=`echo "$$file" | sed 's|^.*/||'`; \
-         relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \
-         (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \
-            echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \
-            rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \
-          else :; fi); \
-       done
-
-uninstall-pdf-am:
-       @$(NORMAL_UNINSTALL)
-       @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \
-       for p in $$list; do \
-         $(am__strip_dir) \
-         echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \
-         rm -f "$(DESTDIR)$(pdfdir)/$$f"; \
-       done
-
-uninstall-ps-am:
-       @$(NORMAL_UNINSTALL)
-       @list='$(PSS)'; test -n "$(psdir)" || list=; \
-       for p in $$list; do \
-         $(am__strip_dir) \
-         echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \
-         rm -f "$(DESTDIR)$(psdir)/$$f"; \
-       done
-
-dist-info: $(INFO_DEPS)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
-       list='$(INFO_DEPS)'; \
-       for base in $$list; do \
-         case $$base in \
-           $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \
-         esac; \
-         if test -f $$base; then d=.; else d=$(srcdir); fi; \
-         base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \
-         for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \
-           if test -f $$file; then \
-             relfile=`expr "$$file" : "$$d/\(.*\)"`; \
-             test -f "$(distdir)/$$relfile" || \
-               cp -p $$file "$(distdir)/$$relfile"; \
-           else :; fi; \
-         done; \
-       done
-
-mostlyclean-aminfo:
-       -rm -rf gcrypt.t2d gcrypt.t2p
-
-clean-aminfo:
-       -test -z "gcrypt.dvi gcrypt.pdf gcrypt.ps gcrypt.html" \
-       || rm -rf gcrypt.dvi gcrypt.pdf gcrypt.ps gcrypt.html
-
-maintainer-clean-aminfo:
-       @list='$(INFO_DEPS)'; for i in $$list; do \
-         i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \
-         echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \
-         rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \
-       done
-install-man1: $(man_MANS)
-       @$(NORMAL_INSTALL)
-       @list1=''; \
-       list2='$(man_MANS)'; \
-       test -n "$(man1dir)" \
-         && test -n "`echo $$list1$$list2`" \
-         || exit 0; \
-       echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
-       $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
-       { for i in $$list1; do echo "$$i"; done;  \
-       if test -n "$$list2"; then \
-         for i in $$list2; do echo "$$i"; done \
-           | sed -n '/\.1[a-z]*$$/p'; \
-       fi; \
-       } | while read p; do \
-         if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; echo "$$p"; \
-       done | \
-       sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
-       sed 'N;N;s,\n, ,g' | { \
-       list=; while read file base inst; do \
-         if test "$$base" = "$$inst"; then list="$$list $$file"; else \
-           echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
-           $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
-         fi; \
-       done; \
-       for i in $$list; do echo "$$i"; done | $(am__base_list) | \
-       while read files; do \
-         test -z "$$files" || { \
-           echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
-           $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
-       done; }
-
-uninstall-man1:
-       @$(NORMAL_UNINSTALL)
-       @list=''; test -n "$(man1dir)" || exit 0; \
-       files=`{ for i in $$list; do echo "$$i"; done; \
-       l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
-         sed -n '/\.1[a-z]*$$/p'; \
-       } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
-       dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
-tags TAGS:
-
-ctags CTAGS:
-
-cscope cscopelist:
-
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-       $(MAKE) $(AM_MAKEFLAGS) \
-         top_distdir="$(top_distdir)" distdir="$(distdir)" \
-         dist-info
-check-am: all-am
-check: $(BUILT_SOURCES)
-       $(MAKE) $(AM_MAKEFLAGS) check-am
-all-am: Makefile $(INFO_DEPS) $(MANS)
-installdirs:
-       for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \
-         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-       done
-install: $(BUILT_SOURCES)
-       $(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-clean: clean-am
-
-clean-am: clean-aminfo clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-am
-       -rm -f Makefile
-distclean-am: clean-am distclean-generic
-
-dvi: dvi-am
-
-dvi-am: $(DVIS)
-
-html: html-am
-
-html-am: $(HTMLS)
-
-info: info-am
-
-info-am: $(INFO_DEPS)
-
-install-data-am: install-info-am install-man
-
-install-dvi: install-dvi-am
-
-install-dvi-am: $(DVIS)
-       @$(NORMAL_INSTALL)
-       @list='$(DVIS)'; test -n "$(dvidir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(dvidir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(dvidir)" || exit 1; \
-       fi; \
-       for p in $$list; do \
-         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; \
-       done | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \
-       done
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am: $(HTMLS)
-       @$(NORMAL_INSTALL)
-       @list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \
-       fi; \
-       for p in $$list; do \
-         if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         $(am__strip_dir) \
-         d2=$$d$$p; \
-         if test -d "$$d2"; then \
-           echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \
-           $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
-           echo " $(INSTALL_DATA) '$$d2'/* '$(DESTDIR)$(htmldir)/$$f'"; \
-           $(INSTALL_DATA) "$$d2"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \
-         else \
-           list2="$$list2 $$d2"; \
-         fi; \
-       done; \
-       test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \
-       done; }
-install-info: install-info-am
-
-install-info-am: $(INFO_DEPS)
-       @$(NORMAL_INSTALL)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
-       list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(infodir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(infodir)" || exit 1; \
-       fi; \
-       for file in $$list; do \
-         case $$file in \
-           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
-         esac; \
-         if test -f $$file; then d=.; else d=$(srcdir); fi; \
-         file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \
-         for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \
-                      $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \
-           if test -f $$ifile; then \
-             echo "$$ifile"; \
-           else : ; fi; \
-         done; \
-       done | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done
-       @$(POST_INSTALL)
-       @if $(am__can_run_installinfo); then \
-         list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \
-         for file in $$list; do \
-           relfile=`echo "$$file" | sed 's|^.*/||'`; \
-           echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\
-           install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\
-         done; \
-       else : ; fi
-install-man: install-man1
-
-install-pdf: install-pdf-am
-
-install-pdf-am: $(PDFS)
-       @$(NORMAL_INSTALL)
-       @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(pdfdir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(pdfdir)" || exit 1; \
-       fi; \
-       for p in $$list; do \
-         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; \
-       done | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done
-install-ps: install-ps-am
-
-install-ps-am: $(PSS)
-       @$(NORMAL_INSTALL)
-       @list='$(PSS)'; test -n "$(psdir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(psdir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(psdir)" || exit 1; \
-       fi; \
-       for p in $$list; do \
-         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; \
-       done | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-aminfo \
-       maintainer-clean-generic maintainer-clean-vti
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-aminfo mostlyclean-generic \
-       mostlyclean-libtool mostlyclean-vti
-
-pdf: pdf-am
-
-pdf-am: $(PDFS)
-
-ps: ps-am
-
-ps-am: $(PSS)
-
-uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
-       uninstall-man uninstall-pdf-am uninstall-ps-am
-
-uninstall-man: uninstall-man1
-
-.MAKE: all check install install-am install-strip
-
-.PHONY: all all-am check check-am clean clean-aminfo clean-generic \
-       clean-libtool cscopelist-am ctags-am dist-info distclean \
-       distclean-generic distclean-libtool distdir dvi dvi-am html \
-       html-am info info-am install install-am install-data \
-       install-data-am install-dvi install-dvi-am install-exec \
-       install-exec-am install-html install-html-am install-info \
-       install-info-am install-man install-man1 install-pdf \
-       install-pdf-am install-ps install-ps-am install-strip \
-       installcheck installcheck-am installdirs maintainer-clean \
-       maintainer-clean-aminfo maintainer-clean-generic \
-       maintainer-clean-vti mostlyclean mostlyclean-aminfo \
-       mostlyclean-generic mostlyclean-libtool mostlyclean-vti pdf \
-       pdf-am ps ps-am tags-am uninstall uninstall-am \
-       uninstall-dvi-am uninstall-html-am uninstall-info-am \
-       uninstall-man uninstall-man1 uninstall-pdf-am uninstall-ps-am
-
-
-yat2m: yat2m.c
-       $(CC_FOR_BUILD) -o $@ $(srcdir)/yat2m.c
-
-.fig.png:
-       fig2dev -L png `test -f '$<' || echo '$(srcdir)/'`$< $@
-
-.fig.jpg:
-       fig2dev -L jpg `test -f '$<' || echo '$(srcdir)/'`$< $@
-
-.fig.eps:
-       fig2dev -L eps `test -f '$<' || echo '$(srcdir)/'`$< $@
-
-.fig.pdf:
-       fig2dev -L pdf `test -f '$<' || echo '$(srcdir)/'`$< $@
-
-yat2m-stamp: $(myman_sources)
-       @rm -f yat2m-stamp.tmp
-       @touch yat2m-stamp.tmp
-       for file in $(myman_sources) ; do \
-              ./yat2m $(YAT2M_OPTIONS) --store \
-                 `test -f '$$file' || echo '$(srcdir)/'`$$file ; done
-       @mv -f yat2m-stamp.tmp $@
-
-yat2m-stamp: yat2m
-
-$(myman_pages) : yat2m-stamp
-       @if test -f $@; then :; else \
-            trap 'rm -rf yat2m-stamp yat2m-lock' 1 2 13 15; \
-               if mkdir yat2m-lock 2>/dev/null; then \
-                 rm -f yat2m-stamp; \
-                 $(MAKE) $(AM_MAKEFLAGS) yat2m-stamp; \
-                 rmdir yat2m-lock; \
-               else \
-                 while test -d yat2m-lock; do sleep 1; done; \
-                 test -f yat2m-stamp; exit $$?; \
-               fi; \
-             fi
-
-# Make sure that gcrypt.texi is touched if any other source file has
-# been modified.  This is required so that the version.texi magic
-# updates the release date.
-gcrypt.texi : $(gcrypt_TEXINFOS)
-       touch $(srcdir)/gcrypt.texi
-
-online: gcrypt.html gcrypt.pdf gcrypt.info
-       set -e; \
-       echo "Uploading current manuals to www.gnupg.org ..."; \
-       cp libgcrypt-modules.png gcrypt.html/; \
-       cp fips-fsm.png gcrypt.html/; \
-        user=werner ; dashdevel="" ; \
-        if echo "@PACKAGE_VERSION@" | grep -- "-svn" >/dev/null; then \
-         dashdevel="-devel" ; \
-         cp gcrypt.pdf gcrypt.html/; \
-         cp gcrypt.info gcrypt.html/; \
-       else \
-          rsync -v gcrypt.pdf gcrypt.info \
-               $${user}@trithemius.gnupg.org:webspace/manuals/ ; \
-        fi ; \
-       cd gcrypt.html ; \
-        rsync -vr --exclude='.svn' .  \
-         $${user}@trithemius.gnupg.org:webspace/manuals/gcrypt$${dashdevel}/
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/doc/Notes-wk b/doc/Notes-wk
new file mode 100644 (file)
index 0000000..618c4a2
--- /dev/null
@@ -0,0 +1,8 @@
+Various private notes
+
+[Von Joachim Ziegler]
+PS: Mir fällt gerade ein: ich hatte noch einen Trick: der Grundschritt beim 
+modularen Potenzieren besteht aus Quadrieren und Dividieren. Und das 
+Quadrieren als Spezialfall kann man noch schneller machen als das 
+Multiplizieren, weil sich die Karatsuba-Formel noch mal vereinfachen lässt...
+(und der Trick ist, glaube ich, nicht in GMP drin)
diff --git a/doc/announce-1.4.txt b/doc/announce-1.4.txt
new file mode 100644 (file)
index 0000000..26e8bb3
--- /dev/null
@@ -0,0 +1,155 @@
+To: gnupg-announce@gnupg.org, info-gnu@gnu.org
+Cc: gcrypt-devel@gnupg.org
+
+
+Hello! 
+
+We are pleased to announce the availability of Libgcrypt 1.4.0.  This
+is the new stable version of Libgcrypt and upward compatible with the
+1.2 series.
+
+The 1.2 series will enter end of life state in 2 years on 2009-12-31.
+
+Libgcrypt is a general purpose library of cryptographic building
+blocks.  It is originally based on code used by GnuPG.  It does not
+provide any implementation of OpenPGP or other protocols.  Thorough
+understanding of applied cryptography is required to use Libgcrypt.
+
+
+Noteworthy changes between 1.2.x and 1.4.0 are:
+
+ * Support for SHA-224 and HMAC using SHA-384 and SHA-512.
+
+ * Support for the SEED cipher.
+
+ * Support for the Camellia cipher. 
+
+ * Support for OFB encryption mode.
+
+ * Support for DSA2.
+
+ * Support for Microsoft Windows.
+
+ * The entire library is now under the LGPLv2+. The helper programs
+   and the manual are under the GPLv2+.  Kudos to Peter Gutmann for
+   giving permissions to relicense the rndw32 and rndunix modules.
+
+ * The visibility attribute is now used if supported by the toolchain.
+
+ * The ACE engine of VIA processors is now used for AES-128.
+
+ * Changed the way the RNG gets initialized.  This allows to keep it
+   uninitialized as long as no random numbers are used.
+
+ * Updated the entropy gatherer for W32.
+
+ * Made the RNG immune against fork without exec.
+
+ * Reading and writing the random seed file is now protected by a
+   fcntl style file lock on systems that provide this function.
+
+ * gcry_mpi_rshift does not anymore truncate the shift count.
+
+ * Reserved algorithm ranges for use by applications.
+
+ * The new function gcry_md_debug should be used instead of the
+   gcry_md_start_debug and gcry_md_stop_debug macros.
+
+ * Non executable stack support is now used by default on systems
+   supporting it.
+
+ * Assembler support for the AMD64 architecture.
+
+ * New configure option --enable-mpi-path for optimized builds.
+
+ * Fixed a bug in the detection of symbol prefixes which inhibited the
+   build of optimized assembler code on certain systems.
+
+ * New control code GCRYCTL_PRINT_CONFIG to print the build
+   configuration.
+
+ * Experimental support for ECDSA; should only be used for testing.
+
+ * New configure option --enable-random-daemon to support a system
+   wide random daemon.  The daemon code is experimental and not yet
+   very well working.  It will eventually allow to keep a global
+   random pool for the sake of short living processes.
+
+ * Minor changes to some function declarations.  Buffer arguments are
+   now typed as void pointer.  This should not affect any compilation.
+   Fixed two bugs in return values and clarified documentation.
+
+ * Interface changes relative to the 1.2.0 release:
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   gcry_fast_random_pol       NEW.
+   gcry_md_debug              NEW.
+   gcry_sexp_nth_string       NEW.
+   GCRY_MD_SHA224             NEW.
+   GCRY_PK_USAGE_CERT         NEW.
+   GCRY_PK_USAGE_AUTH         NEW.
+   GCRY_PK_USAGE_UNKN         NEW.
+   GCRY_PK_ECDSA              NEW.
+   GCRY_CIPHER_SEED           NEW.
+   GCRY_CIPHER_CAMELLIA128    NEW.
+   GCRY_CIPHER_CAMELLIA192    NEW.
+   GCRY_CIPHER_CAMELLIA256    NEW.
+   GCRYCTL_FAKED_RANDOM_P     NEW. 
+   GCRYCTL_PRINT_CONFIG       NEW.
+   GCRYCTL_SET_RNDEGD_SOCKET  NEW.
+   gcry_mpi_scan           CHANGED: Argument BUFFER is now void*.
+   gcry_pk_algo_name       CHANGED: Returns "?" instead of NULL.
+   gcry_cipher_algo_name   CHANGED: Returns "?" instead of "".
+   gcry_pk_spec_t          CHANGED: Element ALIASES is now const ptr.
+   gcry_md_write_t         CHANGED: Argument BUF is now a const void*.
+   gcry_md_ctl             CHANGED: Argument BUFFER is now void*.
+   gcry_cipher_encrypt     CHANGED: Arguments IN and OUT are now void*.
+   gcry_cipher_decrypt     CHANGED: Arguments IN and OUT are now void*.
+   gcry_sexp_sprint        CHANGED: Argument BUFFER is now void*.
+   gcry_create_nonce       CHANGED: Argument BUFFER is now void*.
+   gcry_randomize          CHANGED: Argument BUFFER is now void*.
+   gcry_cipher_register    CHANGED: Argument ALGORITHM_ID is now int*.
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  
+
+Source code is hosted at the GnuPG FTP server and its mirrors as
+listed at http://www.gnupg.org/download/mirrors.html .  On the primary
+server the source file and its digital signatures is:
+
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.0.tar.bz2 (942k)
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.0.tar.bz2.sig
+
+This file is bzip2 compressed.  A gzip compressed version is also
+available:
+
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.0.tar.gz (1176k)
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.0.tar.gz.sig
+
+The SHA-1 checksums are:
+
+cd1b52e8ecfa361737c6f130ed2f1d850e312c16  libgcrypt-1.4.0.tar.bz2
+69183b7100b60da8eb1648f49836a611454541bb  libgcrypt-1.4.0.tar.gz
+
+For help on developing with Libgcrypt you should read the included
+manual and optional ask on the gcrypt-devel mailing list [1].
+
+Improving Libgcrypt is costly, but you can help!  We are looking for
+organizations that find Libgcrypt useful and wish to contribute back.
+You can contribute by reporting bugs, improve the software [2], or by
+donating money.
+
+Commercial support contracts for Libgcrypt are available [3], and they
+help finance continued maintenance.  g10 Code GmbH, a Duesseldorf
+based company, is currently funding Libgcrypt development.  We are
+always looking for interesting development projects.
+
+Many thanks to all who contributed to Libgcrypt development, be it bug
+fixes, code, documentation, testing or helping users.
+
+Happy hacking,
+
+  Werner
+
+
+[1] See http://www.gnupg.org/documentation/mailing-lists.html .
+[2] Note that copyright assignments to the FSF are required.
+[3] See the service directory at http://www.gnupg.org/service.html .
diff --git a/doc/announce.txt b/doc/announce.txt
new file mode 100644 (file)
index 0000000..48c41bf
--- /dev/null
@@ -0,0 +1,91 @@
+To: gnupg-announce@gnupg.org, info-gnu@gnu.org
+Cc: gcrypt-devel@gnupg.org
+
+
+Hello! 
+
+The GNU project is pleased to announce the availability of Libgcrypt
+version 1.4.3.
+
+Libgcrypt is a general purpose library of cryptographic building
+blocks.  It is originally based on code used by GnuPG.  It does not
+provide any implementation of OpenPGP or other protocols.  Thorough
+understanding of applied cryptography is required to use Libgcrypt.
+
+Noteworthy changes in version 1.4.3:
+
+ * Try to auto-initialize Libgcrypt to minimize the effect of
+   applications not doing that correctly.  This is not a perfect
+   solution but given that many applicationion would totally fail
+   without such a hack, we try to help at least with the most common
+   cases.  Folks, please read the manual to learn how to properly
+   initialize Libgcrypt!
+
+ * Auto-initialize the secure memory to 32k instead of aborting the
+   process.
+
+ * Log fatal errors via syslog.
+
+ * Changed the name and the semantics of the fips mode config file.
+
+ * Add convenience macro gcry_fips_mode_active.
+
+ * More self-tests.
+
+ * Documentation cleanups.
+
+
+Source code is hosted at the GnuPG FTP server and its mirrors as
+listed at http://www.gnupg.org/download/mirrors.html .  On the primary
+server the source file and its digital signatures is:
+
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.bz2 (1062k)
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.bz2.sig
+
+This file is bzip2 compressed.  A gzip compressed version is also
+available:
+
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.gz (1325k)
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.3.tar.gz.sig
+
+Alternativley you may upgrade version 1.4.2 using this patch file:
+
+ ftp://ftp.gnupg.org/gcrypt/libgcrypt/libgcrypt-1.4.2-1.4.3.diff.bz2 (42k)
+
+The SHA-1 checksums are:
+
+bdc67c1fdcec464a94dca691615f2335a12db5ce  libgcrypt-1.4.3.tar.bz2
+3d9d583501ce951596fa7dd3667afd357ac7d056  libgcrypt-1.4.3.tar.gz
+e28b74c5824364e20ae7f147f1b89925f5426669  libgcrypt-1.4.2-1.4.3.diff.bz2
+
+
+For help on developing with Libgcrypt you should read the included
+manual and optional ask on the gcrypt-devel mailing list [1].
+
+Improving Libgcrypt is costly, but you can help!  We are looking for
+organizations that find Libgcrypt useful and wish to contribute back.
+You can contribute by reporting bugs, improve the software [2], order
+extensions or support or more general by donating money to the Free
+Software movement [3].
+
+Commercial support contracts for Libgcrypt are available [4], and they
+help finance continued maintenance.  g10 Code GmbH, a Duesseldorf
+based company, is currently funding Libgcrypt development.  We are
+always looking for interesting development projects.
+
+Many thanks to all who contributed to Libgcrypt development, be it bug
+fixes, code, documentation, testing or helping users.
+
+
+Happy hacking,
+
+  Werner
+
+
+
+
+[1] See http://www.gnupg.org/documentation/mailing-lists.html .
+[2] Note that copyright assignments to the FSF are required.
+[3] For example see http://donate.fsf.org .
+[4] See the service directory at http://www.gnupg.org/service.html .
+
diff --git a/doc/fips-fsm.eps b/doc/fips-fsm.eps
deleted file mode 100644 (file)
index 31f52d0..0000000
+++ /dev/null
@@ -1,591 +0,0 @@
-%!PS-Adobe-3.0 EPSF-3.0
-%%Title: /home/wk/s/libgcrypt-1.8/doc/fips-fsm.fig
-%%Creator: fig2dev Version 3.2 Patchlevel 5e
-%%CreationDate: Fri Oct 26 19:32:26 2018
-%%BoundingBox: 0 0 497 579
-%Magnification: 1.0000
-%%EndComments
-%%BeginProlog
-/$F2psDict 200 dict def
-$F2psDict begin
-$F2psDict /mtrx matrix put
-/col-1 {0 setgray} bind def
-/col0 {0.000 0.000 0.000 srgb} bind def
-/col1 {0.000 0.000 1.000 srgb} bind def
-/col2 {0.000 1.000 0.000 srgb} bind def
-/col3 {0.000 1.000 1.000 srgb} bind def
-/col4 {1.000 0.000 0.000 srgb} bind def
-/col5 {1.000 0.000 1.000 srgb} bind def
-/col6 {1.000 1.000 0.000 srgb} bind def
-/col7 {1.000 1.000 1.000 srgb} bind def
-/col8 {0.000 0.000 0.560 srgb} bind def
-/col9 {0.000 0.000 0.690 srgb} bind def
-/col10 {0.000 0.000 0.820 srgb} bind def
-/col11 {0.530 0.810 1.000 srgb} bind def
-/col12 {0.000 0.560 0.000 srgb} bind def
-/col13 {0.000 0.690 0.000 srgb} bind def
-/col14 {0.000 0.820 0.000 srgb} bind def
-/col15 {0.000 0.560 0.560 srgb} bind def
-/col16 {0.000 0.690 0.690 srgb} bind def
-/col17 {0.000 0.820 0.820 srgb} bind def
-/col18 {0.560 0.000 0.000 srgb} bind def
-/col19 {0.690 0.000 0.000 srgb} bind def
-/col20 {0.820 0.000 0.000 srgb} bind def
-/col21 {0.560 0.000 0.560 srgb} bind def
-/col22 {0.690 0.000 0.690 srgb} bind def
-/col23 {0.820 0.000 0.820 srgb} bind def
-/col24 {0.500 0.190 0.000 srgb} bind def
-/col25 {0.630 0.250 0.000 srgb} bind def
-/col26 {0.750 0.380 0.000 srgb} bind def
-/col27 {1.000 0.500 0.500 srgb} bind def
-/col28 {1.000 0.630 0.630 srgb} bind def
-/col29 {1.000 0.750 0.750 srgb} bind def
-/col30 {1.000 0.880 0.880 srgb} bind def
-/col31 {1.000 0.840 0.000 srgb} bind def
-/col32 {0.612 0.000 0.000 srgb} bind def
-/col33 {0.549 0.549 0.549 srgb} bind def
-/col34 {0.549 0.549 0.549 srgb} bind def
-/col35 {0.259 0.259 0.259 srgb} bind def
-/col36 {0.549 0.549 0.549 srgb} bind def
-/col37 {0.259 0.259 0.259 srgb} bind def
-/col38 {0.549 0.549 0.549 srgb} bind def
-/col39 {0.259 0.259 0.259 srgb} bind def
-/col40 {0.549 0.549 0.549 srgb} bind def
-/col41 {0.259 0.259 0.259 srgb} bind def
-/col42 {0.549 0.549 0.549 srgb} bind def
-/col43 {0.259 0.259 0.259 srgb} bind def
-
-end
-
-/cp {closepath} bind def
-/ef {eofill} bind def
-/gr {grestore} bind def
-/gs {gsave} bind def
-/sa {save} bind def
-/rs {restore} bind def
-/l {lineto} bind def
-/m {moveto} bind def
-/rm {rmoveto} bind def
-/n {newpath} bind def
-/s {stroke} bind def
-/sh {show} bind def
-/slc {setlinecap} bind def
-/slj {setlinejoin} bind def
-/slw {setlinewidth} bind def
-/srgb {setrgbcolor} bind def
-/rot {rotate} bind def
-/sc {scale} bind def
-/sd {setdash} bind def
-/ff {findfont} bind def
-/sf {setfont} bind def
-/scf {scalefont} bind def
-/sw {stringwidth} bind def
-/tr {translate} bind def
-/tnt {dup dup currentrgbcolor
-  4 -2 roll dup 1 exch sub 3 -1 roll mul add
-  4 -2 roll dup 1 exch sub 3 -1 roll mul add
-  4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
-  bind def
-/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
-  4 -2 roll mul srgb} bind def
-/reencdict 12 dict def /ReEncode { reencdict begin
-/newcodesandnames exch def /newfontname exch def /basefontname exch def
-/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def
-basefontdict { exch dup /FID ne { dup /Encoding eq
-{ exch dup length array copy newfont 3 1 roll put }
-{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall
-newfont /FontName newfontname put newcodesandnames aload pop
-128 1 255 { newfont /Encoding get exch /.notdef put } for
-newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat
-newfontname newfont definefont pop end } def
-/isovec [
-8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde
-8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis
-8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron
-8#220 /dotlessi 8#230 /oe 8#231 /OE
-8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling
-8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis
-8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot
-8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus
-8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph
-8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine
-8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf
-8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute
-8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring
-8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute
-8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute
-8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve
-8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply
-8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex
-8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave
-8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring
-8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute
-8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute
-8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve
-8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide
-8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex
-8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def
-/Courier-Oblique /Courier-Oblique-iso isovec ReEncode
-/Times-Roman /Times-Roman-iso isovec ReEncode
- /DrawEllipse {
-       /endangle exch def
-       /startangle exch def
-       /yrad exch def
-       /xrad exch def
-       /y exch def
-       /x exch def
-       /savematrix mtrx currentmatrix def
-       x y tr xrad yrad sc 0 0 1 startangle endangle arc
-       closepath
-       savematrix setmatrix
-       } def
-
-/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
-/$F2psEnd {$F2psEnteredState restore end} def
-
-/pageheader {
-save
-newpath 0 579 moveto 0 0 lineto 497 0 lineto 497 579 lineto closepath clip newpath
--56.9 596.0 translate
-1 -1 scale
-$F2psBegin
-10 setmiterlimit
-0 slj 0 slc
- 0.06299 0.06299 sc
-} bind def
-/pagefooter {
-$F2psEnd
-restore
-} bind def
-%%EndProlog
-pageheader
-%
-% Fig objects follow
-%
-% 
-% here starts figure with depth 50
-% Ellipse
-7.500 slw
-n 3238 1735 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 2408 3749 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 1708 5809 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 5848 1685 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 6128 7899 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 7568 4889 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 6008 3879 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 5418 2659 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 4268 3715 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 3208 5865 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 4178 6765 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 4558 7355 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 5208 7365 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 3708 7715 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 3038 7925 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 6568 5895 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Polyline
-0 slj
-0 slc
-n 3900 8370 m 3600 8370 3600 9150 300 arcto 4 {pop} repeat
-  3600 9450 5670 9450 300 arcto 4 {pop} repeat
-  5970 9450 5970 8670 300 arcto 4 {pop} repeat
-  5970 8370 3900 8370 300 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 1215 4335 m 915 4335 915 5145 300 arcto 4 {pop} repeat
-  915 5445 2640 5445 300 arcto 4 {pop} repeat
-  2940 5445 2940 4635 300 arcto 4 {pop} repeat
-  2940 4335 1215 4335 300 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 1230 6345 m 930 6345 930 7155 300 arcto 4 {pop} repeat
-  930 7455 2655 7455 300 arcto 4 {pop} repeat
-  2955 7455 2955 6645 300 arcto 4 {pop} repeat
-  2955 6345 1230 6345 300 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 7050 6360 m 6750 6360 6750 7170 300 arcto 4 {pop} repeat
-  6750 7470 8475 7470 300 arcto 4 {pop} repeat
-  8775 7470 8775 6660 300 arcto 4 {pop} repeat
-  8775 6360 7050 6360 300 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 4125 4335 m 3825 4335 3825 5145 300 arcto 4 {pop} repeat
-  3825 5445 5550 5445 300 arcto 4 {pop} repeat
-  5850 5445 5850 4635 300 arcto 4 {pop} repeat
-  5850 4335 4125 4335 300 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 7050 2310 m 6750 2310 6750 3120 300 arcto 4 {pop} repeat
-  6750 3420 8475 3420 300 arcto 4 {pop} repeat
-  8775 3420 8775 2610 300 arcto 4 {pop} repeat
-  8775 2310 7050 2310 300 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 2775 2295 m 2475 2295 2475 3105 300 arcto 4 {pop} repeat
-  2475 3405 4200 3405 300 arcto 4 {pop} repeat
-  4500 3405 4500 2595 300 arcto 4 {pop} repeat
-  4500 2295 2775 2295 300 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 2775 285 m 2475 285 2475 1095 300 arcto 4 {pop} repeat
-  2475 1395 4200 1395 300 arcto 4 {pop} repeat
-  4500 1395 4500 585 300 arcto 4 {pop} repeat
-  4500 285 2775 285 300 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Ellipse
-n 4192 6338 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 3202 4507 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 3181 5161 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Ellipse
-n 7709 7996 142 142 0 360 DrawEllipse gs col0 s gr
-
-% Arc
-15.000 slw
-1 slc
-gs  clippath
-3182 6598 m 2899 6648 l 2920 6766 l 3203 6716 l 3203 6716 l 2957 6699 l 3182 6598 l cp
-eoclip
-n 4837.5 16740.0 10215.6 -79.2098 -100.7902 arcn
-gs col0 s gr
- gr
-
-% arrowhead
-0 slc
-n 3182 6598 m 2957 6699 l 3203 6716 l 3182 6598 l  cp gs 0.00 setgray ef gr  col0 s
-% Arc
-1 slc
-gs  clippath
-3198 7193 m 2911 7184 l 2908 7304 l 3195 7313 l 3195 7313 l 2957 7246 l 3198 7193 l cp
-eoclip
-n 3026.1 8399.8 1159.2 -1.4743 -95.0051 arcn
-gs col0 s gr
- gr
-
-% arrowhead
-0 slc
-n 3198 7193 m 2957 7246 l 3195 7313 l 3198 7193 l  cp gs 0.00 setgray ef gr  col0 s
-% Arc
-1 slc
-gs  clippath
-6472 6596 m 6757 6631 l 6772 6512 l 6487 6477 l 6487 6477 l 6718 6566 l 6472 6596 l cp
-eoclip
-n 7663.1 -2028.8 8647.1 123.5832 96.0617 arcn
-gs col0 s gr
- gr
-
-% arrowhead
-0 slc
-n 6472 6596 m 6718 6566 l 6487 6477 l 6472 6596 l  cp gs 0.00 setgray ef gr  col0 s
-% Arc
-1 slc
-gs  clippath
-8162 7723 m 8336 7494 l 8241 7421 l 8066 7650 l 8066 7650 l 8260 7496 l 8162 7723 l cp
-eoclip
-n 7717.5 7211.2 619.2 155.2976 24.7024 arcn
-gs col0 s gr
- gr
-
-% arrowhead
-0 slc
-n 8162 7723 m 8260 7496 l 8066 7650 l 8162 7723 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-3360 2023 m 3360 2310 l 3480 2310 l 3480 2023 l 3480 2023 l 3420 2263 l 3360 2023 l cp
-eoclip
-n 3420 1395 m
- 3420 2295 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 3360 2023 m 3420 2263 l 3480 2023 l 3360 2023 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-4555 4218 m 4794 4378 l 4860 4278 l 4621 4118 l 4621 4118 l 4788 4302 l 4555 4218 l cp
-eoclip
-n 3465 3420 m
- 4815 4320 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 4555 4218 m 4788 4302 l 4621 4118 l 4555 4218 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-1830 6073 m 1830 6360 l 1950 6360 l 1950 6073 l 1950 6073 l 1890 6313 l 1830 6073 l cp
-eoclip
-n 1890 5445 m
- 1890 6345 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 1830 6073 m 1890 6313 l 1950 6073 l 1830 6073 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-3511 8249 m 3699 8465 l 3790 8386 l 3601 8170 l 3601 8170 l 3714 8391 l 3511 8249 l cp
-eoclip
-n 2835 7380 m
- 3735 8415 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 3511 8249 m 3714 8391 l 3601 8170 l 3511 8249 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-4785 5762 m 4785 5475 l 4665 5475 l 4665 5762 l 4665 5762 l 4725 5522 l 4785 5762 l cp
-eoclip
-n 4725 8370 m
- 4725 5490 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 4785 5762 m 4725 5522 l 4665 5762 l 4785 5762 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-7270 3691 m 7395 3432 l 7287 3380 l 7162 3639 l 7162 3639 l 7321 3449 l 7270 3691 l cp
-eoclip
-n 4950 8370 m
- 7335 3420 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 7270 3691 m 7321 3449 l 7162 3639 l 7270 3691 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-6478 6990 m 6765 6990 l 6765 6870 l 6478 6870 l 6478 6870 l 6718 6930 l 6478 6990 l cp
-eoclip
-n 2925 6930 m
- 6750 6930 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 6478 6990 m 6718 6930 l 6478 6870 l 6478 6990 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-3774 5596 m 3969 5384 l 3880 5303 l 3686 5515 l 3686 5515 l 3893 5379 l 3774 5596 l cp
-eoclip
-n 2880 6480 m
- 3915 5355 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 3774 5596 m 3893 5379 l 3686 5515 l 3774 5596 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-6478 2895 m 6765 2895 l 6765 2775 l 6478 2775 l 6478 2775 l 6718 2835 l 6478 2895 l cp
-eoclip
-n 4500 2835 m
- 6750 2835 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 6478 2895 m 6718 2835 l 6478 2775 l 6478 2895 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-7800 3692 m 7800 3405 l 7680 3405 l 7680 3692 l 7680 3692 l 7740 3452 l 7800 3692 l cp
-eoclip
-n 7740 6345 m
- 7740 3420 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 7800 3692 m 7740 3452 l 7680 3692 l 7800 3692 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-2092 4127 m 1846 4276 l 1908 4379 l 2154 4229 l 2154 4229 l 1918 4303 l 2092 4127 l cp
-eoclip
-n 3375 3420 m
- 1890 4320 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 2092 4127 m 1918 4303 l 2154 4229 l 2092 4127 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-6689 3565 m 6893 3361 l 6808 3276 l 6604 3480 l 6604 3480 l 6817 3353 l 6689 3565 l cp
-eoclip
-n 5760 4410 m
- 6840 3330 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 6689 3565 m 6817 3353 l 6604 3480 l 6689 3565 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-4773 910 m 4510 794 l 4461 903 l 4724 1020 l 4724 1020 l 4530 868 l 4773 910 l cp
-eoclip
-n 7740 2295 m
- 4500 855 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 4773 910 m 4530 868 l 4724 1020 l 4773 910 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-5995 5505 m 5791 5301 l 5706 5386 l 5910 5590 l 5910 5590 l 5783 5378 l 5995 5505 l cp
-eoclip
-n 6840 6435 m
- 5760 5355 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 5995 5505 m 5783 5378 l 5910 5590 l 5995 5505 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-6706 7624 m 6895 7408 l 6804 7329 l 6615 7545 l 6615 7545 l 6819 7404 l 6706 7624 l cp
-eoclip
-n 5895 8460 m
- 6840 7380 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 6706 7624 m 6819 7404 l 6615 7545 l 6706 7624 l  cp gs 0.00 setgray ef gr  col0 s
-% Polyline
-1 slc
-gs  clippath
-3553 4740 m 3840 4740 l 3840 4620 l 3553 4620 l 3553 4620 l 3793 4680 l 3553 4740 l cp
-eoclip
-n 2925 4680 m
- 3825 4680 l gs col0 s gr gr
-
-% arrowhead
-0 slc
-n 3553 4740 m 3793 4680 l 3553 4620 l 3553 4740 l  cp gs 0.00 setgray ef gr  col0 s
-/Courier-Oblique-iso ff 180.00 scf sf
-3157 1805 m
-gs 1 -1 sc (1) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-2327 3819 m
-gs 1 -1 sc (2) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-1627 5879 m
-gs 1 -1 sc (3) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-5767 1755 m
-gs 1 -1 sc (6) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-6047 7969 m
-gs 1 -1 sc (7) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-7487 4959 m
-gs 1 -1 sc (8) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-5882 3940 m
-gs 1 -1 sc (10) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-5292 2720 m
-gs 1 -1 sc (11) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-4142 3776 m
-gs 1 -1 sc (12) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-3082 5926 m
-gs 1 -1 sc (13) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-4052 6826 m
-gs 1 -1 sc (14) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-4432 7416 m
-gs 1 -1 sc (15) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-5127 7435 m
-gs 1 -1 sc (5) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-3582 7776 m
-gs 1 -1 sc (16) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-2957 7995 m
-gs 1 -1 sc (4) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-6487 5965 m
-gs 1 -1 sc (9) col0 sh gr
-/Times-Roman-iso ff 360.00 scf sf
-3870 9000 m
-gs 1 -1 sc (Operational) col0 sh gr
-/Times-Roman-iso ff 360.00 scf sf
-1620 4995 m
-gs 1 -1 sc (Init) col0 sh gr
-/Times-Roman-iso ff 360.00 scf sf
-1215 7020 m
-gs 1 -1 sc (Self-Test) col0 sh gr
-/Times-Roman-iso ff 360.00 scf sf
-7335 7020 m
-gs 1 -1 sc (Error) col0 sh gr
-/Times-Roman-iso ff 360.00 scf sf
-3915 4995 m
-gs 1 -1 sc (Fatal-Error) col0 sh gr
-/Times-Roman-iso ff 360.00 scf sf
-6930 2970 m
-gs 1 -1 sc (Shutdown) col0 sh gr
-/Times-Roman-iso ff 360.00 scf sf
-2655 2970 m
-gs 1 -1 sc (Power-On) col0 sh gr
-/Times-Roman-iso ff 360.00 scf sf
-2565 945 m
-gs 1 -1 sc (Power-Off) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-4066 6399 m
-gs 1 -1 sc (17) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-3076 4568 m
-gs 1 -1 sc (19) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-3055 5222 m
-gs 1 -1 sc (18) col0 sh gr
-/Courier-Oblique-iso ff 180.00 scf sf
-7612 8047 m
-gs 1 -1 sc (20) col0 sh gr
-% here ends figure;
-pagefooter
-showpage
-%%Trailer
-%EOF
diff --git a/doc/fips-fsm.pdf b/doc/fips-fsm.pdf
deleted file mode 100644 (file)
index d5cd795..0000000
Binary files a/doc/fips-fsm.pdf and /dev/null differ
diff --git a/doc/fips-fsm.png b/doc/fips-fsm.png
deleted file mode 100644 (file)
index b4136af..0000000
Binary files a/doc/fips-fsm.png and /dev/null differ
diff --git a/doc/gcrypt.info b/doc/gcrypt.info
deleted file mode 100644 (file)
index af94f12..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-This is gcrypt.info, produced by makeinfo version 6.3 from gcrypt.texi.
-
-This manual is for Libgcrypt (version 1.8.4, 24 October 2018), which is
-GNU's library of cryptographic building blocks.
-
-Copyright (C) 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2011, 2012
-Free Software Foundation, Inc.
-Copyright (C) 2012, 2013, 2016, 2017 g10 Code GmbH
-
-     Permission is granted to copy, distribute and/or modify this
-     document under the terms of the GNU General Public License as
-     published by the Free Software Foundation; either version 2 of the
-     License, or (at your option) any later version.  The text of the
-     license can be found in the section entitled "GNU General Public
-     License".
-INFO-DIR-SECTION GNU Libraries
-START-INFO-DIR-ENTRY
-* libgcrypt: (gcrypt).  Cryptographic function library.
-END-INFO-DIR-ENTRY
-
-\1f
-Indirect:
-gcrypt.info-1: 838
-gcrypt.info-2: 300899
-\1f
-Tag Table:
-(Indirect)
-Node: Top\7f838
-Node: Introduction\7f3367
-Node: Getting Started\7f3739
-Node: Features\7f4619
-Node: Overview\7f5403
-Node: Preparation\7f6026
-Node: Header\7f6949
-Node: Building sources\7f8020
-Node: Building sources using Automake\7f9937
-Node: Initializing the library\7f11865
-Ref: sample-use-suspend-secmem\7f14933
-Ref: sample-use-resume-secmem\7f15776
-Node: Multi-Threading\7f16679
-Ref: Multi-Threading-Footnote-1\7f17858
-Node: Enabling FIPS mode\7f18267
-Ref: enabling fips mode\7f18448
-Node: Hardware features\7f20260
-Ref: hardware features\7f20427
-Ref: Hardware features-Footnote-1\7f21508
-Node: Generalities\7f21669
-Node: Controlling the library\7f21928
-Node: Error Handling\7f40099
-Node: Error Values\7f42638
-Node: Error Sources\7f47578
-Node: Error Codes\7f49846
-Node: Error Strings\7f53322
-Node: Handler Functions\7f54506
-Node: Progress handler\7f55065
-Node: Allocation handler\7f57214
-Node: Error handler\7f58760
-Node: Logging handler\7f60326
-Node: Symmetric cryptography\7f60918
-Node: Available ciphers\7f61658
-Node: Available cipher modes\7f64339
-Node: Working with cipher handles\7f68192
-Node: General cipher functions\7f79696
-Node: Public Key cryptography\7f83222
-Node: Available algorithms\7f83988
-Node: Used S-expressions\7f84337
-Node: RSA key parameters\7f85454
-Node: DSA key parameters\7f86729
-Node: ECC key parameters\7f87383
-Ref: ecc_keyparam\7f87534
-Node: Cryptographic Functions\7f89405
-Node: General public-key related Functions\7f101252
-Node: Hashing\7f114921
-Node: Available hash algorithms\7f115654
-Node: Working with hash algorithms\7f121617
-Node: Message Authentication Codes\7f135749
-Node: Available MAC algorithms\7f136417
-Node: Working with MAC algorithms\7f141579
-Node: Key Derivation\7f147567
-Node: Random Numbers\7f149969
-Node: Quality of random numbers\7f150252
-Node: Retrieving random numbers\7f150935
-Node: S-expressions\7f152424
-Node: Data types for S-expressions\7f153069
-Node: Working with S-expressions\7f153395
-Node: MPI library\7f167105
-Node: Data types\7f168127
-Node: Basic functions\7f168436
-Node: MPI formats\7f170900
-Node: Calculations\7f174424
-Node: Comparisons\7f176693
-Node: Bit manipulations\7f177696
-Node: EC functions\7f179018
-Ref: gcry_mpi_ec_new\7f181967
-Node: Miscellaneous\7f187526
-Node: Prime numbers\7f191670
-Node: Generation\7f191940
-Node: Checking\7f193227
-Node: Utilities\7f193637
-Node: Memory allocation\7f194014
-Node: Context management\7f195370
-Ref: gcry_ctx_release\7f195808
-Node: Buffer description\7f195969
-Node: Config reporting\7f196756
-Node: Tools\7f197706
-Node: hmac256\7f197873
-Node: Configuration\7f198879
-Node: Architecture\7f201932
-Ref: fig:subsystems\7f203456
-Ref: Architecture-Footnote-1\7f204542
-Ref: Architecture-Footnote-2\7f204604
-Node: Public-Key Subsystem Architecture\7f204688
-Node: Symmetric Encryption Subsystem Architecture\7f206966
-Node: Hashing and MACing Subsystem Architecture\7f208412
-Node: Multi-Precision-Integer Subsystem Architecture\7f210335
-Node: Prime-Number-Generator Subsystem Architecture\7f211773
-Ref: Prime-Number-Generator Subsystem Architecture-Footnote-1\7f213704
-Node: Random-Number Subsystem Architecture\7f213996
-Node: CSPRNG Description\7f216945
-Ref: CSPRNG Description-Footnote-1\7f218501
-Node: FIPS PRNG Description\7f218624
-Node: Self-Tests\7f220758
-Node: FIPS Mode\7f232217
-Ref: fig:fips-fsm\7f236043
-Ref: tbl:fips-states\7f236146
-Ref: tbl:fips-state-transitions\7f237398
-Node: Library Copying\7f241019
-Node: Copying\7f269125
-Node: Figures and Tables\7f288301
-Node: Concept Index\7f288726
-Node: Function and Data Index\7f300899
-\1f
-End Tag Table
diff --git a/doc/gcrypt.info-1 b/doc/gcrypt.info-1
deleted file mode 100644 (file)
index 3acfec9..0000000
+++ /dev/null
@@ -1,7016 +0,0 @@
-This is gcrypt.info, produced by makeinfo version 6.3 from gcrypt.texi.
-
-This manual is for Libgcrypt (version 1.8.4, 24 October 2018), which is
-GNU's library of cryptographic building blocks.
-
-Copyright (C) 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2011, 2012
-Free Software Foundation, Inc.
-Copyright (C) 2012, 2013, 2016, 2017 g10 Code GmbH
-
-     Permission is granted to copy, distribute and/or modify this
-     document under the terms of the GNU General Public License as
-     published by the Free Software Foundation; either version 2 of the
-     License, or (at your option) any later version.  The text of the
-     license can be found in the section entitled "GNU General Public
-     License".
-INFO-DIR-SECTION GNU Libraries
-START-INFO-DIR-ENTRY
-* libgcrypt: (gcrypt).  Cryptographic function library.
-END-INFO-DIR-ENTRY
-
-\1f
-File: gcrypt.info,  Node: Top,  Next: Introduction,  Up: (dir)
-
-The Libgcrypt Library
-*********************
-
-This manual is for Libgcrypt (version 1.8.4, 24 October 2018), which is
-GNU's library of cryptographic building blocks.
-
-Copyright (C) 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2011, 2012
-Free Software Foundation, Inc.
-Copyright (C) 2012, 2013, 2016, 2017 g10 Code GmbH
-
-     Permission is granted to copy, distribute and/or modify this
-     document under the terms of the GNU General Public License as
-     published by the Free Software Foundation; either version 2 of the
-     License, or (at your option) any later version.  The text of the
-     license can be found in the section entitled "GNU General Public
-     License".
-
-* Menu:
-
-* Introduction::                 What is Libgcrypt.
-* Preparation::                  What you should do before using the library.
-* Generalities::                 General library functions and data types.
-* Handler Functions::            Working with handler functions.
-* Symmetric cryptography::       How to use symmetric cryptography.
-* Public Key cryptography::      How to use public key cryptography.
-* Hashing::                      How to use hash algorithms.
-* Message Authentication Codes:: How to use MAC algorithms.
-* Key Derivation::               How to derive keys from strings
-* Random Numbers::               How to work with random numbers.
-* S-expressions::                How to manage S-expressions.
-* MPI library::                  How to work with multi-precision-integers.
-* Prime numbers::                How to use the Prime number related functions.
-* Utilities::                    Utility functions.
-* Tools::                        Utility tools.
-* Configuration::                Configuration files and environment variables.
-* Architecture::                 How Libgcrypt works internally.
-
-Appendices
-
-* Self-Tests::                  Description of the self-tests.
-* FIPS Mode::                   Description of the FIPS mode.
-* Library Copying::             The GNU Lesser General Public License
-                                says how you can copy and share Libgcrypt.
-* Copying::                     The GNU General Public License says how you
-                                can copy and share some parts of Libgcrypt.
-
-Indices
-
-* Figures and Tables::          Index of figures and tables.
-* Concept Index::               Index of concepts and programs.
-* Function and Data Index::     Index of functions, variables and data types.
-
-\1f
-File: gcrypt.info,  Node: Introduction,  Next: Preparation,  Prev: Top,  Up: Top
-
-1 Introduction
-**************
-
-Libgcrypt is a library providing cryptographic building blocks.
-
-* Menu:
-
-* Getting Started::             How to use this manual.
-* Features::                    A glance at Libgcrypt's features.
-* Overview::                    Overview about the library.
-
-\1f
-File: gcrypt.info,  Node: Getting Started,  Next: Features,  Up: Introduction
-
-1.1 Getting Started
-===================
-
-This manual documents the Libgcrypt library application programming
-interface (API). All functions and data types provided by the library
-are explained.
-
-The reader is assumed to possess basic knowledge about applied
-cryptography.
-
-   This manual can be used in several ways.  If read from the beginning
-to the end, it gives a good introduction into the library and how it can
-be used in an application.  Forward references are included where
-necessary.  Later on, the manual can be used as a reference manual to
-get just the information needed about any particular interface of the
-library.  Experienced programmers might want to start looking at the
-examples at the end of the manual, and then only read up those parts of
-the interface which are unclear.
-
-\1f
-File: gcrypt.info,  Node: Features,  Next: Overview,  Prev: Getting Started,  Up: Introduction
-
-1.2 Features
-============
-
-Libgcrypt might have a couple of advantages over other libraries doing a
-similar job.
-
-It's Free Software
-     Anybody can use, modify, and redistribute it under the terms of the
-     GNU Lesser General Public License (*note Library Copying::).  Note,
-     that some parts (which are in general not needed by applications)
-     are subject to the terms of the GNU General Public License (*note
-     Copying::); please see the README file of the distribution for of
-     list of these parts.
-
-It encapsulates the low level cryptography
-     Libgcrypt provides a high level interface to cryptographic building
-     blocks using an extensible and flexible API.
-
-\1f
-File: gcrypt.info,  Node: Overview,  Prev: Features,  Up: Introduction
-
-1.3 Overview
-============
-
-The Libgcrypt library is fully thread-safe, where it makes sense to be
-thread-safe.  Not thread-safe are some cryptographic functions that
-modify a certain context stored in handles.  If the user really intents
-to use such functions from different threads on the same handle, he has
-to take care of the serialization of such functions himself.  If not
-described otherwise, every function is thread-safe.
-
-   Libgcrypt depends on the library 'libgpg-error', which contains some
-common code used by other GnuPG components.
-
-\1f
-File: gcrypt.info,  Node: Preparation,  Next: Generalities,  Prev: Introduction,  Up: Top
-
-2 Preparation
-*************
-
-To use Libgcrypt, you have to perform some changes to your sources and
-the build system.  The necessary changes are small and explained in the
-following sections.  At the end of this chapter, it is described how the
-library is initialized, and how the requirements of the library are
-verified.
-
-* Menu:
-
-* Header::                      What header file you need to include.
-* Building sources::            How to build sources using the library.
-* Building sources using Automake::  How to build sources with the help of Automake.
-* Initializing the library::    How to initialize the library.
-* Multi-Threading::             How Libgcrypt can be used in a MT environment.
-* Enabling FIPS mode::          How to enable the FIPS mode.
-* Hardware features::           How to disable hardware features.
-
-\1f
-File: gcrypt.info,  Node: Header,  Next: Building sources,  Up: Preparation
-
-2.1 Header
-==========
-
-All interfaces (data types and functions) of the library are defined in
-the header file 'gcrypt.h'.  You must include this in all source files
-using the library, either directly or through some other header file,
-like this:
-
-     #include <gcrypt.h>
-
-   The name space of Libgcrypt is 'gcry_*' for function and type names
-and 'GCRY*' for other symbols.  In addition the same name prefixes with
-one prepended underscore are reserved for internal use and should never
-be used by an application.  Note that Libgcrypt uses libgpg-error, which
-uses 'gpg_*' as name space for function and type names and 'GPG_*' for
-other symbols, including all the error codes.
-
-Certain parts of gcrypt.h may be excluded by defining these macros:
-
-'GCRYPT_NO_MPI_MACROS'
-     Do not define the shorthand macros 'mpi_*' for 'gcry_mpi_*'.
-
-'GCRYPT_NO_DEPRECATED'
-     Do not include definitions for deprecated features.  This is useful
-     to make sure that no deprecated features are used.
-
-\1f
-File: gcrypt.info,  Node: Building sources,  Next: Building sources using Automake,  Prev: Header,  Up: Preparation
-
-2.2 Building sources
-====================
-
-If you want to compile a source file including the 'gcrypt.h' header
-file, you must make sure that the compiler can find it in the directory
-hierarchy.  This is accomplished by adding the path to the directory in
-which the header file is located to the compilers include file search
-path (via the '-I' option).
-
-   However, the path to the include file is determined at the time the
-source is configured.  To solve this problem, Libgcrypt ships with a
-small helper program 'libgcrypt-config' that knows the path to the
-include file and other configuration options.  The options that need to
-be added to the compiler invocation at compile time are output by the
-'--cflags' option to 'libgcrypt-config'.  The following example shows
-how it can be used at the command line:
-
-     gcc -c foo.c `libgcrypt-config --cflags`
-
-   Adding the output of 'libgcrypt-config --cflags' to the compiler’s
-command line will ensure that the compiler can find the Libgcrypt header
-file.
-
-   A similar problem occurs when linking the program with the library.
-Again, the compiler has to find the library files.  For this to work,
-the path to the library files has to be added to the library search path
-(via the '-L' option).  For this, the option '--libs' to
-'libgcrypt-config' can be used.  For convenience, this option also
-outputs all other options that are required to link the program with the
-Libgcrypt libraries (in particular, the '-lgcrypt' option).  The example
-shows how to link 'foo.o' with the Libgcrypt library to a program 'foo'.
-
-     gcc -o foo foo.o `libgcrypt-config --libs`
-
-   Of course you can also combine both examples to a single command by
-specifying both options to 'libgcrypt-config':
-
-     gcc -o foo foo.c `libgcrypt-config --cflags --libs`
-
-\1f
-File: gcrypt.info,  Node: Building sources using Automake,  Next: Initializing the library,  Prev: Building sources,  Up: Preparation
-
-2.3 Building sources using Automake
-===================================
-
-It is much easier if you use GNU Automake instead of writing your own
-Makefiles.  If you do that, you do not have to worry about finding and
-invoking the 'libgcrypt-config' script at all.  Libgcrypt provides an
-extension to Automake that does all the work for you.
-
- -- Macro: AM_PATH_LIBGCRYPT ([MINIMUM-VERSION], [ACTION-IF-FOUND],
-          [ACTION-IF-NOT-FOUND])
-     Check whether Libgcrypt (at least version MINIMUM-VERSION, if
-     given) exists on the host system.  If it is found, execute
-     ACTION-IF-FOUND, otherwise do ACTION-IF-NOT-FOUND, if given.
-
-     Additionally, the function defines 'LIBGCRYPT_CFLAGS' to the flags
-     needed for compilation of the program to find the 'gcrypt.h' header
-     file, and 'LIBGCRYPT_LIBS' to the linker flags needed to link the
-     program to the Libgcrypt library.  If the used helper script does
-     not match the target type you are building for a warning is printed
-     and the string 'libgcrypt' is appended to the variable
-     'gpg_config_script_warn'.
-
-     This macro searches for 'libgcrypt-config' along the PATH. If you
-     are cross-compiling, it is useful to set the environment variable
-     'SYSROOT' to the top directory of your target.  The macro will then
-     first look for the helper program in the 'bin' directory below that
-     top directory.  An absolute directory name must be used for
-     'SYSROOT'.  Finally, if the configure command line option
-     '--with-libgcrypt-prefix' is used, only its value is used for the
-     top directory below which the helper script is expected.
-
-   You can use the defined Autoconf variables like this in your
-'Makefile.am':
-
-     AM_CPPFLAGS = $(LIBGCRYPT_CFLAGS)
-     LDADD = $(LIBGCRYPT_LIBS)
-
-\1f
-File: gcrypt.info,  Node: Initializing the library,  Next: Multi-Threading,  Prev: Building sources using Automake,  Up: Preparation
-
-2.4 Initializing the library
-============================
-
-Before the library can be used, it must initialize itself.  This is
-achieved by invoking the function 'gcry_check_version' described below.
-
-   Also, it is often desirable to check that the version of Libgcrypt
-used is indeed one which fits all requirements.  Even with binary
-compatibility, new features may have been introduced, but due to problem
-with the dynamic linker an old version may actually be used.  So you may
-want to check that the version is okay right after program startup.
-
- -- Function: const char * gcry_check_version (const char *REQ_VERSION)
-
-     The function 'gcry_check_version' initializes some subsystems used
-     by Libgcrypt and must be invoked before any other function in the
-     library.  *Note Multi-Threading::.
-
-     Furthermore, this function returns the version number of the
-     library.  It can also verify that the version number is higher than
-     a certain required version number REQ_VERSION, if this value is not
-     a null pointer.
-
-   Libgcrypt uses a concept known as secure memory, which is a region of
-memory set aside for storing sensitive data.  Because such memory is a
-scarce resource, it needs to be setup in advanced to a fixed size.
-Further, most operating systems have special requirements on how that
-secure memory can be used.  For example, it might be required to install
-an application as "setuid(root)" to allow allocating such memory.
-Libgcrypt requires a sequence of initialization steps to make sure that
-this works correctly.  The following examples show the necessary steps.
-
-   If you don't have a need for secure memory, for example if your
-application does not use secret keys or other confidential data or it
-runs in a controlled environment where key material floating around in
-memory is not a problem, you should initialize Libgcrypt this way:
-
-       /* Version check should be the very first call because it
-          makes sure that important subsystems are initialized. */
-       if (!gcry_check_version (GCRYPT_VERSION))
-         {
-           fputs ("libgcrypt version mismatch\n", stderr);
-           exit (2);
-         }
-
-       /* Disable secure memory.  */
-       gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-
-       /* ... If required, other initialization goes here.  */
-
-       /* Tell Libgcrypt that initialization has completed. */
-       gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
-
-   If you have to protect your keys or other information in memory
-against being swapped out to disk and to enable an automatic overwrite
-of used and freed memory, you need to initialize Libgcrypt this way:
-
-       /* Version check should be the very first call because it
-          makes sure that important subsystems are initialized. */
-       if (!gcry_check_version (GCRYPT_VERSION))
-         {
-           fputs ("libgcrypt version mismatch\n", stderr);
-           exit (2);
-         }
-
-       /* We don't want to see any warnings, e.g. because we have not yet
-          parsed program options which might be used to suppress such
-          warnings. */
-       gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
-
-       /* ... If required, other initialization goes here.  Note that the
-          process might still be running with increased privileges and that
-          the secure memory has not been initialized.  */
-
-       /* Allocate a pool of 16k secure memory.  This makes the secure memory
-          available and also drops privileges where needed.  Note that by
-          using functions like gcry_xmalloc_secure and gcry_mpi_snew Libgcrypt
-          may expand the secure memory pool with memory which lacks the
-          property of not being swapped out to disk.   */
-       gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
-
-       /* It is now okay to let Libgcrypt complain when there was/is
-          a problem with the secure memory. */
-       gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
-
-       /* ... If required, other initialization goes here.  */
-
-       /* Tell Libgcrypt that initialization has completed. */
-       gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
-
-   It is important that these initialization steps are not done by a
-library but by the actual application.  A library using Libgcrypt might
-want to check for finished initialization using:
-
-       if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P))
-         {
-           fputs ("libgcrypt has not been initialized\n", stderr);
-           abort ();
-         }
-
-   Instead of terminating the process, the library may instead print a
-warning and try to initialize Libgcrypt itself.  See also the section on
-multi-threading below for more pitfalls.
-
-\1f
-File: gcrypt.info,  Node: Multi-Threading,  Next: Enabling FIPS mode,  Prev: Initializing the library,  Up: Preparation
-
-2.5 Multi-Threading
-===================
-
-As mentioned earlier, the Libgcrypt library is thread-safe if you adhere
-to the following requirements:
-
-   * If you use pthread and your applications forks and does not
-     directly call exec (even calling stdio functions), all kind of
-     problems may occur.  Future versions of Libgcrypt will try to
-     cleanup using pthread_atfork but even that may lead to problems.
-     This is a common problem with almost all applications using pthread
-     and fork.
-
-   * The function 'gcry_check_version' must be called before any other
-     function in the library.  To achieve this in multi-threaded
-     programs, you must synchronize the memory with respect to other
-     threads that also want to use Libgcrypt.  For this, it is
-     sufficient to call 'gcry_check_version' before creating the other
-     threads using Libgcrypt(1).
-
-   * Just like the function 'gpg_strerror', the function 'gcry_strerror'
-     is not thread safe.  You have to use 'gpg_strerror_r' instead.
-
-   ---------- Footnotes ----------
-
-   (1) At least this is true for POSIX threads, as 'pthread_create' is a
-function that synchronizes memory with respects to other threads.  There
-are many functions which have this property, a complete list can be
-found in POSIX, IEEE Std 1003.1-2003, Base Definitions, Issue 6, in the
-definition of the term "Memory Synchronization".  For other thread
-packages, more relaxed or more strict rules may apply.
-
-\1f
-File: gcrypt.info,  Node: Enabling FIPS mode,  Next: Hardware features,  Prev: Multi-Threading,  Up: Preparation
-
-2.6 How to enable the FIPS mode
-===============================
-
-Libgcrypt may be used in a FIPS 140-2 mode.  Note, that this does not
-necessary mean that Libcgrypt is an appoved FIPS 140-2 module.  Check
-the NIST database at <http://csrc.nist.gov/groups/STM/cmvp/> to see what
-versions of Libgcrypt are approved.
-
-   Because FIPS 140 has certain restrictions on the use of cryptography
-which are not always wanted, Libgcrypt needs to be put into FIPS mode
-explicitly.  Three alternative mechanisms are provided to switch
-Libgcrypt into this mode:
-
-   * If the file '/proc/sys/crypto/fips_enabled' exists and contains a
-     numeric value other than '0', Libgcrypt is put into FIPS mode at
-     initialization time.  Obviously this works only on systems with a
-     'proc' file system (i.e.  GNU/Linux).
-
-   * If the file '/etc/gcrypt/fips_enabled' exists, Libgcrypt is put
-     into FIPS mode at initialization time.  Note that this filename is
-     hardwired and does not depend on any configuration options.
-
-   * If the application requests FIPS mode using the control command
-     'GCRYCTL_FORCE_FIPS_MODE'.  This must be done prior to any
-     initialization (i.e.  before 'gcry_check_version').
-
-   In addition to the standard FIPS mode, Libgcrypt may also be put into
-an Enforced FIPS mode by writing a non-zero value into the file
-'/etc/gcrypt/fips_enabled' or by using the control command
-'GCRYCTL_SET_ENFORCED_FIPS_FLAG' before any other calls to libgcrypt.
-The Enforced FIPS mode helps to detect applications which don't fulfill
-all requirements for using Libgcrypt in FIPS mode (*note FIPS Mode::).
-
-   Once Libgcrypt has been put into FIPS mode, it is not possible to
-switch back to standard mode without terminating the process first.  If
-the logging verbosity level of Libgcrypt has been set to at least 2, the
-state transitions and the self-tests are logged.
-
-\1f
-File: gcrypt.info,  Node: Hardware features,  Prev: Enabling FIPS mode,  Up: Preparation
-
-2.7 How to disable hardware features
-====================================
-
-Libgcrypt makes use of certain hardware features.  If the use of a
-feature is not desired it may be either be disabled by a program or
-globally using a configuration file.  The currently supported features
-are
-
-'padlock-rng'
-'padlock-aes'
-'padlock-sha'
-'padlock-mmul'
-'intel-cpu'
-'intel-fast-shld'
-'intel-bmi2'
-'intel-ssse3'
-'intel-pclmul'
-'intel-aesni'
-'intel-rdrand'
-'intel-avx'
-'intel-avx2'
-'intel-rdtsc'
-'arm-neon'
-
-   To disable a feature for all processes using Libgcrypt 1.6 or newer,
-create the file '/etc/gcrypt/hwf.deny' and put each feature not to be
-used on a single line.  Empty lines, white space, and lines prefixed
-with a hash mark are ignored.  The file should be world readable.
-
-   To disable a feature specifically for a program that program must
-tell it Libgcrypt before before calling 'gcry_check_version'.
-Example:(1)
-
-       gcry_control (GCRYCTL_DISABLE_HWF, "intel-rdrand", NULL);
-
-To print the list of active features you may use this command:
-
-       mpicalc --print-config | grep ^hwflist: | tr : '\n' | tail -n +2
-
-   ---------- Footnotes ----------
-
-   (1) NB. Libgcrypt uses the RDRAND feature only as one source of
-entropy.  A CPU with a broken RDRAND will thus not compromise of the
-random number generator
-
-\1f
-File: gcrypt.info,  Node: Generalities,  Next: Handler Functions,  Prev: Preparation,  Up: Top
-
-3 Generalities
-**************
-
-* Menu:
-
-* Controlling the library::     Controlling Libgcrypt's behavior.
-* Error Handling::              Error codes and such.
-
-\1f
-File: gcrypt.info,  Node: Controlling the library,  Next: Error Handling,  Up: Generalities
-
-3.1 Controlling the library
-===========================
-
- -- Function: gcry_error_t gcry_control (enum gcry_ctl_cmds CMD, ...)
-
-     This function can be used to influence the general behavior of
-     Libgcrypt in several ways.  Depending on CMD, more arguments can or
-     have to be provided.
-
-     'GCRYCTL_ENABLE_M_GUARD; Arguments: none'
-          This command enables the built-in memory guard.  It must not
-          be used to activate the memory guard after the memory
-          management has already been used; therefore it can ONLY be
-          used before 'gcry_check_version'.  Note that the memory guard
-          is NOT used when the user of the library has set his own
-          memory management callbacks.
-
-     'GCRYCTL_ENABLE_QUICK_RANDOM; Arguments: none'
-          This command inhibits the use the very secure random quality
-          level ('GCRY_VERY_STRONG_RANDOM') and degrades all request
-          down to 'GCRY_STRONG_RANDOM'.  In general this is not
-          recommended.  However, for some applications the extra quality
-          random Libgcrypt tries to create is not justified and this
-          option may help to get better performance.  Please check with
-          a crypto expert whether this option can be used for your
-          application.
-
-          This option can only be used at initialization time.
-
-     'GCRYCTL_DUMP_RANDOM_STATS; Arguments: none'
-          This command dumps random number generator related statistics
-          to the library's logging stream.
-
-     'GCRYCTL_DUMP_MEMORY_STATS; Arguments: none'
-          This command dumps memory management related statistics to the
-          library's logging stream.
-
-     'GCRYCTL_DUMP_SECMEM_STATS; Arguments: none'
-          This command dumps secure memory management related statistics
-          to the library's logging stream.
-
-     'GCRYCTL_DROP_PRIVS; Arguments: none'
-          This command disables the use of secure memory and drops the
-          privileges of the current process.  This command has not much
-          use; the suggested way to disable secure memory is to use
-          'GCRYCTL_DISABLE_SECMEM' right after initialization.
-
-     'GCRYCTL_DISABLE_SECMEM; Arguments: none'
-          This command disables the use of secure memory.  If this
-          command is used in FIPS mode, FIPS mode will be disabled and
-          the function 'gcry_fips_mode_active' returns false.  However,
-          in Enforced FIPS mode this command has no effect at all.
-
-          Many applications do not require secure memory, so they should
-          disable it right away.  This command should be executed right
-          after 'gcry_check_version'.
-
-     'GCRYCTL_DISABLE_LOCKED_SECMEM; Arguments: none'
-          This command disables the use of the mlock call for secure
-          memory.  Disabling the use of mlock may for example be done if
-          an encrypted swap space is in use.  This command should be
-          executed right after 'gcry_check_version'.  Note that by using
-          functions like gcry_xmalloc_secure and gcry_mpi_snew Libgcrypt
-          may expand the secure memory pool with memory which lacks the
-          property of not being swapped out to disk (but will still be
-          zeroed out on free).
-
-     'GCRYCTL_DISABLE_PRIV_DROP; Arguments: none'
-          This command sets a global flag to tell the secure memory
-          subsystem that it shall not drop privileges after secure
-          memory has been allocated.  This command is commonly used
-          right after 'gcry_check_version' but may also be used right
-          away at program startup.  It won't have an effect after the
-          secure memory pool has been initialized.  WARNING: A process
-          running setuid(root) is a severe security risk.  Processes
-          making use of Libgcrypt or other complex code should drop
-          these extra privileges as soon as possible.  If this command
-          has been used the caller is responsible for dropping the
-          privileges.
-
-     'GCRYCTL_INIT_SECMEM; Arguments: unsigned int nbytes'
-          This command is used to allocate a pool of secure memory and
-          thus enabling the use of secure memory.  It also drops all
-          extra privileges the process has (i.e.  if it is run as setuid
-          (root)).  If the argument NBYTES is 0, secure memory will be
-          disabled.  The minimum amount of secure memory allocated is
-          currently 16384 bytes; you may thus use a value of 1 to
-          request that default size.
-
-     'GCRYCTL_TERM_SECMEM; Arguments: none'
-          This command zeroises the secure memory and destroys the
-          handler.  The secure memory pool may not be used anymore after
-          running this command.  If the secure memory pool as already
-          been destroyed, this command has no effect.  Applications
-          might want to run this command from their exit handler to make
-          sure that the secure memory gets properly destroyed.  This
-          command is not necessarily thread-safe but that should not be
-          needed in cleanup code.  It may be called from a signal
-          handler.
-
-     'GCRYCTL_DISABLE_SECMEM_WARN; Arguments: none'
-          Disable warning messages about problems with the secure memory
-          subsystem.  This command should be run right after
-          'gcry_check_version'.
-
-     'GCRYCTL_SUSPEND_SECMEM_WARN; Arguments: none'
-          Postpone warning messages from the secure memory subsystem.
-          *Note the initialization example: sample-use-suspend-secmem,
-          on how to use it.
-
-     'GCRYCTL_RESUME_SECMEM_WARN; Arguments: none'
-          Resume warning messages from the secure memory subsystem.
-          *Note the initialization example: sample-use-resume-secmem, on
-          how to use it.
-
-     'GCRYCTL_USE_SECURE_RNDPOOL; Arguments: none'
-          This command tells the PRNG to store random numbers in secure
-          memory.  This command should be run right after
-          'gcry_check_version' and not later than the command
-          GCRYCTL_INIT_SECMEM. Note that in FIPS mode the secure memory
-          is always used.
-
-     'GCRYCTL_SET_RANDOM_SEED_FILE; Arguments: const char *filename'
-          This command specifies the file, which is to be used as seed
-          file for the PRNG. If the seed file is registered prior to
-          initialization of the PRNG, the seed file's content (if it
-          exists and seems to be valid) is fed into the PRNG pool.
-          After the seed file has been registered, the PRNG can be
-          signalled to write out the PRNG pool's content into the seed
-          file with the following command.
-
-     'GCRYCTL_UPDATE_RANDOM_SEED_FILE; Arguments: none'
-          Write out the PRNG pool's content into the registered seed
-          file.
-
-          Multiple instances of the applications sharing the same random
-          seed file can be started in parallel, in which case they will
-          read out the same pool and then race for updating it (the last
-          update overwrites earlier updates).  They will differentiate
-          only by the weak entropy that is added in read_seed_file based
-          on the PID and clock, and up to 16 bytes of weak random
-          non-blockingly.  The consequence is that the output of these
-          different instances is correlated to some extent.  In a
-          perfect attack scenario, the attacker can control (or at least
-          guess) the PID and clock of the application, and drain the
-          system's entropy pool to reduce the "up to 16 bytes" above to
-          0.  Then the dependencies of the initial states of the pools
-          are completely known.  Note that this is not an issue if
-          random of 'GCRY_VERY_STRONG_RANDOM' quality is requested as in
-          this case enough extra entropy gets mixed.  It is also not an
-          issue when using Linux (rndlinux driver), because this one
-          guarantees to read full 16 bytes from /dev/urandom and thus
-          there is no way for an attacker without kernel access to
-          control these 16 bytes.
-
-     'GCRYCTL_CLOSE_RANDOM_DEVICE; Arguments: none'
-          Try to close the random device.  If on Unix system you call
-          fork(), the child process does no call exec(), and you do not
-          intend to use Libgcrypt in the child, it might be useful to
-          use this control code to close the inherited file descriptors
-          of the random device.  If Libgcrypt is later used again by the
-          child, the device will be re-opened.  On non-Unix systems this
-          control code is ignored.
-
-     'GCRYCTL_SET_VERBOSITY; Arguments: int level'
-          This command sets the verbosity of the logging.  A level of 0
-          disables all extra logging whereas positive numbers enable
-          more verbose logging.  The level may be changed at any time
-          but be aware that no memory synchronization is done so the
-          effect of this command might not immediately show up in other
-          threads.  This command may even be used prior to
-          'gcry_check_version'.
-
-     'GCRYCTL_SET_DEBUG_FLAGS; Arguments: unsigned int flags'
-          Set the debug flag bits as given by the argument.  Be aware
-          that that no memory synchronization is done so the effect of
-          this command might not immediately show up in other threads.
-          The debug flags are not considered part of the API and thus
-          may change without notice.  As of now bit 0 enables debugging
-          of cipher functions and bit 1 debugging of
-          multi-precision-integers.  This command may even be used prior
-          to 'gcry_check_version'.
-
-     'GCRYCTL_CLEAR_DEBUG_FLAGS; Arguments: unsigned int flags'
-          Set the debug flag bits as given by the argument.  Be aware
-          that that no memory synchronization is done so the effect of
-          this command might not immediately show up in other threads.
-          This command may even be used prior to 'gcry_check_version'.
-
-     'GCRYCTL_DISABLE_INTERNAL_LOCKING; Arguments: none'
-          This command does nothing.  It exists only for backward
-          compatibility.
-
-     'GCRYCTL_ANY_INITIALIZATION_P; Arguments: none'
-          This command returns true if the library has been basically
-          initialized.  Such a basic initialization happens implicitly
-          with many commands to get certain internal subsystems running.
-          The common and suggested way to do this basic initialization
-          is by calling gcry_check_version.
-
-     'GCRYCTL_INITIALIZATION_FINISHED; Arguments: none'
-          This command tells the library that the application has
-          finished the initialization.
-
-     'GCRYCTL_INITIALIZATION_FINISHED_P; Arguments: none'
-          This command returns true if the command
-          GCRYCTL_INITIALIZATION_FINISHED has already been run.
-
-     'GCRYCTL_SET_THREAD_CBS; Arguments: struct ath_ops *ath_ops'
-          This command is obsolete since version 1.6.
-
-     'GCRYCTL_FAST_POLL; Arguments: none'
-          Run a fast random poll.
-
-     'GCRYCTL_SET_RNDEGD_SOCKET; Arguments: const char *filename'
-          This command may be used to override the default name of the
-          EGD socket to connect to.  It may be used only during
-          initialization as it is not thread safe.  Changing the socket
-          name again is not supported.  The function may return an error
-          if the given filename is too long for a local socket name.
-
-          EGD is an alternative random gatherer, used only on systems
-          lacking a proper random device.
-
-     'GCRYCTL_PRINT_CONFIG; Arguments: FILE *stream'
-          This command dumps information pertaining to the configuration
-          of the library to the given stream.  If NULL is given for
-          STREAM, the log system is used.  This command may be used
-          before the initialization has been finished but not before a
-          'gcry_check_version'.  Note that the macro 'estream_t' can be
-          used instead of 'gpgrt_stream_t'.
-
-     'GCRYCTL_OPERATIONAL_P; Arguments: none'
-          This command returns true if the library is in an operational
-          state.  This information makes only sense in FIPS mode.  In
-          contrast to other functions, this is a pure test function and
-          won't put the library into FIPS mode or change the internal
-          state.  This command may be used before the initialization has
-          been finished but not before a 'gcry_check_version'.
-
-     'GCRYCTL_FIPS_MODE_P; Arguments: none'
-          This command returns true if the library is in FIPS mode.
-          Note, that this is no indication about the current state of
-          the library.  This command may be used before the
-          initialization has been finished but not before a
-          'gcry_check_version'.  An application may use this command or
-          the convenience macro below to check whether FIPS mode is
-          actually active.
-
-           -- Function: int gcry_fips_mode_active (void)
-
-               Returns true if the FIPS mode is active.  Note that this
-               is implemented as a macro.
-
-     'GCRYCTL_FORCE_FIPS_MODE; Arguments: none'
-          Running this command puts the library into FIPS mode.  If the
-          library is already in FIPS mode, a self-test is triggered and
-          thus the library will be put into operational state.  This
-          command may be used before a call to 'gcry_check_version' and
-          that is actually the recommended way to let an application
-          switch the library into FIPS mode.  Note that Libgcrypt will
-          reject an attempt to switch to fips mode during or after the
-          initialization.
-
-     'GCRYCTL_SET_ENFORCED_FIPS_FLAG; Arguments: none'
-          Running this command sets the internal flag that puts the
-          library into the enforced FIPS mode during the FIPS mode
-          initialization.  This command does not affect the library if
-          the library is not put into the FIPS mode and it must be used
-          before any other libgcrypt library calls that initialize the
-          library such as 'gcry_check_version'.  Note that Libgcrypt
-          will reject an attempt to switch to the enforced fips mode
-          during or after the initialization.
-
-     'GCRYCTL_SET_PREFERRED_RNG_TYPE; Arguments: int'
-          These are advisory commands to select a certain random number
-          generator.  They are only advisory because libraries may not
-          know what an application actually wants or vice versa.  Thus
-          Libgcrypt employs a priority check to select the actually used
-          RNG. If an applications selects a lower priority RNG but a
-          library requests a higher priority RNG Libgcrypt will switch
-          to the higher priority RNG. Applications and libraries should
-          use these control codes before 'gcry_check_version'.  The
-          available generators are:
-          'GCRY_RNG_TYPE_STANDARD'
-               A conservative standard generator based on the
-               "Continuously Seeded Pseudo Random Number Generator"
-               designed by Peter Gutmann.
-          'GCRY_RNG_TYPE_FIPS'
-               A deterministic random number generator conforming to he
-               document "NIST-Recommended Random Number Generator Based
-               on ANSI X9.31 Appendix A.2.4 Using the 3-Key Triple DES
-               and AES Algorithms" (2005-01-31).  This implementation
-               uses the AES variant.
-          'GCRY_RNG_TYPE_SYSTEM'
-               A wrapper around the system's native RNG. On Unix system
-               these are usually the /dev/random and /dev/urandom
-               devices.
-          The default is 'GCRY_RNG_TYPE_STANDARD' unless FIPS mode as
-          been enabled; in which case 'GCRY_RNG_TYPE_FIPS' is used and
-          locked against further changes.
-
-     'GCRYCTL_GET_CURRENT_RNG_TYPE; Arguments: int *'
-          This command stores the type of the currently used RNG as an
-          integer value at the provided address.
-
-     'GCRYCTL_SELFTEST; Arguments: none'
-          This may be used at anytime to have the library run all
-          implemented self-tests.  It works in standard and in FIPS
-          mode.  Returns 0 on success or an error code on failure.
-
-     'GCRYCTL_DISABLE_HWF; Arguments: const char *name'
-
-          Libgcrypt detects certain features of the CPU at startup time.
-          For performance tests it is sometimes required not to use such
-          a feature.  This option may be used to disable a certain
-          feature; i.e.  Libgcrypt behaves as if this feature has not
-          been detected.  This call can be used several times to disable
-          a set of features, or features may be given as a colon or
-          comma delimited string.  The special feature "all" can be used
-          to disable all available features.
-
-          Note that the detection code might be run if the feature has
-          been disabled.  This command must be used at initialization
-          time; i.e.  before calling 'gcry_check_version'.
-
-     'GCRYCTL_REINIT_SYSCALL_CLAMP; Arguments: none'
-
-          Libgcrypt wraps blocking system calls with two functions calls
-          ("system call clamp") to give user land threading libraries a
-          hook for re-scheduling.  This works by reading the system call
-          clamp from Libgpg-error at initialization time.  However
-          sometimes Libgcrypt needs to be initialized before the user
-          land threading systems and at that point the system call clamp
-          has not been registered with Libgpg-error and in turn
-          Libgcrypt would not use them.  The control code can be used to
-          tell Libgcrypt that a system call clamp has now been
-          registered with Libgpg-error and advised it to read the clamp
-          again.  Obviously this control code may only be used before a
-          second thread is started in a process.
-
-\1f
-File: gcrypt.info,  Node: Error Handling,  Prev: Controlling the library,  Up: Generalities
-
-3.2 Error Handling
-==================
-
-Many functions in Libgcrypt can return an error if they fail.  For this
-reason, the application should always catch the error condition and take
-appropriate measures, for example by releasing the resources and passing
-the error up to the caller, or by displaying a descriptive message to
-the user and cancelling the operation.
-
-   Some error values do not indicate a system error or an error in the
-operation, but the result of an operation that failed properly.  For
-example, if you try to decrypt a tempered message, the decryption will
-fail.  Another error value actually means that the end of a data buffer
-or list has been reached.  The following descriptions explain for many
-error codes what they mean usually.  Some error values have specific
-meanings if returned by a certain functions.  Such cases are described
-in the documentation of those functions.
-
-   Libgcrypt uses the 'libgpg-error' library.  This allows to share the
-error codes with other components of the GnuPG system, and to pass error
-values transparently from the crypto engine, or some helper application
-of the crypto engine, to the user.  This way no information is lost.  As
-a consequence, Libgcrypt does not use its own identifiers for error
-codes, but uses those provided by 'libgpg-error'.  They usually start
-with 'GPG_ERR_'.
-
-   However, Libgcrypt does provide aliases for the functions defined in
-libgpg-error, which might be preferred for name space consistency.
-
-   Most functions in Libgcrypt return an error code in the case of
-failure.  For this reason, the application should always catch the error
-condition and take appropriate measures, for example by releasing the
-resources and passing the error up to the caller, or by displaying a
-descriptive message to the user and canceling the operation.
-
-   Some error values do not indicate a system error or an error in the
-operation, but the result of an operation that failed properly.
-
-   GnuPG components, including Libgcrypt, use an extra library named
-libgpg-error to provide a common error handling scheme.  For more
-information on libgpg-error, see the according manual.
-
-* Menu:
-
-* Error Values::                The error value and what it means.
-* Error Sources::               A list of important error sources.
-* Error Codes::                 A list of important error codes.
-* Error Strings::               How to get a descriptive string from a value.
-
-\1f
-File: gcrypt.info,  Node: Error Values,  Next: Error Sources,  Up: Error Handling
-
-3.2.1 Error Values
-------------------
-
- -- Data type: gcry_err_code_t
-     The 'gcry_err_code_t' type is an alias for the 'libgpg-error' type
-     'gpg_err_code_t'.  The error code indicates the type of an error,
-     or the reason why an operation failed.
-
-     A list of important error codes can be found in the next section.
-
- -- Data type: gcry_err_source_t
-     The 'gcry_err_source_t' type is an alias for the 'libgpg-error'
-     type 'gpg_err_source_t'.  The error source has not a precisely
-     defined meaning.  Sometimes it is the place where the error
-     happened, sometimes it is the place where an error was encoded into
-     an error value.  Usually the error source will give an indication
-     to where to look for the problem.  This is not always true, but it
-     is attempted to achieve this goal.
-
-     A list of important error sources can be found in the next section.
-
- -- Data type: gcry_error_t
-     The 'gcry_error_t' type is an alias for the 'libgpg-error' type
-     'gpg_error_t'.  An error value like this has always two components,
-     an error code and an error source.  Both together form the error
-     value.
-
-     Thus, the error value can not be directly compared against an error
-     code, but the accessor functions described below must be used.
-     However, it is guaranteed that only 0 is used to indicate success
-     ('GPG_ERR_NO_ERROR'), and that in this case all other parts of the
-     error value are set to 0, too.
-
-     Note that in Libgcrypt, the error source is used purely for
-     diagnostic purposes.  Only the error code should be checked to test
-     for a certain outcome of a function.  The manual only documents the
-     error code part of an error value.  The error source is left
-     unspecified and might be anything.
-
- -- Function: gcry_err_code_t gcry_err_code (gcry_error_t ERR)
-     The static inline function 'gcry_err_code' returns the
-     'gcry_err_code_t' component of the error value ERR.  This function
-     must be used to extract the error code from an error value in order
-     to compare it with the 'GPG_ERR_*' error code macros.
-
- -- Function: gcry_err_source_t gcry_err_source (gcry_error_t ERR)
-     The static inline function 'gcry_err_source' returns the
-     'gcry_err_source_t' component of the error value ERR.  This
-     function must be used to extract the error source from an error
-     value in order to compare it with the 'GPG_ERR_SOURCE_*' error
-     source macros.
-
- -- Function: gcry_error_t gcry_err_make (gcry_err_source_t SOURCE,
-          gcry_err_code_t CODE)
-     The static inline function 'gcry_err_make' returns the error value
-     consisting of the error source SOURCE and the error code CODE.
-
-     This function can be used in callback functions to construct an
-     error value to return it to the library.
-
- -- Function: gcry_error_t gcry_error (gcry_err_code_t CODE)
-     The static inline function 'gcry_error' returns the error value
-     consisting of the default error source and the error code CODE.
-
-     For GCRY applications, the default error source is
-     'GPG_ERR_SOURCE_USER_1'.  You can define 'GCRY_ERR_SOURCE_DEFAULT'
-     before including 'gcrypt.h' to change this default.
-
-     This function can be used in callback functions to construct an
-     error value to return it to the library.
-
-   The 'libgpg-error' library provides error codes for all system error
-numbers it knows about.  If ERR is an unknown error number, the error
-code 'GPG_ERR_UNKNOWN_ERRNO' is used.  The following functions can be
-used to construct error values from system errno numbers.
-
- -- Function: gcry_error_t gcry_err_make_from_errno
-          (gcry_err_source_t SOURCE, int ERR)
-     The function 'gcry_err_make_from_errno' is like 'gcry_err_make',
-     but it takes a system error like 'errno' instead of a
-     'gcry_err_code_t' error code.
-
- -- Function: gcry_error_t gcry_error_from_errno (int ERR)
-     The function 'gcry_error_from_errno' is like 'gcry_error', but it
-     takes a system error like 'errno' instead of a 'gcry_err_code_t'
-     error code.
-
-   Sometimes you might want to map system error numbers to error codes
-directly, or map an error code representing a system error back to the
-system error number.  The following functions can be used to do that.
-
- -- Function: gcry_err_code_t gcry_err_code_from_errno (int ERR)
-     The function 'gcry_err_code_from_errno' returns the error code for
-     the system error ERR.  If ERR is not a known system error, the
-     function returns 'GPG_ERR_UNKNOWN_ERRNO'.
-
- -- Function: int gcry_err_code_to_errno (gcry_err_code_t ERR)
-     The function 'gcry_err_code_to_errno' returns the system error for
-     the error code ERR.  If ERR is not an error code representing a
-     system error, or if this system error is not defined on this
-     system, the function returns '0'.
-
-\1f
-File: gcrypt.info,  Node: Error Sources,  Next: Error Codes,  Prev: Error Values,  Up: Error Handling
-
-3.2.2 Error Sources
--------------------
-
-The library 'libgpg-error' defines an error source for every component
-of the GnuPG system.  The error source part of an error value is not
-well defined.  As such it is mainly useful to improve the diagnostic
-error message for the user.
-
-   If the error code part of an error value is '0', the whole error
-value will be '0'.  In this case the error source part is of course
-'GPG_ERR_SOURCE_UNKNOWN'.
-
-   The list of error sources that might occur in applications using
-Libgcrypt is:
-
-'GPG_ERR_SOURCE_UNKNOWN'
-     The error source is not known.  The value of this error source is
-     '0'.
-
-'GPG_ERR_SOURCE_GPGME'
-     The error source is GPGME itself.
-
-'GPG_ERR_SOURCE_GPG'
-     The error source is GnuPG, which is the crypto engine used for the
-     OpenPGP protocol.
-
-'GPG_ERR_SOURCE_GPGSM'
-     The error source is GPGSM, which is the crypto engine used for the
-     OpenPGP protocol.
-
-'GPG_ERR_SOURCE_GCRYPT'
-     The error source is 'libgcrypt', which is used by crypto engines to
-     perform cryptographic operations.
-
-'GPG_ERR_SOURCE_GPGAGENT'
-     The error source is 'gpg-agent', which is used by crypto engines to
-     perform operations with the secret key.
-
-'GPG_ERR_SOURCE_PINENTRY'
-     The error source is 'pinentry', which is used by 'gpg-agent' to
-     query the passphrase to unlock a secret key.
-
-'GPG_ERR_SOURCE_SCD'
-     The error source is the SmartCard Daemon, which is used by
-     'gpg-agent' to delegate operations with the secret key to a
-     SmartCard.
-
-'GPG_ERR_SOURCE_KEYBOX'
-     The error source is 'libkbx', a library used by the crypto engines
-     to manage local keyrings.
-
-'GPG_ERR_SOURCE_USER_1'
-'GPG_ERR_SOURCE_USER_2'
-'GPG_ERR_SOURCE_USER_3'
-'GPG_ERR_SOURCE_USER_4'
-     These error sources are not used by any GnuPG component and can be
-     used by other software.  For example, applications using Libgcrypt
-     can use them to mark error values coming from callback handlers.
-     Thus 'GPG_ERR_SOURCE_USER_1' is the default for errors created with
-     'gcry_error' and 'gcry_error_from_errno', unless you define
-     'GCRY_ERR_SOURCE_DEFAULT' before including 'gcrypt.h'.
-
-\1f
-File: gcrypt.info,  Node: Error Codes,  Next: Error Strings,  Prev: Error Sources,  Up: Error Handling
-
-3.2.3 Error Codes
------------------
-
-The library 'libgpg-error' defines many error values.  The following
-list includes the most important error codes.
-
-'GPG_ERR_EOF'
-     This value indicates the end of a list, buffer or file.
-
-'GPG_ERR_NO_ERROR'
-     This value indicates success.  The value of this error code is '0'.
-     Also, it is guaranteed that an error value made from the error code
-     '0' will be '0' itself (as a whole).  This means that the error
-     source information is lost for this error code, however, as this
-     error code indicates that no error occurred, this is generally not
-     a problem.
-
-'GPG_ERR_GENERAL'
-     This value means that something went wrong, but either there is not
-     enough information about the problem to return a more useful error
-     value, or there is no separate error value for this type of
-     problem.
-
-'GPG_ERR_ENOMEM'
-     This value means that an out-of-memory condition occurred.
-
-'GPG_ERR_E...'
-     System errors are mapped to GPG_ERR_EFOO where FOO is the symbol
-     for the system error.
-
-'GPG_ERR_INV_VALUE'
-     This value means that some user provided data was out of range.
-
-'GPG_ERR_UNUSABLE_PUBKEY'
-     This value means that some recipients for a message were invalid.
-
-'GPG_ERR_UNUSABLE_SECKEY'
-     This value means that some signers were invalid.
-
-'GPG_ERR_NO_DATA'
-     This value means that data was expected where no data was found.
-
-'GPG_ERR_CONFLICT'
-     This value means that a conflict of some sort occurred.
-
-'GPG_ERR_NOT_IMPLEMENTED'
-     This value indicates that the specific function (or operation) is
-     not implemented.  This error should never happen.  It can only
-     occur if you use certain values or configuration options which do
-     not work, but for which we think that they should work at some
-     later time.
-
-'GPG_ERR_DECRYPT_FAILED'
-     This value indicates that a decryption operation was unsuccessful.
-
-'GPG_ERR_WRONG_KEY_USAGE'
-     This value indicates that a key is not used appropriately.
-
-'GPG_ERR_NO_SECKEY'
-     This value indicates that no secret key for the user ID is
-     available.
-
-'GPG_ERR_UNSUPPORTED_ALGORITHM'
-     This value means a verification failed because the cryptographic
-     algorithm is not supported by the crypto backend.
-
-'GPG_ERR_BAD_SIGNATURE'
-     This value means a verification failed because the signature is
-     bad.
-
-'GPG_ERR_NO_PUBKEY'
-     This value means a verification failed because the public key is
-     not available.
-
-'GPG_ERR_NOT_OPERATIONAL'
-     This value means that the library is not yet in state which allows
-     to use this function.  This error code is in particular returned if
-     Libgcrypt is operated in FIPS mode and the internal state of the
-     library does not yet or not anymore allow the use of a service.
-
-     This error code is only available with newer libgpg-error versions,
-     thus you might see "invalid error code" when passing this to
-     'gpg_strerror'.  The numeric value of this error code is 176.
-
-'GPG_ERR_USER_1'
-'GPG_ERR_USER_2'
-'...'
-'GPG_ERR_USER_16'
-     These error codes are not used by any GnuPG component and can be
-     freely used by other software.  Applications using Libgcrypt might
-     use them to mark specific errors returned by callback handlers if
-     no suitable error codes (including the system errors) for these
-     errors exist already.
-
-\1f
-File: gcrypt.info,  Node: Error Strings,  Prev: Error Codes,  Up: Error Handling
-
-3.2.4 Error Strings
--------------------
-
- -- Function: const char * gcry_strerror (gcry_error_t ERR)
-     The function 'gcry_strerror' returns a pointer to a statically
-     allocated string containing a description of the error code
-     contained in the error value ERR.  This string can be used to
-     output a diagnostic message to the user.
-
- -- Function: const char * gcry_strsource (gcry_error_t ERR)
-     The function 'gcry_strsource' returns a pointer to a statically
-     allocated string containing a description of the error source
-     contained in the error value ERR.  This string can be used to
-     output a diagnostic message to the user.
-
-   The following example illustrates the use of the functions described
-above:
-
-     {
-       gcry_cipher_hd_t handle;
-       gcry_error_t err = 0;
-
-       err = gcry_cipher_open (&handle, GCRY_CIPHER_AES,
-                               GCRY_CIPHER_MODE_CBC, 0);
-       if (err)
-         {
-           fprintf (stderr, "Failure: %s/%s\n",
-                    gcry_strsource (err),
-                    gcry_strerror (err));
-         }
-     }
-
-\1f
-File: gcrypt.info,  Node: Handler Functions,  Next: Symmetric cryptography,  Prev: Generalities,  Up: Top
-
-4 Handler Functions
-*******************
-
-Libgcrypt makes it possible to install so called 'handler functions',
-which get called by Libgcrypt in case of certain events.
-
-* Menu:
-
-* Progress handler::            Using a progress handler function.
-* Allocation handler::          Using special memory allocation functions.
-* Error handler::               Using error handler functions.
-* Logging handler::             Using a special logging function.
-
-\1f
-File: gcrypt.info,  Node: Progress handler,  Next: Allocation handler,  Up: Handler Functions
-
-4.1 Progress handler
-====================
-
-It is often useful to retrieve some feedback while long running
-operations are performed.
-
- -- Data type: gcry_handler_progress_t
-     Progress handler functions have to be of the type
-     'gcry_handler_progress_t', which is defined as:
-
-     'void (*gcry_handler_progress_t) (void *, const char *, int, int,
-     int)'
-
-   The following function may be used to register a handler function for
-this purpose.
-
- -- Function: void gcry_set_progress_handler (gcry_handler_progress_t
-          CB, void *CB_DATA)
-
-     This function installs CB as the 'Progress handler' function.  It
-     may be used only during initialization.  CB must be defined as
-     follows:
-
-          void
-          my_progress_handler (void *CB_DATA, const char *WHAT,
-                               int PRINTCHAR, int CURRENT, int TOTAL)
-          {
-            /* Do something.  */
-          }
-
-     A description of the arguments of the progress handler function
-     follows.
-
-     CB_DATA
-          The argument provided in the call to
-          'gcry_set_progress_handler'.
-     WHAT
-          A string identifying the type of the progress output.  The
-          following values for WHAT are defined:
-
-          'need_entropy'
-               Not enough entropy is available.  TOTAL holds the number
-               of required bytes.
-
-          'wait_dev_random'
-               Waiting to re-open a random device.  TOTAL gives the
-               number of seconds until the next try.
-
-          'primegen'
-               Values for PRINTCHAR:
-               '\n'
-                    Prime generated.
-               '!'
-                    Need to refresh the pool of prime numbers.
-               '<, >'
-                    Number of bits adjusted.
-               '^'
-                    Searching for a generator.
-               '.'
-                    Fermat test on 10 candidates failed.
-               ':'
-                    Restart with a new random value.
-               '+'
-                    Rabin Miller test passed.
-
-\1f
-File: gcrypt.info,  Node: Allocation handler,  Next: Error handler,  Prev: Progress handler,  Up: Handler Functions
-
-4.2 Allocation handler
-======================
-
-It is possible to make Libgcrypt use special memory allocation functions
-instead of the built-in ones.
-
-   Memory allocation functions are of the following types:
- -- Data type: gcry_handler_alloc_t
-     This type is defined as: 'void *(*gcry_handler_alloc_t) (size_t
-     n)'.
- -- Data type: gcry_handler_secure_check_t
-     This type is defined as: 'int *(*gcry_handler_secure_check_t)
-     (const void *)'.
- -- Data type: gcry_handler_realloc_t
-     This type is defined as: 'void *(*gcry_handler_realloc_t) (void *p,
-     size_t n)'.
- -- Data type: gcry_handler_free_t
-     This type is defined as: 'void *(*gcry_handler_free_t) (void *)'.
-
-   Special memory allocation functions can be installed with the
-following function:
-
- -- Function: void gcry_set_allocation_handler (gcry_handler_alloc_t
-          FUNC_ALLOC, gcry_handler_alloc_t FUNC_ALLOC_SECURE,
-          gcry_handler_secure_check_t FUNC_SECURE_CHECK,
-          gcry_handler_realloc_t FUNC_REALLOC, gcry_handler_free_t
-          FUNC_FREE)
-     Install the provided functions and use them instead of the built-in
-     functions for doing memory allocation.  Using this function is in
-     general not recommended because the standard Libgcrypt allocation
-     functions are guaranteed to zeroize memory if needed.
-
-     This function may be used only during initialization and may not be
-     used in fips mode.
-
-\1f
-File: gcrypt.info,  Node: Error handler,  Next: Logging handler,  Prev: Allocation handler,  Up: Handler Functions
-
-4.3 Error handler
-=================
-
-The following functions may be used to register handler functions that
-are called by Libgcrypt in case certain error conditions occur.  They
-may and should be registered prior to calling 'gcry_check_version'.
-
- -- Data type: gcry_handler_no_mem_t
-     This type is defined as: 'int (*gcry_handler_no_mem_t) (void *,
-     size_t, unsigned int)'
- -- Function: void gcry_set_outofcore_handler (gcry_handler_no_mem_t
-          FUNC_NO_MEM, void *CB_DATA)
-     This function registers FUNC_NO_MEM as 'out-of-core handler', which
-     means that it will be called in the case of not having enough
-     memory available.  The handler is called with 3 arguments: The
-     first one is the pointer CB_DATA as set with this function, the
-     second is the requested memory size and the last being a flag.  If
-     bit 0 of the flag is set, secure memory has been requested.  The
-     handler should either return true to indicate that Libgcrypt should
-     try again allocating memory or return false to let Libgcrypt use
-     its default fatal error handler.
-
- -- Data type: gcry_handler_error_t
-     This type is defined as: 'void (*gcry_handler_error_t) (void *,
-     int, const char *)'
-
- -- Function: void gcry_set_fatalerror_handler (gcry_handler_error_t
-          FUNC_ERROR, void *CB_DATA)
-     This function registers FUNC_ERROR as 'error handler', which means
-     that it will be called in error conditions.
-
-\1f
-File: gcrypt.info,  Node: Logging handler,  Prev: Error handler,  Up: Handler Functions
-
-4.4 Logging handler
-===================
-
- -- Data type: gcry_handler_log_t
-     This type is defined as: 'void (*gcry_handler_log_t) (void *, int,
-     const char *, va_list)'
-
- -- Function: void gcry_set_log_handler (gcry_handler_log_t FUNC_LOG,
-          void *CB_DATA)
-     This function registers FUNC_LOG as 'logging handler', which means
-     that it will be called in case Libgcrypt wants to log a message.
-     This function may and should be used prior to calling
-     'gcry_check_version'.
-
-\1f
-File: gcrypt.info,  Node: Symmetric cryptography,  Next: Public Key cryptography,  Prev: Handler Functions,  Up: Top
-
-5 Symmetric cryptography
-************************
-
-The cipher functions are used for symmetrical cryptography, i.e.
-cryptography using a shared key.  The programming model follows an
-open/process/close paradigm and is in that similar to other building
-blocks provided by Libgcrypt.
-
-* Menu:
-
-* Available ciphers::           List of ciphers supported by the library.
-* Available cipher modes::      List of cipher modes supported by the library.
-* Working with cipher handles::  How to perform operations related to cipher handles.
-* General cipher functions::    General cipher functions independent of cipher handles.
-
-\1f
-File: gcrypt.info,  Node: Available ciphers,  Next: Available cipher modes,  Up: Symmetric cryptography
-
-5.1 Available ciphers
-=====================
-
-'GCRY_CIPHER_NONE'
-     This is not a real algorithm but used by some functions as error
-     return.  The value always evaluates to false.
-
-'GCRY_CIPHER_IDEA'
-     This is the IDEA algorithm.
-
-'GCRY_CIPHER_3DES'
-     Triple-DES with 3 Keys as EDE. The key size of this algorithm is
-     168 but you have to pass 192 bits because the most significant bits
-     of each byte are ignored.
-
-'GCRY_CIPHER_CAST5'
-     CAST128-5 block cipher algorithm.  The key size is 128 bits.
-
-'GCRY_CIPHER_BLOWFISH'
-     The blowfish algorithm.  The current implementation allows only for
-     a key size of 128 bits.
-
-'GCRY_CIPHER_SAFER_SK128'
-     Reserved and not currently implemented.
-
-'GCRY_CIPHER_DES_SK'
-     Reserved and not currently implemented.
-
-'GCRY_CIPHER_AES'
-'GCRY_CIPHER_AES128'
-'GCRY_CIPHER_RIJNDAEL'
-'GCRY_CIPHER_RIJNDAEL128'
-     AES (Rijndael) with a 128 bit key.
-
-'GCRY_CIPHER_AES192'
-'GCRY_CIPHER_RIJNDAEL192'
-     AES (Rijndael) with a 192 bit key.
-
-'GCRY_CIPHER_AES256'
-'GCRY_CIPHER_RIJNDAEL256'
-     AES (Rijndael) with a 256 bit key.
-
-'GCRY_CIPHER_TWOFISH'
-     The Twofish algorithm with a 256 bit key.
-
-'GCRY_CIPHER_TWOFISH128'
-     The Twofish algorithm with a 128 bit key.
-
-'GCRY_CIPHER_ARCFOUR'
-     An algorithm which is 100% compatible with RSA Inc.'s RC4
-     algorithm.  Note that this is a stream cipher and must be used very
-     carefully to avoid a couple of weaknesses.
-
-'GCRY_CIPHER_DES'
-     Standard DES with a 56 bit key.  You need to pass 64 bit but the
-     high bits of each byte are ignored.  Note, that this is a weak
-     algorithm which can be broken in reasonable time using a brute
-     force approach.
-
-'GCRY_CIPHER_SERPENT128'
-'GCRY_CIPHER_SERPENT192'
-'GCRY_CIPHER_SERPENT256'
-     The Serpent cipher from the AES contest.
-
-'GCRY_CIPHER_RFC2268_40'
-'GCRY_CIPHER_RFC2268_128'
-     Ron's Cipher 2 in the 40 and 128 bit variants.
-
-'GCRY_CIPHER_SEED'
-     A 128 bit cipher as described by RFC4269.
-
-'GCRY_CIPHER_CAMELLIA128'
-'GCRY_CIPHER_CAMELLIA192'
-'GCRY_CIPHER_CAMELLIA256'
-     The Camellia cipher by NTT. See
-     <http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html>.
-
-'GCRY_CIPHER_SALSA20'
-     This is the Salsa20 stream cipher.
-
-'GCRY_CIPHER_SALSA20R12'
-     This is the Salsa20/12 - reduced round version of Salsa20 stream
-     cipher.
-
-'GCRY_CIPHER_GOST28147'
-     The GOST 28147-89 cipher, defined in the respective GOST standard.
-     Translation of this GOST into English is provided in the RFC-5830.
-
-'GCRY_CIPHER_CHACHA20'
-     This is the ChaCha20 stream cipher.
-
-\1f
-File: gcrypt.info,  Node: Available cipher modes,  Next: Working with cipher handles,  Prev: Available ciphers,  Up: Symmetric cryptography
-
-5.2 Available cipher modes
-==========================
-
-'GCRY_CIPHER_MODE_NONE'
-     No mode specified.  This should not be used.  The only exception is
-     that if Libgcrypt is not used in FIPS mode and if any debug flag
-     has been set, this mode may be used to bypass the actual
-     encryption.
-
-'GCRY_CIPHER_MODE_ECB'
-     Electronic Codebook mode.
-
-'GCRY_CIPHER_MODE_CFB'
-'GCRY_CIPHER_MODE_CFB8'
-     Cipher Feedback mode.  For GCRY_CIPHER_MODE_CFB the shift size
-     equals the block size of the cipher (e.g.  for AES it is CFB-128).
-     For GCRY_CIPHER_MODE_CFB8 the shift size is 8 bit but that variant
-     is not yet available.
-
-'GCRY_CIPHER_MODE_CBC'
-     Cipher Block Chaining mode.
-
-'GCRY_CIPHER_MODE_STREAM'
-     Stream mode, only to be used with stream cipher algorithms.
-
-'GCRY_CIPHER_MODE_OFB'
-     Output Feedback mode.
-
-'GCRY_CIPHER_MODE_CTR'
-     Counter mode.
-
-'GCRY_CIPHER_MODE_AESWRAP'
-     This mode is used to implement the AES-Wrap algorithm according to
-     RFC-3394.  It may be used with any 128 bit block length algorithm,
-     however the specs require one of the 3 AES algorithms.  These
-     special conditions apply: If 'gcry_cipher_setiv' has not been used
-     the standard IV is used; if it has been used the lower 64 bit of
-     the IV are used as the Alternative Initial Value.  On encryption
-     the provided output buffer must be 64 bit (8 byte) larger than the
-     input buffer; in-place encryption is still allowed.  On decryption
-     the output buffer may be specified 64 bit (8 byte) shorter than
-     then input buffer.  As per specs the input length must be at least
-     128 bits and the length must be a multiple of 64 bits.
-
-'GCRY_CIPHER_MODE_CCM'
-     Counter with CBC-MAC mode is an Authenticated Encryption with
-     Associated Data (AEAD) block cipher mode, which is specified in
-     'NIST Special Publication 800-38C' and RFC 3610.
-
-'GCRY_CIPHER_MODE_GCM'
-     Galois/Counter Mode (GCM) is an Authenticated Encryption with
-     Associated Data (AEAD) block cipher mode, which is specified in
-     'NIST Special Publication 800-38D'.
-
-'GCRY_CIPHER_MODE_POLY1305'
-     This mode implements the Poly1305 Authenticated Encryption with
-     Associated Data (AEAD) mode according to RFC-7539.  This mode can
-     be used with ChaCha20 stream cipher.
-
-'GCRY_CIPHER_MODE_OCB'
-     OCB is an Authenticated Encryption with Associated Data (AEAD)
-     block cipher mode, which is specified in RFC-7253.  Supported tag
-     lengths are 128, 96, and 64 bit with the default being 128 bit.  To
-     switch to a different tag length 'gcry_cipher_ctl' using the
-     command 'GCRYCTL_SET_TAGLEN' and the address of an 'int' variable
-     set to 12 (for 96 bit) or 8 (for 64 bit) provided for the 'buffer'
-     argument and 'sizeof(int)' for 'buflen'.
-
-     Note that the use of 'gcry_cipher_final' is required.
-
-'GCRY_CIPHER_MODE_XTS'
-     XEX-based tweaked-codebook mode with ciphertext stealing (XTS) mode
-     is used to implement the AES-XTS as specified in IEEE 1619 Standard
-     Architecture for Encrypted Shared Storage Media and NIST SP800-38E.
-
-     The XTS mode requires doubling key-length, for example, using
-     512-bit key with AES-256 ('GCRY_CIPHER_AES256').  The 128-bit tweak
-     value is feed to XTS mode as little-endian byte array using
-     'gcry_cipher_setiv' function.  When encrypting or decrypting,
-     full-sized data unit buffers needs to be passed to
-     'gcry_cipher_encrypt' or 'gcry_cipher_decrypt'.  The tweak value is
-     automatically incremented after each call of 'gcry_cipher_encrypt'
-     and 'gcry_cipher_decrypt'.  Auto-increment allows avoiding need of
-     setting IV between processing of sequential data units.
-
-\1f
-File: gcrypt.info,  Node: Working with cipher handles,  Next: General cipher functions,  Prev: Available cipher modes,  Up: Symmetric cryptography
-
-5.3 Working with cipher handles
-===============================
-
-To use a cipher algorithm, you must first allocate an according handle.
-This is to be done using the open function:
-
- -- Function: gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *HD, int
-          ALGO, int MODE, unsigned int FLAGS)
-
-     This function creates the context handle required for most of the
-     other cipher functions and returns a handle to it in 'hd'.  In case
-     of an error, an according error code is returned.
-
-     The ID of algorithm to use must be specified via ALGO.  See *note
-     Available ciphers::, for a list of supported ciphers and the
-     according constants.
-
-     Besides using the constants directly, the function
-     'gcry_cipher_map_name' may be used to convert the textual name of
-     an algorithm into the according numeric ID.
-
-     The cipher mode to use must be specified via MODE.  See *note
-     Available cipher modes::, for a list of supported cipher modes and
-     the according constants.  Note that some modes are incompatible
-     with some algorithms - in particular, stream mode
-     ('GCRY_CIPHER_MODE_STREAM') only works with stream ciphers.
-     Poly1305 AEAD mode ('GCRY_CIPHER_MODE_POLY1305') only works with
-     ChaCha20 stream cipher.  The block cipher modes
-     ('GCRY_CIPHER_MODE_ECB', 'GCRY_CIPHER_MODE_CBC',
-     'GCRY_CIPHER_MODE_CFB', 'GCRY_CIPHER_MODE_OFB' and
-     'GCRY_CIPHER_MODE_CTR') will work with any block cipher algorithm.
-     GCM mode ('GCRY_CIPHER_MODE_CCM'), CCM mode
-     ('GCRY_CIPHER_MODE_GCM'), OCB mode ('GCRY_CIPHER_MODE_OCB'), and
-     XTS mode ('GCRY_CIPHER_MODE_XTS') will only work with block cipher
-     algorithms which have the block size of 16 bytes.
-
-     The third argument FLAGS can either be passed as '0' or as the
-     bit-wise OR of the following constants.
-
-     'GCRY_CIPHER_SECURE'
-          Make sure that all operations are allocated in secure memory.
-          This is useful when the key material is highly confidential.
-     'GCRY_CIPHER_ENABLE_SYNC'
-          This flag enables the CFB sync mode, which is a special
-          feature of Libgcrypt's CFB mode implementation to allow for
-          OpenPGP's CFB variant.  See 'gcry_cipher_sync'.
-     'GCRY_CIPHER_CBC_CTS'
-          Enable cipher text stealing (CTS) for the CBC mode.  Cannot be
-          used simultaneous as GCRY_CIPHER_CBC_MAC. CTS mode makes it
-          possible to transform data of almost arbitrary size (only
-          limitation is that it must be greater than the algorithm's
-          block size).
-     'GCRY_CIPHER_CBC_MAC'
-          Compute CBC-MAC keyed checksums.  This is the same as CBC
-          mode, but only output the last block.  Cannot be used
-          simultaneous as GCRY_CIPHER_CBC_CTS.
-
-   Use the following function to release an existing handle:
-
- -- Function: void gcry_cipher_close (gcry_cipher_hd_t H)
-
-     This function releases the context created by 'gcry_cipher_open'.
-     It also zeroises all sensitive information associated with this
-     cipher handle.
-
-   In order to use a handle for performing cryptographic operations, a
-'key' has to be set first:
-
- -- Function: gcry_error_t gcry_cipher_setkey (gcry_cipher_hd_t H, const
-          void *K, size_t L)
-
-     Set the key K used for encryption or decryption in the context
-     denoted by the handle H.  The length L (in bytes) of the key K must
-     match the required length of the algorithm set for this context or
-     be in the allowed range for algorithms with variable key size.  The
-     function checks this and returns an error if there is a problem.  A
-     caller should always check for an error.
-
-   Most crypto modes requires an initialization vector (IV), which
-usually is a non-secret random string acting as a kind of salt value.
-The CTR mode requires a counter, which is also similar to a salt value.
-To set the IV or CTR, use these functions:
-
- -- Function: gcry_error_t gcry_cipher_setiv (gcry_cipher_hd_t H, const
-          void *K, size_t L)
-
-     Set the initialization vector used for encryption or decryption.
-     The vector is passed as the buffer K of length L bytes and copied
-     to internal data structures.  The function checks that the IV
-     matches the requirement of the selected algorithm and mode.
-
-     This function is also used by AEAD modes and with Salsa20 and
-     ChaCha20 stream ciphers to set or update the required nonce.  In
-     these cases it needs to be called after setting the key.
-
- -- Function: gcry_error_t gcry_cipher_setctr (gcry_cipher_hd_t H, const
-          void *C, size_t L)
-
-     Set the counter vector used for encryption or decryption.  The
-     counter is passed as the buffer C of length L bytes and copied to
-     internal data structures.  The function checks that the counter
-     matches the requirement of the selected algorithm (i.e., it must be
-     the same size as the block size).
-
- -- Function: gcry_error_t gcry_cipher_reset (gcry_cipher_hd_t H)
-
-     Set the given handle's context back to the state it had after the
-     last call to gcry_cipher_setkey and clear the initialization
-     vector.
-
-     Note that gcry_cipher_reset is implemented as a macro.
-
-   Authenticated Encryption with Associated Data (AEAD) block cipher
-modes require the handling of the authentication tag and the additional
-authenticated data, which can be done by using the following functions:
-
- -- Function: gcry_error_t gcry_cipher_authenticate (gcry_cipher_hd_t H,
-          const void *ABUF, size_t ABUFLEN)
-
-     Process the buffer ABUF of length ABUFLEN as the additional
-     authenticated data (AAD) for AEAD cipher modes.
-
- -- Function: gcry_error_t gcry_cipher_gettag (gcry_cipher_hd_t H,
-          void *TAG, size_t TAGLEN)
-
-     This function is used to read the authentication tag after
-     encryption.  The function finalizes and outputs the authentication
-     tag to the buffer TAG of length TAGLEN bytes.
-
-     Depending on the used mode certain restrictions for TAGLEN are
-     enforced: For GCM TAGLEN must be at least 16 or one of the allowed
-     truncated lengths (4, 8, 12, 13, 14, or 15).
-
- -- Function: gcry_error_t gcry_cipher_checktag (gcry_cipher_hd_t H,
-          const void *TAG, size_t TAGLEN)
-
-     Check the authentication tag after decryption.  The authentication
-     tag is passed as the buffer TAG of length TAGLEN bytes and compared
-     to internal authentication tag computed during decryption.  Error
-     code 'GPG_ERR_CHECKSUM' is returned if the authentication tag in
-     the buffer TAG does not match the authentication tag calculated
-     during decryption.
-
-     Depending on the used mode certain restrictions for TAGLEN are
-     enforced: For GCM TAGLEN must either be 16 or one of the allowed
-     truncated lengths (4, 8, 12, 13, 14, or 15).
-
-   The actual encryption and decryption is done by using one of the
-following functions.  They may be used as often as required to process
-all the data.
-
- -- Function: gcry_error_t gcry_cipher_encrypt (gcry_cipher_hd_t H,
-          unsigned char *out, size_t OUTSIZE, const unsigned char *IN,
-          size_t INLEN)
-
-     'gcry_cipher_encrypt' is used to encrypt the data.  This function
-     can either work in place or with two buffers.  It uses the cipher
-     context already setup and described by the handle H.  There are 2
-     ways to use the function: If IN is passed as 'NULL' and INLEN is
-     '0', in-place encryption of the data in OUT of length OUTSIZE takes
-     place.  With IN being not 'NULL', INLEN bytes are encrypted to the
-     buffer OUT which must have at least a size of INLEN.  OUTSIZE must
-     be set to the allocated size of OUT, so that the function can check
-     that there is sufficient space.  Note that overlapping buffers are
-     not allowed.
-
-     Depending on the selected algorithms and encryption mode, the
-     length of the buffers must be a multiple of the block size.
-
-     Some encryption modes require that 'gcry_cipher_final' is used
-     before the final data chunk is passed to this function.
-
-     The function returns '0' on success or an error code.
-
- -- Function: gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t H,
-          unsigned char *out, size_t OUTSIZE, const unsigned char *IN,
-          size_t INLEN)
-
-     'gcry_cipher_decrypt' is used to decrypt the data.  This function
-     can either work in place or with two buffers.  It uses the cipher
-     context already setup and described by the handle H.  There are 2
-     ways to use the function: If IN is passed as 'NULL' and INLEN is
-     '0', in-place decryption of the data in OUT or length OUTSIZE takes
-     place.  With IN being not 'NULL', INLEN bytes are decrypted to the
-     buffer OUT which must have at least a size of INLEN.  OUTSIZE must
-     be set to the allocated size of OUT, so that the function can check
-     that there is sufficient space.  Note that overlapping buffers are
-     not allowed.
-
-     Depending on the selected algorithms and encryption mode, the
-     length of the buffers must be a multiple of the block size.
-
-     Some encryption modes require that 'gcry_cipher_final' is used
-     before the final data chunk is passed to this function.
-
-     The function returns '0' on success or an error code.
-
-   The OCB mode features integrated padding and must thus be told about
-the end of the input data.  This is done with:
-
- -- Function: gcry_error_t gcry_cipher_final (gcry_cipher_hd_t H)
-
-     Set a flag in the context to tell the encrypt and decrypt functions
-     that their next call will provide the last chunk of data.  Only the
-     first call to this function has an effect and only for modes which
-     support it.  Checking the error is in general not necessary.  This
-     is implemented as a macro.
-
-   OpenPGP (as defined in RFC-4880) requires a special sync operation in
-some places.  The following function is used for this:
-
- -- Function: gcry_error_t gcry_cipher_sync (gcry_cipher_hd_t H)
-
-     Perform the OpenPGP sync operation on context H.  Note that this is
-     a no-op unless the context was created with the flag
-     'GCRY_CIPHER_ENABLE_SYNC'
-
-   Some of the described functions are implemented as macros utilizing a
-catch-all control function.  This control function is rarely used
-directly but there is nothing which would inhibit it:
-
- -- Function: gcry_error_t gcry_cipher_ctl (gcry_cipher_hd_t H, int CMD,
-          void *BUFFER, size_t BUFLEN)
-
-     'gcry_cipher_ctl' controls various aspects of the cipher module and
-     specific cipher contexts.  Usually some more specialized functions
-     or macros are used for this purpose.  The semantics of the function
-     and its parameters depends on the the command CMD and the passed
-     context handle H.  Please see the comments in the source code
-     ('src/global.c') for details.
-
- -- Function: gcry_error_t gcry_cipher_info (gcry_cipher_hd_t H, int
-          WHAT, void *BUFFER, size_t *NBYTES)
-
-     'gcry_cipher_info' is used to retrieve various information about a
-     cipher context or the cipher module in general.
-
-     'GCRYCTL_GET_TAGLEN:'
-          Return the length of the tag for an AE algorithm mode.  An
-          error is returned for modes which do not support a tag.
-          BUFFER must be given as NULL. On success the result is stored
-          NBYTES.  The taglen is returned in bytes.
-
-\1f
-File: gcrypt.info,  Node: General cipher functions,  Prev: Working with cipher handles,  Up: Symmetric cryptography
-
-5.4 General cipher functions
-============================
-
-To work with the algorithms, several functions are available to map
-algorithm names to the internal identifiers, as well as ways to retrieve
-information about an algorithm or the current cipher context.
-
- -- Function: gcry_error_t gcry_cipher_algo_info (int ALGO, int WHAT,
-          void *BUFFER, size_t *NBYTES)
-
-     This function is used to retrieve information on a specific
-     algorithm.  You pass the cipher algorithm ID as ALGO and the type
-     of information requested as WHAT.  The result is either returned as
-     the return code of the function or copied to the provided BUFFER
-     whose allocated length must be available in an integer variable
-     with the address passed in NBYTES.  This variable will also receive
-     the actual used length of the buffer.
-
-     Here is a list of supported codes for WHAT:
-
-     'GCRYCTL_GET_KEYLEN:'
-          Return the length of the key.  If the algorithm supports
-          multiple key lengths, the maximum supported value is returned.
-          The length is returned as number of octets (bytes) and not as
-          number of bits in NBYTES; BUFFER must be zero.  Note that it
-          is usually better to use the convenience function
-          'gcry_cipher_get_algo_keylen'.
-
-     'GCRYCTL_GET_BLKLEN:'
-          Return the block length of the algorithm.  The length is
-          returned as a number of octets in NBYTES; BUFFER must be zero.
-          Note that it is usually better to use the convenience function
-          'gcry_cipher_get_algo_blklen'.
-
-     'GCRYCTL_TEST_ALGO:'
-          Returns '0' when the specified algorithm is available for use.
-          BUFFER and NBYTES must be zero.
-
- -- Function: size_t gcry_cipher_get_algo_keylen (ALGO)
-
-     This function returns length of the key for algorithm ALGO.  If the
-     algorithm supports multiple key lengths, the maximum supported key
-     length is returned.  On error '0' is returned.  The key length is
-     returned as number of octets.
-
-     This is a convenience functions which should be preferred over
-     'gcry_cipher_algo_info' because it allows for proper type checking.
-
- -- Function: size_t gcry_cipher_get_algo_blklen (int ALGO)
-
-     This functions returns the block-length of the algorithm ALGO
-     counted in octets.  On error '0' is returned.
-
-     This is a convenience functions which should be preferred over
-     'gcry_cipher_algo_info' because it allows for proper type checking.
-
- -- Function: const char * gcry_cipher_algo_name (int ALGO)
-
-     'gcry_cipher_algo_name' returns a string with the name of the
-     cipher algorithm ALGO.  If the algorithm is not known or another
-     error occurred, the string '"?"' is returned.  This function should
-     not be used to test for the availability of an algorithm.
-
- -- Function: int gcry_cipher_map_name (const char *NAME)
-
-     'gcry_cipher_map_name' returns the algorithm identifier for the
-     cipher algorithm described by the string NAME.  If this algorithm
-     is not available '0' is returned.
-
- -- Function: int gcry_cipher_mode_from_oid (const char *STRING)
-
-     Return the cipher mode associated with an ASN.1 object identifier.
-     The object identifier is expected to be in the IETF-style dotted
-     decimal notation.  The function returns '0' for an unknown object
-     identifier or when no mode is associated with it.
-
-\1f
-File: gcrypt.info,  Node: Public Key cryptography,  Next: Hashing,  Prev: Symmetric cryptography,  Up: Top
-
-6 Public Key cryptography
-*************************
-
-Public key cryptography, also known as asymmetric cryptography, is an
-easy way for key management and to provide digital signatures.
-Libgcrypt provides two completely different interfaces to public key
-cryptography, this chapter explains the one based on S-expressions.
-
-* Menu:
-
-* Available algorithms::        Algorithms supported by the library.
-* Used S-expressions::          Introduction into the used S-expression.
-* Cryptographic Functions::     Functions for performing the cryptographic actions.
-* General public-key related Functions::  General functions, not implementing any cryptography.
-
-\1f
-File: gcrypt.info,  Node: Available algorithms,  Next: Used S-expressions,  Up: Public Key cryptography
-
-6.1 Available algorithms
-========================
-
-Libgcrypt supports the RSA (Rivest-Shamir-Adleman) algorithms as well as
-DSA (Digital Signature Algorithm) and Elgamal.  The versatile interface
-allows to add more algorithms in the future.
-
-\1f
-File: gcrypt.info,  Node: Used S-expressions,  Next: Cryptographic Functions,  Prev: Available algorithms,  Up: Public Key cryptography
-
-6.2 Used S-expressions
-======================
-
-Libgcrypt's API for asymmetric cryptography is based on data structures
-called S-expressions (see
-<http://people.csail.mit.edu/rivest/sexp.html>) and does not work with
-contexts as most of the other building blocks of Libgcrypt do.
-
-The following information are stored in S-expressions:
-
-   * keys
-
-   * plain text data
-
-   * encrypted data
-
-   * signatures
-
-To describe how Libgcrypt expect keys, we use examples.  Note that words
-in uppercase indicate parameters whereas lowercase words are literals.
-
-   Note that all MPI (multi-precision-integers) values are expected to
-be in 'GCRYMPI_FMT_USG' format.  An easy way to create S-expressions is
-by using 'gcry_sexp_build' which allows to pass a string with
-printf-like escapes to insert MPI values.
-
-* Menu:
-
-* RSA key parameters::  Parameters used with an RSA key.
-* DSA key parameters::  Parameters used with a DSA key.
-* ECC key parameters::  Parameters used with ECC keys.
-
-\1f
-File: gcrypt.info,  Node: RSA key parameters,  Next: DSA key parameters,  Up: Used S-expressions
-
-6.2.1 RSA key parameters
-------------------------
-
-An RSA private key is described by this S-expression:
-
-     (private-key
-       (rsa
-         (n N-MPI)
-         (e E-MPI)
-         (d D-MPI)
-         (p P-MPI)
-         (q Q-MPI)
-         (u U-MPI)))
-
-An RSA public key is described by this S-expression:
-
-     (public-key
-       (rsa
-         (n N-MPI)
-         (e E-MPI)))
-
-N-MPI
-     RSA public modulus n.
-E-MPI
-     RSA public exponent e.
-D-MPI
-     RSA secret exponent d = e^{-1} \bmod (p-1)(q-1).
-P-MPI
-     RSA secret prime p.
-Q-MPI
-     RSA secret prime q with p < q.
-U-MPI
-     Multiplicative inverse u = p^{-1} \bmod q.
-
-   For signing and decryption the parameters (p, q, u) are optional but
-greatly improve the performance.  Either all of these optional
-parameters must be given or none of them.  They are mandatory for
-gcry_pk_testkey.
-
-   Note that OpenSSL uses slighly different parameters: q < p and u =
-q^{-1} \bmod p.  To use these parameters you will need to swap the
-values and recompute u.  Here is example code to do this:
-
-       if (gcry_mpi_cmp (p, q) > 0)
-         {
-           gcry_mpi_swap (p, q);
-           gcry_mpi_invm (u, p, q);
-         }
-
-\1f
-File: gcrypt.info,  Node: DSA key parameters,  Next: ECC key parameters,  Prev: RSA key parameters,  Up: Used S-expressions
-
-6.2.2 DSA key parameters
-------------------------
-
-A DSA private key is described by this S-expression:
-
-     (private-key
-       (dsa
-         (p P-MPI)
-         (q Q-MPI)
-         (g G-MPI)
-         (y Y-MPI)
-         (x X-MPI)))
-
-P-MPI
-     DSA prime p.
-Q-MPI
-     DSA group order q (which is a prime divisor of p-1).
-G-MPI
-     DSA group generator g.
-Y-MPI
-     DSA public key value y = g^x \bmod p.
-X-MPI
-     DSA secret exponent x.
-
-   The public key is similar with "private-key" replaced by "public-key"
-and no X-MPI.
-
-\1f
-File: gcrypt.info,  Node: ECC key parameters,  Prev: DSA key parameters,  Up: Used S-expressions
-
-6.2.3 ECC key parameters
-------------------------
-
-An ECC private key is described by this S-expression:
-
-     (private-key
-       (ecc
-         (p P-MPI)
-         (a A-MPI)
-         (b B-MPI)
-         (g G-POINT)
-         (n N-MPI)
-         (q Q-POINT)
-         (d D-MPI)))
-
-P-MPI
-     Prime specifying the field GF(p).
-A-MPI
-B-MPI
-     The two coefficients of the Weierstrass equation y^2 = x^3 + ax + b
-G-POINT
-     Base point g.
-N-MPI
-     Order of g
-Q-POINT
-     The point representing the public key Q = dG.
-D-MPI
-     The private key d
-
-   All point values are encoded in standard format; Libgcrypt does in
-general only support uncompressed points, thus the first byte needs to
-be '0x04'.  However "EdDSA" describes its own compression scheme which
-is used by default; the non-standard first byte '0x40' may optionally be
-used to explicit flag the use of the algorithm’s native compression
-method.
-
-   The public key is similar with "private-key" replaced by "public-key"
-and no D-MPI.
-
-   If the domain parameters are well-known, the name of this curve may
-be used.  For example
-
-     (private-key
-       (ecc
-         (curve "NIST P-192")
-         (q Q-POINT)
-         (d D-MPI)))
-
-   Note that Q-POINT is optional for a private key.  The 'curve'
-parameter may be given in any case and is used to replace missing
-parameters.
-
-Currently implemented curves are:
-'NIST P-192'
-'1.2.840.10045.3.1.1'
-'prime192v1'
-'secp192r1'
-     The NIST 192 bit curve, its OID, X9.62 and SECP aliases.
-
-'NIST P-224'
-'secp224r1'
-     The NIST 224 bit curve and its SECP alias.
-
-'NIST P-256'
-'1.2.840.10045.3.1.7'
-'prime256v1'
-'secp256r1'
-     The NIST 256 bit curve, its OID, X9.62 and SECP aliases.
-
-'NIST P-384'
-'secp384r1'
-     The NIST 384 bit curve and its SECP alias.
-
-'NIST P-521'
-'secp521r1'
-     The NIST 521 bit curve and its SECP alias.
-
-   As usual the OIDs may optionally be prefixed with the string 'OID.'
-or 'oid.'.
-
-\1f
-File: gcrypt.info,  Node: Cryptographic Functions,  Next: General public-key related Functions,  Prev: Used S-expressions,  Up: Public Key cryptography
-
-6.3 Cryptographic Functions
-===========================
-
-Some functions operating on S-expressions support 'flags' to influence
-the operation.  These flags have to be listed in a sub-S-expression
-named 'flags'.  Flag names are case-sensitive.  The following flags are
-known:
-
-'comp'
-'nocomp'
-     If supported by the algorithm and curve the 'comp' flag requests
-     that points are returned in compact (compressed) representation.
-     The 'nocomp' flag requests that points are returned with full
-     coordinates.  The default depends on the the algorithm and curve.
-     The compact representation requires a small overhead before a point
-     can be used but halves the size of a to be conveyed public key.  If
-     'comp' is used with the "EdDSA" algorithm the key generation prefix
-     the public key with a '0x40' byte.
-
-'pkcs1'
-     Use PKCS#1 block type 2 padding for encryption, block type 1
-     padding for signing.
-
-'oaep'
-     Use RSA-OAEP padding for encryption.
-
-'pss'
-     Use RSA-PSS padding for signing.
-
-'eddsa'
-     Use the EdDSA scheme signing instead of the default ECDSA
-     algorithm.  Note that the EdDSA uses a special form of the public
-     key.
-
-'rfc6979'
-     For DSA and ECDSA use a deterministic scheme for the k parameter.
-
-'no-blinding'
-     Do not use a technique called 'blinding', which is used by default
-     in order to prevent leaking of secret information.  Blinding is
-     only implemented by RSA, but it might be implemented by other
-     algorithms in the future as well, when necessary.
-
-'param'
-     For ECC key generation also return the domain parameters.  For ECC
-     signing and verification override default parameters by provided
-     domain parameters of the public or private key.
-
-'transient-key'
-     This flag is only meaningful for RSA, DSA, and ECC key generation.
-     If given the key is created using a faster and a somewhat less
-     secure random number generator.  This flag may be used for keys
-     which are only used for a short time or per-message and do not
-     require full cryptographic strength.
-
-'no-keytest'
-     This flag skips internal failsafe tests to assert that a generated
-     key is properly working.  It currently has an effect only for
-     standard ECC key generation.  It is mostly useful along with
-     transient-key to achieve fastest ECC key generation.
-
-'use-x931'
-     Force the use of the ANSI X9.31 key generation algorithm instead of
-     the default algorithm.  This flag is only meaningful for RSA key
-     generation and usually not required.  Note that this algorithm is
-     implicitly used if either 'derive-parms' is given or Libgcrypt is
-     in FIPS mode.
-
-'use-fips186'
-     Force the use of the FIPS 186 key generation algorithm instead of
-     the default algorithm.  This flag is only meaningful for DSA and
-     usually not required.  Note that this algorithm is implicitly used
-     if either 'derive-parms' is given or Libgcrypt is in FIPS mode.  As
-     of now FIPS 186-2 is implemented; after the approval of FIPS 186-3
-     the code will be changed to implement 186-3.
-
-'use-fips186-2'
-     Force the use of the FIPS 186-2 key generation algorithm instead of
-     the default algorithm.  This algorithm is slightly different from
-     FIPS 186-3 and allows only 1024 bit keys.  This flag is only
-     meaningful for DSA and only required for FIPS testing backward
-     compatibility.
-
-Now that we know the key basics, we can carry on and explain how to
-encrypt and decrypt data.  In almost all cases the data is a random
-session key which is in turn used for the actual encryption of the real
-data.  There are 2 functions to do this:
-
- -- Function: gcry_error_t gcry_pk_encrypt (gcry_sexp_t *R_CIPH,
-          gcry_sexp_t DATA, gcry_sexp_t PKEY)
-
-     Obviously a public key must be provided for encryption.  It is
-     expected as an appropriate S-expression (see above) in PKEY.  The
-     data to be encrypted can either be in the simple old format, which
-     is a very simple S-expression consisting only of one MPI, or it may
-     be a more complex S-expression which also allows to specify flags
-     for operation, like e.g.  padding rules.
-
-     If you don't want to let Libgcrypt handle the padding, you must
-     pass an appropriate MPI using this expression for DATA:
-
-          (data
-            (flags raw)
-            (value MPI))
-
-     This has the same semantics as the old style MPI only way.  MPI is
-     the actual data, already padded appropriate for your protocol.
-     Most RSA based systems however use PKCS#1 padding and so you can
-     use this S-expression for DATA:
-
-          (data
-            (flags pkcs1)
-            (value BLOCK))
-
-     Here, the "flags" list has the "pkcs1" flag which let the function
-     know that it should provide PKCS#1 block type 2 padding.  The
-     actual data to be encrypted is passed as a string of octets in
-     BLOCK.  The function checks that this data actually can be used
-     with the given key, does the padding and encrypts it.
-
-     If the function could successfully perform the encryption, the
-     return value will be 0 and a new S-expression with the encrypted
-     result is allocated and assigned to the variable at the address of
-     R_CIPH.  The caller is responsible to release this value using
-     'gcry_sexp_release'.  In case of an error, an error code is
-     returned and R_CIPH will be set to 'NULL'.
-
-     The returned S-expression has this format when used with RSA:
-
-          (enc-val
-            (rsa
-              (a A-MPI)))
-
-     Where A-MPI is an MPI with the result of the RSA operation.  When
-     using the Elgamal algorithm, the return value will have this
-     format:
-
-          (enc-val
-            (elg
-              (a A-MPI)
-              (b B-MPI)))
-
-     Where A-MPI and B-MPI are MPIs with the result of the Elgamal
-     encryption operation.
-
- -- Function: gcry_error_t gcry_pk_decrypt (gcry_sexp_t *R_PLAIN,
-          gcry_sexp_t DATA, gcry_sexp_t SKEY)
-
-     Obviously a private key must be provided for decryption.  It is
-     expected as an appropriate S-expression (see above) in SKEY.  The
-     data to be decrypted must match the format of the result as
-     returned by 'gcry_pk_encrypt', but should be enlarged with a
-     'flags' element:
-
-          (enc-val
-            (flags)
-            (elg
-              (a A-MPI)
-              (b B-MPI)))
-
-     This function does not remove padding from the data by default.  To
-     let Libgcrypt remove padding, give a hint in 'flags' telling which
-     padding method was used when encrypting:
-
-          (flags PADDING-METHOD)
-
-     Currently PADDING-METHOD is either 'pkcs1' for PKCS#1 block type 2
-     padding, or 'oaep' for RSA-OAEP padding.
-
-     The function returns 0 on success or an error code.  The variable
-     at the address of R_PLAIN will be set to NULL on error or receive
-     the decrypted value on success.  The format of R_PLAIN is a simple
-     S-expression part (i.e.  not a valid one) with just one MPI if
-     there was no 'flags' element in DATA; if at least an empty 'flags'
-     is passed in DATA, the format is:
-
-          (value PLAINTEXT)
-
-   Another operation commonly performed using public key cryptography is
-signing data.  In some sense this is even more important than encryption
-because digital signatures are an important instrument for key
-management.  Libgcrypt supports digital signatures using 2 functions,
-similar to the encryption functions:
-
- -- Function: gcry_error_t gcry_pk_sign (gcry_sexp_t *R_SIG,
-          gcry_sexp_t DATA, gcry_sexp_t SKEY)
-
-     This function creates a digital signature for DATA using the
-     private key SKEY and place it into the variable at the address of
-     R_SIG.  DATA may either be the simple old style S-expression with
-     just one MPI or a modern and more versatile S-expression which
-     allows to let Libgcrypt handle padding:
-
-           (data
-            (flags pkcs1)
-            (hash HASH-ALGO BLOCK))
-
-     This example requests to sign the data in BLOCK after applying
-     PKCS#1 block type 1 style padding.  HASH-ALGO is a string with the
-     hash algorithm to be encoded into the signature, this may be any
-     hash algorithm name as supported by Libgcrypt.  Most likely, this
-     will be "sha256" or "sha1".  It is obvious that the length of BLOCK
-     must match the size of that message digests; the function checks
-     that this and other constraints are valid.
-
-     If PKCS#1 padding is not required (because the caller does already
-     provide a padded value), either the old format or better the
-     following format should be used:
-
-          (data
-            (flags raw)
-            (value MPI))
-
-     Here, the data to be signed is directly given as an MPI.
-
-     For DSA the input data is expected in this format:
-
-          (data
-            (flags raw)
-            (value MPI))
-
-     Here, the data to be signed is directly given as an MPI.  It is
-     expect that this MPI is the the hash value.  For the standard DSA
-     using a MPI is not a problem in regard to leading zeroes because
-     the hash value is directly used as an MPI. For better standard
-     conformance it would be better to explicit use a memory string
-     (like with pkcs1) but that is currently not supported.  However,
-     for deterministic DSA as specified in RFC6979 this can't be used.
-     Instead the following input is expected.
-
-          (data
-            (flags rfc6979)
-            (hash HASH-ALGO BLOCK))
-
-     Note that the provided hash-algo is used for the internal HMAC; it
-     should match the hash-algo used to create BLOCK.
-
-     The signature is returned as a newly allocated S-expression in
-     R_SIG using this format for RSA:
-
-          (sig-val
-            (rsa
-              (s S-MPI)))
-
-     Where S-MPI is the result of the RSA sign operation.  For DSA the
-     S-expression returned is:
-
-          (sig-val
-            (dsa
-              (r R-MPI)
-              (s S-MPI)))
-
-     Where R-MPI and S-MPI are the result of the DSA sign operation.
-
-     For Elgamal signing (which is slow, yields large numbers, hard to
-     use correctly and probably is not as secure as the other
-     algorithms), the same format is used with "elg" replacing "dsa";
-     for ECDSA signing, the same format is used with "ecdsa" replacing
-     "dsa".
-
-     For the EdDSA algorithm (cf.  Ed25515) the required input
-     parameters are:
-
-          (data
-            (flags eddsa)
-            (hash-algo sha512)
-            (value MESSAGE))
-
-     Note that the MESSAGE may be of any length; hashing is part of the
-     algorithm.  Using a large data block for MESSAGE is not suggested;
-     in that case the used protocol should better require that a hash of
-     the message is used as input to the EdDSA algorithm.
-
-The operation most commonly used is definitely the verification of a
-signature.  Libgcrypt provides this function:
-
- -- Function: gcry_error_t gcry_pk_verify (gcry_sexp_t SIG,
-          gcry_sexp_t DATA, gcry_sexp_t PKEY)
-
-     This is used to check whether the signature SIG matches the DATA.
-     The public key PKEY must be provided to perform this verification.
-     This function is similar in its parameters to 'gcry_pk_sign' with
-     the exceptions that the public key is used instead of the private
-     key and that no signature is created but a signature, in a format
-     as created by 'gcry_pk_sign', is passed to the function in SIG.
-
-     The result is 0 for success (i.e.  the data matches the signature),
-     or an error code where the most relevant code is
-     'GCRY_ERR_BAD_SIGNATURE' to indicate that the signature does not
-     match the provided data.
-
-\1f
-File: gcrypt.info,  Node: General public-key related Functions,  Prev: Cryptographic Functions,  Up: Public Key cryptography
-
-6.4 General public-key related Functions
-========================================
-
-A couple of utility functions are available to retrieve the length of
-the key, map algorithm identifiers and perform sanity checks:
-
- -- Function: const char * gcry_pk_algo_name (int ALGO)
-
-     Map the public key algorithm id ALGO to a string representation of
-     the algorithm name.  For unknown algorithms this functions returns
-     the string '"?"'.  This function should not be used to test for the
-     availability of an algorithm.
-
- -- Function: int gcry_pk_map_name (const char *NAME)
-
-     Map the algorithm NAME to a public key algorithm Id.  Returns 0 if
-     the algorithm name is not known.
-
- -- Function: int gcry_pk_test_algo (int ALGO)
-
-     Return 0 if the public key algorithm ALGO is available for use.
-     Note that this is implemented as a macro.
-
- -- Function: unsigned int gcry_pk_get_nbits (gcry_sexp_t KEY)
-
-     Return what is commonly referred as the key length for the given
-     public or private in KEY.
-
- -- Function: unsigned char * gcry_pk_get_keygrip (gcry_sexp_t KEY,
-          unsigned char *ARRAY)
-
-     Return the so called "keygrip" which is the SHA-1 hash of the
-     public key parameters expressed in a way depended on the algorithm.
-     ARRAY must either provide space for 20 bytes or be 'NULL'.  In the
-     latter case a newly allocated array of that size is returned.  On
-     success a pointer to the newly allocated space or to ARRAY is
-     returned.  'NULL' is returned to indicate an error which is most
-     likely an unknown algorithm or one where a "keygrip" has not yet
-     been defined.  The function accepts public or secret keys in KEY.
-
- -- Function: gcry_error_t gcry_pk_testkey (gcry_sexp_t KEY)
-
-     Return zero if the private key KEY is 'sane', an error code
-     otherwise.  Note that it is not possible to check the 'saneness' of
-     a public key.
-
- -- Function: gcry_error_t gcry_pk_algo_info (int ALGO, int WHAT,
-          void *BUFFER, size_t *NBYTES)
-
-     Depending on the value of WHAT return various information about the
-     public key algorithm with the id ALGO.  Note that the function
-     returns '-1' on error and the actual error code must be retrieved
-     using the function 'gcry_errno'.  The currently defined values for
-     WHAT are:
-
-     'GCRYCTL_TEST_ALGO:'
-          Return 0 if the specified algorithm is available for use.
-          BUFFER must be 'NULL', NBYTES may be passed as 'NULL' or point
-          to a variable with the required usage of the algorithm.  This
-          may be 0 for "don't care" or the bit-wise OR of these flags:
-
-          'GCRY_PK_USAGE_SIGN'
-               Algorithm is usable for signing.
-          'GCRY_PK_USAGE_ENCR'
-               Algorithm is usable for encryption.
-
-          Unless you need to test for the allowed usage, it is in
-          general better to use the macro gcry_pk_test_algo instead.
-
-     'GCRYCTL_GET_ALGO_USAGE:'
-          Return the usage flags for the given algorithm.  An invalid
-          algorithm return 0.  Disabled algorithms are ignored here
-          because we want to know whether the algorithm is at all
-          capable of a certain usage.
-
-     'GCRYCTL_GET_ALGO_NPKEY'
-          Return the number of elements the public key for algorithm
-          ALGO consist of.  Return 0 for an unknown algorithm.
-
-     'GCRYCTL_GET_ALGO_NSKEY'
-          Return the number of elements the private key for algorithm
-          ALGO consist of.  Note that this value is always larger than
-          that of the public key.  Return 0 for an unknown algorithm.
-
-     'GCRYCTL_GET_ALGO_NSIGN'
-          Return the number of elements a signature created with the
-          algorithm ALGO consists of.  Return 0 for an unknown algorithm
-          or for an algorithm not capable of creating signatures.
-
-     'GCRYCTL_GET_ALGO_NENC'
-          Return the number of elements a encrypted message created with
-          the algorithm ALGO consists of.  Return 0 for an unknown
-          algorithm or for an algorithm not capable of encryption.
-
-     Please note that parameters not required should be passed as
-     'NULL'.
-
- -- Function: gcry_error_t gcry_pk_ctl (int CMD, void *BUFFER,
-          size_t BUFLEN)
-
-     This is a general purpose function to perform certain control
-     operations.  CMD controls what is to be done.  The return value is
-     0 for success or an error code.  Currently supported values for CMD
-     are:
-
-     'GCRYCTL_DISABLE_ALGO'
-          Disable the algorithm given as an algorithm id in BUFFER.
-          BUFFER must point to an 'int' variable with the algorithm id
-          and BUFLEN must have the value 'sizeof (int)'.  This function
-          is not thread safe and should thus be used before any other
-          threads are started.
-
-Libgcrypt also provides a function to generate public key pairs:
-
- -- Function: gcry_error_t gcry_pk_genkey (gcry_sexp_t *R_KEY,
-          gcry_sexp_t PARMS)
-
-     This function create a new public key pair using information given
-     in the S-expression PARMS and stores the private and the public key
-     in one new S-expression at the address given by R_KEY.  In case of
-     an error, R_KEY is set to 'NULL'.  The return code is 0 for success
-     or an error code otherwise.
-
-     Here is an example for PARMS to create an 2048 bit RSA key:
-
-          (genkey
-            (rsa
-              (nbits 4:2048)))
-
-     To create an Elgamal key, substitute "elg" for "rsa" and to create
-     a DSA key use "dsa".  Valid ranges for the key length depend on the
-     algorithms; all commonly used key lengths are supported.  Currently
-     supported parameters are:
-
-     'nbits'
-          This is always required to specify the length of the key.  The
-          argument is a string with a number in C-notation.  The value
-          should be a multiple of 8.  Note that the S-expression syntax
-          requires that a number is prefixed with its string length;
-          thus the '4:' in the above example.
-
-     'curve NAME'
-          For ECC a named curve may be used instead of giving the number
-          of requested bits.  This allows to request a specific curve to
-          override a default selection Libgcrypt would have taken if
-          'nbits' has been given.  The available names are listed with
-          the description of the ECC public key parameters.
-
-     'rsa-use-e VALUE'
-          This is only used with RSA to give a hint for the public
-          exponent.  The VALUE will be used as a base to test for a
-          usable exponent.  Some values are special:
-
-          '0'
-               Use a secure and fast value.  This is currently the
-               number 41.
-          '1'
-               Use a value as required by some crypto policies.  This is
-               currently the number 65537.
-          '2'
-               Reserved
-          '> 2'
-               Use the given value.
-
-          If this parameter is not used, Libgcrypt uses for historic
-          reasons 65537.  Note that the value must fit into a 32 bit
-          unsigned variable and that the usual C prefixes are considered
-          (e.g.  017 gives 15).
-
-     'qbits N'
-          This is only meanigful for DSA keys.  If it is given the DSA
-          key is generated with a Q parameyer of size N bits.  If it is
-          not given or zero Q is deduced from NBITS in this way:
-          '512 <= N <= 1024'
-               Q = 160
-          'N = 2048'
-               Q = 224
-          'N = 3072'
-               Q = 256
-          'N = 7680'
-               Q = 384
-          'N = 15360'
-               Q = 512
-          Note that in this case only the values for N, as given in the
-          table, are allowed.  When specifying Q all values of N in the
-          range 512 to 15680 are valid as long as they are multiples of
-          8.
-
-     'domain LIST'
-          This is only meaningful for DLP algorithms.  If specified keys
-          are generated with domain parameters taken from this list.
-          The exact format of this parameter depends on the actual
-          algorithm.  It is currently only implemented for DSA using
-          this format:
-
-               (genkey
-                 (dsa
-                   (domain
-                     (p P-MPI)
-                     (q Q-MPI)
-                     (g Q-MPI))))
-
-          'nbits' and 'qbits' may not be specified because they are
-          derived from the domain parameters.
-
-     'derive-parms LIST'
-          This is currently only implemented for RSA and DSA keys.  It
-          is not allowed to use this together with a 'domain'
-          specification.  If given, it is used to derive the keys using
-          the given parameters.
-
-          If given for an RSA key the X9.31 key generation algorithm is
-          used even if libgcrypt is not in FIPS mode.  If given for a
-          DSA key, the FIPS 186 algorithm is used even if libgcrypt is
-          not in FIPS mode.
-
-               (genkey
-                 (rsa
-                   (nbits 4:1024)
-                   (rsa-use-e 1:3)
-                   (derive-parms
-                     (Xp1 #1A1916DDB29B4EB7EB6732E128#)
-                     (Xp2 #192E8AAC41C576C822D93EA433#)
-                     (Xp  #D8CD81F035EC57EFE822955149D3BFF70C53520D
-                           769D6D76646C7A792E16EBD89FE6FC5B605A6493
-                           39DFC925A86A4C6D150B71B9EEA02D68885F5009
-                           B98BD984#)
-                     (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)
-                     (Xq2 #134E4CAA16D2350A21D775C404#)
-                     (Xq  #CC1092495D867E64065DEE3E7955F2EBC7D47A2D
-                           7C9953388F97DDDC3E1CA19C35CA659EDC2FC325
-                           6D29C2627479C086A699A49C4C9CEE7EF7BD1B34
-                           321DE34A#))))
-
-               (genkey
-                 (dsa
-                   (nbits 4:1024)
-                   (derive-parms
-                     (seed SEED-MPI))))
-
-     'flags FLAGLIST'
-          This is preferred way to define flags.  FLAGLIST may contain
-          any number of flags.  See above for a specification of these
-          flags.
-
-          Here is an example on how to create a key using curve Ed25519
-          with the ECDSA signature algorithm.  Note that the use of
-          ECDSA with that curve is in general not recommended.
-               (genkey
-                 (ecc
-                   (flags transient-key)))
-
-     'transient-key'
-     'use-x931'
-     'use-fips186'
-     'use-fips186-2'
-          These are deprecated ways to set a flag with that name; see
-          above for a description of each flag.
-
-     The key pair is returned in a format depending on the algorithm.
-     Both private and public keys are returned in one container and may
-     be accompanied by some miscellaneous information.
-
-     Here are two examples; the first for Elgamal and the second for
-     elliptic curve key generation:
-
-          (key-data
-            (public-key
-              (elg
-                (p P-MPI)
-                (g G-MPI)
-                (y Y-MPI)))
-            (private-key
-              (elg
-                (p P-MPI)
-                (g G-MPI)
-                (y Y-MPI)
-                (x X-MPI)))
-            (misc-key-info
-              (pm1-factors N1 N2 ... NN))
-
-          (key-data
-            (public-key
-              (ecc
-                (curve Ed25519)
-                (flags eddsa)
-                (q Q-VALUE)))
-            (private-key
-              (ecc
-                (curve Ed25519)
-                (flags eddsa)
-                (q Q-VALUE)
-                (d D-VALUE))))
-
-     As you can see, some of the information is duplicated, but this
-     provides an easy way to extract either the public or the private
-     key.  Note that the order of the elements is not defined, e.g.  the
-     private key may be stored before the public key.  N1 N2 ... NN is a
-     list of prime numbers used to composite P-MPI; this is in general
-     not a very useful information and only available if the key
-     generation algorithm provides them.
-
-Future versions of Libgcrypt will have extended versions of the public
-key interfaced which will take an additional context to allow for
-pre-computations, special operations, and other optimization.  As a
-first step a new function is introduced to help using the ECC algorithms
-in new ways:
-
- -- Function: gcry_error_t gcry_pubkey_get_sexp (gcry_sexp_t *R_SEXP,
-          int MODE, gcry_ctx_t CTX)
-
-     Return an S-expression representing the context CTX.  Depending on
-     the state of that context, the S-expression may either be a public
-     key, a private key or any other object used with public key
-     operations.  On success 0 is returned and a new S-expression is
-     stored at R_SEXP; on error an error code is returned and NULL is
-     stored at R_SEXP.  MODE must be one of:
-
-     '0'
-          Decide what to return depending on the context.  For example
-          if the private key parameter is available a private key is
-          returned, if not a public key is returned.
-
-     'GCRY_PK_GET_PUBKEY'
-          Return the public key even if the context has the private key
-          parameter.
-
-     'GCRY_PK_GET_SECKEY'
-          Return the private key or the error 'GPG_ERR_NO_SECKEY' if it
-          is not possible.
-
-     As of now this function supports only certain ECC operations
-     because a context object is right now only defined for ECC. Over
-     time this function will be extended to cover more algorithms.
-
-\1f
-File: gcrypt.info,  Node: Hashing,  Next: Message Authentication Codes,  Prev: Public Key cryptography,  Up: Top
-
-7 Hashing
-*********
-
-Libgcrypt provides an easy and consistent to use interface for hashing.
-Hashing is buffered and several hash algorithms can be updated at once.
-It is possible to compute a HMAC using the same routines.  The
-programming model follows an open/process/close paradigm and is in that
-similar to other building blocks provided by Libgcrypt.
-
-   For convenience reasons, a few cyclic redundancy check value
-operations are also supported.
-
-* Menu:
-
-* Available hash algorithms::   List of hash algorithms supported by the library.
-* Working with hash algorithms::  List of functions related to hashing.
-
-\1f
-File: gcrypt.info,  Node: Available hash algorithms,  Next: Working with hash algorithms,  Up: Hashing
-
-7.1 Available hash algorithms
-=============================
-
-'GCRY_MD_NONE'
-     This is not a real algorithm but used by some functions as an error
-     return value.  This constant is guaranteed to have the value '0'.
-
-'GCRY_MD_SHA1'
-     This is the SHA-1 algorithm which yields a message digest of 20
-     bytes.  Note that SHA-1 begins to show some weaknesses and it is
-     suggested to fade out its use if strong cryptographic properties
-     are required.
-
-'GCRY_MD_RMD160'
-     This is the 160 bit version of the RIPE message digest
-     (RIPE-MD-160).  Like SHA-1 it also yields a digest of 20 bytes.
-     This algorithm share a lot of design properties with SHA-1 and thus
-     it is advisable not to use it for new protocols.
-
-'GCRY_MD_MD5'
-     This is the well known MD5 algorithm, which yields a message digest
-     of 16 bytes.  Note that the MD5 algorithm has severe weaknesses,
-     for example it is easy to compute two messages yielding the same
-     hash (collision attack).  The use of this algorithm is only
-     justified for non-cryptographic application.
-
-'GCRY_MD_MD4'
-     This is the MD4 algorithm, which yields a message digest of 16
-     bytes.  This algorithm has severe weaknesses and should not be
-     used.
-
-'GCRY_MD_MD2'
-     This is an reserved identifier for MD-2; there is no implementation
-     yet.  This algorithm has severe weaknesses and should not be used.
-
-'GCRY_MD_TIGER'
-     This is the TIGER/192 algorithm which yields a message digest of 24
-     bytes.  Actually this is a variant of TIGER with a different output
-     print order as used by GnuPG up to version 1.3.2.
-
-'GCRY_MD_TIGER1'
-     This is the TIGER variant as used by the NESSIE project.  It uses
-     the most commonly used output print order.
-
-'GCRY_MD_TIGER2'
-     This is another variant of TIGER with a different padding scheme.
-
-'GCRY_MD_HAVAL'
-     This is an reserved value for the HAVAL algorithm with 5 passes and
-     160 bit.  It yields a message digest of 20 bytes.  Note that there
-     is no implementation yet available.
-
-'GCRY_MD_SHA224'
-     This is the SHA-224 algorithm which yields a message digest of 28
-     bytes.  See Change Notice 1 for FIPS 180-2 for the specification.
-
-'GCRY_MD_SHA256'
-     This is the SHA-256 algorithm which yields a message digest of 32
-     bytes.  See FIPS 180-2 for the specification.
-
-'GCRY_MD_SHA384'
-     This is the SHA-384 algorithm which yields a message digest of 48
-     bytes.  See FIPS 180-2 for the specification.
-
-'GCRY_MD_SHA512'
-     This is the SHA-384 algorithm which yields a message digest of 64
-     bytes.  See FIPS 180-2 for the specification.
-
-'GCRY_MD_SHA3_224'
-     This is the SHA3-224 algorithm which yields a message digest of 28
-     bytes.  See FIPS 202 for the specification.
-
-'GCRY_MD_SHA3_256'
-     This is the SHA3-256 algorithm which yields a message digest of 32
-     bytes.  See FIPS 202 for the specification.
-
-'GCRY_MD_SHA3_384'
-     This is the SHA3-384 algorithm which yields a message digest of 48
-     bytes.  See FIPS 202 for the specification.
-
-'GCRY_MD_SHA3_512'
-     This is the SHA3-384 algorithm which yields a message digest of 64
-     bytes.  See FIPS 202 for the specification.
-
-'GCRY_MD_SHAKE128'
-     This is the SHAKE128 extendable-output function (XOF) algorithm
-     with 128 bit security strength.  See FIPS 202 for the
-     specification.
-
-'GCRY_MD_SHAKE256'
-     This is the SHAKE256 extendable-output function (XOF) algorithm
-     with 256 bit security strength.  See FIPS 202 for the
-     specification.
-
-'GCRY_MD_CRC32'
-     This is the ISO 3309 and ITU-T V.42 cyclic redundancy check.  It
-     yields an output of 4 bytes.  Note that this is not a hash
-     algorithm in the cryptographic sense.
-
-'GCRY_MD_CRC32_RFC1510'
-     This is the above cyclic redundancy check function, as modified by
-     RFC 1510.  It yields an output of 4 bytes.  Note that this is not a
-     hash algorithm in the cryptographic sense.
-
-'GCRY_MD_CRC24_RFC2440'
-     This is the OpenPGP cyclic redundancy check function.  It yields an
-     output of 3 bytes.  Note that this is not a hash algorithm in the
-     cryptographic sense.
-
-'GCRY_MD_WHIRLPOOL'
-     This is the Whirlpool algorithm which yields a message digest of 64
-     bytes.
-
-'GCRY_MD_GOSTR3411_94'
-     This is the hash algorithm described in GOST R 34.11-94 which
-     yields a message digest of 32 bytes.
-
-'GCRY_MD_STRIBOG256'
-     This is the 256-bit version of hash algorithm described in GOST R
-     34.11-2012 which yields a message digest of 32 bytes.
-
-'GCRY_MD_STRIBOG512'
-     This is the 512-bit version of hash algorithm described in GOST R
-     34.11-2012 which yields a message digest of 64 bytes.
-
-'GCRY_MD_BLAKE2B_512'
-     This is the BLAKE2b-512 algorithm which yields a message digest of
-     64 bytes.  See RFC 7693 for the specification.
-
-'GCRY_MD_BLAKE2B_384'
-     This is the BLAKE2b-384 algorithm which yields a message digest of
-     48 bytes.  See RFC 7693 for the specification.
-
-'GCRY_MD_BLAKE2B_256'
-     This is the BLAKE2b-256 algorithm which yields a message digest of
-     32 bytes.  See RFC 7693 for the specification.
-
-'GCRY_MD_BLAKE2B_160'
-     This is the BLAKE2b-160 algorithm which yields a message digest of
-     20 bytes.  See RFC 7693 for the specification.
-
-'GCRY_MD_BLAKE2S_256'
-     This is the BLAKE2s-256 algorithm which yields a message digest of
-     32 bytes.  See RFC 7693 for the specification.
-
-'GCRY_MD_BLAKE2S_224'
-     This is the BLAKE2s-224 algorithm which yields a message digest of
-     28 bytes.  See RFC 7693 for the specification.
-
-'GCRY_MD_BLAKE2S_160'
-     This is the BLAKE2s-160 algorithm which yields a message digest of
-     20 bytes.  See RFC 7693 for the specification.
-
-'GCRY_MD_BLAKE2S_128'
-     This is the BLAKE2s-128 algorithm which yields a message digest of
-     16 bytes.  See RFC 7693 for the specification.
-
-\1f
-File: gcrypt.info,  Node: Working with hash algorithms,  Prev: Available hash algorithms,  Up: Hashing
-
-7.2 Working with hash algorithms
-================================
-
-To use most of these function it is necessary to create a context; this
-is done using:
-
- -- Function: gcry_error_t gcry_md_open (gcry_md_hd_t *HD, int ALGO,
-          unsigned int FLAGS)
-
-     Create a message digest object for algorithm ALGO.  FLAGS may be
-     given as an bitwise OR of constants described below.  ALGO may be
-     given as '0' if the algorithms to use are later set using
-     'gcry_md_enable'.  HD is guaranteed to either receive a valid
-     handle or NULL.
-
-     For a list of supported algorithms, see *note Available hash
-     algorithms::.
-
-     The flags allowed for MODE are:
-
-     'GCRY_MD_FLAG_SECURE'
-          Allocate all buffers and the resulting digest in "secure
-          memory".  Use this is the hashed data is highly confidential.
-
-     'GCRY_MD_FLAG_HMAC'
-          Turn the algorithm into a HMAC message authentication
-          algorithm.  This only works if just one algorithm is enabled
-          for the handle and that algorithm is not an extendable-output
-          function.  Note that the function 'gcry_md_setkey' must be
-          used to set the MAC key.  The size of the MAC is equal to the
-          message digest of the underlying hash algorithm.  If you want
-          CBC message authentication codes based on a cipher, see *note
-          Working with cipher handles::.
-
-     'GCRY_MD_FLAG_BUGEMU1'
-          Versions of Libgcrypt before 1.6.0 had a bug in the Whirlpool
-          code which led to a wrong result for certain input sizes and
-          write patterns.  Using this flag emulates that bug.  This may
-          for example be useful for applications which use Whirlpool as
-          part of their key generation.  It is strongly suggested to use
-          this flag only if really needed and if possible to the data
-          should be re-processed using the regular Whirlpool algorithm.
-
-          Note that this flag works for the entire hash context.  If
-          needed arises it may be used to enable bug emulation for other
-          hash algorithms.  Thus you should not use this flag for a
-          multi-algorithm hash context.
-
-     You may use the function 'gcry_md_is_enabled' to later check
-     whether an algorithm has been enabled.
-
-   If you want to calculate several hash algorithms at the same time,
-you have to use the following function right after the 'gcry_md_open':
-
- -- Function: gcry_error_t gcry_md_enable (gcry_md_hd_t H, int ALGO)
-
-     Add the message digest algorithm ALGO to the digest object
-     described by handle H.  Duplicated enabling of algorithms is
-     detected and ignored.
-
-   If the flag 'GCRY_MD_FLAG_HMAC' was used, the key for the MAC must be
-set using the function:
-
- -- Function: gcry_error_t gcry_md_setkey (gcry_md_hd_t H, const void
-          *KEY, size_t KEYLEN)
-
-     For use with the HMAC feature or BLAKE2 keyed hash, set the MAC key
-     to the value of KEY of length KEYLEN bytes.  For HMAC, there is no
-     restriction on the length of the key.  For keyed BLAKE2b hash,
-     length of the key must be 64 bytes or less.  For keyed BLAKE2s
-     hash, length of the key must be 32 bytes or less.
-
-   After you are done with the hash calculation, you should release the
-resources by using:
-
- -- Function: void gcry_md_close (gcry_md_hd_t H)
-
-     Release all resources of hash context H.  H should not be used
-     after a call to this function.  A 'NULL' passed as H is ignored.
-     The function also zeroises all sensitive information associated
-     with this handle.
-
-   Often you have to do several hash operations using the same
-algorithm.  To avoid the overhead of creating and releasing context, a
-reset function is provided:
-
- -- Function: void gcry_md_reset (gcry_md_hd_t H)
-
-     Reset the current context to its initial state.  This is
-     effectively identical to a close followed by an open and enabling
-     all currently active algorithms.
-
-   Often it is necessary to start hashing some data and then continue to
-hash different data.  To avoid hashing the same data several times
-(which might not even be possible if the data is received from a pipe),
-a snapshot of the current hash context can be taken and turned into a
-new context:
-
- -- Function: gcry_error_t gcry_md_copy (gcry_md_hd_t *HANDLE_DST,
-          gcry_md_hd_t HANDLE_SRC)
-
-     Create a new digest object as an exact copy of the object described
-     by handle HANDLE_SRC and store it in HANDLE_DST.  The context is
-     not reset and you can continue to hash data using this context and
-     independently using the original context.
-
-   Now that we have prepared everything to calculate hashes, it is time
-to see how it is actually done.  There are two ways for this, one to
-update the hash with a block of memory and one macro to update the hash
-by just one character.  Both methods can be used on the same hash
-context.
-
- -- Function: void gcry_md_write (gcry_md_hd_t H, const void *BUFFER,
-          size_t LENGTH)
-
-     Pass LENGTH bytes of the data in BUFFER to the digest object with
-     handle H to update the digest values.  This function should be used
-     for large blocks of data.  If this function is used after the
-     context has been finalized, it will keep on pushing the data
-     through the algorithm specific transform function and change the
-     context; however the results are not meaningful and this feature is
-     only available to mitigate timing attacks.
-
- -- Function: void gcry_md_putc (gcry_md_hd_t H, int C)
-
-     Pass the byte in C to the digest object with handle H to update the
-     digest value.  This is an efficient function, implemented as a
-     macro to buffer the data before an actual update.
-
-   The semantics of the hash functions do not provide for reading out
-intermediate message digests because the calculation must be finalized
-first.  This finalization may for example include the number of bytes
-hashed in the message digest or some padding.
-
- -- Function: void gcry_md_final (gcry_md_hd_t H)
-
-     Finalize the message digest calculation.  This is not really needed
-     because 'gcry_md_read' and 'gcry_md_extract' do this implicitly.
-     After this has been done no further updates (by means of
-     'gcry_md_write' or 'gcry_md_putc' should be done; However, to
-     mitigate timing attacks it is sometimes useful to keep on updating
-     the context after having stored away the actual digest.  Only the
-     first call to this function has an effect.  It is implemented as a
-     macro.
-
-   The way to read out the calculated message digest is by using the
-function:
-
- -- Function: unsigned char * gcry_md_read (gcry_md_hd_t H, int ALGO)
-
-     'gcry_md_read' returns the message digest after finalizing the
-     calculation.  This function may be used as often as required but it
-     will always return the same value for one handle.  The returned
-     message digest is allocated within the message context and
-     therefore valid until the handle is released or reset-ed (using
-     'gcry_md_close' or 'gcry_md_reset' or it has been updated as a
-     mitigation measure against timing attacks.  ALGO may be given as 0
-     to return the only enabled message digest or it may specify one of
-     the enabled algorithms.  The function does return 'NULL' if the
-     requested algorithm has not been enabled.
-
-   The way to read output of extendable-output function is by using the
-function:
-
- -- Function: gpg_err_code_t gcry_md_extract (gcry_md_hd_t H, int ALGO,
-          void *BUFFER, size_t LENGTH)
-
-     'gcry_mac_read' returns output from extendable-output function.
-     This function may be used as often as required to generate more
-     output byte stream from the algorithm.  Function extracts the new
-     output bytes to BUFFER of the length LENGTH.  Buffer will be fully
-     populated with new output.  ALGO may be given as 0 to return the
-     only enabled message digest or it may specify one of the enabled
-     algorithms.  The function does return non-zero value if the
-     requested algorithm has not been enabled.
-
-   Because it is often necessary to get the message digest of blocks of
-memory, two fast convenience function are available for this task:
-
- -- Function: gpg_err_code_t gcry_md_hash_buffers ( int ALGO,
-          unsigned int FLAGS, void *DIGEST, const gcry_buffer_t *IOV,
-          int IOVCNT )
-
-     'gcry_md_hash_buffers' is a shortcut function to calculate a
-     message digest from several buffers.  This function does not
-     require a context and immediately returns the message digest of the
-     data described by IOV and IOVCNT.  DIGEST must be allocated by the
-     caller, large enough to hold the message digest yielded by the the
-     specified algorithm ALGO.  This required size may be obtained by
-     using the function 'gcry_md_get_algo_dlen'.
-
-     IOV is an array of buffer descriptions with IOVCNT items.  The
-     caller should zero out the structures in this array and for each
-     array item set the fields '.data' to the address of the data to be
-     hashed, '.len' to number of bytes to be hashed.  If .OFF is also
-     set, the data is taken starting at .OFF bytes from the begin of the
-     buffer.  The field '.size' is not used.
-
-     The only supported flag value for FLAGS is GCRY_MD_FLAG_HMAC which
-     turns this function into a HMAC function; the first item in IOV is
-     then used as the key.
-
-     On success the function returns 0 and stores the resulting hash or
-     MAC at DIGEST.
-
- -- Function: void gcry_md_hash_buffer (int ALGO, void *DIGEST, const
-          void *BUFFER, size_t LENGTH);
-
-     'gcry_md_hash_buffer' is a shortcut function to calculate a message
-     digest of a buffer.  This function does not require a context and
-     immediately returns the message digest of the LENGTH bytes at
-     BUFFER.  DIGEST must be allocated by the caller, large enough to
-     hold the message digest yielded by the the specified algorithm
-     ALGO.  This required size may be obtained by using the function
-     'gcry_md_get_algo_dlen'.
-
-     Note that in contrast to 'gcry_md_hash_buffers' this function will
-     abort the process if an unavailable algorithm is used.
-
-   Hash algorithms are identified by internal algorithm numbers (see
-'gcry_md_open' for a list).  However, in most applications they are used
-by names, so two functions are available to map between string
-representations and hash algorithm identifiers.
-
- -- Function: const char * gcry_md_algo_name (int ALGO)
-
-     Map the digest algorithm id ALGO to a string representation of the
-     algorithm name.  For unknown algorithms this function returns the
-     string '"?"'.  This function should not be used to test for the
-     availability of an algorithm.
-
- -- Function: int gcry_md_map_name (const char *NAME)
-
-     Map the algorithm with NAME to a digest algorithm identifier.
-     Returns 0 if the algorithm name is not known.  Names representing
-     ASN.1 object identifiers are recognized if the IETF dotted format
-     is used and the OID is prefixed with either "'oid.'" or "'OID.'".
-     For a list of supported OIDs, see the source code at 'cipher/md.c'.
-     This function should not be used to test for the availability of an
-     algorithm.
-
- -- Function: gcry_error_t gcry_md_get_asnoid (int ALGO, void *BUFFER,
-          size_t *LENGTH)
-
-     Return an DER encoded ASN.1 OID for the algorithm ALGO in the user
-     allocated BUFFER.  LENGTH must point to variable with the available
-     size of BUFFER and receives after return the actual size of the
-     returned OID. The returned error code may be 'GPG_ERR_TOO_SHORT' if
-     the provided buffer is to short to receive the OID; it is possible
-     to call the function with 'NULL' for BUFFER to have it only return
-     the required size.  The function returns 0 on success.
-
-   To test whether an algorithm is actually available for use, the
-following macro should be used:
-
- -- Function: gcry_error_t gcry_md_test_algo (int ALGO)
-
-     The macro returns 0 if the algorithm ALGO is available for use.
-
-   If the length of a message digest is not known, it can be retrieved
-using the following function:
-
- -- Function: unsigned int gcry_md_get_algo_dlen (int ALGO)
-
-     Retrieve the length in bytes of the digest yielded by algorithm
-     ALGO.  This is often used prior to 'gcry_md_read' to allocate
-     sufficient memory for the digest.
-
-   In some situations it might be hard to remember the algorithm used
-for the ongoing hashing.  The following function might be used to get
-that information:
-
- -- Function: int gcry_md_get_algo (gcry_md_hd_t H)
-
-     Retrieve the algorithm used with the handle H.  Note that this does
-     not work reliable if more than one algorithm is enabled in H.
-
-   The following macro might also be useful:
-
- -- Function: int gcry_md_is_secure (gcry_md_hd_t H)
-
-     This function returns true when the digest object H is allocated in
-     "secure memory"; i.e.  H was created with the
-     'GCRY_MD_FLAG_SECURE'.
-
- -- Function: int gcry_md_is_enabled (gcry_md_hd_t H, int ALGO)
-
-     This function returns true when the algorithm ALGO has been enabled
-     for the digest object H.
-
-   Tracking bugs related to hashing is often a cumbersome task which
-requires to add a lot of printf statements into the code.  Libgcrypt
-provides an easy way to avoid this.  The actual data hashed can be
-written to files on request.
-
- -- Function: void gcry_md_debug (gcry_md_hd_t H, const char *SUFFIX)
-
-     Enable debugging for the digest object with handle H.  This creates
-     files named 'dbgmd-<n>.<string>' while doing the actual hashing.
-     SUFFIX is the string part in the filename.  The number is a counter
-     incremented for each new hashing.  The data in the file is the raw
-     data as passed to 'gcry_md_write' or 'gcry_md_putc'.  If 'NULL' is
-     used for SUFFIX, the debugging is stopped and the file closed.
-     This is only rarely required because 'gcry_md_close' implicitly
-     stops debugging.
-
-\1f
-File: gcrypt.info,  Node: Message Authentication Codes,  Next: Key Derivation,  Prev: Hashing,  Up: Top
-
-8 Message Authentication Codes
-******************************
-
-Libgcrypt provides an easy and consistent to use interface for
-generating Message Authentication Codes (MAC). MAC generation is
-buffered and interface similar to the one used with hash algorithms.
-The programming model follows an open/process/close paradigm and is in
-that similar to other building blocks provided by Libgcrypt.
-
-* Menu:
-
-* Available MAC algorithms::   List of MAC algorithms supported by the library.
-* Working with MAC algorithms::  List of functions related to MAC algorithms.
-
-\1f
-File: gcrypt.info,  Node: Available MAC algorithms,  Next: Working with MAC algorithms,  Up: Message Authentication Codes
-
-8.1 Available MAC algorithms
-============================
-
-'GCRY_MAC_NONE'
-     This is not a real algorithm but used by some functions as an error
-     return value.  This constant is guaranteed to have the value '0'.
-
-'GCRY_MAC_HMAC_SHA256'
-     This is keyed-hash message authentication code (HMAC) message
-     authentication algorithm based on the SHA-256 hash algorithm.
-
-'GCRY_MAC_HMAC_SHA224'
-     This is HMAC message authentication algorithm based on the SHA-224
-     hash algorithm.
-
-'GCRY_MAC_HMAC_SHA512'
-     This is HMAC message authentication algorithm based on the SHA-512
-     hash algorithm.
-
-'GCRY_MAC_HMAC_SHA384'
-     This is HMAC message authentication algorithm based on the SHA-384
-     hash algorithm.
-
-'GCRY_MAC_HMAC_SHA3_256'
-     This is HMAC message authentication algorithm based on the SHA3-384
-     hash algorithm.
-
-'GCRY_MAC_HMAC_SHA3_224'
-     This is HMAC message authentication algorithm based on the SHA3-224
-     hash algorithm.
-
-'GCRY_MAC_HMAC_SHA3_512'
-     This is HMAC message authentication algorithm based on the SHA3-512
-     hash algorithm.
-
-'GCRY_MAC_HMAC_SHA3_384'
-     This is HMAC message authentication algorithm based on the SHA3-384
-     hash algorithm.
-
-'GCRY_MAC_HMAC_SHA1'
-     This is HMAC message authentication algorithm based on the SHA-1
-     hash algorithm.
-
-'GCRY_MAC_HMAC_MD5'
-     This is HMAC message authentication algorithm based on the MD5 hash
-     algorithm.
-
-'GCRY_MAC_HMAC_MD4'
-     This is HMAC message authentication algorithm based on the MD4 hash
-     algorithm.
-
-'GCRY_MAC_HMAC_RMD160'
-     This is HMAC message authentication algorithm based on the
-     RIPE-MD-160 hash algorithm.
-
-'GCRY_MAC_HMAC_WHIRLPOOL'
-     This is HMAC message authentication algorithm based on the
-     WHIRLPOOL hash algorithm.
-
-'GCRY_MAC_HMAC_GOSTR3411_94'
-     This is HMAC message authentication algorithm based on the GOST R
-     34.11-94 hash algorithm.
-
-'GCRY_MAC_HMAC_STRIBOG256'
-     This is HMAC message authentication algorithm based on the 256-bit
-     hash algorithm described in GOST R 34.11-2012.
-
-'GCRY_MAC_HMAC_STRIBOG512'
-     This is HMAC message authentication algorithm based on the 512-bit
-     hash algorithm described in GOST R 34.11-2012.
-
-'GCRY_MAC_CMAC_AES'
-     This is CMAC (Cipher-based MAC) message authentication algorithm
-     based on the AES block cipher algorithm.
-
-'GCRY_MAC_CMAC_3DES'
-     This is CMAC message authentication algorithm based on the
-     three-key EDE Triple-DES block cipher algorithm.
-
-'GCRY_MAC_CMAC_CAMELLIA'
-     This is CMAC message authentication algorithm based on the Camellia
-     block cipher algorithm.
-
-'GCRY_MAC_CMAC_CAST5'
-     This is CMAC message authentication algorithm based on the
-     CAST128-5 block cipher algorithm.
-
-'GCRY_MAC_CMAC_BLOWFISH'
-     This is CMAC message authentication algorithm based on the Blowfish
-     block cipher algorithm.
-
-'GCRY_MAC_CMAC_TWOFISH'
-     This is CMAC message authentication algorithm based on the Twofish
-     block cipher algorithm.
-
-'GCRY_MAC_CMAC_SERPENT'
-     This is CMAC message authentication algorithm based on the Serpent
-     block cipher algorithm.
-
-'GCRY_MAC_CMAC_SEED'
-     This is CMAC message authentication algorithm based on the SEED
-     block cipher algorithm.
-
-'GCRY_MAC_CMAC_RFC2268'
-     This is CMAC message authentication algorithm based on the Ron's
-     Cipher 2 block cipher algorithm.
-
-'GCRY_MAC_CMAC_IDEA'
-     This is CMAC message authentication algorithm based on the IDEA
-     block cipher algorithm.
-
-'GCRY_MAC_CMAC_GOST28147'
-     This is CMAC message authentication algorithm based on the GOST
-     28147-89 block cipher algorithm.
-
-'GCRY_MAC_GMAC_AES'
-     This is GMAC (GCM mode based MAC) message authentication algorithm
-     based on the AES block cipher algorithm.
-
-'GCRY_MAC_GMAC_CAMELLIA'
-     This is GMAC message authentication algorithm based on the Camellia
-     block cipher algorithm.
-
-'GCRY_MAC_GMAC_TWOFISH'
-     This is GMAC message authentication algorithm based on the Twofish
-     block cipher algorithm.
-
-'GCRY_MAC_GMAC_SERPENT'
-     This is GMAC message authentication algorithm based on the Serpent
-     block cipher algorithm.
-
-'GCRY_MAC_GMAC_SEED'
-     This is GMAC message authentication algorithm based on the SEED
-     block cipher algorithm.
-
-'GCRY_MAC_POLY1305'
-     This is plain Poly1305 message authentication algorithm, used with
-     one-time key.
-
-'GCRY_MAC_POLY1305_AES'
-     This is Poly1305-AES message authentication algorithm, used with
-     key and one-time nonce.
-
-'GCRY_MAC_POLY1305_CAMELLIA'
-     This is Poly1305-Camellia message authentication algorithm, used
-     with key and one-time nonce.
-
-'GCRY_MAC_POLY1305_TWOFISH'
-     This is Poly1305-Twofish message authentication algorithm, used
-     with key and one-time nonce.
-
-'GCRY_MAC_POLY1305_SERPENT'
-     This is Poly1305-Serpent message authentication algorithm, used
-     with key and one-time nonce.
-
-'GCRY_MAC_POLY1305_SEED'
-     This is Poly1305-SEED message authentication algorithm, used with
-     key and one-time nonce.
-
-\1f
-File: gcrypt.info,  Node: Working with MAC algorithms,  Prev: Available MAC algorithms,  Up: Message Authentication Codes
-
-8.2 Working with MAC algorithms
-===============================
-
-To use most of these function it is necessary to create a context; this
-is done using:
-
- -- Function: gcry_error_t gcry_mac_open (gcry_mac_hd_t *HD, int ALGO,
-          unsigned int FLAGS, gcry_ctx_t CTX)
-
-     Create a MAC object for algorithm ALGO.  FLAGS may be given as an
-     bitwise OR of constants described below.  HD is guaranteed to
-     either receive a valid handle or NULL. CTX is context object to
-     associate MAC object with.  CTX maybe set to NULL.
-
-     For a list of supported algorithms, see *note Available MAC
-     algorithms::.
-
-     The flags allowed for MODE are:
-
-     'GCRY_MAC_FLAG_SECURE'
-          Allocate all buffers and the resulting MAC in "secure memory".
-          Use this if the MAC data is highly confidential.
-
-   In order to use a handle for performing MAC algorithm operations, a
-'key' has to be set first:
-
- -- Function: gcry_error_t gcry_mac_setkey (gcry_mac_hd_t H, const void
-          *KEY, size_t KEYLEN)
-
-     Set the MAC key to the value of KEY of length KEYLEN bytes.  With
-     HMAC algorithms, there is no restriction on the length of the key.
-     With CMAC algorithms, the length of the key is restricted to those
-     supported by the underlying block cipher.
-
-   GMAC algorithms and Poly1305-with-cipher algorithms need
-initialization vector to be set, which can be performed with function:
-
- -- Function: gcry_error_t gcry_mac_setiv (gcry_mac_hd_t H, const void
-          *IV, size_t IVLEN)
-
-     Set the IV to the value of IV of length IVLEN bytes.
-
-   After you are done with the MAC calculation, you should release the
-resources by using:
-
- -- Function: void gcry_mac_close (gcry_mac_hd_t H)
-
-     Release all resources of MAC context H.  H should not be used after
-     a call to this function.  A 'NULL' passed as H is ignored.  The
-     function also clears all sensitive information associated with this
-     handle.
-
-   Often you have to do several MAC operations using the same algorithm.
-To avoid the overhead of creating and releasing context, a reset
-function is provided:
-
- -- Function: gcry_error_t gcry_mac_reset (gcry_mac_hd_t H)
-
-     Reset the current context to its initial state.  This is
-     effectively identical to a close followed by an open and setting
-     same key.
-
-     Note that gcry_mac_reset is implemented as a macro.
-
-   Now that we have prepared everything to calculate MAC, it is time to
-see how it is actually done.
-
- -- Function: gcry_error_t gcry_mac_write (gcry_mac_hd_t H, const void
-          *BUFFER, size_t LENGTH)
-
-     Pass LENGTH bytes of the data in BUFFER to the MAC object with
-     handle H to update the MAC values.  If this function is used after
-     the context has been finalized, it will keep on pushing the data
-     through the algorithm specific transform function and thereby
-     change the context; however the results are not meaningful and this
-     feature is only available to mitigate timing attacks.
-
-   The way to read out the calculated MAC is by using the function:
-
- -- Function: gcry_error_t gcry_mac_read (gcry_mac_hd_t H, void *BUFFER,
-          size_t *LENGTH)
-
-     'gcry_mac_read' returns the MAC after finalizing the calculation.
-     Function copies the resulting MAC value to BUFFER of the length
-     LENGTH.  If LENGTH is larger than length of resulting MAC value,
-     then length of MAC is returned through LENGTH.
-
-   To compare existing MAC value with recalculated MAC, one is to use
-the function:
-
- -- Function: gcry_error_t gcry_mac_verify (gcry_mac_hd_t H, void
-          *BUFFER, size_t LENGTH)
-
-     'gcry_mac_verify' finalizes MAC calculation and compares result
-     with LENGTH bytes of data in BUFFER.  Error code 'GPG_ERR_CHECKSUM'
-     is returned if the MAC value in the buffer BUFFER does not match
-     the MAC calculated in object H.
-
-   In some situations it might be hard to remember the algorithm used
-for the MAC calculation.  The following function might be used to get
-that information:
-
- -- Function: int gcry_mac_get_algo (gcry_mac_hd_t H)
-
-     Retrieve the algorithm used with the handle H.
-
-   MAC algorithms are identified by internal algorithm numbers (see
-'gcry_mac_open' for a list).  However, in most applications they are
-used by names, so two functions are available to map between string
-representations and MAC algorithm identifiers.
-
- -- Function: const char * gcry_mac_algo_name (int ALGO)
-
-     Map the MAC algorithm id ALGO to a string representation of the
-     algorithm name.  For unknown algorithms this function returns the
-     string '"?"'.  This function should not be used to test for the
-     availability of an algorithm.
-
- -- Function: int gcry_mac_map_name (const char *NAME)
-
-     Map the algorithm with NAME to a MAC algorithm identifier.  Returns
-     0 if the algorithm name is not known.  This function should not be
-     used to test for the availability of an algorithm.
-
-   To test whether an algorithm is actually available for use, the
-following macro should be used:
-
- -- Function: gcry_error_t gcry_mac_test_algo (int ALGO)
-
-     The macro returns 0 if the MAC algorithm ALGO is available for use.
-
-   If the length of a message digest is not known, it can be retrieved
-using the following function:
-
- -- Function: unsigned int gcry_mac_get_algo_maclen (int ALGO)
-
-     Retrieve the length in bytes of the MAC yielded by algorithm ALGO.
-     This is often used prior to 'gcry_mac_read' to allocate sufficient
-     memory for the MAC value.  On error '0' is returned.
-
- -- Function: unsigned int gcry_mac_get_algo_keylen (ALGO)
-
-     This function returns length of the key for MAC algorithm ALGO.  If
-     the algorithm supports multiple key lengths, the default supported
-     key length is returned.  On error '0' is returned.  The key length
-     is returned as number of octets.
-
-\1f
-File: gcrypt.info,  Node: Key Derivation,  Next: Random Numbers,  Prev: Message Authentication Codes,  Up: Top
-
-9 Key Derivation
-****************
-
-Libgcypt provides a general purpose function to derive keys from
-strings.
-
- -- Function: gpg_error_t gcry_kdf_derive ( const void *PASSPHRASE,
-          size_t PASSPHRASELEN, int ALGO, int SUBALGO, const void *SALT,
-          size_t SALTLEN, unsigned long ITERATIONS, size_t KEYSIZE,
-          void *KEYBUFFER )
-
-     Derive a key from a passphrase.  KEYSIZE gives the requested size
-     of the keys in octets.  KEYBUFFER is a caller provided buffer
-     filled on success with the derived key.  The input passphrase is
-     taken from PASSPHRASE which is an arbitrary memory buffer of
-     PASSPHRASELEN octets.  ALGO specifies the KDF algorithm to use; see
-     below.  SUBALGO specifies an algorithm used internally by the KDF
-     algorithms; this is usually a hash algorithm but certain KDF
-     algorithms may use it differently.  SALT is a salt of length
-     SALTLEN octets, as needed by most KDF algorithms.  ITERATIONS is a
-     positive integer parameter to most KDFs.
-
-     On success 0 is returned; on failure an error code.
-
-     Currently supported KDFs (parameter ALGO):
-
-     'GCRY_KDF_SIMPLE_S2K'
-          The OpenPGP simple S2K algorithm (cf.  RFC4880).  Its use is
-          strongly deprecated.  SALT and ITERATIONS are not needed and
-          may be passed as 'NULL'/'0'.
-
-     'GCRY_KDF_SALTED_S2K'
-          The OpenPGP salted S2K algorithm (cf.  RFC4880).  Usually not
-          used.  ITERATIONS is not needed and may be passed as '0'.
-          SALTLEN must be given as 8.
-
-     'GCRY_KDF_ITERSALTED_S2K'
-          The OpenPGP iterated+salted S2K algorithm (cf.  RFC4880).
-          This is the default for most OpenPGP applications.  SALTLEN
-          must be given as 8.  Note that OpenPGP defines a special
-          encoding of the ITERATIONS; however this function takes the
-          plain decoded iteration count.
-
-     'GCRY_KDF_PBKDF2'
-          The PKCS#5 Passphrase Based Key Derivation Function number 2.
-
-     'GCRY_KDF_SCRYPT'
-          The SCRYPT Key Derivation Function.  The subalgorithm is used
-          to specify the CPU/memory cost parameter N, and the number of
-          iterations is used for the parallelization parameter p.  The
-          block size is fixed at 8 in the current implementation.
-
-\1f
-File: gcrypt.info,  Node: Random Numbers,  Next: S-expressions,  Prev: Key Derivation,  Up: Top
-
-10 Random Numbers
-*****************
-
-* Menu:
-
-* Quality of random numbers::   Libgcrypt uses different quality levels.
-* Retrieving random numbers::   How to retrieve random numbers.
-
-\1f
-File: gcrypt.info,  Node: Quality of random numbers,  Next: Retrieving random numbers,  Up: Random Numbers
-
-10.1 Quality of random numbers
-==============================
-
-Libgcypt offers random numbers of different quality levels:
-
- -- Data type: gcry_random_level_t
-     The constants for the random quality levels are of this enum type.
-
-'GCRY_WEAK_RANDOM'
-     For all functions, except for 'gcry_mpi_randomize', this level maps
-     to GCRY_STRONG_RANDOM. If you do not want this, consider using
-     'gcry_create_nonce'.
-'GCRY_STRONG_RANDOM'
-     Use this level for session keys and similar purposes.
-'GCRY_VERY_STRONG_RANDOM'
-     Use this level for long term key material.
-
-\1f
-File: gcrypt.info,  Node: Retrieving random numbers,  Prev: Quality of random numbers,  Up: Random Numbers
-
-10.2 Retrieving random numbers
-==============================
-
- -- Function: void gcry_randomize (unsigned char *BUFFER, size_t LENGTH,
-          enum gcry_random_level LEVEL)
-
-     Fill BUFFER with LENGTH random bytes using a random quality as
-     defined by LEVEL.
-
- -- Function: void * gcry_random_bytes (size_t NBYTES, enum
-          gcry_random_level LEVEL)
-
-     Convenience function to allocate a memory block consisting of
-     NBYTES fresh random bytes using a random quality as defined by
-     LEVEL.
-
- -- Function: void * gcry_random_bytes_secure (size_t NBYTES, enum
-          gcry_random_level LEVEL)
-
-     Convenience function to allocate a memory block consisting of
-     NBYTES fresh random bytes using a random quality as defined by
-     LEVEL.  This function differs from 'gcry_random_bytes' in that the
-     returned buffer is allocated in a "secure" area of the memory.
-
- -- Function: void gcry_create_nonce (unsigned char *BUFFER, size_t
-          LENGTH)
-
-     Fill BUFFER with LENGTH unpredictable bytes.  This is commonly
-     called a nonce and may also be used for initialization vectors and
-     padding.  This is an extra function nearly independent of the other
-     random function for 3 reasons: It better protects the regular
-     random generator's internal state, provides better performance and
-     does not drain the precious entropy pool.
-
-\1f
-File: gcrypt.info,  Node: S-expressions,  Next: MPI library,  Prev: Random Numbers,  Up: Top
-
-11 S-expressions
-****************
-
-S-expressions are used by the public key functions to pass complex data
-structures around.  These LISP like objects are used by some
-cryptographic protocols (cf.  RFC-2692) and Libgcrypt provides functions
-to parse and construct them.  For detailed information, see 'Ron Rivest,
-code and description of S-expressions,
-<http://theory.lcs.mit.edu/~rivest/sexp.html>'.
-
-* Menu:
-
-* Data types for S-expressions::  Data types related with S-expressions.
-* Working with S-expressions::  How to work with S-expressions.
-
-\1f
-File: gcrypt.info,  Node: Data types for S-expressions,  Next: Working with S-expressions,  Up: S-expressions
-
-11.1 Data types for S-expressions
-=================================
-
- -- Data type: gcry_sexp_t
-     The 'gcry_sexp_t' type describes an object with the Libgcrypt
-     internal representation of an S-expression.
-
-\1f
-File: gcrypt.info,  Node: Working with S-expressions,  Prev: Data types for S-expressions,  Up: S-expressions
-
-11.2 Working with S-expressions
-===============================
-
-There are several functions to create an Libgcrypt S-expression object
-from its external representation or from a string template.  There is
-also a function to convert the internal representation back into one of
-the external formats:
-
- -- Function: gcry_error_t gcry_sexp_new (gcry_sexp_t *R_SEXP,
-          const void *BUFFER, size_t LENGTH, int AUTODETECT)
-
-     This is the generic function to create an new S-expression object
-     from its external representation in BUFFER of LENGTH bytes.  On
-     success the result is stored at the address given by R_SEXP.  With
-     AUTODETECT set to 0, the data in BUFFER is expected to be in
-     canonized format, with AUTODETECT set to 1 the parses any of the
-     defined external formats.  If BUFFER does not hold a valid
-     S-expression an error code is returned and R_SEXP set to 'NULL'.
-     Note that the caller is responsible for releasing the newly
-     allocated S-expression using 'gcry_sexp_release'.
-
- -- Function: gcry_error_t gcry_sexp_create (gcry_sexp_t *R_SEXP,
-          void *BUFFER, size_t LENGTH, int AUTODETECT,
-          void (*FREEFNC)(void*))
-
-     This function is identical to 'gcry_sexp_new' but has an extra
-     argument FREEFNC, which, when not set to 'NULL', is expected to be
-     a function to release the BUFFER; most likely the standard 'free'
-     function is used for this argument.  This has the effect of
-     transferring the ownership of BUFFER to the created object in
-     R_SEXP.  The advantage of using this function is that Libgcrypt
-     might decide to directly use the provided buffer and thus avoid
-     extra copying.
-
- -- Function: gcry_error_t gcry_sexp_sscan (gcry_sexp_t *R_SEXP,
-          size_t *ERROFF, const char *BUFFER, size_t LENGTH)
-
-     This is another variant of the above functions.  It behaves nearly
-     identical but provides an ERROFF argument which will receive the
-     offset into the buffer where the parsing stopped on error.
-
- -- Function: gcry_error_t gcry_sexp_build (gcry_sexp_t *R_SEXP,
-          size_t *ERROFF, const char *FORMAT, ...)
-
-     This function creates an internal S-expression from the string
-     template FORMAT and stores it at the address of R_SEXP.  If there
-     is a parsing error, the function returns an appropriate error code
-     and stores the offset into FORMAT where the parsing stopped in
-     ERROFF.  The function supports a couple of printf-like formatting
-     characters and expects arguments for some of these escape sequences
-     right after FORMAT.  The following format characters are defined:
-
-     '%m'
-          The next argument is expected to be of type 'gcry_mpi_t' and a
-          copy of its value is inserted into the resulting S-expression.
-          The MPI is stored as a signed integer.
-     '%M'
-          The next argument is expected to be of type 'gcry_mpi_t' and a
-          copy of its value is inserted into the resulting S-expression.
-          The MPI is stored as an unsigned integer.
-     '%s'
-          The next argument is expected to be of type 'char *' and that
-          string is inserted into the resulting S-expression.
-     '%d'
-          The next argument is expected to be of type 'int' and its
-          value is inserted into the resulting S-expression.
-     '%u'
-          The next argument is expected to be of type 'unsigned int' and
-          its value is inserted into the resulting S-expression.
-     '%b'
-          The next argument is expected to be of type 'int' directly
-          followed by an argument of type 'char *'.  This represents a
-          buffer of given length to be inserted into the resulting
-          S-expression.
-     '%S'
-          The next argument is expected to be of type 'gcry_sexp_t' and
-          a copy of that S-expression is embedded in the resulting
-          S-expression.  The argument needs to be a regular
-          S-expression, starting with a parenthesis.
-
-     No other format characters are defined and would return an error.
-     Note that the format character '%%' does not exists, because a
-     percent sign is not a valid character in an S-expression.
-
- -- Function: void gcry_sexp_release (gcry_sexp_t SEXP)
-
-     Release the S-expression object SEXP.  If the S-expression is
-     stored in secure memory it explicitly zeroises that memory; note
-     that this is done in addition to the zeroisation always done when
-     freeing secure memory.
-
-The next 2 functions are used to convert the internal representation
-back into a regular external S-expression format and to show the
-structure for debugging.
-
- -- Function: size_t gcry_sexp_sprint (gcry_sexp_t SEXP, int MODE,
-          char *BUFFER, size_t MAXLENGTH)
-
-     Copies the S-expression object SEXP into BUFFER using the format
-     specified in MODE.  MAXLENGTH must be set to the allocated length
-     of BUFFER.  The function returns the actual length of valid bytes
-     put into BUFFER or 0 if the provided buffer is too short.  Passing
-     'NULL' for BUFFER returns the required length for BUFFER.  For
-     convenience reasons an extra byte with value 0 is appended to the
-     buffer.
-
-     The following formats are supported:
-
-     'GCRYSEXP_FMT_DEFAULT'
-          Returns a convenient external S-expression representation.
-
-     'GCRYSEXP_FMT_CANON'
-          Return the S-expression in canonical format.
-
-     'GCRYSEXP_FMT_BASE64'
-          Not currently supported.
-
-     'GCRYSEXP_FMT_ADVANCED'
-          Returns the S-expression in advanced format.
-
- -- Function: void gcry_sexp_dump (gcry_sexp_t SEXP)
-
-     Dumps SEXP in a format suitable for debugging to Libgcrypt's
-     logging stream.
-
-Often canonical encoding is used in the external representation.  The
-following function can be used to check for valid encoding and to learn
-the length of the S-expression.
-
- -- Function: size_t gcry_sexp_canon_len (const unsigned char *BUFFER,
-          size_t LENGTH, size_t *ERROFF, int *ERRCODE)
-
-     Scan the canonical encoded BUFFER with implicit length values and
-     return the actual length this S-expression uses.  For a valid
-     S-expression it should never return 0.  If LENGTH is not 0, the
-     maximum length to scan is given; this can be used for syntax checks
-     of data passed from outside.  ERRCODE and ERROFF may both be passed
-     as 'NULL'.
-
-There are functions to parse S-expressions and retrieve elements:
-
- -- Function: gcry_sexp_t gcry_sexp_find_token (const gcry_sexp_t LIST,
-          const char *TOKEN, size_t TOKLEN)
-
-     Scan the S-expression for a sublist with a type (the car of the
-     list) matching the string TOKEN.  If TOKLEN is not 0, the token is
-     assumed to be raw memory of this length.  The function returns a
-     newly allocated S-expression consisting of the found sublist or
-     'NULL' when not found.
-
- -- Function: int gcry_sexp_length (const gcry_sexp_t LIST)
-
-     Return the length of the LIST.  For a valid S-expression this
-     should be at least 1.
-
- -- Function: gcry_sexp_t gcry_sexp_nth (const gcry_sexp_t LIST,
-          int NUMBER)
-
-     Create and return a new S-expression from the element with index
-     NUMBER in LIST.  Note that the first element has the index 0.  If
-     there is no such element, 'NULL' is returned.
-
- -- Function: gcry_sexp_t gcry_sexp_car (const gcry_sexp_t LIST)
-
-     Create and return a new S-expression from the first element in
-     LIST; this is called the "type" and should always exist per
-     S-expression specification and in general be a string.  'NULL' is
-     returned in case of a problem.
-
- -- Function: gcry_sexp_t gcry_sexp_cdr (const gcry_sexp_t LIST)
-
-     Create and return a new list form all elements except for the first
-     one.  Note that this function may return an invalid S-expression
-     because it is not guaranteed, that the type exists and is a string.
-     However, for parsing a complex S-expression it might be useful for
-     intermediate lists.  Returns 'NULL' on error.
-
- -- Function: const char * gcry_sexp_nth_data (const gcry_sexp_t LIST,
-          int NUMBER, size_t *DATALEN)
-
-     This function is used to get data from a LIST.  A pointer to the
-     actual data with index NUMBER is returned and the length of this
-     data will be stored to DATALEN.  If there is no data at the given
-     index or the index represents another list, 'NULL' is returned.
-     *Caution:* The returned pointer is valid as long as LIST is not
-     modified or released.
-
-     Here is an example on how to extract and print the surname (Meier)
-     from the S-expression '(Name Otto Meier (address Burgplatz 3))':
-
-          size_t len;
-          const char *name;
-
-          name = gcry_sexp_nth_data (list, 2, &len);
-          printf ("my name is %.*s\n", (int)len, name);
-
- -- Function: void * gcry_sexp_nth_buffer (const gcry_sexp_t LIST,
-          int NUMBER, size_t *RLENGTH)
-
-     This function is used to get data from a LIST.  A malloced buffer
-     with the actual data at list index NUMBER is returned and the
-     length of this buffer will be stored to RLENGTH.  If there is no
-     data at the given index or the index represents another list,
-     'NULL' is returned.  The caller must release the result using
-     'gcry_free'.
-
-     Here is an example on how to extract and print the CRC value from
-     the S-expression '(hash crc32 #23ed00d7)':
-
-          size_t len;
-          char *value;
-
-          value = gcry_sexp_nth_buffer (list, 2, &len);
-          if (value)
-            fwrite (value, len, 1, stdout);
-          gcry_free (value);
-
- -- Function: char * gcry_sexp_nth_string (gcry_sexp_t LIST, int NUMBER)
-
-     This function is used to get and convert data from a LIST.  The
-     data is assumed to be a Nul terminated string.  The caller must
-     release this returned value using 'gcry_free'.  If there is no data
-     at the given index, the index represents a list or the value can't
-     be converted to a string, 'NULL' is returned.
-
- -- Function: gcry_mpi_t gcry_sexp_nth_mpi (gcry_sexp_t LIST,
-          int NUMBER, int MPIFMT)
-
-     This function is used to get and convert data from a LIST.  This
-     data is assumed to be an MPI stored in the format described by
-     MPIFMT and returned as a standard Libgcrypt MPI. The caller must
-     release this returned value using 'gcry_mpi_release'.  If there is
-     no data at the given index, the index represents a list or the
-     value can't be converted to an MPI, 'NULL' is returned.  If you use
-     this function to parse results of a public key function, you most
-     likely want to use 'GCRYMPI_FMT_USG'.
-
- -- Function: gpg_error_t gcry_sexp_extract_param ( gcry_sexp_t SEXP,
-          const char *PATH, const char *LIST, ...)
-
-     Extract parameters from an S-expression using a list of parameter
-     names.  The names of these parameters are specified in LIST. White
-     space between the parameter names are ignored.  Some special
-     characters may be given to control the conversion:
-
-     '+'
-          Switch to unsigned integer format (GCRYMPI_FMT_USG). This is
-          the default mode.
-     '-'
-          Switch to standard signed format (GCRYMPI_FMT_STD).
-     '/'
-          Switch to opaque MPI format.  The resulting MPIs may not be
-          used for computations; see 'gcry_mpi_get_opaque' for details.
-     '&'
-          Switch to buffer descriptor mode.  See below for details.
-     '?'
-          If immediately following a parameter letter (no white space
-          allowed), that parameter is considered optional.
-
-     In general parameter names are single letters.  To use a string for
-     a parameter name, enclose the name in single quotes.
-
-     Unless in buffer descriptor mode for each parameter name a pointer
-     to an 'gcry_mpi_t' variable is expected that must be set to 'NULL'
-     prior to invoking this function, and finally a 'NULL' is expected.
-     For example
-
-            gcry_sexp_extract_param (key, NULL, "n/x+e d-'foo'",
-                                     &mpi_n, &mpi_x, &mpi_e, &mpi_d, &mpi_foo, NULL)
-
-     stores the parameter 'n' from KEY as an unsigned MPI into MPI_N,
-     the parameter 'x' as an opaque MPI into MPI_X, the parameters 'e'
-     and 'd' again as an unsigned MPI into MPI_E and MPI_D and finally
-     the parameter 'foo' as a signed MPI into MPI_FOO.
-
-     PATH is an optional string used to locate a token.  The exclamation
-     mark separated tokens are used via 'gcry_sexp_find_token' to find a
-     start point inside the S-expression.
-
-     In buffer descriptor mode a pointer to a 'gcry_buffer_t' descriptor
-     is expected instead of a pointer to an MPI. The caller may use two
-     different operation modes here: If the DATA field of the provided
-     descriptor is 'NULL', the function allocates a new buffer and
-     stores it at DATA; the other fields are set accordingly with OFF
-     set to 0.  If DATA is not 'NULL', the function assumes that the
-     DATA, SIZE, and OFF fields specify a buffer where to but the value
-     of the respective parameter; on return the LEN field receives the
-     number of bytes copied to that buffer; in case the buffer is too
-     small, the function immediately returns with an error code (and LEN
-     is set to 0).
-
-     The function returns 0 on success.  On error an error code is
-     returned, all passed MPIs that might have been allocated up to this
-     point are deallocated and set to 'NULL', and all passed buffers are
-     either truncated if the caller supplied the buffer, or deallocated
-     if the function allocated the buffer.
-
-\1f
-File: gcrypt.info,  Node: MPI library,  Next: Prime numbers,  Prev: S-expressions,  Up: Top
-
-12 MPI library
-**************
-
-* Menu:
-
-* Data types::                  MPI related data types.
-* Basic functions::             First steps with MPI numbers.
-* MPI formats::                 External representation of MPIs.
-* Calculations::                Performing MPI calculations.
-* Comparisons::                 How to compare MPI values.
-* Bit manipulations::           How to access single bits of MPI values.
-* EC functions::                Elliptic curve related functions.
-* Miscellaneous::               Miscellaneous MPI functions.
-
-Public key cryptography is based on mathematics with large numbers.  To
-implement the public key functions, a library for handling these large
-numbers is required.  Because of the general usefulness of such a
-library, its interface is exposed by Libgcrypt.  In the context of
-Libgcrypt and in most other applications, these large numbers are called
-MPIs (multi-precision-integers).
-
-\1f
-File: gcrypt.info,  Node: Data types,  Next: Basic functions,  Up: MPI library
-
-12.1 Data types
-===============
-
- -- Data type: gcry_mpi_t
-     This type represents an object to hold an MPI.
-
- -- Data type: gcry_mpi_point_t
-     This type represents an object to hold a point for elliptic curve
-     math.
-
-\1f
-File: gcrypt.info,  Node: Basic functions,  Next: MPI formats,  Prev: Data types,  Up: MPI library
-
-12.2 Basic functions
-====================
-
-To work with MPIs, storage must be allocated and released for the
-numbers.  This can be done with one of these functions:
-
- -- Function: gcry_mpi_t gcry_mpi_new (unsigned int NBITS)
-
-     Allocate a new MPI object, initialize it to 0 and initially
-     allocate enough memory for a number of at least NBITS.  This
-     pre-allocation is only a small performance issue and not actually
-     necessary because Libgcrypt automatically re-allocates the required
-     memory.
-
- -- Function: gcry_mpi_t gcry_mpi_snew (unsigned int NBITS)
-
-     This is identical to 'gcry_mpi_new' but allocates the MPI in the so
-     called "secure memory" which in turn will take care that all
-     derived values will also be stored in this "secure memory".  Use
-     this for highly confidential data like private key parameters.
-
- -- Function: gcry_mpi_t gcry_mpi_copy (const gcry_mpi_t A)
-
-     Create a new MPI as the exact copy of A but with the constant and
-     immutable flags cleared.
-
- -- Function: void gcry_mpi_release (gcry_mpi_t A)
-
-     Release the MPI A and free all associated resources.  Passing
-     'NULL' is allowed and ignored.  When a MPI stored in the "secure
-     memory" is released, that memory gets wiped out immediately.
-
-The simplest operations are used to assign a new value to an MPI:
-
- -- Function: gcry_mpi_t gcry_mpi_set (gcry_mpi_t W, const gcry_mpi_t U)
-
-     Assign the value of U to W and return W.  If 'NULL' is passed for
-     W, a new MPI is allocated, set to the value of U and returned.
-
- -- Function: gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t W, unsigned long U)
-
-     Assign the value of U to W and return W.  If 'NULL' is passed for
-     W, a new MPI is allocated, set to the value of U and returned.
-     This function takes an 'unsigned int' as type for U and thus it is
-     only possible to set W to small values (usually up to the word size
-     of the CPU).
-
- -- Function: void gcry_mpi_swap (gcry_mpi_t A, gcry_mpi_t B)
-
-     Swap the values of A and B.
-
- -- Function: void gcry_mpi_snatch (gcry_mpi_t W, const gcry_mpi_t U)
-
-     Set U into W and release U.  If W is 'NULL' only U will be
-     released.
-
- -- Function: void gcry_mpi_neg (gcry_mpi_t W, gcry_mpi_t U)
-
-     Set the sign of W to the negative of U.
-
- -- Function: void gcry_mpi_abs (gcry_mpi_t W)
-
-     Clear the sign of W.
-
-\1f
-File: gcrypt.info,  Node: MPI formats,  Next: Calculations,  Prev: Basic functions,  Up: MPI library
-
-12.3 MPI formats
-================
-
-The following functions are used to convert between an external
-representation of an MPI and the internal one of Libgcrypt.
-
- -- Function: gcry_error_t gcry_mpi_scan (gcry_mpi_t *R_MPI,
-          enum gcry_mpi_format FORMAT, const unsigned char *BUFFER,
-          size_t BUFLEN, size_t *NSCANNED)
-
-     Convert the external representation of an integer stored in BUFFER
-     with a length of BUFLEN into a newly created MPI returned which
-     will be stored at the address of R_MPI.  For certain formats the
-     length argument is not required and should be passed as '0'.  A
-     BUFLEN larger than 16 MiByte will be rejected.  After a successful
-     operation the variable NSCANNED receives the number of bytes
-     actually scanned unless NSCANNED was given as 'NULL'.  FORMAT
-     describes the format of the MPI as stored in BUFFER:
-
-     'GCRYMPI_FMT_STD'
-          2-complement stored without a length header.  Note that
-          'gcry_mpi_print' stores a '0' as a string of zero length.
-
-     'GCRYMPI_FMT_PGP'
-          As used by OpenPGP (only defined as unsigned).  This is
-          basically 'GCRYMPI_FMT_STD' with a 2 byte big endian length
-          header.  A length header indicating a length of more than
-          16384 is not allowed.
-
-     'GCRYMPI_FMT_SSH'
-          As used in the Secure Shell protocol.  This is
-          'GCRYMPI_FMT_STD' with a 4 byte big endian header.
-
-     'GCRYMPI_FMT_HEX'
-          Stored as a string with each byte of the MPI encoded as 2 hex
-          digits.  Negative numbers are prefix with a minus sign and in
-          addition the high bit is always zero to make clear that an
-          explicit sign ist used.  When using this format, BUFLEN must
-          be zero.
-
-     'GCRYMPI_FMT_USG'
-          Simple unsigned integer.
-
-     Note that all of the above formats store the integer in big-endian
-     format (MSB first).
-
- -- Function: gcry_error_t gcry_mpi_print (enum gcry_mpi_format FORMAT,
-          unsigned char *BUFFER, size_t BUFLEN, size_t *NWRITTEN,
-          const gcry_mpi_t A)
-
-     Convert the MPI A into an external representation described by
-     FORMAT (see above) and store it in the provided BUFFER which has a
-     usable length of at least the BUFLEN bytes.  If NWRITTEN is not
-     NULL, it will receive the number of bytes actually stored in BUFFER
-     after a successful operation.
-
- -- Function: gcry_error_t gcry_mpi_aprint (enum gcry_mpi_format FORMAT,
-          unsigned char **BUFFER, size_t *NBYTES, const gcry_mpi_t A)
-
-     Convert the MPI A into an external representation described by
-     FORMAT (see above) and store it in a newly allocated buffer which
-     address will be stored in the variable BUFFER points to.  The
-     number of bytes stored in this buffer will be stored in the
-     variable NBYTES points to, unless NBYTES is 'NULL'.
-
-     Even if NBYTES is zero, the function allocates at least one byte
-     and store a zero there.  Thus with formats 'GCRYMPI_FMT_STD' and
-     'GCRYMPI_FMT_USG' the caller may safely set a returned length of 0
-     to 1 to represent a zero as a 1 byte string.
-
- -- Function: void gcry_mpi_dump (const gcry_mpi_t A)
-
-     Dump the value of A in a format suitable for debugging to
-     Libgcrypt's logging stream.  Note that one leading space but no
-     trailing space or linefeed will be printed.  It is okay to pass
-     'NULL' for A.
-
-\1f
-File: gcrypt.info,  Node: Calculations,  Next: Comparisons,  Prev: MPI formats,  Up: MPI library
-
-12.4 Calculations
-=================
-
-Basic arithmetic operations:
-
- -- Function: void gcry_mpi_add (gcry_mpi_t W, gcry_mpi_t U,
-          gcry_mpi_t V)
-
-     W = U + V.
-
- -- Function: void gcry_mpi_add_ui (gcry_mpi_t W, gcry_mpi_t U,
-          unsigned long V)
-
-     W = U + V.  Note that V is an unsigned integer.
-
- -- Function: void gcry_mpi_addm (gcry_mpi_t W, gcry_mpi_t U,
-          gcry_mpi_t V, gcry_mpi_t M)
-
-     W = U + V \bmod M.
-
- -- Function: void gcry_mpi_sub (gcry_mpi_t W, gcry_mpi_t U,
-          gcry_mpi_t V)
-
-     W = U - V.
-
- -- Function: void gcry_mpi_sub_ui (gcry_mpi_t W, gcry_mpi_t U,
-          unsigned long V)
-
-     W = U - V.  V is an unsigned integer.
-
- -- Function: void gcry_mpi_subm (gcry_mpi_t W, gcry_mpi_t U,
-          gcry_mpi_t V, gcry_mpi_t M)
-
-     W = U - V \bmod M.
-
- -- Function: void gcry_mpi_mul (gcry_mpi_t W, gcry_mpi_t U,
-          gcry_mpi_t V)
-
-     W = U * V.
-
- -- Function: void gcry_mpi_mul_ui (gcry_mpi_t W, gcry_mpi_t U,
-          unsigned long V)
-
-     W = U * V.  V is an unsigned integer.
-
- -- Function: void gcry_mpi_mulm (gcry_mpi_t W, gcry_mpi_t U,
-          gcry_mpi_t V, gcry_mpi_t M)
-
-     W = U * V \bmod M.
-
- -- Function: void gcry_mpi_mul_2exp (gcry_mpi_t W, gcry_mpi_t U,
-          unsigned long E)
-
-     W = U * 2^e.
-
- -- Function: void gcry_mpi_div (gcry_mpi_t Q, gcry_mpi_t R,
-          gcry_mpi_t DIVIDEND, gcry_mpi_t DIVISOR, int ROUND)
-
-     Q = DIVIDEND / DIVISOR, R = DIVIDEND \bmod DIVISOR.  Q and R may be
-     passed as 'NULL'.  ROUND should be negative or 0.
-
- -- Function: void gcry_mpi_mod (gcry_mpi_t R, gcry_mpi_t DIVIDEND,
-          gcry_mpi_t DIVISOR)
-
-     R = DIVIDEND \bmod DIVISOR.
-
- -- Function: void gcry_mpi_powm (gcry_mpi_t W, const gcry_mpi_t B,
-          const gcry_mpi_t E, const gcry_mpi_t M)
-
-     W = B^e \bmod M.
-
- -- Function: int gcry_mpi_gcd (gcry_mpi_t G, gcry_mpi_t A,
-          gcry_mpi_t B)
-
-     Set G to the greatest common divisor of A and B.  Return true if
-     the G is 1.
-
- -- Function: int gcry_mpi_invm (gcry_mpi_t X, gcry_mpi_t A,
-          gcry_mpi_t M)
-
-     Set X to the multiplicative inverse of A \bmod M.  Return true if
-     the inverse exists.
-
-\1f
-File: gcrypt.info,  Node: Comparisons,  Next: Bit manipulations,  Prev: Calculations,  Up: MPI library
-
-12.5 Comparisons
-================
-
-The next 2 functions are used to compare MPIs:
-
- -- Function: int gcry_mpi_cmp (const gcry_mpi_t U, const gcry_mpi_t V)
-
-     Compare the multi-precision-integers number U and V returning 0 for
-     equality, a positive value for U > V and a negative for U < V.  If
-     both numbers are opaque values (cf, gcry_mpi_set_opaque) the
-     comparison is done by checking the bit sizes using memcmp.  If only
-     one number is an opaque value, the opaque value is less than the
-     other number.
-
- -- Function: int gcry_mpi_cmp_ui (const gcry_mpi_t U, unsigned long V)
-
-     Compare the multi-precision-integers number U with the unsigned
-     integer V returning 0 for equality, a positive value for U > V and
-     a negative for U < V.
-
- -- Function: int gcry_mpi_is_neg (const gcry_mpi_t A)
-
-     Return 1 if A is less than zero; return 0 if zero or positive.
-
-\1f
-File: gcrypt.info,  Node: Bit manipulations,  Next: EC functions,  Prev: Comparisons,  Up: MPI library
-
-12.6 Bit manipulations
-======================
-
-There are a couple of functions to get information on arbitrary bits in
-an MPI and to set or clear them:
-
- -- Function: unsigned int gcry_mpi_get_nbits (gcry_mpi_t A)
-
-     Return the number of bits required to represent A.
-
- -- Function: int gcry_mpi_test_bit (gcry_mpi_t A, unsigned int N)
-
-     Return true if bit number N (counting from 0) is set in A.
-
- -- Function: void gcry_mpi_set_bit (gcry_mpi_t A, unsigned int N)
-
-     Set bit number N in A.
-
- -- Function: void gcry_mpi_clear_bit (gcry_mpi_t A, unsigned int N)
-
-     Clear bit number N in A.
-
- -- Function: void gcry_mpi_set_highbit (gcry_mpi_t A, unsigned int N)
-
-     Set bit number N in A and clear all bits greater than N.
-
- -- Function: void gcry_mpi_clear_highbit (gcry_mpi_t A, unsigned int N)
-
-     Clear bit number N in A and all bits greater than N.
-
- -- Function: void gcry_mpi_rshift (gcry_mpi_t X, gcry_mpi_t A,
-          unsigned int N)
-
-     Shift the value of A by N bits to the right and store the result in
-     X.
-
- -- Function: void gcry_mpi_lshift (gcry_mpi_t X, gcry_mpi_t A,
-          unsigned int N)
-
-     Shift the value of A by N bits to the left and store the result in
-     X.
-
-\1f
-File: gcrypt.info,  Node: EC functions,  Next: Miscellaneous,  Prev: Bit manipulations,  Up: MPI library
-
-12.7 EC functions
-=================
-
-Libgcrypt provides an API to access low level functions used by its
-elliptic curve implementation.  These functions allow to implement
-elliptic curve methods for which no explicit support is available.
-
- -- Function: gcry_mpi_point_t gcry_mpi_point_new (unsigned int NBITS)
-
-     Allocate a new point object, initialize it to 0, and allocate
-     enough memory for a points of at least NBITS.  This pre-allocation
-     yields only a small performance win and is not really necessary
-     because Libgcrypt automatically re-allocates the required memory.
-     Using 0 for NBITS is usually the right thing to do.
-
- -- Function: void gcry_mpi_point_release (gcry_mpi_point_t POINT)
-
-     Release POINT and free all associated resources.  Passing 'NULL' is
-     allowed and ignored.
-
- -- Function: gcry_mpi_point_t gcry_mpi_point_copy
-          (gcry_mpi_point_t POINT)
-
-     Allocate and return a new point object and initialize it with
-     POINT.  If POINT is NULL the function is identical to
-     'gcry_mpi_point_new(0)'.
-
- -- Function: void gcry_mpi_point_get (gcry_mpi_t X, gcry_mpi_t Y,
-          gcry_mpi_t Z, gcry_mpi_point_t POINT)
-
-     Store the projective coordinates from POINT into the MPIs X, Y, and
-     Z.  If a coordinate is not required, 'NULL' may be used for X, Y,
-     or Z.
-
- -- Function: void gcry_mpi_point_snatch_get (gcry_mpi_t X,
-          gcry_mpi_t Y, gcry_mpi_t Z, gcry_mpi_point_t POINT)
-
-     Store the projective coordinates from POINT into the MPIs X, Y, and
-     Z.  If a coordinate is not required, 'NULL' may be used for X, Y,
-     or Z.  The object POINT is then released.  Using this function
-     instead of 'gcry_mpi_point_get' and 'gcry_mpi_point_release' has
-     the advantage of avoiding some extra memory allocations and copies.
-
- -- Function: gcry_mpi_point_t gcry_mpi_point_set (
-          gcry_mpi_point_t POINT, gcry_mpi_t X, gcry_mpi_t Y,
-          gcry_mpi_t Z)
-
-     Store the projective coordinates from X, Y, and Z into POINT.  If a
-     coordinate is given as 'NULL', the value 0 is used.  If 'NULL' is
-     used for POINT a new point object is allocated and returned.
-     Returns POINT or the newly allocated point object.
-
- -- Function: gcry_mpi_point_t gcry_mpi_point_snatch_set (
-          gcry_mpi_point_t POINT, gcry_mpi_t X, gcry_mpi_t Y,
-          gcry_mpi_t Z)
-
-     Store the projective coordinates from X, Y, and Z into POINT.  If a
-     coordinate is given as 'NULL', the value 0 is used.  If 'NULL' is
-     used for POINT a new point object is allocated and returned.  The
-     MPIs X, Y, and Z are released.  Using this function instead of
-     'gcry_mpi_point_set' and 3 calls to 'gcry_mpi_release' has the
-     advantage of avoiding some extra memory allocations and copies.
-     Returns POINT or the newly allocated point object.
-
- -- Function: gpg_error_t gcry_mpi_ec_new (gcry_ctx_t *R_CTX,
-          gcry_sexp_t KEYPARAM, const char *CURVENAME)
-
-     Allocate a new context for elliptic curve operations.  If KEYPARAM
-     is given it specifies the parameters of the curve (*note
-     ecc_keyparam::).  If CURVENAME is given in addition to KEYPARAM and
-     the key parameters do not include a named curve reference, the
-     string CURVENAME is used to fill in missing parameters.  If only
-     CURVENAME is given, the context is initialized for this named
-     curve.
-
-     If a parameter specifying a point (e.g.  'g' or 'q') is not found,
-     the parser looks for a non-encoded point by appending '.x', '.y',
-     and '.z' to the parameter name and looking them all up to create a
-     point.  A parameter with the suffix '.z' is optional and defaults
-     to 1.
-
-     On success the function returns 0 and stores the new context object
-     at R_CTX; this object eventually needs to be released (*note
-     gcry_ctx_release::).  On error the function stores 'NULL' at R_CTX
-     and returns an error code.
-
- -- Function: gcry_mpi_t gcry_mpi_ec_get_mpi ( const char *NAME,
-          gcry_ctx_t CTX, int COPY)
-
-     Return the MPI with NAME from the context CTX.  If not found 'NULL'
-     is returned.  If the returned MPI may later be modified, it is
-     suggested to pass '1' to COPY, so that the function guarantees that
-     a modifiable copy of the MPI is returned.  If '0' is used for COPY,
-     this function may return a constant flagged MPI. In any case
-     'gcry_mpi_release' needs to be called to release the result.  For
-     valid names *note ecc_keyparam::.  If the public key 'q' is
-     requested but only the private key 'd' is available, 'q' will be
-     recomputed on the fly.  If a point parameter is requested it is
-     returned as an uncompressed encoded point unless these special
-     names are used:
-     Q@EDDSA
-          Return an EdDSA style compressed point.  This is only
-          supported for Twisted Edwards curves.
-
- -- Function: gcry_mpi_point_t gcry_mpi_ec_get_point ( const char *NAME,
-          gcry_ctx_t CTX, int COPY)
-
-     Return the point with NAME from the context CTX.  If not found
-     'NULL' is returned.  If the returned MPI may later be modified, it
-     is suggested to pass '1' to COPY, so that the function guarantees
-     that a modifiable copy of the MPI is returned.  If '0' is used for
-     COPY, this function may return a constant flagged point.  In any
-     case 'gcry_mpi_point_release' needs to be called to release the
-     result.  If the public key 'q' is requested but only the private
-     key 'd' is available, 'q' will be recomputed on the fly.
-
- -- Function: gpg_error_t gcry_mpi_ec_set_mpi ( const char *NAME,
-          gcry_mpi_t NEWVALUE, gcry_ctx_t CTX)
-
-     Store the MPI NEWVALUE at NAME into the context CTX.  On success
-     '0' is returned; on error an error code.  Valid names are the MPI
-     parameters of an elliptic curve (*note ecc_keyparam::).
-
- -- Function: gpg_error_t gcry_mpi_ec_set_point ( const char *NAME,
-          gcry_mpi_point_t NEWVALUE, gcry_ctx_t CTX)
-
-     Store the point NEWVALUE at NAME into the context CTX.  On success
-     '0' is returned; on error an error code.  Valid names are the point
-     parameters of an elliptic curve (*note ecc_keyparam::).
-
- -- Function: gpg_err_code_t gcry_mpi_ec_decode_point (
-          mpi_point_t RESULT, gcry_mpi_t VALUE, gcry_ctx_t CTX)
-
-     Decode the point given as an MPI in VALUE and store at RESULT.  To
-     decide which encoding is used the function takes a context CTX
-     which can be created with 'gcry_mpi_ec_new'.  If 'NULL' is given
-     for the context the function assumes a 0x04 prefixed uncompressed
-     encoding.  On error an error code is returned and RESULT might be
-     changed.
-
- -- Function: int gcry_mpi_ec_get_affine ( gcry_mpi_t X, gcry_mpi_t Y,
-          gcry_mpi_point_t POINT, gcry_ctx_t CTX)
-
-     Compute the affine coordinates from the projective coordinates in
-     POINT and store them into X and Y.  If one coordinate is not
-     required, 'NULL' may be passed to X or Y.  CTX is the context
-     object which has been created using 'gcry_mpi_ec_new'.  Returns 0
-     on success or not 0 if POINT is at infinity.
-
-     Note that you can use 'gcry_mpi_ec_set_point' with the value
-     'GCRYMPI_CONST_ONE' for Z to convert affine coordinates back into
-     projective coordinates.
-
- -- Function: void gcry_mpi_ec_dup ( gcry_mpi_point_t W,
-          gcry_mpi_point_t U, gcry_ctx_t CTX)
-
-     Double the point U of the elliptic curve described by CTX and store
-     the result into W.
-
- -- Function: void gcry_mpi_ec_add ( gcry_mpi_point_t W,
-          gcry_mpi_point_t U, gcry_mpi_point_t V, gcry_ctx_t CTX)
-
-     Add the points U and V of the elliptic curve described by CTX and
-     store the result into W.
-
- -- Function: void gcry_mpi_ec_sub ( gcry_mpi_point_t W,
-          gcry_mpi_point_t U, gcry_mpi_point_t V, gcry_ctx_t CTX)
-
-     Subtracts the point V from the point U of the elliptic curve
-     described by CTX and store the result into W.  Only Twisted Edwards
-     curves are supported for now.
-
- -- Function: void gcry_mpi_ec_mul ( gcry_mpi_point_t W, gcry_mpi_t N,
-          gcry_mpi_point_t U, gcry_ctx_t CTX)
-
-     Multiply the point U of the elliptic curve described by CTX by N
-     and store the result into W.
-
- -- Function: int gcry_mpi_ec_curve_point ( gcry_mpi_point_t POINT,
-          gcry_ctx_t CTX)
-
-     Return true if POINT is on the elliptic curve described by CTX.
-
-\1f
-File: gcrypt.info,  Node: Miscellaneous,  Prev: EC functions,  Up: MPI library
-
-12.8 Miscellaneous
-==================
-
-An MPI data type is allowed to be "misused" to store an arbitrary value.
-Two functions implement this kludge:
-
- -- Function: gcry_mpi_t gcry_mpi_set_opaque (gcry_mpi_t A, void *P,
-          unsigned int NBITS)
-
-     Store NBITS of the value P points to in A and mark A as an opaque
-     value (i.e.  an value that can't be used for any math calculation
-     and is only used to store an arbitrary bit pattern in A).
-     Ownership of P is taken by this function and thus the user may not
-     use dereference the passed value anymore.  It is required that them
-     memory referenced by P has been allocated in a way that 'gcry_free'
-     is able to release it.
-
-     WARNING: Never use an opaque MPI for actual math operations.  The
-     only valid functions are gcry_mpi_get_opaque and gcry_mpi_release.
-     Use gcry_mpi_scan to convert a string of arbitrary bytes into an
-     MPI.
-
- -- Function: gcry_mpi_t gcry_mpi_set_opaque_copy (gcry_mpi_t A,
-          const void *P, unsigned int NBITS)
-
-     Same as 'gcry_mpi_set_opaque' but ownership of P is not taken
-     instead a copy of P is used.
-
- -- Function: void * gcry_mpi_get_opaque (gcry_mpi_t A,
-          unsigned int *NBITS)
-
-     Return a pointer to an opaque value stored in A and return its size
-     in NBITS.  Note that the returned pointer is still owned by A and
-     that the function should never be used for an non-opaque MPI.
-
-   Each MPI has an associated set of flags for special purposes.  The
-currently defined flags are:
-
-'GCRYMPI_FLAG_SECURE'
-     Setting this flag converts A into an MPI stored in "secure memory".
-     Clearing this flag is not allowed.
-'GCRYMPI_FLAG_OPAQUE'
-     This is an interanl flag, indicating the an opaque valuue and not
-     an integer is stored.  This is an read-only flag; it may not be set
-     or cleared.
-'GCRYMPI_FLAG_IMMUTABLE'
-     If this flag is set, the MPI is marked as immutable.  Setting or
-     changing the value of that MPI is ignored and an error message is
-     logged.  The flag is sometimes useful for debugging.
-'GCRYMPI_FLAG_CONST'
-     If this flag is set, the MPI is marked as a constant and as
-     immutable Setting or changing the value of that MPI is ignored and
-     an error message is logged.  Such an MPI will never be deallocated
-     and may thus be used without copying.  Note that using
-     gcry_mpi_copy will return a copy of that constant with this and the
-     immutable flag cleared.  A few commonly used constants are
-     pre-defined and accessible using the macros 'GCRYMPI_CONST_ONE',
-     'GCRYMPI_CONST_TWO', 'GCRYMPI_CONST_THREE', 'GCRYMPI_CONST_FOUR',
-     and 'GCRYMPI_CONST_EIGHT'.
-'GCRYMPI_FLAG_USER1'
-'GCRYMPI_FLAG_USER2'
-'GCRYMPI_FLAG_USER3'
-'GCRYMPI_FLAG_USER4'
-     These flags are reserved for use by the application.
-
- -- Function: void gcry_mpi_set_flag (gcry_mpi_t A,
-          enum gcry_mpi_flag FLAG)
-
-     Set the FLAG for the MPI A.  The only allowed flags are
-     'GCRYMPI_FLAG_SECURE', 'GCRYMPI_FLAG_IMMUTABLE', and
-     'GCRYMPI_FLAG_CONST'.
-
- -- Function: void gcry_mpi_clear_flag (gcry_mpi_t A,
-          enum gcry_mpi_flag FLAG)
-
-     Clear FLAG for the multi-precision-integers A.  The only allowed
-     flag is 'GCRYMPI_FLAG_IMMUTABLE' but only if 'GCRYMPI_FLAG_CONST'
-     is not set.  If 'GCRYMPI_FLAG_CONST' is set, clearing
-     'GCRYMPI_FLAG_IMMUTABLE' will simply be ignored.
-   o
- -- Function: int gcry_mpi_get_flag (gcry_mpi_t A,
-          enum gcry_mpi_flag FLAG)
-
-     Return true if FLAG is set for A.
-
-   To put a random value into an MPI, the following convenience function
-may be used:
-
- -- Function: void gcry_mpi_randomize (gcry_mpi_t W, unsigned int NBITS,
-          enum gcry_random_level LEVEL)
-
-     Set the multi-precision-integers W to a random non-negative number
-     of NBITS, using random data quality of level LEVEL.  In case NBITS
-     is not a multiple of a byte, NBITS is rounded up to the next byte
-     boundary.  When using a LEVEL of 'GCRY_WEAK_RANDOM' this function
-     makes use of 'gcry_create_nonce'.
-
-\1f
-File: gcrypt.info,  Node: Prime numbers,  Next: Utilities,  Prev: MPI library,  Up: Top
-
-13 Prime numbers
-****************
-
-* Menu:
-
-* Generation::                  Generation of new prime numbers.
-* Checking::                    Checking if a given number is prime.
-
-\1f
-File: gcrypt.info,  Node: Generation,  Next: Checking,  Up: Prime numbers
-
-13.1 Generation
-===============
-
- -- Function: gcry_error_t gcry_prime_generate (gcry_mpi_t
-          *PRIME,unsigned int PRIME_BITS, unsigned int FACTOR_BITS,
-          gcry_mpi_t **FACTORS, gcry_prime_check_func_t CB_FUNC, void
-          *CB_ARG, gcry_random_level_t RANDOM_LEVEL, unsigned int FLAGS)
-
-     Generate a new prime number of PRIME_BITS bits and store it in
-     PRIME.  If FACTOR_BITS is non-zero, one of the prime factors of
-     (PRIME - 1) / 2 must be FACTOR_BITS bits long.  If FACTORS is
-     non-zero, allocate a new, 'NULL'-terminated array holding the prime
-     factors and store it in FACTORS.  FLAGS might be used to influence
-     the prime number generation process.
-
- -- Function: gcry_error_t gcry_prime_group_generator (gcry_mpi_t *R_G,
-          gcry_mpi_t PRIME, gcry_mpi_t *FACTORS, gcry_mpi_t START_G)
-
-     Find a generator for PRIME where the factorization of (PRIME-1) is
-     in the 'NULL' terminated array FACTORS.  Return the generator as a
-     newly allocated MPI in R_G.  If START_G is not NULL, use this as
-     the start for the search.
-
- -- Function: void gcry_prime_release_factors (gcry_mpi_t *FACTORS)
-
-     Convenience function to release the FACTORS array.
-
-\1f
-File: gcrypt.info,  Node: Checking,  Prev: Generation,  Up: Prime numbers
-
-13.2 Checking
-=============
-
- -- Function: gcry_error_t gcry_prime_check (gcry_mpi_t P, unsigned int
-          FLAGS)
-
-     Check whether the number P is prime.  Returns zero in case P is
-     indeed a prime, returns 'GPG_ERR_NO_PRIME' in case P is not a prime
-     and a different error code in case something went horribly wrong.
-
-\1f
-File: gcrypt.info,  Node: Utilities,  Next: Tools,  Prev: Prime numbers,  Up: Top
-
-14 Utilities
-************
-
-* Menu:
-
-* Memory allocation::   Functions related with memory allocation.
-* Context management::  Functions related with context management.
-* Buffer description::  A data type to describe buffers.
-* Config reporting::    How to return Libgcrypt's configuration.
-
-\1f
-File: gcrypt.info,  Node: Memory allocation,  Next: Context management,  Up: Utilities
-
-14.1 Memory allocation
-======================
-
- -- Function: void * gcry_malloc (size_t N)
-
-     This function tries to allocate N bytes of memory.  On success it
-     returns a pointer to the memory area, in an out-of-core condition,
-     it returns NULL.
-
- -- Function: void * gcry_malloc_secure (size_t N)
-     Like 'gcry_malloc', but uses secure memory.
-
- -- Function: void * gcry_calloc (size_t N, size_t M)
-
-     This function allocates a cleared block of memory (i.e.
-     initialized with zero bytes) long enough to contain a vector of N
-     elements, each of size M bytes.  On success it returns a pointer to
-     the memory block; in an out-of-core condition, it returns NULL.
-
- -- Function: void * gcry_calloc_secure (size_t N, size_t M)
-     Like 'gcry_calloc', but uses secure memory.
-
- -- Function: void * gcry_realloc (void *P, size_t N)
-
-     This function tries to resize the memory area pointed to by P to N
-     bytes.  On success it returns a pointer to the new memory area, in
-     an out-of-core condition, it returns NULL. Depending on whether the
-     memory pointed to by P is secure memory or not, gcry_realloc tries
-     to use secure memory as well.
-
- -- Function: void gcry_free (void *P)
-     Release the memory area pointed to by P.
-
-\1f
-File: gcrypt.info,  Node: Context management,  Next: Buffer description,  Prev: Memory allocation,  Up: Utilities
-
-14.2 Context management
-=======================
-
-Some function make use of a context object.  As of now there are only a
-few math functions.  However, future versions of Libgcrypt may make more
-use of this context object.
-
- -- Data type: gcry_ctx_t
-     This type is used to refer to the general purpose context object.
-
- -- Function: void gcry_ctx_release (gcry_ctx_t CTX)
-     Release the context object CTX and all associated resources.  A
-     'NULL' passed as CTX is ignored.
-
-\1f
-File: gcrypt.info,  Node: Buffer description,  Next: Config reporting,  Prev: Context management,  Up: Utilities
-
-14.3 Buffer description
-=======================
-
-To help hashing non-contiguous areas of memory a general purpose data
-type is defined:
-
- -- Data type: gcry_buffer_t
-     This type is a structure to describe a buffer.  The user should
-     make sure that this structure is initialized to zero.  The
-     available fields of this structure are:
-
-     '.size'
-          This is either 0 for no information available or indicates the
-          allocated length of the buffer.
-     '.off'
-          This is the offset into the buffer.
-     '.len'
-          This is the valid length of the buffer starting at '.off'.
-     '.data'
-          This is the address of the buffer.
-
-\1f
-File: gcrypt.info,  Node: Config reporting,  Prev: Buffer description,  Up: Utilities
-
-14.4 How to return Libgcrypt's configuration.
-=============================================
-
-Although 'GCRYCTL_PRINT_CONFIG' can be used to print configuration
-options, it is sometimes necessary to check them in a program.  This can
-be accomplished by using this function:
-
- -- Function: char * gcry_get_config (int MODE, const char *WHAT)
-
-     This function returns a malloced string with colon delimited
-     configure options.  With a value of 0 for MODE this string
-     resembles the output of 'GCRYCTL_PRINT_CONFIG'.  However, if WHAT
-     is not NULL, only the line where the first field (e.g.  "cpu-arch")
-     matches WHAT is returned.
-
-     Other values than 0 for MODE are not defined.  The caller shall
-     free the string using 'gcry_free'.  On error NULL is returned and
-     ERRNO is set; if a value for WHAT is unknow ERRNO will be set to 0.
-
-\1f
-File: gcrypt.info,  Node: Tools,  Next: Configuration,  Prev: Utilities,  Up: Top
-
-15 Tools
-********
-
-* Menu:
-
-* hmac256:: A standalone HMAC-SHA-256 implementation
-
-\1f
-File: gcrypt.info,  Node: hmac256,  Up: Tools
-
-15.1 A HMAC-SHA-256 tool
-========================
-
-This is a standalone HMAC-SHA-256 implementation used to compute an
-HMAC-SHA-256 message authentication code.  The tool has originally been
-developed as a second implementation for Libgcrypt to allow comparing
-against the primary implementation and to be used for internal
-consistency checks.  It should not be used for sensitive data because no
-mechanisms to clear the stack etc are used.
-
-   The code has been written in a highly portable manner and requires
-only a few standard definitions to be provided in a config.h file.
-
-'hmac256' is commonly invoked as
-
-     hmac256 "This is my key" foo.txt
-
-This compute the MAC on the file 'foo.txt' using the key given on the
-command line.
-
-'hmac256' understands these options:
-
-'--binary'
-     Print the MAC as a binary string.  The default is to print the MAC
-     encoded has lower case hex digits.
-
-'--version'
-     Print version of the program and exit.
-
-\1f
-File: gcrypt.info,  Node: Configuration,  Next: Architecture,  Prev: Tools,  Up: Top
-
-16 Configuration files and environment variables
-************************************************
-
-This chapter describes which files and environment variables can be used
-to change the behaviour of Libgcrypt.
-
-The environment variables considered by Libgcrypt are:
-
-'GCRYPT_BARRETT'
-     By setting this variable to any value a different algorithm for
-     modular reduction is used for ECC.
-
-'GCRYPT_RNDUNIX_DBG'
-'GCRYPT_RNDUNIX_DBGALL'
-     These two environment variables are used to enable debug output for
-     the rndunix entropy gatherer, which is used on systems lacking a
-     /dev/random device.  The value of 'GCRYPT_RNDUNIX_DBG' is a file
-     name or '-' for stdout.  Debug output is the written to this file.
-     By setting 'GCRYPT_RNDUNIX_DBGALL' to any value the debug output
-     will be more verbose.
-
-'GCRYPT_RNDW32_NOPERF'
-     Setting this environment variable on Windows to any value disables
-     the use of performance data ('HKEY_PERFORMANCE_DATA') as source for
-     entropy.  On some older Windows systems this could help to speed up
-     the creation of random numbers but also decreases the amount of
-     data used to init the random number generator.
-
-'GCRYPT_RNDW32_DBG'
-     Setting the value of this variable to a positive integer logs
-     information about the Windows entropy gatherer using the standard
-     log interface.
-
-'HOME'
-     This is used to locate the socket to connect to the EGD random
-     daemon.  The EGD can be used on system without a /dev/random to
-     speed up the random number generator.  It is not needed on the
-     majority of today's operating systems and support for EGD requires
-     the use of a configure option at build time.
-
-The files which Libgcrypt uses to retrieve system information and the
-files which can be created by the user to modify Libgcrypt's behavior
-are:
-
-'/etc/gcrypt/hwf.deny'
-     This file can be used to disable the use of hardware based
-     optimizations, *note hardware features::.
-
-'/etc/gcrypt/random.conf'
-     This file can be used to globally change parameters of the random
-     generator.  The file is a simple text file where empty lines and
-     lines with the first non white-space character being '#' are
-     ignored.  Supported options are
-
-     'disable-jent'
-          Disable the use of the jitter based entropy generator.
-
-     'only-urandom'
-          Always use the non-blocking /dev/urandom or the respective
-          system call instead of the blocking /dev/random.  If Libgcrypt
-          is used early in the boot process of the system, this option
-          should only be used if the system also supports the getrandom
-          system call.
-
-'/etc/gcrypt/fips_enabled'
-'/proc/sys/crypto/fips_enabled'
-     On Linux these files are used to enable FIPS mode, *note enabling
-     fips mode::.
-
-'/proc/cpuinfo'
-'/proc/self/auxv'
-     On Linux running on the ARM architecture, these files are used to
-     read hardware capabilities of the CPU.
-
-\1f
-File: gcrypt.info,  Node: Architecture,  Next: Self-Tests,  Prev: Configuration,  Up: Top
-
-17 Architecture
-***************
-
-This chapter describes the internal architecture of Libgcrypt.
-
-   Libgcrypt is a function library written in ISO C-90.  Any compliant
-compiler should be able to build Libgcrypt as long as the target is
-either a POSIX platform or compatible to the API used by Windows NT.
-Provisions have been take so that the library can be directly used from
-C++ applications; however building with a C++ compiler is not supported.
-
-   Building Libgcrypt is done by using the common './configure && make'
-approach.  The configure command is included in the source distribution
-and as a portable shell script it works on any Unix-alike system.  The
-result of running the configure script are a C header file ('config.h'),
-customized Makefiles, the setup of symbolic links and a few other
-things.  After that the make tool builds and optionally installs the
-library and the documentation.  See the files 'INSTALL' and 'README' in
-the source distribution on how to do this.
-
-   Libgcrypt is developed using a Subversion(1) repository.  Although
-all released versions are tagged in this repository, they should not be
-used to build production versions of Libgcrypt.  Instead released
-tarballs should be used.  These tarballs are available from several
-places with the master copy at 'ftp://ftp.gnupg.org/gcrypt/libgcrypt/'.
-Announcements of new releases are posted to the
-'gnupg-announce@gnupg.org' mailing list(2).
-
-    \0\b[image src="libgcrypt-modules.png" alt="Libgcrypt subsystems"\0\b]
-
-Figure 17.1: Libgcrypt subsystems
-
-   Libgcrypt consists of several subsystems (*note Figure 17.1:
-fig:subsystems.) and all these subsystems provide a public API; this
-includes the helper subsystems like the one for S-expressions.  The API
-style depends on the subsystem; in general an open-use-close approach is
-implemented.  The open returns a handle to a context used for all
-further operations on this handle, several functions may then be used on
-this handle and a final close function releases all resources associated
-with the handle.
-
-* Menu:
-
-* Public-Key Subsystem Architecture::              About public keys.
-* Symmetric Encryption Subsystem Architecture::    About standard ciphers.
-* Hashing and MACing Subsystem Architecture::      About hashing.
-* Multi-Precision-Integer Subsystem Architecture:: About big integers.
-* Prime-Number-Generator Subsystem Architecture::  About prime numbers.
-* Random-Number Subsystem Architecture::           About random stuff.
-
-   ---------- Footnotes ----------
-
-   (1) A version control system available for many platforms
-
-   (2) See <http://www.gnupg.org/documentation/mailing-lists.en.html>
-for details.
-
-\1f
-File: gcrypt.info,  Node: Public-Key Subsystem Architecture,  Next: Symmetric Encryption Subsystem Architecture,  Up: Architecture
-
-17.1 Public-Key Architecture
-============================
-
-Because public key cryptography is almost always used to process small
-amounts of data (hash values or session keys), the interface is not
-implemented using the open-use-close paradigm, but with single
-self-contained functions.  Due to the wide variety of parameters
-required by different algorithms S-expressions, as flexible way to
-convey these parameters, are used.  There is a set of helper functions
-to work with these S-expressions.
-
-   Aside of functions to register new algorithms, map algorithms names
-to algorithms identifiers and to lookup properties of a key, the
-following main functions are available:
-
-'gcry_pk_encrypt'
-     Encrypt data using a public key.
-
-'gcry_pk_decrypt'
-     Decrypt data using a private key.
-
-'gcry_pk_sign'
-     Sign data using a private key.
-
-'gcry_pk_verify'
-     Verify that a signature matches the data.
-
-'gcry_pk_testkey'
-     Perform a consistency over a public or private key.
-
-'gcry_pk_genkey'
-     Create a new public/private key pair.
-
-   All these functions lookup the module implementing the algorithm and
-pass the actual work to that module.  The parsing of the S-expression
-input and the construction of S-expression for the return values is done
-by the high level code ('cipher/pubkey.c').  Thus the internal interface
-between the algorithm modules and the high level functions passes data
-in a custom format.
-
-   By default Libgcrypt uses a blinding technique for RSA decryption to
-mitigate real world timing attacks over a network: Instead of using the
-RSA decryption directly, a blinded value y = x r^{e} \bmod n is
-decrypted and the unblinded value x' = y' r^{-1} \bmod n returned.  The
-blinding value r is a random value with the size of the modulus n and
-generated with 'GCRY_WEAK_RANDOM' random level.
-
-   The algorithm used for RSA and DSA key generation depends on whether
-Libgcrypt is operated in standard or in FIPS mode.  In standard mode an
-algorithm based on the Lim-Lee prime number generator is used.  In FIPS
-mode RSA keys are generated as specified in ANSI X9.31 (1998) and DSA
-keys as specified in FIPS 186-2.
-
-\1f
-File: gcrypt.info,  Node: Symmetric Encryption Subsystem Architecture,  Next: Hashing and MACing Subsystem Architecture,  Prev: Public-Key Subsystem Architecture,  Up: Architecture
-
-17.2 Symmetric Encryption Subsystem Architecture
-================================================
-
-The interface to work with symmetric encryption algorithms is made up of
-functions from the 'gcry_cipher_' name space.  The implementation
-follows the open-use-close paradigm and uses registered algorithm
-modules for the actual work.  Unless a module implements optimized
-cipher mode implementations, the high level code ('cipher/cipher.c')
-implements the modes and calls the core algorithm functions to process
-each block.
-
-   The most important functions are:
-
-'gcry_cipher_open'
-     Create a new instance to encrypt or decrypt using a specified
-     algorithm and mode.
-
-'gcry_cipher_close'
-     Release an instance.
-
-'gcry_cipher_setkey'
-     Set a key to be used for encryption or decryption.
-
-'gcry_cipher_setiv'
-     Set an initialization vector to be used for encryption or
-     decryption.
-
-'gcry_cipher_encrypt'
-'gcry_cipher_decrypt'
-     Encrypt or decrypt data.  These functions may be called with
-     arbitrary amounts of data and as often as needed to encrypt or
-     decrypt all data.
-
-   There are also functions to query properties of algorithms or
-context, like block length, key length, map names or to enable features
-like padding methods.
-
-\1f
-File: gcrypt.info,  Node: Hashing and MACing Subsystem Architecture,  Next: Multi-Precision-Integer Subsystem Architecture,  Prev: Symmetric Encryption Subsystem Architecture,  Up: Architecture
-
-17.3 Hashing and MACing Subsystem Architecture
-==============================================
-
-The interface to work with message digests and CRC algorithms is made up
-of functions from the 'gcry_md_' name space.  The implementation follows
-the open-use-close paradigm and uses registered algorithm modules for
-the actual work.  Although CRC algorithms are not considered
-cryptographic hash algorithms, they share enough properties so that it
-makes sense to handle them in the same way.  It is possible to use
-several algorithms at once with one context and thus compute them all on
-the same data.
-
-   The most important functions are:
-
-'gcry_md_open'
-     Create a new message digest instance and optionally enable one
-     algorithm.  A flag may be used to turn the message digest algorithm
-     into a HMAC algorithm.
-
-'gcry_md_enable'
-     Enable an additional algorithm for the instance.
-
-'gcry_md_setkey'
-     Set the key for the MAC.
-
-'gcry_md_write'
-     Pass more data for computing the message digest to an instance.
-
-'gcry_md_putc'
-     Buffered version of 'gcry_md_write' implemented as a macro.
-
-'gcry_md_read'
-     Finalize the computation of the message digest or HMAC and return
-     the result.
-
-'gcry_md_close'
-     Release an instance
-
-'gcry_md_hash_buffer'
-     Convenience function to directly compute a message digest over a
-     memory buffer without the need to create an instance first.
-
-   There are also functions to query properties of algorithms or the
-instance, like enabled algorithms, digest length, map algorithm names.
-it is also possible to reset an instance or to copy the current state of
-an instance at any time.  Debug functions to write the hashed data to
-files are available as well.
-
-\1f
-File: gcrypt.info,  Node: Multi-Precision-Integer Subsystem Architecture,  Next: Prime-Number-Generator Subsystem Architecture,  Prev: Hashing and MACing Subsystem Architecture,  Up: Architecture
-
-17.4 Multi-Precision-Integer Subsystem Architecture
-===================================================
-
-The implementation of Libgcrypt's big integer computation code is based
-on an old release of GNU Multi-Precision Library (GMP). The decision not
-to use the GMP library directly was due to stalled development at that
-time and due to security requirements which could not be provided by the
-code in GMP. As GMP does, Libgcrypt provides high performance assembler
-implementations of low level code for several CPUS to gain much better
-performance than with a generic C implementation.
-
-Major features of Libgcrypt's multi-precision-integer code compared to
-GMP are:
-
-   * Avoidance of stack based allocations to allow protection against
-     swapping out of sensitive data and for easy zeroing of sensitive
-     intermediate results.
-
-   * Optional use of secure memory and tracking of its use so that
-     results are also put into secure memory.
-
-   * MPIs are identified by a handle (implemented as a pointer) to give
-     better control over allocations and to augment them with extra
-     properties like opaque data.
-
-   * Removal of unnecessary code to reduce complexity.
-
-   * Functions specialized for public key cryptography.
-
-\1f
-File: gcrypt.info,  Node: Prime-Number-Generator Subsystem Architecture,  Next: Random-Number Subsystem Architecture,  Prev: Multi-Precision-Integer Subsystem Architecture,  Up: Architecture
-
-17.5 Prime-Number-Generator Subsystem Architecture
-==================================================
-
-Libgcrypt provides an interface to its prime number generator.  These
-functions make use of the internal prime number generator which is
-required for the generation for public key key pairs.  The plain prime
-checking function is exported as well.
-
-   The generation of random prime numbers is based on the Lim and Lee
-algorithm to create practically save primes.(1)  This algorithm creates
-a pool of smaller primes, select a few of them to create candidate
-primes of the form 2 * p_0 * p_1 * ... * p_n + 1, tests the candidate
-for primality and permutates the pool until a prime has been found.  It
-is possible to clamp one of the small primes to a certain size to help
-DSA style algorithms.  Because most of the small primes in the pool are
-not used for the resulting prime number, they are saved for later use
-(see 'save_pool_prime' and 'get_pool_prime' in 'cipher/primegen.c').
-The prime generator optionally supports the finding of an appropriate
-generator.
-
-The primality test works in three steps:
-
-  1. The standard sieve algorithm using the primes up to 4999 is used as
-     a quick first check.
-
-  2. A Fermat test filters out almost all non-primes.
-
-  3. A 5 round Rabin-Miller test is finally used.  The first round uses
-     a witness of 2, whereas the next rounds use a random witness.
-
-   To support the generation of RSA and DSA keys in FIPS mode according
-to X9.31 and FIPS 186-2, Libgcrypt implements two additional prime
-generation functions: '_gcry_derive_x931_prime' and
-'_gcry_generate_fips186_2_prime'.  These functions are internal and not
-available through the public API.
-
-   ---------- Footnotes ----------
-
-   (1) Chae Hoon Lim and Pil Joong Lee.  A key recovery attack on
-discrete log-based schemes using a prime order subgroup.  In Burton S.
-Kaliski Jr., editor, Advances in Cryptology: Crypto '97, pages 249­-263,
-Berlin / Heidelberg / New York, 1997.  Springer-Verlag.  Described on
-page 260.
-
-\1f
-File: gcrypt.info,  Node: Random-Number Subsystem Architecture,  Prev: Prime-Number-Generator Subsystem Architecture,  Up: Architecture
-
-17.6 Random-Number Subsystem Architecture
-=========================================
-
-Libgcrypt provides 3 levels or random quality: The level
-'GCRY_VERY_STRONG_RANDOM' usually used for key generation, the level
-'GCRY_STRONG_RANDOM' for all other strong random requirements and the
-function 'gcry_create_nonce' which is used for weaker usages like
-nonces.  There is also a level 'GCRY_WEAK_RANDOM' which in general maps
-to 'GCRY_STRONG_RANDOM' except when used with the function
-'gcry_mpi_randomize', where it randomizes an multi-precision-integer
-using the 'gcry_create_nonce' function.
-
-There are two distinct random generators available:
-
-   * The Continuously Seeded Pseudo Random Number Generator (CSPRNG),
-     which is based on the classic GnuPG derived big pool
-     implementation.  Implemented in 'random/random-csprng.c' and used
-     by default.
-   * A FIPS approved ANSI X9.31 PRNG using AES with a 128 bit key.
-     Implemented in 'random/random-fips.c' and used if Libgcrypt is in
-     FIPS mode.
-
-Both generators make use of so-called entropy gathering modules:
-
-rndlinux
-     Uses the operating system provided '/dev/random' and '/dev/urandom'
-     devices.  The '/dev/gcrypt/random.conf' config option
-     'only-urandom' can be used to inhibit the use of the blocking
-     '/dev/random' device.
-
-rndunix
-     Runs several operating system commands to collect entropy from
-     sources like virtual machine and process statistics.  It is a kind
-     of poor-man's '/dev/random' implementation.  It is not available in
-     FIPS mode.
-
-rndegd
-     Uses the operating system provided Entropy Gathering Daemon (EGD).
-     The EGD basically uses the same algorithms as rndunix does.
-     However as a system daemon it keeps on running and thus can serve
-     several processes requiring entropy input and does not waste
-     collected entropy if the application does not need all the
-     collected entropy.  It is not available in FIPS mode.
-
-rndw32
-     Targeted for the Microsoft Windows OS. It uses certain properties
-     of that system and is the only gathering module available for that
-     OS.
-
-rndhw
-     Extra module to collect additional entropy by utilizing a hardware
-     random number generator.  As of now the supported hardware RNG is
-     the Padlock engine of VIA (Centaur) CPUs and x86 CPUs with the
-     RDRAND instruction.  It is not available in FIPS mode.
-
-rndjent
-     Extra module to collect additional entropy using a CPU jitter based
-     approach.  This is only used on X86 hardware where the RDTSC opcode
-     is available.  The '/dev/gcrypt/random.conf' config option
-     'disable-jent' can be used to inhibit the use of this module.
-
-* Menu:
-
-* CSPRNG Description::      Description of the CSPRNG.
-* FIPS PRNG Description::   Description of the FIPS X9.31 PRNG.
-
-\1f
-File: gcrypt.info,  Node: CSPRNG Description,  Next: FIPS PRNG Description,  Up: Random-Number Subsystem Architecture
-
-17.6.1 Description of the CSPRNG
---------------------------------
-
-This random number generator is loosely modelled after the one described
-in Peter Gutmann's paper: "Software Generation of Practically Strong
-Random Numbers".(1)
-
-   A pool of 600 bytes is used and mixed using the core SHA-1 hash
-transform function.  Several extra features are used to make the robust
-against a wide variety of attacks and to protect against failures of
-subsystems.  The state of the generator may be saved to a file and
-initially seed form a file.
-
-   Depending on how Libgcrypt was build the generator is able to select
-the best working entropy gathering module.  It makes use of the slow and
-fast collection methods and requires the pool to initially seeded form
-the slow gatherer or a seed file.  An entropy estimation is used to mix
-in enough data from the gather modules before returning the actual
-random output.  Process fork detection and protection is implemented.
-
-   The implementation of the nonce generator (for 'gcry_create_nonce')
-is a straightforward repeated hash design: A 28 byte buffer is initially
-seeded with the PID and the time in seconds in the first 20 bytes and
-with 8 bytes of random taken from the 'GCRY_STRONG_RANDOM' generator.
-Random numbers are then created by hashing all the 28 bytes with SHA-1
-and saving that again in the first 20 bytes.  The hash is also returned
-as result.
-
-   ---------- Footnotes ----------
-
-   (1) Also described in chapter 6 of his book "Cryptographic Security
-Architecture", New York, 2004, ISBN 0-387-95387-6.
-
-\1f
-File: gcrypt.info,  Node: FIPS PRNG Description,  Prev: CSPRNG Description,  Up: Random-Number Subsystem Architecture
-
-17.6.2 Description of the FIPS X9.31 PRNG
------------------------------------------
-
-The core of this deterministic random number generator is implemented
-according to the document "NIST-Recommended Random Number Generator
-Based on ANSI X9.31 Appendix A.2.4 Using the 3-Key Triple DES and AES
-Algorithms", dated 2005-01-31.  This implementation uses the AES
-variant.
-
-   The generator is based on contexts to utilize the same core functions
-for all random levels as required by the high-level interface.  All
-random generators return their data in 128 bit blocks.  If the caller
-requests less bits, the extra bits are not used.  The key for each
-generator is only set once at the first time a generator context is
-used.  The seed value is set along with the key and again after 1000
-output blocks.
-
-   On Unix like systems the 'GCRY_VERY_STRONG_RANDOM' and
-'GCRY_STRONG_RANDOM' generators are keyed and seeded using the rndlinux
-module with the '/dev/random' device.  Thus these generators may block
-until the OS kernel has collected enough entropy.  When used with
-Microsoft Windows the rndw32 module is used instead.
-
-   The generator used for 'gcry_create_nonce' is keyed and seeded from
-the 'GCRY_STRONG_RANDOM' generator.  Thus is may also block if the
-'GCRY_STRONG_RANDOM' generator has not yet been used before and thus
-gets initialized on the first use by 'gcry_create_nonce'.  This special
-treatment is justified by the weaker requirements for a nonce generator
-and to save precious kernel entropy for use by the "real" random
-generators.
-
-   A self-test facility uses a separate context to check the
-functionality of the core X9.31 functions using a known answers test.
-During runtime each output block is compared to the previous one to
-detect a stuck generator.
-
-   The DT value for the generator is made up of the current time down to
-microseconds (if available) and a free running 64 bit counter.  When
-used with the test context the DT value is taken from the context and
-incremented on each use.
-
-\1f
-File: gcrypt.info,  Node: Self-Tests,  Next: FIPS Mode,  Prev: Architecture,  Up: Top
-
-Appendix A Description of the Self-Tests
-****************************************
-
-In addition to the build time regression test suite, Libgcrypt
-implements self-tests to be performed at runtime.  Which self-tests are
-actually used depends on the mode Libgcrypt is used in.  In standard
-mode a limited set of self-tests is run at the time an algorithm is
-first used.  Note that not all algorithms feature a self-test in
-standard mode.  The 'GCRYCTL_SELFTEST' control command may be used to
-run all implemented self-tests at any time; this will even run more
-tests than those run in FIPS mode.
-
-   If any of the self-tests fails, the library immediately returns an
-error code to the caller.  If Libgcrypt is in FIPS mode the self-tests
-will be performed within the "Self-Test" state and any failure puts the
-library into the "Error" state.
-
-A.1 Power-Up Tests
-==================
-
-Power-up tests are only performed if Libgcrypt is in FIPS mode.
-
-A.1.1 Symmetric Cipher Algorithm Power-Up Tests
------------------------------------------------
-
-The following symmetric encryption algorithm tests are run during
-power-up:
-
-3DES
-     To test the 3DES 3-key EDE encryption in ECB mode these tests are
-     run:
-       1. A known answer test is run on a 64 bit test vector processed
-          by 64 rounds of Single-DES block encryption and decryption
-          using a key changed with each round.
-       2. A known answer test is run on a 64 bit test vector processed
-          by 16 rounds of 2-key and 3-key Triple-DES block encryption
-          and decryptions using a key changed with each round.
-       3. 10 known answer tests using 3-key Triple-DES EDE encryption,
-          comparing the ciphertext to the known value, then running a
-          decryption and comparing it to the initial plaintext.
-     ('cipher/des.c:selftest')
-
-AES-128
-     A known answer tests is run using one test vector and one test key
-     with AES in ECB mode.  ('cipher/rijndael.c:selftest_basic_128')
-
-AES-192
-     A known answer tests is run using one test vector and one test key
-     with AES in ECB mode.  ('cipher/rijndael.c:selftest_basic_192')
-
-AES-256
-     A known answer tests is run using one test vector and one test key
-     with AES in ECB mode.  ('cipher/rijndael.c:selftest_basic_256')
-
-A.1.2 Hash Algorithm Power-Up Tests
------------------------------------
-
-The following hash algorithm tests are run during power-up:
-
-SHA-1
-     A known answer test using the string '"abc"' is run.
-     ('cipher/sha1.c:selftests_sha1')
-SHA-224
-     A known answer test using the string '"abc"' is run.
-     ('cipher/sha256.c:selftests_sha224')
-SHA-256
-     A known answer test using the string '"abc"' is run.
-     ('cipher/sha256.c:selftests_sha256')
-SHA-384
-     A known answer test using the string '"abc"' is run.
-     ('cipher/sha512.c:selftests_sha384')
-SHA-512
-     A known answer test using the string '"abc"' is run.
-     ('cipher/sha512.c:selftests_sha512')
-
-A.1.3 MAC Algorithm Power-Up Tests
-----------------------------------
-
-The following MAC algorithm tests are run during power-up:
-
-HMAC SHA-1
-     A known answer test using 9 byte of data and a 64 byte key is run.
-     ('cipher/hmac-tests.c:selftests_sha1')
-HMAC SHA-224
-     A known answer test using 28 byte of data and a 4 byte key is run.
-     ('cipher/hmac-tests.c:selftests_sha224')
-HMAC SHA-256
-     A known answer test using 28 byte of data and a 4 byte key is run.
-     ('cipher/hmac-tests.c:selftests_sha256')
-HMAC SHA-384
-     A known answer test using 28 byte of data and a 4 byte key is run.
-     ('cipher/hmac-tests.c:selftests_sha384')
-HMAC SHA-512
-     A known answer test using 28 byte of data and a 4 byte key is run.
-     ('cipher/hmac-tests.c:selftests_sha512')
-
-A.1.4 Random Number Power-Up Test
----------------------------------
-
-The DRNG is tested during power-up this way:
-
-  1. Requesting one block of random using the public interface to check
-     general working and the duplicated block detection.
-  2. 3 know answer tests using pre-defined keys, seed and initial DT
-     values.  For each test 3 blocks of 16 bytes are requested and
-     compared to the expected result.  The DT value is incremented for
-     each block.
-
-A.1.5 Public Key Algorithm Power-Up Tests
------------------------------------------
-
-The public key algorithms are tested during power-up:
-
-RSA
-     A pre-defined 1024 bit RSA key is used and these tests are run in
-     turn:
-       1. Conversion of S-expression to internal format.
-          ('cipher/rsa.c:selftests_rsa')
-       2. Private key consistency check.  ('cipher/rsa.c:selftests_rsa')
-       3. A pre-defined 20 byte value is signed with PKCS#1 padding for
-          SHA-1.  The result is verified using the public key against
-          the original data and against modified data.
-          ('cipher/rsa.c:selftest_sign_1024')
-       4. A 1000 bit random value is encrypted and checked that it does
-          not match the original random value.  The encrypted result is
-          then decrypted and checked that it matches the original random
-          value.  ('cipher/rsa.c:selftest_encr_1024')
-
-DSA
-     A pre-defined 1024 bit DSA key is used and these tests are run in
-     turn:
-       1. Conversion of S-expression to internal format.
-          ('cipher/dsa.c:selftests_dsa')
-       2. Private key consistency check.  ('cipher/dsa.c:selftests_dsa')
-       3. A pre-defined 20 byte value is signed with PKCS#1 padding for
-          SHA-1.  The result is verified using the public key against
-          the original data and against modified data.
-          ('cipher/dsa.c:selftest_sign_1024')
-
-A.1.6 Integrity Power-Up Tests
-------------------------------
-
-The integrity of the Libgcrypt is tested during power-up but only if
-checking has been enabled at build time.  The check works by computing a
-HMAC SHA-256 checksum over the file used to load Libgcrypt into memory.
-That checksum is compared against a checksum stored in a file of the
-same name but with a single dot as a prefix and a suffix of '.hmac'.
-
-A.1.7 Critical Functions Power-Up Tests
----------------------------------------
-
-The 3DES weak key detection is tested during power-up by calling the
-detection function with keys taken from a table listening all weak keys.
-The table itself is protected using a SHA-1 hash.
-('cipher/des.c:selftest')
-
-A.2 Conditional Tests
-=====================
-
-The conditional tests are performed if a certain condition is met.  This
-may occur at any time; the library does not necessary enter the
-"Self-Test" state to run these tests but will transit to the "Error"
-state if a test failed.
-
-A.2.1 Key-Pair Generation Tests
--------------------------------
-
-After an asymmetric key-pair has been generated, Libgcrypt runs a
-pair-wise consistency tests on the generated key.  On failure the
-generated key is not used, an error code is returned and, if in FIPS
-mode, the library is put into the "Error" state.
-
-RSA
-     The test uses a random number 64 bits less the size of the modulus
-     as plaintext and runs an encryption and decryption operation in
-     turn.  The encrypted value is checked to not match the plaintext
-     and the result of the decryption is checked to match the plaintext.
-
-     A new random number of the same size is generated, signed and
-     verified to test the correctness of the signing operation.  As a
-     second signing test, the signature is modified by incrementing its
-     value and then verified with the expected result that the
-     verification fails.  ('cipher/rsa.c:test_keys')
-DSA
-     The test uses a random number of the size of the Q parameter to
-     create a signature and then checks that the signature verifies.  As
-     a second signing test, the data is modified by incrementing its
-     value and then verified against the signature with the expected
-     result that the verification fails.  ('cipher/dsa.c:test_keys')
-
-A.2.2 Software Load Tests
--------------------------
-
-No code is loaded at runtime.
-
-A.2.3 Manual Key Entry Tests
-----------------------------
-
-A manual key entry feature is not implemented in Libgcrypt.
-
-A.2.4 Continuous RNG Tests
---------------------------
-
-The continuous random number test is only used in FIPS mode.  The RNG
-generates blocks of 128 bit size; the first block generated per context
-is saved in the context and another block is generated to be returned to
-the caller.  Each block is compared against the saved block and then
-stored in the context.  If a duplicated block is detected an error is
-signaled and the library is put into the "Fatal-Error" state.
-('random/random-fips.c:x931_aes_driver')
-
-A.3 Application Requested Tests
-===============================
-
-The application may requests tests at any time by means of the
-'GCRYCTL_SELFTEST' control command.  Note that using these tests is not
-FIPS conform: Although Libgcrypt rejects all application requests for
-services while running self-tests, it does not ensure that no other
-operations of Libgcrypt are still being executed.  Thus, in FIPS mode an
-application requesting self-tests needs to power-cycle Libgcrypt
-instead.
-
-   When self-tests are requested, Libgcrypt runs all the tests it does
-during power-up as well as a few extra checks as described below.
-
-A.3.1 Symmetric Cipher Algorithm Tests
---------------------------------------
-
-The following symmetric encryption algorithm tests are run in addition
-to the power-up tests:
-
-AES-128
-     A known answer tests with test vectors taken from NIST SP800-38a
-     and using the high level functions is run for block modes CFB and
-     OFB.
-
-A.3.2 Hash Algorithm Tests
---------------------------
-
-The following hash algorithm tests are run in addition to the power-up
-tests:
-
-SHA-1
-SHA-224
-SHA-256
-       1. A known answer test using a 56 byte string is run.
-       2. A known answer test using a string of one million letters "a"
-          is run.
-     ('cipher/sha1.c:selftests_sha1',
-     'cipher/sha256.c:selftests_sha224',
-     'cipher/sha256.c:selftests_sha256')
-SHA-384
-SHA-512
-       1. A known answer test using a 112 byte string is run.
-       2. A known answer test using a string of one million letters "a"
-          is run.
-     ('cipher/sha512.c:selftests_sha384',
-     'cipher/sha512.c:selftests_sha512')
-
-A.3.3 MAC Algorithm Tests
--------------------------
-
-The following MAC algorithm tests are run in addition to the power-up
-tests:
-
-HMAC SHA-1
-       1. A known answer test using 9 byte of data and a 20 byte key is
-          run.
-       2. A known answer test using 9 byte of data and a 100 byte key is
-          run.
-       3. A known answer test using 9 byte of data and a 49 byte key is
-          run.
-     ('cipher/hmac-tests.c:selftests_sha1')
-HMAC SHA-224
-HMAC SHA-256
-HMAC SHA-384
-HMAC SHA-512
-       1. A known answer test using 9 byte of data and a 20 byte key is
-          run.
-       2. A known answer test using 50 byte of data and a 20 byte key is
-          run.
-       3. A known answer test using 50 byte of data and a 26 byte key is
-          run.
-       4. A known answer test using 54 byte of data and a 131 byte key
-          is run.
-       5. A known answer test using 152 byte of data and a 131 byte key
-          is run.
-     ('cipher/hmac-tests.c:selftests_sha224',
-     'cipher/hmac-tests.c:selftests_sha256',
-     'cipher/hmac-tests.c:selftests_sha384',
-     'cipher/hmac-tests.c:selftests_sha512')
-
-\1f
-File: gcrypt.info,  Node: FIPS Mode,  Next: Library Copying,  Prev: Self-Tests,  Up: Top
-
-Appendix B Description of the FIPS Mode
-***************************************
-
-This appendix gives detailed information pertaining to the FIPS mode.
-In particular, the changes to the standard mode and the finite state
-machine are described.  The self-tests required in this mode are
-described in the appendix on self-tests.
-
-B.1 Restrictions in FIPS Mode
-=============================
-
-If Libgcrypt is used in FIPS mode these restrictions are effective:
-
-   * The cryptographic algorithms are restricted to this list:
-
-     GCRY_CIPHER_3DES
-          3 key EDE Triple-DES symmetric encryption.
-     GCRY_CIPHER_AES128
-          AES 128 bit symmetric encryption.
-     GCRY_CIPHER_AES192
-          AES 192 bit symmetric encryption.
-     GCRY_CIPHER_AES256
-          AES 256 bit symmetric encryption.
-     GCRY_MD_SHA1
-          SHA-1 message digest.
-     GCRY_MD_SHA224
-          SHA-224 message digest.
-     GCRY_MD_SHA256
-          SHA-256 message digest.
-     GCRY_MD_SHA384
-          SHA-384 message digest.
-     GCRY_MD_SHA512
-          SHA-512 message digest.
-     GCRY_MD_SHA1,GCRY_MD_FLAG_HMAC
-          HMAC using a SHA-1 message digest.
-     GCRY_MD_SHA224,GCRY_MD_FLAG_HMAC
-          HMAC using a SHA-224 message digest.
-     GCRY_MD_SHA256,GCRY_MD_FLAG_HMAC
-          HMAC using a SHA-256 message digest.
-     GCRY_MD_SHA384,GCRY_MD_FLAG_HMAC
-          HMAC using a SHA-384 message digest.
-     GCRY_MD_SHA512,GCRY_MD_FLAG_HMAC
-          HMAC using a SHA-512 message digest.
-     GCRY_PK_RSA
-          RSA encryption and signing.
-     GCRY_PK_DSA
-          DSA signing.
-
-     Note that the CRC algorithms are not considered cryptographic
-     algorithms and thus are in addition available.
-
-   * RSA key generation refuses to create a key with a keysize of less
-     than 1024 bits.
-
-   * DSA key generation refuses to create a key with a keysize other
-     than 1024 bits.
-
-   * The 'transient-key' flag for RSA and DSA key generation is ignored.
-
-   * Support for the VIA Padlock engine is disabled.
-
-   * FIPS mode may only be used on systems with a /dev/random device.
-     Switching into FIPS mode on other systems will fail at runtime.
-
-   * Saving and loading a random seed file is ignored.
-
-   * An X9.31 style random number generator is used in place of the
-     large-pool-CSPRNG generator.
-
-   * The command 'GCRYCTL_ENABLE_QUICK_RANDOM' is ignored.
-
-   * Message digest debugging is disabled.
-
-   * All debug output related to cryptographic data is suppressed.
-
-   * On-the-fly self-tests are not performed, instead self-tests are run
-     before entering operational state.
-
-   * The function 'gcry_set_allocation_handler' may not be used.  If it
-     is used Libgcrypt disables FIPS mode unless Enforced FIPS mode is
-     enabled, in which case Libgcrypt will enter the error state.
-
-   * The digest algorithm MD5 may not be used.  If it is used Libgcrypt
-     disables FIPS mode unless Enforced FIPS mode is enabled, in which
-     case Libgcrypt will enter the error state.
-
-   * In Enforced FIPS mode the command 'GCRYCTL_DISABLE_SECMEM' is
-     ignored.  In standard FIPS mode it disables FIPS mode.
-
-   * A handler set by 'gcry_set_outofcore_handler' is ignored.
-   * A handler set by 'gcry_set_fatalerror_handler' is ignored.
-
-   Note that when we speak about disabling FIPS mode, it merely means
-that the function 'gcry_fips_mode_active' returns false; it does not
-mean that any non FIPS algorithms are allowed.
-
-B.2 FIPS Finite State Machine
-=============================
-
-The FIPS mode of libgcrypt implements a finite state machine (FSM) using
-8 states (*note Table B.1: tbl:fips-states.) and checks at runtime that
-only valid transitions (*note Table B.2: tbl:fips-state-transitions.)
-may happen.
-
-           \0\b[image src="fips-fsm.png" alt="FIPS FSM Diagram"\0\b]
-
-Figure B.1: FIPS mode state diagram
-
-States used by the FIPS FSM:
-
-Power-Off
-     Libgcrypt is not runtime linked to another application.  This
-     usually means that the library is not loaded into main memory.
-     This state is documentation only.
-
-Power-On
-     Libgcrypt is loaded into memory and API calls may be made.
-     Compiler introduced constructor functions may be run.  Note that
-     Libgcrypt does not implement any arbitrary constructor functions to
-     be called by the operating system
-
-Init
-     The Libgcrypt initialization functions are performed and the
-     library has not yet run any self-test.
-
-Self-Test
-     Libgcrypt is performing self-tests.
-
-Operational
-     Libgcrypt is in the operational state and all interfaces may be
-     used.
-
-Error
-     Libgrypt is in the error state.  When calling any FIPS relevant
-     interfaces they either return an error ('GPG_ERR_NOT_OPERATIONAL')
-     or put Libgcrypt into the Fatal-Error state and won't return.
-
-Fatal-Error
-     Libgcrypt is in a non-recoverable error state and will
-     automatically transit into the Shutdown state.
-
-Shutdown
-     Libgcrypt is about to be terminated and removed from the memory.
-     The application may at this point still running cleanup handlers.
-
-Table B.1: FIPS mode states
-
-The valid state transitions (*note Figure B.1: fig:fips-fsm.) are:
-'1'
-     Power-Off to Power-On is implicitly done by the OS loading
-     Libgcrypt as a shared library and having it linked to an
-     application.
-
-'2'
-     Power-On to Init is triggered by the application calling the
-     Libgcrypt initialization function 'gcry_check_version'.
-
-'3'
-     Init to Self-Test is either triggered by a dedicated API call or
-     implicit by invoking a libgrypt service controlled by the FSM.
-
-'4'
-     Self-Test to Operational is triggered after all self-tests passed
-     successfully.
-
-'5'
-     Operational to Shutdown is an artificial state without any direct
-     action in Libgcrypt.  When reaching the Shutdown state the library
-     is deinitialized and can't return to any other state again.
-
-'6'
-     Shutdown to Power-off is the process of removing Libgcrypt from the
-     computer's memory.  For obvious reasons the Power-Off state can't
-     be represented within Libgcrypt and thus this transition is for
-     documentation only.
-
-'7'
-     Operational to Error is triggered if Libgcrypt detected an
-     application error which can't be returned to the caller but still
-     allows Libgcrypt to properly run.  In the Error state all FIPS
-     relevant interfaces return an error code.
-
-'8'
-     Error to Shutdown is similar to the Operational to Shutdown
-     transition (5).
-
-'9'
-     Error to Fatal-Error is triggered if Libgrypt detects an fatal
-     error while already being in Error state.
-
-'10'
-     Fatal-Error to Shutdown is automatically entered by Libgcrypt after
-     having reported the error.
-
-'11'
-     Power-On to Shutdown is an artificial state to document that
-     Libgcrypt has not ye been initialized but the process is about to
-     terminate.
-
-'12'
-     Power-On to Fatal-Error will be triggered if certain Libgcrypt
-     functions are used without having reached the Init state.
-
-'13'
-     Self-Test to Fatal-Error is triggered by severe errors in Libgcrypt
-     while running self-tests.
-
-'14'
-     Self-Test to Error is triggered by a failed self-test.
-
-'15'
-     Operational to Fatal-Error is triggered if Libcrypt encountered a
-     non-recoverable error.
-
-'16'
-     Operational to Self-Test is triggered if the application requested
-     to run the self-tests again.
-
-'17'
-     Error to Self-Test is triggered if the application has requested to
-     run self-tests to get to get back into operational state after an
-     error.
-
-'18'
-     Init to Error is triggered by errors in the initialization code.
-
-'19'
-     Init to Fatal-Error is triggered by non-recoverable errors in the
-     initialization code.
-
-'20'
-     Error to Error is triggered by errors while already in the Error
-     state.
-
-Table B.2: FIPS mode state transitions
-
-B.3 FIPS Miscellaneous Information
-==================================
-
-Libgcrypt does not do any key management on itself; the application
-needs to care about it.  Keys which are passed to Libgcrypt should be
-allocated in secure memory as available with the functions
-'gcry_malloc_secure' and 'gcry_calloc_secure'.  By calling 'gcry_free'
-on this memory, the memory and thus the keys are overwritten with zero
-bytes before releasing the memory.
-
-   For use with the random number generator, Libgcrypt generates 3
-internal keys which are stored in the encryption contexts used by the
-RNG. These keys are stored in secure memory for the lifetime of the
-process.  Application are required to use 'GCRYCTL_TERM_SECMEM' before
-process termination.  This will zero out the entire secure memory and
-thus also the encryption contexts with these keys.
-
-\1f
-File: gcrypt.info,  Node: Library Copying,  Next: Copying,  Prev: FIPS Mode,  Up: Top
-
-GNU Lesser General Public License
-*********************************
-
-                      Version 2.1, February 1999
-
-     Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-     59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-     Everyone is permitted to copy and distribute verbatim copies
-     of this license document, but changing it is not allowed.
-
-     [This is the first released version of the Lesser GPL.  It also counts
-     as the successor of the GNU Library Public License, version 2, hence the
-     version number 2.1.]
-
-Preamble
-========
-
-The licenses for most software are designed to take away your freedom to
-share and change it.  By contrast, the GNU General Public Licenses are
-intended to guarantee your freedom to share and change free software--to
-make sure the software is free for all its users.
-
-   This license, the Lesser General Public License, applies to some
-specially designated software--typically libraries--of the Free Software
-Foundation and other authors who decide to use it.  You can use it too,
-but we suggest you first think carefully about whether this license or
-the ordinary General Public License is the better strategy to use in any
-particular case, based on the explanations below.
-
-   When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of it
-in new free programs; and that you are informed that you can do these
-things.
-
-   To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-   For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling it.
-And you must show them these terms so they know their rights.
-
-   We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-   To protect each distributor, we want to make it very clear that there
-is no warranty for the free library.  Also, if the library is modified
-by someone else and passed on, the recipients should know that what they
-have is not the original version, so that the original author's
-reputation will not be affected by problems that might be introduced by
-others.
-
-   Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that any
-patent license obtained for a version of the library must be consistent
-with the full freedom of use specified in this license.
-
-   Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and is
-quite different from the ordinary General Public License.  We use this
-license for certain libraries in order to permit linking those libraries
-into non-free programs.
-
-   When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the entire
-combination fits its criteria of freedom.  The Lesser General Public
-License permits more lax criteria for linking other code with the
-library.
-
-   We call this license the "Lesser" General Public License because it
-does _Less_ to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less of
-an advantage over competing non-free programs.  These disadvantages are
-the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-   For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it
-becomes a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free library
-does the same job as widely used non-free libraries.  In this case,
-there is little to gain by limiting the free library to free software
-only, so we use the Lesser General Public License.
-
-   In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of free
-software.  For example, permission to use the GNU C Library in non-free
-programs enables many more people to use the whole GNU operating system,
-as well as its variant, the GNU/Linux operating system.
-
-   Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is linked
-with the Library has the freedom and the wherewithal to run that program
-using a modified version of the Library.
-
-   The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-                   GNU LESSER GENERAL PUBLIC LICENSE
-    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-     program which contains a notice placed by the copyright holder or
-     other authorized party saying it may be distributed under the terms
-     of this Lesser General Public License (also called "this License").
-     Each licensee is addressed as "you".
-
-     A "library" means a collection of software functions and/or data
-     prepared so as to be conveniently linked with application programs
-     (which use some of those functions and data) to form executables.
-
-     The "Library", below, refers to any such software library or work
-     which has been distributed under these terms.  A "work based on the
-     Library" means either the Library or any derivative work under
-     copyright law: that is to say, a work containing the Library or a
-     portion of it, either verbatim or with modifications and/or
-     translated straightforwardly into another language.  (Hereinafter,
-     translation is included without limitation in the term
-     "modification".)
-
-     "Source code" for a work means the preferred form of the work for
-     making modifications to it.  For a library, complete source code
-     means all the source code for all modules it contains, plus any
-     associated interface definition files, plus the scripts used to
-     control compilation and installation of the library.
-
-     Activities other than copying, distribution and modification are
-     not covered by this License; they are outside its scope.  The act
-     of running a program using the Library is not restricted, and
-     output from such a program is covered only if its contents
-     constitute a work based on the Library (independent of the use of
-     the Library in a tool for writing it).  Whether that is true
-     depends on what the Library does and what the program that uses the
-     Library does.
-
-  1. You may copy and distribute verbatim copies of the Library's
-     complete source code as you receive it, in any medium, provided
-     that you conspicuously and appropriately publish on each copy an
-     appropriate copyright notice and disclaimer of warranty; keep
-     intact all the notices that refer to this License and to the
-     absence of any warranty; and distribute a copy of this License
-     along with the Library.
-
-     You may charge a fee for the physical act of transferring a copy,
-     and you may at your option offer warranty protection in exchange
-     for a fee.
-
-  2. You may modify your copy or copies of the Library or any portion of
-     it, thus forming a work based on the Library, and copy and
-     distribute such modifications or work under the terms of Section 1
-     above, provided that you also meet all of these conditions:
-
-       a. The modified work must itself be a software library.
-
-       b. You must cause the files modified to carry prominent notices
-          stating that you changed the files and the date of any change.
-
-       c. You must cause the whole of the work to be licensed at no
-          charge to all third parties under the terms of this License.
-
-       d. If a facility in the modified Library refers to a function or
-          a table of data to be supplied by an application program that
-          uses the facility, other than as an argument passed when the
-          facility is invoked, then you must make a good faith effort to
-          ensure that, in the event an application does not supply such
-          function or table, the facility still operates, and performs
-          whatever part of its purpose remains meaningful.
-
-          (For example, a function in a library to compute square roots
-          has a purpose that is entirely well-defined independent of the
-          application.  Therefore, Subsection 2d requires that any
-          application-supplied function or table used by this function
-          must be optional: if the application does not supply it, the
-          square root function must still compute square roots.)
-
-     These requirements apply to the modified work as a whole.  If
-     identifiable sections of that work are not derived from the
-     Library, and can be reasonably considered independent and separate
-     works in themselves, then this License, and its terms, do not apply
-     to those sections when you distribute them as separate works.  But
-     when you distribute the same sections as part of a whole which is a
-     work based on the Library, the distribution of the whole must be on
-     the terms of this License, whose permissions for other licensees
-     extend to the entire whole, and thus to each and every part
-     regardless of who wrote it.
-
-     Thus, it is not the intent of this section to claim rights or
-     contest your rights to work written entirely by you; rather, the
-     intent is to exercise the right to control the distribution of
-     derivative or collective works based on the Library.
-
-     In addition, mere aggregation of another work not based on the
-     Library with the Library (or with a work based on the Library) on a
-     volume of a storage or distribution medium does not bring the other
-     work under the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-     License instead of this License to a given copy of the Library.  To
-     do this, you must alter all the notices that refer to this License,
-     so that they refer to the ordinary GNU General Public License,
-     version 2, instead of to this License.  (If a newer version than
-     version 2 of the ordinary GNU General Public License has appeared,
-     then you can specify that version instead if you wish.)  Do not
-     make any other change in these notices.
-
-     Once this change is made in a given copy, it is irreversible for
-     that copy, so the ordinary GNU General Public License applies to
-     all subsequent copies and derivative works made from that copy.
-
-     This option is useful when you wish to copy part of the code of the
-     Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or derivative
-     of it, under Section 2) in object code or executable form under the
-     terms of Sections 1 and 2 above provided that you accompany it with
-     the complete corresponding machine-readable source code, which must
-     be distributed under the terms of Sections 1 and 2 above on a
-     medium customarily used for software interchange.
-
-     If distribution of object code is made by offering access to copy
-     from a designated place, then offering equivalent access to copy
-     the source code from the same place satisfies the requirement to
-     distribute the source code, even though third parties are not
-     compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-     Library, but is designed to work with the Library by being compiled
-     or linked with it, is called a "work that uses the Library".  Such
-     a work, in isolation, is not a derivative work of the Library, and
-     therefore falls outside the scope of this License.
-
-     However, linking a "work that uses the Library" with the Library
-     creates an executable that is a derivative of the Library (because
-     it contains portions of the Library), rather than a "work that uses
-     the library".  The executable is therefore covered by this License.
-     Section 6 states terms for distribution of such executables.
-
-     When a "work that uses the Library" uses material from a header
-     file that is part of the Library, the object code for the work may
-     be a derivative work of the Library even though the source code is
-     not.  Whether this is true is especially significant if the work
-     can be linked without the Library, or if the work is itself a
-     library.  The threshold for this to be true is not precisely
-     defined by law.
-
-     If such an object file uses only numerical parameters, data
-     structure layouts and accessors, and small macros and small inline
-     functions (ten lines or less in length), then the use of the object
-     file is unrestricted, regardless of whether it is legally a
-     derivative work.  (Executables containing this object code plus
-     portions of the Library will still fall under Section 6.)
-
-     Otherwise, if the work is a derivative of the Library, you may
-     distribute the object code for the work under the terms of Section
-     6.  Any executables containing that work also fall under Section 6,
-     whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or link
-     a "work that uses the Library" with the Library to produce a work
-     containing portions of the Library, and distribute that work under
-     terms of your choice, provided that the terms permit modification
-     of the work for the customer's own use and reverse engineering for
-     debugging such modifications.
-
-     You must give prominent notice with each copy of the work that the
-     Library is used in it and that the Library and its use are covered
-     by this License.  You must supply a copy of this License.  If the
-     work during execution displays copyright notices, you must include
-     the copyright notice for the Library among them, as well as a
-     reference directing the user to the copy of this License.  Also,
-     you must do one of these things:
-
-       a. Accompany the work with the complete corresponding
-          machine-readable source code for the Library including
-          whatever changes were used in the work (which must be
-          distributed under Sections 1 and 2 above); and, if the work is
-          an executable linked with the Library, with the complete
-          machine-readable "work that uses the Library", as object code
-          and/or source code, so that the user can modify the Library
-          and then relink to produce a modified executable containing
-          the modified Library.  (It is understood that the user who
-          changes the contents of definitions files in the Library will
-          not necessarily be able to recompile the application to use
-          the modified definitions.)
-
-       b. Use a suitable shared library mechanism for linking with the
-          Library.  A suitable mechanism is one that (1) uses at run
-          time a copy of the library already present on the user's
-          computer system, rather than copying library functions into
-          the executable, and (2) will operate properly with a modified
-          version of the library, if the user installs one, as long as
-          the modified version is interface-compatible with the version
-          that the work was made with.
-
-       c. Accompany the work with a written offer, valid for at least
-          three years, to give the same user the materials specified in
-          Subsection 6a, above, for a charge no more than the cost of
-          performing this distribution.
-
-       d. If distribution of the work is made by offering access to copy
-          from a designated place, offer equivalent access to copy the
-          above specified materials from the same place.
-
-       e. Verify that the user has already received a copy of these
-          materials or that you have already sent this user a copy.
-
-     For an executable, the required form of the "work that uses the
-     Library" must include any data and utility programs needed for
-     reproducing the executable from it.  However, as a special
-     exception, the materials to be distributed need not include
-     anything that is normally distributed (in either source or binary
-     form) with the major components (compiler, kernel, and so on) of
-     the operating system on which the executable runs, unless that
-     component itself accompanies the executable.
-
-     It may happen that this requirement contradicts the license
-     restrictions of other proprietary libraries that do not normally
-     accompany the operating system.  Such a contradiction means you
-     cannot use both them and the Library together in an executable that
-     you distribute.
-
-  7. You may place library facilities that are a work based on the
-     Library side-by-side in a single library together with other
-     library facilities not covered by this License, and distribute such
-     a combined library, provided that the separate distribution of the
-     work based on the Library and of the other library facilities is
-     otherwise permitted, and provided that you do these two things:
-
-       a. Accompany the combined library with a copy of the same work
-          based on the Library, uncombined with any other library
-          facilities.  This must be distributed under the terms of the
-          Sections above.
-
-       b. Give prominent notice with the combined library of the fact
-          that part of it is a work based on the Library, and explaining
-          where to find the accompanying uncombined form of the same
-          work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute the
-     Library except as expressly provided under this License.  Any
-     attempt otherwise to copy, modify, sublicense, link with, or
-     distribute the Library is void, and will automatically terminate
-     your rights under this License.  However, parties who have received
-     copies, or rights, from you under this License will not have their
-     licenses terminated so long as such parties remain in full
-     compliance.
-
-  9. You are not required to accept this License, since you have not
-     signed it.  However, nothing else grants you permission to modify
-     or distribute the Library or its derivative works.  These actions
-     are prohibited by law if you do not accept this License.
-     Therefore, by modifying or distributing the Library (or any work
-     based on the Library), you indicate your acceptance of this License
-     to do so, and all its terms and conditions for copying,
-     distributing or modifying the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-     Library), the recipient automatically receives a license from the
-     original licensor to copy, distribute, link with or modify the
-     Library subject to these terms and conditions.  You may not impose
-     any further restrictions on the recipients' exercise of the rights
-     granted herein.  You are not responsible for enforcing compliance
-     by third parties with this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-     infringement or for any other reason (not limited to patent
-     issues), conditions are imposed on you (whether by court order,
-     agreement or otherwise) that contradict the conditions of this
-     License, they do not excuse you from the conditions of this
-     License.  If you cannot distribute so as to satisfy simultaneously
-     your obligations under this License and any other pertinent
-     obligations, then as a consequence you may not distribute the
-     Library at all.  For example, if a patent license would not permit
-     royalty-free redistribution of the Library by all those who receive
-     copies directly or indirectly through you, then the only way you
-     could satisfy both it and this License would be to refrain entirely
-     from distribution of the Library.
-
-     If any portion of this section is held invalid or unenforceable
-     under any particular circumstance, the balance of the section is
-     intended to apply, and the section as a whole is intended to apply
-     in other circumstances.
-
-     It is not the purpose of this section to induce you to infringe any
-     patents or other property right claims or to contest validity of
-     any such claims; this section has the sole purpose of protecting
-     the integrity of the free software distribution system which is
-     implemented by public license practices.  Many people have made
-     generous contributions to the wide range of software distributed
-     through that system in reliance on consistent application of that
-     system; it is up to the author/donor to decide if he or she is
-     willing to distribute software through any other system and a
-     licensee cannot impose that choice.
-
-     This section is intended to make thoroughly clear what is believed
-     to be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-     certain countries either by patents or by copyrighted interfaces,
-     the original copyright holder who places the Library under this
-     License may add an explicit geographical distribution limitation
-     excluding those countries, so that distribution is permitted only
-     in or among countries not thus excluded.  In such case, this
-     License incorporates the limitation as if written in the body of
-     this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-     versions of the Lesser General Public License from time to time.
-     Such new versions will be similar in spirit to the present version,
-     but may differ in detail to address new problems or concerns.
-
-     Each version is given a distinguishing version number.  If the
-     Library specifies a version number of this License which applies to
-     it and "any later version", you have the option of following the
-     terms and conditions either of that version or of any later version
-     published by the Free Software Foundation.  If the Library does not
-     specify a license version number, you may choose any version ever
-     published by the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-     programs whose distribution conditions are incompatible with these,
-     write to the author to ask for permission.  For software which is
-     copyrighted by the Free Software Foundation, write to the Free
-     Software Foundation; we sometimes make exceptions for this.  Our
-     decision will be guided by the two goals of preserving the free
-     status of all derivatives of our free software and of promoting the
-     sharing and reuse of software generally.
-
-                              NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-     WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE
-     LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS
-     AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY
-     OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
-     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-     FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
-     PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE
-     DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR
-     OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
-     MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
-     LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
-     INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
-     INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF
-     DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
-     OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY
-     OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
-     ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-                      END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Libraries
-==============================================
-
-If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of
-the ordinary General Public License).
-
-   To apply these terms, attach the following notices to the library.
-It is safest to attach them to the start of each source file to most
-effectively convey the exclusion of warranty; and each file should have
-at least the "copyright" line and a pointer to where the full notice is
-found.
-
-     ONE LINE TO GIVE THE LIBRARY'S NAME AND AN IDEA OF WHAT IT DOES.
-     Copyright (C) YEAR  NAME OF AUTHOR
-
-     This library 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.
-
-     This library 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 library; if not, write to the Free Software
-     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
-     USA.
-
-   Also add information on how to contact you by electronic and paper
-mail.
-
-   You should also get your employer (if you work as a programmer) or
-your school, if any, to sign a "copyright disclaimer" for the library,
-if necessary.  Here is a sample; alter the names:
-
-     Yoyodyne, Inc., hereby disclaims all copyright interest in the library
-     `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-     SIGNATURE OF TY COON, 1 April 1990
-     Ty Coon, President of Vice
-
-   That's all there is to it!
-
-\1f
-File: gcrypt.info,  Node: Copying,  Next: Figures and Tables,  Prev: Library Copying,  Up: Top
-
-GNU General Public License
-**************************
-
-                         Version 2, June 1991
-
-     Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-     Everyone is permitted to copy and distribute verbatim copies
-     of this license document, but changing it is not allowed.
-
-Preamble
-========
-
-The licenses for most software are designed to take away your freedom to
-share and change it.  By contrast, the GNU General Public License is
-intended to guarantee your freedom to share and change free software--to
-make sure the software is free for all its users.  This General Public
-License applies to most of the Free Software Foundation's software and
-to any other program whose authors commit to using it.  (Some other Free
-Software Foundation software is covered by the GNU Library General
-Public License instead.)  You can apply it to your programs, too.
-
-   When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it if
-you want it, that you can change the software or use pieces of it in new
-free programs; and that you know you can do these things.
-
-   To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-   For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-   We protect your rights with two steps: (1) copyright the software,
-and (2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-   Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-   Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-   The precise terms and conditions for copying, distribution and
-modification follow.
-
-    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  1. This License applies to any program or other work which contains a
-     notice placed by the copyright holder saying it may be distributed
-     under the terms of this General Public License.  The "Program",
-     below, refers to any such program or work, and a "work based on the
-     Program" means either the Program or any derivative work under
-     copyright law: that is to say, a work containing the Program or a
-     portion of it, either verbatim or with modifications and/or
-     translated into another language.  (Hereinafter, translation is
-     included without limitation in the term "modification".)  Each
-     licensee is addressed as "you".
-
-     Activities other than copying, distribution and modification are
-     not covered by this License; they are outside its scope.  The act
-     of running the Program is not restricted, and the output from the
-     Program is covered only if its contents constitute a work based on
-     the Program (independent of having been made by running the
-     Program).  Whether that is true depends on what the Program does.
-
-  2. You may copy and distribute verbatim copies of the Program's source
-     code as you receive it, in any medium, provided that you
-     conspicuously and appropriately publish on each copy an appropriate
-     copyright notice and disclaimer of warranty; keep intact all the
-     notices that refer to this License and to the absence of any
-     warranty; and give any other recipients of the Program a copy of
-     this License along with the Program.
-
-     You may charge a fee for the physical act of transferring a copy,
-     and you may at your option offer warranty protection in exchange
-     for a fee.
-
-  3. You may modify your copy or copies of the Program or any portion of
-     it, thus forming a work based on the Program, and copy and
-     distribute such modifications or work under the terms of Section 1
-     above, provided that you also meet all of these conditions:
-
-       a. You must cause the modified files to carry prominent notices
-          stating that you changed the files and the date of any change.
-
-       b. You must cause any work that you distribute or publish, that
-          in whole or in part contains or is derived from the Program or
-          any part thereof, to be licensed as a whole at no charge to
-          all third parties under the terms of this License.
-
-       c. If the modified program normally reads commands interactively
-          when run, you must cause it, when started running for such
-          interactive use in the most ordinary way, to print or display
-          an announcement including an appropriate copyright notice and
-          a notice that there is no warranty (or else, saying that you
-          provide a warranty) and that users may redistribute the
-          program under these conditions, and telling the user how to
-          view a copy of this License.  (Exception: if the Program
-          itself is interactive but does not normally print such an
-          announcement, your work based on the Program is not required
-          to print an announcement.)
-
-     These requirements apply to the modified work as a whole.  If
-     identifiable sections of that work are not derived from the
-     Program, and can be reasonably considered independent and separate
-     works in themselves, then this License, and its terms, do not apply
-     to those sections when you distribute them as separate works.  But
-     when you distribute the same sections as part of a whole which is a
-     work based on the Program, the distribution of the whole must be on
-     the terms of this License, whose permissions for other licensees
-     extend to the entire whole, and thus to each and every part
-     regardless of who wrote it.
-
-     Thus, it is not the intent of this section to claim rights or
-     contest your rights to work written entirely by you; rather, the
-     intent is to exercise the right to control the distribution of
-     derivative or collective works based on the Program.
-
-     In addition, mere aggregation of another work not based on the
-     Program with the Program (or with a work based on the Program) on a
-     volume of a storage or distribution medium does not bring the other
-     work under the scope of this License.
-
-  4. You may copy and distribute the Program (or a work based on it,
-     under Section 2) in object code or executable form under the terms
-     of Sections 1 and 2 above provided that you also do one of the
-     following:
-
-       a. Accompany it with the complete corresponding machine-readable
-          source code, which must be distributed under the terms of
-          Sections 1 and 2 above on a medium customarily used for
-          software interchange; or,
-
-       b. Accompany it with a written offer, valid for at least three
-          years, to give any third party, for a charge no more than your
-          cost of physically performing source distribution, a complete
-          machine-readable copy of the corresponding source code, to be
-          distributed under the terms of Sections 1 and 2 above on a
-          medium customarily used for software interchange; or,
-
-       c. Accompany it with the information you received as to the offer
-          to distribute corresponding source code.  (This alternative is
-          allowed only for noncommercial distribution and only if you
-          received the program in object code or executable form with
-          such an offer, in accord with Subsection b above.)
-
-     The source code for a work means the preferred form of the work for
-     making modifications to it.  For an executable work, complete
-     source code means all the source code for all modules it contains,
-     plus any associated interface definition files, plus the scripts
-     used to control compilation and installation of the executable.
-     However, as a special exception, the source code distributed need
-     not include anything that is normally distributed (in either source
-     or binary form) with the major components (compiler, kernel, and so
-     on) of the operating system on which the executable runs, unless
-     that component itself accompanies the executable.
-
-     If distribution of executable or object code is made by offering
-     access to copy from a designated place, then offering equivalent
-     access to copy the source code from the same place counts as
-     distribution of the source code, even though third parties are not
-     compelled to copy the source along with the object code.
-
-  5. You may not copy, modify, sublicense, or distribute the Program
-     except as expressly provided under this License.  Any attempt
-     otherwise to copy, modify, sublicense or distribute the Program is
-     void, and will automatically terminate your rights under this
-     License.  However, parties who have received copies, or rights,
-     from you under this License will not have their licenses terminated
-     so long as such parties remain in full compliance.
-
-  6. You are not required to accept this License, since you have not
-     signed it.  However, nothing else grants you permission to modify
-     or distribute the Program or its derivative works.  These actions
-     are prohibited by law if you do not accept this License.
-     Therefore, by modifying or distributing the Program (or any work
-     based on the Program), you indicate your acceptance of this License
-     to do so, and all its terms and conditions for copying,
-     distributing or modifying the Program or works based on it.
-
-  7. Each time you redistribute the Program (or any work based on the
-     Program), the recipient automatically receives a license from the
-     original licensor to copy, distribute or modify the Program subject
-     to these terms and conditions.  You may not impose any further
-     restrictions on the recipients' exercise of the rights granted
-     herein.  You are not responsible for enforcing compliance by third
-     parties to this License.
-
-  8. If, as a consequence of a court judgment or allegation of patent
-     infringement or for any other reason (not limited to patent
-     issues), conditions are imposed on you (whether by court order,
-     agreement or otherwise) that contradict the conditions of this
-     License, they do not excuse you from the conditions of this
-     License.  If you cannot distribute so as to satisfy simultaneously
-     your obligations under this License and any other pertinent
-     obligations, then as a consequence you may not distribute the
-     Program at all.  For example, if a patent license would not permit
-     royalty-free redistribution of the Program by all those who receive
-     copies directly or indirectly through you, then the only way you
-     could satisfy both it and this License would be to refrain entirely
-     from distribution of the Program.
-
-     If any portion of this section is held invalid or unenforceable
-     under any particular circumstance, the balance of the section is
-     intended to apply and the section as a whole is intended to apply
-     in other circumstances.
-
-     It is not the purpose of this section to induce you to infringe any
-     patents or other property right claims or to contest validity of
-     any such claims; this section has the sole purpose of protecting
-     the integrity of the free software distribution system, which is
-     implemented by public license practices.  Many people have made
-     generous contributions to the wide range of software distributed
-     through that system in reliance on consistent application of that
-     system; it is up to the author/donor to decide if he or she is
-     willing to distribute software through any other system and a
-     licensee cannot impose that choice.
-
-     This section is intended to make thoroughly clear what is believed
-     to be a consequence of the rest of this License.
-
-  9. If the distribution and/or use of the Program is restricted in
-     certain countries either by patents or by copyrighted interfaces,
-     the original copyright holder who places the Program under this
-     License may add an explicit geographical distribution limitation
-     excluding those countries, so that distribution is permitted only
-     in or among countries not thus excluded.  In such case, this
-     License incorporates the limitation as if written in the body of
-     this License.
-
-  10. The Free Software Foundation may publish revised and/or new
-     versions of the General Public License from time to time.  Such new
-     versions will be similar in spirit to the present version, but may
-     differ in detail to address new problems or concerns.
-
-     Each version is given a distinguishing version number.  If the
-     Program specifies a version number of this License which applies to
-     it and "any later version", you have the option of following the
-     terms and conditions either of that version or of any later version
-     published by the Free Software Foundation.  If the Program does not
-     specify a version number of this License, you may choose any
-     version ever published by the Free Software Foundation.
-
-  11. If you wish to incorporate parts of the Program into other free
-     programs whose distribution conditions are different, write to the
-     author to ask for permission.  For software which is copyrighted by
-     the Free Software Foundation, write to the Free Software
-     Foundation; we sometimes make exceptions for this.  Our decision
-     will be guided by the two goals of preserving the free status of
-     all derivatives of our free software and of promoting the sharing
-     and reuse of software generally.
-
-                              NO WARRANTY
-
-  12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
-     WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
-     LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS
-     AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-     OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
-     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-     FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
-     PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
-     DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR
-     OR CORRECTION.
-
-  13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-     WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
-     MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE
-     LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
-     INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
-     INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-     DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
-     OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
-     OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
-     ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-                      END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Programs
-=============================================
-
-If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these
-terms.
-
-   To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-     ONE LINE TO GIVE THE PROGRAM'S NAME AND AN IDEA OF WHAT IT DOES.
-     Copyright (C) 19YY  NAME OF AUTHOR
-
-     This program is free software; you can redistribute it and/or
-     modify it under the terms of the GNU General Public License
-     as published by the Free Software Foundation; either version 2
-     of the License, or (at your option) any later version.
-
-     This program is distributed in the hope that it will be useful,
-     but WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-     GNU General Public License for more details.
-
-     You should have received a copy of the GNU General Public License along
-     with this program; if not, write to the Free Software Foundation, Inc.,
-     59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
-
-   Also add information on how to contact you by electronic and paper
-mail.
-
-   If the program is interactive, make it output a short notice like
-this when it starts in an interactive mode:
-
-     Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR
-     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
-     type `show w'.  This is free software, and you are welcome
-     to redistribute it under certain conditions; type `show c'
-     for details.
-
-   The hypothetical commands 'show w' and 'show c' should show the
-appropriate parts of the General Public License.  Of course, the
-commands you use may be called something other than 'show w' and 'show
-c'; they could even be mouse-clicks or menu items--whatever suits your
-program.
-
-   You should also get your employer (if you work as a programmer) or
-your school, if any, to sign a "copyright disclaimer" for the program,
-if necessary.  Here is a sample; alter the names:
-
-     Yoyodyne, Inc., hereby disclaims all copyright
-     interest in the program `Gnomovision'
-     (which makes passes at compilers) written
-     by James Hacker.
-
-     SIGNATURE OF TY COON, 1 April 1989
-     Ty Coon, President of Vice
-
-   This General Public License does not permit incorporating your
-program into proprietary programs.  If your program is a subroutine
-library, you may consider it more useful to permit linking proprietary
-applications with the library.  If this is what you want to do, use the
-GNU Library General Public License instead of this License.
-
-\1f
-File: gcrypt.info,  Node: Figures and Tables,  Next: Concept Index,  Prev: Copying,  Up: Top
-
-List of Figures and Tables
-**************************
-
-* Menu:
-
-* Figure 17.1: fig:subsystems.           Libgcrypt subsystems
-* Figure B.1: fig:fips-fsm.              FIPS mode state diagram
-
-* Menu:
-
-* Table B.1: tbl:fips-states.            FIPS mode states
-* Table B.2: tbl:fips-state-transitions. FIPS mode state transitions
-
-\1f
-File: gcrypt.info,  Node: Concept Index,  Next: Function and Data Index,  Prev: Figures and Tables,  Up: Top
-
-Concept Index
-*************
-
-\0\b[index\0\b]
-* Menu:
-
-* /etc/gcrypt/fips_enabled:              Configuration.        (line 69)
-* /etc/gcrypt/hwf.deny:                  Configuration.        (line 48)
-* /etc/gcrypt/random.conf:               Configuration.        (line 52)
-* /proc/cpuinfo:                         Configuration.        (line 74)
-* /proc/self/auxv:                       Configuration.        (line 74)
-* 3DES:                                  Available ciphers.    (line 14)
-* Advanced Encryption Standard:          Available ciphers.    (line 35)
-* AES:                                   Available ciphers.    (line 35)
-* AES-Wrap mode:                         Available cipher modes.
-                                                               (line 35)
-* Arcfour:                               Available ciphers.    (line 52)
-* BLAKE2b-512, BLAKE2b-384, BLAKE2b-256, BLAKE2b-160: Available hash algorithms.
-                                                               (line  6)
-* BLAKE2s-256, BLAKE2s-224, BLAKE2s-160, BLAKE2s-128: Available hash algorithms.
-                                                               (line  6)
-* Blowfish:                              Available ciphers.    (line 22)
-* bug emulation:                         Working with hash algorithms.
-                                                               (line 38)
-* Camellia:                              Available ciphers.    (line 77)
-* CAST5:                                 Available ciphers.    (line 19)
-* CBC, Cipher Block Chaining mode:       Available cipher modes.
-                                                               (line 23)
-* CBC-MAC:                               Working with cipher handles.
-                                                               (line 56)
-* CCM, Counter with CBC-MAC mode:        Available cipher modes.
-                                                               (line 48)
-* CFB, Cipher Feedback mode:             Available cipher modes.
-                                                               (line 17)
-* ChaCha20:                              Available ciphers.    (line 92)
-* cipher text stealing:                  Working with cipher handles.
-                                                               (line 50)
-* comp:                                  Cryptographic Functions.
-                                                               (line 13)
-* CRC32:                                 Available hash algorithms.
-                                                               (line  6)
-* CTR, Counter mode:                     Available cipher modes.
-                                                               (line 32)
-* DES:                                   Available ciphers.    (line 57)
-* DES-EDE:                               Available ciphers.    (line 14)
-* Digital Encryption Standard:           Available ciphers.    (line 14)
-* disable-jent:                          Configuration.        (line 58)
-* ECB, Electronic Codebook mode:         Available cipher modes.
-                                                               (line 13)
-* EdDSA:                                 Cryptographic Functions.
-                                                               (line 33)
-* Enforced FIPS mode:                    Enabling FIPS mode.   (line 29)
-* error codes:                           Error Values.         (line  6)
-* error codes, list of:                  Error Sources.        (line  6)
-* error codes, list of <1>:              Error Codes.          (line  6)
-* error codes, printing of:              Error Strings.        (line  6)
-* error sources:                         Error Values.         (line  6)
-* error sources, printing of:            Error Strings.        (line  6)
-* error strings:                         Error Strings.        (line  6)
-* error values:                          Error Values.         (line  6)
-* error values, printing of:             Error Strings.        (line  6)
-* FIPS 140:                              Enabling FIPS mode.   (line  6)
-* FIPS 186:                              Cryptographic Functions.
-                                                               (line 72)
-* FIPS 186 <1>:                          Public-Key Subsystem Architecture.
-                                                               (line 50)
-* FIPS 186-2:                            Cryptographic Functions.
-                                                               (line 80)
-* FIPS mode:                             Enabling FIPS mode.   (line  6)
-* fips_enabled:                          Configuration.        (line 69)
-* GCM, Galois/Counter Mode:              Available cipher modes.
-                                                               (line 53)
-* GCRYPT_BARRETT:                        Configuration.        (line 12)
-* GCRYPT_RNDUNIX_DBG:                    Configuration.        (line 17)
-* GCRYPT_RNDUNIX_DBGALL:                 Configuration.        (line 17)
-* GCRYPT_RNDW32_DBG:                     Configuration.        (line 32)
-* GCRYPT_RNDW32_NOPERF:                  Configuration.        (line 25)
-* GOST 28147-89:                         Available ciphers.    (line 88)
-* GPL, GNU General Public License:       Copying.              (line  6)
-* hardware features:                     Hardware features.    (line  6)
-* HAVAL:                                 Available hash algorithms.
-                                                               (line  6)
-* HMAC:                                  Working with hash algorithms.
-                                                               (line 28)
-* HMAC-GOSTR-3411-94:                    Available MAC algorithms.
-                                                               (line  6)
-* HMAC-MD2, HMAC-MD4, HMAC-MD5:          Available MAC algorithms.
-                                                               (line  6)
-* HMAC-RIPE-MD-160:                      Available MAC algorithms.
-                                                               (line  6)
-* HMAC-SHA-1:                            Available MAC algorithms.
-                                                               (line  6)
-* HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384, HMAC-SHA-512: Available MAC algorithms.
-                                                               (line  6)
-* HMAC-SHA3-224, HMAC-SHA3-256, HMAC-SHA3-384, HMAC-SHA3-512: Available MAC algorithms.
-                                                               (line  6)
-* HMAC-Stribog-256, HMAC-Stribog-512:    Available MAC algorithms.
-                                                               (line  6)
-* HMAC-TIGER1:                           Available MAC algorithms.
-                                                               (line  6)
-* HMAC-Whirlpool:                        Available MAC algorithms.
-                                                               (line  6)
-* HOME:                                  Configuration.        (line 37)
-* IDEA:                                  Available ciphers.    (line 11)
-* LGPL, GNU Lesser General Public License: Library Copying.    (line  6)
-* MD2, MD4, MD5:                         Available hash algorithms.
-                                                               (line  6)
-* no-blinding:                           Cryptographic Functions.
-                                                               (line 41)
-* no-keytest:                            Cryptographic Functions.
-                                                               (line 59)
-* nocomp:                                Cryptographic Functions.
-                                                               (line 13)
-* OAEP:                                  Cryptographic Functions.
-                                                               (line 27)
-* OCB, OCB3:                             Available cipher modes.
-                                                               (line 63)
-* OFB, Output Feedback mode:             Available cipher modes.
-                                                               (line 29)
-* only-urandom:                          Configuration.        (line 61)
-* param:                                 Cryptographic Functions.
-                                                               (line 47)
-* PKCS1:                                 Cryptographic Functions.
-                                                               (line 23)
-* Poly1305 based AEAD mode with ChaCha20: Available cipher modes.
-                                                               (line 58)
-* PSS:                                   Cryptographic Functions.
-                                                               (line 30)
-* RC2:                                   Available ciphers.    (line 69)
-* RC4:                                   Available ciphers.    (line 52)
-* rfc-2268:                              Available ciphers.    (line 69)
-* RFC6979:                               Cryptographic Functions.
-                                                               (line 38)
-* Rijndael:                              Available ciphers.    (line 35)
-* RIPE-MD-160:                           Available hash algorithms.
-                                                               (line  6)
-* Salsa20:                               Available ciphers.    (line 81)
-* Salsa20/12:                            Available ciphers.    (line 84)
-* Seed (cipher):                         Available ciphers.    (line 72)
-* Serpent:                               Available ciphers.    (line 65)
-* SHA-1:                                 Available hash algorithms.
-                                                               (line  6)
-* SHA-224, SHA-256, SHA-384, SHA-512:    Available hash algorithms.
-                                                               (line  6)
-* SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256: Available hash algorithms.
-                                                               (line  6)
-* sync mode (OpenPGP):                   Working with cipher handles.
-                                                               (line 46)
-* TIGER, TIGER1, TIGER2:                 Available hash algorithms.
-                                                               (line  6)
-* transient-key:                         Cryptographic Functions.
-                                                               (line 52)
-* Triple-DES:                            Available ciphers.    (line 14)
-* Twofish:                               Available ciphers.    (line 46)
-* Whirlpool:                             Available hash algorithms.
-                                                               (line  6)
-* X9.31:                                 Cryptographic Functions.
-                                                               (line 65)
-* X9.31 <1>:                             Public-Key Subsystem Architecture.
-                                                               (line 50)
-* XTS, XTS mode:                         Available cipher modes.
-                                                               (line 74)
-
diff --git a/doc/gcrypt.info-2 b/doc/gcrypt.info-2
deleted file mode 100644 (file)
index 2e683e3..0000000
Binary files a/doc/gcrypt.info-2 and /dev/null differ
index c32748f..6c8acae 100644 (file)
@@ -8,9 +8,9 @@
 @syncodeindex pg fn
 @c %**end of header
 @copying
-This manual is for Libgcrypt
-(version @value{VERSION}, @value{UPDATED}),
-which is GNU's library of cryptographic building blocks.
+This manual is for Libgcrypt version @value{VERSION} and was last
+updated @value{UPDATED}.  Libgcrypt is GNU's library of cryptographic
+building blocks.
 
 @noindent
 Copyright @copyright{} 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc. @*
@@ -169,7 +169,7 @@ Anybody can use, modify, and redistribute it under the terms of the GNU
 Lesser General Public License (@pxref{Library Copying}).  Note, that
 some parts (which are in general not needed by applications) are subject
 to the terms of the GNU General Public License (@pxref{Copying}); please
-see the README file of the distribution for of list of these parts.
+see the README file of the distribution for the list of these parts.
 
 @item It encapsulates the low level cryptography
 Libgcrypt provides a high level interface to cryptographic
@@ -211,6 +211,7 @@ of the library are verified.
 * Initializing the library::    How to initialize the library.
 * Multi-Threading::             How Libgcrypt can be used in a MT environment.
 * Enabling FIPS mode::          How to enable the FIPS mode.
+* Disabling FIPS mode::         How to disable the FIPS mode.
 * Hardware features::           How to disable hardware features.
 @end menu
 
@@ -269,7 +270,7 @@ gcc -c foo.c `libgcrypt-config --cflags`
 @end example
 
 Adding the output of @samp{libgcrypt-config --cflags} to the
-compilers command line will ensure that the compiler can find the
+compiler's command line will ensure that the compiler can find the
 Libgcrypt header file.
 
 A similar problem occurs when linking the program with the library.
@@ -316,7 +317,7 @@ Additionally, the function defines @code{LIBGCRYPT_CFLAGS} to the
 flags needed for compilation of the program to find the
 @file{gcrypt.h} header file, and @code{LIBGCRYPT_LIBS} to the linker
 flags needed to link the program to the Libgcrypt library.  If the
-used helper script does not match the target type you are building for
+used helper script does not match the target type you are building for,
 a warning is printed and the string @code{libgcrypt} is appended to the
 variable @code{gpg_config_script_warn}.
 
@@ -382,10 +383,12 @@ memory is not a problem, you should initialize Libgcrypt this way:
 
 @example
   /* Version check should be the very first call because it
-     makes sure that important subsystems are initialized. */
-  if (!gcry_check_version (GCRYPT_VERSION))
+     makes sure that important subsystems are initialized.
+     #define NEED_LIBGCRYPT_VERSION to the minimum required version. */
+  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
     @{
-      fputs ("libgcrypt version mismatch\n", stderr);
+      fprintf (stderr, "libgcrypt is too old (need %s, have %s)\n",
+         NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL));
       exit (2);
     @}
 
@@ -405,10 +408,12 @@ and freed memory, you need to initialize Libgcrypt this way:
 
 @example
   /* Version check should be the very first call because it
-     makes sure that important subsystems are initialized. */
-  if (!gcry_check_version (GCRYPT_VERSION))
+     makes sure that important subsystems are initialized.
+     #define NEED_LIBGCRYPT_VERSION to the minimum required version. */
+  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
     @{
-      fputs ("libgcrypt version mismatch\n", stderr);
+      fprintf (stderr, "libgcrypt is too old (need %s, have %s)\n",
+         NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL));
       exit (2);
     @}
 
@@ -502,14 +507,14 @@ Just like the function @code{gpg_strerror}, the function
 @cindex FIPS 140
 
 @anchor{enabling fips mode}
-Libgcrypt may be used in a FIPS 140-2 mode.  Note, that this does not
-necessary mean that Libcgrypt is an appoved FIPS 140-2 module.  Check the
+Libgcrypt may be used in a FIPS 140-3 mode.  Note, that this does not
+necessary mean that Libcgrypt is an appoved FIPS 140-3 module.  Check the
 NIST database at @url{http://csrc.nist.gov/groups/STM/cmvp/} to see what
 versions of Libgcrypt are approved.
 
 Because FIPS 140 has certain restrictions on the use of cryptography
 which are not always wanted, Libgcrypt needs to be put into FIPS mode
-explicitly.  Three alternative mechanisms are provided to switch
+explicitly.  Four alternative mechanisms are provided to switch
 Libgcrypt into this mode:
 
 @itemize
@@ -525,26 +530,36 @@ into FIPS mode at initialization time.  Note that this filename is
 hardwired and does not depend on any configuration options.
 
 @item
+By setting the environment variable @code{LIBGCRYPT_FORCE_FIPS_MODE},
+Libgcrypt is put into FIPS mode at initialization time.
+
+@item
 If the application requests FIPS mode using the control command
 @code{GCRYCTL_FORCE_FIPS_MODE}.  This must be done prior to any
 initialization (i.e. before @code{gcry_check_version}).
 
 @end itemize
 
-@cindex Enforced FIPS mode
 
-In addition to the standard FIPS mode, Libgcrypt may also be put into
-an Enforced FIPS mode by writing a non-zero value into the file
-@file{/etc/gcrypt/fips_enabled} or by using the control command
-@code{GCRYCTL_SET_ENFORCED_FIPS_FLAG} before any other calls to
-libgcrypt.  The Enforced FIPS mode helps to detect applications
-which don't fulfill all requirements for using
-Libgcrypt in FIPS mode (@pxref{FIPS Mode}).
+@node Disabling FIPS mode
+@section How to disable the FIPS mode
+@cindex FIPS mode
+@cindex FIPS 140
+
+@anchor{disabling fips mode}
+When the system is configured using libgcrypt in FIPS mode (by file or
+environement variable), but an application wants to use non-FIPS
+features, Libgcrypt needs to be gotten out of FIPS mode.  A mechanism
+is provided to switch Libgcrypt into non-FIPS mode:
+
+@itemize
+@item
+If the application requests non-FIPS mode using the control command
+@code{GCRYCTL_NO_FIPS_MODE}.  This must be done prior to any
+initialization (i.e. before @code{gcry_check_version}).
+@end itemize
+
 
-Once Libgcrypt has been put into FIPS mode, it is not possible to
-switch back to standard mode without terminating the process first.
-If the logging verbosity level of Libgcrypt has been set to at least
-2, the state transitions and the self-tests are logged.
 
 @node Hardware features
 @section How to disable hardware features
@@ -552,7 +567,7 @@ If the logging verbosity level of Libgcrypt has been set to at least
 
 @anchor{hardware features}
 Libgcrypt makes use of certain hardware features.  If the use of a
-feature is not desired it may be either be disabled by a program or
+feature is not desired, it may be disabled either by a program or
 globally using a configuration file.  The currently supported features
 are
 
@@ -565,13 +580,30 @@ are
 @item intel-fast-shld
 @item intel-bmi2
 @item intel-ssse3
+@item intel-sse4.1
 @item intel-pclmul
 @item intel-aesni
 @item intel-rdrand
 @item intel-avx
 @item intel-avx2
+@item intel-fast-vpgather
 @item intel-rdtsc
+@item intel-shaext
+@item intel-vaes-vpclmul
 @item arm-neon
+@item arm-aes
+@item arm-sha1
+@item arm-sha2
+@item arm-pmull
+@item ppc-vcrypto
+@item ppc-arch_3_00
+@item ppc-arch_2_07
+@item ppc-arch_3_10
+@item s390x-msa
+@item s390x-msa-4
+@item s390x-msa-8
+@item s390x-msa-9
+@item s390x-vx
 @end table
 
 To disable a feature for all processes using Libgcrypt 1.6 or newer,
@@ -580,11 +612,11 @@ to be used on a single line.  Empty lines, white space, and lines
 prefixed with a hash mark are ignored.  The file should be world
 readable.
 
-To disable a feature specifically for a program that program must tell
+To disable a feature specifically for a program, that program must tell
 it Libgcrypt before before calling @code{gcry_check_version}.
 Example:@footnote{NB. Libgcrypt uses the RDRAND feature only as one
 source of entropy.  A CPU with a broken RDRAND will thus not
-compromise of the random number generator}
+compromise the random number generator}
 
 @example
   gcry_control (GCRYCTL_DISABLE_HWF, "intel-rdrand", NULL);
@@ -658,10 +690,8 @@ to disable secure memory is to use @code{GCRYCTL_DISABLE_SECMEM} right
 after initialization.
 
 @item GCRYCTL_DISABLE_SECMEM; Arguments: none
-This command disables the use of secure memory.  If this command is
-used in FIPS mode, FIPS mode will be disabled and the function
-@code{gcry_fips_mode_active} returns false.  However, in Enforced FIPS
-mode this command has no effect at all.
+This command disables the use of secure memory.  In FIPS mode this command
+has no effect at all.
 
 Many applications do not require secure memory, so they should disable
 it right away.  This command should be executed right after
@@ -672,7 +702,7 @@ This command disables the use of the mlock call for secure memory.
 Disabling the use of mlock may for example be done if an encrypted
 swap space is in use.  This command should be executed right after
 @code{gcry_check_version}.  Note that by using functions like
-gcry_xmalloc_secure and gcry_mpi_snew Libgcrypt may expand the secure
+@code{gcry_xmalloc_secure} and @code{gcry_mpi_snew} Libgcrypt may expand the secure
 memory pool with memory which lacks the property of not being swapped
 out to disk (but will still be zeroed out on free).
 
@@ -696,10 +726,21 @@ the process has (i.e. if it is run as setuid (root)).  If the argument
 of secure memory allocated is currently 16384 bytes; you may thus use a
 value of 1 to request that default size.
 
+@item GCRYCTL_AUTO_EXPAND_SECMEM; Arguments: unsigned int chunksize
+This command enables on-the-fly expanding of the secure memory area.
+Note that by using functions like @code{gcry_xmalloc_secure} and
+@code{gcry_mpi_snew} will do this auto expanding anyway.  The argument
+to this option is the suggested size for new secure memory areas.  A
+larger size improves performance of all memory allocation and
+releasing functions.  The given chunksize is rounded up to the next
+32KiB.  The drawback of auto expanding is that memory might be swapped
+out to disk; this can be fixed by configuring the system to use an
+encrypted swap space.
+
 @item GCRYCTL_TERM_SECMEM; Arguments: none
 This command zeroises the secure memory and destroys the handler.  The
 secure memory pool may not be used anymore after running this command.
-If the secure memory pool as already been destroyed, this command has
+If the secure memory pool has already been destroyed, this command has
 no effect.  Applications might want to run this command from their
 exit handler to make sure that the secure memory gets properly
 destroyed.  This command is not necessarily thread-safe but that
@@ -751,9 +792,9 @@ and clock of the application, and drain the system's entropy pool to
 reduce the "up to 16 bytes" above to 0.  Then the dependencies of the
 initial states of the pools are completely known.  Note that this is not
 an issue if random of @code{GCRY_VERY_STRONG_RANDOM} quality is
-requested as in this case enough extra entropy gets mixed.  It is also
-not an issue when using Linux (rndlinux driver), because this one
-guarantees to read full 16 bytes from /dev/urandom and thus there is no
+requested, as in this case enough extra entropy gets mixed.  It is also
+not an issue when using rndgetentropy or rndoldlinux module, because the
+module guarantees to read full 16 bytes and thus there is no
 way for an attacker without kernel access to control these 16 bytes.
 
 @item GCRYCTL_CLOSE_RANDOM_DEVICE; Arguments: none
@@ -766,14 +807,14 @@ re-opened.  On non-Unix systems this control code is ignored.
 
 @item GCRYCTL_SET_VERBOSITY; Arguments: int level
 This command sets the verbosity of the logging.  A level of 0 disables
-all extra logging whereas positive numbers enable more verbose logging.
+all extra logging, whereas positive numbers enable more verbose logging.
 The level may be changed at any time but be aware that no memory
 synchronization is done so the effect of this command might not
 immediately show up in other threads.  This command may even be used
 prior to @code{gcry_check_version}.
 
 @item GCRYCTL_SET_DEBUG_FLAGS; Arguments: unsigned int flags
-Set the debug flag bits as given by the argument.  Be aware that that no
+Set the debug flag bits as given by the argument.  Be aware that no
 memory synchronization is done so the effect of this command might not
 immediately show up in other threads.  The debug flags are not
 considered part of the API and thus may change without notice.  As of
@@ -794,15 +835,15 @@ This command does nothing.  It exists only for backward compatibility.
 This command returns true if the library has been basically initialized.
 Such a basic initialization happens implicitly with many commands to get
 certain internal subsystems running.  The common and suggested way to
-do this basic initialization is by calling gcry_check_version.
+do this basic initialization is by calling @code{gcry_check_version}.
 
 @item GCRYCTL_INITIALIZATION_FINISHED; Arguments: none
 This command tells the library that the application has finished the
 initialization.
 
 @item GCRYCTL_INITIALIZATION_FINISHED_P; Arguments: none
-This command returns true if the command@*
-GCRYCTL_INITIALIZATION_FINISHED has already been run.
+This command returns true if the command
+@code{GCRYCTL_INITIALIZATION_FINISHED} has already been run.
 
 @item GCRYCTL_SET_THREAD_CBS; Arguments: struct ath_ops *ath_ops
 This command is obsolete since version 1.6.
@@ -822,14 +863,14 @@ proper random device.
 
 @item GCRYCTL_PRINT_CONFIG; Arguments: FILE *stream
 This command dumps information pertaining to the configuration of the
-library to the given stream.  If NULL is given for @var{stream}, the log
+library to the given stream.  If @code{NULL} is given for @var{stream}, the log
 system is used.  This command may be used before the initialization has
 been finished but not before a @code{gcry_check_version}.  Note that
 the macro @code{estream_t} can be used instead of @code{gpgrt_stream_t}.
 
 @item GCRYCTL_OPERATIONAL_P; Arguments: none
 This command returns true if the library is in an operational state.
-This information makes only sense in FIPS mode.  In contrast to other
+This information makes sense only in FIPS mode.  In contrast to other
 functions, this is a pure test function and won't put the library into
 FIPS mode or change the internal state.  This command may be used before
 the initialization has been finished but not before a @code{gcry_check_version}.
@@ -856,16 +897,17 @@ already in FIPS mode, a self-test is triggered and thus the library will
 be put into operational state.  This command may be used before a call
 to @code{gcry_check_version} and that is actually the recommended way to let an
 application switch the library into FIPS mode.  Note that Libgcrypt will
-reject an attempt to switch to fips mode during or after the initialization.
+reject an attempt to switch to FIPS mode during or after the initialization.
+
+@item GCRYCTL_NO_FIPS_MODE; Arguments: none
+Running this command puts the library into non-FIPS mode.  This
+command may be used before a call to @code{gcry_check_version} and
+that is actually the recommended way to let an application switch the
+library into non-FIPS mode.  Note that Libgcrypt will reject an attempt to
+switch to non-FIPS mode during or after the initialization.
 
 @item GCRYCTL_SET_ENFORCED_FIPS_FLAG; Arguments: none
-Running this command sets the internal flag that puts the library into
-the enforced FIPS mode during the FIPS mode initialization.  This command
-does not affect the library if the library is not put into the FIPS mode and
-it must be used before any other libgcrypt library calls that initialize
-the library such as @code{gcry_check_version}. Note that Libgcrypt will
-reject an attempt to switch to the enforced fips mode during or after
-the initialization.
+This command is obsolete and has no effect; do not use it.
 
 @item GCRYCTL_SET_PREFERRED_RNG_TYPE; Arguments: int
 These are advisory commands to select a certain random number
@@ -873,7 +915,7 @@ generator.  They are only advisory because libraries may not know what
 an application actually wants or vice versa.  Thus Libgcrypt employs a
 priority check to select the actually used RNG.  If an applications
 selects a lower priority RNG but a library requests a higher priority
-RNG Libgcrypt will switch to the higher priority RNG.  Applications
+RNG, Libgcrypt will switch to the higher priority RNG.  Applications
 and libraries should use these control codes before
 @code{gcry_check_version}.  The available generators are:
 @table @code
@@ -881,7 +923,7 @@ and libraries should use these control codes before
 A conservative standard generator based on the ``Continuously Seeded
 Pseudo Random Number Generator'' designed by Peter Gutmann.
 @item GCRY_RNG_TYPE_FIPS
-A deterministic random number generator conforming to he document
+A deterministic random number generator conforming to the document
 ``NIST-Recommended Random Number Generator Based on ANSI X9.31
 Appendix A.2.4 Using the 3-Key Triple DES and AES Algorithms''
 (2005-01-31).  This implementation uses the AES variant.
@@ -927,10 +969,23 @@ needs to be initialized before the user land threading systems and at
 that point the system call clamp has not been registered with
 Libgpg-error and in turn Libgcrypt would not use them.  The control
 code can be used to tell Libgcrypt that a system call clamp has now
-been registered with Libgpg-error and advised it to read the clamp
-again.  Obviously this control code may only be used before a second
-thread is started in a process.
+been registered with Libgpg-error and advise Libgcrypt to read the
+clamp again.  Obviously this control code may only be used before a
+second thread is started in a process.
+
+@item GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER; Arguments: enum gcry_cipher_algos [, enum gcry_cipher_modes]
+
+Check if the given symmetric cipher and optional cipher mode combination
+is approved under the current FIPS 140-3 certification. If the
+combination is approved, this function returns @code{GPG_ERR_NO_ERROR}.
+Otherwise @code{GPG_ERR_NOT_SUPPORTED} is returned.
+
+@item GCRYCTL_FIPS_SERVICE_INDICATOR_KDF; Arguments: enum gcry_kdf_algos
 
+Check if the given KDF is approved under the current FIPS 140-3
+certification. If the KDF is approved, this function returns
+@code{GPG_ERR_NO_ERROR}. Otherwise @code{GPG_ERR_NOT_SUPPORTED}
+is returned.
 
 @end table
 
@@ -950,7 +1005,7 @@ descriptive message to the user and cancelling the operation.
 
 Some error values do not indicate a system error or an error in the
 operation, but the result of an operation that failed properly.  For
-example, if you try to decrypt a tempered message, the decryption will
+example, if you try to decrypt a tampered message, the decryption will
 fail.  Another error value actually means that the end of a data
 buffer or list has been reached.  The following descriptions explain
 for many error codes what they mean usually.  Some error values have
@@ -1021,7 +1076,7 @@ A list of important error sources can be found in the next section.
 @deftp {Data type} {gcry_error_t}
 The @code{gcry_error_t} type is an alias for the @code{libgpg-error}
 type @code{gpg_error_t}.  An error value like this has always two
-components, an error code and an error source.  Both together form the
+components: an error code and an error source.  Both together form the
 error value.
 
 Thus, the error value can not be directly compared against an error
@@ -1392,7 +1447,7 @@ Fermat test on 10 candidates failed.
 @item :
 Restart with a new random value.
 @item +
-Rabin Miller test passed.
+Rabin-Miller test passed.
 @end table
 
 @end table
@@ -1430,7 +1485,7 @@ general not recommended because the standard Libgcrypt allocation
 functions are guaranteed to zeroize memory if needed.
 
 This function may be used only during initialization and may not be
-used in fips mode.
+used in FIPS mode.
 
 
 @end deftypefun
@@ -1516,7 +1571,7 @@ This is the IDEA algorithm.
 @cindex Triple-DES
 @cindex DES-EDE
 @cindex Digital Encryption Standard
-Triple-DES with 3 Keys as EDE.  The key size of this algorithm is 168 but
+Triple-DES with 3 keys as EDE.  The key size of this algorithm is 168 bits but
 you have to pass 192 bits because the most significant bits of each byte
 are ignored.
 
@@ -1526,8 +1581,8 @@ CAST128-5 block cipher algorithm.  The key size is 128 bits.
 
 @item GCRY_CIPHER_BLOWFISH
 @cindex Blowfish
-The blowfish algorithm. The current implementation allows only for a key
-size of 128 bits.
+The blowfish algorithm. The supported key sizes are 8 to 576 bits in
+8 bit increments.
 
 @item GCRY_CIPHER_SAFER_SK128
 Reserved and not currently implemented.
@@ -1568,7 +1623,7 @@ avoid a couple of weaknesses.
 
 @item  GCRY_CIPHER_DES
 @cindex DES
-Standard DES with a 56 bit key. You need to pass 64 bit but the high
+Standard DES with a 56 bit key. You need to pass 64 bits but the high
 bits of each byte are ignored.  Note, that this is a weak algorithm
 which can be broken in reasonable time using a brute force approach.
 
@@ -1608,10 +1663,23 @@ This is the Salsa20/12 - reduced round version of Salsa20 stream cipher.
 The GOST 28147-89 cipher, defined in the respective GOST standard.
 Translation of this GOST into English is provided in the RFC-5830.
 
+@item GCRY_CIPHER_GOST28147_MESH
+@cindex GOST 28147-89 CryptoPro keymeshing
+The GOST 28147-89 cipher, defined in the respective GOST standard.
+Translation of this GOST into English is provided in the RFC-5830.
+This cipher will use CryptoPro keymeshing as defined in RFC 4357
+if it has to be used for the selected parameter set.
+
 @item GCRY_CIPHER_CHACHA20
 @cindex ChaCha20
 This is the ChaCha20 stream cipher.
 
+@item GCRY_CIPHER_SM4
+@cindex SM4 (cipher)
+A 128 bit cipher by the State Cryptography Administration
+of China (SCA).  See
+@uref{https://tools.ietf.org/html/draft-ribose-cfrg-sm4-10}.
+
 @end table
 
 @node Available cipher modes
@@ -1630,9 +1698,9 @@ Electronic Codebook mode.
 @item GCRY_CIPHER_MODE_CFB
 @item GCRY_CIPHER_MODE_CFB8
 @cindex CFB, Cipher Feedback mode
-Cipher Feedback mode.  For GCRY_CIPHER_MODE_CFB the shift size equals
+Cipher Feedback mode.  For @code{GCRY_CIPHER_MODE_CFB} the shift size equals
 the block size of the cipher (e.g. for AES it is CFB-128).  For
-GCRY_CIPHER_MODE_CFB8 the shift size is 8 bit but that variant is not
+@code{GCRY_CIPHER_MODE_CFB8} the shift size is 8 bits but that variant is not
 yet available.
 
 @item  GCRY_CIPHER_MODE_CBC
@@ -1655,12 +1723,12 @@ Counter mode.
 This mode is used to implement the AES-Wrap algorithm according to
 RFC-3394.  It may be used with any 128 bit block length algorithm,
 however the specs require one of the 3 AES algorithms.  These special
-conditions apply: If @code{gcry_cipher_setiv} has not been used the
-standard IV is used; if it has been used the lower 64 bit of the IV
+conditions apply: If @code{gcry_cipher_setiv} has not been used, the
+standard IV is used; if it has been used, the lower 64 bits of the IV
 are used as the Alternative Initial Value.  On encryption the provided
-output buffer must be 64 bit (8 byte) larger than the input buffer;
+output buffer must be 64 bits (8 bytes) larger than the input buffer;
 in-place encryption is still allowed.  On decryption the output buffer
-may be specified 64 bit (8 byte) shorter than then input buffer.  As
+may be specified 64 bits (8 bytes) shorter than then input buffer.  As
 per specs the input length must be at least 128 bits and the length
 must be a multiple of 64 bits.
 
@@ -1679,17 +1747,17 @@ Associated Data (AEAD) block cipher mode, which is specified in
 @item  GCRY_CIPHER_MODE_POLY1305
 @cindex Poly1305 based AEAD mode with ChaCha20
 This mode implements the Poly1305 Authenticated Encryption with Associated
-Data (AEAD) mode according to RFC-7539. This mode can be used with ChaCha20
+Data (AEAD) mode according to RFC-8439. This mode can be used with ChaCha20
 stream cipher.
 
 @item  GCRY_CIPHER_MODE_OCB
 @cindex OCB, OCB3
 OCB is an Authenticated Encryption with Associated Data (AEAD) block
 cipher mode, which is specified in RFC-7253.  Supported tag lengths
-are 128, 96, and 64 bit with the default being 128 bit.  To switch to
-a different tag length @code{gcry_cipher_ctl} using the command
+are 128, 96, and 64 bits with the default being 128 bits.  To switch to
+a different tag length, @code{gcry_cipher_ctl} using the command
 @code{GCRYCTL_SET_TAGLEN} and the address of an @code{int} variable
-set to 12 (for 96 bit) or 8 (for 64 bit) provided for the
+set to 12 (for 96 bits) or 8 (for 64 bits) provided for the
 @code{buffer} argument and @code{sizeof(int)} for @code{buflen}.
 
 Note that the use of @code{gcry_cipher_final} is required.
@@ -1711,6 +1779,50 @@ value is automatically incremented after each call of
 Auto-increment allows avoiding need of setting IV between processing
 of sequential data units.
 
+@item  GCRY_CIPHER_MODE_EAX
+@cindex EAX, EAX mode
+EAX is an Authenticated Encryption with Associated Data (AEAD) block cipher
+mode by Bellare, Rogaway, and Wagner (see
+@uref{http://web.cs.ucdavis.edu/~rogaway/papers/eax.html}).
+
+@item  GCRY_CIPHER_MODE_SIV
+@cindex SIV, SIV mode
+Synthetic Initialization Vector (SIV) is an Authenticated Encryption
+with Associated Data (AEAD) block cipher mode, which is specified in
+RFC-5297.  This mode works with block ciphers with block size of 128
+bits and uses tag length of 128 bits.  Depending on how it is used,
+SIV achieves either the goal of deterministic authenticated encryption
+or the goal of nonce-based, misuse-resistant authenticated encryption.
+
+The SIV mode requires doubling key-length, for example, using 512-bit
+key with AES-256 (@code{GCRY_CIPHER_AES256}). Multiple AD instances can
+be passed to SIV mode with separate calls to
+@code{gcry_cipher_authenticate}. Nonce may be passed either through
+@code{gcry_cipher_setiv} or in the last call to
+@code{gcry_cipher_authenticate}. Note that use of @code{gcry_cipher_setiv}
+blocks any further calls to @code{gcry_cipher_authenticate} as nonce needs
+to be the last AD element with the SIV mode. When encrypting or decrypting,
+full-sized plaintext or ciphertext needs to be passed to
+@code{gcry_cipher_encrypt} or @code{gcry_cipher_decrypt}. Decryption tag
+needs to be given to SIV mode before decryption using
+@code{gcry_cipher_set_decryption_tag}.
+
+@item  GCRY_CIPHER_MODE_GCM_SIV
+@cindex GCM-SIV, GCM-SIV mode, AES-GCM-SIV
+This mode implements is GCM-SIV Authenticated Encryption with
+Associated Data (AEAD) block cipher mode specified in RFC-5297
+(AES-GCM-SIV: Nonce Misuse-Resistant Authenticated Encryption).
+This implementations works with block ciphers with block size of
+128 bits and uses tag length of 128 bits.  Supported key lengths
+by the mode are 128 bits and 256 bits. GCM-SIV is specified as
+nonce misuse resistant, so that it does not fail catastrophically
+if a nonce is repeated.
+
+When encrypting or decrypting, full-sized plaintext or ciphertext
+needs to be passed to @code{gcry_cipher_encrypt} or
+@code{gcry_cipher_decrypt}. Decryption tag needs to be given to
+GCM-SIV mode before decryption using @code{gcry_cipher_set_decryption_tag}.
+
 @end table
 
 @node Working with cipher handles
@@ -1726,7 +1838,7 @@ other cipher functions and returns a handle to it in `hd'.  In case of
 an error, an according error code is returned.
 
 The ID of algorithm to use must be specified via @var{algo}.  See
-@ref{Available ciphers}, for a list of supported ciphers and the
+@ref{Available ciphers} for a list of supported ciphers and the
 according constants.
 
 Besides using the constants directly, the function
@@ -1734,19 +1846,22 @@ Besides using the constants directly, the function
 an algorithm into the according numeric ID.
 
 The cipher mode to use must be specified via @var{mode}.  See
-@ref{Available cipher modes}, for a list of supported cipher modes
+@ref{Available cipher modes} for a list of supported cipher modes
 and the according constants.  Note that some modes are incompatible
 with some algorithms - in particular, stream mode
 (@code{GCRY_CIPHER_MODE_STREAM}) only works with stream ciphers.
 Poly1305 AEAD mode (@code{GCRY_CIPHER_MODE_POLY1305}) only works with
 ChaCha20 stream cipher. The block cipher modes
 (@code{GCRY_CIPHER_MODE_ECB}, @code{GCRY_CIPHER_MODE_CBC},
-@code{GCRY_CIPHER_MODE_CFB}, @code{GCRY_CIPHER_MODE_OFB} and
-@code{GCRY_CIPHER_MODE_CTR}) will work with any block cipher
-algorithm.  GCM mode (@code{GCRY_CIPHER_MODE_CCM}), CCM mode
-(@code{GCRY_CIPHER_MODE_GCM}), OCB mode (@code{GCRY_CIPHER_MODE_OCB}),
-and XTS mode (@code{GCRY_CIPHER_MODE_XTS}) will only work
-with block cipher algorithms which have the block size of 16 bytes.
+@code{GCRY_CIPHER_MODE_CFB}, @code{GCRY_CIPHER_MODE_OFB},
+@code{GCRY_CIPHER_MODE_CTR} and @code{GCRY_CIPHER_MODE_EAX}) will work
+with any block cipher algorithm.  GCM mode
+(@code{GCRY_CIPHER_MODE_GCM}), CCM mode (@code{GCRY_CIPHER_MODE_CCM}),
+OCB mode (@code{GCRY_CIPHER_MODE_OCB}), XTS mode
+(@code{GCRY_CIPHER_MODE_XTS}), SIV mode
+(@code{GCRY_CIPHER_MODE_SIV}) and GCM-SIV mode
+(@code{GCRY_CIPHER_MODE_GCM_SIV}) will only work with block cipher
+algorithms which have the block size of 16 bytes.
 
 The third argument @var{flags} can either be passed as @code{0} or as
 the bit-wise OR of the following constants.
@@ -1763,13 +1878,13 @@ See @code{gcry_cipher_sync}.
 @item GCRY_CIPHER_CBC_CTS
 @cindex cipher text stealing
 Enable cipher text stealing (CTS) for the CBC mode.  Cannot be used
-simultaneous as GCRY_CIPHER_CBC_MAC.  CTS mode makes it possible to
+simultaneously with GCRY_CIPHER_CBC_MAC.  CTS mode makes it possible to
 transform data of almost arbitrary size (only limitation is that it
 must be greater than the algorithm's block size).
 @item GCRY_CIPHER_CBC_MAC
 @cindex CBC-MAC
 Compute CBC-MAC keyed checksums.  This is the same as CBC mode, but
-only output the last block.  Cannot be used simultaneous as
+only output the last block.  Cannot be used simultaneously with
 GCRY_CIPHER_CBC_CTS.
 @end table
 @end deftypefun
@@ -1820,16 +1935,16 @@ needs to be called after setting the key.
 Set the counter vector used for encryption or decryption. The counter
 is passed as the buffer @var{c} of length @var{l} bytes and copied to
 internal data structures.  The function checks that the counter
-matches the requirement of the selected algorithm (i.e., it must be
+matches the requirement of the selected algorithm (i.e., it must have
 the same size as the block size).
 @end deftypefun
 
 @deftypefun gcry_error_t gcry_cipher_reset (gcry_cipher_hd_t @var{h})
 
 Set the given handle's context back to the state it had after the last
-call to gcry_cipher_setkey and clear the initialization vector.
+call to @code{gcry_cipher_setkey} and clear the initialization vector.
 
-Note that gcry_cipher_reset is implemented as a macro.
+Note that @code{gcry_cipher_reset} is implemented as a macro.
 @end deftypefun
 
 Authenticated Encryption with Associated Data (AEAD) block cipher
@@ -1938,6 +2053,16 @@ implemented as a macro.
 @end deftypefun
 
 
+The SIV mode and the GCM-SIV mode requires decryption tag to be input
+before decryption. This is done with:
+
+@deftypefun gcry_error_t gcry_cipher_set_decryption_tag (gcry_cipher_hd_t @var{h}, const void *@var{tag}, size_t @var{taglen})
+
+Set decryption tag for SIV or GCM-SIV mode decryption.  This is
+implemented as a macro.
+@end deftypefun
+
+
 OpenPGP (as defined in RFC-4880) requires a special sync operation in
 some places.  The following function is used for this:
 
@@ -1945,7 +2070,7 @@ some places.  The following function is used for this:
 
 Perform the OpenPGP sync operation on context @var{h}.  Note that this
 is a no-op unless the context was created with the flag
-@code{GCRY_CIPHER_ENABLE_SYNC}
+@code{GCRY_CIPHER_ENABLE_SYNC}.
 @end deftypefun
 
 Some of the described functions are implemented as macros utilizing a
@@ -1957,7 +2082,7 @@ directly but there is nothing which would inhibit it:
 @code{gcry_cipher_ctl} controls various aspects of the cipher module and
 specific cipher contexts.  Usually some more specialized functions or
 macros are used for this purpose.  The semantics of the function and its
-parameters depends on the the command @var{cmd} and the passed context
+parameters depends on the command @var{cmd} and the passed context
 handle @var{h}.  Please see the comments in the source code
 (@code{src/global.c}) for details.
 @end deftypefun
@@ -1974,7 +2099,7 @@ information about a cipher context or the cipher module in general.
 @item GCRYCTL_GET_TAGLEN:
 Return the length of the tag for an AE algorithm mode.  An error is
 returned for modes which do not support a tag.  @var{buffer} must be
-given as NULL.  On success the result is stored @var{nbytes}.  The
+given as @code{NULL}.  On success the result is stored @var{nbytes}.  The
 taglen is returned in bytes.
 
 @end table
@@ -2035,7 +2160,7 @@ length is returned.  On error @code{0} is returned.  The key length is
 returned as number of octets.
 
 This is a convenience functions which should be preferred over
-@code{gcry_cipher_algo_info} because it allows for proper type
+@code{gcry_cipher_algo_info} because it allows proper type
 checking.
 @end deftypefun
 @c end gcry_cipher_get_algo_keylen
@@ -2046,7 +2171,7 @@ This functions returns the block-length of the algorithm @var{algo}
 counted in octets.  On error @code{0} is returned.
 
 This is a convenience functions which should be preferred over
-@code{gcry_cipher_algo_info} because it allows for proper type
+@code{gcry_cipher_algo_info} because it allows proper type
 checking.
 @end deftypefun
 @c end gcry_cipher_get_algo_blklen
@@ -2064,7 +2189,7 @@ not be used to test for the availability of an algorithm.
 
 @code{gcry_cipher_map_name} returns the algorithm identifier for the
 cipher algorithm described by the string @var{name}.  If this algorithm
-is not available @code{0} is returned.
+is not available, @code{0} is returned.
 @end deftypefun
 
 @deftypefun int gcry_cipher_mode_from_oid (const char *@var{string})
@@ -2093,6 +2218,7 @@ S-expressions.
 * Available algorithms::        Algorithms supported by the library.
 * Used S-expressions::          Introduction into the used S-expression.
 * Cryptographic Functions::     Functions for performing the cryptographic actions.
+* Dedicated ECC Functions::     Dedicated functions for elliptic curves.
 * General public-key related Functions::  General functions, not implementing any cryptography.
 @end menu
 
@@ -2100,8 +2226,7 @@ S-expressions.
 @section Available algorithms
 
 Libgcrypt supports the RSA (Rivest-Shamir-Adleman) algorithms as well
-as DSA (Digital Signature Algorithm) and Elgamal.  The versatile
-interface allows to add more algorithms in the future.
+as DSA (Digital Signature Algorithm), Elgamal, ECDSA, ECDH, and EdDSA.
 
 @node Used S-expressions
 @section Used S-expressions
@@ -2109,7 +2234,7 @@ interface allows to add more algorithms in the future.
 Libgcrypt's API for asymmetric cryptography is based on data structures
 called S-expressions (see
 @uref{http://people.csail.mit.edu/@/rivest/@/sexp.html}) and does not work
-with contexts as most of the other building blocks of Libgcrypt do.
+with contexts/handles as most of the other building blocks of Libgcrypt do.
 
 @noindent
 The following information are stored in S-expressions:
@@ -2134,7 +2259,7 @@ uppercase
 @iftex
 italics
 @end iftex
-indicate parameters whereas lowercase words are literals.
+indicate parameters, whereas lowercase words are literals.
 
 Note that all MPI (multi-precision-integers) values are expected to be in
 @code{GCRYMPI_FMT_USG} format.  An easy way to create S-expressions is
@@ -2190,10 +2315,10 @@ RSA secret prime @math{q} with @math{p < q}.
 Multiplicative inverse @math{u = p^{-1} \bmod q}.
 @end table
 
-For signing and decryption the parameters @math{(p, q, u)} are optional
+For signing and decryption, the parameters @math{(p, q, u)} are optional
 but greatly improve the performance.  Either all of these optional
 parameters must be given or none of them.  They are mandatory for
-gcry_pk_testkey.
+@code{gcry_pk_testkey}.
 
 Note that OpenSSL uses slighly different parameters: @math{q < p} and
  @math{u = q^{-1} \bmod p}.  To use these parameters you will need to
@@ -2239,7 +2364,7 @@ DSA public key value @math{y = g^x \bmod p}.
 DSA secret exponent x.
 @end table
 
-The public key is similar with "private-key" replaced by "public-key"
+The public key is similar, with "private-key" replaced by "public-key"
 and no @var{x-mpi}.
 
 
@@ -2283,9 +2408,9 @@ general only support uncompressed points, thus the first byte needs to
 be @code{0x04}.  However ``EdDSA'' describes its own compression
 scheme which is used by default; the non-standard first byte
 @code{0x40} may optionally be used to explicit flag the use of the
-algorithms native compression method.
+algorithm's native compression method.
 
-The public key is similar with "private-key" replaced by "public-key"
+The public key is similar, with "private-key" replaced by "public-key"
 and no @var{d-mpi}.
 
 If the domain parameters are well-known, the name of this curve may be
@@ -2305,30 +2430,158 @@ missing parameters.
 
 @noindent
 Currently implemented curves are:
+
 @table @code
+@item Curve25519
+@itemx X25519
+@itemx 1.3.6.1.4.1.3029.1.5.1
+@itemx 1.3.101.110
+The RFC-8410 255 bit curve, its RFC name, OpenPGP and RFC OIDs.
+
+@item X448
+@itemx 1.3.101.111
+The RFC-8410 448 bit curve and its RFC OID.
+
+@item Ed25519
+@itemx 1.3.6.1.4.1.11591.15.1
+@itemx 1.3.101.112
+The signing variant of the RFC-8410 255 bit curve, its OpenPGP and RFC OIDs.
+
+@item Ed448
+@itemx 1.3.101.113
+The signing variant of the RFC-8410 448 bit curve and its RFC OID.
+
 @item NIST P-192
 @itemx 1.2.840.10045.3.1.1
+@itemx nistp192
 @itemx prime192v1
 @itemx secp192r1
-The NIST 192 bit curve, its OID, X9.62 and SECP aliases.
+The NIST 192 bit curve, its OID and aliases.
 
 @item NIST P-224
+@itemx 1.3.132.0.33
+@itemx nistp224
 @itemx secp224r1
-The NIST 224 bit curve and its SECP alias.
+The NIST 224 bit curve, its OID and aliases.
 
 @item NIST P-256
 @itemx 1.2.840.10045.3.1.7
+@itemx nistp256
 @itemx prime256v1
 @itemx secp256r1
-The NIST 256 bit curve, its OID, X9.62 and SECP aliases.
+The NIST 256 bit curve, its OID and aliases.
 
 @item NIST P-384
+@itemx 1.3.132.0.34
+@itemx nistp384
 @itemx secp384r1
-The NIST 384 bit curve and its SECP alias.
+The NIST 384 bit curve, its OID and aliases.
 
 @item NIST P-521
+@itemx 1.3.132.0.35
+@itemx nistp521
 @itemx secp521r1
-The NIST 521 bit curve and its SECP alias.
+The NIST 521 bit curve, its OID and aliases.
+
+@item brainpoolP160r1
+@itemx 1.3.36.3.3.2.8.1.1.1
+The Brainpool 160 bit curve and its OID.
+
+@item brainpoolP192r1
+@itemx 1.3.36.3.3.2.8.1.1.3
+The Brainpool 192 bit curve and its OID.
+
+@item brainpoolP224r1
+@itemx 1.3.36.3.3.2.8.1.1.5
+The Brainpool 224 bit curve and its OID.
+
+@item brainpoolP256r1
+@itemx 1.3.36.3.3.2.8.1.1.7
+The Brainpool 256 bit curve and its OID.
+
+@item brainpoolP320r1
+@itemx 1.3.36.3.3.2.8.1.1.9
+The Brainpool 320 bit curve and its OID.
+
+@item brainpoolP384r1
+@itemx 1.3.36.3.3.2.8.1.1.11
+The Brainpool 384 bit curve and its OID.
+
+@item brainpoolP512r1
+@itemx 1.3.36.3.3.2.8.1.1.13
+The Brainpool 512 bit curve and its OID.
+
+@item GOST2001-test
+@itemx 1.2.643.2.2.35.0
+
+@item GOST2001-CryptoPro-A
+@itemx 1.2.643.2.2.35.1
+
+@item GOST2001-CryptoPro-B
+@itemx 1.2.643.2.2.35.2
+
+@item GOST2001-CryptoPro-C
+@itemx 1.2.643.2.2.35.3
+
+@item GOST2001-CryptoPro-A
+@itemx GOST2001-CryptoPro-XchA
+
+@item GOST2001-CryptoPro-C
+@itemx GOST2001-CryptoPro-XchB
+
+@item GOST2001-CryptoPro-A
+@itemx 1.2.643.2.2.36.0
+
+@item GOST2001-CryptoPro-C
+@itemx 1.2.643.2.2.36.1
+
+@item GOST2012-256-tc26-A
+@itemx 1.2.643.7.1.2.1.1.1
+
+@item GOST2001-CryptoPro-A
+@itemx 1.2.643.7.1.2.1.1.2
+
+@item GOST2001-CryptoPro-A
+@itemx GOST2012-256-tc26-B
+
+@item GOST2001-CryptoPro-B
+@itemx 1.2.643.7.1.2.1.1.3
+
+@item GOST2001-CryptoPro-B
+@itemx GOST2012-256-tc26-C
+
+@item GOST2001-CryptoPro-C
+@itemx 1.2.643.7.1.2.1.1.4
+
+@item GOST2001-CryptoPro-C
+@itemx GOST2012-256-tc26-D
+
+@item GOST2012-512-test
+@itemx GOST2012-test
+
+@item GOST2012-512-test
+@itemx 1.2.643.7.1.2.1.2.0
+
+@item GOST2012-512-tc26-A
+@itemx GOST2012-tc26-A
+
+@item GOST2012-512-tc26-B
+@itemx GOST2012-tc26-B
+
+@item GOST2012-512-tc26-A
+@itemx 1.2.643.7.1.2.1.2.1
+
+@item GOST2012-512-tc26-B
+@itemx 1.2.643.7.1.2.1.2.2
+
+@item GOST2012-512-tc26-C
+@itemx 1.2.643.7.1.2.1.2.3
+
+@item secp256k1
+@itemx 1.3.132.0.10
+
+@item sm2p256v1
+@itemx 1.2.156.10197.1.301
 
 @end table
 As usual the OIDs may optionally be prefixed with the string @code{OID.}
@@ -2350,14 +2603,14 @@ are known:
 @itemx nocomp
 @cindex comp
 @cindex nocomp
-If supported by the algorithm and curve the @code{comp} flag requests
+If supported by the algorithm and curve, the @code{comp} flag requests
 that points are returned in compact (compressed) representation.  The
 @code{nocomp} flag requests that points are returned with full
 coordinates.  The default depends on the the algorithm and curve.  The
 compact representation requires a small overhead before a point can be
-used but halves the size of a to be conveyed public key.  If
-@code{comp} is used with the ``EdDSA'' algorithm the key generation
-prefix the public key with a @code{0x40} byte.
+used but halves the size of a public key to be conveyed.  If
+@code{comp} is used with the ``EdDSA'' algorithm, the key generation
+prefixes the public key with a @code{0x40} byte.
 
 @item pkcs1
 @cindex PKCS1
@@ -2397,7 +2650,7 @@ domain parameters of the public or private key.
 @item transient-key
 @cindex transient-key
 This flag is only meaningful for RSA, DSA, and ECC key generation.  If
-given the key is created using a faster and a somewhat less secure
+given, the key is created using a faster and a somewhat less secure
 random number generator.  This flag may be used for keys which are
 only used for a short time or per-message and do not require full
 cryptographic strength.
@@ -2543,7 +2796,7 @@ type 2 padding, or @code{oaep} for RSA-OAEP padding.
 
 @noindent
 The function returns 0 on success or an error code.  The variable at the
-address of @var{r_plain} will be set to NULL on error or receive the
+address of @var{r_plain} will be set to @code{NULL} on error or receive the
 decrypted value on success.  The format of @var{r_plain} is a
 simple S-expression part (i.e. not a valid one) with just one MPI if
 there was no @code{flags} element in @var{data}; if at least an empty
@@ -2610,10 +2863,10 @@ For DSA the input data is expected in this format:
 
 @noindent
 Here, the data to be signed is directly given as an @var{MPI}.  It is
-expect that this MPI is the the hash value.  For the standard DSA
+expect that this MPI is the hash value.  For the standard DSA,
 using a MPI is not a problem in regard to leading zeroes because the
 hash value is directly used as an MPI.  For better standard
-conformance it would be better to explicit use a memory string (like
+conformance it would be better to explicitly use a memory string (like
 with pkcs1) but that is currently not supported.  However, for
 deterministic DSA as specified in RFC6979 this can't be used.  Instead
 the following input is expected.
@@ -2651,10 +2904,10 @@ S-expression returned is:
 Where @var{r-mpi} and @var{s-mpi} are the result of the DSA sign
 operation.
 
-For Elgamal signing (which is slow, yields large numbers, hard to use
-correctly and probably is not as secure as the other algorithms), the
-same format is used with "elg" replacing "dsa"; for ECDSA signing, the
-same format is used with "ecdsa" replacing "dsa".
+For Elgamal signing (which is slow, yields large numbers and probably
+is not as secure as the other algorithms), the same format is used
+with "elg" replacing "dsa"; for ECDSA signing, the same format is used
+with "ecdsa" replacing "dsa".
 
 For the EdDSA algorithm (cf. Ed25515) the required input parameters are:
 
@@ -2666,9 +2919,12 @@ For the EdDSA algorithm (cf. Ed25515) the required input parameters are:
 @end example
 
 Note that the @var{message} may be of any length; hashing is part of
-the algorithm.  Using a large data block for @var{message} is not
-suggested; in that case the used protocol should better require that a
-hash of the message is used as input to the EdDSA algorithm.
+the algorithm.  Using a large data block for @var{message} is in
+general not suggested; in that case the used protocol should better
+require that a hash of the message is used as input to the EdDSA
+algorithm.  Note that for X.509 certificates @var{message} is the
+@code{tbsCertificate} part and in CMS @var{message} is the
+@code{signedAttrs} part; see RFC-8410 and RFC-8419.
 
 
 @end deftypefun
@@ -2696,6 +2952,94 @@ to indicate that the signature does not match the provided data.
 @end deftypefun
 @c end gcry_pk_verify
 
+Additionally, libgcrypt provides three functions for digital
+signatures.  Those functions are useful when hashing computation
+should be closely combined with signature computation.
+
+@deftypefun gcry_error_t gcry_pk_hash_sign (@w{gcry_sexp_t *@var{result},} @w{const char *@var{data_tmpl},} @w{gcry_sexp_t @var{skey},} @w{gcry_md_hd_t @var{hd},} @w{gcry_ctx_t @var{ctx}})
+
+This function is a variant of @code{gcry_pk_sign} which takes as
+additional parameter @var{hd}, handle for hash, and an optional
+context @var{ctx}.  @var{skey} is a private key in S-expression.  The
+hash algorithm used by the handle needs to be enabled and input needs
+to be supplied beforehand.  @var{data-tmpl} specifies a template to
+compose an S-expression to be signed.  A template should include
+@code{"(hash %s %b)"} or @code{"(hash ALGONAME %b)"}.  For the former
+case, "%s" is substituted by the string of algorithm of
+@code{gcry_md_get_algo (}@var{hd}@code{)} and when @code{gcry_md_read}
+is called, @code{ALGO=0} is used internally.  For the latter case,
+hash algorithm by @code{ALGONAME} is used when @code{gcry_md_read} is
+called internally.  The hash handle must not yet been finalized; the
+function takes a copy of the state and does a finalize on the copy.
+The last argument, @var{ctx}, may be used for supplying nonce
+externally.  If no need, @var{ctx} should be passed as @code{NULL}.
+
+@end deftypefun
+@c end gcry_pk_hash_sign
+
+@deftypefun gcry_error_t gcry_pk_hash_verify (@w{gcry_sexp_t @var{sigval},} @w{const char *@var{data_tmpl}}, @w{gcry_sexp_t @var{pkey},} @w{gcry_md_hd_t @var{hd},} @w{gcry_ctx_t @var{ctx}})
+
+This function is a variant of @code{gcry_pk_verify} which takes as
+additional parameter @var{hd}, handle for hash, and an optional
+context @var{ctx}.  @var{pkey} is a public key in S-expression.  See
+@code{gcry_pk_hash_sign}, for the explanation of handle for hash,
+@var{data-tmpl} and @var{ctx}.
+
+@end deftypefun
+@c end gcry_pk_hash_verify
+
+@deftypefun gcry_error_t gcry_pk_random_override_new (@w{gcry_ctx_t *@var{r_ctx},} @w{const unsigned char *@var{p},} @w{size_t @var{len}})
+
+This function is used to allocate a new context for nonce, by memory
+area pointed to by @var{p} to @var{len} bytes.  This context can be
+used when calling @code{gcry_pk_hash_sign} or
+@code{gcry_pk_hash_verify} to supply nonce externally, instead of
+generating internally.
+
+On success the function returns 0 and stores the new context object at
+@var{r_ctx}; this object eventually needs to be released
+(@pxref{gcry_ctx_release}).  On error the function stores @code{NULL} at
+@var{r_ctx} and returns an error code.
+
+@end deftypefun
+@c end gcry_pk_random_override_new
+
+
+@node Dedicated ECC Functions
+@section Dedicated functions for elliptic curves.
+
+@noindent
+The S-expression based interface is not optimal for certain operations on elliptic
+curves.  Thus a few special functions are implemented to
+support common operations on curves with one of these assigned curve
+ids:
+
+@table @code
+@item GCRY_ECC_CURVE25519
+@item GCRY_ECC_CURVE448
+@end table
+
+@deftypefun @w{unsigned int} gcry_ecc_get_algo_keylen (@w{int @var{curveid}});
+
+Returns the length in bytes of a point on the curve with the id
+@var{curveid}.  0 is returned for curves which have no assigned id.
+@end deftypefun
+
+
+@deftypefun gpg_error_t gcry_ecc_mul_point @
+            (@w{int @var{curveid}}, @
+            @w{unsigned char *@var{result}}, @
+            @w{const unsigned char *@var{scalar}}, @
+            @w{const unsigned char *@var{point}})
+
+This function computes the scalar multiplication on the Montgomery
+form of the curve with id @var{curveid}.  If @var{point} is @code{NULL}, the
+base point of the curve is used.  The caller needs to provide a large
+enough buffer for @var{result} and a valid @var{scalar} and
+@var{point}.
+@end deftypefun
+
+
 @node General public-key related Functions
 @section General public-key related Functions
 
@@ -2727,7 +3071,7 @@ Note that this is implemented as a macro.
 @deftypefun {unsigned int} gcry_pk_get_nbits (gcry_sexp_t @var{key})
 
 Return what is commonly referred as the key length for the given
-public or private in @var{key}.
+public or private key in @var{key}.
 @end deftypefun
 
 @deftypefun {unsigned char *} gcry_pk_get_keygrip (@w{gcry_sexp_t @var{key}}, @w{unsigned char *@var{array}})
@@ -2777,7 +3121,7 @@ Unless you need to test for the allowed usage, it is in general better
 to use the macro gcry_pk_test_algo instead.
 
 @item GCRYCTL_GET_ALGO_USAGE:
-Return the usage flags for the given algorithm.  An invalid algorithm
+Return the usage flags for the given algorithm.  For an invalid algorithm
 return 0.  Disabled algorithms are ignored here because we
 want to know whether the algorithm is at all capable of a certain usage.
 
@@ -2795,7 +3139,7 @@ Return the number of elements a signature created with the algorithm
 @var{algo} consists of.  Return 0 for an unknown algorithm or for an
 algorithm not capable of creating signatures.
 
-@item GCRYCTL_GET_ALGO_NENC
+@item GCRYCTL_GET_ALGO_NENCR
 Return the number of elements a encrypted message created with the algorithm
 @var{algo} consists of.  Return 0 for an unknown algorithm or for an
 algorithm not capable of encryption.
@@ -2892,9 +3236,9 @@ and that the usual C prefixes are considered (e.g. 017 gives 15).
 
 
 @item qbits @var{n}
-This is only meanigful for DSA keys.  If it is given the DSA key is
-generated with a Q parameyer of size @var{n} bits.  If it is not given
-or zero Q is deduced from NBITS in this way:
+This is only meanigful for DSA keys.  If it is given, the DSA key is
+generated with a Q parameter of size @var{n} bits.  If it is not given
+or zero, Q is deduced from @var{nbits} in this way:
 @table @samp
 @item 512 <= N <= 1024
 Q = 160
@@ -2908,11 +3252,11 @@ Q = 384
 Q = 512
 @end table
 Note that in this case only the values for N, as given in the table,
-are allowed.  When specifying Q all values of N in the range 512 to
+are allowed.  When specifying Q, all values of N in the range 512 to
 15680 are valid as long as they are multiples of 8.
 
 @item domain @var{list}
-This is only meaningful for DLP algorithms.  If specified keys are
+This is only meaningful for DLP algorithms.  If specified, keys are
 generated with domain parameters taken from this list.  The exact
 format of this parameter depends on the actual algorithm.  It is
 currently only implemented for DSA using this format:
@@ -2934,7 +3278,7 @@ This is currently only implemented for RSA and DSA keys.  It is not
 allowed to use this together with a @code{domain} specification.  If
 given, it is used to derive the keys using the given parameters.
 
-If given for an RSA key the X9.31 key generation algorithm is used
+If given for an RSA key, the X9.31 key generation algorithm is used
 even if libgcrypt is not in FIPS mode.  If given for a DSA key, the
 FIPS 186 algorithm is used even if libgcrypt is not in FIPS mode.
 
@@ -2997,7 +3341,7 @@ private and public keys are returned in one container and may be
 accompanied by some miscellaneous information.
 
 @noindent
-Here are two examples; the first for Elgamal and the second for
+Here are two examples: the first for Elgamal and the second for
 elliptic curve key generation:
 
 @example
@@ -3046,7 +3390,7 @@ algorithm provides them.
 
 @noindent
 Future versions of Libgcrypt will have extended versions of the public
-key interfaced which will take an additional context to allow for
+key interface which will take an additional context to allow for
 pre-computations, special operations, and other optimization.  As a
 first step a new function is introduced to help using the ECC
 algorithms in new ways:
@@ -3058,13 +3402,13 @@ Return an S-expression representing the context @var{ctx}.  Depending
 on the state of that context, the S-expression may either be a public
 key, a private key or any other object used with public key
 operations.  On success 0 is returned and a new S-expression is stored
-at @var{r_sexp}; on error an error code is returned and NULL is stored
+at @var{r_sexp}; on error an error code is returned and @code{NULL} is stored
 at @var{r_sexp}.  @var{mode} must be one of:
 
 @table @code
 @item 0
 Decide what to return depending on the context.  For example if the
-private key parameter is available a private key is returned, if not a
+private key parameter is available, a private key is returned; if not, a
 public key is returned.
 
 @item GCRY_PK_GET_PUBKEY
@@ -3093,7 +3437,7 @@ function will be extended to cover more algorithms.
 @node Hashing
 @chapter Hashing
 
-Libgcrypt provides an easy and consistent to use interface for hashing.
+Libgcrypt provides an easy to use and consistent interface for hashing.
 Hashing is buffered and several hash algorithms can be updated at once.
 It is possible to compute a HMAC using the same routines.  The
 programming model follows an open/process/close paradigm and is in that
@@ -3112,12 +3456,13 @@ are also supported.
 
 @c begin table of hash algorithms
 @cindex SHA-1
-@cindex SHA-224, SHA-256, SHA-384, SHA-512
+@cindex SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256
 @cindex SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256
 @cindex RIPE-MD-160
 @cindex MD2, MD4, MD5
 @cindex TIGER, TIGER1, TIGER2
 @cindex HAVAL
+@cindex SM3
 @cindex Whirlpool
 @cindex BLAKE2b-512, BLAKE2b-384, BLAKE2b-256, BLAKE2b-160
 @cindex BLAKE2s-256, BLAKE2s-224, BLAKE2s-160, BLAKE2s-128
@@ -3134,7 +3479,7 @@ fade out its use if strong cryptographic properties are required.
 
 @item GCRY_MD_RMD160
 This is the 160 bit version of the RIPE message digest (RIPE-MD-160).
-Like SHA-1 it also yields a digest of 20 bytes.  This algorithm share a
+Like SHA-1 it also yields a digest of 20 bytes.  This algorithm shares a
 lot of design properties with SHA-1 and thus it is advisable not to use
 it for new protocols.
 
@@ -3151,7 +3496,7 @@ This is the MD4 algorithm, which yields a message digest of 16 bytes.
 This algorithm has severe weaknesses and should not be used.
 
 @item GCRY_MD_MD2
-This is an reserved identifier for MD-2; there is no implementation yet.
+This is a reserved identifier for MD-2; there is no implementation yet.
 This algorithm has severe weaknesses and should not be used.
 
 @item GCRY_MD_TIGER
@@ -3169,7 +3514,7 @@ This is another variant of TIGER with a different padding scheme.
 
 @item GCRY_MD_HAVAL
 This is an reserved value for the HAVAL algorithm with 5 passes and 160
-bit. It yields a message digest of 20 bytes.  Note that there is no
+bits. It yields a message digest of 20 bytes.  Note that there is no
 implementation yet available.
 
 @item GCRY_MD_SHA224
@@ -3185,9 +3530,17 @@ This is the SHA-384 algorithm which yields a message digest of 48 bytes.
 See FIPS 180-2 for the specification.
 
 @item GCRY_MD_SHA512
-This is the SHA-384 algorithm which yields a message digest of 64 bytes.
+This is the SHA-512 algorithm which yields a message digest of 64 bytes.
 See FIPS 180-2 for the specification.
 
+@item GCRY_MD_SHA512_224
+This is the SHA-512/224 algorithm which yields a message digest of 28 bytes.
+See FIPS 180-4 for the specification.
+
+@item GCRY_MD_SHA512_256
+This is the SHA-512/256 algorithm which yields a message digest of 32 bytes.
+See FIPS 180-4 for the specification.
+
 @item GCRY_MD_SHA3_224
 This is the SHA3-224 algorithm which yields a message digest of 28 bytes.
 See FIPS 202 for the specification.
@@ -3201,7 +3554,7 @@ This is the SHA3-384 algorithm which yields a message digest of 48 bytes.
 See FIPS 202 for the specification.
 
 @item GCRY_MD_SHA3_512
-This is the SHA3-384 algorithm which yields a message digest of 64 bytes.
+This is the SHA3-512 algorithm which yields a message digest of 64 bytes.
 See FIPS 202 for the specification.
 
 @item GCRY_MD_SHAKE128
@@ -3277,6 +3630,9 @@ See RFC 7693 for the specification.
 This is the BLAKE2s-128 algorithm which yields a message digest of 16 bytes.
 See RFC 7693 for the specification.
 
+@item GCRY_MD_SM3
+This is the SM3 algorithm which yields a message digest of 32 bytes.
+
 @end table
 @c end table of hash algorithms
 
@@ -3292,7 +3648,7 @@ Create a message digest object for algorithm @var{algo}.  @var{flags}
 may be given as an bitwise OR of constants described below.  @var{algo}
 may be given as @code{0} if the algorithms to use are later set using
 @code{gcry_md_enable}. @var{hd} is guaranteed to either receive a valid
-handle or NULL.
+handle or @code{NULL}.
 
 For a list of supported algorithms, see @ref{Available hash
 algorithms}.
@@ -3303,7 +3659,7 @@ The flags allowed for @var{mode} are:
 @table @code
 @item GCRY_MD_FLAG_SECURE
 Allocate all buffers and the resulting digest in "secure memory".  Use
-this is the hashed data is highly confidential.
+this if the hashed data is highly confidential.
 
 @item GCRY_MD_FLAG_HMAC
 @cindex HMAC
@@ -3322,11 +3678,11 @@ which led to a wrong result for certain input sizes and write
 patterns.  Using this flag emulates that bug.  This may for example be
 useful for applications which use Whirlpool as part of their key
 generation.  It is strongly suggested to use this flag only if really
-needed and if possible to the data should be re-processed using the
+needed; and if possible, the data should be re-processed using the
 regular Whirlpool algorithm.
 
-Note that this flag works for the entire hash context.  If needed
-arises it may be used to enable bug emulation for other hash
+Note that this flag works for the entire hash context.  If need
+arises, it may be used to enable bug emulation for other hash
 algorithms.  Thus you should not use this flag for a multi-algorithm
 hash context.
 
@@ -3358,8 +3714,8 @@ be set using the function:
 For use with the HMAC feature or BLAKE2 keyed hash, set the MAC key to
 the value of @var{key} of length @var{keylen} bytes.  For HMAC, there
 is no restriction on the length of the key.  For keyed BLAKE2b hash,
-length of the key must be 64 bytes or less.  For keyed BLAKE2s hash,
-length of the key must be 32 bytes or less.
+length of the key must be in the range 1 to 64 bytes.  For keyed
+BLAKE2s hash, length of the key must be in the range 1 to 32 bytes.
 
 @end deftypefun
 
@@ -3405,7 +3761,7 @@ independently using the original context.
 
 
 Now that we have prepared everything to calculate hashes, it is time to
-see how it is actually done.  There are two ways for this, one to
+see how it is actually done.  There are two ways for this: one to
 update the hash with a block of memory and one macro to update the hash
 by just one character.  Both methods can be used on the same hash context.
 
@@ -3437,7 +3793,7 @@ message digest or some padding.
 Finalize the message digest calculation.  This is not really needed
 because @code{gcry_md_read} and @code{gcry_md_extract} do this implicitly.
 After this has been done no further updates (by means of @code{gcry_md_write}
-or @code{gcry_md_putc} should be done; However, to mitigate timing
+or @code{gcry_md_putc}) should be done; However, to mitigate timing
 attacks it is sometimes useful to keep on updating the context after
 having stored away the actual digest.  Only the first call to this function
 has an effect. It is implemented as a macro.
@@ -3453,7 +3809,7 @@ calculation.  This function may be used as often as required but it will
 always return the same value for one handle.  The returned message digest
 is allocated within the message context and therefore valid until the
 handle is released or reset-ed (using @code{gcry_md_close} or
-@code{gcry_md_reset} or it has been updated as a mitigation measure
+@code{gcry_md_reset}) or it has been updated as a mitigation measure
 against timing attacks.  @var{algo} may be given as 0 to return the only
 enabled message digest or it may specify one of the enabled algorithms.
 The function does return @code{NULL} if the requested algorithm has not
@@ -3513,7 +3869,7 @@ at @var{digest}.
 digest of a buffer.  This function does not require a context and
 immediately returns the message digest of the @var{length} bytes at
 @var{buffer}.  @var{digest} must be allocated by the caller, large
-enough to hold the message digest yielded by the the specified algorithm
+enough to hold the message digest yielded by the specified algorithm
 @var{algo}.  This required size may be obtained by using the function
 @code{gcry_md_get_algo_dlen}.
 
@@ -3555,7 +3911,7 @@ Return an DER encoded ASN.1 OID for the algorithm @var{algo} in the
 user allocated @var{buffer}. @var{length} must point to variable with
 the available size of @var{buffer} and receives after return the
 actual size of the returned OID.  The returned error code may be
-@code{GPG_ERR_TOO_SHORT} if the provided buffer is to short to receive
+@code{GPG_ERR_TOO_SHORT} if the provided buffer is too short to receive
 the OID; it is possible to call the function with @code{NULL} for
 @var{buffer} to have it only return the required size.  The function
 returns 0 on success.
@@ -3634,7 +3990,7 @@ because @code{gcry_md_close} implicitly stops debugging.
 @node Message Authentication Codes
 @chapter Message Authentication Codes
 
-Libgcrypt provides an easy and consistent to use interface for generating
+Libgcrypt provides an easy to use and consistent interface for generating
 Message Authentication Codes (MAC). MAC generation is buffered and interface
 similar to the one used with hash algorithms. The programming model follows
 an open/process/close paradigm and is in that similar to other building blocks
@@ -3651,13 +4007,16 @@ provided by Libgcrypt.
 @c begin table of MAC algorithms
 @cindex HMAC-SHA-1
 @cindex HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384, HMAC-SHA-512
+@cindex HMAC-SHA-512/224, HMAC-SHA-512/256
 @cindex HMAC-SHA3-224, HMAC-SHA3-256, HMAC-SHA3-384, HMAC-SHA3-512
 @cindex HMAC-RIPE-MD-160
 @cindex HMAC-MD2, HMAC-MD4, HMAC-MD5
 @cindex HMAC-TIGER1
+@cindex HMAC-SM3
 @cindex HMAC-Whirlpool
 @cindex HMAC-Stribog-256, HMAC-Stribog-512
 @cindex HMAC-GOSTR-3411-94
+@cindex HMAC-BLAKE2s, HMAC-BLAKE2b
 @table @code
 @item GCRY_MAC_NONE
 This is not a real algorithm but used by some functions as an error
@@ -3680,7 +4039,7 @@ This is HMAC message authentication algorithm based on the SHA-384 hash
 algorithm.
 
 @item GCRY_MAC_HMAC_SHA3_256
-This is HMAC message authentication algorithm based on the SHA3-384 hash
+This is HMAC message authentication algorithm based on the SHA3-256 hash
 algorithm.
 
 @item GCRY_MAC_HMAC_SHA3_224
@@ -3695,6 +4054,14 @@ algorithm.
 This is HMAC message authentication algorithm based on the SHA3-384 hash
 algorithm.
 
+@item GCRY_MAC_HMAC_SHA512_224
+This is HMAC message authentication algorithm based on the SHA-512/224 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_SHA512_256
+This is HMAC message authentication algorithm based on the SHA-512/256 hash
+algorithm.
+
 @item GCRY_MAC_HMAC_SHA1
 This is HMAC message authentication algorithm based on the SHA-1 hash
 algorithm.
@@ -3727,6 +4094,42 @@ algorithm described in GOST R 34.11-2012.
 This is HMAC message authentication algorithm based on the 512-bit hash
 algorithm described in GOST R 34.11-2012.
 
+@item GCRY_MAC_HMAC_BLAKE2B_512
+This is HMAC message authentication algorithm based on the BLAKE2b-512 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_BLAKE2B_384
+This is HMAC message authentication algorithm based on the BLAKE2b-384 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_BLAKE2B_256
+This is HMAC message authentication algorithm based on the BLAKE2b-256 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_BLAKE2B_160
+This is HMAC message authentication algorithm based on the BLAKE2b-160 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_BLAKE2S_256
+This is HMAC message authentication algorithm based on the BLAKE2s-256 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_BLAKE2S_224
+This is HMAC message authentication algorithm based on the BLAKE2s-224 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_BLAKE2S_160
+This is HMAC message authentication algorithm based on the BLAKE2s-160 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_BLAKE2S_128
+This is HMAC message authentication algorithm based on the BLAKE2s-128 hash
+algorithm.
+
+@item GCRY_MAC_HMAC_SM3
+This is HMAC message authentication algorithm based on the SM3 hash
+algorithm.
+
 @item GCRY_MAC_CMAC_AES
 This is CMAC (Cipher-based MAC) message authentication algorithm based on
 the AES block cipher algorithm.
@@ -3771,6 +4174,10 @@ block cipher algorithm.
 This is CMAC message authentication algorithm based on the GOST 28147-89
 block cipher algorithm.
 
+@item GCRY_MAC_CMAC_SM4
+This is CMAC message authentication algorithm based on the SM4
+block cipher algorithm.
+
 @item GCRY_MAC_GMAC_AES
 This is GMAC (GCM mode based MAC) message authentication algorithm based on
 the AES block cipher algorithm.
@@ -3815,6 +4222,9 @@ key and one-time nonce.
 This is Poly1305-SEED message authentication algorithm, used with
 key and one-time nonce.
 
+@item GCRY_MAC_GOST28147_IMIT
+This is MAC construction defined in GOST 28147-89 (see RFC 5830 Section 8).
+
 @end table
 @c end table of MAC algorithms
 
@@ -3826,10 +4236,10 @@ this is done using:
 
 @deftypefun gcry_error_t gcry_mac_open (gcry_mac_hd_t *@var{hd}, int @var{algo}, unsigned int @var{flags}, gcry_ctx_t @var{ctx})
 
-Create a MAC object for algorithm @var{algo}. @var{flags} may be given as an
+Create a MAC object for algorithm @var{algo}. @var{flags} may be given as a
 bitwise OR of constants described below. @var{hd} is guaranteed to either
-receive a valid handle or NULL. @var{ctx} is context object to associate MAC
-object with. @var{ctx} maybe set to NULL.
+receive a valid handle or @code{NULL}. @var{ctx} is context object to associate MAC
+object with. @var{ctx} maybe set to @code{NULL}.
 
 For a list of supported algorithms, see @ref{Available MAC algorithms}.
 
@@ -4011,7 +4421,7 @@ from strings.
 
 
 Derive a key from a passphrase.  @var{keysize} gives the requested
-size of the keys in octets.  @var{keybuffer} is a caller provided
+size of the key in octets.  @var{keybuffer} is a caller provided
 buffer filled on success with the derived key.  The input passphrase
 is taken from @var{passphrase} which is an arbitrary memory buffer of
 @var{passphraselen} octets.  @var{algo} specifies the KDF algorithm to
@@ -4081,7 +4491,7 @@ The constants for the random quality levels are of this enum type.
 @table @code
 @item GCRY_WEAK_RANDOM
 For all functions, except for @code{gcry_mpi_randomize}, this level maps
-to GCRY_STRONG_RANDOM.  If you do not want this, consider using
+to @code{GCRY_STRONG_RANDOM}.  If you do not want this, consider using
 @code{gcry_create_nonce}.
 @item GCRY_STRONG_RANDOM
 Use this level for session keys and similar purposes.
@@ -4141,7 +4551,7 @@ to parse and construct them.  For detailed information, see
 @uref{http://theory.lcs.mit.edu/~rivest/sexp.html}}.
 
 @menu
-* Data types for S-expressions::  Data types related with S-expressions.
+* Data types for S-expressions::  Data types related to S-expressions.
 * Working with S-expressions::  How to work with S-expressions.
 @end menu
 
@@ -4169,9 +4579,9 @@ This is the generic function to create an new S-expression object from
 its external representation in @var{buffer} of @var{length} bytes.  On
 success the result is stored at the address given by @var{r_sexp}.
 With @var{autodetect} set to 0, the data in @var{buffer} is expected to
-be in canonized format, with @var{autodetect} set to 1 the parses any of
+be in canonized format, with @var{autodetect} set to 1 the function parses any of
 the defined external formats.  If @var{buffer} does not hold a valid
-S-expression an error code is returned and @var{r_sexp} set to
+S-expression, an error code is returned and @var{r_sexp} set to
 @code{NULL}.
 Note that the caller is responsible for releasing the newly allocated
 S-expression using @code{gcry_sexp_release}.
@@ -4245,7 +4655,7 @@ sign is not a valid character in an S-expression.
 @deftypefun void gcry_sexp_release (@w{gcry_sexp_t @var{sexp}})
 
 Release the S-expression object @var{sexp}.  If the S-expression is
-stored in secure memory it explicitly zeroises that memory; note that
+stored in secure memory, it explicitly zeroises that memory; note that
 this is done in addition to the zeroisation always done when freeing
 secure memory.
 @end deftypefun
@@ -4346,7 +4756,7 @@ returned in case of a problem.
 
 Create and return a new list form all elements except for the first one.
 Note that this function may return an invalid S-expression because it
-is not guaranteed, that the type exists and is a string.  However, for
+is not guaranteed that the type exists and is a string.  However, for
 parsing a complex S-expression it might be useful for intermediate
 lists.  Returns @code{NULL} on error.
 @end deftypefun
@@ -4425,30 +4835,57 @@ likely want to use @code{GCRYMPI_FMT_USG}.
   @w{const char *@var{list}}, ...)
 
 Extract parameters from an S-expression using a list of parameter
-names.  The names of these parameters are specified in LIST.  White
+names.  The names of these parameters are specified in @var{list}.  White
 space between the parameter names are ignored. Some special characters
-may be given to control the conversion:
+and character sequences may be given to control the conversion:
 
 @table @samp
 @item +
-Switch to unsigned integer format (GCRYMPI_FMT_USG).  This is the
+Switch to unsigned integer format (@code{GCRYMPI_FMT_USG}).  This is the
 default mode.
 @item -
-Switch to standard signed format (GCRYMPI_FMT_STD).
+Switch to standard signed format (@code{GCRYMPI_FMT_STD}).
 @item /
 Switch to opaque MPI format.  The resulting MPIs may not be used for
 computations; see @code{gcry_mpi_get_opaque} for details.
 @item &
 Switch to buffer descriptor mode.  See below for details.
+@item %s
+Switch to string mode.  The expected argument is the address of a
+@code{char *} variable; the caller must release that value.  If the
+parameter was marked optional and is not found, @code{NULL} is stored.
+@item %#s
+Switch to multi string mode.  The expected argument is the address of a
+@code{char *} variable; the caller must release that value.  If the
+parameter was marked optional and is not found, @code{NULL} is stored.  A
+multi string takes all values, assumes they are strings and
+concatenates them using a space as delimiter.  In case a value is
+actually another list, this is not further parsed but a @code{()} is
+inserted in place of that sublist.
+@item %u
+Switch to unsigned integer mode. The expected argument is address of
+a @code{unsigned int} variable.
+@item %lu
+Switch to unsigned long integer mode. The expected argument is address of
+a @code{unsigned long} variable.
+@item %d
+Switch to signed integer mode. The expected argument is address of
+a @code{int} variable.
+@item %ld
+Switch to signed long integer mode. The expected argument is address of
+a @code{long} variable.
+@item %zu
+Switch to size_t mode. The expected argument is address of
+a @code{size_t} variable.
 @item ?
 If immediately following a parameter letter (no white space allowed),
 that parameter is considered optional.
 @end table
 
-In general parameter names are single letters.  To use a string for a
+In general, parameter names are single letters.  To use a string for a
 parameter name, enclose the name in single quotes.
 
-Unless in buffer descriptor mode for each parameter name a pointer to
+Unless in buffer descriptor mode, for each parameter name a pointer to
 an @code{gcry_mpi_t} variable is expected that must be set to
 @code{NULL} prior to invoking this function, and finally a @code{NULL}
 is expected.  For example
@@ -4476,7 +4913,7 @@ provided descriptor is @code{NULL}, the function allocates a new
 buffer and stores it at @var{data}; the other fields are set
 accordingly with @var{off} set to 0.  If @var{data} is not
 @code{NULL}, the function assumes that the @var{data}, @var{size}, and
-@var{off} fields specify a buffer where to but the value of the
+@var{off} fields specify a buffer where to put the value of the
 respective parameter; on return the @var{len} field receives the
 number of bytes copied to that buffer; in case the buffer is too
 small, the function immediately returns with an error code (and
@@ -4581,6 +5018,18 @@ int} as type for @var{u} and thus it is only possible to set @var{w} to
 small values (usually up to the word size of the CPU).
 @end deftypefun
 
+@deftypefun gcry_error_t gcry_mpi_get_ui (@w{unsigned int *@var{w}}, @w{gcry_mpi_t @var{u}})
+
+If @var{u} is not negative and small enough to be stored in an
+@code{unsigned int} variable, store its value at @var{w}.  If the
+value does not fit or is negative, return @code{GPG_ERR_ERANGE} and do not
+change the value stored at @var{w}.  Note that this function returns
+an @code{unsigned int} so that this value can immediately be used with
+the bit test functions.  This is in contrast to the other "_ui"
+functions which allow for values up to an @code{unsigned long}.
+@end deftypefun
+
+
 @deftypefun void gcry_mpi_swap (@w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{b}})
 
 Swap the values of @var{a} and @var{b}.
@@ -4590,7 +5039,7 @@ Swap the values of @var{a} and @var{b}.
                                   @w{const gcry_mpi_t @var{u}})
 
 Set @var{u} into @var{w} and release @var{u}.  If @var{w} is
-@code{NULL} only @var{u} will be released.
+@code{NULL}, only @var{u} will be released.
 @end deftypefun
 
 @deftypefun void gcry_mpi_neg (@w{gcry_mpi_t @var{w}}, @w{gcry_mpi_t @var{u}})
@@ -4617,7 +5066,7 @@ Convert the external representation of an integer stored in @var{buffer}
 with a length of @var{buflen} into a newly created MPI returned which
 will be stored at the address of @var{r_mpi}.  For certain formats the
 length argument is not required and should be passed as @code{0}. A
-@var{buflen} larger than 16 MiByte will be rejected.  After a
+@var{buflen} larger than 16 MiB will be rejected.  After a
 successful operation the variable @var{nscanned} receives the number of
 bytes actually scanned unless @var{nscanned} was given as
 @code{NULL}. @var{format} describes the format of the MPI as stored in
@@ -4639,7 +5088,7 @@ with a 4 byte big endian header.
 
 @item GCRYMPI_FMT_HEX
 Stored as a string with each byte of the MPI encoded as 2 hex digits.
-Negative numbers are prefix with a minus sign and in addition the
+Negative numbers are prefixed with a minus sign and in addition the
 high bit is always zero to make clear that an explicit sign ist used.
 When using this format, @var{buflen} must be zero.
 
@@ -4657,8 +5106,8 @@ format (MSB first).
 
 Convert the MPI @var{a} into an external representation described by
 @var{format} (see above) and store it in the provided @var{buffer}
-which has a usable length of at least the @var{buflen} bytes. If
-@var{nwritten} is not NULL, it will receive the number of bytes
+which has a usable length of at least @var{buflen} bytes. If
+@var{nwritten} is not @code{NULL}, it will receive the number of bytes
 actually stored in @var{buffer} after a successful operation.
 @end deftypefun
 
@@ -4750,7 +5199,9 @@ Basic arithmetic operations:
 
 @math{@var{q} = @var{dividend} / @var{divisor}}, @math{@var{r} =
 @var{dividend} \bmod @var{divisor}}.  @var{q} and @var{r} may be passed
-as @code{NULL}.  @var{round} should be negative or 0.
+as @code{NULL}.  @var{round} is either negative for floored division
+(rounds towards the next lower integer) or zero for truncated division
+(rounds towards zero).
 @end deftypefun
 
 @deftypefun void gcry_mpi_mod (@w{gcry_mpi_t @var{r}}, @w{gcry_mpi_t @var{dividend}}, @w{gcry_mpi_t @var{divisor}})
@@ -4767,7 +5218,7 @@ as @code{NULL}.  @var{round} should be negative or 0.
 @deftypefun int gcry_mpi_gcd (@w{gcry_mpi_t @var{g}}, @w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{b}})
 
 Set @var{g} to the greatest common divisor of @var{a} and @var{b}.
-Return true if the @var{g} is 1.
+Return true if @var{g} is 1.
 @end deftypefun
 
 @deftypefun int gcry_mpi_invm (@w{gcry_mpi_t @var{x}}, @w{gcry_mpi_t @var{a}}, @w{gcry_mpi_t @var{m}})
@@ -4786,10 +5237,10 @@ The next 2 functions are used to compare MPIs:
 
 @deftypefun int gcry_mpi_cmp (@w{const gcry_mpi_t @var{u}}, @w{const gcry_mpi_t @var{v}})
 
-Compare the multi-precision-integers number @var{u} and @var{v}
+Compare the multi-precision-integers number @var{u} and @var{v},
 returning 0 for equality, a positive value for @var{u} > @var{v} and a
 negative for @var{u} < @var{v}.  If both numbers are opaque values
-(cf, gcry_mpi_set_opaque) the comparison is done by checking the bit
+(cf. @code{gcry_mpi_set_opaque}), the comparison is done by checking the bit
 sizes using memcmp.  If only one number is an opaque value, the opaque
 value is less than the other number.
 @end deftypefun
@@ -4797,7 +5248,7 @@ value is less than the other number.
 @deftypefun int gcry_mpi_cmp_ui (@w{const gcry_mpi_t @var{u}}, @w{unsigned long @var{v}})
 
 Compare the multi-precision-integers number @var{u} with the unsigned
-integer @var{v} returning 0 for equality, a positive value for @var{u} >
+integer @var{v}, returning 0 for equality, a positive value for @var{u} >
 @var{v} and a negative for @var{u} < @var{v}.
 @end deftypefun
 
@@ -4882,7 +5333,7 @@ Release @var{point} and free all associated resources.  Passing
 @deftypefun gcry_mpi_point_t gcry_mpi_point_copy (@w{gcry_mpi_point_t @var{point}})
 
 Allocate and return a new point object and initialize it with
-@var{point}.  If @var{point} is NULL the function is identical to
+@var{point}.  If @var{point} is @code{NULL}, the function is identical to
 @code{gcry_mpi_point_new(0)}.
 @end deftypefun
 
@@ -4913,7 +5364,7 @@ advantage of avoiding some extra memory allocations and copies.
 
 Store the projective coordinates from @var{x}, @var{y}, and @var{z}
 into @var{point}.  If a coordinate is given as @code{NULL}, the value
-0 is used.  If @code{NULL} is used for @var{point} a new point object
+0 is used.  If @code{NULL} is used for @var{point}, a new point object
 is allocated and returned.  Returns @var{point} or the newly allocated
 point object.
 @end deftypefun
@@ -4924,7 +5375,7 @@ point object.
 
 Store the projective coordinates from @var{x}, @var{y}, and @var{z}
 into @var{point}.  If a coordinate is given as @code{NULL}, the value
-0 is used.  If @code{NULL} is used for @var{point} a new point object
+0 is used.  If @code{NULL} is used for @var{point}, a new point object
 is allocated and returned.  The MPIs @var{x}, @var{y}, and @var{z} are
 released.  Using this function instead of @code{gcry_mpi_point_set}
 and 3 calls to @code{gcry_mpi_release} has the advantage of avoiding
@@ -4937,7 +5388,7 @@ newly allocated point object.
  @w{gcry_sexp_t @var{keyparam}}, @w{const char *@var{curvename}})
 
 Allocate a new context for elliptic curve operations.  If
-@var{keyparam} is given it specifies the parameters of the curve
+@var{keyparam} is given, it specifies the parameters of the curve
 (@pxref{ecc_keyparam}).  If @var{curvename} is given in addition to
 @var{keyparam} and the key parameters do not include a named curve
 reference, the string @var{curvename} is used to fill in missing
@@ -4960,15 +5411,15 @@ On success the function returns 0 and stores the new context object at
  @w{const char *@var{name}}, @w{gcry_ctx_t @var{ctx}}, @w{int @var{copy}})
 
 Return the MPI with @var{name} from the context @var{ctx}.  If not
-found @code{NULL} is returned.  If the returned MPI may later be
+found, @code{NULL} is returned.  If the returned MPI may later be
 modified, it is suggested to pass @code{1} to @var{copy}, so that the
 function guarantees that a modifiable copy of the MPI is returned.  If
 @code{0} is used for @var{copy}, this function may return a constant
 flagged MPI.  In any case @code{gcry_mpi_release} needs to be called
-to release the result.  For valid names @ref{ecc_keyparam}.  If the
+to release the result.  For valid names, see @ref{ecc_keyparam}.  If the
 public key @code{q} is requested but only the private key @code{d} is
 available, @code{q} will be recomputed on the fly.  If a point
-parameter is requested it is returned as an uncompressed
+parameter is requested, it is returned as an uncompressed
 encoded point unless these special names are used:
 @table @var
 @item q@@eddsa
@@ -4981,7 +5432,7 @@ Twisted Edwards curves.
  @w{const char *@var{name}}, @w{gcry_ctx_t @var{ctx}}, @w{int @var{copy}})
 
 Return the point with @var{name} from the context @var{ctx}.  If not
-found @code{NULL} is returned.  If the returned MPI may later be
+found, @code{NULL} is returned.  If the returned MPI may later be
 modified, it is suggested to pass @code{1} to @var{copy}, so that the
 function guarantees that a modifiable copy of the MPI is returned.  If
 @code{0} is used for @var{copy}, this function may return a constant
@@ -5017,7 +5468,7 @@ Valid names are the point parameters of an elliptic curve
 Decode the point given as an MPI in @var{value} and store at
 @var{result}.  To decide which encoding is used the function takes a
 context @var{ctx} which can be created with @code{gcry_mpi_ec_new}.
-If @code{NULL} is given for the context the function assumes a 0x04
+If @code{NULL} is given for the context, the function assumes a 0x04
 prefixed uncompressed encoding.  On error an error code is returned
 and @var{result} might be changed.
 @end deftypefun
@@ -5093,19 +5544,19 @@ Store @var{nbits} of the value @var{p} points to in @var{a} and mark
 @var{a} as an opaque value (i.e. an value that can't be used for any
 math calculation and is only used to store an arbitrary bit pattern in
 @var{a}).  Ownership of @var{p} is taken by this function and thus the
-user may not use dereference the passed value anymore.  It is required
-that them memory referenced by @var{p} has been allocated in a way
+user may not dereference the passed value anymore.  It is required
+that the memory referenced by @var{p} has been allocated in a way
 that @code{gcry_free} is able to release it.
 
 WARNING: Never use an opaque MPI for actual math operations.  The only
-valid functions are gcry_mpi_get_opaque and gcry_mpi_release.  Use
-gcry_mpi_scan to convert a string of arbitrary bytes into an MPI.
+valid functions are @code{gcry_mpi_get_opaque} and @code{gcry_mpi_release}.  Use
+@code{gcry_mpi_scan} to convert a string of arbitrary bytes into an MPI.
 @end deftypefun
 
 @deftypefun gcry_mpi_t gcry_mpi_set_opaque_copy (@w{gcry_mpi_t @var{a}}, @w{const void *@var{p}}, @w{unsigned int @var{nbits}})
 
 Same as @code{gcry_mpi_set_opaque} but ownership of @var{p} is not
-taken instead a copy of @var{p} is used.
+taken; instead a copy of @var{p} is used.
 @end deftypefun
 
 
@@ -5125,7 +5576,7 @@ currently defined flags are:
 Setting this flag converts @var{a} into an MPI stored in "secure
 memory".  Clearing this flag is not allowed.
 @item GCRYMPI_FLAG_OPAQUE
-This is an interanl flag, indicating the an opaque valuue and not an
+This is an internal flag, indicating that an opaque value and not an
 integer is stored.  This is an read-only flag; it may not be set or
 cleared.
 @item GCRYMPI_FLAG_IMMUTABLE
@@ -5136,7 +5587,7 @@ logged.  The flag is sometimes useful for debugging.
 If this flag is set, the MPI is marked as a constant and as immutable
 Setting or changing the value of that MPI is ignored and an error
 message is logged.  Such an MPI will never be deallocated and may thus
-be used without copying.  Note that using gcry_mpi_copy will return a
+be used without copying.  Note that using @code{gcry_mpi_copy} will return a
 copy of that constant with this and the immutable flag cleared.  A few
 commonly used constants are pre-defined and accessible using the
 macros @code{GCRYMPI_CONST_ONE}, @code{GCRYMPI_CONST_TWO},
@@ -5165,7 +5616,7 @@ allowed flag is @code{GCRYMPI_FLAG_IMMUTABLE} but only if
 @code{GCRYMPI_FLAG_CONST} is not set.  If @code{GCRYMPI_FLAG_CONST} is
 set, clearing @code{GCRYMPI_FLAG_IMMUTABLE} will simply be ignored.
 @end deftypefun
-o
+
 @deftypefun int gcry_mpi_get_flag (@w{gcry_mpi_t @var{a}}, @
  @w{enum gcry_mpi_flag @var{flag}})
 
@@ -5182,7 +5633,7 @@ Set the multi-precision-integers @var{w} to a random non-negative number of
 @var{nbits}, using random data quality of level @var{level}.  In case
 @var{nbits} is not a multiple of a byte, @var{nbits} is rounded up to
 the next byte boundary.  When using a @var{level} of
-@code{GCRY_WEAK_RANDOM} this function makes use of
+@code{GCRY_WEAK_RANDOM}, this function makes use of
 @code{gcry_create_nonce}.
 @end deftypefun
 
@@ -5213,9 +5664,9 @@ might be used to influence the prime number generation process.
 @deftypefun gcry_error_t gcry_prime_group_generator (gcry_mpi_t *@var{r_g}, gcry_mpi_t @var{prime}, gcry_mpi_t *@var{factors}, gcry_mpi_t @var{start_g})
 
 Find a generator for @var{prime} where the factorization of
-(@var{prime}-1) is in the @code{NULL} terminated array @var{factors}.
+(@var{prime} - 1) is in the @code{NULL} terminated array @var{factors}.
 Return the generator as a newly allocated MPI in @var{r_g}.  If
-@var{start_g} is not NULL, use this as the start for the search.
+@var{start_g} is not @code{NULL}, use this as the start for the search.
 @end deftypefun
 
 @deftypefun void gcry_prime_release_factors (gcry_mpi_t *@var{factors})
@@ -5241,10 +5692,10 @@ wrong.
 @chapter Utilities
 
 @menu
-* Memory allocation::   Functions related with memory allocation.
-* Context management::  Functions related with context management.
+* Memory allocation::   Functions related to memory allocation.
+* Context management::  Functions related to context management.
 * Buffer description::  A data type to describe buffers.
-* Config reporting::    How to return Libgcrypt's configuration.
+* Config reporting::    How to check Libgcrypt's configuration.
 @end menu
 
 
@@ -5255,7 +5706,7 @@ wrong.
 
 This function tries to allocate @var{n} bytes of memory.  On success
 it returns a pointer to the memory area, in an out-of-core condition,
-it returns NULL.
+it returns @code{NULL}.
 @end deftypefun
 
 @deftypefun {void *} gcry_malloc_secure (size_t @var{n})
@@ -5267,7 +5718,7 @@ Like @code{gcry_malloc}, but uses secure memory.
 This function allocates a cleared block of memory (i.e. initialized with
 zero bytes) long enough to contain a vector of @var{n} elements, each of
 size @var{m} bytes.  On success it returns a pointer to the memory
-block; in an out-of-core condition, it returns NULL.
+block; in an out-of-core condition, it returns @code{NULL}.
 @end deftypefun
 
 @deftypefun {void *} gcry_calloc_secure (size_t @var{n}, size_t @var{m})
@@ -5278,9 +5729,9 @@ Like @code{gcry_calloc}, but uses secure memory.
 
 This function tries to resize the memory area pointed to by @var{p} to
 @var{n} bytes.  On success it returns a pointer to the new memory
-area, in an out-of-core condition, it returns NULL.  Depending on
+area, in an out-of-core condition, it returns @code{NULL}.  Depending on
 whether the memory pointed to by @var{p} is secure memory or not,
-gcry_realloc tries to use secure memory as well.
+@code{gcry_realloc} tries to use secure memory as well.
 @end deftypefun
 
 @deftypefun void gcry_free (void *@var{p})
@@ -5291,7 +5742,7 @@ Release the memory area pointed to by @var{p}.
 @node Context management
 @section Context management
 
-Some function make use of a context object.  As of now there are only
+Some function make use of a context object.  As of now, there are only
 a few math functions. However, future versions of Libgcrypt may make
 more use of this context object.
 
@@ -5308,7 +5759,7 @@ Release the context object @var{ctx} and all associated resources.  A
 @node Buffer description
 @section Buffer description
 
-To help hashing non-contiguous areas of memory a general purpose data
+To help hashing non-contiguous areas of memory, a general purpose data
 type is defined:
 
 @deftp {Data type} {gcry_buffer_t}
@@ -5330,7 +5781,7 @@ of this structure are:
 @end deftp
 
 @node Config reporting
-@section How to return Libgcrypt's configuration.
+@section How to check Libgcrypt's configuration.
 
 Although @code{GCRYCTL_PRINT_CONFIG} can be used to print
 configuration options, it is sometimes necessary to check them in a
@@ -5343,12 +5794,12 @@ program.  This can be accomplished by using this function:
 This function returns a malloced string with colon delimited configure
 options.  With a value of 0 for @var{mode} this string resembles the
 output of @code{GCRYCTL_PRINT_CONFIG}.  However, if @var{what} is not
-NULL, only the line where the first field (e.g. "cpu-arch") matches
+@code{NULL}, only the line where the first field (e.g. "cpu-arch") matches
 @var{what} is returned.
 
 Other values than 0 for @var{mode} are not defined.  The caller shall
-free the string using @code{gcry_free}.  On error NULL is returned and
-ERRNO is set; if a value for WHAT is unknow ERRNO will be set to 0.
+free the string using @code{gcry_free}.  On error @code{NULL} is returned and
+@code{ERRNO} is set; if a value for @var{what} is unknown, @code{ERRNO} will be set to 0.
 @end deftypefun
 
 
@@ -5408,7 +5859,7 @@ the command line.
 
 @item --binary
 Print the MAC as a binary string.  The default is to print the MAC
-encoded has lower case hex digits.
+encoded as lower case hex digits.
 
 @item --version
 Print version of the program and exit.
@@ -5435,6 +5886,11 @@ The environment variables considered by Libgcrypt are:
 
 @table @code
 
+@item LIBGCRYPT_FORCE_FIPS_MODE
+@cindex LIBGCRYPT_FORCE_FIPS_MODE
+By setting this variable to any value, Libgcrypt is put into FIPS mode
+at initialization time (@pxref{enabling fips mode}).
+
 @item GCRYPT_BARRETT
 @cindex GCRYPT_BARRETT
 By setting this variable to any value a different algorithm for
@@ -5448,8 +5904,8 @@ These two environment variables are used to enable debug output for
 the rndunix entropy gatherer, which is used on systems lacking a
 /dev/random device.  The value of @code{GCRYPT_RNDUNIX_DBG} is a file
 name or @code{-} for stdout.  Debug output is the written to this
-file.  By setting @code{GCRYPT_RNDUNIX_DBGALL} to any value the debug
-output will be more verbose.
+file.  Setting @code{GCRYPT_RNDUNIX_DBGALL} to any value will make the debug
+output more verbose.
 
 @item GCRYPT_RNDW32_NOPERF
 @cindex GCRYPT_RNDW32_NOPERF
@@ -5471,7 +5927,7 @@ interface.
 This is used to locate the socket to connect to the EGD random
 daemon.  The EGD can be used on system without a /dev/random to speed
 up the random number generator.  It is not needed on the majority of
-today's operating systems and support for EGD requires the use of a
+today's operating systems, and support for EGD requires the use of a
 configure option at build time.
 
 @end table
@@ -5537,11 +5993,11 @@ This chapter describes the internal architecture of Libgcrypt.
 Libgcrypt is a function library written in ISO C-90.  Any compliant
 compiler should be able to build Libgcrypt as long as the target is
 either a POSIX platform or compatible to the API used by Windows NT.
-Provisions have been take so that the library can be directly used from
+Provisions have been taken so that the library can be directly used from
 C++ applications; however building with a C++ compiler is not supported.
 
 Building Libgcrypt is done by using the common @code{./configure && make}
-approach.  The configure command is included in the source distribution
+approach.  The configure command is included in the source distribution,
 and as a portable shell script it works on any Unix-alike system.  The
 result of running the configure script are a C header file
 (@file{config.h}), customized Makefiles, the setup of symbolic links and
@@ -5572,7 +6028,7 @@ all these subsystems provide a public API; this includes the helper
 subsystems like the one for S-expressions.  The API style depends on the
 subsystem; in general an open-use-close approach is implemented.  The
 open returns a handle to a context used for all further operations on
-this handle, several functions may then be used on this handle and a
+this handle, several functions may then be used on this handle, and a
 final close function releases all resources associated with the handle.
 
 @menu
@@ -5594,12 +6050,12 @@ Because public key cryptography is almost always used to process small
 amounts of data (hash values or session keys), the interface is not
 implemented using the open-use-close paradigm, but with single
 self-contained functions.  Due to the wide variety of parameters
-required by different algorithms S-expressions, as flexible way to
-convey these parameters, are used.  There is a set of helper functions
+required by different algorithms, S-expressions - as flexible way to
+convey these parameters - are used.  There is a set of helper functions
 to work with these S-expressions.
 @c see @ref{S-expression Subsystem Architecture}.
 
-Aside of functions to register new algorithms, map algorithms names to
+Aside from functions to register new algorithms, map algorithms names to
 algorithms identifiers and to lookup properties of a key, the
 following main functions are available:
 
@@ -5644,7 +6100,7 @@ random level.
 @cindex X9.31
 @cindex FIPS 186
 The algorithm used for RSA and DSA key generation depends on whether
-Libgcrypt is operated in standard or in FIPS mode.  In standard mode
+Libgcrypt is operating in standard or in FIPS mode.  In standard mode
 an algorithm based on the Lim-Lee prime number generator is used.  In
 FIPS mode RSA keys are generated as specified in ANSI X9.31 (1998) and
 DSA keys as specified in FIPS 186-2.
@@ -5684,6 +6140,9 @@ Set an initialization vector to be used for encryption or decryption.
 Encrypt or decrypt data.  These functions may be called with arbitrary
 amounts of data and as often as needed to encrypt or decrypt all data.
 
+There is no strict alignment requirements for data, but the best
+performance can be archived if data is aligned to cacheline boundary.
+
 @end table
 
 There are also functions to query properties of algorithms or context,
@@ -5721,6 +6180,9 @@ Set the key for the MAC.
 @item gcry_md_write
 Pass more data for computing the message digest to an instance.
 
+There is no strict alignment requirements for data, but the best
+performance can be archived if data is aligned to cacheline boundary.
+
 @item gcry_md_putc
 Buffered version of @code{gcry_md_write} implemented as a macro.
 
@@ -5739,7 +6201,7 @@ memory buffer without the need to create an instance first.
 
 There are also functions to query properties of algorithms or the
 instance, like enabled algorithms, digest length, map algorithm names.
-it is also possible to reset an instance or to copy the current state
+It is also possible to reset an instance or to copy the current state
 of an instance at any time.  Debug functions to write the hashed data
 to files are available as well.
 
@@ -5791,14 +6253,14 @@ Functions specialized for public key cryptography.
 
 Libgcrypt provides an interface to its prime number generator.  These
 functions make use of the internal prime number generator which is
-required for the generation for public key key pairs.  The plain prime
+required for the generation for public key pairs.  The plain prime
 checking function is exported as well.
 
 The generation of random prime numbers is based on the Lim and Lee
-algorithm to create practically save primes.@footnote{Chae Hoon Lim
+algorithm to create practically safe primes.@footnote{Chae Hoon Lim
 and Pil Joong Lee. A key recovery attack on discrete log-based schemes
 using a prime order subgroup. In Burton S. Kaliski Jr., editor,
-Advances in Cryptology: Crypto '97, pages 249­-263, Berlin /
+Advances in Cryptology: Crypto '97, pages 249--263, Berlin /
 Heidelberg / New York, 1997. Springer-Verlag.  Described on page 260.}
 This algorithm creates a pool of smaller primes, select a few of them
 to create candidate primes of the form @math{2 * p_0 * p_1 * ... * p_n
@@ -5845,11 +6307,11 @@ requirements and the function @code{gcry_create_nonce} which is used
 for weaker usages like nonces.  There is also a level
 @code{GCRY_WEAK_RANDOM} which in general maps to
 @code{GCRY_STRONG_RANDOM} except when used with the function
-@code{gcry_mpi_randomize}, where it randomizes an
-multi-precision-integer using the @code{gcry_create_nonce} function.
+@code{gcry_mpi_randomize}, where it randomizes a
+multi-precision integer using the @code{gcry_create_nonce} function.
 
 @noindent
-There are two distinct random generators available:
+There are three distinct random generators available:
 
 @itemize
 @item
@@ -5857,15 +6319,25 @@ The Continuously Seeded Pseudo Random Number Generator (CSPRNG), which
 is based on the classic GnuPG derived big pool implementation.
 Implemented in @code{random/random-csprng.c} and used by default.
 @item
-A FIPS approved ANSI X9.31 PRNG using AES with a 128 bit key. Implemented in
-@code{random/random-fips.c} and used if Libgcrypt is in FIPS mode.
+The Deterministic Random Bits Generator (DRBG), based on the
+specification by NIST SP800-90A.  Implemented in
+@code{random/random-drbg.c} and used if Libgcrypt is in FIPS mode,
+or Libgcrypt is configured by GCRYCTL_SET_PREFERRED_RNG_TYPE with
+GCRY_RNG_TYPE_FIPS.
+@item
+Direct access to native RNG on the system.  Implemented in
+@code{random/random-system.c} and used if Libgcrypt is configured by
+GCRYCTL_SET_PREFERRED_RNG_TYPE with GCRY_RNG_TYPE_SYSTEM.
 @end itemize
 
 @noindent
-Both generators make use of so-called entropy gathering modules:
+All generators make use of so-called entropy gathering modules:
 
 @table @asis
-@item rndlinux
+@item rndgetentropy
+Uses the operating system provided @code{getentropy} function.
+
+@item rndoldlinux
 Uses the operating system provided @file{/dev/random} and
 @file{/dev/urandom} devices.  The @file{/dev/gcrypt/random.conf}
 config option @option{only-urandom} can be used to inhibit the use of
@@ -5874,7 +6346,7 @@ the blocking @file{/dev/random} device.
 @item rndunix
 Runs several operating system commands to collect entropy from sources
 like virtual machine and process statistics.  It is a kind of
-poor-man's @code{/dev/random} implementation. It is not available in
+poor-man's @code{/dev/random} implementation.  It is not available in
 FIPS mode.
 
 @item rndegd
@@ -5882,8 +6354,7 @@ Uses the operating system provided Entropy Gathering Daemon (EGD).
 The EGD basically uses the same algorithms as rndunix does.  However
 as a system daemon it keeps on running and thus can serve several
 processes requiring entropy input and does not waste collected entropy
-if the application does not need all the collected entropy. It is not
-available in FIPS mode.
+if the application does not need all the collected entropy.
 
 @item rndw32
 Targeted for the Microsoft Windows OS.  It uses certain properties of
@@ -5893,12 +6364,11 @@ that system and is the only gathering module available for that OS.
 Extra module to collect additional entropy by utilizing a hardware
 random number generator.  As of now the supported hardware RNG is
 the Padlock engine of VIA (Centaur) CPUs and x86 CPUs with the RDRAND
-instruction.  It is not available in FIPS mode.
+instruction.
 
 @item rndjent
 Extra module to collect additional entropy using a CPU jitter based
-approach.  This is only used on X86 hardware where the RDTSC opcode is
-available.  The @file{/dev/gcrypt/random.conf} config option
+approach.  The @file{/dev/gcrypt/random.conf} config option
 @option{disable-jent} can be used to inhibit the use of this module.
 
 @end table
@@ -5906,7 +6376,7 @@ available.  The @file{/dev/gcrypt/random.conf} config option
 
 @menu
 * CSPRNG Description::      Description of the CSPRNG.
-* FIPS PRNG Description::   Description of the FIPS X9.31 PRNG.
+* DRBG Description::   Description of the DRBG.
 @end menu
 
 
@@ -5914,20 +6384,20 @@ available.  The @file{/dev/gcrypt/random.conf} config option
 @subsection Description of the CSPRNG
 
 This random number generator is loosely modelled after the one
-described in Peter Gutmann's paper: "Software Generation of
+described in Peter Gutmann's paper "Software Generation of
 Practically Strong Random Numbers".@footnote{Also described in chapter
 6 of his book "Cryptographic Security Architecture", New York, 2004,
 ISBN 0-387-95387-6.}
 
 A pool of 600 bytes is used and mixed using the core SHA-1 hash
-transform function.  Several extra features are used to make the
+transform function.  Several extra features are used to make it
 robust against a wide variety of attacks and to protect against
 failures of subsystems.  The state of the generator may be saved to a
-file and initially seed form a file.
+file and initially seeded form a file.
 
-Depending on how Libgcrypt was build the generator is able to select
+Depending on how Libgcrypt was build, the generator is able to select
 the best working entropy gathering module.  It makes use of the slow
-and fast collection methods and requires the pool to initially seeded
+and fast collection methods and requires the pool to be initially seeded
 form the slow gatherer or a seed file.  An entropy estimation is used
 to mix in enough data from the gather modules before returning the
 actual random output.  Process fork detection and protection is
@@ -5944,46 +6414,36 @@ created by hashing all the 28 bytes with SHA-1 and saving that again
 in the first 20 bytes.  The hash is also returned as result.
 
 
-@node FIPS PRNG Description
-@subsection Description of the FIPS X9.31 PRNG
+@node DRBG Description
+@subsection Description of the DRBG
 
 The core of this deterministic random number generator is implemented
-according to the document ``NIST-Recommended Random Number Generator
-Based on ANSI X9.31 Appendix A.2.4 Using the 3-Key Triple DES and AES
-Algorithms'', dated 2005-01-31.  This implementation uses the AES
-variant.
+according to the document ``NIST Recommended DRBG Based on ANSI NIST
+SP800-90A''.  By default, this implementation uses the
+DRBG_NOPR_HMACSHA256 variant (HMAC DRBG with DF with SHA256, without
+prediction resistance.
 
 The generator is based on contexts to utilize the same core functions
 for all random levels as required by the high-level interface.  All
 random generators return their data in 128 bit blocks.  If the caller
-requests less bits, the extra bits are not used.  The key for each
+requests fewer bits, the extra bits are not used.  The key for each
 generator is only set once at the first time a generator context is
 used.  The seed value is set along with the key and again after 1000
 output blocks.
 
 On Unix like systems the @code{GCRY_VERY_STRONG_RANDOM} and
 @code{GCRY_STRONG_RANDOM} generators are keyed and seeded using the
-rndlinux module with the @file{/dev/random} device. Thus these
+rndgetentropy or rndoldlinux module.  With rndoldlinux module, these
 generators may block until the OS kernel has collected enough entropy.
-When used with Microsoft Windows the rndw32 module is used instead.
+When used with Microsoft Windows, the rndw32 module is used instead.
 
 The generator used for @code{gcry_create_nonce} is keyed and seeded
-from the @code{GCRY_STRONG_RANDOM} generator.  Thus is may also block
-if the @code{GCRY_STRONG_RANDOM} generator has not yet been used
-before and thus gets initialized on the first use by
-@code{gcry_create_nonce}.  This special treatment is justified by the
-weaker requirements for a nonce generator and to save precious kernel
-entropy for use by the ``real'' random generators.
-
-A self-test facility uses a separate context to check the
-functionality of the core X9.31 functions using a known answers test.
-During runtime each output block is compared to the previous one to
-detect a stuck generator.
-
-The DT value for the generator is made up of the current time down to
-microseconds (if available) and a free running 64 bit counter.  When
-used with the test context the DT value is taken from the context and
-incremented on each use.
+from the @code{GCRY_STRONG_RANDOM} generator.  Thus, with rndoldlinux
+module, it may also block if the @code{GCRY_STRONG_RANDOM} generator
+has not yet been used before and thus gets initialized on the first
+use by @code{gcry_create_nonce}.  This special treatment is justified
+by the weaker requirements for a nonce generator and to save precious
+kernel entropy for use by the ``real'' random generators.
 
 @c @node Helper Subsystems Architecture
 @c @section Helper Subsystems Architecture
@@ -6047,7 +6507,7 @@ command may be used to run all implemented self-tests at any time;
 this will even run more tests than those run in FIPS mode.
 
 If any of the self-tests fails, the library immediately returns an
-error code to the caller.  If Libgcrypt is in FIPS mode the self-tests
+error code to the caller.  If Libgcrypt is in FIPS mode, the self-tests
 will be performed within the ``Self-Test'' state and any failure puts
 the library into the ``Error'' state.
 
@@ -6062,25 +6522,6 @@ The following symmetric encryption algorithm tests are run during
 power-up:
 
 @table @asis
-@item 3DES
-To test the 3DES 3-key EDE encryption in ECB mode these tests are
-run:
-@enumerate
-@item
-A known answer test is run on a 64 bit test vector processed by 64
-rounds of Single-DES block encryption and decryption using a key
-changed with each round.
-@item
-A known answer test is run on a 64 bit test vector processed by 16
-rounds of 2-key and 3-key Triple-DES block encryption and decryptions
-using a key changed with each round.
-@item
-10 known answer tests using 3-key Triple-DES EDE encryption, comparing
-the ciphertext to the known value, then running a decryption and
-comparing it to the initial plaintext.
-@end enumerate
-(@code{cipher/des.c:selftest})
-
 @item AES-128
 A known answer tests is run using one test vector and one test
 key with AES in ECB mode. (@code{cipher/rijndael.c:selftest_basic_128})
@@ -6122,20 +6563,29 @@ The following MAC algorithm tests are run during power-up:
 
 @table @asis
 @item HMAC SHA-1
-A known answer test using 9 byte of data and a 64 byte key is run.
-(@code{cipher/hmac-tests.c:selftests_sha1})
+A known answer test using 9 bytes of data and a 64 byte key is run.
+(@code{cipher/mac-hmac.c:selftests_sha1})
 @item HMAC SHA-224
-A known answer test using 28 byte of data and a 4 byte key is run.
-(@code{cipher/hmac-tests.c:selftests_sha224})
+A known answer test using 28 bytes of data and a 4 byte key is run.
+(@code{cipher/mac-hmac.c:selftests_sha224})
 @item HMAC SHA-256
-A known answer test using 28 byte of data and a 4 byte key is run.
-(@code{cipher/hmac-tests.c:selftests_sha256})
+A known answer test using 28 bytes of data and a 4 byte key is run.
+(@code{cipher/mac-hmac.c:selftests_sha256})
 @item HMAC SHA-384
-A known answer test using 28 byte of data and a 4 byte key is run.
-(@code{cipher/hmac-tests.c:selftests_sha384})
+A known answer test using 28 bytes of data and a 4 byte key is run.
+(@code{cipher/mac-hmac.c:selftests_sha384})
 @item HMAC SHA-512
-A known answer test using 28 byte of data and a 4 byte key is run.
-(@code{cipher/hmac-tests.c:selftests_sha512})
+A known answer test using 28 bytes of data and a 4 byte key is run.
+(@code{cipher/mac-hmac.c:selftests_sha512})
+@item HMAC SHA3-224
+@itemx HMAC SHA3-256
+@itemx HMAC SHA3-384
+@itemx HMAC SHA3-512
+A known answer test using 9 bytes of data and a 20 byte key is run.
+(@code{cipher/mac-hmac.c:selftests_sha3})
+@item CMAC AES
+A known answer test using 40 bytes of data and a 16 byte key is run.
+(@code{cipher/mac-cmac.c:selftests_cmac_aes})
 @end table
 
 @subsection Random Number Power-Up Test
@@ -6158,7 +6608,7 @@ The public key algorithms are tested during power-up:
 
 @table @asis
 @item RSA
-A pre-defined 1024 bit RSA key is used and these tests are run
+A pre-defined 2048 bit RSA key is used and these tests are run
 in turn:
 @enumerate
 @item
@@ -6168,50 +6618,50 @@ Conversion of S-expression to internal format.
 Private key consistency check.
 (@code{cipher/@/rsa.c:@/selftests_rsa})
 @item
-A pre-defined 20 byte value is signed with PKCS#1 padding for SHA-1.
+A pre-defined 20 byte value is signed with PKCS#1 padding for SHA-256.
 The result is verified using the public key against the original data
-and against modified data.  (@code{cipher/@/rsa.c:@/selftest_sign_1024})
+and against modified data.  (@code{cipher/@/rsa.c:@/selftest_sign_2048})
 @item
-A 1000 bit random value is encrypted and checked that it does not
-match the original random value.  The encrypted result is then
+A predefined 66 byte value is encrypted and checked that it matches
+reference encyrpted message.  The encrypted result is then
 decrypted and checked that it matches the original random value.
-(@code{cipher/@/rsa.c:@/selftest_encr_1024})
+(@code{cipher/@/rsa.c:@/selftest_encr_2048})
 @end enumerate
 
-@item DSA
-A pre-defined 1024 bit DSA key is used and these tests are run in turn:
+@item ECC
+A pre-defined SEC P-256 ECDSA key is used and these tests are run
+in turn:
 @enumerate
 @item
 Conversion of S-expression to internal format.
-(@code{cipher/@/dsa.c:@/selftests_dsa})
+(@code{cipher/@/ecc.c:@/selftests_ecdsa})
 @item
 Private key consistency check.
-(@code{cipher/@/dsa.c:@/selftests_dsa})
+(@code{cipher/@/ecc.c:@/selftests_ecdsa})
 @item
-A pre-defined 20 byte value is signed with PKCS#1 padding for
-SHA-1.  The result is verified using the public key against the
-original data and against modified data.
-(@code{cipher/@/dsa.c:@/selftest_sign_1024})
+A pre-defined 32 byte value (SHA-256 digest) is signed.
+The result is verified using the public key against the original data
+and against modified data.  (@code{cipher/@/ecc.c:@/selftest_sign})
 @end enumerate
 @end table
 
+@subsection Key derivation function Power-Up Tests
+
+The key derivation functions are tested during power-up:
+
+@table @asis
+@item PBKDF2
+A known answer tests with 8 byte password and 4 byte salt and SHA-1 is used.
+(@code{cipher/@/kdf.c:@/selftest_pbkdf2})
+@end table
+
 @subsection Integrity Power-Up Tests
 
 The integrity of the Libgcrypt is tested during power-up but only if
 checking has been enabled at build time.  The check works by computing
 a HMAC SHA-256 checksum over the file used to load Libgcrypt into
-memory.  That checksum is compared against a checksum stored in a file
-of the same name but with a single dot as a prefix and a suffix of
-@file{.hmac}.
-
-
-@subsection Critical Functions Power-Up Tests
-
-The 3DES weak key detection is tested during power-up by calling the
-detection function with keys taken from a table listening all weak
-keys.  The table itself is protected using a SHA-1 hash.
-(@code{cipher/@/des.c:@/selftest})
-
+memory.  That checksum is compared against a checksum stored inside of
+the same file as in the text in the .rodata1 section of the ELF file.
 
 
 @c --------------------------------
@@ -6233,7 +6683,7 @@ mode, the library is put into the ``Error'' state.
 @item RSA
 The test uses a random number 64 bits less the size of the modulus as
 plaintext and runs an encryption and decryption operation in turn.  The
-encrypted value is checked to not match the plaintext and the result
+encrypted value is checked to not match the plaintext, and the result
 of the decryption is checked to match the plaintext.
 
 A new random number of the same size is generated, signed and verified
@@ -6241,12 +6691,6 @@ to test the correctness of the signing operation.  As a second signing
 test, the signature is modified by incrementing its value and then
 verified with the expected result that the verification fails.
 (@code{cipher/@/rsa.c:@/test_keys})
-@item DSA
-The test uses a random number of the size of the Q parameter to create
-a signature and then checks that the signature verifies.  As a second
-signing test, the data is modified by incrementing its value and then
-verified against the signature with the expected result that the
-verification fails.  (@code{cipher/@/dsa.c:@/test_keys})
 @end table
 
 
@@ -6259,25 +6703,13 @@ No code is loaded at runtime.
 A manual key entry feature is not implemented in Libgcrypt.
 
 
-@subsection Continuous RNG Tests
-
-The continuous random number test is only used in FIPS mode.  The RNG
-generates blocks of 128 bit size; the first block generated per
-context is saved in the context and another block is generated to be
-returned to the caller.  Each block is compared against the saved
-block and then stored in the context.  If a duplicated block is
-detected an error is signaled and the library is put into the
-``Fatal-Error'' state.
-(@code{random/@/random-fips.c:@/x931_aes_driver})
-
-
 
 @c --------------------------------
 @section Application Requested Tests
 
 The application may requests tests at any time by means of the
 @code{GCRYCTL_SELFTEST} control command.  Note that using these tests
-is not FIPS conform: Although Libgcrypt rejects all application
+is not FIPS conformant: Although Libgcrypt rejects all application
 requests for services while running self-tests, it does not ensure
 that no other operations of Libgcrypt are still being executed.  Thus,
 in FIPS mode an application requesting self-tests needs to power-cycle
@@ -6337,35 +6769,85 @@ tests:
 @item HMAC SHA-1
 @enumerate
 @item
-A known answer test using 9 byte of data and a 20 byte key is run.
+A known answer test using 9 bytes of data and a 20 byte key is run.
 @item
-A known answer test using 9 byte of data and a 100 byte key is run.
+A known answer test using 9 bytes of data and a 100 byte key is run.
 @item
-A known answer test using 9 byte of data and a 49 byte key is run.
+A known answer test using 9 bytes of data and a 49 byte key is run.
 @end enumerate
-(@code{cipher/hmac-tests.c:selftests_sha1})
+(@code{cipher/mac-hmac.c:selftests_sha1})
 @item HMAC SHA-224
 @itemx HMAC SHA-256
 @itemx HMAC SHA-384
 @itemx HMAC SHA-512
 @enumerate
 @item
-A known answer test using 9 byte of data and a 20 byte key is run.
+A known answer test using 9 bytes of data and a 20 byte key is run.
+@item
+A known answer test using 50 bytes of data and a 20 byte key is run.
+@item
+A known answer test using 50 bytes of data and a 26 byte key is run.
+@item
+A known answer test using 54 bytes of data and a 131 byte key is run.
+@item
+A known answer test using 152 bytes of data and a 131 byte key is run.
+@end enumerate
+(@code{cipher/@/mac-hmac.c:@/selftests_sha224},
+@code{cipher/@/mac-hmac.c:@/selftests_sha256},
+@code{cipher/@/mac-hmac.c:@/selftests_sha384},
+@code{cipher/@/mac-hmac.c:@/selftests_sha512})
+@end table
+
+@table @asis
+@item HMAC SHA3-224
+@itemx HMAC SHA3-256
+@itemx HMAC SHA3-384
+@itemx HMAC SHA3-512
+@enumerate
+@item
+A known answer test using 28 byte of data and a 4 byte key is run.
 @item
 A known answer test using 50 byte of data and a 20 byte key is run.
 @item
-A known answer test using 50 byte of data and a 26 byte key is run.
+A known answer test using 50 byte of data and a 25 byte key is run.
+@item
+A known answer test using 20 byte of data and a 20 byte key with truncation is run.
 @item
 A known answer test using 54 byte of data and a 131 byte key is run.
 @item
+A known answer test using 54 byte of data and a 147 byte key is run.
+@item
 A known answer test using 152 byte of data and a 131 byte key is run.
+@item
+A known answer test using 152 byte of data and a 147 byte key is run.
 @end enumerate
-(@code{cipher/@/hmac-tests.c:@/selftests_sha224},
-@code{cipher/@/hmac-tests.c:@/selftests_sha256},
-@code{cipher/@/hmac-tests.c:@/selftests_sha384},
-@code{cipher/@/hmac-tests.c:@/selftests_sha512})
+(@code{cipher/@/mac-hmac.c:@/selftests_sha3},
 @end table
 
+@table @asis
+@item CMAC AES
+@enumerate
+@item
+A known answer test using 0 byte of data and a 16 byte key is run.
+@item
+A known answer test using 24 byte of data and a 16 byte key is run.
+@item
+A known answer test using 64 byte of data and a 32 byte key is run.
+@item
+A known answer test using 16 byte of data and a 16 byte key is run.
+@item
+A known answer test using 64 byte of data and a 16 byte key is run.
+@item
+A known answer test using 0 byte of data and a 24 byte key is run.
+@item
+A known answer test using 64 byte of data and a 24 byte key is run.
+@item
+A known answer test using 0 byte of data and a 32 byte key is run.
+@item
+A known answer test using 16 byte of data and a 32 byte key is run.
+@end enumerate
+(@code{cipher/@/mac-cmac.c:@/selftests_cmac_aes},
+@end table
 
 @c ********************************************
 @node FIPS Mode
@@ -6380,15 +6862,13 @@ described in the appendix on self-tests.
 @section Restrictions in FIPS Mode
 
 @noindent
-If Libgcrypt is used in FIPS mode these restrictions are effective:
+If Libgcrypt is used in FIPS mode, these restrictions are effective:
 
 @itemize
 @item
 The cryptographic algorithms are restricted to this list:
 
 @table @asis
-@item GCRY_CIPHER_3DES
-3 key EDE Triple-DES symmetric encryption.
 @item GCRY_CIPHER_AES128
 AES 128 bit symmetric encryption.
 @item GCRY_CIPHER_AES192
@@ -6405,6 +6885,14 @@ SHA-256 message digest.
 SHA-384 message digest.
 @item GCRY_MD_SHA512
 SHA-512 message digest.
+@item GCRY_MD_SHA3_224
+SHA3-224 message digest.
+@item GCRY_MD_SHA3_256
+SHA3-256 message digest.
+@item GCRY_MD_SHA3_384
+SHA3-384 message digest.
+@item GCRY_MD_SHA3_512
+SHA3-512 message digest.
 @item GCRY_MD_SHA1,GCRY_MD_FLAG_HMAC
 HMAC using a SHA-1 message digest.
 @item GCRY_MD_SHA224,GCRY_MD_FLAG_HMAC
@@ -6415,38 +6903,45 @@ HMAC using a SHA-256 message digest.
 HMAC using a SHA-384 message digest.
 @item GCRY_MD_SHA512,GCRY_MD_FLAG_HMAC
 HMAC using a SHA-512 message digest.
+@item GCRY_MD_SHA3_224,GCRY_MD_FLAG_HMAC
+HMAC using a SHA3-224 message digest.
+@item GCRY_MD_SHA3_256,GCRY_MD_FLAG_HMAC
+HMAC using a SHA3-256 message digest.
+@item GCRY_MD_SHA3_384,GCRY_MD_FLAG_HMAC
+HMAC using a SHA3-384 message digest.
+@item GCRY_MD_SHA3_512,GCRY_MD_FLAG_HMAC
+HMAC using a SHA3-512 message digest.
+@item GCRY_MAC_CMAC_AES
+CMAC using a AES key.
 @item GCRY_PK_RSA
 RSA encryption and signing.
-@item GCRY_PK_DSA
-DSA signing.
+@item GCRY_PK_ECC
+ECC encryption and signing.
 @end table
 
 Note that the CRC algorithms are not considered cryptographic algorithms
 and thus are in addition available.
 
 @item
-RSA key generation refuses to create a key with a keysize of
-less than 1024 bits.
+RSA key generation refuses to create and use a key with a keysize of
+less than 2048 bits.
 
 @item
-DSA key generation refuses to create a key with a keysize other
-than 1024 bits.
-
-@item
-The @code{transient-key} flag for RSA and DSA key generation is ignored.
+The @code{transient-key} flag for RSA key generation is ignored.
 
 @item
 Support for the VIA Padlock engine is disabled.
 
 @item
-FIPS mode may only be used on systems with a /dev/random device.
-Switching into FIPS mode on other systems will fail at runtime.
+FIPS mode may only be used on systems with a /dev/random device or
+with a getentropy syscall. Switching into FIPS mode on other systems
+will fail at runtime.
 
 @item
 Saving and loading a random seed file is ignored.
 
 @item
-An X9.31 style random number generator is used in place of the
+The DRBG style random number generator is used in place of the
 large-pool-CSPRNG generator.
 
 @item
@@ -6463,21 +6958,22 @@ On-the-fly self-tests are not performed, instead self-tests are run
 before entering operational state.
 
 @item
-The function @code{gcry_set_allocation_handler} may not be used.  If
-it is used Libgcrypt disables FIPS mode unless Enforced FIPS mode is
-enabled, in which case Libgcrypt will enter the error state.
+The function @code{gcry_set_allocation_handler} may not be used. In FIPS mode
+this function does not have any effect, because FIPS has requirements for
+memory zeroization.
+
+@item
+The digest algorithm MD5 may not be used.
 
 @item
-The digest algorithm MD5 may not be used.  If it is used Libgcrypt
-disables FIPS mode unless Enforced FIPS mode is enabled, in which case
-Libgcrypt will enter the error state.
+The signatures using SHA-1 digest algorithm may not be used.
 
 @item
-In Enforced FIPS mode the command @code{GCRYCTL_DISABLE_SECMEM} is
-ignored.  In standard FIPS mode it disables FIPS mode.
+In FIPS mode the command @code{GCRYCTL_DISABLE_SECMEM} is ignored.
 
 @item
 A handler set by @code{gcry_set_outofcore_handler} is ignored.
+
 @item
 A handler set by @code{gcry_set_fatalerror_handler} is ignored.
 
@@ -6490,7 +6986,7 @@ not mean that any non FIPS algorithms are allowed.
 @c ********************************************
 @section FIPS Finite State Machine
 
-The FIPS mode of libgcrypt implements a finite state machine (FSM) using
+The FIPS mode of Libgcrypt implements a finite state machine (FSM) using
 8 states (@pxref{tbl:fips-states}) and checks at runtime that only valid
 transitions (@pxref{tbl:fips-state-transitions}) may happen.
 
@@ -6537,7 +7033,7 @@ will automatically transit into the  Shutdown state.
 
 @item Shutdown
 Libgcrypt is about to be terminated and removed from the memory. The
-application may at this point still running cleanup handlers.
+application may at this point still run cleanup handlers.
 
 @end table
 @end float
@@ -6558,7 +7054,7 @@ Libgcrypt initialization function @code{gcry_check_version}.
 
 @item 3
 Init to Self-Test is either triggered by a dedicated API call or implicit
-by invoking a libgrypt service controlled by the FSM.
+by invoking a Libgrypt service controlled by the FSM.
 
 @item 4
 Self-Test to Operational is triggered after all self-tests passed
@@ -6570,7 +7066,7 @@ in Libgcrypt.  When reaching the Shutdown state the library is
 deinitialized and can't return to any other state again.
 
 @item 6
-Shutdown to Power-off is the process of removing Libgcrypt from the
+Shutdown to Power-Off is the process of removing Libgcrypt from the
 computer's memory.  For obvious reasons the Power-Off state can't be
 represented within Libgcrypt and thus this transition is for
 documentation only.
@@ -6595,7 +7091,7 @@ after having reported the error.
 
 @item 11
 Power-On to Shutdown is an artificial state to document that Libgcrypt
-has not ye been initialized but the process is about to terminate.
+has not yet been initialized but the process is about to terminate.
 
 @item 12
 Power-On to Fatal-Error will be triggered if certain Libgcrypt functions
@@ -6618,7 +7114,7 @@ the self-tests again.
 
 @item 17
 Error to Self-Test is triggered if the application has requested to run
-self-tests to get to get back into operational state after an error.
+self-tests to get back into operational state after an error.
 
 @item 18
 Init to Error is triggered by errors in the initialization code.
@@ -6682,13 +7178,4 @@ memory and thus also the encryption contexts with these keys.
 
 @bye
 
-GCRYCTL_SET_RANDOM_DAEMON_SOCKET
-GCRYCTL_USE_RANDOM_DAEMON
-The random daemon is still a bit experimental, thus we do not document
-them.  Note that they should be used during initialization and that
-these functions are not really thread safe.
-
-
-
-
 @c  LocalWords:  int HD
diff --git a/doc/libgcrypt-modules.eps b/doc/libgcrypt-modules.eps
deleted file mode 100644 (file)
index 61c60ab..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-%!PS-Adobe-3.0 EPSF-3.0
-%%Title: /home/wk/s/libgcrypt-1.8/doc/libgcrypt-modules.fig
-%%Creator: fig2dev Version 3.2 Patchlevel 5e
-%%CreationDate: Fri Oct 26 19:32:26 2018
-%%BoundingBox: 0 0 488 300
-%Magnification: 1.0000
-%%EndComments
-%%BeginProlog
-/$F2psDict 200 dict def
-$F2psDict begin
-$F2psDict /mtrx matrix put
-/col-1 {0 setgray} bind def
-/col0 {0.000 0.000 0.000 srgb} bind def
-/col1 {0.000 0.000 1.000 srgb} bind def
-/col2 {0.000 1.000 0.000 srgb} bind def
-/col3 {0.000 1.000 1.000 srgb} bind def
-/col4 {1.000 0.000 0.000 srgb} bind def
-/col5 {1.000 0.000 1.000 srgb} bind def
-/col6 {1.000 1.000 0.000 srgb} bind def
-/col7 {1.000 1.000 1.000 srgb} bind def
-/col8 {0.000 0.000 0.560 srgb} bind def
-/col9 {0.000 0.000 0.690 srgb} bind def
-/col10 {0.000 0.000 0.820 srgb} bind def
-/col11 {0.530 0.810 1.000 srgb} bind def
-/col12 {0.000 0.560 0.000 srgb} bind def
-/col13 {0.000 0.690 0.000 srgb} bind def
-/col14 {0.000 0.820 0.000 srgb} bind def
-/col15 {0.000 0.560 0.560 srgb} bind def
-/col16 {0.000 0.690 0.690 srgb} bind def
-/col17 {0.000 0.820 0.820 srgb} bind def
-/col18 {0.560 0.000 0.000 srgb} bind def
-/col19 {0.690 0.000 0.000 srgb} bind def
-/col20 {0.820 0.000 0.000 srgb} bind def
-/col21 {0.560 0.000 0.560 srgb} bind def
-/col22 {0.690 0.000 0.690 srgb} bind def
-/col23 {0.820 0.000 0.820 srgb} bind def
-/col24 {0.500 0.190 0.000 srgb} bind def
-/col25 {0.630 0.250 0.000 srgb} bind def
-/col26 {0.750 0.380 0.000 srgb} bind def
-/col27 {1.000 0.500 0.500 srgb} bind def
-/col28 {1.000 0.630 0.630 srgb} bind def
-/col29 {1.000 0.750 0.750 srgb} bind def
-/col30 {1.000 0.880 0.880 srgb} bind def
-/col31 {1.000 0.840 0.000 srgb} bind def
-/col32 {0.557 0.557 0.557 srgb} bind def
-/col33 {0.255 0.271 0.255 srgb} bind def
-/col34 {0.753 0.753 0.753 srgb} bind def
-/col35 {0.502 0.502 0.502 srgb} bind def
-/col36 {0.388 0.388 0.388 srgb} bind def
-/col37 {0.804 0.804 0.804 srgb} bind def
-/col38 {0.424 0.424 0.424 srgb} bind def
-/col39 {0.776 0.718 0.592 srgb} bind def
-/col40 {0.937 0.973 1.000 srgb} bind def
-/col41 {0.863 0.796 0.651 srgb} bind def
-/col42 {0.251 0.251 0.251 srgb} bind def
-/col43 {0.878 0.878 0.878 srgb} bind def
-/col44 {0.557 0.561 0.557 srgb} bind def
-/col45 {0.667 0.667 0.667 srgb} bind def
-/col46 {0.333 0.333 0.333 srgb} bind def
-/col47 {0.843 0.843 0.843 srgb} bind def
-/col48 {0.682 0.682 0.682 srgb} bind def
-/col49 {0.745 0.745 0.745 srgb} bind def
-/col50 {0.318 0.318 0.318 srgb} bind def
-/col51 {0.906 0.890 0.906 srgb} bind def
-/col52 {0.000 0.000 0.286 srgb} bind def
-/col53 {0.475 0.475 0.475 srgb} bind def
-/col54 {0.188 0.204 0.188 srgb} bind def
-/col55 {0.255 0.255 0.255 srgb} bind def
-/col56 {0.780 0.714 0.588 srgb} bind def
-/col57 {0.867 0.616 0.576 srgb} bind def
-/col58 {0.945 0.925 0.878 srgb} bind def
-/col59 {0.765 0.765 0.765 srgb} bind def
-/col60 {0.886 0.784 0.659 srgb} bind def
-/col61 {0.882 0.882 0.882 srgb} bind def
-/col62 {0.824 0.824 0.824 srgb} bind def
-/col63 {0.929 0.929 0.929 srgb} bind def
-/col64 {0.855 0.478 0.102 srgb} bind def
-/col65 {0.945 0.894 0.102 srgb} bind def
-/col66 {0.533 0.490 0.761 srgb} bind def
-/col67 {0.839 0.839 0.839 srgb} bind def
-/col68 {0.549 0.549 0.647 srgb} bind def
-/col69 {0.290 0.290 0.290 srgb} bind def
-/col70 {0.549 0.420 0.420 srgb} bind def
-/col71 {0.353 0.353 0.353 srgb} bind def
-/col72 {0.718 0.608 0.451 srgb} bind def
-/col73 {0.255 0.576 1.000 srgb} bind def
-/col74 {0.749 0.439 0.231 srgb} bind def
-/col75 {0.859 0.467 0.000 srgb} bind def
-/col76 {0.855 0.722 0.000 srgb} bind def
-/col77 {0.000 0.392 0.000 srgb} bind def
-/col78 {0.353 0.420 0.231 srgb} bind def
-/col79 {0.827 0.827 0.827 srgb} bind def
-/col80 {0.557 0.557 0.643 srgb} bind def
-/col81 {0.953 0.725 0.365 srgb} bind def
-/col82 {0.537 0.600 0.420 srgb} bind def
-/col83 {0.392 0.392 0.392 srgb} bind def
-/col84 {0.718 0.902 1.000 srgb} bind def
-/col85 {0.525 0.753 0.925 srgb} bind def
-/col86 {0.741 0.741 0.741 srgb} bind def
-/col87 {0.827 0.584 0.322 srgb} bind def
-/col88 {0.596 0.824 0.996 srgb} bind def
-/col89 {0.549 0.612 0.420 srgb} bind def
-/col90 {0.969 0.420 0.000 srgb} bind def
-/col91 {0.353 0.420 0.224 srgb} bind def
-/col92 {0.549 0.612 0.420 srgb} bind def
-/col93 {0.549 0.612 0.482 srgb} bind def
-/col94 {0.094 0.290 0.094 srgb} bind def
-/col95 {0.678 0.678 0.678 srgb} bind def
-/col96 {0.969 0.741 0.353 srgb} bind def
-/col97 {0.388 0.420 0.612 srgb} bind def
-/col98 {0.969 0.969 0.969 srgb} bind def
-/col99 {0.871 0.000 0.000 srgb} bind def
-/col100 {0.678 0.678 0.678 srgb} bind def
-/col101 {0.969 0.741 0.353 srgb} bind def
-/col102 {0.678 0.678 0.678 srgb} bind def
-/col103 {0.969 0.741 0.353 srgb} bind def
-/col104 {0.388 0.420 0.612 srgb} bind def
-/col105 {0.322 0.420 0.161 srgb} bind def
-/col106 {0.580 0.580 0.580 srgb} bind def
-/col107 {0.000 0.388 0.000 srgb} bind def
-/col108 {0.000 0.388 0.290 srgb} bind def
-/col109 {0.482 0.518 0.290 srgb} bind def
-/col110 {0.906 0.741 0.482 srgb} bind def
-/col111 {0.647 0.710 0.776 srgb} bind def
-/col112 {0.420 0.420 0.580 srgb} bind def
-/col113 {0.518 0.420 0.420 srgb} bind def
-/col114 {0.322 0.612 0.290 srgb} bind def
-/col115 {0.839 0.906 0.906 srgb} bind def
-/col116 {0.322 0.388 0.388 srgb} bind def
-/col117 {0.094 0.420 0.290 srgb} bind def
-/col118 {0.612 0.647 0.710 srgb} bind def
-/col119 {1.000 0.580 0.000 srgb} bind def
-/col120 {1.000 0.580 0.000 srgb} bind def
-/col121 {0.000 0.388 0.290 srgb} bind def
-/col122 {0.482 0.518 0.290 srgb} bind def
-/col123 {0.388 0.451 0.482 srgb} bind def
-/col124 {0.906 0.741 0.482 srgb} bind def
-/col125 {0.871 0.871 0.871 srgb} bind def
-/col126 {0.953 0.933 0.827 srgb} bind def
-/col127 {0.961 0.682 0.365 srgb} bind def
-/col128 {0.584 0.808 0.600 srgb} bind def
-/col129 {0.710 0.082 0.490 srgb} bind def
-/col130 {0.933 0.933 0.933 srgb} bind def
-/col131 {0.518 0.518 0.518 srgb} bind def
-/col132 {0.482 0.482 0.482 srgb} bind def
-/col133 {0.000 0.353 0.000 srgb} bind def
-/col134 {0.906 0.451 0.451 srgb} bind def
-/col135 {1.000 0.796 0.192 srgb} bind def
-/col136 {0.161 0.475 0.290 srgb} bind def
-/col137 {0.871 0.157 0.129 srgb} bind def
-/col138 {0.129 0.349 0.776 srgb} bind def
-/col139 {0.973 0.973 0.973 srgb} bind def
-/col140 {0.902 0.902 0.902 srgb} bind def
-/col141 {0.129 0.518 0.353 srgb} bind def
-/col142 {0.788 0.788 0.788 srgb} bind def
-/col143 {0.875 0.847 0.875 srgb} bind def
-/col144 {0.969 0.953 0.969 srgb} bind def
-
-end
-
-/cp {closepath} bind def
-/ef {eofill} bind def
-/gr {grestore} bind def
-/gs {gsave} bind def
-/sa {save} bind def
-/rs {restore} bind def
-/l {lineto} bind def
-/m {moveto} bind def
-/rm {rmoveto} bind def
-/n {newpath} bind def
-/s {stroke} bind def
-/sh {show} bind def
-/slc {setlinecap} bind def
-/slj {setlinejoin} bind def
-/slw {setlinewidth} bind def
-/srgb {setrgbcolor} bind def
-/rot {rotate} bind def
-/sc {scale} bind def
-/sd {setdash} bind def
-/ff {findfont} bind def
-/sf {setfont} bind def
-/scf {scalefont} bind def
-/sw {stringwidth} bind def
-/tr {translate} bind def
-/tnt {dup dup currentrgbcolor
-  4 -2 roll dup 1 exch sub 3 -1 roll mul add
-  4 -2 roll dup 1 exch sub 3 -1 roll mul add
-  4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
-  bind def
-/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
-  4 -2 roll mul srgb} bind def
-/reencdict 12 dict def /ReEncode { reencdict begin
-/newcodesandnames exch def /newfontname exch def /basefontname exch def
-/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def
-basefontdict { exch dup /FID ne { dup /Encoding eq
-{ exch dup length array copy newfont 3 1 roll put }
-{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall
-newfont /FontName newfontname put newcodesandnames aload pop
-128 1 255 { newfont /Encoding get exch /.notdef put } for
-newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat
-newfontname newfont definefont pop end } def
-/isovec [
-8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde
-8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis
-8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron
-8#220 /dotlessi 8#230 /oe 8#231 /OE
-8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling
-8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis
-8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot
-8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus
-8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph
-8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine
-8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf
-8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute
-8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring
-8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute
-8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute
-8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve
-8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply
-8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex
-8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave
-8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring
-8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute
-8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute
-8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve
-8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide
-8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex
-8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def
-/Helvetica /Helvetica-iso isovec ReEncode
-/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
-/$F2psEnd {$F2psEnteredState restore end} def
-
-/pageheader {
-save
-newpath 0 300 moveto 0 0 lineto 488 0 lineto 488 300 lineto closepath clip newpath
--32.6 348.9 translate
-1 -1 scale
-$F2psBegin
-10 setmiterlimit
-0 slj 0 slc
- 0.06299 0.06299 sc
-} bind def
-/pagefooter {
-$F2psEnd
-restore
-} bind def
-%%EndProlog
-pageheader
-%
-% Fig objects follow
-%
-% 
-% here starts figure with depth 50
-% Polyline
-0 slj
-0 slc
-15.000 slw
-n 645 810 m 540 810 540 2055 105 arcto 4 {pop} repeat
-  540 2160 2685 2160 105 arcto 4 {pop} repeat
-  2790 2160 2790 915 105 arcto 4 {pop} repeat
-  2790 810 645 810 105 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 645 2790 m 540 2790 540 4035 105 arcto 4 {pop} repeat
-  540 4140 2685 4140 105 arcto 4 {pop} repeat
-  2790 4140 2790 2895 105 arcto 4 {pop} repeat
-  2790 2790 645 2790 105 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 3345 2790 m 3240 2790 3240 4035 105 arcto 4 {pop} repeat
-  3240 4140 5385 4140 105 arcto 4 {pop} repeat
-  5490 4140 5490 2895 105 arcto 4 {pop} repeat
-  5490 2790 3345 2790 105 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 6075 2805 m 5970 2805 5970 4050 105 arcto 4 {pop} repeat
-  5970 4155 8115 4155 105 arcto 4 {pop} repeat
-  8220 4155 8220 2910 105 arcto 4 {pop} repeat
-  8220 2805 6075 2805 105 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 3345 810 m 3240 810 3240 2055 105 arcto 4 {pop} repeat
-  3240 2160 5385 2160 105 arcto 4 {pop} repeat
-  5490 2160 5490 915 105 arcto 4 {pop} repeat
-  5490 810 3345 810 105 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 6090 810 m 5985 810 5985 2055 105 arcto 4 {pop} repeat
-  5985 2160 8130 2160 105 arcto 4 {pop} repeat
-  8235 2160 8235 915 105 arcto 4 {pop} repeat
-  8235 810 6090 810 105 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 3513 4563 m 3438 4563 3438 5438 75 arcto 4 {pop} repeat
-  3438 5513 4947 5513 75 arcto 4 {pop} repeat
-  5022 5513 5022 4638 75 arcto 4 {pop} repeat
-  5022 4563 3513 4563 75 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 5583 4563 m 5508 4563 5508 5438 75 arcto 4 {pop} repeat
-  5508 5513 7017 5513 75 arcto 4 {pop} repeat
-  7092 5513 7092 4638 75 arcto 4 {pop} repeat
-  7092 4563 5583 4563 75 arcto 4 {pop} repeat
- cp gs col0 s gr 
-% Polyline
-n 1443 4567 m 1368 4567 1368 5442 75 arcto 4 {pop} repeat
-  1368 5517 2877 5517 75 arcto 4 {pop} repeat
-  2952 5517 2952 4642 75 arcto 4 {pop} repeat
-  2952 4567 1443 4567 75 arcto 4 {pop} repeat
- cp gs col0 s gr 
-/Helvetica-iso ff 300.00 scf sf
-900 1440 m
-gs 1 -1 sc (Public-Key) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-900 1815 m
-gs 1 -1 sc (Encryption) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-630 3420 m
-gs 1 -1 sc (Multi-Precision-) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-900 3795 m
-gs 1 -1 sc (Integers) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-3420 3420 m
-gs 1 -1 sc (Prime-Number) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-3420 3795 m
-gs 1 -1 sc (Generator) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-6420 3435 m
-gs 1 -1 sc (Random) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-6420 3810 m
-gs 1 -1 sc (Numbers) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-3600 1440 m
-gs 1 -1 sc (Symmetric) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-3600 1815 m
-gs 1 -1 sc (Encryption) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-6435 1440 m
-gs 1 -1 sc (Hashing) col0 sh gr
-/Helvetica-iso ff 300.00 scf sf
-6435 1815 m
-gs 1 -1 sc (MACing) col0 sh gr
-/Helvetica-iso ff 210.00 scf sf
-3825 5130 m
-gs 1 -1 sc (Memory) col0 sh gr
-/Helvetica-iso ff 210.00 scf sf
-5635 5133 m
-gs 1 -1 sc (Miscelleanous) col0 sh gr
-/Helvetica-iso ff 210.00 scf sf
-1495 5137 m
-gs 1 -1 sc (S-expressions) col0 sh gr
-% here ends figure;
-pagefooter
-showpage
-%%Trailer
-%EOF
diff --git a/doc/libgcrypt-modules.pdf b/doc/libgcrypt-modules.pdf
deleted file mode 100644 (file)
index 6311b1b..0000000
Binary files a/doc/libgcrypt-modules.pdf and /dev/null differ
diff --git a/doc/libgcrypt-modules.png b/doc/libgcrypt-modules.png
deleted file mode 100644 (file)
index fea7b18..0000000
Binary files a/doc/libgcrypt-modules.png and /dev/null differ
diff --git a/doc/stamp-vti b/doc/stamp-vti
deleted file mode 100644 (file)
index ccc0155..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-@set UPDATED 24 October 2018
-@set UPDATED-MONTH October 2018
-@set EDITION 1.8.4
-@set VERSION 1.8.4
diff --git a/doc/version.texi b/doc/version.texi
deleted file mode 100644 (file)
index ccc0155..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-@set UPDATED 24 October 2018
-@set UPDATED-MONTH October 2018
-@set EDITION 1.8.4
-@set VERSION 1.8.4
diff --git a/libgcrypt.txt b/libgcrypt.txt
new file mode 100644 (file)
index 0000000..afce70d
--- /dev/null
@@ -0,0 +1,118 @@
+%%comments:
+<p>
+The copyright licensing notice below applies to this text.  The software
+described in this text has its own copyright notice and license, which can
+usually be found in the distribution itself.
+</p>
+<p>
+Copyright &copy; 2000, 2001, 2002 Free Software Foundation, Inc.
+</p>
+<p>
+Permission is granted to copy, distribute, and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.1 or any
+later version published by the Free Software Foundation; with no Invariant
+Sections, with no Front-Cover Texts, and with no Back-Cover Texts.  A copy
+of this license is included in the file <a href="COPYING.DOC">COPYING.DOC</a>.
+</p>
+
+%%name: Libgcrypt
+
+%%short-description: Cryptographic library
+
+%%full-description: This is a general purpose cryptographic library
+based on the code from GnuPG.  It provides functions for all
+cryptograhic building blocks: symmetric ciphers
+(AES,DES,Blowfish,CAST5,Twofish,Arcfour), hash algorithms (MD4, MD5,
+RIPE-MD160, SHA-1, SHA-256, TIGER-192), MACs (HMAC for all hash algorithms),
+public key algorithms (RSA, ElGamal, DSA), large integer functions,
+random numbers and a lot of supporting functions.
+
+%%category: sec, libs
+
+%%license: LGPL
+
+%%license-verified-by: Janet Casey <jcasey@gnu.org>
+
+%%license-verified-on: 2001-04-23
+
+%%maintainer: Moritz Schulte <libgcrypt 'at' g10code.com>
+
+%%updated: 2004-04-15
+
+%%keywords: encryption, public key, digital signature, hash, libgcrypt
+
+%%interface: Command line
+
+%%programs: 
+
+%%GNU: yes
+
+%%web-page: http://www.gnupg.org
+
+%%support: Paid extension/consulting from http://www.g10code.com
+
+%%doc: Programmer reference in Texinfo, Postscript, HTML included
+
+%%developers:  Matthew Skala, Michael Roth, Niklas Hernaeus, Remi
+Guyomarch, Simon Josefsson, Werner Koch, Moritz Schulte.
+
+%%contributors: 
+
+%%sponsors: 
+
+%%source-tarball: ftp://ftp.gnupg.org/gcrypt/libgcrypt/
+
+%%source-info:
+
+%%source-template:
+
+%%debian:
+
+%%rpm: 
+
+%%repository:  See http://www.gnupg.org/cvs-access.html
+
+%%related:   
+
+%%related-outside-directory: 
+
+%%source-language: C
+
+%%supported-languages: C, C++
+
+%%use-requirements:
+
+%%build-prerequisites:
+
+%%weak-prerequisites: 
+
+%%source-prerequisites:
+
+%%version: 1.3.0-cvs released ...
+
+%%announce-list: <gnupg-announce@gnupg.org>  
+                <gnupg-announce-request@gnupg.org>
+
+%%announce-news:
+
+%%help-list: 
+
+%%help-news:
+
+%%help-irc-channel:
+
+%%dev-irc-channel:
+
+%%dev-list: <gcrypt-devel@gnupg.org>  
+           <gcrypt-devel-request@gnupg.org>
+
+%%dev-news:
+
+%%bug-list: 
+
+%%bug-database: 
+
+%%entry-written-by: Werner Koch <wk@gnupg.org>
+
+%%entry-added: 2001-06-01
+
index 0c90875..c33f100 100644 (file)
@@ -1,2 +1,2 @@
-EXTRA_DIST = libtool.m4 onceonly.m4 socklen.m4 sys_socket_h.m4 noexecstack.m4
+EXTRA_DIST = libtool.m4 socklen.m4 noexecstack.m4
 EXTRA_DIST += gpg-error.m4
diff --git a/m4/Makefile.in b/m4/Makefile.in
deleted file mode 100644 (file)
index 08fe8f1..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = m4
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-SOURCES =
-DIST_SOURCES =
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-EXTRA_DIST = libtool.m4 onceonly.m4 socklen.m4 sys_socket_h.m4 \
-       noexecstack.m4 gpg-error.m4
-all: all-am
-
-.SUFFIXES:
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-               && { if test -f $@; then exit 0; else break; fi; }; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu m4/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-tags TAGS:
-
-ctags CTAGS:
-
-cscope cscopelist:
-
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-check-am: all-am
-check: check-am
-all-am: Makefile
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool mostlyclean-am
-
-distclean: distclean-am
-       -rm -f Makefile
-distclean-am: clean-am distclean-generic
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-generic mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: install-am install-strip
-
-.PHONY: all all-am check check-am clean clean-generic clean-libtool \
-       cscopelist-am ctags-am distclean distclean-generic \
-       distclean-libtool distdir dvi dvi-am html html-am info info-am \
-       install install-am install-data install-data-am install-dvi \
-       install-dvi-am install-exec install-exec-am install-html \
-       install-html-am install-info install-info-am install-man \
-       install-pdf install-pdf-am install-ps install-ps-am \
-       install-strip installcheck installcheck-am installdirs \
-       maintainer-clean maintainer-clean-generic mostlyclean \
-       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-       tags-am uninstall uninstall-am
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/m4/ax_cc_for_build.m4 b/m4/ax_cc_for_build.m4
new file mode 100644 (file)
index 0000000..c62ffad
--- /dev/null
@@ -0,0 +1,77 @@
+# ===========================================================================
+#     https://www.gnu.org/software/autoconf-archive/ax_cc_for_build.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CC_FOR_BUILD
+#
+# DESCRIPTION
+#
+#   Find a build-time compiler. Sets CC_FOR_BUILD and EXEEXT_FOR_BUILD.
+#
+# LICENSE
+#
+#   Copyright (c) 2010 Reuben Thomas <rrt@sc3d.org>
+#   Copyright (c) 1999 Richard Henderson <rth@redhat.com>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 3
+
+dnl Get a default for CC_FOR_BUILD to put into Makefile.
+AC_DEFUN([AX_CC_FOR_BUILD],
+[# Put a plausible default for CC_FOR_BUILD in Makefile.
+if test -z "$CC_FOR_BUILD"; then
+  if test "x$cross_compiling" = "xno"; then
+    CC_FOR_BUILD='$(CC)'
+  else
+    CC_FOR_BUILD=gcc
+  fi
+fi
+AC_SUBST(CC_FOR_BUILD)
+# Also set EXEEXT_FOR_BUILD.
+if test "x$cross_compiling" = "xno"; then
+  EXEEXT_FOR_BUILD='$(EXEEXT)'
+else
+  AC_CACHE_CHECK([for build system executable suffix], bfd_cv_build_exeext,
+    [rm -f conftest*
+     echo 'int main () { return 0; }' > conftest.c
+     bfd_cv_build_exeext=
+     ${CC_FOR_BUILD} -o conftest conftest.c 1>&5 2>&5
+     for file in conftest.*; do
+       case $file in
+       *.c | *.o | *.obj | *.ilk | *.pdb) ;;
+       *) bfd_cv_build_exeext=`echo $file | sed -e s/conftest//` ;;
+       esac
+     done
+     rm -f conftest*
+     test x"${bfd_cv_build_exeext}" = x && bfd_cv_build_exeext=no])
+  EXEEXT_FOR_BUILD=""
+  test x"${bfd_cv_build_exeext}" != xno && EXEEXT_FOR_BUILD=${bfd_cv_build_exeext}
+fi
+AC_SUBST(EXEEXT_FOR_BUILD)])dnl
index 1661204..4b5cd40 100644 (file)
@@ -1,5 +1,6 @@
 # gpg-error.m4 - autoconf macro to detect libgpg-error.
-# Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH
+# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2018, 2020, 2021
+#               g10 Code GmbH
 #
 # This file is free software; as a special exception the author gives
 # unlimited permission to copy and/or distribute it, with or without
@@ -9,7 +10,7 @@
 # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 #
-# Last-changed: 2014-10-02
+# Last-changed: 2022-02-15
 
 
 dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION,
@@ -31,7 +32,7 @@ AC_DEFUN([AM_PATH_GPG_ERROR],
   dnl since that is consistent with how our three siblings use the directory/
   dnl package name in --with-$dir_name-prefix=PFX.
   AC_ARG_WITH(libgpg-error-prefix,
-              AC_HELP_STRING([--with-libgpg-error-prefix=PFX],
+              AS_HELP_STRING([--with-libgpg-error-prefix=PFX],
                              [prefix where GPG Error is installed (optional)]),
               [gpg_error_config_prefix="$withval"])
 
@@ -61,16 +62,90 @@ AC_DEFUN([AM_PATH_GPG_ERROR],
   fi
 
   AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no)
-  min_gpg_error_version=ifelse([$1], ,0.0,$1)
-  AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version)
+  min_gpg_error_version=ifelse([$1], ,1.33,$1)
   ok=no
-  if test "$GPG_ERROR_CONFIG" != "no" \
-     && test -f "$GPG_ERROR_CONFIG" ; then
+
+  AC_PATH_PROG(GPGRT_CONFIG, gpgrt-config, no, [$prefix/bin:$PATH])
+  if test "$GPGRT_CONFIG" != "no"; then
+    # Determine gpgrt_libdir
+    #
+    # Get the prefix of gpgrt-config assuming it's something like:
+    #   <PREFIX>/bin/gpgrt-config
+    gpgrt_prefix=${GPGRT_CONFIG%/*/*}
+    possible_libdir1=${gpgrt_prefix}/lib
+    # Determine by using system libdir-format with CC, it's like:
+    #   Normal style: /usr/lib
+    #   GNU cross style: /usr/<triplet>/lib
+    #   Debian style: /usr/lib/<multiarch-name>
+    #   Fedora/openSUSE style: /usr/lib, /usr/lib32 or /usr/lib64
+    # It is assumed that CC is specified to the one of host on cross build.
+    if libdir_candidates=$(${CC:-cc} -print-search-dirs | \
+          sed -n -e "/^libraries/{s/libraries: =//;s/:/\\
+/g;p;}"); then
+      # From the output of -print-search-dirs, select valid pkgconfig dirs.
+      libdir_candidates=$(for dir in $libdir_candidates; do
+        if p=$(cd $dir 2>/dev/null && pwd); then
+          test -d "$p/pkgconfig" && echo $p;
+        fi
+      done)
+
+      for possible_libdir0 in $libdir_candidates; do
+        # possible_libdir0:
+        #   Fallback candidate, the one of system-installed (by $CC)
+        #   (/usr/<triplet>/lib, /usr/lib/<multiarch-name> or /usr/lib32)
+        # possible_libdir1:
+        #   Another candidate, user-locally-installed
+        #   (<gpgrt_prefix>/lib)
+        # possible_libdir2
+        #   Most preferred
+        #   (<gpgrt_prefix>/<triplet>/lib,
+        #    <gpgrt_prefix>/lib/<multiarch-name> or <gpgrt_prefix>/lib32)
+        if test "${possible_libdir0##*/}" = "lib"; then
+          possible_prefix0=${possible_libdir0%/lib}
+          possible_prefix0_triplet=${possible_prefix0##*/}
+          if test -z "$possible_prefix0_triplet"; then
+            continue
+          fi
+          possible_libdir2=${gpgrt_prefix}/$possible_prefix0_triplet/lib
+        else
+          possible_prefix0=${possible_libdir0%%/lib*}
+          possible_libdir2=${gpgrt_prefix}${possible_libdir0#$possible_prefix0}
+        fi
+        if test -f ${possible_libdir2}/pkgconfig/gpg-error.pc; then
+          gpgrt_libdir=${possible_libdir2}
+        elif test -f ${possible_libdir1}/pkgconfig/gpg-error.pc; then
+          gpgrt_libdir=${possible_libdir1}
+        elif test -f ${possible_libdir0}/pkgconfig/gpg-error.pc; then
+          gpgrt_libdir=${possible_libdir0}
+        fi
+        if test -n "$gpgrt_libdir"; then break; fi
+      done
+    else
+      # When we cannot determine system libdir-format, use this:
+      gpgrt_libdir=${possible_libdir1}
+    fi
+  else
+    unset GPGRT_CONFIG
+  fi
+
+  if test -n "$gpgrt_libdir"; then
+    GPGRT_CONFIG="$GPGRT_CONFIG --libdir=$gpgrt_libdir"
+    if $GPGRT_CONFIG gpg-error >/dev/null 2>&1; then
+      GPG_ERROR_CONFIG="$GPGRT_CONFIG gpg-error"
+      AC_MSG_NOTICE([Use gpgrt-config with $gpgrt_libdir as gpg-error-config])
+      gpg_error_config_version=`$GPG_ERROR_CONFIG --modversion`
+    else
+      unset GPGRT_CONFIG
+    fi
+  elif test "$GPG_ERROR_CONFIG" != "no"; then
+    gpg_error_config_version=`$GPG_ERROR_CONFIG --version`
+    unset GPGRT_CONFIG
+  fi
+  if test "$GPG_ERROR_CONFIG" != "no"; then
     req_major=`echo $min_gpg_error_version | \
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
     req_minor=`echo $min_gpg_error_version | \
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
-    gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version`
     major=`echo $gpg_error_config_version | \
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
     minor=`echo $gpg_error_config_version | \
@@ -85,22 +160,34 @@ AC_DEFUN([AM_PATH_GPG_ERROR],
         fi
     fi
   fi
+  AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version)
   if test $ok = yes; then
-    GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags`
-    GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs`
-    GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --cflags 2>/dev/null`
-    GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --libs 2>/dev/null`
+    GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG --cflags`
+    GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG --libs`
+    if test -z "$GPGRT_CONFIG"; then
+      GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG --mt --cflags 2>/dev/null`
+      GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG --mt --libs 2>/dev/null`
+    else
+      GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG --variable=mtcflags 2>/dev/null`
+      GPG_ERROR_MT_CFLAGS="$GPG_ERROR_CFLAGS${GPG_ERROR_CFLAGS:+ }$GPG_ERROR_MT_CFLAGS"
+      GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG --variable=mtlibs 2>/dev/null`
+      GPG_ERROR_MT_LIBS="$GPG_ERROR_LIBS${GPG_ERROR_LIBS:+ }$GPG_ERROR_MT_LIBS"
+    fi
     AC_MSG_RESULT([yes ($gpg_error_config_version)])
     ifelse([$2], , :, [$2])
-    gpg_error_config_host=`$GPG_ERROR_CONFIG $gpg_error_config_args --host 2>/dev/null || echo none`
+    if test -z "$GPGRT_CONFIG"; then
+      gpg_error_config_host=`$GPG_ERROR_CONFIG --host 2>/dev/null || echo none`
+    else
+      gpg_error_config_host=`$GPG_ERROR_CONFIG --variable=host 2>/dev/null || echo none`
+    fi
     if test x"$gpg_error_config_host" != xnone ; then
       if test x"$gpg_error_config_host" != x"$host" ; then
   AC_MSG_WARN([[
 ***
-*** The config script $GPG_ERROR_CONFIG was
+*** The config script "$GPG_ERROR_CONFIG" was
 *** built for $gpg_error_config_host and thus may not match the
 *** used host $host.
-*** You may want to use the configure option --with-gpg-error-prefix
+*** You may want to use the configure option --with-libgpg-error-prefix
 *** to specify a matching config script or use \$SYSROOT.
 ***]])
         gpg_config_script_warn="$gpg_config_script_warn libgpg-error"
index 1d62b05..c6f534e 100644 (file)
@@ -34,7 +34,7 @@ m4_define([_LT_COPYING], [dnl
 #
 # You should have received a copy of the GNU General Public License
 # along with GNU Libtool; see the file COPYING.  If not, a copy
-# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# can be downloaded from https://www.gnu.org/licenses/gpl.html, or
 # obtained by writing to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 ])
@@ -1045,16 +1045,11 @@ _LT_EOF
       _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
     darwin1.*)
       _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
-    darwin*) # darwin 5.x on
-      # if running on 10.5 or later, the deployment target defaults
-      # to the OS version, if on x86, and 10.4, the deployment
-      # target defaults to 10.4. Don't you love it?
-      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
-       10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
-         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
-       10.[[012]]*)
+    darwin*)
+      case ${MACOSX_DEPLOYMENT_TARGET},$host in
+       10.[[012]]*,*|,*powerpc*)
          _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
-       10.*)
+       *)
          _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
       esac
     ;;
@@ -7474,7 +7469,7 @@ AC_LANG_POP
 # to write the compiler configuration to `libtool'.
 m4_defun([_LT_LANG_GCJ_CONFIG],
 [AC_REQUIRE([LT_PROG_GCJ])dnl
-AC_LANG_SAVE
+AC_LANG_PUSH([Java])
 
 # Source file extension for Java test sources.
 ac_ext=java
@@ -7530,7 +7525,7 @@ if test -n "$compiler"; then
   _LT_CONFIG($1)
 fi
 
-AC_LANG_RESTORE
+AC_LANG_POP
 
 GCC=$lt_save_GCC
 CC=$lt_save_CC
@@ -7545,7 +7540,7 @@ CFLAGS=$lt_save_CFLAGS
 # to write the compiler configuration to `libtool'.
 m4_defun([_LT_LANG_GO_CONFIG],
 [AC_REQUIRE([LT_PROG_GO])dnl
-AC_LANG_SAVE
+AC_LANG_PUSH([Go])
 
 # Source file extension for Go test sources.
 ac_ext=go
@@ -7601,7 +7596,7 @@ if test -n "$compiler"; then
   _LT_CONFIG($1)
 fi
 
-AC_LANG_RESTORE
+AC_LANG_POP
 
 GCC=$lt_save_GCC
 CC=$lt_save_CC
@@ -7616,7 +7611,9 @@ CFLAGS=$lt_save_CFLAGS
 # to write the compiler configuration to `libtool'.
 m4_defun([_LT_LANG_RC_CONFIG],
 [AC_REQUIRE([LT_PROG_RC])dnl
-AC_LANG_SAVE
+
+dnl Here, something like AC_LANG_PUSH([RC]) is expected.
+dnl But Resource Compiler is not supported as a language by autoconf
 
 # Source file extension for RC test sources.
 ac_ext=rc
@@ -7655,8 +7652,10 @@ if test -n "$compiler"; then
   _LT_CONFIG($1)
 fi
 
+dnl Here, AC_LANG_POP is expected.
 GCC=$lt_save_GCC
-AC_LANG_RESTORE
+dnl Back to C
+AC_LANG([C])
 CC=$lt_save_CC
 CFLAGS=$lt_save_CFLAGS
 ])# _LT_LANG_RC_CONFIG
index 4aab484..ae0b26b 100644 (file)
@@ -25,7 +25,7 @@ AC_REQUIRE([AM_PROG_AS])
 
 AC_MSG_CHECKING([whether non excutable stack support is requested])
 AC_ARG_ENABLE(noexecstack,
-              AC_HELP_STRING([--disable-noexecstack],
+              AS_HELP_STRING([--disable-noexecstack],
                              [disable non executable stack support]),
               noexecstack_support=$enableval, noexecstack_support=yes)
 AC_MSG_RESULT($noexecstack_support)
diff --git a/m4/onceonly.m4 b/m4/onceonly.m4
deleted file mode 100644 (file)
index 6d913fa..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-# onceonly.m4 serial 4 (gettext-0.15)
-dnl Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-dnl This file defines some "once only" variants of standard autoconf macros.
-dnl   AC_CHECK_HEADERS_ONCE         like  AC_CHECK_HEADERS
-dnl   AC_CHECK_FUNCS_ONCE           like  AC_CHECK_FUNCS
-dnl   AC_CHECK_DECLS_ONCE           like  AC_CHECK_DECLS
-dnl   AC_REQUIRE([AC_HEADER_STDC])  like  AC_HEADER_STDC
-dnl The advantage is that the check for each of the headers/functions/decls
-dnl will be put only once into the 'configure' file. It keeps the size of
-dnl the 'configure' file down, and avoids redundant output when 'configure'
-dnl is run.
-dnl The drawback is that the checks cannot be conditionalized. If you write
-dnl   if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi
-dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to
-dnl empty, and the check will be inserted before the body of the AC_DEFUNed
-dnl function.
-
-dnl This file is only needed in autoconf <= 2.59.  Newer versions of autoconf
-dnl have this macro built-in.  But about AC_CHECK_DECLS_ONCE: note that in
-dnl autoconf >= 2.60 the symbol separator is a comma, whereas here it is
-dnl whitespace.
-
-dnl Autoconf version 2.57 or newer is recommended.
-AC_PREREQ(2.54)
-
-# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of
-# AC_CHECK_HEADERS(HEADER1 HEADER2 ...).
-AC_DEFUN([AC_CHECK_HEADERS_ONCE], [
-  :
-  AC_FOREACH([gl_HEADER_NAME], [$1], [
-    AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(m4_defn([gl_HEADER_NAME]),
-                                                 [-./], [___])), [
-      AC_CHECK_HEADERS(gl_HEADER_NAME)
-    ])
-    AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME,
-                                                   [-./], [___])))
-  ])
-])
-
-# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of
-# AC_CHECK_FUNCS(FUNC1 FUNC2 ...).
-AC_DEFUN([AC_CHECK_FUNCS_ONCE], [
-  :
-  AC_FOREACH([gl_FUNC_NAME], [$1], [
-    AC_DEFUN([gl_CHECK_FUNC_]m4_defn([gl_FUNC_NAME]), [
-      AC_CHECK_FUNCS(m4_defn([gl_FUNC_NAME]))
-    ])
-    AC_REQUIRE([gl_CHECK_FUNC_]m4_defn([gl_FUNC_NAME]))
-  ])
-])
-
-# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of
-# AC_CHECK_DECLS(DECL1, DECL2, ...).
-AC_DEFUN([AC_CHECK_DECLS_ONCE], [
-  :
-  AC_FOREACH([gl_DECL_NAME], [$1], [
-    AC_DEFUN([gl_CHECK_DECL_]m4_defn([gl_DECL_NAME]), [
-      AC_CHECK_DECLS(m4_defn([gl_DECL_NAME]))
-    ])
-    AC_REQUIRE([gl_CHECK_DECL_]m4_defn([gl_DECL_NAME]))
-  ])
-])
index 5e3765a..251960b 100644 (file)
@@ -1,5 +1,5 @@
-# socklen.m4 serial 4
-dnl Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+# socklen.m4 serial 11
+dnl Copyright (C) 2005-2007, 2009-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -8,45 +8,69 @@ dnl From Albert Chin, Windows fixes from Simon Josefsson.
 
 dnl Check for socklen_t: historically on BSD it is an int, and in
 dnl POSIX 1g it is a type of its own, but some platforms use different
-dnl types for the argument to getsockopt, getpeername, etc.  So we
-dnl have to test to find something that will work.
+dnl types for the argument to getsockopt, getpeername, etc.:
+dnl HP-UX 10.20, IRIX 6.5, OSF/1 4.0, Interix 3.5, BeOS.
+dnl So we have to test to find something that will work.
 
-dnl On mingw32, socklen_t is in ws2tcpip.h ('int'), so we try to find
-dnl it there first.  That file is included by gnulib's socket_.h, which
-dnl all users of this module should include.  Cygwin must not include
-dnl ws2tcpip.h.
 AC_DEFUN([gl_TYPE_SOCKLEN_T],
-  [AC_REQUIRE([gl_HEADER_SYS_SOCKET])dnl
+  [AC_REQUIRE([gl_CHECK_SOCKET_HEADERS])dnl
    AC_CHECK_TYPE([socklen_t], ,
-     [AC_MSG_CHECKING([for socklen_t equivalent])
-      AC_CACHE_VAL([gl_cv_gl_cv_socklen_t_equiv],
-       [# Systems have either "struct sockaddr *" or
-        # "void *" as the second argument to getpeername
-        gl_cv_socklen_t_equiv=
-        for arg2 in "struct sockaddr" void; do
-          for t in int size_t "unsigned int" "long int" "unsigned long int"; do
-            AC_TRY_COMPILE(
-              [#include <sys/types.h>
-               #include <sys/socket.h>
+     [AC_CACHE_CHECK([for socklen_t equivalent],
+        [gl_cv_socklen_t_equiv],
+        [# Systems have either "struct sockaddr *" or
+         # "void *" as the second argument to getpeername
+         gl_cv_socklen_t_equiv=
+         for arg2 in "struct sockaddr" void; do
+           for t in int size_t "unsigned int" "long int" "unsigned long int"; do
+             AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+                 [[#include <sys/types.h>
+                   #include <sys/socket.h>
 
-               int getpeername (int, $arg2 *, $t *);],
-              [$t len;
-               getpeername (0, 0, &len);],
-              [gl_cv_socklen_t_equiv="$t"])
-            test "$gl_cv_socklen_t_equiv" != "" && break
-          done
-          test "$gl_cv_socklen_t_equiv" != "" && break
-        done
-      ])
-      if test "$gl_cv_socklen_t_equiv" = ""; then
-       AC_MSG_ERROR([Cannot find a type to use in place of socklen_t])
-      fi
-      AC_MSG_RESULT([$gl_cv_socklen_t_equiv])
+                   int getpeername (int, $arg2 *, $t *);]],
+                 [[$t len;
+                  getpeername (0, 0, &len);]])],
+               [gl_cv_socklen_t_equiv="$t"])
+             test "$gl_cv_socklen_t_equiv" != "" && break
+           done
+           test "$gl_cv_socklen_t_equiv" != "" && break
+         done
+         if test "$gl_cv_socklen_t_equiv" = ""; then
+           AC_MSG_ERROR([Cannot find a type to use in place of socklen_t])
+         fi
+        ])
       AC_DEFINE_UNQUOTED([socklen_t], [$gl_cv_socklen_t_equiv],
-       [type to use in place of socklen_t if not defined])],
-     [#include <sys/types.h>
-      #if HAVE_SYS_SOCKET_H
-      # include <sys/socket.h>
-      #elif HAVE_WS2TCPIP_H
-      # include <ws2tcpip.h>
-      #endif])])
+        [type to use in place of socklen_t if not defined])],
+     [gl_SOCKET_HEADERS])])
+
+dnl On mingw32, socklen_t is in ws2tcpip.h ('int'), so we try to find
+dnl it there too.  But on Cygwin, wc2tcpip.h must not be included.  Users
+dnl of this module should use the same include pattern as gl_SOCKET_HEADERS.
+dnl When you change this macro, keep also in sync:
+dnl   - gl_CHECK_SOCKET_HEADERS,
+dnl   - the Include section of modules/socklen.
+AC_DEFUN([gl_SOCKET_HEADERS],
+[
+/* <sys/types.h> is not needed according to POSIX, but the
+   <sys/socket.h> in i386-unknown-freebsd4.10 and
+   powerpc-apple-darwin5.5 required it. */
+#include <sys/types.h>
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#elif HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+#endif
+])
+
+dnl Tests for the existence of the header for socket facilities.
+dnl Defines the C macros HAVE_SYS_SOCKET_H, HAVE_WS2TCPIP_H.
+dnl This macro must match gl_SOCKET_HEADERS.
+AC_DEFUN([gl_CHECK_SOCKET_HEADERS],
+  [AC_CHECK_HEADERS_ONCE([sys/socket.h])
+   if test $ac_cv_header_sys_socket_h = no; then
+     dnl We cannot use AC_CHECK_HEADERS_ONCE here, because that would make
+     dnl the check for those headers unconditional; yet cygwin reports
+     dnl that the headers are present but cannot be compiled (since on
+     dnl cygwin, all socket information should come from sys/socket.h).
+     AC_CHECK_HEADERS([ws2tcpip.h])
+   fi
+  ])
diff --git a/m4/sys_socket_h.m4 b/m4/sys_socket_h.m4
deleted file mode 100644 (file)
index d3e45b4..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# sys_socket_h.m4 serial 2
-dnl Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-dnl From Simon Josefsson.
-
-AC_DEFUN([gl_HEADER_SYS_SOCKET],
-[
-  AC_CHECK_HEADERS_ONCE([sys/socket.h])
-  if test $ac_cv_header_sys_socket_h = yes; then
-    SYS_SOCKET_H=''
-  else
-    dnl We cannot use AC_CHECK_HEADERS_ONCE here, because that would make
-    dnl the check for those headers unconditional; yet cygwin reports
-    dnl that the headers are present but cannot be compiled (since on
-    dnl cygwin, all socket information should come from sys/socket.h).
-    AC_CHECK_HEADERS([winsock2.h ws2tcpip.h])
-    SYS_SOCKET_H='sys/socket.h'
-  fi
-  AC_SUBST(SYS_SOCKET_H)
-])
index 8f39ee7..e1362c8 100644 (file)
@@ -173,5 +173,8 @@ libmpi_la_SOURCES = longlong.h         \
              mpicoder.c     \
              mpih-div.c     \
              mpih-mul.c     \
-             mpiutil.c      \
-              ec.c ec-internal.h ec-ed25519.c
+             mpih-const-time.c \
+             mpiutil.c         \
+              ec.c ec-internal.h ec-ed25519.c ec-nist.c ec-inline.h \
+              ec-hw-s390x.c
+EXTRA_libmpi_la_SOURCES = asm-common-aarch64.h asm-common-amd64.h
diff --git a/mpi/Makefile.in b/mpi/Makefile.in
deleted file mode 100644 (file)
index 3102b5c..0000000
+++ /dev/null
@@ -1,828 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Copyright (C) 1992, 1999, 2000, 2002 Free Software Foundation, Inc.
-#
-# 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-# 1.5 leads to a combinatorial explosion due to all the conditionals
-# I was not able to build it with 64Megs - 1.6 fixes this.
-# not anymore required: AUTOMAKE_OPTIONS = 1.6
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-subdir = mpi
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-       $(top_srcdir)/build-aux/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-LTLIBRARIES = $(noinst_LTLIBRARIES)
-libmpi_la_LIBADD =
-am_libmpi_la_OBJECTS = mpi-add.lo mpi-bit.lo mpi-cmp.lo mpi-div.lo \
-       mpi-gcd.lo mpi-inline.lo mpi-inv.lo mpi-mul.lo mpi-mod.lo \
-       mpi-pow.lo mpi-mpow.lo mpi-scan.lo mpicoder.lo mpih-div.lo \
-       mpih-mul.lo mpiutil.lo ec.lo ec-ed25519.lo
-@MPI_MOD_ASM_MPIH_ADD1_FALSE@@MPI_MOD_C_MPIH_ADD1_TRUE@am__objects_1 = mpih-add1.lo
-@MPI_MOD_ASM_MPIH_ADD1_TRUE@am__objects_1 = mpih-add1-asm.lo
-@MPI_MOD_ASM_MPIH_SUB1_FALSE@@MPI_MOD_C_MPIH_SUB1_TRUE@am__objects_2 = mpih-sub1.lo
-@MPI_MOD_ASM_MPIH_SUB1_TRUE@am__objects_2 = mpih-sub1-asm.lo
-@MPI_MOD_ASM_MPIH_MUL1_FALSE@@MPI_MOD_C_MPIH_MUL1_TRUE@am__objects_3 = mpih-mul1.lo
-@MPI_MOD_ASM_MPIH_MUL1_TRUE@am__objects_3 = mpih-mul1-asm.lo
-@MPI_MOD_ASM_MPIH_MUL2_FALSE@@MPI_MOD_C_MPIH_MUL2_TRUE@am__objects_4 = mpih-mul2.lo
-@MPI_MOD_ASM_MPIH_MUL2_TRUE@am__objects_4 = mpih-mul2-asm.lo
-@MPI_MOD_ASM_MPIH_MUL3_FALSE@@MPI_MOD_C_MPIH_MUL3_TRUE@am__objects_5 = mpih-mul3.lo
-@MPI_MOD_ASM_MPIH_MUL3_TRUE@am__objects_5 = mpih-mul3-asm.lo
-@MPI_MOD_ASM_MPIH_LSHIFT_FALSE@@MPI_MOD_C_MPIH_LSHIFT_TRUE@am__objects_6 = mpih-lshift.lo
-@MPI_MOD_ASM_MPIH_LSHIFT_TRUE@am__objects_6 = mpih-lshift-asm.lo
-@MPI_MOD_ASM_MPIH_RSHIFT_FALSE@@MPI_MOD_C_MPIH_RSHIFT_TRUE@am__objects_7 = mpih-rshift.lo
-@MPI_MOD_ASM_MPIH_RSHIFT_TRUE@am__objects_7 = mpih-rshift-asm.lo
-@MPI_MOD_ASM_UDIV_FALSE@@MPI_MOD_C_UDIV_TRUE@am__objects_8 = udiv.lo
-@MPI_MOD_ASM_UDIV_TRUE@am__objects_8 = udiv-asm.lo
-@MPI_MOD_ASM_UDIV_QRNND_FALSE@@MPI_MOD_C_UDIV_QRNND_TRUE@am__objects_9 = udiv-qrnnd.lo
-@MPI_MOD_ASM_UDIV_QRNND_TRUE@am__objects_9 = udiv-qrnnd-asm.lo
-nodist_libmpi_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
-       $(am__objects_3) $(am__objects_4) $(am__objects_5) \
-       $(am__objects_6) $(am__objects_7) $(am__objects_8) \
-       $(am__objects_9)
-libmpi_la_OBJECTS = $(am_libmpi_la_OBJECTS) \
-       $(nodist_libmpi_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-libmpi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(libmpi_la_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS)
-LTCPPASCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) \
-       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-       $(AM_CCASFLAGS) $(CCASFLAGS)
-AM_V_CPPAS = $(am__v_CPPAS_@AM_V@)
-am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@)
-am__v_CPPAS_0 = @echo "  CPPAS   " $@;
-am__v_CPPAS_1 = 
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-       $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(libmpi_la_SOURCES) $(nodist_libmpi_la_SOURCES)
-DIST_SOURCES = $(libmpi_la_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-
-# Need to include ../src in addition to top_srcdir because gcrypt.h is
-# a built header.
-AM_CPPFLAGS = -I../src -I$(top_srcdir)/src
-AM_CFLAGS = $(GPG_ERROR_CFLAGS)
-AM_ASFLAGS = $(MPI_SFLAGS)
-AM_CCASFLAGS = $(NOEXECSTACK_FLAGS)
-EXTRA_DIST = config.links
-DISTCLEANFILES = mpi-asm-defs.h \
-                 mpih-add1-asm.S mpih-mul1-asm.S mpih-mul2-asm.S mpih-mul3-asm.S  \
-                mpih-lshift-asm.S mpih-rshift-asm.S mpih-sub1-asm.S asm-syntax.h \
-                 mpih-add1.c mpih-mul1.c mpih-mul2.c mpih-mul3.c  \
-                mpih-lshift.c mpih-rshift.c mpih-sub1.c \
-                sysdep.h mod-source-info.h
-
-@MPI_MOD_ASM_MPIH_ADD1_FALSE@@MPI_MOD_C_MPIH_ADD1_FALSE@mpih_add1 = 
-@MPI_MOD_ASM_MPIH_ADD1_FALSE@@MPI_MOD_C_MPIH_ADD1_TRUE@mpih_add1 = mpih-add1.c
-
-# Beware: The following list is not a comment but grepped by
-#         config.links to get the list of symlinked modules
-#         Optional modules are marked with an O in the second column.
-#BEGIN_ASM_LIST
-# mpih-add1    C
-# mpih-sub1    C
-# mpih-mul1    C
-# mpih-mul2    C
-# mpih-mul3    C
-# mpih-lshift  C
-# mpih-rshift  C
-# udiv         O
-# udiv-qrnnd   O
-#END_ASM_LIST
-
-# Note: This function has not yet been implemented.  There is only a dummy in
-# generic/
-# udiv-w-sdiv  O
-
-# And we need to have conditionals for all modules because
-# we don't know whether they are .c or .S.  Very ugly; I know.
-# Remember to define them all in configure.ac
-@MPI_MOD_ASM_MPIH_ADD1_TRUE@mpih_add1 = mpih-add1-asm.S
-@MPI_MOD_ASM_MPIH_SUB1_FALSE@@MPI_MOD_C_MPIH_SUB1_FALSE@mpih_sub1 = 
-@MPI_MOD_ASM_MPIH_SUB1_FALSE@@MPI_MOD_C_MPIH_SUB1_TRUE@mpih_sub1 = mpih-sub1.c
-@MPI_MOD_ASM_MPIH_SUB1_TRUE@mpih_sub1 = mpih-sub1-asm.S
-@MPI_MOD_ASM_MPIH_MUL1_FALSE@@MPI_MOD_C_MPIH_MUL1_FALSE@mpih_mul1 = 
-@MPI_MOD_ASM_MPIH_MUL1_FALSE@@MPI_MOD_C_MPIH_MUL1_TRUE@mpih_mul1 = mpih-mul1.c
-@MPI_MOD_ASM_MPIH_MUL1_TRUE@mpih_mul1 = mpih-mul1-asm.S
-@MPI_MOD_ASM_MPIH_MUL2_FALSE@@MPI_MOD_C_MPIH_MUL2_FALSE@mpih_mul2 = 
-@MPI_MOD_ASM_MPIH_MUL2_FALSE@@MPI_MOD_C_MPIH_MUL2_TRUE@mpih_mul2 = mpih-mul2.c
-@MPI_MOD_ASM_MPIH_MUL2_TRUE@mpih_mul2 = mpih-mul2-asm.S
-@MPI_MOD_ASM_MPIH_MUL3_FALSE@@MPI_MOD_C_MPIH_MUL3_FALSE@mpih_mul3 = 
-@MPI_MOD_ASM_MPIH_MUL3_FALSE@@MPI_MOD_C_MPIH_MUL3_TRUE@mpih_mul3 = mpih-mul3.c
-@MPI_MOD_ASM_MPIH_MUL3_TRUE@mpih_mul3 = mpih-mul3-asm.S
-@MPI_MOD_ASM_MPIH_LSHIFT_FALSE@@MPI_MOD_C_MPIH_LSHIFT_FALSE@mpih_lshift = 
-@MPI_MOD_ASM_MPIH_LSHIFT_FALSE@@MPI_MOD_C_MPIH_LSHIFT_TRUE@mpih_lshift = mpih-lshift.c
-@MPI_MOD_ASM_MPIH_LSHIFT_TRUE@mpih_lshift = mpih-lshift-asm.S
-@MPI_MOD_ASM_MPIH_RSHIFT_FALSE@@MPI_MOD_C_MPIH_RSHIFT_FALSE@mpih_rshift = 
-@MPI_MOD_ASM_MPIH_RSHIFT_FALSE@@MPI_MOD_C_MPIH_RSHIFT_TRUE@mpih_rshift = mpih-rshift.c
-@MPI_MOD_ASM_MPIH_RSHIFT_TRUE@mpih_rshift = mpih-rshift-asm.S
-@MPI_MOD_ASM_UDIV_FALSE@@MPI_MOD_C_UDIV_FALSE@udiv = 
-@MPI_MOD_ASM_UDIV_FALSE@@MPI_MOD_C_UDIV_TRUE@udiv = udiv.c
-@MPI_MOD_ASM_UDIV_TRUE@udiv = udiv-asm.S
-@MPI_MOD_ASM_UDIV_QRNND_FALSE@@MPI_MOD_C_UDIV_QRNND_FALSE@udiv_qrnnd = 
-@MPI_MOD_ASM_UDIV_QRNND_FALSE@@MPI_MOD_C_UDIV_QRNND_TRUE@udiv_qrnnd = udiv-qrnnd.c
-@MPI_MOD_ASM_UDIV_QRNND_TRUE@udiv_qrnnd = udiv-qrnnd-asm.S
-noinst_LTLIBRARIES = libmpi.la
-libmpi_la_LDFLAGS = 
-nodist_libmpi_la_SOURCES = $(mpih_add1) $(mpih_sub1) $(mpih_mul1) \
-       $(mpih_mul2) $(mpih_mul3) $(mpih_lshift) $(mpih_rshift) \
-       $(udiv) $(udiv_qrnnd)
-
-libmpi_la_SOURCES = longlong.h    \
-             mpi-add.c      \
-             mpi-bit.c      \
-             mpi-cmp.c      \
-             mpi-div.c      \
-             mpi-gcd.c      \
-             mpi-internal.h \
-             mpi-inline.h   \
-             mpi-inline.c   \
-             mpi-inv.c      \
-             mpi-mul.c      \
-             mpi-mod.c      \
-             mpi-pow.c      \
-             mpi-mpow.c     \
-             mpi-scan.c     \
-             mpicoder.c     \
-             mpih-div.c     \
-             mpih-mul.c     \
-             mpiutil.c      \
-              ec.c ec-internal.h ec-ed25519.c
-
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-               && { if test -f $@; then exit 0; else break; fi; }; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu mpi/Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu mpi/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-clean-noinstLTLIBRARIES:
-       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-       @list='$(noinst_LTLIBRARIES)'; \
-       locs=`for p in $$list; do echo $$p; done | \
-             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-             sort -u`; \
-       test -z "$$locs" || { \
-         echo rm -f $${locs}; \
-         rm -f $${locs}; \
-       }
-
-libmpi.la: $(libmpi_la_OBJECTS) $(libmpi_la_DEPENDENCIES) $(EXTRA_libmpi_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(libmpi_la_LINK)  $(libmpi_la_OBJECTS) $(libmpi_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-       -rm -f *.$(OBJEXT)
-
-distclean-compile:
-       -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ec-ed25519.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ec.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-add.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-bit.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-cmp.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-div.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-gcd.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-inline.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-inv.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-mod.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-mpow.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-mul.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-pow.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpi-scan.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpicoder.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-add1-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-add1.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-div.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-lshift-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-lshift.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-mul.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-mul1-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-mul1.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-mul2-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-mul2.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-mul3-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-mul3.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-rshift-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-rshift.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-sub1-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpih-sub1.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpiutil.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udiv-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udiv-qrnnd-asm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udiv-qrnnd.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udiv.Plo@am__quote@
-
-.S.o:
-@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCCAS_FALSE@        $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ $<
-
-.S.obj:
-@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCCAS_FALSE@        $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.S.lo:
-@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    $(AM_V_CPPAS)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCCAS_FALSE@    DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCCAS_FALSE@        $(AM_V_CPPAS@am__nodep@)$(LTCPPASCOMPILE) -c -o $@ $<
-
-.c.o:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-       $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       set x; \
-       here=`pwd`; \
-       $(am__define_uniq_tagged_files); \
-       shift; \
-       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-         test -n "$$unique" || unique=$$empty_fix; \
-         if test $$# -gt 0; then \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             "$$@" $$unique; \
-         else \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             $$unique; \
-         fi; \
-       fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       $(am__define_uniq_tagged_files); \
-       test -z "$(CTAGS_ARGS)$$unique" \
-         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$unique
-
-GTAGS:
-       here=`$(am__cd) $(top_builddir) && pwd` \
-         && $(am__cd) $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-       list='$(am__tagged_files)'; \
-       case "$(srcdir)" in \
-         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-         *) sdir=$(subdir)/$(srcdir) ;; \
-       esac; \
-       for i in $$list; do \
-         if test -f "$$i"; then \
-           echo "$(subdir)/$$i"; \
-         else \
-           echo "$$sdir/$$i"; \
-         fi; \
-       done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LTLIBRARIES)
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-       mostlyclean-am
-
-distclean: distclean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-       distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
-       clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
-       ctags-am distclean distclean-compile distclean-generic \
-       distclean-libtool distclean-tags distdir dvi dvi-am html \
-       html-am info info-am install install-am install-data \
-       install-data-am install-dvi install-dvi-am install-exec \
-       install-exec-am install-html install-html-am install-info \
-       install-info-am install-man install-pdf install-pdf-am \
-       install-ps install-ps-am install-strip installcheck \
-       installcheck-am installdirs maintainer-clean \
-       maintainer-clean-generic mostlyclean mostlyclean-compile \
-       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-       tags tags-am uninstall uninstall-am
-
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
index fa8cd01..24859b1 100644 (file)
 
 #include "sysdep.h"
 #include "asm-syntax.h"
+#include "asm-common-aarch64.h"
 
 /*******************
  *  mpi_limb_t
  *  _gcry_mpih_add_n( mpi_ptr_t res_ptr,       x0
  *                mpi_ptr_t s1_ptr,            x1
  *                mpi_ptr_t s2_ptr,            x2
- *                mpi_size_t size)             x3
+ *                mpi_size_t size)             w3
  */
 
 .text
 
-.globl _gcry_mpih_add_n
-.type  _gcry_mpih_add_n,%function
-_gcry_mpih_add_n:
-       and     x5, x3, #3;
+.globl C_SYMBOL_NAME(_gcry_mpih_add_n)
+ELF(.type  C_SYMBOL_NAME(_gcry_mpih_add_n),%function)
+C_SYMBOL_NAME(_gcry_mpih_add_n):
+       CFI_STARTPROC()
+       and     w5, w3, #3;
        adds    xzr, xzr, xzr; /* clear carry flag */
 
-       cbz     x5, .Large_loop;
+       cbz     w5, .Large_loop;
 
 .Loop:
        ldr     x4, [x1], #8;
-       sub     x3, x3, #1;
+       sub     w3, w3, #1;
        ldr     x11, [x2], #8;
-       and     x5, x3, #3;
+       and     w5, w3, #3;
        adcs    x4, x4, x11;
        str     x4, [x0], #8;
-       cbz     x3, .Lend;
-       cbnz    x5, .Loop;
+       cbz     w3, .Lend;
+       cbnz    w5, .Loop;
 
 .Large_loop:
        ldp     x4, x6, [x1], #16;
        ldp     x5, x7, [x2], #16;
        ldp     x8, x10, [x1], #16;
        ldp     x9, x11, [x2], #16;
-       sub     x3, x3, #4;
+       sub     w3, w3, #4;
        adcs    x4, x4, x5;
        adcs    x6, x6, x7;
        adcs    x8, x8, x9;
        adcs    x10, x10, x11;
        stp     x4, x6, [x0], #16;
        stp     x8, x10, [x0], #16;
-       cbnz    x3, .Large_loop;
+       cbnz    w3, .Large_loop;
 
 .Lend:
        adc     x0, xzr, xzr;
-       ret;
-.size _gcry_mpih_add_n,.-_gcry_mpih_add_n;
+       ret_spec_stop;
+       CFI_ENDPROC()
+ELF(.size C_SYMBOL_NAME(_gcry_mpih_add_n),.-C_SYMBOL_NAME(_gcry_mpih_add_n);)
index 65e98fe..f34c13c 100644 (file)
 
 #include "sysdep.h"
 #include "asm-syntax.h"
+#include "asm-common-aarch64.h"
 
 /*******************
  * mpi_limb_t
  * _gcry_mpih_mul_1( mpi_ptr_t res_ptr,                x0
  *               mpi_ptr_t s1_ptr,             x1
- *               mpi_size_t s1_size,           x2
+ *               mpi_size_t s1_size,           w2
  *               mpi_limb_t s2_limb)           x3
  */
 
 .text
 
-.globl _gcry_mpih_mul_1
-.type  _gcry_mpih_mul_1,%function
-_gcry_mpih_mul_1:
-       and     x5, x2, #3;
+.globl C_SYMBOL_NAME(_gcry_mpih_mul_1)
+ELF(.type  C_SYMBOL_NAME(_gcry_mpih_mul_1),%function)
+C_SYMBOL_NAME(_gcry_mpih_mul_1):
+       CFI_STARTPROC()
+       and     w5, w2, #3;
        mov     x4, xzr;
 
-       cbz     x5, .Large_loop;
+       cbz     w5, .Large_loop;
 
 .Loop:
        ldr     x5, [x1], #8;
-       sub     x2, x2, #1;
+       sub     w2, w2, #1;
        mul     x9, x5, x3;
        umulh   x10, x5, x3;
-       and     x5, x2, #3;
+       and     w5, w2, #3;
        adds    x4, x4, x9;
        str     x4, [x0], #8;
        adc     x4, x10, xzr;
 
-       cbz     x2, .Lend;
-       cbnz    x5, .Loop;
+       cbz     w2, .Lend;
+       cbnz    w5, .Loop;
 
 .Large_loop:
        ldp     x5, x6, [x1];
-       sub     x2, x2, #4;
+       sub     w2, w2, #4;
 
        mul     x9, x5, x3;
        ldp     x7, x8, [x1, #16];
@@ -88,9 +90,10 @@ _gcry_mpih_mul_1:
        str     x4, [x0], #8;
        adc     x4, x16, xzr;
 
-       cbnz    x2, .Large_loop;
+       cbnz    w2, .Large_loop;
 
 .Lend:
        mov     x0, x4;
-       ret;
-.size _gcry_mpih_mul_1,.-_gcry_mpih_mul_1;
+       ret_spec_stop;
+       CFI_ENDPROC()
+ELF(.size C_SYMBOL_NAME(_gcry_mpih_mul_1),.-C_SYMBOL_NAME(_gcry_mpih_mul_1);)
index bd3b2c9..1880999 100644 (file)
 
 #include "sysdep.h"
 #include "asm-syntax.h"
+#include "asm-common-aarch64.h"
 
 /*******************
  * mpi_limb_t
  * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr,     x0
  *                  mpi_ptr_t s1_ptr,          x1
- *                  mpi_size_t s1_size,        x2
+ *                  mpi_size_t s1_size,        w2
  *                  mpi_limb_t s2_limb)        x3
  */
 
 .text
 
-.globl _gcry_mpih_addmul_1
-.type  _gcry_mpih_addmul_1,%function
-_gcry_mpih_addmul_1:
-       and     x5, x2, #3;
+.globl C_SYMBOL_NAME(_gcry_mpih_addmul_1)
+ELF(.type  C_SYMBOL_NAME(_gcry_mpih_addmul_1),%function)
+C_SYMBOL_NAME(_gcry_mpih_addmul_1):
+       CFI_STARTPROC()
+       and     w5, w2, #3;
        mov     x6, xzr;
        mov     x7, xzr;
 
-       cbz     x5, .Large_loop;
+       cbz     w5, .Large_loop;
 
 .Loop:
        ldr     x5, [x1], #8;
@@ -48,21 +50,21 @@ _gcry_mpih_addmul_1:
        mul     x12, x5, x3;
        ldr     x4, [x0];
        umulh   x13, x5, x3;
-       sub     x2, x2, #1;
+       sub     w2, w2, #1;
 
        adds    x12, x12, x4;
-       and     x5, x2, #3;
+       and     w5, w2, #3;
        adc     x13, x13, x7;
        adds    x12, x12, x6;
        str     x12, [x0], #8;
        adc     x6, x7, x13;
 
-       cbz     x2, .Lend;
-       cbnz    x5, .Loop;
+       cbz     w2, .Lend;
+       cbnz    w5, .Loop;
 
 .Large_loop:
        ldp     x5, x9, [x1], #16;
-       sub     x2, x2, #4;
+       sub     w2, w2, #4;
        ldp     x4, x8, [x0];
 
        mul     x12, x5, x3;
@@ -100,9 +102,10 @@ _gcry_mpih_addmul_1:
        str     x14, [x0], #8;
        adc     x6, x7, x15;
 
-       cbnz    x2, .Large_loop;
+       cbnz    w2, .Large_loop;
 
 .Lend:
        mov     x0, x6;
-       ret;
-.size _gcry_mpih_addmul_1,.-_gcry_mpih_addmul_1;
+       ret_spec_stop;
+       CFI_ENDPROC()
+ELF(.size C_SYMBOL_NAME(_gcry_mpih_addmul_1),.-C_SYMBOL_NAME(_gcry_mpih_addmul_1);)
index a58bc53..e5faedd 100644 (file)
 
 #include "sysdep.h"
 #include "asm-syntax.h"
+#include "asm-common-aarch64.h"
 
 /*******************
  * mpi_limb_t
  * _gcry_mpih_submul_1( mpi_ptr_t res_ptr,     x0
  *                  mpi_ptr_t s1_ptr,          x1
- *                  mpi_size_t s1_size,        x2
+ *                  mpi_size_t s1_size,        w2
  *                  mpi_limb_t s2_limb)        x3
  */
 
 .text
 
-.globl _gcry_mpih_submul_1
-.type  _gcry_mpih_submul_1,%function
-_gcry_mpih_submul_1:
-       and     x5, x2, #3;
+.globl C_SYMBOL_NAME(_gcry_mpih_submul_1)
+ELF(.type  C_SYMBOL_NAME(_gcry_mpih_submul_1),%function)
+C_SYMBOL_NAME(_gcry_mpih_submul_1):
+       CFI_STARTPROC()
+       and     w5, w2, #3;
        mov     x7, xzr;
-       cbz     x5, .Large_loop;
+       cbz     w5, .Large_loop;
 
        subs    xzr, xzr, xzr;
 
@@ -46,26 +48,26 @@ _gcry_mpih_submul_1:
        ldr     x4, [x1], #8;
        cinc    x7, x7, cc;
        ldr     x5, [x0];
-       sub     x2, x2, #1;
+       sub     w2, w2, #1;
 
        mul     x6, x4, x3;
        subs    x5, x5, x7;
        umulh   x4, x4, x3;
-       and     x10, x2, #3;
+       and     w10, w2, #3;
 
        cset    x7, cc;
        subs    x5, x5, x6;
        add     x7, x7, x4;
        str     x5, [x0], #8;
 
-       cbz     x2, .Loop_end;
-       cbnz    x10, .Loop;
+       cbz     w2, .Loop_end;
+       cbnz    w10, .Loop;
 
        cinc    x7, x7, cc;
 
 .Large_loop:
        ldp     x4, x8, [x1], #16;
-       sub     x2, x2, #4;
+       sub     w2, w2, #4;
        ldp     x5, x9, [x0];
 
        mul     x6, x4, x3;
@@ -110,12 +112,13 @@ _gcry_mpih_submul_1:
        str     x9, [x0], #8;
        cinc    x7, x7, cc;
 
-       cbnz    x2, .Large_loop;
+       cbnz    w2, .Large_loop;
 
        mov     x0, x7;
-       ret;
+       ret_spec_stop;
 
 .Loop_end:
        cinc    x0, x7, cc;
-       ret;
-.size _gcry_mpih_submul_1,.-_gcry_mpih_submul_1;
+       ret_spec_stop;
+       CFI_ENDPROC()
+ELF(.size C_SYMBOL_NAME(_gcry_mpih_submul_1),.-C_SYMBOL_NAME(_gcry_mpih_submul_1);)
index cbf2f08..4690828 100644 (file)
 
 #include "sysdep.h"
 #include "asm-syntax.h"
+#include "asm-common-aarch64.h"
 
 /*******************
  *  mpi_limb_t
  *  _gcry_mpih_sub_n( mpi_ptr_t res_ptr,       x0
  *                mpi_ptr_t s1_ptr,            x1
  *                mpi_ptr_t s2_ptr,            x2
- *                mpi_size_t size)             x3
+ *                mpi_size_t size)             w3
  */
 
 .text
 
-.globl _gcry_mpih_sub_n
-.type  _gcry_mpih_sub_n,%function
-_gcry_mpih_sub_n:
-       and     x5, x3, #3;
+.globl C_SYMBOL_NAME(_gcry_mpih_sub_n)
+ELF(.type  C_SYMBOL_NAME(_gcry_mpih_sub_n),%function)
+C_SYMBOL_NAME(_gcry_mpih_sub_n):
+       CFI_STARTPROC()
+       and     w5, w3, #3;
        subs    xzr, xzr, xzr; /* prepare carry flag for sub */
 
-       cbz     x5, .Large_loop;
+       cbz     w5, .Large_loop;
 
 .Loop:
        ldr     x4, [x1], #8;
-       sub     x3, x3, #1;
+       sub     w3, w3, #1;
        ldr     x11, [x2], #8;
-       and     x5, x3, #3;
+       and     w5, w3, #3;
        sbcs    x4, x4, x11;
        str     x4, [x0], #8;
-       cbz     x3, .Lend;
-       cbnz    x5, .Loop;
+       cbz     w3, .Lend;
+       cbnz    w5, .Loop;
 
 .Large_loop:
        ldp     x4, x6, [x1], #16;
        ldp     x5, x7, [x2], #16;
        ldp     x8, x10, [x1], #16;
        ldp     x9, x11, [x2], #16;
-       sub     x3, x3, #4;
+       sub     w3, w3, #4;
        sbcs    x4, x4, x5;
        sbcs    x6, x6, x7;
        sbcs    x8, x8, x9;
        sbcs    x10, x10, x11;
        stp     x4, x6, [x0], #16;
        stp     x8, x10, [x0], #16;
-       cbnz    x3, .Large_loop;
+       cbnz    w3, .Large_loop;
 
 .Lend:
        cset    x0, cc;
-       ret;
-.size _gcry_mpih_sub_n,.-_gcry_mpih_sub_n;
+       ret_spec_stop;
+       CFI_ENDPROC()
+ELF(.size C_SYMBOL_NAME(_gcry_mpih_sub_n),.-C_SYMBOL_NAME(_gcry_mpih_sub_n);)
index ce44674..c3f2d02 100644 (file)
@@ -1,9 +1,16 @@
+#include <config.h>
+
+#include "asm-common-amd64.h"
+
 #ifdef USE_MS_ABI
  /* Store registers and move four first input arguments from MS ABI to
   * SYSV ABI.  */
  #define FUNC_ENTRY() \
+       CFI_STARTPROC(); \
        pushq %rsi; \
+       CFI_PUSH(%rsi); \
        pushq %rdi; \
+       CFI_PUSH(%rdi); \
        movq %rdx, %rsi; \
        movq %rcx, %rdi; \
        movq %r8, %rdx; \
  /* Restore registers.  */
  #define FUNC_EXIT() \
        popq %rdi; \
-       popq %rsi;
+       CFI_POP(%rdi); \
+       popq %rsi; \
+       CFI_POP(%rsi); \
+       ret_spec_stop; \
+       CFI_ENDPROC();
 #else
- #define FUNC_ENTRY() /**/
- #define FUNC_EXIT() /**/
+ #define FUNC_ENTRY() \
+       CFI_STARTPROC();
+
+ #define FUNC_EXIT() \
+       ret_spec_stop; \
+       CFI_ENDPROC();
 #endif
index 6a90262..39c00c5 100644 (file)
@@ -61,5 +61,3 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:)
        movq    %rcx, %rax              /* zero %rax */
        adcq    %rax, %rax
        FUNC_EXIT()
-       ret
-       
\ No newline at end of file
index 9e8979b..a9c7d7e 100644 (file)
        .globl C_SYMBOL_NAME(_gcry_mpih_lshift)
 C_SYMBOL_NAME(_gcry_mpih_lshift:)
        FUNC_ENTRY()
-       movq    -8(%rsi,%rdx,8), %mm7
-       movd    %ecx, %mm1
+       /* Note: %xmm6 and %xmm7 not used for WIN64 ABI compatibility. */
+       movq    -8(%rsi,%rdx,8), %xmm4
+       movd    %ecx, %xmm1
        movl    $64, %eax
        subl    %ecx, %eax
-       movd    %eax, %mm0
-       movq    %mm7, %mm3
-       psrlq   %mm0, %mm7
-       movd    %mm7, %rax
+       movd    %eax, %xmm0
+       movdqa  %xmm4, %xmm3
+       psrlq   %xmm0, %xmm4
+       movd    %xmm4, %rax
        subq    $2, %rdx
        jl      .Lendo
 
        ALIGN(4)                        /* minimal alignment for claimed speed */
-.Loop: movq    (%rsi,%rdx,8), %mm6
-       movq    %mm6, %mm2
-       psrlq   %mm0, %mm6
-       psllq   %mm1, %mm3
-       por     %mm6, %mm3
-       movq    %mm3, 8(%rdi,%rdx,8)
+.Loop: movq    (%rsi,%rdx,8), %xmm5
+       movdqa  %xmm5, %xmm2
+       psrlq   %xmm0, %xmm5
+       psllq   %xmm1, %xmm3
+       por     %xmm5, %xmm3
+       movq    %xmm3, 8(%rdi,%rdx,8)
        je      .Lende
-       movq    -8(%rsi,%rdx,8), %mm7
-       movq    %mm7, %mm3
-       psrlq   %mm0, %mm7
-       psllq   %mm1, %mm2
-       por     %mm7, %mm2
-       movq    %mm2, (%rdi,%rdx,8)
+       movq    -8(%rsi,%rdx,8), %xmm4
+       movdqa  %xmm4, %xmm3
+       psrlq   %xmm0, %xmm4
+       psllq   %xmm1, %xmm2
+       por     %xmm4, %xmm2
+       movq    %xmm2, (%rdi,%rdx,8)
        subq    $2, %rdx
        jge     .Loop
 
-.Lendo:        movq    %mm3, %mm2
-.Lende:        psllq   %mm1, %mm2
-       movq    %mm2, (%rdi)
-       emms
+.Lendo:        movdqa  %xmm3, %xmm2
+.Lende:        psllq   %xmm1, %xmm2
+       movq    %xmm2, (%rdi)
        FUNC_EXIT()
-       ret
index 67ab47e..dacb9d8 100644 (file)
@@ -64,4 +64,3 @@ C_SYMBOL_NAME(_gcry_mpih_mul_1:)
 
        movq    %r8, %rax
        FUNC_EXIT()
-       ret
index 1aa4fa0..0791358 100644 (file)
@@ -63,4 +63,3 @@ C_SYMBOL_NAME(_gcry_mpih_addmul_1:)
 
        movq    %r8, %rax
        FUNC_EXIT()
-       ret
index bc41c4e..f8889eb 100644 (file)
@@ -64,4 +64,3 @@ C_SYMBOL_NAME(_gcry_mpih_submul_1:)
 
        movq    %r8, %rax
        FUNC_EXIT()
-       ret
index 7bd5942..8ecf155 100644 (file)
        .globl C_SYMBOL_NAME(_gcry_mpih_rshift)
 C_SYMBOL_NAME(_gcry_mpih_rshift:)
        FUNC_ENTRY()
-       movq    (%rsi), %mm7
-       movd    %ecx, %mm1
+       /* Note: %xmm6 and %xmm7 not used for WIN64 ABI compatibility. */
+       movq    (%rsi), %xmm4
+       movd    %ecx, %xmm1
        movl    $64, %eax
        subl    %ecx, %eax
-       movd    %eax, %mm0
-       movq    %mm7, %mm3
-       psllq   %mm0, %mm7
-       movd    %mm7, %rax
+       movd    %eax, %xmm0
+       movdqa  %xmm4, %xmm3
+       psllq   %xmm0, %xmm4
+       movd    %xmm4, %rax
        leaq    (%rsi,%rdx,8), %rsi
        leaq    (%rdi,%rdx,8), %rdi
        negq    %rdx
@@ -58,25 +59,23 @@ C_SYMBOL_NAME(_gcry_mpih_rshift:)
        jg      .Lendo
 
        ALIGN(4)                        /* minimal alignment for claimed speed */
-.Loop: movq    -8(%rsi,%rdx,8), %mm6
-       movq    %mm6, %mm2
-       psllq   %mm0, %mm6
-       psrlq   %mm1, %mm3
-       por     %mm6, %mm3
-       movq    %mm3, -16(%rdi,%rdx,8)
+.Loop: movq    -8(%rsi,%rdx,8), %xmm5
+       movdqa  %xmm5, %xmm2
+       psllq   %xmm0, %xmm5
+       psrlq   %xmm1, %xmm3
+       por     %xmm5, %xmm3
+       movq    %xmm3, -16(%rdi,%rdx,8)
        je      .Lende
-       movq    (%rsi,%rdx,8), %mm7
-       movq    %mm7, %mm3
-       psllq   %mm0, %mm7
-       psrlq   %mm1, %mm2
-       por     %mm7, %mm2
-       movq    %mm2, -8(%rdi,%rdx,8)
+       movq    (%rsi,%rdx,8), %xmm4
+       movdqa  %xmm4, %xmm3
+       psllq   %xmm0, %xmm4
+       psrlq   %xmm1, %xmm2
+       por     %xmm4, %xmm2
+       movq    %xmm2, -8(%rdi,%rdx,8)
        addq    $2, %rdx
        jle     .Loop
 
-.Lendo:        movq    %mm3, %mm2
-.Lende:        psrlq   %mm1, %mm2
-       movq    %mm2, -8(%rdi)
-       emms
+.Lendo:        movdqa  %xmm3, %xmm2
+.Lende:        psrlq   %xmm1, %xmm2
+       movq    %xmm2, -8(%rdi)
        FUNC_EXIT()
-       ret
index ccf6496..d60b58a 100644 (file)
@@ -60,4 +60,3 @@ C_SYMBOL_NAME(_gcry_mpih_sub_n:)
        movq    %rcx, %rax              /* zero %rax */
        adcq    %rax, %rax
        FUNC_EXIT()
-       ret
diff --git a/mpi/asm-common-aarch64.h b/mpi/asm-common-aarch64.h
new file mode 100644 (file)
index 0000000..cf4bdb8
--- /dev/null
@@ -0,0 +1,26 @@
+/* asm-common-aarch64.h  -  Common macros for AArch64 assembly
+ *
+ * Copyright (C) 2018 Martin Storsjö <martin@martin.st>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MPI_ASM_COMMON_AARCH64_H
+#define MPI_ASM_COMMON_AARCH64_H
+
+#include "../cipher/asm-common-aarch64.h"
+
+#endif /* MPI_ASM_COMMON_AARCH64_H */
diff --git a/mpi/asm-common-amd64.h b/mpi/asm-common-amd64.h
new file mode 100644 (file)
index 0000000..ad0e8e6
--- /dev/null
@@ -0,0 +1,26 @@
+/* asm-common-amd64.h  -  Common macros for AMD64 assembly
+ *
+ * Copyright (C) 2022 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MPI_ASM_COMMON_AMD64_H
+#define MPI_ASM_COMMON_AMD64_H
+
+#include "../cipher/asm-common-amd64.h"
+
+#endif /* MPI_ASM_COMMON_AMD64_H */
index 3ead4f0..8cd6657 100644 (file)
@@ -50,30 +50,18 @@ case "${host}" in
        path=""
        mpi_cpu_arch="x86"
        ;;
-    i[3467]86*-*-openbsd*         | \
-    i[3467]86*-*-freebsd*-elf     | \
-    i[3467]86*-*-freebsd[3-9]*    | \
-    i[3467]86*-*-freebsd[12][0-9]*| \
-    i[3467]86*-*-freebsdelf*      | \
-    i[3467]86*-*-netbsd*          | \
-    i[3467]86*-*-k*bsd*)
-       echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
-       cat  $srcdir/mpi/i386/syntax.h     >>./mpi/asm-syntax.h
-       path="i386"
-       mpi_cpu_arch="x86"
-       ;;
-    i586*-*-openbsd*         | \
-    i586*-*-freebsd*-elf     | \
-    i586*-*-freebsd[3-9]*    | \
-    i586*-*-freebsd[12][0-9]*| \
-    i586*-*-freebsdelf*      | \
-    i586*-*-netbsd*         | \
-    i586*-*-k*bsd*          | \
-    pentium-*-netbsd*       | \
+    i[34567]86*-*-openbsd*         | \
+    i[34567]86*-*-freebsd*-elf     | \
+    i[34567]86*-*-freebsd[3-9]*    | \
+    i[34567]86*-*-freebsd[12][0-9]*| \
+    i[34567]86*-*-freebsdelf*      | \
+    i[34567]86*-*-netbsd*          | \
+    i[34567]86*-*-k*bsd*           | \
+    pentium-*-netbsd*             | \
     pentiumpro-*-netbsd*)
        echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
        cat  $srcdir/mpi/i386/syntax.h     >>./mpi/asm-syntax.h
-       path="i586 i386"
+       path="i386"
        mpi_cpu_arch="x86"
        ;;
     i[34]86*-*-bsdi4*)
@@ -82,50 +70,28 @@ case "${host}" in
        path="i386"
        mpi_cpu_arch="x86"
        ;;
-    i[3467]86*-*-linuxaout*  | \
-    i[3467]86*-*-linuxoldld* | \
-    i[3467]86*-*-*bsd*)
-       echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h
-       echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h
-       cat  $srcdir/mpi/i386/syntax.h      >>./mpi/asm-syntax.h
-       path="i386"
-        mpi_cpu_arch="x86"
-       ;;
-    i586*-*-linuxaout*  | \
-    i586*-*-linuxoldld* | \
-    i586*-*-*bsd*)
+    i[34567]86*-*-linuxaout*  | \
+    i[34567]86*-*-linuxoldld* | \
+    i[34567]86*-*-*bsd*)
        echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h
        echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h
        cat  $srcdir/mpi/i386/syntax.h      >>./mpi/asm-syntax.h
-       path="i586 i386"
-        mpi_cpu_arch="x86"
-       ;;
-    i[3467]86*-msdosdjgpp* | \
-    i[34]86*-apple-darwin*)
-       echo '#define BSD_SYNTAX'        >>./mpi/asm-syntax.h
-       cat  $srcdir/mpi/i386/syntax.h   >>./mpi/asm-syntax.h
        path="i386"
         mpi_cpu_arch="x86"
        ;;
-    i586*-msdosdjgpp* | \
-    i[567]86*-apple-darwin*)
+    i[34567]86*-msdosdjgpp* | \
+    i[34567]86*-apple-darwin*)
        echo '#define BSD_SYNTAX'        >>./mpi/asm-syntax.h
        cat  $srcdir/mpi/i386/syntax.h   >>./mpi/asm-syntax.h
-       path="i586 i386"
-        mpi_cpu_arch="x86"
-       ;;
-    i[3467]86*-*-*)
-       echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
-       cat  $srcdir/mpi/i386/syntax.h      >>./mpi/asm-syntax.h
        path="i386"
         mpi_cpu_arch="x86"
        ;;
-    i586*-*-*  | \
-    pentium-*-*   | \
+    i[34567]86*-*-* | \
+    pentium-*-*     | \
     pentiumpro-*-*)
        echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h
        cat  $srcdir/mpi/i386/syntax.h      >>./mpi/asm-syntax.h
-       path="i586 i386"
+       path="i386"
         mpi_cpu_arch="x86"
        ;;
     x86_64-apple-darwin*)
@@ -246,6 +212,11 @@ case "${host}" in
        path="mips2"
        mpi_cpu_arch="mips"
        ;;
+    s390x*-*-*)
+       echo '/* No working assembler modules available */' >>./mpi/asm-syntax.h
+       path=""
+       mpi_cpu_arch="s390x"
+       ;;
 
     # Motorola 68k configurations.  Let m68k mean 68020-68040.
     # mc68000 or mc68060 configurations need to be specified explicitly
@@ -375,6 +346,7 @@ if test "$try_asm_modules" != "yes" ; then
     path=""
     mpi_sflags=""
     mpi_extra_modules=""
+    mpi_cpu_arch="disabled"
 fi
 
 # Make sure that mpi_cpu_arch is not the empty string.
@@ -382,6 +354,16 @@ if test x"$mpi_cpu_arch" = x ; then
     mpi_cpu_arch="unknown"
 fi
 
+# Add .note.gnu.property section for Intel CET in assembler sources
+# when CET is enabled.  */
+if test x"$mpi_cpu_arch" = xx86 ; then
+    cat <<EOF >> ./mpi/asm-syntax.h
+
+#if defined(__ASSEMBLER__) && defined(__CET__)
+# include <cet.h>
+#endif
+EOF
+fi
 
 # Make sysdep.h
 echo '/* created by config.links - do not edit */' >./mpi/sysdep.h
diff --git a/mpi/ec-hw-s390x.c b/mpi/ec-hw-s390x.c
new file mode 100644 (file)
index 0000000..149a061
--- /dev/null
@@ -0,0 +1,412 @@
+/* ec-hw-s390x.c -  zSeries ECC acceleration
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef HAVE_GCC_INLINE_ASM_S390X
+
+#include "mpi-internal.h"
+#include "g10lib.h"
+#include "context.h"
+#include "ec-context.h"
+#include "ec-internal.h"
+
+#include "../cipher/bufhelp.h"
+#include "../cipher/asm-inline-s390x.h"
+
+
+#define S390X_PCC_PARAM_BLOCK_SIZE 4096
+
+
+extern void reverse_buffer (unsigned char *buffer, unsigned int length);
+
+static int s390_mul_point_montgomery (mpi_point_t result, gcry_mpi_t scalar,
+                                     mpi_point_t point, mpi_ec_t ctx,
+                                     byte *param_block_buf);
+
+
+static int
+mpi_copy_to_raw(byte *raw, unsigned int raw_nbytes, gcry_mpi_t a)
+{
+  unsigned int num_to_zero;
+  unsigned int nbytes;
+  int i, j;
+
+  if (mpi_has_sign (a))
+    return -1;
+
+  if (mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
+    {
+      unsigned int nbits;
+      byte *buf;
+
+      buf = mpi_get_opaque (a, &nbits);
+      nbytes = (nbits + 7) / 8;
+
+      if (raw_nbytes < nbytes)
+       return -1;
+
+      num_to_zero = raw_nbytes - nbytes;
+      if (num_to_zero > 0)
+        memset (raw, 0, num_to_zero);
+      if (nbytes > 0)
+       memcpy (raw + num_to_zero, buf, nbytes);
+
+      return 0;
+    }
+
+  nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
+  if (raw_nbytes < nbytes)
+    return -1;
+
+  num_to_zero = raw_nbytes - nbytes;
+  if (num_to_zero > 0)
+    memset (raw, 0, num_to_zero);
+
+  for (j = a->nlimbs - 1, i = 0; i < a->nlimbs; i++, j--)
+    {
+      buf_put_be64(raw + num_to_zero + i * BYTES_PER_MPI_LIMB, a->d[j]);
+    }
+
+  return 0;
+}
+
+int
+_gcry_s390x_ec_hw_mul_point (mpi_point_t result, gcry_mpi_t scalar,
+                            mpi_point_t point, mpi_ec_t ctx)
+{
+  byte param_block_buf[S390X_PCC_PARAM_BLOCK_SIZE];
+  byte *param_out_x = NULL;
+  byte *param_out_y = NULL;
+  byte *param_in_x = NULL;
+  byte *param_in_y = NULL;
+  byte *param_scalar = NULL;
+  unsigned int field_nbits;
+  unsigned int pcc_func;
+  gcry_mpi_t x, y;
+  gcry_mpi_t d = NULL;
+  int rc = -1;
+
+  if (ctx->name == NULL)
+    return -1;
+
+  if (!(_gcry_get_hw_features () & HWF_S390X_MSA_9))
+    return -1; /* ECC acceleration not supported by HW. */
+
+  if (ctx->model == MPI_EC_MONTGOMERY)
+    return s390_mul_point_montgomery (result, scalar, point, ctx,
+                                     param_block_buf);
+
+  if (ctx->model == MPI_EC_WEIERSTRASS && ctx->nbits == 256 &&
+      strcmp (ctx->name, "NIST P-256") == 0)
+    {
+      struct pcc_param_block_nistp256_s
+      {
+       byte out_x[256 / 8];
+       byte out_y[256 / 8];
+       byte in_x[256 / 8];
+       byte in_y[256 / 8];
+       byte scalar[256 / 8];
+       byte c_and_ribm[64];
+      } *params = (void *)param_block_buf;
+
+      memset (params->c_and_ribm, 0, sizeof(params->c_and_ribm));
+
+      pcc_func = PCC_FUNCTION_NIST_P256;
+      field_nbits = 256;
+      param_out_x = params->out_x;
+      param_out_y = params->out_y;
+      param_in_x = params->in_x;
+      param_in_y = params->in_y;
+      param_scalar = params->scalar;
+    }
+  else if (ctx->model == MPI_EC_WEIERSTRASS && ctx->nbits == 384 &&
+           strcmp (ctx->name, "NIST P-384") == 0)
+    {
+      struct pcc_param_block_nistp384_s
+      {
+       byte out_x[384 / 8];
+       byte out_y[384 / 8];
+       byte in_x[384 / 8];
+       byte in_y[384 / 8];
+       byte scalar[384 / 8];
+       byte c_and_ribm[64];
+      } *params = (void *)param_block_buf;
+
+      memset (params->c_and_ribm, 0, sizeof(params->c_and_ribm));
+
+      pcc_func = PCC_FUNCTION_NIST_P384;
+      field_nbits = 384;
+      param_out_x = params->out_x;
+      param_out_y = params->out_y;
+      param_in_x = params->in_x;
+      param_in_y = params->in_y;
+      param_scalar = params->scalar;
+    }
+  else if (ctx->model == MPI_EC_WEIERSTRASS && ctx->nbits == 521 &&
+           strcmp (ctx->name, "NIST P-521") == 0)
+    {
+      struct pcc_param_block_nistp521_s
+      {
+       byte out_x[640 / 8]; /* note: first 14 bytes not modified by pcc */
+       byte out_y[640 / 8]; /* note: first 14 bytes not modified by pcc */
+       byte in_x[640 / 8];
+       byte in_y[640 / 8];
+       byte scalar[640 / 8];
+       byte c_and_ribm[64];
+      } *params = (void *)param_block_buf;
+
+      memset (params->out_x, 0, 14);
+      memset (params->out_y, 0, 14);
+      memset (params->c_and_ribm, 0, sizeof(params->c_and_ribm));
+
+      pcc_func = PCC_FUNCTION_NIST_P521;
+      field_nbits = 640;
+      param_out_x = params->out_x;
+      param_out_y = params->out_y;
+      param_in_x = params->in_x;
+      param_in_y = params->in_y;
+      param_scalar = params->scalar;
+    }
+  else if (ctx->model == MPI_EC_EDWARDS && ctx->nbits == 255 &&
+           strcmp (ctx->name, "Ed25519") == 0)
+    {
+      struct pcc_param_block_ed25519_s
+      {
+       byte out_x[256 / 8];
+       byte out_y[256 / 8];
+       byte in_x[256 / 8];
+       byte in_y[256 / 8];
+       byte scalar[256 / 8];
+       byte c_and_ribm[64];
+      } *params = (void *)param_block_buf;
+
+      memset (params->c_and_ribm, 0, sizeof(params->c_and_ribm));
+
+      pcc_func = PCC_FUNCTION_ED25519;
+      field_nbits = 256;
+      param_out_x = params->out_x;
+      param_out_y = params->out_y;
+      param_in_x = params->in_x;
+      param_in_y = params->in_y;
+      param_scalar = params->scalar;
+    }
+  else if (ctx->model == MPI_EC_EDWARDS && ctx->nbits == 448 &&
+           strcmp (ctx->name, "Ed448") == 0)
+    {
+      struct pcc_param_block_ed448_s
+      {
+       byte out_x[512 / 8]; /* note: first 8 bytes not modified by pcc */
+       byte out_y[512 / 8]; /* note: first 8 bytes not modified by pcc */
+       byte in_x[512 / 8];
+       byte in_y[512 / 8];
+       byte scalar[512 / 8];
+       byte c_and_ribm[64];
+      } *params = (void *)param_block_buf;
+
+      memset (params->out_x, 0, 8);
+      memset (params->out_y, 0, 8);
+      memset (params->c_and_ribm, 0, sizeof(params->c_and_ribm));
+
+      pcc_func = PCC_FUNCTION_ED448;
+      field_nbits = 512;
+      param_out_x = params->out_x;
+      param_out_y = params->out_y;
+      param_in_x = params->in_x;
+      param_in_y = params->in_y;
+      param_scalar = params->scalar;
+    }
+
+  if (param_scalar == NULL)
+    return -1; /* No curve match. */
+
+  if (!(pcc_query () & km_function_to_mask (pcc_func)))
+    return -1; /* HW does not support acceleration for this curve. */
+
+  x = mpi_new (0);
+  y = mpi_new (0);
+
+  if (_gcry_mpi_ec_get_affine (x, y, point, ctx) < 0)
+    {
+      /* Point at infinity. */
+      goto out;
+    }
+
+  if (mpi_has_sign (scalar) || mpi_cmp (scalar, ctx->n) >= 0)
+    {
+      d = mpi_is_secure (scalar) ? mpi_snew (ctx->nbits) : mpi_new (ctx->nbits);
+      _gcry_mpi_mod (d, scalar, ctx->n);
+    }
+  else
+    {
+      d = scalar;
+    }
+
+  if (mpi_copy_to_raw (param_in_x, field_nbits / 8, x) < 0)
+    goto out;
+
+  if (mpi_copy_to_raw (param_in_y, field_nbits / 8, y) < 0)
+    goto out;
+
+  if (mpi_copy_to_raw (param_scalar, field_nbits / 8, d) < 0)
+    goto out;
+
+  if (pcc_scalar_multiply (pcc_func, param_block_buf) != 0)
+    goto out;
+
+  _gcry_mpi_set_buffer (result->x, param_out_x, field_nbits / 8, 0);
+  _gcry_mpi_set_buffer (result->y, param_out_y, field_nbits / 8, 0);
+  mpi_set_ui (result->z, 1);
+  mpi_normalize (result->x);
+  mpi_normalize (result->y);
+  if (ctx->model == MPI_EC_EDWARDS)
+    mpi_point_resize (result, ctx);
+
+  rc = 0;
+
+out:
+  if (d != scalar)
+    mpi_release (d);
+  mpi_release (y);
+  mpi_release (x);
+  wipememory (param_block_buf, S390X_PCC_PARAM_BLOCK_SIZE);
+
+  return rc;
+}
+
+
+static int
+s390_mul_point_montgomery (mpi_point_t result, gcry_mpi_t scalar,
+                          mpi_point_t point, mpi_ec_t ctx,
+                          byte *param_block_buf)
+{
+  byte *param_out_x = NULL;
+  byte *param_in_x = NULL;
+  byte *param_scalar = NULL;
+  unsigned int field_nbits;
+  unsigned int pcc_func;
+  gcry_mpi_t x;
+  gcry_mpi_t d = NULL;
+  int rc = -1;
+
+  if (ctx->nbits == 255 && strcmp (ctx->name, "Curve25519") == 0)
+    {
+      struct pcc_param_block_x25519_s
+      {
+       byte out_x[256 / 8];
+       byte in_x[256 / 8];
+       byte scalar[256 / 8];
+       byte c_and_ribm[64];
+      } *params = (void *)param_block_buf;
+
+      memset (params->c_and_ribm, 0, sizeof(params->c_and_ribm));
+
+      pcc_func = PCC_FUNCTION_X25519;
+      field_nbits = 256;
+      param_out_x = params->out_x;
+      param_in_x = params->in_x;
+      param_scalar = params->scalar;
+    }
+  else if (ctx->nbits == 448 && strcmp (ctx->name, "X448") == 0)
+    {
+      struct pcc_param_block_x448_s
+      {
+       byte out_x[512 / 8]; /* note: first 8 bytes not modified by pcc */
+       byte in_x[512 / 8];
+       byte scalar[512 / 8];
+       byte c_and_ribm[64];
+      } *params = (void *)param_block_buf;
+
+      memset (params->out_x, 0, 8);
+      memset (params->c_and_ribm, 0, sizeof(params->c_and_ribm));
+
+      pcc_func = PCC_FUNCTION_X448;
+      field_nbits = 512;
+      param_out_x = params->out_x;
+      param_in_x = params->in_x;
+      param_scalar = params->scalar;
+    }
+
+  if (param_scalar == NULL)
+    return -1; /* No curve match. */
+
+  if (!(pcc_query () & km_function_to_mask (pcc_func)))
+    return -1; /* HW does not support acceleration for this curve. */
+
+  x = mpi_new (0);
+
+  if (mpi_is_opaque (scalar))
+    {
+      const unsigned int pbits = ctx->nbits;
+      unsigned int n;
+      unsigned char *raw;
+
+      raw = _gcry_mpi_get_opaque_copy (scalar, &n);
+      if ((n + 7) / 8 != (pbits + 7) / 8)
+        log_fatal ("scalar size (%d) != prime size (%d)\n",
+                   (n + 7) / 8, (pbits + 7) / 8);
+
+      reverse_buffer (raw, (n + 7 ) / 8);
+      if ((pbits % 8))
+        raw[0] &= (1 << (pbits % 8)) - 1;
+      raw[0] |= (1 << ((pbits + 7) % 8));
+      raw[(pbits + 7) / 8 - 1] &= (256 - ctx->h);
+      d = mpi_is_secure (scalar) ? mpi_snew (pbits) : mpi_new (pbits);
+      _gcry_mpi_set_buffer (d, raw, (n + 7) / 8, 0);
+      xfree (raw);
+    }
+  else
+    {
+      d = scalar;
+    }
+
+  if (_gcry_mpi_ec_get_affine (x, NULL, point, ctx) < 0)
+    {
+      /* Point at infinity. */
+      goto out;
+    }
+
+  if (mpi_copy_to_raw (param_in_x, field_nbits / 8, x) < 0)
+    goto out;
+
+  if (mpi_copy_to_raw (param_scalar, field_nbits / 8, d) < 0)
+    goto out;
+
+  if (pcc_scalar_multiply (pcc_func, param_block_buf) != 0)
+    goto out;
+
+  _gcry_mpi_set_buffer (result->x, param_out_x, field_nbits / 8, 0);
+  mpi_set_ui (result->z, 1);
+  mpi_point_resize (result, ctx);
+
+  rc = 0;
+
+out:
+  if (d != scalar)
+    mpi_release (d);
+  mpi_release (x);
+  wipememory (param_block_buf, S390X_PCC_PARAM_BLOCK_SIZE);
+
+  return rc;
+}
+
+#endif /* HAVE_GCC_INLINE_ASM_S390X */
diff --git a/mpi/ec-inline.h b/mpi/ec-inline.h
new file mode 100644 (file)
index 0000000..a07826e
--- /dev/null
@@ -0,0 +1,1065 @@
+/* ec-inline.h - EC inline addition/substraction helpers
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GCRY_EC_INLINE_H
+#define GCRY_EC_INLINE_H
+
+#include "mpi-internal.h"
+#include "longlong.h"
+#include "ec-context.h"
+#include "../cipher/bithelp.h"
+#include "../cipher/bufhelp.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 MASK_AND64(mask, val) ((mask) & (val))
+#define LIMB_OR64(val1, val2) ((val1) | (val2))
+#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)), \
+            "rme" ((mpi_limb_t)(C2)), \
+            "rme" ((mpi_limb_t)(C1)), \
+            "rme" ((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)), \
+            "rme" ((mpi_limb_t)(C2)), \
+            "rme" ((mpi_limb_t)(C1)), \
+            "rme" ((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)), \
+            "rme" ((mpi_limb_t)(C3)), \
+            "rme" ((mpi_limb_t)(C2)), \
+            "rme" ((mpi_limb_t)(C1)), \
+            "rme" ((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)), \
+            "rme" ((mpi_limb_t)(C3)), \
+            "rme" ((mpi_limb_t)(C2)), \
+            "rme" ((mpi_limb_t)(C1)), \
+            "rme" ((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)), \
+            "rme" ((mpi_limb_t)(C4)), \
+            "rme" ((mpi_limb_t)(C3)), \
+            "rme" ((mpi_limb_t)(C2)), \
+            "rme" ((mpi_limb_t)(C1)), \
+            "rme" ((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)), \
+            "rme" ((mpi_limb_t)(C4)), \
+            "rme" ((mpi_limb_t)(C3)), \
+            "rme" ((mpi_limb_t)(C2)), \
+            "rme" ((mpi_limb_t)(C1)), \
+            "rme" ((mpi_limb_t)(C0)) \
+          : "cc")
+
+#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")
+
+#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")
+
+#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")
+
+#endif /* __s390x__ */
+
+
+/* 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 mpi_limb64_t
+MASK_AND64(mpi_limb_t mask, mpi_limb64_t val)
+{
+  val.lo &= mask;
+  val.hi &= mask;
+  return val;
+}
+
+static inline mpi_limb64_t
+LIMB_OR64(mpi_limb64_t val1, mpi_limb64_t val2)
+{
+  val1.lo |= val2.lo;
+  val1.hi |= val2.hi;
+  return val1;
+}
+
+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 ADD6_LIMB32(a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0, \
+                   c5, c4, c3, c2, c1, c0) do { \
+    mpi_limb_t __carry6_32; \
+    __asm__ ("addl %10, %3\n" \
+            "adcl %9, %2\n" \
+            "adcl %8, %1\n" \
+            "sbbl %0, %0\n" \
+            : "=r" (__carry6_32), \
+              "=&r" (a2), \
+              "=&r" (a1), \
+              "=&r" (a0) \
+            : "0" ((mpi_limb_t)(0)), \
+              "1" ((mpi_limb_t)(b2)), \
+              "2" ((mpi_limb_t)(b1)), \
+              "3" ((mpi_limb_t)(b0)), \
+              "g" ((mpi_limb_t)(c2)), \
+              "g" ((mpi_limb_t)(c1)), \
+              "g" ((mpi_limb_t)(c0)) \
+            : "cc"); \
+    __asm__ ("addl $1, %3\n" \
+            "adcl %10, %2\n" \
+            "adcl %9, %1\n" \
+            "adcl %8, %0\n" \
+            : "=r" (a5), \
+              "=&r" (a4), \
+              "=&r" (a3), \
+              "=&r" (__carry6_32) \
+            : "0" ((mpi_limb_t)(b5)), \
+              "1" ((mpi_limb_t)(b4)), \
+              "2" ((mpi_limb_t)(b3)), \
+              "3" ((mpi_limb_t)(__carry6_32)), \
+              "g" ((mpi_limb_t)(c5)), \
+              "g" ((mpi_limb_t)(c4)), \
+              "g" ((mpi_limb_t)(c3)) \
+          : "cc"); \
+  } while (0)
+
+#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")
+
+#define SUB6_LIMB32(a5, a4, a3, a2, a1, a0, b5, b4, b3, b2, b1, b0, \
+                   c5, c4, c3, c2, c1, c0) do { \
+    mpi_limb_t __borrow6_32; \
+    __asm__ ("subl %10, %3\n" \
+            "sbbl %9, %2\n" \
+            "sbbl %8, %1\n" \
+            "sbbl %0, %0\n" \
+            : "=r" (__borrow6_32), \
+              "=&r" (a2), \
+              "=&r" (a1), \
+              "=&r" (a0) \
+            : "0" ((mpi_limb_t)(0)), \
+              "1" ((mpi_limb_t)(b2)), \
+              "2" ((mpi_limb_t)(b1)), \
+              "3" ((mpi_limb_t)(b0)), \
+              "g" ((mpi_limb_t)(c2)), \
+              "g" ((mpi_limb_t)(c1)), \
+              "g" ((mpi_limb_t)(c0)) \
+            : "cc"); \
+    __asm__ ("addl $1, %3\n" \
+            "sbbl %10, %2\n" \
+            "sbbl %9, %1\n" \
+            "sbbl %8, %0\n" \
+            : "=r" (a5), \
+              "=&r" (a4), \
+              "=&r" (a3), \
+              "=&r" (__borrow6_32) \
+            : "0" ((mpi_limb_t)(b5)), \
+              "1" ((mpi_limb_t)(b4)), \
+              "2" ((mpi_limb_t)(b3)), \
+              "3" ((mpi_limb_t)(__borrow6_32)), \
+              "g" ((mpi_limb_t)(c5)), \
+              "g" ((mpi_limb_t)(c4)), \
+              "g" ((mpi_limb_t)(c3)) \
+          : "cc"); \
+  } while (0)
+
+#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)), \
+            "Ir" ((mpi_limb_t)(C3)), \
+            "Ir" ((mpi_limb_t)(C2)), \
+            "Ir" ((mpi_limb_t)(C1)), \
+            "Ir" ((mpi_limb_t)(C0)) \
+          : "cc")
+
+#define ADD6_LIMB32(A5, A4, A3, A2, A1, A0, B5, B4, B3, B2, B1, B0, \
+                   C5, C4, C3, C2, C1, C0) do { \
+    mpi_limb_t __carry6_32; \
+    __asm__ ("adds %3, %7, %10\n" \
+            "adcs %2, %6, %9\n" \
+            "adcs %1, %5, %8\n" \
+            "adc  %0, %4, %4\n" \
+            : "=r" (__carry6_32), \
+              "=&r" (A2), \
+              "=&r" (A1), \
+              "=&r" (A0) \
+            : "r" ((mpi_limb_t)(0)), \
+              "r" ((mpi_limb_t)(B2)), \
+              "r" ((mpi_limb_t)(B1)), \
+              "r" ((mpi_limb_t)(B0)), \
+              "Ir" ((mpi_limb_t)(C2)), \
+              "Ir" ((mpi_limb_t)(C1)), \
+              "Ir" ((mpi_limb_t)(C0)) \
+            : "cc"); \
+    ADD4_LIMB32(A5, A4, A3, __carry6_32, B5, B4, B3, __carry6_32, \
+               C5, C4, C3, 0xffffffffU); \
+  } while (0)
+
+#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)), \
+            "Ir" ((mpi_limb_t)(C3)), \
+            "Ir" ((mpi_limb_t)(C2)), \
+            "Ir" ((mpi_limb_t)(C1)), \
+            "Ir" ((mpi_limb_t)(C0)) \
+          : "cc")
+
+
+#define SUB6_LIMB32(A5, A4, A3, A2, A1, A0, B5, B4, B3, B2, B1, B0, \
+                   C5, C4, C3, C2, C1, C0) do { \
+    mpi_limb_t __borrow6_32; \
+    __asm__ ("subs %3, %7, %10\n" \
+            "sbcs %2, %6, %9\n" \
+            "sbcs %1, %5, %8\n" \
+            "sbc  %0, %4, %4\n" \
+            : "=r" (__borrow6_32), \
+              "=&r" (A2), \
+              "=&r" (A1), \
+              "=&r" (A0) \
+            : "r" ((mpi_limb_t)(0)), \
+              "r" ((mpi_limb_t)(B2)), \
+              "r" ((mpi_limb_t)(B1)), \
+              "r" ((mpi_limb_t)(B0)), \
+              "Ir" ((mpi_limb_t)(C2)), \
+              "Ir" ((mpi_limb_t)(C1)), \
+              "Ir" ((mpi_limb_t)(C0)) \
+            : "cc"); \
+    SUB4_LIMB32(A5, A4, A3, __borrow6_32, B5, B4, B3, 0, \
+               C5, C4, C3, -__borrow6_32); \
+  } while (0)
+
+#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(ADD6_LIMB32)
+/* A[0..2] = B[0..2] + C[0..2] */
+#define ADD3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) \
+       ADD6_LIMB32(A2.hi, A2.lo, A1.hi, A1.lo, A0.hi, A0.lo, \
+                   B2.hi, B2.lo, B1.hi, B1.lo, B0.hi, B0.lo, \
+                   C2.hi, C2.lo, C1.hi, C1.lo, C0.hi, C0.lo)
+#endif
+
+#if defined(ADD6_LIMB32)
+/* 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_limb_t __carry4; \
+    ADD6_LIMB32(__carry4, A2.lo, A1.hi, A1.lo, A0.hi, A0.lo, \
+               0, B2.lo, B1.hi, B1.lo, B0.hi, B0.lo, \
+               0, C2.lo, C1.hi, C1.lo, C0.hi, C0.lo); \
+    ADD4_LIMB32(A3.hi, A3.lo, A2.hi, __carry4, \
+               B3.hi, B3.lo, B2.hi, __carry4, \
+               C3.hi, C3.lo, C2.hi, 0xffffffffU); \
+  } 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
+
+#if defined(SUB6_LIMB32)
+/* A[0..2] = B[0..2] - C[0..2] */
+#define SUB3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) \
+       SUB6_LIMB32(A2.hi, A2.lo, A1.hi, A1.lo, A0.hi, A0.lo, \
+                   B2.hi, B2.lo, B1.hi, B1.lo, B0.hi, B0.lo, \
+                   C2.hi, C2.lo, C1.hi, C1.lo, C0.hi, C0.lo)
+#endif
+
+#if defined(SUB6_LIMB32)
+/* 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_limb_t __borrow4; \
+    SUB6_LIMB32(__borrow4, A2.lo, A1.hi, A1.lo, A0.hi, A0.lo, \
+               0, B2.lo, B1.hi, B1.lo, B0.hi, B0.lo, \
+               0, C2.lo, C1.hi, C1.lo, C0.hi, C0.lo); \
+    SUB4_LIMB32(A3.hi, A3.lo, A2.hi, __borrow4, \
+               B3.hi, B3.lo, B2.hi, 0, \
+               C3.hi, C3.lo, C2.hi, -__borrow4); \
+  } 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 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; \
+    ADD4_LIMB64(__carry7, A2, A1, A0, zero, B2, B1, B0, \
+               zero, C2, C1, C0); \
+    ADD5_LIMB64(A6, A5, A4, A3, __carry7, B6, B5, B4, B3, \
+               __carry7, C6, C5, C4, C3, LIMB64_HILO(-1, -1)); \
+  } 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 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; \
+    SUB4_LIMB64(__borrow7, A2, A1, A0, zero, B2, B1, B0, \
+               zero, C2, C1, C0); \
+    SUB5_LIMB64(A6, A5, A4, A3, __borrow7, B6, B5, B4, B3, zero, \
+               C6, C5, C4, C3, LIMB_TO64(-LIMB_FROM64(__borrow7))); \
+  } while (0)
+#endif
+
+
+#if defined(WORDS_BIGENDIAN) || (BITS_PER_MPI_LIMB64 != BITS_PER_MPI_LIMB)
+#define LOAD64_UNALIGNED(x, pos) \
+  LIMB64_HILO(LOAD32(x, 2 * (pos) + 2), LOAD32(x, 2 * (pos) + 1))
+#else
+#define LOAD64_UNALIGNED(x, pos) \
+  buf_get_le64((const byte *)(&(x)[pos]) + 4)
+#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 */
index 759335a..3f948aa 100644 (file)
 #ifndef GCRY_EC_INTERNAL_H
 #define GCRY_EC_INTERNAL_H
 
+#include <config.h>
+
 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
+
+#ifdef HAVE_GCC_INLINE_ASM_S390X
+int _gcry_s390x_ec_hw_mul_point (mpi_point_t result, gcry_mpi_t scalar,
+                                mpi_point_t point, mpi_ec_t ctx);
+# define mpi_ec_hw_mul_point _gcry_s390x_ec_hw_mul_point
+#else
+# define mpi_ec_hw_mul_point(r,s,p,c) (-1)
+#endif
+
 #endif /*GCRY_EC_INTERNAL_H*/
diff --git a/mpi/ec-nist.c b/mpi/ec-nist.c
new file mode 100644 (file)
index 0000000..69b05a6
--- /dev/null
@@ -0,0 +1,823 @@
+/* ec-nist.c -  NIST optimized elliptic curve functions
+ * Copyright (C) 2021 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+
+#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_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;
+  mpi_limb_t s_is_negative;
+  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);
+
+  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,
+              p_mult[0][2], p_mult[0][1], p_mult[0][0]);
+
+  s_is_negative = LO32_LIMB64(s[3]) >> 31;
+
+  mask2 = vzero - s_is_negative;
+  mask1 = s_is_negative - 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_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;
+  mpi_limb_t s_is_negative;
+  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;
+
+  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)),
+              LOAD64_UNALIGNED(wp, 11 / 2),
+              LOAD64_UNALIGNED(wp, 9 / 2),
+              LOAD64_UNALIGNED(wp, 7 / 2),
+              zero,
+              zero,
+              LIMB64_HILO(0, LOAD32(wp, 13)),
+              LOAD64_UNALIGNED(wp, 11 / 2));
+
+  /* "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],
+              p_mult[0 + 2][3], p_mult[0 + 2][2],
+              p_mult[0 + 2][1], p_mult[0 + 2][0]);
+
+  s_is_negative = (HI32_LIMB64(s[3]) >> 31);
+
+  mask2 = vzero - s_is_negative;
+  mask1 = s_is_negative - 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[12][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_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_limb64_t e[wsize + 1];
+  mpi_limb_t mask1;
+  mpi_limb_t mask2;
+  mpi_limb_t mask3;
+  mpi_limb_t s_is_negative;
+  mpi_limb_t d_is_negative;
+  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;
+
+  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)),
+              LOAD64_UNALIGNED(wp, 13 / 2),
+              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)),
+              LOAD64_UNALIGNED(wp, 9 / 2));
+
+  /* "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]);
+
+  /* "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),
+              LOAD64_UNALIGNED(wp, 9 / 2),
+              LIMB64_HILO(LOAD32(wp, 8), LOAD32(wp, 15)),
+              LOAD64_UNALIGNED(wp, 13 / 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]);
+
+  /* "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)),
+              LOAD64_UNALIGNED(wp, 11 / 2),
+              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)));
+
+  /* "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 - 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 -2*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]);
+
+  /* Add 1*P */
+  ADD5_LIMB64 (d[4], d[3], d[2], d[1], d[0],
+              s[4], s[3], s[2], s[1], s[0],
+              zero,
+              p_mult[0 + 4][3], p_mult[0 + 4][2],
+              p_mult[0 + 4][1], p_mult[0 + 4][0]);
+
+  /* Add 2*P */
+  ADD5_LIMB64 (e[4], e[3], e[2], e[1], e[0],
+              s[4], s[3], s[2], s[1], s[0],
+              zero,
+              p_mult[1 + 4][3], p_mult[1 + 4][2],
+              p_mult[1 + 4][1], p_mult[1 + 4][0]);
+
+  s_is_negative = LO32_LIMB64(s[4]) >> 31;
+  d_is_negative = LO32_LIMB64(d[4]) >> 31;
+  mask3 = vzero - d_is_negative;
+  mask2 = (vzero - s_is_negative) & ~mask3;
+  mask1 = (s_is_negative - vone) & ~mask3;
+
+  s[0] = LIMB_OR64(MASK_AND64(mask2, d[0]), MASK_AND64(mask1, s[0]));
+  s[1] = LIMB_OR64(MASK_AND64(mask2, d[1]), MASK_AND64(mask1, s[1]));
+  s[2] = LIMB_OR64(MASK_AND64(mask2, d[2]), MASK_AND64(mask1, s[2]));
+  s[3] = LIMB_OR64(MASK_AND64(mask2, d[3]), MASK_AND64(mask1, s[3]));
+  s[0] = LIMB_OR64(MASK_AND64(mask3, e[0]), s[0]);
+  s[1] = LIMB_OR64(MASK_AND64(mask3, e[1]), s[1]);
+  s[2] = LIMB_OR64(MASK_AND64(mask3, e[2]), s[2]);
+  s[3] = LIMB_OR64(MASK_AND64(mask3, e[3]), s[3]);
+
+  STORE64(wp, 0, s[0]);
+  STORE64(wp, 1, s[1]);
+  STORE64(wp, 2, s[2]);
+  STORE64(wp, 3, 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_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) && defined(WORDS_BIGENDIAN)
+  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;
+  mpi_limb_t s_is_negative;
+  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;
+
+  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
+# ifdef WORDS_BIGENDIAN
+#  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) LOAD64_UNALIGNED(wp, idx / 2)
+#endif
+#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,
+              p_mult[0 + 3][5], p_mult[0 + 3][4],
+              p_mult[0 + 3][3], p_mult[0 + 3][2],
+              p_mult[0 + 3][1], p_mult[0 + 3][0]);
+
+  s_is_negative = LO32_LIMB64(s[6]) >> 31;
+  mask2 = vzero - s_is_negative;
+  mask1 = s_is_negative - 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);
+
+#if (BITS_PER_MPI_LIMB64 == BITS_PER_MPI_LIMB) && defined(WORDS_BIGENDIAN)
+  wipememory(wp_shr32, sizeof(wp_shr32));
+#endif
+}
+
+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 */
index 89077cd..c24921e 100644 (file)
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -30,6 +30,7 @@
 #include "ec-context.h"
 #include "ec-internal.h"
 
+extern void reverse_buffer (unsigned char *buffer, unsigned int length);
 
 #define point_init(a)  _gcry_mpi_point_init ((a))
 #define point_free(a)  _gcry_mpi_point_free_parts ((a))
@@ -153,20 +154,21 @@ _gcry_mpi_point_copy (gcry_mpi_point_t point)
 }
 
 
-static void
-point_resize (mpi_point_t p, mpi_ec_t ctx)
+void
+_gcry_mpi_ec_point_resize (mpi_point_t p, mpi_ec_t ctx)
 {
-  /*
-   * For now, we allocate enough limbs for our EC computation of ec_*.
-   * Once we will improve ec_* to be constant size (and constant
-   * time), NLIMBS can be ctx->p->nlimbs.
-   */
-  size_t nlimbs = 2*ctx->p->nlimbs+1;
+  size_t nlimbs = ctx->p->nlimbs;
 
   mpi_resize (p->x, nlimbs);
-  if (ctx->model != MPI_EC_MONTGOMERY)
-    mpi_resize (p->y, nlimbs);
+  p->x->nlimbs = nlimbs;
   mpi_resize (p->z, nlimbs);
+  p->z->nlimbs = nlimbs;
+
+  if (ctx->model != MPI_EC_MONTGOMERY)
+    {
+      mpi_resize (p->y, nlimbs);
+      p->y->nlimbs = nlimbs;
+    }
 }
 
 
@@ -283,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
@@ -292,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.  */
@@ -307,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
@@ -351,7 +353,375 @@ ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx)
       log_mpidump ("  p", ctx->p);
     }
 }
+\f
+/* Routines for 2^255 - 19.  */
+
+#define LIMB_SIZE_25519 ((256+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB)
+
+static void
+ec_addm_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];
+  mpi_limb_t borrow;
+
+  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
+    log_bug ("addm_25519: different sizes\n");
+
+  up = u->d;
+  vp = v->d;
+  wp = w->d;
+
+  _gcry_mpih_add_n (wp, up, vp, 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));
+}
+
+static void
+ec_subm_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];
+  mpi_limb_t borrow;
+
+  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
+    log_bug ("subm_25519: different sizes\n");
+
+  up = u->d;
+  vp = v->d;
+  wp = w->d;
+
+  borrow = _gcry_mpih_sub_n (wp, up, vp, 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));
+}
+
+static void
+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 cy;
+  int msb;
+
+  (void)ctx;
+  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
+    log_bug ("mulm_25519: different sizes\n");
+
+  up = u->d;
+  vp = v->d;
+  wp = w->d;
+
+  _gcry_mpih_mul_n (n, up, vp, wsize);
+  memcpy (wp, n, wsize * BYTES_PER_MPI_LIMB);
+  wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB));
+
+  _gcry_mpih_rshift (n, n+LIMB_SIZE_25519-1, LIMB_SIZE_25519+1,
+                    (255 % BITS_PER_MPI_LIMB));
+
+  cy = _gcry_mpih_addmul_1 (wp, n, wsize, 19);
+
+  memset (n, 0, wsize * BYTES_PER_MPI_LIMB);
+  msb = (wp[LIMB_SIZE_25519-1] >> (255 % BITS_PER_MPI_LIMB));
+  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, n, wsize);
+
+  cy = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize);
+  mpih_set_cond (wp, n, wsize, (cy == 0UL));
+}
+
+static void
+ec_mul2_25519 (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx)
+{
+  ec_addm_25519 (w, u, u, ctx);
+}
+
+static void
+ec_pow2_25519 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
+{
+  ec_mulm_25519 (w, b, b, ctx);
+}
+\f
+/* Routines for 2^448 - 2^224 - 1.  */
+
+#define LIMB_SIZE_448 ((448+BITS_PER_MPI_LIMB-1)/BITS_PER_MPI_LIMB)
+#define LIMB_SIZE_HALF_448 ((LIMB_SIZE_448+1)/2)
 
+static void
+ec_addm_448 (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_448;
+  mpi_limb_t n[LIMB_SIZE_448];
+  mpi_limb_t cy;
+
+  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
+    log_bug ("addm_448: different sizes\n");
+
+  up = u->d;
+  vp = v->d;
+  wp = w->d;
+
+  cy = _gcry_mpih_add_n (wp, up, vp, wsize);
+  _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize);
+  mpih_set_cond (wp, n, wsize, (cy != 0UL));
+}
+
+static void
+ec_subm_448 (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_448;
+  mpi_limb_t n[LIMB_SIZE_448];
+  mpi_limb_t borrow;
+
+  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
+    log_bug ("subm_448: different sizes\n");
+
+  up = u->d;
+  vp = v->d;
+  wp = w->d;
+
+  borrow = _gcry_mpih_sub_n (wp, up, vp, wsize);
+  _gcry_mpih_add_n (n, wp, ctx->p->d, wsize);
+  mpih_set_cond (wp, n, wsize, (borrow != 0UL));
+}
+
+static void
+ec_mulm_448 (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_448;
+  mpi_limb_t n[LIMB_SIZE_448*2];
+  mpi_limb_t a2[LIMB_SIZE_HALF_448];
+  mpi_limb_t a3[LIMB_SIZE_HALF_448];
+  mpi_limb_t b0[LIMB_SIZE_HALF_448];
+  mpi_limb_t b1[LIMB_SIZE_HALF_448];
+  mpi_limb_t cy;
+
+  if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize)
+    log_bug ("mulm_448: different sizes\n");
+
+  up = u->d;
+  vp = v->d;
+  wp = w->d;
+
+  _gcry_mpih_mul_n (n, up, vp, wsize);
+
+  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;
+  _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 (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;
+
+  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);
+#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
+  cy = _gcry_mpih_rshift (b1, b1, LIMB_SIZE_HALF_448, 32);
+  wp[LIMB_SIZE_HALF_448-1] |= cy;
+#endif
+  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];
+#endif
+
+  memset (n, 0, wsize * BYTES_PER_MPI_LIMB);
+
+#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2)
+  n[LIMB_SIZE_HALF_448-1] = cy << 32;
+#else
+  n[LIMB_SIZE_HALF_448] = cy;
+#endif
+  n[0] = cy;
+  _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
+ec_mul2_448 (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx)
+{
+  ec_addm_448 (w, u, u, ctx);
+}
+
+static void
+ec_pow2_448 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
+{
+  ec_mulm_448 (w, b, b, ctx);
+}
+\f
+
+/* 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;
+
+  /* computation routines for the field.  */
+  void (* addm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx);
+  void (* subm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx);
+  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[] = {
+  {
+    "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
+    ec_addm_25519,
+    ec_subm_25519,
+    ec_mulm_25519,
+    ec_mul2_25519,
+    ec_pow2_25519,
+    NULL
+  },
+  {
+   "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+    ec_addm_448,
+    ec_subm_448,
+    ec_mulm_448,
+    ec_mul2_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
+  },
+  {
+    "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    ec_secp256k1_mod
+  },
+  { NULL, NULL, NULL, NULL, NULL, NULL },
+};
+
+static gcry_mpi_t field_table_mpis[DIM(field_table)];
+\f
 
 /* Force recomputation of all helper variables.  */
 void
@@ -396,17 +766,37 @@ ec_get_two_inv_p (mpi_ec_t ec)
 }
 
 
-static const char *curve25519_bad_points[] = {
+static const char *const curve25519_bad_points[] = {
+  "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
   "0x0000000000000000000000000000000000000000000000000000000000000000",
   "0x0000000000000000000000000000000000000000000000000000000000000001",
   "0x00b8495f16056286fdb1329ceb8d09da6ac49ff1fae35616aeb8413b7c7aebe0",
   "0x57119fd0dd4e22d8868e1c58c45c44045bef839c55b1d0b1248c50a3bc959c5f",
   "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec",
-  "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
   "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee",
   NULL
 };
 
+
+static const char *const curve448_bad_points[] = {
+  "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
+  "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+  "0x00000000000000000000000000000000000000000000000000000000"
+  "00000000000000000000000000000000000000000000000000000000",
+  "0x00000000000000000000000000000000000000000000000000000000"
+  "00000000000000000000000000000000000000000000000000000001",
+  "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
+  "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+  "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+  "00000000000000000000000000000000000000000000000000000000",
+  NULL
+};
+
+static const char *const *bad_points_table[] = {
+  curve25519_bad_points,
+  curve448_bad_points,
+};
+
 static gcry_mpi_t
 scanval (const char *string)
 {
@@ -445,10 +835,7 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
   ctx->model = model;
   ctx->dialect = dialect;
   ctx->flags = flags;
-  if (dialect == ECC_DIALECT_ED25519)
-    ctx->nbits = 256;
-  else
-    ctx->nbits = mpi_get_nbits (p);
+  ctx->nbits = mpi_get_nbits (p);
   ctx->p = mpi_copy (p);
   ctx->a = mpi_copy (a);
   ctx->b = mpi_copy (b);
@@ -459,8 +846,19 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
 
   if (model == MPI_EC_MONTGOMERY)
     {
-      for (i=0; i< DIM(ctx->t.scratch) && curve25519_bad_points[i]; i++)
-        ctx->t.scratch[i] = scanval (curve25519_bad_points[i]);
+      for (i=0; i< DIM(bad_points_table); i++)
+        {
+          gcry_mpi_t p_candidate = scanval (bad_points_table[i][0]);
+          int match_p = !mpi_cmp (ctx->p, p_candidate);
+          int j;
+
+          mpi_free (p_candidate);
+          if (!match_p)
+            continue;
+
+          for (j=0; i< DIM(ctx->t.scratch) && bad_points_table[i][j]; j++)
+            ctx->t.scratch[j] = scanval (bad_points_table[i][j]);
+        }
     }
   else
     {
@@ -469,6 +867,60 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
         ctx->t.scratch[i] = mpi_alloc_like (ctx->p);
     }
 
+  ctx->addm = ec_addm;
+  ctx->subm = ec_subm;
+  ctx->mulm = ec_mulm;
+  ctx->mul2 = ec_mul2;
+  ctx->pow2 = ec_pow2;
+  ctx->mod = ec_mod;
+
+  for (i=0; field_table[i].p; i++)
+    {
+      gcry_mpi_t f_p;
+      gpg_err_code_t rc;
+
+      if (field_table_mpis[i] == NULL)
+       {
+         rc = _gcry_mpi_scan (&f_p, GCRYMPI_FMT_HEX, field_table[i].p, 0,
+                              NULL);
+         if (rc)
+           log_fatal ("scanning ECC parameter failed: %s\n",
+                      gpg_strerror (rc));
+         field_table_mpis[i] = f_p; /* cache */
+       }
+      else
+       {
+         f_p = field_table_mpis[i];
+       }
+
+      if (!mpi_cmp (p, f_p))
+        {
+          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;
+
+         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;
+
+          break;
+        }
+    }
+
   /* Prepare for fast reduction.  */
   /* FIXME: need a test for NIST values.  However it does not gain us
      any real advantage, for 384 bits it is actually slower than using
@@ -503,7 +955,6 @@ ec_deinit (void *opaque)
   mpi_free (ctx->b);
   _gcry_mpi_point_release (ctx->G);
   mpi_free (ctx->n);
-  mpi_free (ctx->h);
 
   /* The key.  */
   _gcry_mpi_point_release (ctx->Q);
@@ -643,14 +1094,17 @@ _gcry_mpi_ec_set_point (const char *name, gcry_mpi_point_t newvalue,
 gpg_err_code_t
 _gcry_mpi_ec_decode_point (mpi_point_t result, gcry_mpi_t value, mpi_ec_t ec)
 {
-  gcry_err_code_t rc;
+  gpg_err_code_t rc;
 
-  if (ec && ec->dialect == ECC_DIALECT_ED25519)
+  if (ec
+      && (ec->dialect == ECC_DIALECT_ED25519
+          || (ec->model == MPI_EC_EDWARDS
+              && ec->dialect == ECC_DIALECT_SAFECURVE)))
     rc = _gcry_ecc_eddsa_decodepoint (value, ec, result, NULL, NULL);
   else if (ec && ec->model == MPI_EC_MONTGOMERY)
     rc = _gcry_ecc_mont_decodepoint (value, ec, result);
   else
-    rc = _gcry_ecc_os2ec (result, value);
+    rc = _gcry_ecc_sec_decodepoint (value, ec, result);
 
   return rc;
 }
@@ -673,6 +1127,15 @@ _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
       {
         gcry_mpi_t z1, z2, z3;
 
+       if (!mpi_cmp_ui (point->z, 1))
+         {
+           if (x)
+             mpi_set (x, point->x);
+           if (y)
+             mpi_set (y, point->y);
+           return 0;
+         }
+
         z1 = mpi_new (0);
         z2 = mpi_new (0);
         ec_invm (z1, point->z, ctx);  /* z1 = z^(-1) mod p  */
@@ -712,13 +1175,33 @@ _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
       {
         gcry_mpi_t z;
 
+       if (!mpi_cmp_ui (point->z, 1))
+         {
+           if (x)
+             mpi_set (x, point->x);
+           if (y)
+             mpi_set (y, point->y);
+           return 0;
+         }
+
         z = mpi_new (0);
         ec_invm (z, point->z, ctx);
 
+        mpi_resize (z, ctx->p->nlimbs);
+        z->nlimbs = ctx->p->nlimbs;
+
         if (x)
-          ec_mulm (x, point->x, z, ctx);
+          {
+            mpi_resize (x, ctx->p->nlimbs);
+            x->nlimbs = ctx->p->nlimbs;
+            ctx->mulm (x, point->x, z, ctx);
+          }
         if (y)
-          ec_mulm (y, point->y, z, ctx);
+          {
+            mpi_resize (y, ctx->p->nlimbs);
+            y->nlimbs = ctx->p->nlimbs;
+            ctx->mulm (y, point->y, z, ctx);
+          }
 
         _gcry_mpi_release (z);
       }
@@ -847,41 +1330,41 @@ dup_point_edwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
   /* Compute: (X_3 : Y_3 : Z_3) = 2( X_1 : Y_1 : Z_1 ) */
 
   /* B = (X_1 + Y_1)^2  */
-  ec_addm (B, X1, Y1, ctx);
-  ec_pow2 (B, B, ctx);
+  ctx->addm (B, X1, Y1, ctx);
+  ctx->pow2 (B, B, ctx);
 
   /* C = X_1^2 */
   /* D = Y_1^2 */
-  ec_pow2 (C, X1, ctx);
-  ec_pow2 (D, Y1, ctx);
+  ctx->pow2 (C, X1, ctx);
+  ctx->pow2 (D, Y1, ctx);
 
   /* E = aC */
   if (ctx->dialect == ECC_DIALECT_ED25519)
-    mpi_sub (E, ctx->p, C);
+    ctx->subm (E, ctx->p, C, ctx);
   else
-    ec_mulm (E, ctx->a, C, ctx);
+    ctx->mulm (E, ctx->a, C, ctx);
 
   /* F = E + D */
-  ec_addm (F, E, D, ctx);
+  ctx->addm (F, E, D, ctx);
 
   /* H = Z_1^2 */
-  ec_pow2 (H, Z1, ctx);
+  ctx->pow2 (H, Z1, ctx);
 
   /* J = F - 2H */
-  ec_mul2 (J, H, ctx);
-  ec_subm (J, F, J, ctx);
+  ctx->mul2 (J, H, ctx);
+  ctx->subm (J, F, J, ctx);
 
   /* X_3 = (B - C - D) · J */
-  ec_subm (X3, B, C, ctx);
-  ec_subm (X3, X3, D, ctx);
-  ec_mulm (X3, X3, J, ctx);
+  ctx->subm (X3, B, C, ctx);
+  ctx->subm (X3, X3, D, ctx);
+  ctx->mulm (X3, X3, J, ctx);
 
   /* Y_3 = F · (E - D) */
-  ec_subm (Y3, E, D, ctx);
-  ec_mulm (Y3, Y3, F, ctx);
+  ctx->subm (Y3, E, D, ctx);
+  ctx->mulm (Y3, Y3, F, ctx);
 
   /* Z_3 = F · J */
-  ec_mulm (Z3, F, J, ctx);
+  ctx->mulm (Z3, F, J, ctx);
 
 #undef X1
 #undef Y1
@@ -1099,54 +1582,56 @@ add_points_edwards (mpi_point_t result,
 #define G (ctx->t.scratch[6])
 #define tmp (ctx->t.scratch[7])
 
+  mpi_point_resize (result, ctx);
+
   /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_3)  */
 
   /* A = Z1 · Z2 */
-  ec_mulm (A, Z1, Z2, ctx);
+  ctx->mulm (A, Z1, Z2, ctx);
 
   /* B = A^2 */
-  ec_pow2 (B, A, ctx);
+  ctx->pow2 (B, A, ctx);
 
   /* C = X1 · X2 */
-  ec_mulm (C, X1, X2, ctx);
+  ctx->mulm (C, X1, X2, ctx);
 
   /* D = Y1 · Y2 */
-  ec_mulm (D, Y1, Y2, ctx);
+  ctx->mulm (D, Y1, Y2, ctx);
 
   /* E = d · C · D */
-  ec_mulm (E, ctx->b, C, ctx);
-  ec_mulm (E, E, D, ctx);
+  ctx->mulm (E, ctx->b, C, ctx);
+  ctx->mulm (E, E, D, ctx);
 
   /* F = B - E */
-  ec_subm (F, B, E, ctx);
+  ctx->subm (F, B, E, ctx);
 
   /* G = B + E */
-  ec_addm (G, B, E, ctx);
+  ctx->addm (G, B, E, ctx);
 
   /* X_3 = A · F · ((X_1 + Y_1) · (X_2 + Y_2) - C - D) */
-  ec_addm (tmp, X1, Y1, ctx);
-  ec_addm (X3, X2, Y2, ctx);
-  ec_mulm (X3, X3, tmp, ctx);
-  ec_subm (X3, X3, C, ctx);
-  ec_subm (X3, X3, D, ctx);
-  ec_mulm (X3, X3, F, ctx);
-  ec_mulm (X3, X3, A, ctx);
+  ctx->addm (tmp, X1, Y1, ctx);
+  ctx->addm (X3, X2, Y2, ctx);
+  ctx->mulm (X3, X3, tmp, ctx);
+  ctx->subm (X3, X3, C, ctx);
+  ctx->subm (X3, X3, D, ctx);
+  ctx->mulm (X3, X3, F, ctx);
+  ctx->mulm (X3, X3, A, ctx);
 
   /* Y_3 = A · G · (D - aC) */
   if (ctx->dialect == ECC_DIALECT_ED25519)
     {
-      ec_addm (Y3, D, C, ctx);
+      ctx->addm (Y3, D, C, ctx);
     }
   else
     {
-      ec_mulm (Y3, ctx->a, C, ctx);
-      ec_subm (Y3, D, Y3, ctx);
+      ctx->mulm (Y3, ctx->a, C, ctx);
+      ctx->subm (Y3, D, Y3, ctx);
     }
-  ec_mulm (Y3, Y3, G, ctx);
-  ec_mulm (Y3, Y3, A, ctx);
+  ctx->mulm (Y3, Y3, G, ctx);
+  ctx->mulm (Y3, Y3, A, ctx);
 
   /* Z_3 = F · G */
-  ec_mulm (Z3, F, G, ctx);
+  ctx->mulm (Z3, F, G, ctx);
 
 
 #undef X1
@@ -1177,24 +1662,24 @@ montgomery_ladder (mpi_point_t prd, mpi_point_t sum,
                    mpi_point_t p1, mpi_point_t p2, gcry_mpi_t dif_x,
                    mpi_ec_t ctx)
 {
-  ec_addm (sum->x, p2->x, p2->z, ctx);
-  ec_subm (p2->z, p2->x, p2->z, ctx);
-  ec_addm (prd->x, p1->x, p1->z, ctx);
-  ec_subm (p1->z, p1->x, p1->z, ctx);
-  ec_mulm (p2->x, p1->z, sum->x, ctx);
-  ec_mulm (p2->z, prd->x, p2->z, ctx);
-  ec_pow2 (p1->x, prd->x, ctx);
-  ec_pow2 (p1->z, p1->z, ctx);
-  ec_addm (sum->x, p2->x, p2->z, ctx);
-  ec_subm (p2->z, p2->x, p2->z, ctx);
-  ec_mulm (prd->x, p1->x, p1->z, ctx);
-  ec_subm (p1->z, p1->x, p1->z, ctx);
-  ec_pow2 (sum->x, sum->x, ctx);
-  ec_pow2 (sum->z, p2->z, ctx);
-  ec_mulm (prd->z, p1->z, ctx->a, ctx); /* CTX->A: (a-2)/4 */
-  ec_mulm (sum->z, sum->z, dif_x, ctx);
-  ec_addm (prd->z, p1->x, prd->z, ctx);
-  ec_mulm (prd->z, prd->z, p1->z, ctx);
+  ctx->addm (sum->x, p2->x, p2->z, ctx);
+  ctx->subm (p2->z, p2->x, p2->z, ctx);
+  ctx->addm (prd->x, p1->x, p1->z, ctx);
+  ctx->subm (p1->z, p1->x, p1->z, ctx);
+  ctx->mulm (p2->x, p1->z, sum->x, ctx);
+  ctx->mulm (p2->z, prd->x, p2->z, ctx);
+  ctx->pow2 (p1->x, prd->x, ctx);
+  ctx->pow2 (p1->z, p1->z, ctx);
+  ctx->addm (sum->x, p2->x, p2->z, ctx);
+  ctx->subm (p2->z, p2->x, p2->z, ctx);
+  ctx->mulm (prd->x, p1->x, p1->z, ctx);
+  ctx->subm (p1->z, p1->x, p1->z, ctx);
+  ctx->pow2 (sum->x, sum->x, ctx);
+  ctx->pow2 (sum->z, p2->z, ctx);
+  ctx->mulm (prd->z, p1->z, ctx->a, ctx); /* CTX->A: (a-2)/4 */
+  ctx->mulm (sum->z, sum->z, dif_x, ctx);
+  ctx->addm (prd->z, p1->x, prd->z, ctx);
+  ctx->mulm (prd->z, prd->z, p1->z, ctx);
 }
 
 
@@ -1257,7 +1742,7 @@ sub_points_edwards (mpi_point_t result,
 {
   mpi_point_t p2i = _gcry_mpi_point_new (0);
   point_set (p2i, p2);
-  mpi_sub (p2i->x, ctx->p, p2i->x);
+  ctx->subm (p2i->x, ctx->p, p2i->x, ctx);
   add_points_edwards (result, p1, p2i, ctx);
   _gcry_mpi_point_release (p2i);
 }
@@ -1284,7 +1769,7 @@ _gcry_mpi_ec_sub_points (mpi_point_t result,
 }
 
 
-/* Scalar point multiplication - the main function for ECC.  If takes
+/* Scalar point multiplication - the main function for ECC.  It takes
    an integer SCALAR and a POINT as well as the usual context CTX.
    RESULT will be set to the resulting point. */
 void
@@ -1296,6 +1781,14 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
   unsigned int i, loops;
   mpi_point_struct p1, p2, p1inv;
 
+  /* First try HW accelerated scalar multiplications.  Error
+     is returned if acceleration is not supported or if HW
+     does not support acceleration of given input.  */
+  if (mpi_ec_hw_mul_point (result, scalar, point, ctx) >= 0)
+    {
+      return;
+    }
+
   if (ctx->model == MPI_EC_EDWARDS
       || (ctx->model == MPI_EC_WEIERSTRASS
           && mpi_is_secure (scalar)))
@@ -1309,7 +1802,11 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       unsigned int nbits;
       int j;
 
-      nbits = mpi_get_nbits (scalar);
+      if (mpi_cmp (scalar, ctx->p) >= 0)
+        nbits = mpi_get_nbits (scalar);
+      else
+        nbits = mpi_get_nbits (ctx->p);
+
       if (ctx->model == MPI_EC_WEIERSTRASS)
         {
           mpi_set_ui (result->x, 1);
@@ -1321,6 +1818,7 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
           mpi_set_ui (result->x, 0);
           mpi_set_ui (result->y, 1);
           mpi_set_ui (result->z, 1);
+          mpi_point_resize (point, ctx);
         }
 
       if (mpi_is_secure (scalar))
@@ -1330,8 +1828,8 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
           mpi_point_struct tmppnt;
 
           point_init (&tmppnt);
-          point_resize (result, ctx);
-          point_resize (&tmppnt, ctx);
+          mpi_point_resize (result, ctx);
+          mpi_point_resize (&tmppnt, ctx);
           for (j=nbits-1; j >= 0; j--)
             {
               _gcry_mpi_ec_dup_point (result, result, ctx);
@@ -1342,6 +1840,12 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
         }
       else
         {
+          if (ctx->model == MPI_EC_EDWARDS)
+            {
+              mpi_point_resize (result, ctx);
+              mpi_point_resize (point, ctx);
+            }
+
           for (j=nbits-1; j >= 0; j--)
             {
               _gcry_mpi_ec_dup_point (result, result, ctx);
@@ -1358,6 +1862,8 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       mpi_point_struct p1_, p2_;
       mpi_point_t q1, q2, prd, sum;
       unsigned long sw;
+      mpi_size_t rsize;
+      int scalar_copied = 0;
 
       /* Compute scalar point multiplication with Montgomery Ladder.
          Note that we don't use Y-coordinate in the points at all.
@@ -1373,10 +1879,39 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       p2.x  = mpi_copy (point->x);
       mpi_set_ui (p2.z, 1);
 
-      point_resize (&p1, ctx);
-      point_resize (&p2, ctx);
-      point_resize (&p1_, ctx);
-      point_resize (&p2_, ctx);
+      if (mpi_is_opaque (scalar))
+        {
+          const unsigned int pbits = ctx->nbits;
+          gcry_mpi_t a;
+          unsigned int n;
+          unsigned char *raw;
+
+          scalar_copied = 1;
+
+          raw = _gcry_mpi_get_opaque_copy (scalar, &n);
+          if ((n+7)/8 != (pbits+7)/8)
+            log_fatal ("scalar size (%d) != prime size (%d)\n",
+                       (n+7)/8, (pbits+7)/8);
+
+          reverse_buffer (raw, (n+7)/8);
+          if ((pbits % 8))
+            raw[0] &= (1 << (pbits % 8)) - 1;
+          raw[0] |= (1 << ((pbits + 7) % 8));
+          raw[(pbits+7)/8 - 1] &= (256 - ctx->h);
+          a = mpi_is_secure (scalar) ? mpi_snew (pbits): mpi_new (pbits);
+          _gcry_mpi_set_buffer (a, raw, (n+7)/8, 0);
+          xfree (raw);
+
+          scalar = a;
+        }
+
+      mpi_point_resize (&p1, ctx);
+      mpi_point_resize (&p2, ctx);
+      mpi_point_resize (&p1_, ctx);
+      mpi_point_resize (&p2_, ctx);
+
+      mpi_resize (point->x, ctx->p->nlimbs);
+      point->x->nlimbs = ctx->p->nlimbs;
 
       q1 = &p1;
       q2 = &p2;
@@ -1399,7 +1934,9 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       sw = (nbits & 1);
       point_swap_cond (&p1, &p1_, sw, ctx);
 
-      if (p1.z->nlimbs == 0)
+      rsize = p1.z->nlimbs;
+      MPN_NORMALIZE (p1.z->d, rsize);
+      if (rsize == 0)
         {
           mpi_set_ui (result->x, 1);
           mpi_set_ui (result->z, 0);
@@ -1417,6 +1954,8 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       point_free (&p2);
       point_free (&p1_);
       point_free (&p2_);
+      if (scalar_copied)
+        _gcry_mpi_release (scalar);
       return;
     }
 
@@ -1587,19 +2126,21 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
         if (_gcry_mpi_ec_get_affine (x, y, point, ctx))
           goto leave;
 
+        mpi_resize (w, ctx->p->nlimbs);
+        w->nlimbs = ctx->p->nlimbs;
+
         /* a · x^2 + y^2 - 1 - b · x^2 · y^2 == 0 */
-        ec_pow2 (x, x, ctx);
-        ec_pow2 (y, y, ctx);
+        ctx->pow2 (x, x, ctx);
+        ctx->pow2 (y, y, ctx);
         if (ctx->dialect == ECC_DIALECT_ED25519)
-          mpi_sub (w, ctx->p, x);
+          ctx->subm (w, ctx->p, x, ctx);
         else
-          ec_mulm (w, ctx->a, x, ctx);
-        ec_addm (w, w, y, ctx);
-        ec_subm (w, w, mpi_const (MPI_C_ONE), ctx);
-        ec_mulm (x, x, y, ctx);
-        ec_mulm (x, x, ctx->b, ctx);
-        ec_subm (w, w, x, ctx);
-        if (!mpi_cmp_ui (w, 0))
+          ctx->mulm (w, ctx->a, x, ctx);
+        ctx->addm (w, w, y, ctx);
+        ctx->mulm (x, x, y, ctx);
+        ctx->mulm (x, x, ctx->b, ctx);
+        ctx->subm (w, w, x, ctx);
+        if (!mpi_cmp_ui (w, 1))
           res = 1;
       }
       break;
index 652b232..95a7589 100644 (file)
        ALIGN (3)
        .globl C_SYMBOL_NAME(_gcry_mpih_add_n)
 C_SYMBOL_NAME(_gcry_mpih_add_n:)
+       CFI_STARTPROC()
        pushl %edi
+       CFI_PUSH(%edi)
        pushl %esi
+       CFI_PUSH(%esi)
 
        movl 12(%esp),%edi              /* res_ptr */
        movl 16(%esp),%esi              /* s1_ptr */
        movl 20(%esp),%edx              /* s2_ptr */
        movl 24(%esp),%ecx              /* size */
 
+#if defined __CET__ && (__CET__ & 1) != 0
+       pushl   %ebx
+       CFI_PUSH(%ebx)
+#endif
+
        movl    %ecx,%eax
        shrl    $3,%ecx                 /* compute count for unrolled loop */
        negl    %eax
@@ -63,41 +71,70 @@ C_SYMBOL_NAME(_gcry_mpih_add_n:)
        subl    %eax,%esi               /* ... by a constant when we ... */
        subl    %eax,%edx               /* ... enter the loop */
        shrl    $2,%eax                 /* restore previous value */
+#if defined __CET__ && (__CET__ & 1) != 0
+       leal    -4(,%eax,4),%ebx        /* Count for 4-byte endbr32 */
+#endif
 #ifdef PIC
 /* Calculate start address in loop for PIC.  Due to limitations in some
    assemblers, Loop-L0-3 cannot be put into the leal */
        call    L0
+       CFI_ADJUST_CFA_OFFSET(4)
 L0:    leal    (%eax,%eax,8),%eax
        addl    (%esp),%eax
        addl    $(Loop-L0-3),%eax
        addl    $4,%esp
+       CFI_ADJUST_CFA_OFFSET(-4)
 #else
 /* Calculate start address in loop for non-PIC.  */
        leal    (Loop - 3)(%eax,%eax,8),%eax
 #endif
+#if defined __CET__ && (__CET__ & 1) != 0
+       addl    %ebx,%eax               /* Adjust for endbr32 */
+#endif
        jmp     *%eax                   /* jump into loop */
        ALIGN (3)
 Loop:  movl    (%esi),%eax
        adcl    (%edx),%eax
        movl    %eax,(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    4(%esi),%eax
        adcl    4(%edx),%eax
        movl    %eax,4(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    8(%esi),%eax
        adcl    8(%edx),%eax
        movl    %eax,8(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    12(%esi),%eax
        adcl    12(%edx),%eax
        movl    %eax,12(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    16(%esi),%eax
        adcl    16(%edx),%eax
        movl    %eax,16(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    20(%esi),%eax
        adcl    20(%edx),%eax
        movl    %eax,20(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    24(%esi),%eax
        adcl    24(%edx),%eax
        movl    %eax,24(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    28(%esi),%eax
        adcl    28(%edx),%eax
        movl    %eax,28(%edi)
@@ -110,7 +147,15 @@ Loop:      movl    (%esi),%eax
        sbbl    %eax,%eax
        negl    %eax
 
+#if defined __CET__ && (__CET__ & 1) != 0
+       popl    %ebx
+       CFI_POP(%ebx)
+#endif
+
        popl %esi
+       CFI_POP(%esi)
        popl %edi
-       ret
+       CFI_POP(%edi)
+       ret_spec_stop
+       CFI_ENDPROC()
 
index bf8ed9d..3404cf5 100644 (file)
        ALIGN (3)
        .globl C_SYMBOL_NAME(_gcry_mpih_lshift)
 C_SYMBOL_NAME(_gcry_mpih_lshift:)
+       CFI_STARTPROC()
        pushl   %edi
+       CFI_PUSH(%edi)
        pushl   %esi
+       CFI_PUSH(%esi)
        pushl   %ebx
+       CFI_PUSH(%ebx)
 
        movl    16(%esp),%edi           /* res_ptr */
        movl    20(%esp),%esi           /* s_ptr */
@@ -82,13 +86,17 @@ L1: movl    (%esi,%edx,4),%eax
        popl    %ebx
        popl    %esi
        popl    %edi
-       ret
+       ret_spec_stop
 
 Lend:  shll    %cl,%ebx                /* compute least significant limb */
        movl    %ebx,(%edi)             /* store it */
 
        popl    %ebx
+       CFI_POP(%ebx)
        popl    %esi
+       CFI_POP(%esi)
        popl    %edi
-       ret
+       CFI_POP(%edi)
+       ret_spec_stop
+       CFI_ENDPROC()
 
index c9760ef..a672d05 100644 (file)
        GLOBL   C_SYMBOL_NAME(_gcry_mpih_mul_1)
 C_SYMBOL_NAME(_gcry_mpih_mul_1:)
 
+       CFI_STARTPROC()
        INSN1(push,l    ,R(edi))
+       CFI_PUSH(%edi)
        INSN1(push,l    ,R(esi))
+       CFI_PUSH(%esi)
        INSN1(push,l    ,R(ebx))
+       CFI_PUSH(%ebx)
        INSN1(push,l    ,R(ebp))
+       CFI_PUSH(%ebp)
 
        INSN2(mov,l     ,R(res_ptr),MEM_DISP(esp,20))
        INSN2(mov,l     ,R(s1_ptr),MEM_DISP(esp,24))
@@ -77,8 +82,13 @@ Loop:
        INSN2(mov,l     ,R(eax),R(ebx))
 
        INSN1(pop,l     ,R(ebp))
+       CFI_POP(%ebp)
        INSN1(pop,l     ,R(ebx))
+       CFI_POP(%ebx)
        INSN1(pop,l     ,R(esi))
+       CFI_POP(%esi)
        INSN1(pop,l     ,R(edi))
-       ret
+       CFI_POP(%edi)
+       ret_spec_stop
+       CFI_ENDPROC()
 
index 9794e11..e09c3f7 100644 (file)
        GLOBL   C_SYMBOL_NAME(_gcry_mpih_addmul_1)
 C_SYMBOL_NAME(_gcry_mpih_addmul_1:)
 
+       CFI_STARTPROC()
        INSN1(push,l    ,R(edi))
+       CFI_PUSH(%edi)
        INSN1(push,l    ,R(esi))
+       CFI_PUSH(%esi)
        INSN1(push,l    ,R(ebx))
+       CFI_PUSH(%ebx)
        INSN1(push,l    ,R(ebp))
+       CFI_PUSH(%ebp)
 
        INSN2(mov,l     ,R(res_ptr),MEM_DISP(esp,20))
        INSN2(mov,l     ,R(s1_ptr),MEM_DISP(esp,24))
@@ -79,8 +84,13 @@ Loop:
        INSN2(mov,l     ,R(eax),R(ebx))
 
        INSN1(pop,l     ,R(ebp))
+       CFI_POP(%ebp)
        INSN1(pop,l     ,R(ebx))
+       CFI_POP(%ebx)
        INSN1(pop,l     ,R(esi))
+       CFI_POP(%esi)
        INSN1(pop,l     ,R(edi))
-       ret
+       CFI_POP(%edi)
+       ret_spec_stop
+       CFI_ENDPROC()
 
index 6df2017..4112c69 100644 (file)
        GLOBL   C_SYMBOL_NAME(_gcry_mpih_submul_1)
 C_SYMBOL_NAME(_gcry_mpih_submul_1:)
 
+       CFI_STARTPROC()
        INSN1(push,l    ,R(edi))
+       CFI_PUSH(%edi)
        INSN1(push,l    ,R(esi))
+       CFI_PUSH(%esi)
        INSN1(push,l    ,R(ebx))
+       CFI_PUSH(%ebx)
        INSN1(push,l    ,R(ebp))
+       CFI_PUSH(%ebp)
 
        INSN2(mov,l     ,R(res_ptr),MEM_DISP(esp,20))
        INSN2(mov,l     ,R(s1_ptr),MEM_DISP(esp,24))
@@ -79,8 +84,13 @@ Loop:
        INSN2(mov,l     ,R(eax),R(ebx))
 
        INSN1(pop,l     ,R(ebp))
+       CFI_POP(%ebp)
        INSN1(pop,l     ,R(ebx))
+       CFI_POP(%ebx)
        INSN1(pop,l     ,R(esi))
+       CFI_POP(%esi)
        INSN1(pop,l     ,R(edi))
-       ret
+       CFI_POP(%edi)
+       ret_spec_stop
+       CFI_ENDPROC()
 
index 2920e55..5d34696 100644 (file)
        ALIGN (3)
        .globl C_SYMBOL_NAME(_gcry_mpih_rshift)
 C_SYMBOL_NAME(_gcry_mpih_rshift:)
+       CFI_STARTPROC()
        pushl   %edi
+       CFI_PUSH(%edi)
        pushl   %esi
+       CFI_PUSH(%esi)
        pushl   %ebx
+       CFI_PUSH(%ebx)
 
        movl    16(%esp),%edi           /* wp */
        movl    20(%esp),%esi           /* up */
@@ -67,7 +71,7 @@ C_SYMBOL_NAME(_gcry_mpih_rshift:)
        movl    %ebx,%eax
 
        ALIGN (3)
-Loop2:  movl    (%esi,%edx,4),%ebx      /* load next higher limb */
+Loop2: movl     (%esi,%edx,4),%ebx     /* load next higher limb */
        shrdl   %cl,%ebx,%eax           /* compute result limb */
        movl    %eax,(%edi,%edx,4)      /* store it */
        incl    %edx
@@ -85,13 +89,17 @@ L2: movl    (%esi,%edx,4),%eax
        popl    %ebx
        popl    %esi
        popl    %edi
-       ret
+       ret_spec_stop
 
 Lend2: shrl    %cl,%ebx                /* compute most significant limb */
        movl    %ebx,(%edi)             /* store it */
 
        popl    %ebx
+       CFI_POP(%ebx)
        popl    %esi
+       CFI_POP(%esi)
        popl    %edi
-       ret
+       CFI_POP(%edi)
+       ret_spec_stop
+       CFI_ENDPROC()
 
index f447f7a..49477ae 100644 (file)
        ALIGN (3)
        .globl C_SYMBOL_NAME(_gcry_mpih_sub_n)
 C_SYMBOL_NAME(_gcry_mpih_sub_n:)
+       CFI_STARTPROC()
        pushl %edi
+       CFI_PUSH(%edi)
        pushl %esi
+       CFI_PUSH(%esi)
 
        movl 12(%esp),%edi              /* res_ptr */
        movl 16(%esp),%esi              /* s1_ptr */
        movl 20(%esp),%edx              /* s2_ptr */
        movl 24(%esp),%ecx              /* size */
 
+#if defined __CET__ && (__CET__ & 1) != 0
+       pushl   %ebx
+       CFI_PUSH(%ebx)
+#endif
+
        movl    %ecx,%eax
        shrl    $3,%ecx                 /* compute count for unrolled loop */
        negl    %eax
@@ -64,41 +72,70 @@ C_SYMBOL_NAME(_gcry_mpih_sub_n:)
        subl    %eax,%esi               /* ... by a constant when we ... */
        subl    %eax,%edx               /* ... enter the loop */
        shrl    $2,%eax                 /* restore previous value */
+#if defined __CET__ && (__CET__ & 1) != 0
+       leal    -4(,%eax,4),%ebx        /* Count for 4-byte endbr32 */
+#endif
 #ifdef PIC
 /* Calculate start address in loop for PIC.  Due to limitations in some
    assemblers, Loop-L0-3 cannot be put into the leal */
        call    L0
+       CFI_ADJUST_CFA_OFFSET(4)
 L0:    leal    (%eax,%eax,8),%eax
        addl    (%esp),%eax
        addl    $(Loop-L0-3),%eax
        addl    $4,%esp
+       CFI_ADJUST_CFA_OFFSET(-4)
 #else
 /* Calculate start address in loop for non-PIC.  */
        leal    (Loop - 3)(%eax,%eax,8),%eax
 #endif
+#if defined __CET__ && (__CET__ & 1) != 0
+       addl    %ebx,%eax               /* Adjust for endbr32 */
+#endif
        jmp     *%eax                   /* jump into loop */
        ALIGN (3)
 Loop:  movl    (%esi),%eax
        sbbl    (%edx),%eax
        movl    %eax,(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    4(%esi),%eax
        sbbl    4(%edx),%eax
        movl    %eax,4(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    8(%esi),%eax
        sbbl    8(%edx),%eax
        movl    %eax,8(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    12(%esi),%eax
        sbbl    12(%edx),%eax
        movl    %eax,12(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    16(%esi),%eax
        sbbl    16(%edx),%eax
        movl    %eax,16(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    20(%esi),%eax
        sbbl    20(%edx),%eax
        movl    %eax,20(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    24(%esi),%eax
        sbbl    24(%edx),%eax
        movl    %eax,24(%edi)
+#ifdef _CET_ENDBR
+       _CET_ENDBR
+#endif
        movl    28(%esi),%eax
        sbbl    28(%edx),%eax
        movl    %eax,28(%edi)
@@ -111,7 +148,15 @@ Loop:      movl    (%esi),%eax
        sbbl    %eax,%eax
        negl    %eax
 
+#if defined __CET__ && (__CET__ & 1) != 0
+       popl    %ebx
+       CFI_POP(%ebx)
+#endif
+
        popl %esi
+       CFI_POP(%esi)
        popl %edi
-       ret
+       CFI_POP(%edi)
+       ret_spec_stop
+       CFI_ENDPROC()
 
index 39ede98..af4d9e8 100644 (file)
  *      to avoid revealing of sensitive data due to paging etc.
  */
 
+#include <config.h>
+
+#ifdef __i386__
+#ifdef HAVE_GCC_ASM_CFI_DIRECTIVES
+# define CFI_STARTPROC()            .cfi_startproc
+# define CFI_ENDPROC()              .cfi_endproc
+# define CFI_ADJUST_CFA_OFFSET(off) .cfi_adjust_cfa_offset off
+# define CFI_REL_OFFSET(reg,off)    .cfi_rel_offset reg, off
+# define CFI_RESTORE(reg)           .cfi_restore reg
+
+# define CFI_PUSH(reg) \
+       CFI_ADJUST_CFA_OFFSET(4); CFI_REL_OFFSET(reg, 0)
+# define CFI_POP(reg) \
+       CFI_ADJUST_CFA_OFFSET(-4); CFI_RESTORE(reg)
+#else
+# define CFI_STARTPROC()
+# define CFI_ENDPROC()
+# define CFI_ADJUST_CFA_OFFSET(off)
+# define CFI_REL_OFFSET(reg,off)
+# define CFI_RESTORE(reg)
+
+# define CFI_PUSH(reg)
+# define CFI_POP(reg)
+#endif
+#endif
+
 #undef ALIGN
 
 #if defined (BSD_SYNTAX) || defined (ELF_SYNTAX)
@@ -66,3 +92,7 @@
 #undef ALIGN
 #define ALIGN(log) .align log,0x90
 #endif
+
+/* 'ret' instruction replacement for straight-line speculation mitigation */
+#define ret_spec_stop \
+       ret; int3;
diff --git a/mpi/i586/README b/mpi/i586/README
deleted file mode 100644 (file)
index d73b082..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-This directory contains mpn functions optimized for Intel Pentium
-processors.
-
-RELEVANT OPTIMIZATION ISSUES
-
-1. Pentium doesn't allocate cache lines on writes, unlike most other modern
-processors.  Since the functions in the mpn class do array writes, we have to
-handle allocating the destination cache lines by reading a word from it in the
-loops, to achieve the best performance.
-
-2. Pairing of memory operations requires that the two issued operations refer
-to different cache banks.  The simplest way to insure this is to read/write
-two words from the same object.  If we make operations on different objects,
-they might or might not be to the same cache bank.
-
-STATUS
-
-1. mpn_lshift and mpn_rshift run at about 6 cycles/limb, but the Pentium
-documentation indicates that they should take only 43/8 = 5.375 cycles/limb,
-or 5 cycles/limb asymptotically.
-
-2. mpn_add_n and mpn_sub_n run at asymptotically 2 cycles/limb.  Due to loop
-overhead and other delays (cache refill?), they run at or near 2.5 cycles/limb.
-
-3. mpn_mul_1, mpn_addmul_1, mpn_submul_1 all run 1 cycle faster than they
-should...
diff --git a/mpi/i586/distfiles b/mpi/i586/distfiles
deleted file mode 100644 (file)
index 8f821fb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-mpih-add1.S
-mpih-mul1.S
-mpih-mul2.S
-mpih-mul3.S
-mpih-lshift.S
-mpih-rshift.S
-mpih-sub1.S
-README
-
diff --git a/mpi/i586/mpih-add1.S b/mpi/i586/mpih-add1.S
deleted file mode 100644 (file)
index 7436d59..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/* i80586 add_n -- Add two limb vectors of the same length > 0 and store
- *                sum in a third limb vector.
- *
- *      Copyright (C) 1992, 1994, 1995, 1996, 1998,
- *                    2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- *  mpi_limb_t
- *  _gcry_mpih_add_n( mpi_ptr_t res_ptr,       (sp + 4)
- *                mpi_ptr_t s1_ptr,    (sp + 8)
- *                mpi_ptr_t s2_ptr,    (sp + 12)
- *                mpi_size_t size)     (sp + 16)
- */
-
-.text
-       ALIGN (3)
-       .globl C_SYMBOL_NAME(_gcry_mpih_add_n)
-C_SYMBOL_NAME(_gcry_mpih_add_n:)
-       pushl   %edi
-       pushl   %esi
-       pushl   %ebx
-       pushl   %ebp
-
-       movl    20(%esp),%edi           /* res_ptr */
-       movl    24(%esp),%esi           /* s1_ptr */
-       movl    28(%esp),%ebp           /* s2_ptr */
-       movl    32(%esp),%ecx           /* size */
-
-       movl    (%ebp),%ebx
-
-       decl    %ecx
-       movl    %ecx,%edx
-       shrl    $3,%ecx
-       andl    $7,%edx
-       testl   %ecx,%ecx               /* zero carry flag */
-       jz      Lend
-       pushl   %edx
-
-       ALIGN (3)
-Loop:  movl    28(%edi),%eax           /* fetch destination cache line */
-       leal    32(%edi),%edi
-
-L1:    movl    (%esi),%eax
-       movl    4(%esi),%edx
-       adcl    %ebx,%eax
-       movl    4(%ebp),%ebx
-       adcl    %ebx,%edx
-       movl    8(%ebp),%ebx
-       movl    %eax,-32(%edi)
-       movl    %edx,-28(%edi)
-
-L2:    movl    8(%esi),%eax
-       movl    12(%esi),%edx
-       adcl    %ebx,%eax
-       movl    12(%ebp),%ebx
-       adcl    %ebx,%edx
-       movl    16(%ebp),%ebx
-       movl    %eax,-24(%edi)
-       movl    %edx,-20(%edi)
-
-L3:    movl    16(%esi),%eax
-       movl    20(%esi),%edx
-       adcl    %ebx,%eax
-       movl    20(%ebp),%ebx
-       adcl    %ebx,%edx
-       movl    24(%ebp),%ebx
-       movl    %eax,-16(%edi)
-       movl    %edx,-12(%edi)
-
-L4:    movl    24(%esi),%eax
-       movl    28(%esi),%edx
-       adcl    %ebx,%eax
-       movl    28(%ebp),%ebx
-       adcl    %ebx,%edx
-       movl    32(%ebp),%ebx
-       movl    %eax,-8(%edi)
-       movl    %edx,-4(%edi)
-
-       leal    32(%esi),%esi
-       leal    32(%ebp),%ebp
-       decl    %ecx
-       jnz     Loop
-
-       popl    %edx
-Lend:
-       decl    %edx                    /* test %edx w/o clobbering carry */
-       js      Lend2
-       incl    %edx
-Loop2:
-       leal    4(%edi),%edi
-       movl    (%esi),%eax
-       adcl    %ebx,%eax
-       movl    4(%ebp),%ebx
-       movl    %eax,-4(%edi)
-       leal    4(%esi),%esi
-       leal    4(%ebp),%ebp
-       decl    %edx
-       jnz     Loop2
-Lend2:
-       movl    (%esi),%eax
-       adcl    %ebx,%eax
-       movl    %eax,(%edi)
-
-       sbbl    %eax,%eax
-       negl    %eax
-
-       popl    %ebp
-       popl    %ebx
-       popl    %esi
-       popl    %edi
-       ret
-
-
diff --git a/mpi/i586/mpih-lshift.S b/mpi/i586/mpih-lshift.S
deleted file mode 100644 (file)
index 9d25fe9..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/* i80586   lshift
- *
- *      Copyright (C) 1992, 1994, 1998, 
- *                    2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_lshift( mpi_ptr_t wp,    (sp + 4)
- *                mpi_ptr_t up,        (sp + 8)
- *                mpi_size_t usize,    (sp + 12)
- *                unsigned cnt)        (sp + 16)
- */
-
-.text
-       ALIGN (3)
-       .globl C_SYMBOL_NAME(_gcry_mpih_lshift)
-C_SYMBOL_NAME(_gcry_mpih_lshift:)
-
-       pushl   %edi
-       pushl   %esi
-       pushl   %ebx
-       pushl   %ebp
-
-       movl    20(%esp),%edi           /* res_ptr */
-       movl    24(%esp),%esi           /* s_ptr */
-       movl    28(%esp),%ebp           /* size */
-       movl    32(%esp),%ecx           /* cnt */
-
-/* We can use faster code for shift-by-1 under certain conditions.  */
-       cmp     $1,%ecx
-       jne     Lnormal
-       leal    4(%esi),%eax
-       cmpl    %edi,%eax
-       jnc     Lspecial                /* jump if s_ptr + 1 >= res_ptr */
-       leal    (%esi,%ebp,4),%eax
-       cmpl    %eax,%edi
-       jnc     Lspecial                /* jump if res_ptr >= s_ptr + size */
-
-Lnormal:
-       leal    -4(%edi,%ebp,4),%edi
-       leal    -4(%esi,%ebp,4),%esi
-
-       movl    (%esi),%edx
-       subl    $4,%esi
-       xorl    %eax,%eax
-       shldl   %cl,%edx,%eax           /* compute carry limb */
-       pushl   %eax                    /* push carry limb onto stack */
-
-       decl    %ebp
-       pushl   %ebp
-       shrl    $3,%ebp
-       jz      Lend
-
-       movl    (%edi),%eax             /* fetch destination cache line */
-
-       ALIGN   (2)
-Loop:  movl    -28(%edi),%eax          /* fetch destination cache line */
-       movl    %edx,%ebx
-
-       movl    (%esi),%eax
-       movl    -4(%esi),%edx
-       shldl   %cl,%eax,%ebx
-       shldl   %cl,%edx,%eax
-       movl    %ebx,(%edi)
-       movl    %eax,-4(%edi)
-
-       movl    -8(%esi),%ebx
-       movl    -12(%esi),%eax
-       shldl   %cl,%ebx,%edx
-       shldl   %cl,%eax,%ebx
-       movl    %edx,-8(%edi)
-       movl    %ebx,-12(%edi)
-
-       movl    -16(%esi),%edx
-       movl    -20(%esi),%ebx
-       shldl   %cl,%edx,%eax
-       shldl   %cl,%ebx,%edx
-       movl    %eax,-16(%edi)
-       movl    %edx,-20(%edi)
-
-       movl    -24(%esi),%eax
-       movl    -28(%esi),%edx
-       shldl   %cl,%eax,%ebx
-       shldl   %cl,%edx,%eax
-       movl    %ebx,-24(%edi)
-       movl    %eax,-28(%edi)
-
-       subl    $32,%esi
-       subl    $32,%edi
-       decl    %ebp
-       jnz     Loop
-
-Lend:  popl    %ebp
-       andl    $7,%ebp
-       jz      Lend2
-Loop2: movl    (%esi),%eax
-       shldl   %cl,%eax,%edx
-       movl    %edx,(%edi)
-       movl    %eax,%edx
-       subl    $4,%esi
-       subl    $4,%edi
-       decl    %ebp
-       jnz     Loop2
-
-Lend2: shll    %cl,%edx                /* compute least significant limb */
-       movl    %edx,(%edi)             /* store it */
-
-       popl    %eax                    /* pop carry limb */
-
-       popl    %ebp
-       popl    %ebx
-       popl    %esi
-       popl    %edi
-       ret
-
-/* We loop from least significant end of the arrays, which is only
-   permissable if the source and destination don't overlap, since the
-   function is documented to work for overlapping source and destination.
-*/
-
-Lspecial:
-       movl    (%esi),%edx
-       addl    $4,%esi
-
-       decl    %ebp
-       pushl   %ebp
-       shrl    $3,%ebp
-
-       addl    %edx,%edx
-       incl    %ebp
-       decl    %ebp
-       jz      LLend
-
-       movl    (%edi),%eax             /* fetch destination cache line */
-
-       ALIGN   (2)
-LLoop: movl    28(%edi),%eax           /* fetch destination cache line */
-       movl    %edx,%ebx
-
-       movl    (%esi),%eax
-       movl    4(%esi),%edx
-       adcl    %eax,%eax
-       movl    %ebx,(%edi)
-       adcl    %edx,%edx
-       movl    %eax,4(%edi)
-
-       movl    8(%esi),%ebx
-       movl    12(%esi),%eax
-       adcl    %ebx,%ebx
-       movl    %edx,8(%edi)
-       adcl    %eax,%eax
-       movl    %ebx,12(%edi)
-
-       movl    16(%esi),%edx
-       movl    20(%esi),%ebx
-       adcl    %edx,%edx
-       movl    %eax,16(%edi)
-       adcl    %ebx,%ebx
-       movl    %edx,20(%edi)
-
-       movl    24(%esi),%eax
-       movl    28(%esi),%edx
-       adcl    %eax,%eax
-       movl    %ebx,24(%edi)
-       adcl    %edx,%edx
-       movl    %eax,28(%edi)
-
-       leal    32(%esi),%esi           /* use leal not to clobber carry */
-       leal    32(%edi),%edi
-       decl    %ebp
-       jnz     LLoop
-
-LLend: popl    %ebp
-       sbbl    %eax,%eax               /* save carry in %eax */
-       andl    $7,%ebp
-       jz      LLend2
-       addl    %eax,%eax               /* restore carry from eax */
-LLoop2: movl   %edx,%ebx
-       movl    (%esi),%edx
-       adcl    %edx,%edx
-       movl    %ebx,(%edi)
-
-       leal    4(%esi),%esi            /* use leal not to clobber carry */
-       leal    4(%edi),%edi
-       decl    %ebp
-       jnz     LLoop2
-
-       jmp     LL1
-LLend2: addl   %eax,%eax               /* restore carry from eax */
-LL1:   movl    %edx,(%edi)             /* store last limb */
-
-       sbbl    %eax,%eax
-       negl    %eax
-
-       popl    %ebp
-       popl    %ebx
-       popl    %esi
-       popl    %edi
-       ret
-
-
diff --git a/mpi/i586/mpih-mul1.S b/mpi/i586/mpih-mul1.S
deleted file mode 100644 (file)
index 3601d96..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/* i80586 mul_1 -- Multiply a limb vector with a limb and store
- *                      the result in a second limb vector.
- *
- *      Copyright (C) 1992, 1994, 1996, 1998,
- *                    2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_mul_1( mpi_ptr_t res_ptr,        (sp + 4)
- *               mpi_ptr_t s1_ptr,     (sp + 8)
- *               mpi_size_t s1_size,   (sp + 12)
- *               mpi_limb_t s2_limb)   (sp + 16)
- */
-
-#define res_ptr edi
-#define s1_ptr esi
-#define size   ecx
-#define s2_limb ebp
-
-       TEXT
-       ALIGN (3)
-       GLOBL   C_SYMBOL_NAME(_gcry_mpih_mul_1)
-C_SYMBOL_NAME(_gcry_mpih_mul_1:)
-
-       INSN1(push,l    ,R(edi))
-       INSN1(push,l    ,R(esi))
-       INSN1(push,l    ,R(ebx))
-       INSN1(push,l    ,R(ebp))
-
-       INSN2(mov,l     ,R(res_ptr),MEM_DISP(esp,20))
-       INSN2(mov,l     ,R(s1_ptr),MEM_DISP(esp,24))
-       INSN2(mov,l     ,R(size),MEM_DISP(esp,28))
-       INSN2(mov,l     ,R(s2_limb),MEM_DISP(esp,32))
-
-       INSN2(lea,l     ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
-       INSN2(lea,l     ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
-       INSN1(neg,l     ,R(size))
-       INSN2(xor,l     ,R(ebx),R(ebx))
-       ALIGN (3)
-
-Loop:  INSN2(adc,l     ,R(ebx),$0)
-       INSN2(mov,l     ,R(eax),MEM_INDEX(s1_ptr,size,4))
-
-       INSN1(mul,l     ,R(s2_limb))
-
-       INSN2(add,l     ,R(ebx),R(eax))
-
-       INSN2(mov,l     ,MEM_INDEX(res_ptr,size,4),R(ebx))
-       INSN1(inc,l     ,R(size))
-
-       INSN2(mov,l     ,R(ebx),R(edx))
-       INSN1(jnz,      ,Loop)
-
-       INSN2(adc,l     ,R(ebx),$0)
-       INSN2(mov,l     ,R(eax),R(ebx))
-       INSN1(pop,l     ,R(ebp))
-       INSN1(pop,l     ,R(ebx))
-       INSN1(pop,l     ,R(esi))
-       INSN1(pop,l     ,R(edi))
-       ret
-
diff --git a/mpi/i586/mpih-mul2.S b/mpi/i586/mpih-mul2.S
deleted file mode 100644 (file)
index f32d363..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/* i80586 addmul_1 -- Multiply a limb vector with a limb and add
- *                   the result to a second limb vector.
- *
- *      Copyright (C) 1992, 1994, 1998, 
- *                    2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr,      (sp + 4)
- *                  mpi_ptr_t s1_ptr,       (sp + 8)
- *                  mpi_size_t s1_size,     (sp + 12)
- *                  mpi_limb_t s2_limb)     (sp + 16)
- */
-
-#define res_ptr edi
-#define s1_ptr esi
-#define size   ecx
-#define s2_limb ebp
-
-       TEXT
-       ALIGN (3)
-       GLOBL   C_SYMBOL_NAME(_gcry_mpih_addmul_1)
-C_SYMBOL_NAME(_gcry_mpih_addmul_1:)
-
-       INSN1(push,l    ,R(edi))
-       INSN1(push,l    ,R(esi))
-       INSN1(push,l    ,R(ebx))
-       INSN1(push,l    ,R(ebp))
-
-       INSN2(mov,l     ,R(res_ptr),MEM_DISP(esp,20))
-       INSN2(mov,l     ,R(s1_ptr),MEM_DISP(esp,24))
-       INSN2(mov,l     ,R(size),MEM_DISP(esp,28))
-       INSN2(mov,l     ,R(s2_limb),MEM_DISP(esp,32))
-
-       INSN2(lea,l     ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
-       INSN2(lea,l     ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
-       INSN1(neg,l     ,R(size))
-       INSN2(xor,l     ,R(ebx),R(ebx))
-       ALIGN (3)
-
-Loop:  INSN2(adc,l     ,R(ebx),$0)
-       INSN2(mov,l     ,R(eax),MEM_INDEX(s1_ptr,size,4))
-
-       INSN1(mul,l     ,R(s2_limb))
-
-       INSN2(add,l     ,R(eax),R(ebx))
-       INSN2(mov,l     ,R(ebx),MEM_INDEX(res_ptr,size,4))
-
-       INSN2(adc,l     ,R(edx),$0)
-       INSN2(add,l     ,R(ebx),R(eax))
-
-       INSN2(mov,l     ,MEM_INDEX(res_ptr,size,4),R(ebx))
-       INSN1(inc,l     ,R(size))
-
-       INSN2(mov,l     ,R(ebx),R(edx))
-       INSN1(jnz,      ,Loop)
-
-       INSN2(adc,l     ,R(ebx),$0)
-       INSN2(mov,l     ,R(eax),R(ebx))
-       INSN1(pop,l     ,R(ebp))
-       INSN1(pop,l     ,R(ebx))
-       INSN1(pop,l     ,R(esi))
-       INSN1(pop,l     ,R(edi))
-       ret
-
diff --git a/mpi/i586/mpih-mul3.S b/mpi/i586/mpih-mul3.S
deleted file mode 100644 (file)
index fa27d4e..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/* i80586 submul_1 -- Multiply a limb vector with a limb and add
- *                   the result to a second limb vector.
- *
- *      Copyright (C) 1992, 1994, 1998,
- *                    2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_submul_1( mpi_ptr_t res_ptr,      (sp + 4)
- *                  mpi_ptr_t s1_ptr,       (sp + 8)
- *                  mpi_size_t s1_size,     (sp + 12)
- *                  mpi_limb_t s2_limb)     (sp + 16)
- */
-
-#define res_ptr edi
-#define s1_ptr esi
-#define size   ecx
-#define s2_limb ebp
-
-       TEXT
-       ALIGN (3)
-       GLOBL   C_SYMBOL_NAME(_gcry_mpih_submul_1)
-C_SYMBOL_NAME(_gcry_mpih_submul_1:)
-
-       INSN1(push,l    ,R(edi))
-       INSN1(push,l    ,R(esi))
-       INSN1(push,l    ,R(ebx))
-       INSN1(push,l    ,R(ebp))
-
-       INSN2(mov,l     ,R(res_ptr),MEM_DISP(esp,20))
-       INSN2(mov,l     ,R(s1_ptr),MEM_DISP(esp,24))
-       INSN2(mov,l     ,R(size),MEM_DISP(esp,28))
-       INSN2(mov,l     ,R(s2_limb),MEM_DISP(esp,32))
-
-       INSN2(lea,l     ,R(res_ptr),MEM_INDEX(res_ptr,size,4))
-       INSN2(lea,l     ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4))
-       INSN1(neg,l     ,R(size))
-       INSN2(xor,l     ,R(ebx),R(ebx))
-       ALIGN (3)
-
-Loop:  INSN2(adc,l     ,R(ebx),$0)
-       INSN2(mov,l     ,R(eax),MEM_INDEX(s1_ptr,size,4))
-
-       INSN1(mul,l     ,R(s2_limb))
-
-       INSN2(add,l     ,R(eax),R(ebx))
-       INSN2(mov,l     ,R(ebx),MEM_INDEX(res_ptr,size,4))
-
-       INSN2(adc,l     ,R(edx),$0)
-       INSN2(sub,l     ,R(ebx),R(eax))
-
-       INSN2(mov,l     ,MEM_INDEX(res_ptr,size,4),R(ebx))
-       INSN1(inc,l     ,R(size))
-
-       INSN2(mov,l     ,R(ebx),R(edx))
-       INSN1(jnz,      ,Loop)
-
-       INSN2(adc,l     ,R(ebx),$0)
-       INSN2(mov,l     ,R(eax),R(ebx))
-       INSN1(pop,l     ,R(ebp))
-       INSN1(pop,l     ,R(ebx))
-       INSN1(pop,l     ,R(esi))
-       INSN1(pop,l     ,R(edi))
-       ret
-
diff --git a/mpi/i586/mpih-rshift.S b/mpi/i586/mpih-rshift.S
deleted file mode 100644 (file)
index c661e3d..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/* i80586   rshift
- *
- *      Copyright (C) 1992, 1994, 1998,
- *                    2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_rshift( mpi_ptr_t wp,    (sp + 4)
- *                mpi_ptr_t up,        (sp + 8)
- *                mpi_size_t usize,    (sp + 12)
- *                unsigned cnt)        (sp + 16)
- */
-
-.text
-       ALIGN (3)
-       .globl C_SYMBOL_NAME(_gcry_mpih_rshift)
-C_SYMBOL_NAME(_gcry_mpih_rshift:)
-       pushl   %edi
-       pushl   %esi
-       pushl   %ebx
-       pushl   %ebp
-
-       movl    20(%esp),%edi           /* res_ptr */
-       movl    24(%esp),%esi           /* s_ptr */
-       movl    28(%esp),%ebp           /* size */
-       movl    32(%esp),%ecx           /* cnt */
-
-/* We can use faster code for shift-by-1 under certain conditions.  */
-       cmp     $1,%ecx
-       jne     Rnormal
-       leal    4(%edi),%eax
-       cmpl    %esi,%eax
-       jnc     Rspecial                /* jump if res_ptr + 1 >= s_ptr */
-       leal    (%edi,%ebp,4),%eax
-       cmpl    %eax,%esi
-       jnc     Rspecial                /* jump if s_ptr >= res_ptr + size */
-
-Rnormal:
-       movl    (%esi),%edx
-       addl    $4,%esi
-       xorl    %eax,%eax
-       shrdl   %cl,%edx,%eax           /* compute carry limb */
-       pushl   %eax                    /* push carry limb onto stack */
-
-       decl    %ebp
-       pushl   %ebp
-       shrl    $3,%ebp
-       jz      Rend
-
-       movl    (%edi),%eax             /* fetch destination cache line */
-
-       ALIGN   (2)
-Roop:  movl    28(%edi),%eax           /* fetch destination cache line */
-       movl    %edx,%ebx
-
-       movl    (%esi),%eax
-       movl    4(%esi),%edx
-       shrdl   %cl,%eax,%ebx
-       shrdl   %cl,%edx,%eax
-       movl    %ebx,(%edi)
-       movl    %eax,4(%edi)
-
-       movl    8(%esi),%ebx
-       movl    12(%esi),%eax
-       shrdl   %cl,%ebx,%edx
-       shrdl   %cl,%eax,%ebx
-       movl    %edx,8(%edi)
-       movl    %ebx,12(%edi)
-
-       movl    16(%esi),%edx
-       movl    20(%esi),%ebx
-       shrdl   %cl,%edx,%eax
-       shrdl   %cl,%ebx,%edx
-       movl    %eax,16(%edi)
-       movl    %edx,20(%edi)
-
-       movl    24(%esi),%eax
-       movl    28(%esi),%edx
-       shrdl   %cl,%eax,%ebx
-       shrdl   %cl,%edx,%eax
-       movl    %ebx,24(%edi)
-       movl    %eax,28(%edi)
-
-       addl    $32,%esi
-       addl    $32,%edi
-       decl    %ebp
-       jnz     Roop
-
-Rend:  popl    %ebp
-       andl    $7,%ebp
-       jz      Rend2
-Roop2: movl    (%esi),%eax
-       shrdl   %cl,%eax,%edx           /* compute result limb */
-       movl    %edx,(%edi)
-       movl    %eax,%edx
-       addl    $4,%esi
-       addl    $4,%edi
-       decl    %ebp
-       jnz     Roop2
-
-Rend2: shrl    %cl,%edx                /* compute most significant limb */
-       movl    %edx,(%edi)             /* store it */
-
-       popl    %eax                    /* pop carry limb */
-
-       popl    %ebp
-       popl    %ebx
-       popl    %esi
-       popl    %edi
-       ret
-
-/* We loop from least significant end of the arrays, which is only
-   permissable if the source and destination don't overlap, since the
-   function is documented to work for overlapping source and destination.
-*/
-
-Rspecial:
-       leal    -4(%edi,%ebp,4),%edi
-       leal    -4(%esi,%ebp,4),%esi
-
-       movl    (%esi),%edx
-       subl    $4,%esi
-
-       decl    %ebp
-       pushl   %ebp
-       shrl    $3,%ebp
-
-       shrl    $1,%edx
-       incl    %ebp
-       decl    %ebp
-       jz      RLend
-
-       movl    (%edi),%eax             /* fetch destination cache line */
-
-       ALIGN   (2)
-RLoop: movl    -28(%edi),%eax          /* fetch destination cache line */
-       movl    %edx,%ebx
-
-       movl    (%esi),%eax
-       movl    -4(%esi),%edx
-       rcrl    $1,%eax
-       movl    %ebx,(%edi)
-       rcrl    $1,%edx
-       movl    %eax,-4(%edi)
-
-       movl    -8(%esi),%ebx
-       movl    -12(%esi),%eax
-       rcrl    $1,%ebx
-       movl    %edx,-8(%edi)
-       rcrl    $1,%eax
-       movl    %ebx,-12(%edi)
-
-       movl    -16(%esi),%edx
-       movl    -20(%esi),%ebx
-       rcrl    $1,%edx
-       movl    %eax,-16(%edi)
-       rcrl    $1,%ebx
-       movl    %edx,-20(%edi)
-
-       movl    -24(%esi),%eax
-       movl    -28(%esi),%edx
-       rcrl    $1,%eax
-       movl    %ebx,-24(%edi)
-       rcrl    $1,%edx
-       movl    %eax,-28(%edi)
-
-       leal    -32(%esi),%esi          /* use leal not to clobber carry */
-       leal    -32(%edi),%edi
-       decl    %ebp
-       jnz     RLoop
-
-RLend: popl    %ebp
-       sbbl    %eax,%eax               /* save carry in %eax */
-       andl    $7,%ebp
-       jz      RLend2
-       addl    %eax,%eax               /* restore carry from eax */
-RLoop2: movl   %edx,%ebx
-       movl    (%esi),%edx
-       rcrl    $1,%edx
-       movl    %ebx,(%edi)
-
-       leal    -4(%esi),%esi           /* use leal not to clobber carry */
-       leal    -4(%edi),%edi
-       decl    %ebp
-       jnz     RLoop2
-
-       jmp     RL1
-RLend2: addl   %eax,%eax               /* restore carry from eax */
-RL1:   movl    %edx,(%edi)             /* store last limb */
-
-       movl    $0,%eax
-       rcrl    $1,%eax
-
-       popl    %ebp
-       popl    %ebx
-       popl    %esi
-       popl    %edi
-       ret
-
diff --git a/mpi/i586/mpih-sub1.S b/mpi/i586/mpih-sub1.S
deleted file mode 100644 (file)
index ef2d580..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/* i80586 sub_n -- Sub two limb vectors of the same length > 0 and store
- *                sum in a third limb vector.
- *
- *      Copyright (C) 1992, 1994, 1995, 1998, 
- *                    2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- *  mpi_limb_t
- *  _gcry_mpih_sub_n( mpi_ptr_t res_ptr,       (sp + 4)
- *                mpi_ptr_t s1_ptr,    (sp + 8)
- *                mpi_ptr_t s2_ptr,    (sp + 12)
- *                mpi_size_t size)     (sp + 16)
- */
-
-
-.text
-       ALIGN (3)
-       .globl C_SYMBOL_NAME(_gcry_mpih_sub_n)
-C_SYMBOL_NAME(_gcry_mpih_sub_n:)
-
-       pushl   %edi
-       pushl   %esi
-       pushl   %ebx
-       pushl   %ebp
-
-       movl    20(%esp),%edi           /* res_ptr */
-       movl    24(%esp),%esi           /* s1_ptr */
-       movl    28(%esp),%ebp           /* s2_ptr */
-       movl    32(%esp),%ecx           /* size */
-
-       movl    (%ebp),%ebx
-
-       decl    %ecx
-       movl    %ecx,%edx
-       shrl    $3,%ecx
-       andl    $7,%edx
-       testl   %ecx,%ecx               /* zero carry flag */
-       jz      Lend
-       pushl   %edx
-
-       ALIGN (3)
-Loop:  movl    28(%edi),%eax           /* fetch destination cache line */
-       leal    32(%edi),%edi
-
-L1:    movl    (%esi),%eax
-       movl    4(%esi),%edx
-       sbbl    %ebx,%eax
-       movl    4(%ebp),%ebx
-       sbbl    %ebx,%edx
-       movl    8(%ebp),%ebx
-       movl    %eax,-32(%edi)
-       movl    %edx,-28(%edi)
-
-L2:    movl    8(%esi),%eax
-       movl    12(%esi),%edx
-       sbbl    %ebx,%eax
-       movl    12(%ebp),%ebx
-       sbbl    %ebx,%edx
-       movl    16(%ebp),%ebx
-       movl    %eax,-24(%edi)
-       movl    %edx,-20(%edi)
-
-L3:    movl    16(%esi),%eax
-       movl    20(%esi),%edx
-       sbbl    %ebx,%eax
-       movl    20(%ebp),%ebx
-       sbbl    %ebx,%edx
-       movl    24(%ebp),%ebx
-       movl    %eax,-16(%edi)
-       movl    %edx,-12(%edi)
-
-L4:    movl    24(%esi),%eax
-       movl    28(%esi),%edx
-       sbbl    %ebx,%eax
-       movl    28(%ebp),%ebx
-       sbbl    %ebx,%edx
-       movl    32(%ebp),%ebx
-       movl    %eax,-8(%edi)
-       movl    %edx,-4(%edi)
-
-       leal    32(%esi),%esi
-       leal    32(%ebp),%ebp
-       decl    %ecx
-       jnz     Loop
-
-       popl    %edx
-Lend:
-       decl    %edx                    /* test %edx w/o clobbering carry */
-       js      Lend2
-       incl    %edx
-Loop2:
-       leal    4(%edi),%edi
-       movl    (%esi),%eax
-       sbbl    %ebx,%eax
-       movl    4(%ebp),%ebx
-       movl    %eax,-4(%edi)
-       leal    4(%esi),%esi
-       leal    4(%ebp),%ebp
-       decl    %edx
-       jnz     Loop2
-Lend2:
-       movl    (%esi),%eax
-       sbbl    %ebx,%eax
-       movl    %eax,(%edi)
-
-       sbbl    %eax,%eax
-       negl    %eax
-
-       popl    %ebp
-       popl    %ebx
-       popl    %esi
-       popl    %edi
-       ret
-
index d6958f3..39cdd0c 100644 (file)
@@ -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;                                                \
@@ -305,9 +305,13 @@ extern UDItype __udiv_qrnnd ();
     (ph) = __ph; \
   } while (0)
 # define count_leading_zeros(count, x) \
-  __asm__ ("clz %0, %1\n"                                               \
-           : "=r" ((count))                                             \
-           : "r" ((UDItype)(x)))
+  do {                                                                  \
+    UDItype __co;                                                       \
+    __asm__ ("clz %0, %1\n"                                             \
+             : "=r" (__co)                                              \
+             : "r" ((UDItype)(x)));                                     \
+    (count) = __co;                                                     \
+  } while (0)
 #endif /* __aarch64__ */
 
 /***************************************
@@ -494,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));                               \
@@ -860,10 +864,10 @@ extern USItype __udiv_qrnnd ();
                                                __GNUC_MINOR__ >= 4)
 #  define umul_ppmm(w1, w0, u, v) \
   do {                                                                  \
-    UDItype _r;                                                         \
-    _r = (UDItype) u * v;                                               \
-    (w1) = _r >> 32;                                                    \
-    (w0) = (USItype) _r;                                                \
+    UDItype __r;                                                        \
+    __r = (UDItype)(u) * (v);                                           \
+    (w1) = __r >> 32;                                                   \
+    (w0) = (USItype) __r;                                               \
   } while (0)
 # elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #  define umul_ppmm(w1, w0, u, v) \
@@ -876,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)),                                        \
@@ -894,11 +898,11 @@ extern USItype __udiv_qrnnd ();
                                                __GNUC_MINOR__ >= 4)
 typedef unsigned int UTItype __attribute__ ((mode (TI)));
 #  define umul_ppmm(w1, w0, u, v) \
-  do {                                                                 \
-    UTItype _r;                                                        \
-    _r = (UTItype) u * v;                                              \
-    (w1) = _r >> 64;                                                   \
-    (w0) = (UDItype) _r;                                               \
+  do {                                                                  \
+    UTItype __r;                                                        \
+    __r = (UTItype)(u) * (v);                                           \
+    (w1) = __r >> 64;                                                   \
+    (w0) = (UDItype) __r;                                               \
   } while (0)
 # elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #  define umul_ppmm(w1, w0, u, v) \
@@ -911,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)),                                        \
@@ -1088,7 +1092,6 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
 /* Powerpc 64 bit support taken from gmp-4.1.2. */
 /* We should test _IBMR2 here when we add assembly support for the system
    vendor compilers.  */
-#if 0 /* Not yet enabled because we don't have hardware for a test. */
 #if (defined (_ARCH_PPC) || defined (__powerpc__)) && W_TYPE_SIZE == 64
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
   do {                                                                 \
@@ -1141,7 +1144,6 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
 #define SMUL_TIME 14  /* ??? */
 #define UDIV_TIME 120 /* ??? */
 #endif /* 64-bit PowerPC.  */
-#endif /* if 0 */
 
 /***************************************
  **************  PYR  ******************
@@ -1492,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));                               \
@@ -1539,6 +1541,54 @@ extern USItype __udiv_qrnnd ();
 
 
 /***************************************
+ *********** s390x/zSeries  ************
+ ***************************************/
+#if defined (__s390x__) && W_TYPE_SIZE == 64 && __GNUC__ >= 4
+# define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("algr %1,%5\n"                                               \
+          "alcgr %0,%3\n"                                              \
+          : "=r" ((sh)),                                               \
+            "=&r" ((sl))                                               \
+          : "0" ((UDItype)(ah)),                                       \
+            "r"  ((UDItype)(bh)),                                      \
+            "1" ((UDItype)(al)),                                       \
+            "r"  ((UDItype)(bl))                                       \
+          __CLOBBER_CC)
+# define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("slgr %1,%5\n"                                               \
+          "slbgr %0,%3\n"                                              \
+          : "=r" ((sh)),                                               \
+            "=&r" ((sl))                                               \
+          : "0" ((UDItype)(ah)),                                       \
+            "r" ((UDItype)(bh)),                                       \
+            "1" ((UDItype)(al)),                                       \
+            "r" ((UDItype)(bl))                                        \
+          __CLOBBER_CC)
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+#  define umul_ppmm(w1, w0, u, v) \
+  do {                                                                  \
+    UTItype ___r;                                                       \
+    __asm__ ("mlgr %0,%2"                                               \
+            : "=r" (___r)                                              \
+            : "0" ((UDItype)(u)),                                      \
+              "r" ((UDItype)(v)));                                     \
+    (w1) = ___r >> 64;                                                  \
+    (w0) = (UDItype) ___r;                                              \
+  } while (0)
+# define udiv_qrnnd(q, r, n1, n0, d) \
+  do {                                                                  \
+    UTItype ___r = ((UTItype)n1 << 64) | n0;                            \
+    __asm__ ("dlgr %0,%2"                                               \
+            : "=r" (___r)                                              \
+            : "0" (___r),                                              \
+              "r" ((UDItype)(d)));                                     \
+    (r) = ___r >> 64;                                                   \
+    (q) = (UDItype) ___r;                                               \
+  } while (0)
+#endif /* __s390x__ */
+
+
+/***************************************
  *****  End CPU Specific Versions  *****
  ***************************************/
 
@@ -1680,6 +1730,26 @@ extern USItype __udiv_qrnnd ();
 #endif
 
 #if !defined (count_leading_zeros)
+#  if defined (HAVE_BUILTIN_CLZL) && SIZEOF_UNSIGNED_LONG * 8 == W_TYPE_SIZE
+#    define count_leading_zeros(count, x) (count = __builtin_clzl(x))
+#    undef COUNT_LEADING_ZEROS_0 /* Input X=0 is undefined for the builtin. */
+#  elif defined (HAVE_BUILTIN_CLZ) && SIZEOF_UNSIGNED_INT * 8 == W_TYPE_SIZE
+#    define count_leading_zeros(count, x) (count = __builtin_clz(x))
+#    undef COUNT_LEADING_ZEROS_0 /* Input X=0 is undefined for the builtin. */
+#  endif
+#endif
+
+#if !defined (count_trailing_zeros)
+#  if defined (HAVE_BUILTIN_CTZL) && SIZEOF_UNSIGNED_LONG * 8 == W_TYPE_SIZE
+#    define count_trailing_zeros(count, x) (count = __builtin_ctzl(x))
+#    undef COUNT_LEADING_ZEROS_0 /* Input X=0 is undefined for the builtin. */
+#  elif defined (HAVE_BUILTIN_CTZ) && SIZEOF_UNSIGNED_INT * 8 == W_TYPE_SIZE
+#    define count_trailing_zeros(count, x) (count = __builtin_ctz(x))
+#    undef COUNT_LEADING_ZEROS_0 /* Input X=0 is undefined for the builtin. */
+#  endif
+#endif
+
+#if !defined (count_leading_zeros)
 extern
 #  ifdef __STDC__
 const
index 53f476e..38dd352 100644 (file)
@@ -191,6 +191,7 @@ _gcry_mpi_sub_ui(gcry_mpi_t w, gcry_mpi_t u, unsigned long v )
        cy = _gcry_mpih_add_1(wp, up, usize, v);
        wp[usize] = cy;
        wsize = usize + cy;
+       wsign = 1;
     }
     else {  /* The signs are different.  Need exact comparison to determine
             * which operand to subtract from which.  */
index 66e0961..8927fa0 100644 (file)
@@ -89,8 +89,11 @@ do_mpi_cmp (gcry_mpi_t u, gcry_mpi_t v, int absmode)
       usign = absmode? 0 : u->sign;
       vsign = absmode? 0 : v->sign;
 
-      /* Compare sign bits.  */
+      /* Special treatment for +0 == -0 */
+      if (!usize && !vsize)
+        return 0;
 
+      /* Compare sign bits.  */
       if (!usign && vsign)
         return 1;
       if (usign && !vsign)
index 9ac99c3..166ab87 100644 (file)
@@ -64,8 +64,9 @@ _gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
  * rem is optional
  */
 
-ulong
-_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor )
+unsigned long
+_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend,
+                     unsigned long divisor )
 {
     mpi_limb_t rlimb;
 
@@ -166,6 +167,9 @@ _gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t d
     if( quot )
        mpi_resize( quot, qsize);
 
+    if (!dsize)
+      _gcry_divide_by_zero();
+
     /* Read pointers here, when reallocation is finished.  */
     np = num->d;
     dp = den->d;
@@ -321,7 +325,7 @@ _gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned int count )
  * (note: divisor must fit into a limb)
  */
 int
-_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor )
+_gcry_mpi_divisible_ui(gcry_mpi_t dividend, unsigned long divisor )
 {
     return !_gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
 }
index 898ca47..11fcbde 100644 (file)
@@ -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) \
@@ -254,6 +259,28 @@ mpi_limb_t _gcry_mpih_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
 mpi_limb_t _gcry_mpih_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
                                                           unsigned cnt);
 
+/*-- mpih-const-time.c --*/
+#define mpih_set_cond(w,u,s,o) _gcry_mpih_set_cond ((w),(u),(s),(o))
+#define mpih_add_n_cond(w,u,v,s,o) _gcry_mpih_add_n_cond ((w),(u),(v),(s),(o))
+#define mpih_sub_n_cond(w,u,v,s,o) _gcry_mpih_sub_n_cond ((w),(u),(v),(s),(o))
+#define mpih_swap_cond(u,v,s,o) _gcry_mpih_swap_cond ((u),(v),(s),(o))
+#define mpih_abs_cond(w,u,s,o) _gcry_mpih_abs_cond ((w),(u),(s),(o))
+#define mpih_mod(v,vs,u,us) _gcry_mpih_mod ((v),(vs),(u),(us))
+
+void _gcry_mpih_set_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
+                          unsigned long op_enable);
+mpi_limb_t _gcry_mpih_add_n_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp,
+                                  mpi_size_t usize, unsigned long op_enable);
+mpi_limb_t _gcry_mpih_sub_n_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp,
+                                  mpi_size_t usize, unsigned long op_enable);
+void _gcry_mpih_swap_cond (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t usize,
+                           unsigned long op_enable);
+void _gcry_mpih_abs_cond (mpi_ptr_t wp, mpi_ptr_t up,
+                          mpi_size_t usize, unsigned long op_enable);
+mpi_ptr_t _gcry_mpih_mod (mpi_ptr_t vp, mpi_size_t vsize,
+                          mpi_ptr_t up, mpi_size_t usize);
+int _gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v);
+
 
 /* Define stuff for longlong.h.  */
 #define W_TYPE_SIZE BITS_PER_MPI_LIMB
index ee6813b..7ce8746 100644 (file)
 #include "mpi-internal.h"
 #include "g10lib.h"
 
+/*
+ * This uses a modular inversion algorithm designed by Niels Möller
+ * which was implemented in Nettle.  The same algorithm was later also
+ * adapted to GMP in mpn_sec_invert.
+ *
+ * For the description of the algorithm, see Algorithm 5 in Appendix A
+ * of "Fast Software Polynomial Multiplication on ARM Processors using
+ * the NEON Engine" by Danilo Câmara, Conrado P. L. Gouvêa, Julio
+ * López, and Ricardo Dahab:
+ *   https://hal.inria.fr/hal-01506572/document
+ *
+ * Note that in the reference above, at the line 2 of Algorithm 5,
+ * initial value of V was described as V:=1 wrongly.  It must be V:=0.
+ */
+static mpi_ptr_t
+mpih_invm_odd (mpi_ptr_t ap, mpi_ptr_t np, mpi_size_t nsize)
+{
+  int secure;
+  unsigned int iterations;
+  mpi_ptr_t n1hp;
+  mpi_ptr_t bp;
+  mpi_ptr_t up, vp;
+
+  secure = _gcry_is_secure (ap);
+  up = mpi_alloc_limb_space (nsize, secure);
+  MPN_ZERO (up, nsize);
+  up[0] = 1;
+
+  vp = mpi_alloc_limb_space (nsize, secure);
+  MPN_ZERO (vp, nsize);
+
+  secure = _gcry_is_secure (np);
+  bp = mpi_alloc_limb_space (nsize, secure);
+  MPN_COPY (bp, np, nsize);
+
+  n1hp = mpi_alloc_limb_space (nsize, secure);
+  MPN_COPY (n1hp, np, nsize);
+  _gcry_mpih_rshift (n1hp, n1hp, nsize, 1);
+  _gcry_mpih_add_1 (n1hp, n1hp, nsize, 1);
+
+  iterations = 2 * nsize * BITS_PER_MPI_LIMB;
+
+  while (iterations-- > 0)
+    {
+      mpi_limb_t odd_a, odd_u, underflow, borrow;
+
+      odd_a = ap[0] & 1;
+
+      underflow = mpih_sub_n_cond (ap, ap, bp, nsize, odd_a);
+      mpih_add_n_cond (bp, bp, ap, nsize, underflow);
+      mpih_abs_cond (ap, ap, nsize, underflow);
+      mpih_swap_cond (up, vp, nsize, underflow);
+
+      _gcry_mpih_rshift (ap, ap, nsize, 1);
+
+      borrow = mpih_sub_n_cond (up, up, vp, nsize, odd_a);
+      mpih_add_n_cond (up, up, np, nsize, borrow);
+
+      odd_u = _gcry_mpih_rshift (up, up, nsize, 1) != 0;
+      mpih_add_n_cond (up, up, n1hp, nsize, odd_u);
+    }
+
+  _gcry_mpi_free_limb_space (n1hp, nsize);
+  _gcry_mpi_free_limb_space (up, nsize);
+
+  if (_gcry_mpih_cmp_ui (bp, nsize, 1) == 0)
+    {
+      /* Inverse exists.  */
+      _gcry_mpi_free_limb_space (bp, nsize);
+      return vp;
+    }
+  else
+    {
+      _gcry_mpi_free_limb_space (bp, nsize);
+      _gcry_mpi_free_limb_space (vp, nsize);
+      return NULL;
+    }
+}
+
+
+/*
+ * Calculate the multiplicative inverse X of A mod 2^K
+ * A must be positive.
+ *
+ * See section 7 in "A New Algorithm for Inversion mod p^k" by Çetin
+ * Kaya Koç: https://eprint.iacr.org/2017/411.pdf
+ */
+static mpi_ptr_t
+mpih_invm_pow2 (mpi_ptr_t ap, mpi_size_t asize, unsigned int k)
+{
+  int secure = _gcry_is_secure (ap);
+  mpi_size_t i;
+  unsigned int iterations;
+  mpi_ptr_t xp, wp, up, vp;
+  mpi_size_t usize;
+
+  if (!(ap[0] & 1))
+    return NULL;
+
+  iterations = ((k + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB)
+    * BITS_PER_MPI_LIMB;
+  usize = iterations / BITS_PER_MPI_LIMB;
+
+  up = mpi_alloc_limb_space (usize, secure);
+  MPN_ZERO (up, usize);
+  up[0] = 1;
+
+  vp = mpi_alloc_limb_space (usize, secure);
+  for (i = 0; i < (usize < asize ? usize : asize); i++)
+    vp[i] = ap[i];
+  for (; i < usize; i++)
+    vp[i] = 0;
+  if ((k % BITS_PER_MPI_LIMB))
+    for (i = k % BITS_PER_MPI_LIMB; i < BITS_PER_MPI_LIMB; i++)
+      vp[k/BITS_PER_MPI_LIMB] &= ~(((mpi_limb_t)1) << i);
+
+  wp = mpi_alloc_limb_space (usize, secure);
+  MPN_COPY (wp, up, usize);
+
+  xp = mpi_alloc_limb_space (usize, secure);
+  MPN_ZERO (xp, usize);
+
+  /*
+   * It can be considered that overflow at _gcry_mpih_sub_n results
+   * adding 2^(USIZE*BITS_PER_MPI_LIMB), which is no problem in modulo
+   * 2^K computation.
+   */
+  for (i = 0; i < iterations; i++)
+    {
+      int b0 = (up[0] & 1);
+
+      xp[i/BITS_PER_MPI_LIMB] |= ((mpi_limb_t)b0<<(i%BITS_PER_MPI_LIMB));
+      _gcry_mpih_sub_n (wp, up, vp, usize);
+      mpih_set_cond (up, wp, usize, b0);
+      _gcry_mpih_rshift (up, up, usize, 1);
+    }
+
+  if ((k % BITS_PER_MPI_LIMB))
+    for (i = k % BITS_PER_MPI_LIMB; i < BITS_PER_MPI_LIMB; i++)
+      xp[k/BITS_PER_MPI_LIMB] &= ~(((mpi_limb_t)1) << i);
+
+  _gcry_mpi_free_limb_space (up, usize);
+  _gcry_mpi_free_limb_space (vp, usize);
+  _gcry_mpi_free_limb_space (wp, usize);
+
+  return xp;
+}
+
+
 /****************
  * Calculate the multiplicative inverse X of A mod N
  * That is: Find the solution x for
  *             1 = (a*x) mod n
  */
-int
-_gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
+static int
+mpi_invm_generic (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
 {
+    int is_gcd_one;
 #if 0
+    /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X) */
     gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3;
-    gcry_mpi_t ta, tb, tc;
 
     u = mpi_copy(a);
     v = mpi_copy(n);
@@ -63,6 +213,8 @@ _gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
        log_mpidump("v2=", v2); */
     mpi_set(x, u1);
 
+    is_gcd_one = (mpi_cmp_ui (u3, 1) == 0);
+
     mpi_free(u1);
     mpi_free(u2);
     mpi_free(u3);
@@ -77,7 +229,11 @@ _gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
     mpi_free(v);
 #elif 0
     /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X)
-     * modified according to Michael Penk's solution for Exercise 35 */
+     * modified according to Michael Penk's solution for Exercise 35
+     * (in the first edition)
+     * In the third edition, it's Exercise 39, and it is described in
+     * page 646 of ANSWERS TO EXERCISES chapter.
+     */
 
     /* FIXME: we can simplify this in most cases (see Knuth) */
     gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3;
@@ -144,7 +300,8 @@ _gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
            mpi_sub(t2, t2, u);
        }
     } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
-    /* mpi_lshift( u3, k ); */
+    /* mpi_lshift( u3, u3, k ); */
+    is_gcd_one = (k == 0 && mpi_cmp_ui (u3, 1) == 0);
     mpi_set(x, u1);
 
     mpi_free(u1);
@@ -160,16 +317,15 @@ _gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
     /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X)
      * modified according to Michael Penk's solution for Exercise 35
      * with further enhancement */
+    /* The reference in the comment above is for the first edition.
+     * In the third edition, it's Exercise 39, and it is described in
+     * page 646 of ANSWERS TO EXERCISES chapter.
+     */
     gcry_mpi_t u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3;
     unsigned k;
     int sign;
     int odd ;
 
-    if (!mpi_cmp_ui (a, 0))
-        return 0; /* Inverse does not exists.  */
-    if (!mpi_cmp_ui (n, 1))
-        return 0; /* Inverse does not exists.  */
-
     u = mpi_copy(a);
     v = mpi_copy(n);
 
@@ -250,7 +406,8 @@ _gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
                mpi_sub(t2, t2, u);
        }
     } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
-    /* mpi_lshift( u3, k ); */
+    /* mpi_lshift( u3, u3, k ); */
+    is_gcd_one = (k == 0 && mpi_cmp_ui (u3, 1) == 0);
     mpi_set(x, u1);
 
     mpi_free(u1);
@@ -268,5 +425,141 @@ _gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
     mpi_free(u);
     mpi_free(v);
 #endif
-    return 1;
+    return is_gcd_one;
+}
+
+
+/*
+ * Set X to the multiplicative inverse of A mod M.  Return true if the
+ * inverse exists.
+ */
+int
+_gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
+{
+  mpi_ptr_t ap, xp;
+
+  if (!mpi_cmp_ui (a, 0))
+    return 0; /* Inverse does not exists.  */
+  if (!mpi_cmp_ui (n, 1))
+    return 0; /* Inverse does not exists.  */
+
+  if (mpi_test_bit (n, 0))
+    {
+      if (a->nlimbs <= n->nlimbs)
+        {
+          ap = mpi_alloc_limb_space (n->nlimbs, _gcry_is_secure (a->d));
+          MPN_ZERO (ap, n->nlimbs);
+          MPN_COPY (ap, a->d, a->nlimbs);
+        }
+      else
+        ap = _gcry_mpih_mod (a->d, a->nlimbs, n->d, n->nlimbs);
+
+      xp = mpih_invm_odd (ap, n->d, n->nlimbs);
+      _gcry_mpi_free_limb_space (ap, n->nlimbs);
+
+      if (xp)
+        {
+          _gcry_mpi_assign_limb_space (x, xp, n->nlimbs);
+          x->nlimbs = n->nlimbs;
+          return 1;
+        }
+      else
+        return 0; /* Inverse does not exists.  */
+    }
+  else if (!a->sign && !n->sign)
+    {
+      unsigned int k = mpi_trailing_zeros (n);
+      mpi_size_t x1size = ((k + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB);
+      mpi_size_t hsize;
+      gcry_mpi_t q;
+      mpi_ptr_t x1p, x2p, q_invp, hp, diffp;
+      mpi_size_t i;
+
+      if (k == _gcry_mpi_get_nbits (n) - 1)
+        {
+          x1p = mpih_invm_pow2 (a->d, a->nlimbs, k);
+
+          if (x1p)
+            {
+              _gcry_mpi_assign_limb_space (x, x1p, x1size);
+              x->nlimbs = x1size;
+              return 1;
+            }
+          else
+            return 0; /* Inverse does not exists.  */
+        }
+
+      /* N can be expressed as P * Q, where P = 2^K.  P and Q are coprime.  */
+      /*
+       * Compute X1 = invm (A, P) and X2 = invm (A, Q), and combine
+       * them by Garner's formula, to get X = invm (A, P*Q).
+       * A special case of Chinese Remainder Theorem.
+       */
+
+      /* X1 = invm (A, P) */
+      x1p = mpih_invm_pow2 (a->d, a->nlimbs, k);
+      if (!x1p)
+        return 0;               /* Inverse does not exists.  */
+
+      /* Q = N / P          */
+      q = mpi_new (0);
+      mpi_rshift (q, n, k);
+
+      /* X2 = invm (A%Q, Q) */
+      ap = _gcry_mpih_mod (a->d, a->nlimbs, q->d, q->nlimbs);
+      x2p = mpih_invm_odd (ap, q->d, q->nlimbs);
+      _gcry_mpi_free_limb_space (ap, q->nlimbs);
+      if (!x2p)
+        {
+          _gcry_mpi_free_limb_space (x1p, x1size);
+          mpi_free (q);
+          return 0;             /* Inverse does not exists.  */
+        }
+
+      /* Q_inv = Q^(-1) = invm (Q, P) */
+      q_invp = mpih_invm_pow2 (q->d, q->nlimbs, k);
+
+      /* H = (X1 - X2) * Q_inv % P */
+      diffp = mpi_alloc_limb_space (x1size, _gcry_is_secure (a->d));
+      if (x1size >= q->nlimbs)
+        _gcry_mpih_sub (diffp, x1p, x1size, x2p, q->nlimbs);
+      else
+       _gcry_mpih_sub_n (diffp, x1p, x2p, x1size);
+      _gcry_mpi_free_limb_space (x1p, x1size);
+      if ((k % BITS_PER_MPI_LIMB))
+        for (i = k % BITS_PER_MPI_LIMB; i < BITS_PER_MPI_LIMB; i++)
+          diffp[k/BITS_PER_MPI_LIMB] &= ~(((mpi_limb_t)1) << i);
+
+      hsize = x1size * 2;
+      hp = mpi_alloc_limb_space (hsize, _gcry_is_secure (a->d));
+      _gcry_mpih_mul_n (hp, diffp, q_invp, x1size);
+      _gcry_mpi_free_limb_space (diffp, x1size);
+      _gcry_mpi_free_limb_space (q_invp, x1size);
+
+      for (i = x1size; i < hsize; i++)
+        hp[i] = 0;
+      if ((k % BITS_PER_MPI_LIMB))
+        for (i = k % BITS_PER_MPI_LIMB; i < BITS_PER_MPI_LIMB; i++)
+          hp[k/BITS_PER_MPI_LIMB] &= ~(((mpi_limb_t)1) << i);
+
+      xp = mpi_alloc_limb_space (x1size + q->nlimbs, _gcry_is_secure (a->d));
+      if (x1size >= q->nlimbs)
+        _gcry_mpih_mul (xp, hp, x1size, q->d, q->nlimbs);
+      else
+        _gcry_mpih_mul (xp, q->d, q->nlimbs, hp, x1size);
+
+      _gcry_mpi_free_limb_space (hp, hsize);
+
+      _gcry_mpih_add (xp, xp, x1size + q->nlimbs, x2p, q->nlimbs);
+      _gcry_mpi_free_limb_space (x2p, q->nlimbs);
+
+      _gcry_mpi_assign_limb_space (x, xp, x1size + q->nlimbs);
+      x->nlimbs = x1size + q->nlimbs;
+
+      mpi_free (q);
+
+      return 1;
+    }
+  else
+    return mpi_invm_generic (x, a, n);
 }
index 4c63a14..830ee4e 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "mpi-internal.h"
 #include "g10lib.h"
+#include "../cipher/bufhelp.h"
 
 /* The maximum length we support in the functions converting an
  * external representation to an MPI.  This limit is used to catch
@@ -51,8 +52,9 @@ mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
   unsigned int nbits, nbytes, nlimbs, nread=0;
   mpi_limb_t a;
   gcry_mpi_t val = MPI_NULL;
+  unsigned int max_nread = *ret_nread;
 
-  if ( *ret_nread < 2 )
+  if ( max_nread < 2 )
     goto leave;
   nbits = buffer[0] << 8 | buffer[1];
   if ( nbits > MAX_EXTERN_MPI_BITS )
@@ -73,9 +75,22 @@ mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
   for ( ; j > 0; j-- )
     {
       a = 0;
+      if (i == 0 && nread + BYTES_PER_MPI_LIMB <= max_nread)
+       {
+#if BYTES_PER_MPI_LIMB == 4
+         a = buf_get_be32 (buffer);
+#elif BYTES_PER_MPI_LIMB == 8
+         a = buf_get_be64 (buffer);
+#else
+#     error please implement for this limb size.
+#endif
+         buffer += BYTES_PER_MPI_LIMB;
+         nread += BYTES_PER_MPI_LIMB;
+         i += BYTES_PER_MPI_LIMB;
+       }
       for (; i < BYTES_PER_MPI_LIMB; i++ )
         {
-          if ( ++nread > *ret_nread )
+          if ( ++nread > max_nread )
             {
 /*               log_debug ("mpi larger than buffer"); */
               mpi_free (val);
@@ -99,8 +114,45 @@ mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
  * Fill the mpi VAL from the hex string in STR.
  */
 static int
-mpi_fromstr (gcry_mpi_t val, const char *str)
+mpi_fromstr (gcry_mpi_t val, const char *str, size_t slen)
 {
+  static const int hex2int[2][256] =
+  {
+    {
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x10, 0x20, 0x30,
+      0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, -1, 0xa0,
+      0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xa0,
+      0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+    },
+    {
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x01, 0x02, 0x03,
+      0x04, 0x05, 0x06, 0x07, 0x08, 0x09, -1, -1, -1, -1, -1, -1, -1, 0x0a,
+      0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x0a,
+      0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+    }
+  };
   int sign = 0;
   int prepend_zero = 0;
   int i, j, c, c1, c2;
@@ -111,19 +163,17 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
     {
       sign = 1;
       str++;
+      slen--;
     }
 
   /* Skip optional hex prefix.  */
   if ( *str == '0' && str[1] == 'x' )
-    str += 2;
-
-  nbits = strlen (str);
-  if (nbits > MAX_EXTERN_SCAN_BYTES)
     {
-      mpi_clear (val);
-      return 1;  /* Error.  */
+      str += 2;
+      slen -= 2;
     }
-  nbits *= 4;
+
+  nbits = slen * 4;
   if ((nbits % 8))
     prepend_zero = 1;
 
@@ -140,6 +190,44 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
   for (; j > 0; j--)
     {
       a = 0;
+
+      if (prepend_zero == 0 && (i & 31) == 0)
+       {
+         while (slen >= sizeof(u32) * 2)
+           {
+             u32 n, m;
+             u32 x, y;
+
+             x = buf_get_le32(str);
+             y = buf_get_le32(str + 4);
+             str += 8;
+             slen -= 8;
+
+             a <<= 31; /* Two step to avoid compiler warning on 32-bit. */
+             a <<= 1;
+
+             n = (hex2int[0][(x >> 0) & 0xff]
+                  | hex2int[1][(x >> 8) & 0xff]) << 8;
+             m = (hex2int[0][(y >> 0) & 0xff]
+                  | hex2int[1][(y >> 8) & 0xff]) << 8;
+             n |= hex2int[0][(x >> 16) & 0xff];
+             n |= hex2int[1][(x >> 24) & 0xff];
+             m |= hex2int[0][(y >> 16) & 0xff];
+             m |= hex2int[1][(y >> 24) & 0xff];
+
+             a |= (n << 16) | m;
+             i += 32;
+             if ((int)(n | m) < 0)
+               {
+                 /* Invalid character. */
+                 mpi_clear (val);
+                 return 1;  /* Error.  */
+               }
+             if (i == BITS_PER_MPI_LIMB)
+               break;
+           }
+       }
+
       for (; i < BYTES_PER_MPI_LIMB; i++)
         {
           if (prepend_zero)
@@ -148,7 +236,10 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
               prepend_zero = 0;
            }
           else
-            c1 = *str++;
+           {
+             c1 = *str++;
+             slen--;
+           }
 
           if (!c1)
             {
@@ -156,30 +247,15 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
               return 1;  /* Error.  */
            }
           c2 = *str++;
+         slen--;
           if (!c2)
             {
               mpi_clear (val);
               return 1;  /* Error.  */
            }
-          if ( c1 >= '0' && c1 <= '9' )
-            c = c1 - '0';
-          else if ( c1 >= 'a' && c1 <= 'f' )
-            c = c1 - 'a' + 10;
-          else if ( c1 >= 'A' && c1 <= 'F' )
-            c = c1 - 'A' + 10;
-          else
-            {
-              mpi_clear (val);
-              return 1;  /* Error.  */
-           }
-          c <<= 4;
-          if ( c2 >= '0' && c2 <= '9' )
-            c |= c2 - '0';
-          else if( c2 >= 'a' && c2 <= 'f' )
-            c |= c2 - 'a' + 10;
-          else if( c2 >= 'A' && c2 <= 'F' )
-            c |= c2 - 'A' + 10;
-          else
+         c = hex2int[0][c1 & 0xff];
+         c |= hex2int[1][c2 & 0xff];
+          if (c < 0)
             {
               mpi_clear(val);
               return 1;  /* Error. */
@@ -248,19 +324,11 @@ do_get_buffer (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
     {
       alimb = a->d[i];
 #if BYTES_PER_MPI_LIMB == 4
-      *p++ = alimb >> 24;
-      *p++ = alimb >> 16;
-      *p++ = alimb >>  8;
-      *p++ = alimb       ;
+      buf_put_be32 (p, alimb);
+      p += 4;
 #elif BYTES_PER_MPI_LIMB == 8
-      *p++ = alimb >> 56;
-      *p++ = alimb >> 48;
-      *p++ = alimb >> 40;
-      *p++ = alimb >> 32;
-      *p++ = alimb >> 24;
-      *p++ = alimb >> 16;
-      *p++ = alimb >>  8;
-      *p++ = alimb       ;
+      buf_put_be64 (p, alimb);
+      p += 8;
 #else
 #     error please implement for this limb size.
 #endif
@@ -270,7 +338,22 @@ do_get_buffer (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
     {
       length = *nbytes;
       /* Reverse buffer and pad with zeroes.  */
-      for (i=0; i < length/2; i++)
+      for (i = 0; i + 8 < length / 2; i += 8)
+       {
+         u64 head = buf_get_be64 (buffer + i);
+         u64 tail = buf_get_be64 (buffer + length - 8 - i);
+         buf_put_le64 (buffer + length - 8 - i, head);
+         buf_put_le64 (buffer + i, tail);
+       }
+      if (i + 4 < length / 2)
+       {
+         u32 head = buf_get_be32 (buffer + i);
+         u32 tail = buf_get_be32 (buffer + length - 4 - i);
+         buf_put_le32 (buffer + length - 4 - i, head);
+         buf_put_le32 (buffer + i, tail);
+         i += 4;
+       }
+      for (; i < length/2; i++)
         {
           tmp = buffer[i];
           buffer[i] = buffer[length-1-i];
@@ -298,7 +381,18 @@ byte *
 _gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int fill_le,
                       unsigned int *r_nbytes, int *sign)
 {
-  return do_get_buffer (a, fill_le, 0, r_nbytes, sign, 0);
+  if (mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
+    {
+      unsigned int nbits;
+      byte *p = _gcry_mpi_get_opaque_copy (a, &nbits);
+
+      if (r_nbytes)
+        *r_nbytes = (nbits+7)/8;
+
+      return p;
+    }
+  else
+    return do_get_buffer (a, fill_le, 0, r_nbytes, sign, 0);
 }
 
 byte *
@@ -343,53 +437,33 @@ _gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg,
   for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; )
     {
 #if BYTES_PER_MPI_LIMB == 4
-      alimb  = *p--        ;
-      alimb |= *p-- <<  8 ;
-      alimb |= *p-- << 16 ;
-      alimb |= *p-- << 24 ;
+      alimb = buf_get_be32(p - 4 + 1);
+      p -= 4;
 #elif BYTES_PER_MPI_LIMB == 8
-      alimb  = (mpi_limb_t)*p--        ;
-      alimb |= (mpi_limb_t)*p-- <<  8 ;
-      alimb |= (mpi_limb_t)*p-- << 16 ;
-      alimb |= (mpi_limb_t)*p-- << 24 ;
-      alimb |= (mpi_limb_t)*p-- << 32 ;
-      alimb |= (mpi_limb_t)*p-- << 40 ;
-      alimb |= (mpi_limb_t)*p-- << 48 ;
-      alimb |= (mpi_limb_t)*p-- << 56 ;
+      alimb = buf_get_be64(p - 8 + 1);
+      p -= 8;
 #else
-#       error please implement for this limb size.
+#     error please implement for this limb size.
 #endif
       a->d[i++] = alimb;
     }
   if ( p >= buffer )
     {
+      byte last[BYTES_PER_MPI_LIMB] = { 0 };
+      unsigned int n = (p - buffer) + 1;
+
+      n = n > BYTES_PER_MPI_LIMB ? BYTES_PER_MPI_LIMB : n;
+      memcpy (last + BYTES_PER_MPI_LIMB - n, p - n + 1, n);
+      p -= n;
+
 #if BYTES_PER_MPI_LIMB == 4
-      alimb  = *p--;
-      if (p >= buffer)
-        alimb |= *p-- <<  8;
-      if (p >= buffer)
-        alimb |= *p-- << 16;
-      if (p >= buffer)
-        alimb |= *p-- << 24;
+      alimb = buf_get_be32(last);
 #elif BYTES_PER_MPI_LIMB == 8
-      alimb  = (mpi_limb_t)*p--;
-      if (p >= buffer)
-        alimb |= (mpi_limb_t)*p-- << 8;
-      if (p >= buffer)
-        alimb |= (mpi_limb_t)*p-- << 16;
-      if (p >= buffer)
-        alimb |= (mpi_limb_t)*p-- << 24;
-      if (p >= buffer)
-        alimb |= (mpi_limb_t)*p-- << 32;
-      if (p >= buffer)
-        alimb |= (mpi_limb_t)*p-- << 40;
-      if (p >= buffer)
-        alimb |= (mpi_limb_t)*p-- << 48;
-      if (p >= buffer)
-        alimb |= (mpi_limb_t)*p-- << 56;
+      alimb = buf_get_be64(last);
 #else
 #     error please implement for this limb size.
 #endif
+
       a->d[i++] = alimb;
     }
   a->nlimbs = i;
@@ -435,25 +509,24 @@ twocompl (unsigned char *p, unsigned int n)
     ;
   if (i >= 0)
     {
-      if ((p[i] & 0x01))
-        p[i] = (((p[i] ^ 0xfe) | 0x01) & 0xff);
-      else if ((p[i] & 0x02))
-        p[i] = (((p[i] ^ 0xfc) | 0x02) & 0xfe);
-      else if ((p[i] & 0x04))
-        p[i] = (((p[i] ^ 0xf8) | 0x04) & 0xfc);
-      else if ((p[i] & 0x08))
-        p[i] = (((p[i] ^ 0xf0) | 0x08) & 0xf8);
-      else if ((p[i] & 0x10))
-        p[i] = (((p[i] ^ 0xe0) | 0x10) & 0xf0);
-      else if ((p[i] & 0x20))
-        p[i] = (((p[i] ^ 0xc0) | 0x20) & 0xe0);
-      else if ((p[i] & 0x40))
-        p[i] = (((p[i] ^ 0x80) | 0x40) & 0xc0);
-      else
-        p[i] = 0x80;
+      unsigned char pi = p[i];
+      unsigned int ntz = _gcry_ctz (pi);
+
+      p[i] = ((p[i] ^ (0xfe << ntz)) | (0x01 << ntz)) & (0xff << ntz);
 
-      for (i--; i >= 0; i--)
-        p[i] ^= 0xff;
+      for (i--; i >= 7; i -= 8)
+       {
+         buf_put_he64(&p[i-7], ~buf_get_he64(&p[i-7]));
+       }
+      if (i >= 3)
+       {
+         buf_put_he32(&p[i-3], ~buf_get_he32(&p[i-3]));
+         i -= 4;
+       }
+      for (; i >= 0; i--)
+       {
+         p[i] ^= 0xff;
+       }
     }
 }
 
@@ -560,7 +633,7 @@ _gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
       if (len && len < 4)
         return GPG_ERR_TOO_SHORT;
 
-      n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
+      n = buf_get_be32 (s);
       s += 4;
       if (len)
         len -= 4;
@@ -594,12 +667,19 @@ _gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
     }
   else if (format == GCRYMPI_FMT_HEX)
     {
+      size_t slen;
       /* We can only handle C strings for now.  */
       if (buflen)
         return GPG_ERR_INV_ARG;
 
-      a = secure? mpi_alloc_secure (0) : mpi_alloc(0);
-      if (mpi_fromstr (a, (const char *)buffer))
+      slen = strlen ((const char *)buffer);
+      if (slen > MAX_EXTERN_SCAN_BYTES)
+       return GPG_ERR_INV_OBJ;
+      a = secure? mpi_alloc_secure ((((slen+1)/2)+BYTES_PER_MPI_LIMB-1)
+                                   /BYTES_PER_MPI_LIMB)
+               : mpi_alloc((((slen+1)/2)+BYTES_PER_MPI_LIMB-1)
+                           /BYTES_PER_MPI_LIMB);
+      if (mpi_fromstr (a, (const char *)buffer, slen))
         {
           mpi_free (a);
           return GPG_ERR_INV_OBJ;
@@ -787,10 +867,8 @@ _gcry_mpi_print (enum gcry_mpi_format format,
         {
           unsigned char *s = buffer;
 
-          *s++ = n >> 24;
-          *s++ = n >> 16;
-          *s++ = n >> 8;
-          *s++ = n;
+         buf_put_be32 (s, n);
+         s += 4;
           if (extra == 1)
             *s++ = 0;
           else if (extra)
@@ -821,6 +899,11 @@ _gcry_mpi_print (enum gcry_mpi_format format,
        }
       if (buffer)
         {
+         static const u32 nibble2hex[] =
+         {
+           '0', '1', '2', '3', '4', '5', '6', '7',
+           '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+         };
           unsigned char *s = buffer;
 
           if (negative)
@@ -831,13 +914,37 @@ _gcry_mpi_print (enum gcry_mpi_format format,
               *s++ = '0';
            }
 
-          for (i=0; i < n; i++)
+         for (i = 0; i + 4 < n; i += 4)
+           {
+             u32 c = buf_get_be32(tmp + i);
+             u32 o1, o2;
+
+             o1 = nibble2hex[(c >> 28) & 0xF];
+             o1 <<= 8;
+             o1 |= nibble2hex[(c >> 24) & 0xF];
+             o1 <<= 8;
+             o1 |= nibble2hex[(c >> 20) & 0xF];
+             o1 <<= 8;
+             o1 |= nibble2hex[(c >> 16) & 0xF];
+
+             o2 = nibble2hex[(c >> 12) & 0xF];
+             o2 <<= 8;
+             o2 |= (u64)nibble2hex[(c >> 8) & 0xF];
+             o2 <<= 8;
+             o2 |= (u64)nibble2hex[(c >> 4) & 0xF];
+             o2 <<= 8;
+             o2 |= (u64)nibble2hex[(c >> 0) & 0xF];
+
+             buf_put_be32 (s + 0, o1);
+             buf_put_be32 (s + 4, o2);
+             s += 8;
+           }
+          for (; i < n; i++)
             {
               unsigned int c = tmp[i];
 
-              *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ;
-              c &= 15;
-              *s++ = c < 10? '0'+c : 'A'+c-10 ;
+              *s++ = nibble2hex[c >> 4];
+              *s++ = nibble2hex[c & 0xF];
            }
           *s++ = 0;
           *nwritten = s - buffer;
diff --git a/mpi/mpih-const-time.c b/mpi/mpih-const-time.c
new file mode 100644 (file)
index 0000000..b527ad7
--- /dev/null
@@ -0,0 +1,209 @@
+/* mpih-const-time.c  -  Constant-time MPI helper functions
+ *      Copyright (C) 2020  g10 Code GmbH
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpi-internal.h"
+#include "g10lib.h"
+
+#define A_LIMB_1 ((mpi_limb_t)1)
+
+/* 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;
+
+/*
+ *  W = U when OP_ENABLED=1
+ *  otherwise, W keeps old value
+ */
+void
+_gcry_mpih_set_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
+                     unsigned long op_enable)
+{
+  mpi_size_t i;
+  mpi_limb_t mask1 = vzero - op_enable;
+  mpi_limb_t mask2 = op_enable - vone;
+
+  for (i = 0; i < usize; i++)
+    {
+      wp[i] = (wp[i] & mask2) | (up[i] & mask1);
+    }
+}
+
+
+/*
+ *  W = U + V when OP_ENABLED=1
+ *  otherwise, W = U
+ */
+mpi_limb_t
+_gcry_mpih_add_n_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp,
+                       mpi_size_t usize, unsigned long op_enable)
+{
+  mpi_size_t i;
+  mpi_limb_t cy;
+  mpi_limb_t mask1 = vzero - op_enable;
+  mpi_limb_t mask2 = op_enable - vone;
+
+  cy = 0;
+  for (i = 0; i < usize; i++)
+    {
+      mpi_limb_t u = up[i];
+      mpi_limb_t x = u + vp[i];
+      mpi_limb_t cy1 = x < u;
+      mpi_limb_t cy2;
+
+      x = x + cy;
+      cy2 = x < cy;
+      cy = cy1 | cy2;
+      wp[i] = (u & mask2) | (x & mask1);
+    }
+
+  return cy & mask1;
+}
+
+
+/*
+ *  W = U - V when OP_ENABLED=1
+ *  otherwise, W = U
+ */
+mpi_limb_t
+_gcry_mpih_sub_n_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_ptr_t vp,
+                       mpi_size_t usize, unsigned long op_enable)
+{
+  mpi_size_t i;
+  mpi_limb_t cy;
+  mpi_limb_t mask1 = vzero - op_enable;
+  mpi_limb_t mask2 = op_enable - vone;
+
+  cy = 0;
+  for (i = 0; i < usize; i++)
+    {
+      mpi_limb_t u = up[i];
+      mpi_limb_t x = u - vp[i];
+      mpi_limb_t cy1 = x > u;
+      mpi_limb_t cy2;
+
+      cy2 = x < cy;
+      x = x - cy;
+      cy = cy1 | cy2;
+      wp[i] = (u & mask2) | (x & mask1);
+    }
+
+  return cy & mask1;
+}
+
+
+/*
+ *  Swap value of U and V when OP_ENABLED=1
+ *  otherwise, no change
+ */
+void
+_gcry_mpih_swap_cond (mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t usize,
+                      unsigned long op_enable)
+{
+  mpi_size_t i;
+  mpi_limb_t mask1 = vzero - op_enable;
+  mpi_limb_t mask2 = op_enable - vone;
+
+  for (i = 0; i < usize; i++)
+    {
+      mpi_limb_t u = up[i];
+      mpi_limb_t v = vp[i];
+      up[i] = (u & mask2) | (v & mask1);
+      vp[i] = (u & mask1) | (v & mask2);
+    }
+}
+
+
+/*
+ *  W = -U when OP_ENABLED=1
+ *  otherwise, W = U
+ */
+void
+_gcry_mpih_abs_cond (mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
+                     unsigned long op_enable)
+{
+  mpi_size_t i;
+  mpi_limb_t mask1 = vzero - op_enable;
+  mpi_limb_t mask2 = op_enable - vone;
+  mpi_limb_t cy = op_enable;
+
+  for (i = 0; i < usize; i++)
+    {
+      mpi_limb_t u = up[i];
+      mpi_limb_t x = ~u + cy;
+
+      cy = (x < ~u);
+      wp[i] = (u & mask2) | (x & mask1);
+    }
+}
+
+
+/*
+ * Allocating memory for W,
+ * compute W = V % U, then return W
+ */
+mpi_ptr_t
+_gcry_mpih_mod (mpi_ptr_t vp, mpi_size_t vsize,
+                mpi_ptr_t up, mpi_size_t usize)
+{
+  int secure;
+  mpi_ptr_t rp;
+  mpi_size_t i;
+
+  secure = _gcry_is_secure (vp);
+  rp = mpi_alloc_limb_space (usize, secure);
+  MPN_ZERO (rp, usize);
+
+  for (i = 0; i < vsize * BITS_PER_MPI_LIMB; i++)
+    {
+      unsigned int j = vsize * BITS_PER_MPI_LIMB - 1 - i;
+      unsigned int limbno = j / BITS_PER_MPI_LIMB;
+      unsigned int bitno = j % BITS_PER_MPI_LIMB;
+      mpi_limb_t limb = vp[limbno];
+      unsigned int the_bit = ((limb & (A_LIMB_1 << bitno)) ? 1 : 0);
+      mpi_limb_t underflow;
+      mpi_limb_t overflow;
+
+      overflow = _gcry_mpih_lshift (rp, rp, usize, 1);
+      rp[0] |= the_bit;
+
+      underflow = _gcry_mpih_sub_n (rp, rp, up, usize);
+      mpih_add_n_cond (rp, rp, up, usize, overflow ^ underflow);
+    }
+
+  return rp;
+}
+
+int
+_gcry_mpih_cmp_ui (mpi_ptr_t up, mpi_size_t usize, unsigned long v)
+{
+  int is_all_zero = 1;
+  mpi_size_t i;
+
+  for (i = 1; i < usize; i++)
+    is_all_zero &= (up[i] == 0);
+
+  if (is_all_zero)
+    return up[0] - v;
+  return 1;
+}
index 3ae84c3..74fbac3 100644 (file)
 #include "mpi-internal.h"
 #include "mod-source-info.h"
 
+
+#if SIZEOF_UNSIGNED_INT == 2
+# define MY_UINT_MAX 0xffff
+/* (visual check:      0123 ) */
+#elif SIZEOF_UNSIGNED_INT == 4
+# define MY_UINT_MAX 0xffffffff
+/* (visual check:      01234567 ) */
+#elif SIZEOF_UNSIGNED_INT == 8
+# define MY_UINT_MAX 0xffffffffffffffff
+/* (visual check:      0123456789abcdef ) */
+#else
+# error Need MY_UINT_MAX for this limb size
+#endif
+
+
 /* Constants allocated right away at startup.  */
 static gcry_mpi_t constants[MPI_NUMBER_OF_CONSTANTS];
 
+/* 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;
 
 
 const char *
@@ -177,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
@@ -346,11 +366,15 @@ _gcry_mpi_copy (gcry_mpi_t a)
     gcry_mpi_t b;
 
     if( a && (a->flags & 4) ) {
-       void *p = _gcry_is_secure(a->d)? xmalloc_secure ((a->sign+7)/8)
-                                       : xmalloc ((a->sign+7)/8);
-        if (a->d)
-          memcpy( p, a->d, (a->sign+7)/8 );
-       b = mpi_set_opaque( NULL, p, a->sign );
+        void *p = NULL;
+        if (a->sign) {
+            p = _gcry_is_secure(a->d)? xmalloc_secure ((a->sign+7)/8)
+                                     : xmalloc ((a->sign+7)/8);
+            if (a->d)
+                memcpy( p, a->d, (a->sign+7)/8 );
+        }
+        b = mpi_set_opaque( NULL, p, a->sign );
+        b->flags = a->flags;
         b->flags &= ~(16|32); /* Reset the immutable and constant flags.  */
     }
     else if( a ) {
@@ -498,23 +522,30 @@ _gcry_mpi_set_cond (gcry_mpi_t w, const gcry_mpi_t u, unsigned long set)
 {
   mpi_size_t i;
   mpi_size_t nlimbs = u->alloced;
-  mpi_limb_t mask = ((mpi_limb_t)0) - set;
-  mpi_limb_t x;
+  mpi_limb_t mask1 = vzero - set;
+  mpi_limb_t mask2 = set - vone;
+  mpi_limb_t xu;
+  mpi_limb_t xw;
+  mpi_limb_t *uu = u->d;
+  mpi_limb_t *uw = w->d;
 
   if (w->alloced != u->alloced)
     log_bug ("mpi_set_cond: different sizes\n");
 
   for (i = 0; i < nlimbs; i++)
     {
-      x = mask & (w->d[i] ^ u->d[i]);
-      w->d[i] = w->d[i] ^ x;
+      xu = uu[i];
+      xw = uw[i];
+      uw[i] = (xw & mask2) | (xu & mask1);
     }
 
-  x = mask & (w->nlimbs ^ u->nlimbs);
-  w->nlimbs = w->nlimbs ^ x;
+  xu = u->nlimbs;
+  xw = w->nlimbs;
+  w->nlimbs = (xw & mask2) | (xu & mask1);
 
-  x = mask & (w->sign ^ u->sign);
-  w->sign = w->sign ^ x;
+  xu = u->sign;
+  xw = w->sign;
+  w->sign = (xw & mask2) | (xu & mask1);
   return w;
 }
 
@@ -539,23 +570,27 @@ _gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u)
   return w;
 }
 
+/* If U is non-negative and small enough store it as an unsigned int
+ * at W.  If the value does not fit into an unsigned int or is
+ * negative return GPG_ERR_ERANGE.  Note that we return an unsigned
+ * int so that the value can be used with the bit test functions; in
+ * contrast the other _ui functions take an unsigned long so that on
+ * some platforms they may accept a larger value.  On error the value
+ * at W is not changed. */
 gcry_err_code_t
-_gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
+_gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u)
 {
-  gcry_err_code_t err = GPG_ERR_NO_ERROR;
-  unsigned long x = 0;
+  mpi_limb_t x;
 
-  if (w->nlimbs > 1)
-    err = GPG_ERR_TOO_LARGE;
-  else if (w->nlimbs == 1)
-    x = w->d[0];
-  else
-    x = 0;
+  if (u->nlimbs > 1 || u->sign)
+    return GPG_ERR_ERANGE;
 
-  if (! err)
-    *u = x;
+  x = (u->nlimbs == 1) ? u->d[0] : 0;
+  if (sizeof (x) > sizeof (unsigned int) && x > MY_UINT_MAX)
+    return GPG_ERR_ERANGE;
 
-  return err;
+  *w = x;
+  return 0;
 }
 
 
@@ -588,8 +623,12 @@ _gcry_mpi_swap_cond (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
 {
   mpi_size_t i;
   mpi_size_t nlimbs;
-  mpi_limb_t mask = ((mpi_limb_t)0) - swap;
-  mpi_limb_t x;
+  mpi_limb_t mask1 = vzero - swap;
+  mpi_limb_t mask2 = swap - vone;
+  mpi_limb_t *ua = a->d;
+  mpi_limb_t *ub = b->d;
+  mpi_limb_t xa;
+  mpi_limb_t xb;
 
   if (a->alloced > b->alloced)
     nlimbs = b->alloced;
@@ -600,18 +639,38 @@ _gcry_mpi_swap_cond (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap)
 
   for (i = 0; i < nlimbs; i++)
     {
-      x = mask & (a->d[i] ^ b->d[i]);
-      a->d[i] = a->d[i] ^ x;
-      b->d[i] = b->d[i] ^ x;
+      xa = ua[i];
+      xb = ub[i];
+      ua[i] = (xa & mask2) | (xb & mask1);
+      ub[i] = (xa & mask1) | (xb & mask2);
     }
 
-  x = mask & (a->nlimbs ^ b->nlimbs);
-  a->nlimbs = a->nlimbs ^ x;
-  b->nlimbs = b->nlimbs ^ x;
+  xa = a->nlimbs;
+  xb = b->nlimbs;
+  a->nlimbs = (xa & mask2) | (xb & mask1);
+  b->nlimbs = (xa & mask1) | (xb & mask2);
+
+  xa = a->sign;
+  xb = b->sign;
+  a->sign = (xa & mask2) | (xb & mask1);
+  b->sign = (xa & mask1) | (xb & mask2);
+}
+
+
+/****************
+ * Set bit N of A, when SET is 1.
+ * This implementation should be constant-time regardless of SET.
+ */
+void
+_gcry_mpi_set_bit_cond (gcry_mpi_t a, unsigned int n, unsigned long set)
+{
+  unsigned int limbno, bitno;
+  mpi_limb_t set_the_bit = !!set;
+
+  limbno = n / BITS_PER_MPI_LIMB;
+  bitno  = n % BITS_PER_MPI_LIMB;
 
-  x = mask & (a->sign ^ b->sign);
-  a->sign = a->sign ^ x;
-  b->sign = b->sign ^ x;
+  a->d[limbno] |= (set_the_bit<<bitno);
 }
 
 
diff --git a/mpi/pentium4/README b/mpi/pentium4/README
deleted file mode 100644 (file)
index 215fc7f..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-Copyright 2001 Free Software Foundation, Inc.
-
-This file is part of the GNU MP Library.
-
-The GNU MP Library 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.
-
-The GNU MP Library 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 the GNU MP Library; see the file COPYING.LIB.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
-
-
-
-
-                   INTEL PENTIUM-4 MPN SUBROUTINES
-
-
-This directory contains mpn functions optimized for Intel Pentium-4.
-
-The mmx subdirectory has routines using MMX instructions, the sse2
-subdirectory has routines using SSE2 instructions.  All P4s have these, the
-separate directories are just so configure can omit that code if the
-assembler doesn't support it.
-
-
-STATUS
-
-                                cycles/limb
-
-       mpn_add_n/sub_n            4 normal, 6 in-place
-
-       mpn_mul_1                  4 normal, 6 in-place
-       mpn_addmul_1               6
-       mpn_submul_1               7
-
-       mpn_mul_basecase           6 cycles/crossproduct (approx)
-
-       mpn_sqr_basecase           3.5 cycles/crossproduct (approx)
-                                   or 7.0 cycles/triangleproduct (approx)
-
-       mpn_l/rshift               1.75
-
-
-
-The shifts ought to be able to go at 1.5 c/l, but not much effort has been
-applied to them yet.
-
-In-place operations, and all addmul, submul, mul_basecase and sqr_basecase
-calls, suffer from pipeline anomalies associated with write combining and
-movd reads and writes to the same or nearby locations.  The movq
-instructions do not trigger the same hardware problems.  Unfortunately,
-using movq and splitting/combining seems to require too many extra
-instructions to help.  Perhaps future chip steppings will be better.
-
-
-
-NOTES
-
-The Pentium-4 pipeline "Netburst", provides for quite a number of surprises.
-Many traditional x86 instructions run very slowly, requiring use of
-alterative instructions for acceptable performance.
-
-adcl and sbbl are quite slow at 8 cycles for reg->reg.  paddq of 32-bits
-within a 64-bit mmx register seems better, though the combination
-paddq/psrlq when propagating a carry is still a 4 cycle latency.
-
-incl and decl should be avoided, instead use add $1 and sub $1.  Apparently
-the carry flag is not separately renamed, so incl and decl depend on all
-previous flags-setting instructions.
-
-shll and shrl have a 4 cycle latency, or 8 times the latency of the fastest
-integer instructions (addl, subl, orl, andl, and some more).  shldl and
-shrdl seem to have 13 and 15 cycles latency, respectively.  Bizarre.
-
-movq mmx -> mmx does have 6 cycle latency, as noted in the documentation.
-pxor/por or similar combination at 2 cycles latency can be used instead.
-The movq however executes in the float unit, thereby saving MMX execution
-resources.  With the right juggling, data moves shouldn't be on a dependent
-chain.
-
-L1 is write-through, but the write-combining sounds like it does enough to
-not require explicit destination prefetching.
-
-xmm registers so far haven't found a use, but not much effort has been
-expended.  A configure test for whether the operating system knows
-fxsave/fxrestor will be needed if they're used.
-
-
-
-REFERENCES
-
-Intel Pentium-4 processor manuals,
-
-       http://developer.intel.com/design/pentium4/manuals
-
-"Intel Pentium 4 Processor Optimization Reference Manual", Intel, 2001,
-order number 248966.  Available on-line:
-
-       http://developer.intel.com/design/pentium4/manuals/248966.htm
-
-
-
-----------------
-Local variables:
-mode: text
-fill-column: 76
-End:
diff --git a/mpi/pentium4/distfiles b/mpi/pentium4/distfiles
deleted file mode 100644 (file)
index b419f85..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-README
-
-
diff --git a/mpi/pentium4/mmx/distfiles b/mpi/pentium4/mmx/distfiles
deleted file mode 100644 (file)
index 8f0ea42..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-mpih-lshift.S
-mpih-rshift.S
diff --git a/mpi/pentium4/mmx/mpih-lshift.S b/mpi/pentium4/mmx/mpih-lshift.S
deleted file mode 100644 (file)
index e2dd184..0000000
+++ /dev/null
@@ -1,457 +0,0 @@
-/* Intel Pentium-4 mpn_lshift -- left shift.
- *
- * Copyright 2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_lshift( mpi_ptr_t wp,    (sp + 4)
- *                mpi_ptr_t up,        (sp + 8)
- *                mpi_size_t usize,    (sp + 12)
- *                unsigned cnt)        (sp + 16)
- *
- * P4 Willamette, Northwood: 1.75 cycles/limb
- * P4 Prescott:                     2.0 cycles/limb
- */
-
-.text
-       ALIGN (3)
-       .globl C_SYMBOL_NAME(_gcry_mpih_lshift)
-C_SYMBOL_NAME(_gcry_mpih_lshift:)
-
-       
-       pushl   %ebx
-       pushl   %edi
-
-
-       movl    20(%esp), %eax
-       movl    12(%esp), %edx
-
-       movl    16(%esp), %ebx
-       movl    24(%esp), %ecx
-
-       cmp     $5, %eax
-       jae     .Lunroll
-
-       movl    -4(%ebx,%eax,4), %edi   
-       decl    %eax
-
-       jnz     .Lsimple
-
-       shldl   %cl, %edi, %eax 
-
-       shll    %cl, %edi
-
-       movl    %edi, (%edx)            
-       popl    %edi                    
-
-       popl    %ebx
-
-       ret
-
-
-
-
-
-.Lsimple:
-       
-       
-       
-       
-       
-       
-       
-
-
-       movd    (%ebx,%eax,4), %mm5     
-
-       movd    %ecx, %mm6              
-       negl    %ecx
-
-       psllq   %mm6, %mm5
-       addl    $32, %ecx
-
-       movd    %ecx, %mm7
-       psrlq   $32, %mm5               
-
-
-.Lsimple_top:
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-       movq    -4(%ebx,%eax,4), %mm0
-       decl    %eax
-
-       psrlq   %mm7, %mm0
-
-       
-
-       movd    %mm0, 4(%edx,%eax,4)
-       jnz     .Lsimple_top
-
-
-       movd    (%ebx), %mm0
-
-       movd    %mm5, %eax
-       psllq   %mm6, %mm0
-
-       popl    %edi
-       popl    %ebx
-
-       movd    %mm0, (%edx)
-
-       emms
-
-       ret
-
-
-
-
-
-       .align  8, 0x90
-.Lunroll:
-       
-       
-       
-       
-       
-       
-       
-
-
-       movd    -4(%ebx,%eax,4), %mm5   
-       leal    (%ebx,%eax,4), %edi
-
-       movd    %ecx, %mm6              
-       andl    $4, %edi
-
-       psllq   %mm6, %mm5
-       jz      .Lstart_src_aligned
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-       movq    -8(%ebx,%eax,4), %mm0   
-
-       psllq   %mm6, %mm0
-       decl    %eax
-
-       psrlq   $32, %mm0
-
-       
-
-       movd    %mm0, (%edx,%eax,4)
-.Lstart_src_aligned:
-
-       movq    -8(%ebx,%eax,4), %mm1   
-       leal    (%edx,%eax,4), %edi
-
-       andl    $4, %edi
-       psrlq   $32, %mm5               
-
-       movq    -16(%ebx,%eax,4), %mm3  
-       jz      .Lstart_dst_aligned
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-       movq    %mm1, %mm0
-       addl    $32, %ecx               
-
-       psllq   %mm6, %mm0
-
-       movd    %ecx, %mm6
-       psrlq   $32, %mm0
-
-       
-
-       movd    %mm0, -4(%edx,%eax,4)
-       subl    $4, %edx
-.Lstart_dst_aligned:
-
-
-       psllq   %mm6, %mm1
-       negl    %ecx                    
-
-       addl    $64, %ecx               
-       movq    %mm3, %mm2
-
-       movd    %ecx, %mm7
-       subl    $8, %eax                
-
-       psrlq   %mm7, %mm3
-
-       por     %mm1, %mm3              
-       jc      .Lfinish
-
-
-       
-
-       .align  8, 0x90
-.Lunroll_loop:
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-       movq    8(%ebx,%eax,4), %mm0
-       psllq   %mm6, %mm2
-
-       movq    %mm0, %mm1
-       psrlq   %mm7, %mm0
-
-       movq    %mm3, 24(%edx,%eax,4)   
-       por     %mm2, %mm0
-
-       movq    (%ebx,%eax,4), %mm3     
-       psllq   %mm6, %mm1              
-
-       movq    %mm0, 16(%edx,%eax,4)
-       movq    %mm3, %mm2              
-
-       psrlq   %mm7, %mm3              
-       subl    $4, %eax
-
-       por     %mm1, %mm3              
-       jnc     .Lunroll_loop
-
-
-
-.Lfinish:
-       
-
-       testb   $2, %al
-
-       jz      .Lfinish_no_two
-
-       movq    8(%ebx,%eax,4), %mm0
-       psllq   %mm6, %mm2
-
-       movq    %mm0, %mm1
-       psrlq   %mm7, %mm0
-
-       movq    %mm3, 24(%edx,%eax,4)   
-       por     %mm2, %mm0
-
-       movq    %mm1, %mm2
-       movq    %mm0, %mm3
-
-       subl    $2, %eax
-.Lfinish_no_two:
-
-
-       
-       
-       
-       
-
-       testb   $1, %al
-       movd    %mm5, %eax      
-
-       popl    %edi
-       jz      .Lfinish_zero
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-
-       
-       
-       
-       
-
-
-       movd    (%ebx), %mm0
-       psllq   %mm6, %mm2
-
-       movq    %mm3, 12(%edx)
-       psllq   $32, %mm0
-
-       movq    %mm0, %mm1
-       psrlq   %mm7, %mm0
-
-       por     %mm2, %mm0
-       psllq   %mm6, %mm1
-
-       movq    %mm0, 4(%edx)
-       psrlq   $32, %mm1
-
-       andl    $32, %ecx
-       popl    %ebx
-
-       jz      .Lfinish_one_unaligned
-
-       movd    %mm1, (%edx)
-.Lfinish_one_unaligned:
-
-       emms
-
-       ret
-
-
-
-
-.Lfinish_zero:
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-
-       
-       
-
-
-       movq    %mm3, 8(%edx)
-       andl    $32, %ecx
-
-       psllq   %mm6, %mm2
-       jz      .Lfinish_zero_unaligned
-
-       movq    %mm2, (%edx)
-.Lfinish_zero_unaligned:
-
-       psrlq   $32, %mm2
-       popl    %ebx
-
-       movd    %mm5, %eax      
-
-       movd    %mm2, 4(%edx)
-
-       emms
-
-       ret
diff --git a/mpi/pentium4/mmx/mpih-rshift.S b/mpi/pentium4/mmx/mpih-rshift.S
deleted file mode 100644 (file)
index e3374e3..0000000
+++ /dev/null
@@ -1,453 +0,0 @@
-/* Intel Pentium-4 mpn_rshift -- right shift.
- *
- * Copyright 2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_rshift( mpi_ptr_t wp,    (sp + 4)
- *                mpi_ptr_t up,        (sp + 8)
- *                mpi_size_t usize,    (sp + 12)
- *                unsigned cnt)        (sp + 16)
- *
- * P4 Willamette, Northwood: 1.75 cycles/limb
- * P4 Prescott:                     2.0 cycles/limb
- */
-
-.text
-       ALIGN (3)
-       .globl C_SYMBOL_NAME(_gcry_mpih_rshift)
-C_SYMBOL_NAME(_gcry_mpih_rshift:)
-       pushl   %ebx
-       pushl   %edi
-
-
-       movl    20(%esp), %eax
-       movl    12(%esp), %edx
-
-       movl    16(%esp), %ebx
-       movl    24(%esp), %ecx
-
-       cmp     $5, %eax
-       jae     .Lunroll
-
-       decl    %eax
-       movl    (%ebx), %edi            
-
-       jnz     .Lsimple
-
-       shrdl   %cl, %edi, %eax 
-
-       shrl    %cl, %edi
-
-       movl    %edi, (%edx)            
-       popl    %edi                    
-
-       popl    %ebx
-
-       ret
-
-
-
-
-
-       .align  8, 0x90
-.Lsimple:
-       
-       
-       
-       
-       
-       
-       
-
-
-       movd    (%ebx), %mm5            
-       leal    (%ebx,%eax,4), %ebx     
-
-       movd    %ecx, %mm6              
-       leal    -4(%edx,%eax,4), %edx   
-
-       psllq   $32, %mm5
-       negl    %eax
-
-
-
-
-
-
-
-.Lsimple_top:
-       
-       
-       
-       
-       
-       
-       
-       
-
-       movq    (%ebx,%eax,4), %mm0
-       incl    %eax
-
-       psrlq   %mm6, %mm0
-
-       movd    %mm0, (%edx,%eax,4)
-       jnz     .Lsimple_top
-
-
-       movd    (%ebx), %mm0
-       psrlq   %mm6, %mm5              
-
-       psrlq   %mm6, %mm0
-       popl    %edi
-
-       movd    %mm5, %eax
-       popl    %ebx
-
-       movd    %mm0, 4(%edx)
-
-       emms
-
-       ret
-
-
-
-
-
-       .align  8, 0x90
-.Lunroll:
-       
-       
-       
-       
-       
-       
-       
-
-
-       movd    (%ebx), %mm5            
-       movl    $4, %edi
-
-       movd    %ecx, %mm6              
-       testl   %edi, %ebx
-
-       psllq   $32, %mm5
-       jz      .Lstart_src_aligned
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-       movq    (%ebx), %mm0            
-
-       psrlq   %mm6, %mm0
-       addl    $4, %ebx
-
-       decl    %eax
-
-       movd    %mm0, (%edx)
-       addl    $4, %edx
-.Lstart_src_aligned:
-
-
-       movq    (%ebx), %mm1
-       testl   %edi, %edx
-
-       psrlq   %mm6, %mm5              
-       jz      .Lstart_dst_aligned
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-       movq    %mm1, %mm0
-       addl    $32, %ecx               
-
-       psrlq   %mm6, %mm0
-
-       movd    %ecx, %mm6
-
-       movd    %mm0, (%edx)
-       addl    $4, %edx
-.Lstart_dst_aligned:
-
-
-       movq    8(%ebx), %mm3
-       negl    %ecx
-
-       movq    %mm3, %mm2              
-       addl    $64, %ecx
-
-       movd    %ecx, %mm7
-       psrlq   %mm6, %mm1
-
-       leal    -12(%ebx,%eax,4), %ebx
-       leal    -20(%edx,%eax,4), %edx
-
-       psllq   %mm7, %mm3
-       subl    $7, %eax                
-
-       por     %mm1, %mm3              
-       negl    %eax                    
-
-       jns     .Lfinish
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-       .align  8, 0x90
-.Lunroll_loop:
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-       movq    (%ebx,%eax,4), %mm0
-       psrlq   %mm6, %mm2
-
-       movq    %mm0, %mm1
-       psllq   %mm7, %mm0
-
-       movq    %mm3, -8(%edx,%eax,4)   
-       por     %mm2, %mm0
-
-       movq    8(%ebx,%eax,4), %mm3    
-       psrlq   %mm6, %mm1              
-
-       movq    %mm0, (%edx,%eax,4)
-       movq    %mm3, %mm2              
-
-       psllq   %mm7, %mm3              
-       addl    $4, %eax
-
-       por     %mm1, %mm3              
-       js      .Lunroll_loop
-
-
-.Lfinish:
-       
-
-       testb   $2, %al
-
-       jnz     .Lfinish_no_two
-
-       movq    (%ebx,%eax,4), %mm0
-       psrlq   %mm6, %mm2
-
-       movq    %mm0, %mm1
-       psllq   %mm7, %mm0
-
-       movq    %mm3, -8(%edx,%eax,4)   
-       por     %mm2, %mm0
-
-       movq    %mm1, %mm2
-       movq    %mm0, %mm3
-
-       addl    $2, %eax
-.Lfinish_no_two:
-
-
-       
-       
-       
-       
-
-       testb   $1, %al
-       popl    %edi
-
-       movd    %mm5, %eax      
-       jnz     .Lfinish_zero
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-
-       
-       
-       
-
-
-       movd    8(%ebx), %mm0
-       psrlq   %mm6, %mm2
-
-       movq    %mm0, %mm1
-       psllq   %mm7, %mm0
-
-       movq    %mm3, (%edx)
-       por     %mm2, %mm0
-
-       psrlq   %mm6, %mm1
-       andl    $32, %ecx
-
-       popl    %ebx
-       jz      .Lfinish_one_unaligned
-
-       
-       movd    %mm1, 16(%edx)
-.Lfinish_one_unaligned:
-
-       movq    %mm0, 8(%edx)
-
-       emms
-
-       ret
-
-
-
-
-.Lfinish_zero:
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-       
-
-
-       
-       
-       
-
-
-       movq    %mm3, 4(%edx)
-       psrlq   %mm6, %mm2
-
-       movd    %mm2, 12(%edx)
-       andl    $32, %ecx
-
-       popl    %ebx
-       jz      .Lfinish_zero_unaligned
-
-       movq    %mm2, 12(%edx)
-.Lfinish_zero_unaligned:
-
-       emms
-
-       ret
diff --git a/mpi/pentium4/sse2/distfiles b/mpi/pentium4/sse2/distfiles
deleted file mode 100644 (file)
index 7252cd7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-mpih-add1.S
-mpih-mul1.S
-mpih-mul2.S
-mpih-mul3.S
-mpih-sub1.S
diff --git a/mpi/pentium4/sse2/mpih-add1.S b/mpi/pentium4/sse2/mpih-add1.S
deleted file mode 100644 (file)
index 55ed663..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Intel Pentium-4 mpn_add_n -- mpn addition.
- *
- * Copyright 2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-       /*******************
- *  mpi_limb_t
- *  _gcry_mpih_add_n( mpi_ptr_t res_ptr,       (sp + 4)
- *                mpi_ptr_t s1_ptr,    (sp + 8)
- *                mpi_ptr_t s2_ptr,    (sp + 12)
- *                mpi_size_t size)     (sp + 16)
- *
- * P4 Willamette, Northwood: 4.0 cycles/limb if dst!=src1 and dst!=src2
- *                         6.0 cycles/limb if dst==src1 or dst==src2
- * P4 Prescott:                    >= 5 cycles/limb
- *
- * The 4 c/l achieved here isn't particularly good, but is better than 9 c/l
- * for a basic adc loop.
- */
-
-       TEXT
-       ALIGN (3)
-       GLOBL C_SYMBOL_NAME(_gcry_mpih_add_n)
-C_SYMBOL_NAME(_gcry_mpih_add_n:)
-
-       pxor    %mm0, %mm0
-       
-       movl    8(%esp), %eax           /* s1_ptr */
-       movl    %ebx, 8(%esp)           /* re-use parameter space */
-       movl    12(%esp), %ebx          /* res_ptr */
-       movl    4(%esp), %edx           /* s2_ptr */
-       movl    16(%esp), %ecx          /* size */
-
-       leal    (%eax,%ecx,4), %eax     /* src1 end */
-       leal    (%ebx,%ecx,4), %ebx     /* src2 end */
-       leal    (%edx,%ecx,4), %edx     /* dst end */
-       negl    %ecx                    /* -size */
-
-Ltop:
-/*
-       C eax   src1 end
-       C ebx   src2 end
-       C ecx   counter, limbs, negative
-       C edx   dst end
-       C mm0   carry bit
-*/
-
-       movd    (%eax,%ecx,4), %mm1
-       movd    (%ebx,%ecx,4), %mm2
-       paddq   %mm2, %mm1
-
-       paddq   %mm1, %mm0
-       movd    %mm0, (%edx,%ecx,4)
-
-       psrlq   $32, %mm0
-
-       addl    $1, %ecx
-       jnz     Ltop
-
-
-       movd    %mm0, %eax
-       movl    8(%esp), %ebx   /* restore saved EBX */
-       emms
-       ret
diff --git a/mpi/pentium4/sse2/mpih-mul1.S b/mpi/pentium4/sse2/mpih-mul1.S
deleted file mode 100644 (file)
index a0c98fb..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Intel Pentium-4 mpn_mul_1 -- Multiply a limb vector with a limb and store
- * the result in a second limb vector.
- *
- * Copyright 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_mul_1( mpi_ptr_t res_ptr,        (sp + 4)
- *               mpi_ptr_t s1_ptr,     (sp + 8)
- *               mpi_size_t s1_size,   (sp + 12)
- *               mpi_limb_t s2_limb)   (sp + 16)
- *
- *                           src != dst      src == dst
- * P6 model 9  (Banias)          ?.?
- * P6 model 13 (Dothan)          4.75            4.75
- * P4 model 0  (Willamette)      4.0             6.0
- * P4 model 1  (?)               4.0             6.0
- * P4 model 2  (Northwood)       4.0             6.0
- * P4 model 3  (Prescott)        ?.?             ?.?
- * P4 model 4  (Nocona)          ?.?             ?.?
- * Unfortunately when src==dst the write-combining described in
- * pentium4/README takes us up to 6 c/l.
- *
- */
-
-       TEXT
-       ALIGN (3)
-       GLOBL   C_SYMBOL_NAME(_gcry_mpih_mul_1)
-C_SYMBOL_NAME(_gcry_mpih_mul_1:); 
-
-       pxor    %mm0, %mm0
-
-.Lstart_1c:
-       movl    8(%esp), %eax
-       movd    16(%esp), %mm7
-       movl    4(%esp), %edx
-       movl    12(%esp), %ecx
-
-.Ltop:
-
-/*
-       C eax   src, incrementing
-       C ebx
-       C ecx   counter, size iterations
-       C edx   dst, incrementing
-       C
-       C mm0   carry limb
-       C mm7   multiplier
-*/
-       
-       movd    (%eax), %mm1
-       addl    $4, %eax
-       pmuludq %mm7, %mm1
-
-       paddq   %mm1, %mm0
-       movd    %mm0, (%edx)
-       addl    $4, %edx
-
-       psrlq   $32, %mm0
-
-       subl    $1, %ecx
-       jnz     .Ltop
-
-
-       movd    %mm0, %eax
-       emms
-       ret
-
diff --git a/mpi/pentium4/sse2/mpih-mul2.S b/mpi/pentium4/sse2/mpih-mul2.S
deleted file mode 100644 (file)
index f975adf..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Intel Pentium-4 mpn_addmul_1 -- Multiply a limb vector with a limb and add
- * the result to a second limb vector.
- *
- * Copyright 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr,      (sp + 4)
- *                  mpi_ptr_t s1_ptr,       (sp + 8)
- *                  mpi_size_t s1_size,     (sp + 12)
- *                  mpi_limb_t s2_limb)     (sp + 16)
- *
- * P3 model 9  (Banias)          ?.?
- * P3 model 13 (Dothan)          5.8
- * P4 model 0  (Willamette)      5.5
- * P4 model 1  (?)               5.5
- * P4 model 2  (Northwood)       5.5
- * P4 model 3  (Prescott)        6.0
- * P4 model 4  (Nocona)
- *
- * Only the carry limb propagation is on the dependent chain, but some other
- * Pentium4 pipeline magic brings down performance to 6 cycles/l from the
- * ideal 4 cycles/l.
- */
-
-
-       TEXT
-       ALIGN (4)
-       GLOBL   C_SYMBOL_NAME(_gcry_mpih_addmul_1)
-C_SYMBOL_NAME(_gcry_mpih_addmul_1:)
-
-       pxor    %mm4, %mm4
-.Lstart_1c:
-       movl    8(%esp), %eax
-       movl    12(%esp), %ecx
-       movl    4(%esp), %edx
-       movd    16(%esp), %mm7
-
-/*
-       C eax   src, incrementing ; 5B
-       C ecx   loop counter, decrementing
-       C edx   dst, incrementing
-       C
-       C mm4   carry, low 32-bits
-       C mm7   multiplier
-*/
-
-       movd            (%eax), %mm2    
-       pmuludq         %mm7, %mm2
-
-       shrl    $1, %ecx
-       jnc     .Leven
-
-       leal            4(%eax), %eax
-       movd            (%edx), %mm1
-       paddq           %mm2, %mm1
-       paddq           %mm1, %mm4
-       movd            %mm4, (%edx)
-       psrlq           $32, %mm4
-
-       testl   %ecx, %ecx
-       jz      .Lrtn
-       leal    4(%edx), %edx
-
-       movd            (%eax), %mm2    
-       pmuludq         %mm7, %mm2
-.Leven:
-       movd            4(%eax), %mm0   
-       movd            (%edx), %mm1    
-       pmuludq         %mm7, %mm0
-
-       subl    $1, %ecx
-       jz      .Lend
-.Lloop:
-       paddq           %mm2, %mm1      
-       movd            8(%eax), %mm2   
-       paddq           %mm1, %mm4      
-       movd            4(%edx), %mm3   
-       pmuludq         %mm7, %mm2
-       movd            %mm4, (%edx)
-       psrlq           $32, %mm4
-
-       paddq           %mm0, %mm3      
-       movd            12(%eax), %mm0  
-       paddq           %mm3, %mm4      
-       movd            8(%edx), %mm1   
-       pmuludq         %mm7, %mm0
-       movd            %mm4, 4(%edx)
-       psrlq           $32, %mm4
-
-       leal    8(%eax), %eax
-       leal    8(%edx), %edx
-       subl    $1, %ecx
-       jnz     .Lloop
-.Lend:
-       paddq           %mm2, %mm1      
-       paddq           %mm1, %mm4      
-       movd            4(%edx), %mm3   
-       movd            %mm4, (%edx)
-       psrlq           $32, %mm4
-       paddq           %mm0, %mm3      
-       paddq           %mm3, %mm4      
-       movd            %mm4, 4(%edx)
-       psrlq           $32, %mm4
-.Lrtn:
-       movd    %mm4, %eax
-       emms
-       ret
diff --git a/mpi/pentium4/sse2/mpih-mul3.S b/mpi/pentium4/sse2/mpih-mul3.S
deleted file mode 100644 (file)
index ebcd2a6..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Intel Pentium-4 mpn_submul_1 -- Multiply a limb vector with a limb and
- * subtract the result from a second limb vector.
- *
- * Copyright 2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- * mpi_limb_t
- * _gcry_mpih_submul_1( mpi_ptr_t res_ptr,      (sp + 4)
- *                  mpi_ptr_t s1_ptr,       (sp + 8)
- *                  mpi_size_t s1_size,     (sp + 12)
- *                  mpi_limb_t s2_limb)     (sp + 16)
- *
- * P4: 7 cycles/limb, unstable timing, at least on early Pentium4 silicon
- *    (stepping 10).
- *
- * This code is not particularly good at 7 c/l.  The dependent chain is only
- * 4 c/l and there's only 4 MMX unit instructions, so it's not clear why that
- * speed isn't achieved.
- *
- * The arrangements made here to get a two instruction dependent chain are
- * slightly subtle.  In the loop the carry (or borrow rather) is a negative
- * so that a paddq can be used to give a low limb ready to store, and a high
- * limb ready to become the new carry after a psrlq.
- *
- * If the carry was a simple twos complement negative then the psrlq shift
- * would need to bring in 0 bits or 1 bits according to whether the high was
- * zero or non-zero, since a non-zero value would represent a negative
- * needing sign extension.  That wouldn't be particularly easy to arrange and
- * certainly would add an instruction to the dependent chain, so instead an
- * offset is applied so that the high limb will be 0xFFFFFFFF+c.  With c in
- * the range -0xFFFFFFFF to 0, the value 0xFFFFFFFF+c is in the range 0 to
- * 0xFFFFFFFF and is therefore always positive and can always have 0 bits
- * shifted in, which is what psrlq does.
- *
- * The extra 0xFFFFFFFF must be subtracted before c is used, but that can be
- * done off the dependent chain.  The total adjustment then is to add
- * 0xFFFFFFFF00000000 to offset the new carry, and subtract
- * 0x00000000FFFFFFFF to remove the offset from the current carry, for a net
- * add of 0xFFFFFFFE00000001.  In the code this is applied to the destination
- * limb when fetched.
- *
- * It's also possible to view the 0xFFFFFFFF adjustment as a ones-complement
- * negative, which is how it's undone for the return value, but that doesn't
- * seem as clear.
-*/
-
-       TEXT
-       ALIGN (4)
-       GLOBL   C_SYMBOL_NAME(_gcry_mpih_submul_1)
-C_SYMBOL_NAME(_gcry_mpih_submul_1:)
-
-       pxor    %mm1, %mm1              
-
-.Lstart_1c:
-       movl    8(%esp), %eax
-       pcmpeqd %mm0, %mm0
-
-       movd    16(%esp), %mm7
-       pcmpeqd %mm6, %mm6
-
-       movl    4(%esp), %edx
-       psrlq   $32, %mm0               
-
-       movl    12(%esp), %ecx
-       psllq   $32, %mm6               
-
-       psubq   %mm0, %mm6              
-
-       psubq   %mm1, %mm0              
-
-/*
-       C eax   src, incrementing
-       C ebx
-       C ecx   loop counter, decrementing
-       C edx   dst, incrementing
-       C
-       C mm0   0xFFFFFFFF - borrow
-       C mm6   0xFFFFFFFE00000001
-       C mm7   multiplier
-*/
-       
-.Lloop:
-       movd    (%eax), %mm1            
-       leal    4(%eax), %eax
-       movd    (%edx), %mm2            
-       paddq   %mm6, %mm2              
-       pmuludq %mm7, %mm1
-       psubq   %mm1, %mm2              
-       paddq   %mm2, %mm0              
-       subl    $1, %ecx
-       movd    %mm0, (%edx)            
-       psrlq   $32, %mm0
-       leal    4(%edx), %edx
-       jnz     .Lloop
-
-       movd    %mm0, %eax
-       notl    %eax
-       emms
-       ret
diff --git a/mpi/pentium4/sse2/mpih-sub1.S b/mpi/pentium4/sse2/mpih-sub1.S
deleted file mode 100644 (file)
index 33900c7..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Intel Pentium-4 mpn_sub_n -- mpn subtraction.
- *
- * Copyright 2001, 2002 Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- */
-
-
-#include "sysdep.h"
-#include "asm-syntax.h"
-
-
-/*******************
- *  mpi_limb_t
- *  _gcry_mpih_sub_n( mpi_ptr_t res_ptr,       (sp + 4)
- *                mpi_ptr_t s1_ptr,    (sp + 8)
- *                mpi_ptr_t s2_ptr,    (sp + 12)
- *                mpi_size_t size)     (sp + 16)
- *
- * P4 Willamette, Northwood: 4.0 cycles/limb if dst!=src1 and dst!=src2
- *                          6.0 cycles/limb if dst==src1 or dst==src2
- * P4 Prescott:                     >= 5 cycles/limb
- *
- * The main loop code is 2x unrolled so that the carry bit can alternate
- * between mm0 and mm1.
- */
-
-
-.text
-       ALIGN (3)
-       .globl C_SYMBOL_NAME(_gcry_mpih_sub_n)
-C_SYMBOL_NAME(_gcry_mpih_sub_n:)
-
-       pxor    %mm0, %mm0
-.Lstart_nc:
-       movl    8(%esp), %eax
-       movl    %ebx, 8(%esp)
-       movl    12(%esp), %ebx
-       movl    4(%esp), %edx
-       movl    16(%esp), %ecx
-
-       leal    (%eax,%ecx,4), %eax     
-       leal    (%ebx,%ecx,4), %ebx     
-       leal    (%edx,%ecx,4), %edx     
-       negl    %ecx                    
-
-.Ltop:
-/*
-       C eax   src1 end
-       C ebx   src2 end
-       C ecx   counter, limbs, negative
-       C edx   dst end
-       C mm0   carry bit
-*/
-
-       movd    (%eax,%ecx,4), %mm1
-       movd    (%ebx,%ecx,4), %mm2
-       psubq   %mm2, %mm1
-
-       psubq   %mm0, %mm1
-       movd    %mm1, (%edx,%ecx,4)
-
-       psrlq   $63, %mm1
-
-       addl    $1, %ecx
-       jz      .Ldone_mm1
-
-       movd    (%eax,%ecx,4), %mm0
-       movd    (%ebx,%ecx,4), %mm2
-       psubq   %mm2, %mm0
-
-       psubq   %mm1, %mm0
-       movd    %mm0, (%edx,%ecx,4)
-
-       psrlq   $63, %mm0
-
-       addl    $1, %ecx
-       jnz     .Ltop
-
-
-       movd    %mm0, %eax
-       movl    8(%esp), %ebx
-       emms
-       ret
-
-
-
-.Ldone_mm1:
-       movd    %mm1, %eax
-       movl    8(%esp), %ebx
-       emms
-       ret
index 60af5b4..af97857 100644 (file)
@@ -39,31 +39,42 @@ random-system.c \
 rndjent.c \
 rndhw.c
 
-if USE_RANDOM_DAEMON
-librandom_la_SOURCES += random-daemon.c
-endif USE_RANDOM_DAEMON
-
-
 EXTRA_librandom_la_SOURCES = \
-rndlinux.c \
+rndgetentropy.c \
+rndoldlinux.c \
 rndegd.c \
 rndunix.c \
 rndw32.c  \
 rndw32ce.c \
+jitterentropy-gcd.c jitterentropy-gcd.h \
+jitterentropy-health.c jitterentropy-health.h \
+jitterentropy-noise.c jitterentropy-noise.h \
+jitterentropy-sha3.c jitterentropy-sha3.h \
+jitterentropy-timer.c jitterentropy-timer.h \
+jitterentropy-base.h \
 jitterentropy-base.c jitterentropy.h jitterentropy-base-user.h
 
-
 # The rndjent module needs to be compiled without optimization.  */
 if ENABLE_O_FLAG_MUNGING
-o_flag_munging = sed -e 's/-O\([1-9s][1-9s]*\)/-O0/g' -e 's/-Ofast/-O0/g'
+o_flag_munging = sed -e 's/-O\([1-9sg][1-9sg]*\)/-O0/g' -e 's/-Ofast/-O0/g'
 else
 o_flag_munging = cat
 endif
 
 rndjent.o: $(srcdir)/rndjent.c jitterentropy-base-user.h \
+           $(srcdir)/jitterentropy-gcd.c $(srcdir)/jitterentropy-gcd.h \
+           $(srcdir)/jitterentropy-health.c $(srcdir)/jitterentropy-health.h \
+           $(srcdir)/jitterentropy-noise.c $(srcdir)/jitterentropy-noise.h \
+           $(srcdir)/jitterentropy-sha3.c $(srcdir)/jitterentropy-sha3.h \
+           $(srcdir)/jitterentropy-timer.c $(srcdir)/jitterentropy-timer.h \
            $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
        `echo $(COMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
 
 rndjent.lo: $(srcdir)/rndjent.c jitterentropy-base-user.h \
+           $(srcdir)/jitterentropy-gcd.c $(srcdir)/jitterentropy-gcd.h \
+           $(srcdir)/jitterentropy-health.c $(srcdir)/jitterentropy-health.h \
+           $(srcdir)/jitterentropy-noise.c $(srcdir)/jitterentropy-noise.h \
+           $(srcdir)/jitterentropy-sha3.c $(srcdir)/jitterentropy-sha3.h \
+           $(srcdir)/jitterentropy-timer.c $(srcdir)/jitterentropy-timer.h \
             $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
        `echo $(LTCOMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
diff --git a/random/Makefile.in b/random/Makefile.in
deleted file mode 100644 (file)
index c23bb2e..0000000
+++ /dev/null
@@ -1,689 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Makefile for cipher modules
-# Copyright (C) 2008 Free Software Foundation, Inc.
-#
-# 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 <http://www.gnu.org/licenses/>.
-
-# Process this file with automake to produce Makefile.in
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-@USE_RANDOM_DAEMON_TRUE@am__append_1 = random-daemon.c
-subdir = random
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-       $(top_srcdir)/build-aux/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-CONFIG_CLEAN_VPATH_FILES =
-LTLIBRARIES = $(noinst_LTLIBRARIES)
-am__DEPENDENCIES_1 =
-am__librandom_la_SOURCES_DIST = random.c random.h rand-internal.h \
-       random-csprng.c random-drbg.c random-system.c rndjent.c \
-       rndhw.c random-daemon.c
-@USE_RANDOM_DAEMON_TRUE@am__objects_1 = random-daemon.lo
-am_librandom_la_OBJECTS = random.lo random-csprng.lo random-drbg.lo \
-       random-system.lo rndjent.lo rndhw.lo $(am__objects_1)
-librandom_la_OBJECTS = $(am_librandom_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-       $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(librandom_la_SOURCES) $(EXTRA_librandom_la_SOURCES)
-DIST_SOURCES = $(am__librandom_la_SOURCES_DIST) \
-       $(EXTRA_librandom_la_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-
-# Need to include ../src in addition to top_srcdir because gcrypt.h is
-# a built header.
-AM_CPPFLAGS = -I../src -I$(top_srcdir)/src
-AM_CFLAGS = $(GPG_ERROR_CFLAGS)
-noinst_LTLIBRARIES = librandom.la
-GCRYPT_MODULES = @GCRYPT_RANDOM@
-librandom_la_DEPENDENCIES = $(GCRYPT_MODULES)
-librandom_la_LIBADD = $(GCRYPT_MODULES)
-librandom_la_SOURCES = random.c random.h rand-internal.h \
-       random-csprng.c random-drbg.c random-system.c rndjent.c \
-       rndhw.c $(am__append_1)
-EXTRA_librandom_la_SOURCES = \
-rndlinux.c \
-rndegd.c \
-rndunix.c \
-rndw32.c  \
-rndw32ce.c \
-jitterentropy-base.c jitterentropy.h jitterentropy-base-user.h
-
-@ENABLE_O_FLAG_MUNGING_FALSE@o_flag_munging = cat
-
-# The rndjent module needs to be compiled without optimization.  */
-@ENABLE_O_FLAG_MUNGING_TRUE@o_flag_munging = sed -e 's/-O\([1-9s][1-9s]*\)/-O0/g' -e 's/-Ofast/-O0/g'
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-               && { if test -f $@; then exit 0; else break; fi; }; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu random/Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu random/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-
-clean-noinstLTLIBRARIES:
-       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
-       @list='$(noinst_LTLIBRARIES)'; \
-       locs=`for p in $$list; do echo $$p; done | \
-             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-             sort -u`; \
-       test -z "$$locs" || { \
-         echo rm -f $${locs}; \
-         rm -f $${locs}; \
-       }
-
-librandom.la: $(librandom_la_OBJECTS) $(librandom_la_DEPENDENCIES) $(EXTRA_librandom_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(LINK)  $(librandom_la_OBJECTS) $(librandom_la_LIBADD) $(LIBS)
-
-mostlyclean-compile:
-       -rm -f *.$(OBJEXT)
-
-distclean-compile:
-       -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jitterentropy-base.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-csprng.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-daemon.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-drbg.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-system.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndegd.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndhw.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndjent.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndlinux.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndunix.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndw32.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rndw32ce.Plo@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-       $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       set x; \
-       here=`pwd`; \
-       $(am__define_uniq_tagged_files); \
-       shift; \
-       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-         test -n "$$unique" || unique=$$empty_fix; \
-         if test $$# -gt 0; then \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             "$$@" $$unique; \
-         else \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             $$unique; \
-         fi; \
-       fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       $(am__define_uniq_tagged_files); \
-       test -z "$(CTAGS_ARGS)$$unique" \
-         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$unique
-
-GTAGS:
-       here=`$(am__cd) $(top_builddir) && pwd` \
-         && $(am__cd) $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-       list='$(am__tagged_files)'; \
-       case "$(srcdir)" in \
-         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-         *) sdir=$(subdir)/$(srcdir) ;; \
-       esac; \
-       for i in $$list; do \
-         if test -f "$$i"; then \
-           echo "$(subdir)/$$i"; \
-         else \
-           echo "$$sdir/$$i"; \
-         fi; \
-       done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LTLIBRARIES)
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
-       mostlyclean-am
-
-distclean: distclean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-       distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
-       clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
-       ctags-am distclean distclean-compile distclean-generic \
-       distclean-libtool distclean-tags distdir dvi dvi-am html \
-       html-am info info-am install install-am install-data \
-       install-data-am install-dvi install-dvi-am install-exec \
-       install-exec-am install-html install-html-am install-info \
-       install-info-am install-man install-pdf install-pdf-am \
-       install-ps install-ps-am install-strip installcheck \
-       installcheck-am installdirs maintainer-clean \
-       maintainer-clean-generic mostlyclean mostlyclean-compile \
-       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-       tags tags-am uninstall uninstall-am
-
-
-rndjent.o: $(srcdir)/rndjent.c jitterentropy-base-user.h \
-           $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
-       `echo $(COMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
-
-rndjent.lo: $(srcdir)/rndjent.c jitterentropy-base-user.h \
-            $(srcdir)/jitterentropy-base.c $(srcdir)/jitterentropy.h
-       `echo $(LTCOMPILE) -c $(srcdir)/rndjent.c | $(o_flag_munging) `
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
index 75dd768..389106f 100644 (file)
@@ -39,6 +39,9 @@
  * DAMAGE.
  */
 
+#include <fcntl.h>
+#include <limits.h>
+
 #ifndef GCRYPT_JITTERENTROPY_BASE_USER_H
 #define GCRYPT_JITTERENTROPY_BASE_USER_H
 
@@ -86,9 +89,9 @@ jent_get_nstime(u64 *out)
    * not rely on that extra little entropy.  */
   if (!clock_gettime (CLOCK_REALTIME, &tv))
     {
-      tmp = time.tv_sec;
+      tmp = tv.tv_sec;
       tmp = tmp << 32;
-      tmp = tmp | time.tv_nsec;
+      tmp = tmp | tv.tv_nsec;
     }
   else
     tmp = 0;
@@ -131,4 +134,174 @@ jent_fips_enabled(void)
 }
 
 
+static inline void jent_memset_secure(void *s, size_t n)
+{
+       wipememory (s, n);
+}
+
+static inline long jent_ncpu(void)
+{
+#ifdef _POSIX_SOURCE
+       long ncpu = sysconf(_SC_NPROCESSORS_ONLN);
+
+       if (ncpu == -1)
+               return -errno;
+
+       if (ncpu == 0)
+               return -EFAULT;
+
+       return ncpu;
+#else
+       return 1;
+#endif
+}
+
+#ifdef __linux__
+
+# if defined(_SC_LEVEL1_DCACHE_SIZE) &&                                        \
+     defined(_SC_LEVEL2_CACHE_SIZE) &&                                 \
+     defined(_SC_LEVEL3_CACHE_SIZE)
+
+static inline void jent_get_cachesize(long *l1, long *l2, long *l3)
+{
+       *l1 = sysconf(_SC_LEVEL1_DCACHE_SIZE);
+       *l2 = sysconf(_SC_LEVEL2_CACHE_SIZE);
+       *l3 = sysconf(_SC_LEVEL3_CACHE_SIZE);
+}
+
+# else
+
+static inline void jent_get_cachesize(long *l1, long *l2, long *l3)
+{
+#define JENT_SYSFS_CACHE_DIR "/sys/devices/system/cpu/cpu0/cache"
+       long val;
+       unsigned int i;
+       char buf[10], file[50];
+       int fd = 0;
+
+       /* Iterate over all caches */
+       for (i = 0; i < 4; i++) {
+               unsigned int shift = 0;
+               char *ext;
+
+               /*
+                * Check the cache type - we are only interested in Unified
+                * and Data caches.
+                */
+               memset(buf, 0, sizeof(buf));
+               snprintf(file, sizeof(file), "%s/index%u/type",
+                        JENT_SYSFS_CACHE_DIR, i);
+               fd = open(file, O_RDONLY);
+               if (fd < 0)
+                       continue;
+               while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
+               close(fd);
+               buf[sizeof(buf) - 1] = '\0';
+
+               if (strncmp(buf, "Data", 4) && strncmp(buf, "Unified", 7))
+                       continue;
+
+               /* Get size of cache */
+               memset(buf, 0, sizeof(buf));
+               snprintf(file, sizeof(file), "%s/index%u/size",
+                        JENT_SYSFS_CACHE_DIR, i);
+
+               fd = open(file, O_RDONLY);
+               if (fd < 0)
+                       continue;
+               while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR);
+               close(fd);
+               buf[sizeof(buf) - 1] = '\0';
+
+               ext = strstr(buf, "K");
+               if (ext) {
+                       shift = 10;
+                       ext = '\0';
+               } else {
+                       ext = strstr(buf, "M");
+                       if (ext) {
+                               shift = 20;
+                               ext = '\0';
+                       }
+               }
+
+               val = strtol(buf, NULL, 10);
+               if (val == LONG_MAX)
+                       continue;
+               val <<= shift;
+
+               if (!*l1)
+                       *l1 = val;
+               else if (!*l2)
+                       *l2 = val;
+               else {
+                       *l3 = val;
+                       break;
+               }
+       }
+#undef JENT_SYSFS_CACHE_DIR
+}
+
+# endif
+
+static inline uint32_t jent_cache_size_roundup(void)
+{
+       static int checked = 0;
+       static uint32_t cache_size = 0;
+
+       if (!checked) {
+               long l1 = 0, l2 = 0, l3 = 0;
+
+               jent_get_cachesize(&l1, &l2, &l3);
+               checked = 1;
+
+               /* Cache size reported by system */
+               if (l1 > 0)
+                       cache_size += (uint32_t)l1;
+               if (l2 > 0)
+                       cache_size += (uint32_t)l2;
+               if (l3 > 0)
+                       cache_size += (uint32_t)l3;
+
+               /*
+                * Force the output_size to be of the form
+                * (bounding_power_of_2 - 1).
+                */
+               cache_size |= (cache_size >> 1);
+               cache_size |= (cache_size >> 2);
+               cache_size |= (cache_size >> 4);
+               cache_size |= (cache_size >> 8);
+               cache_size |= (cache_size >> 16);
+
+               if (cache_size == 0)
+                       return 0;
+
+               /*
+                * Make the output_size the smallest power of 2 strictly
+                * greater than cache_size.
+                */
+               cache_size++;
+       }
+
+       return cache_size;
+}
+
+#else /* __linux__ */
+
+static inline uint32_t jent_cache_size_roundup(void)
+{
+       return 0;
+}
+
+#endif /* __linux__ */
+
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+#include <sched.h>
+
+static inline void jent_yield(void)
+{
+       sched_yield();
+}
+#endif
+
 #endif /* GCRYPT_JITTERENTROPY_BASE_USER_H */
index dc907b2..cf7630d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Non-physical true random number generator based on timing jitter.
  *
- * Copyright Stephan Mueller <smueller@chronox.de>, 2014 - 2017
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014 - 2021
  *
  * Design
  * ======
  * Interface
  * =========
  *
- * See documentation in doc/ folder.
- *
- * License
- * =======
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, and the entire permission notice in its entirety,
- *    including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
+ * See documentation in jitterentropy(3) man page.
  *
- * ALTERNATIVELY, this product may be distributed under the terms of
- * the GNU General Public License, in which case the provisions of the GPL2 are
- * required INSTEAD OF the above restrictions.  (This clause is
- * necessary due to a potential bad interaction between the GPL and
- * the restrictions contained in a BSD-style copyright.)
+ * License: see LICENSE file in root directory
  *
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * DAMAGE.
  */
 
-#undef _FORTIFY_SOURCE
-#pragma GCC optimize ("O0")
-
 #include "jitterentropy.h"
 
-#ifndef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
- /* only check optimization in a compilation for real work */
- #ifdef __OPTIMIZE__
-  #error "The CPU Jitter random number generator must not be compiled with optimizations. See documentation. Use the compiler switch -O0 for compiling jitterentropy-base.c."
- #endif
-#endif
+#include "jitterentropy-base.h"
+#include "jitterentropy-gcd.h"
+#include "jitterentropy-health.h"
+#include "jitterentropy-noise.h"
+#include "jitterentropy-timer.h"
+#include "jitterentropy-sha3.h"
 
-#define MAJVERSION 2 /* API / ABI incompatible changes, functional changes that
+#define MAJVERSION 3 /* API / ABI incompatible changes, functional changes that
                      * require consumer to be updated (as long as this number
                      * is zero, the API is not considered stable and can
                      * change without a bump of the major version) */
-#define MINVERSION 1 /* API compatible, ABI may change, functional
+#define MINVERSION 3 /* API compatible, ABI may change, functional
                      * enhancements only, consumer can be left unchanged if
                      * enhancements are not considered */
 #define PATCHLEVEL 0 /* API / ABI compatible, no functional changes, no
                      * enhancements, bug fixes only */
 
+/***************************************************************************
+ * Jitter RNG Static Definitions
+ *
+ * None of the following should be altered
+ ***************************************************************************/
+
+#ifdef __OPTIMIZE__
+ #error "The CPU Jitter random number generator must not be compiled with optimizations. See documentation. Use the compiler switch -O0 for compiling jitterentropy.c."
+#endif
+
+/*
+ * JENT_POWERUP_TESTLOOPCOUNT needs some loops to identify edge
+ * systems. 100 is definitely too little.
+ *
+ * SP800-90B requires at least 1024 initial test cycles.
+ */
+#define JENT_POWERUP_TESTLOOPCOUNT 1024
+
 /**
  * jent_version() - Return machine-usable version number of jent library
  *
@@ -82,7 +77,7 @@
  * The result of this function can be used in comparing the version number
  * in a calling program if version-specific calls need to be make.
  *
- * Return: Version number of kcapi library
+ * @return Version number of jitterentropy library
  */
 JENT_PRIVATE_STATIC
 unsigned int jent_version(void)
@@ -96,412 +91,55 @@ unsigned int jent_version(void)
        return version;
 }
 
-/**
- * Update of the loop count used for the next round of
- * an entropy collection.
- *
- * Input:
- * @ec entropy collector struct -- may be NULL
- * @bits is the number of low bits of the timer to consider
- * @min is the number of bits we shift the timer value to the right at
- *     the end to make sure we have a guaranteed minimum value
- *
- * @return Newly calculated loop counter
- */
-static uint64_t jent_loop_shuffle(struct rand_data *ec,
-                                 unsigned int bits, unsigned int min)
-{
-       uint64_t time = 0;
-       uint64_t shuffle = 0;
-       unsigned int i = 0;
-       unsigned int mask = (1<<bits) - 1;
-
-       jent_get_nstime(&time);
-       /*
-        * Mix the current state of the random number into the shuffle
-        * calculation to balance that shuffle a bit more.
-        */
-       if (ec)
-               time ^= ec->data;
-       /*
-        * We fold the time value as much as possible to ensure that as many
-        * bits of the time stamp are included as possible.
-        */
-       for (i = 0; (DATA_SIZE_BITS / bits) > i; i++) {
-               shuffle ^= time & mask;
-               time = time >> bits;
-       }
-
-       /*
-        * We add a lower boundary value to ensure we have a minimum
-        * RNG loop count.
-        */
-       return (shuffle + (1<<min));
-}
-
-/***************************************************************************
- * Noise sources
- ***************************************************************************/
-
-/**
- * CPU Jitter noise source -- this is the noise source based on the CPU
- *                           execution time jitter
- *
- * This function injects the individual bits of the time value into the
- * entropy pool using an LFSR.
- *
- * The code is deliberately inefficient with respect to the bit shifting
- * and shall stay that way. This function is the root cause why the code
- * shall be compiled without optimization. This function not only acts as
- * folding operation, but this function's execution is used to measure
- * the CPU execution time jitter. Any change to the loop in this function
- * implies that careful retesting must be done.
- *
- * Input:
- * @ec entropy collector struct -- may be NULL
- * @time time stamp to be injected
- * @loop_cnt if a value not equal to 0 is set, use the given value as number of
- *          loops to perform the folding
- *
- * Output:
- * updated ec->data
- *
- * @return Number of loops the folding operation is performed
- */
-static uint64_t jent_lfsr_time(struct rand_data *ec, uint64_t time,
-                              uint64_t loop_cnt)
-{
-       unsigned int i;
-       uint64_t j = 0;
-       uint64_t new = 0;
-#define MAX_FOLD_LOOP_BIT 4
-#define MIN_FOLD_LOOP_BIT 0
-       uint64_t fold_loop_cnt =
-               jent_loop_shuffle(ec, MAX_FOLD_LOOP_BIT, MIN_FOLD_LOOP_BIT);
-
-       /*
-        * testing purposes -- allow test app to set the counter, not
-        * needed during runtime
-        */
-       if (loop_cnt)
-               fold_loop_cnt = loop_cnt;
-       for (j = 0; j < fold_loop_cnt; j++) {
-               new = ec->data;
-               for (i = 1; (DATA_SIZE_BITS) >= i; i++) {
-                       uint64_t tmp = time << (DATA_SIZE_BITS - i);
-
-                       tmp = tmp >> (DATA_SIZE_BITS - 1);
-
-                       /*
-                       * Fibonacci LSFR with polynomial of
-                       *  x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is
-                       *  primitive according to
-                       *   http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf
-                       * (the shift values are the polynomial values minus one
-                       * due to counting bits from 0 to 63). As the current
-                       * position is always the LSB, the polynomial only needs
-                       * to shift data in from the left without wrap.
-                       */
-                       new ^= tmp;
-                       new ^= ((new >> 63) & 1);
-                       new ^= ((new >> 60) & 1);
-                       new ^= ((new >> 55) & 1);
-                       new ^= ((new >> 30) & 1);
-                       new ^= ((new >> 27) & 1);
-                       new ^= ((new >> 22) & 1);
-                       new = rol64(new, 1);
-               }
-       }
-       ec->data = new;
-
-       return fold_loop_cnt;
-}
-
-/**
- * Memory Access noise source -- this is a noise source based on variations in
- *                              memory access times
- *
- * This function performs memory accesses which will add to the timing
- * variations due to an unknown amount of CPU wait states that need to be
- * added when accessing memory. The memory size should be larger than the L1
- * caches as outlined in the documentation and the associated testing.
- *
- * The L1 cache has a very high bandwidth, albeit its access rate is  usually
- * slower than accessing CPU registers. Therefore, L1 accesses only add minimal
- * variations as the CPU has hardly to wait. Starting with L2, significant
- * variations are added because L2 typically does not belong to the CPU any more
- * and therefore a wider range of CPU wait states is necessary for accesses.
- * L3 and real memory accesses have even a wider range of wait states. However,
- * to reliably access either L3 or memory, the ec->mem memory must be quite
- * large which is usually not desirable.
- *
- * Input:
- * @ec Reference to the entropy collector with the memory access data -- if
- *     the reference to the memory block to be accessed is NULL, this noise
- *     source is disabled
- * @loop_cnt if a value not equal to 0 is set, use the given value as number of
- *          loops to perform the folding
- *
- * @return Number of memory access operations
- */
-static unsigned int jent_memaccess(struct rand_data *ec, uint64_t loop_cnt)
-{
-       unsigned int wrap = 0;
-       uint64_t i = 0;
-#define MAX_ACC_LOOP_BIT 7
-#define MIN_ACC_LOOP_BIT 0
-       uint64_t acc_loop_cnt =
-               jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
-
-       if (NULL == ec || NULL == ec->mem)
-               return 0;
-       wrap = ec->memblocksize * ec->memblocks;
-
-       /*
-        * testing purposes -- allow test app to set the counter, not
-        * needed during runtime
-        */
-       if (loop_cnt)
-               acc_loop_cnt = loop_cnt;
-
-       for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) {
-               unsigned char *tmpval = ec->mem + ec->memlocation;
-               /*
-                * memory access: just add 1 to one byte,
-                * wrap at 255 -- memory access implies read
-                * from and write to memory location
-                */
-               *tmpval = (*tmpval + 1) & 0xff;
-               /*
-                * Addition of memblocksize - 1 to pointer
-                * with wrap around logic to ensure that every
-                * memory location is hit evenly
-                */
-               ec->memlocation = ec->memlocation + ec->memblocksize - 1;
-               ec->memlocation = ec->memlocation % wrap;
-       }
-       return i;
-}
-
 /***************************************************************************
- * Start of entropy processing logic
+ * Helper
  ***************************************************************************/
 
-/**
- * Stuck test by checking the:
- *     1st derivation of the jitter measurement (time delta)
- *     2nd derivation of the jitter measurement (delta of time deltas)
- *     3rd derivation of the jitter measurement (delta of delta of time deltas)
- *
- * All values must always be non-zero.
- *
- * Input:
- * @ec Reference to entropy collector
- * @current_delta Jitter time delta
- *
- * @return
- *     0 jitter measurement not stuck (good bit)
- *     1 jitter measurement stuck (reject bit)
- */
-static int jent_stuck(struct rand_data *ec, uint64_t current_delta)
-{
-       int64_t delta2 = ec->last_delta - current_delta;
-       int64_t delta3 = delta2 - ec->last_delta2;
-
-       ec->last_delta = current_delta;
-       ec->last_delta2 = delta2;
-
-       if (!current_delta || !delta2 || !delta3)
-               return 1;
-
-       return 0;
-}
-
-/**
- * This is the heart of the entropy generation: calculate time deltas and
- * use the CPU jitter in the time deltas. The jitter is injected into the
- * entropy pool.
- *
- * WARNING: ensure that ->prev_time is primed before using the output
- *         of this function! This can be done by calling this function
- *         and not using its result.
- *
- * Input:
- * @entropy_collector Reference to entropy collector
- *
- * @return: result of stuck test
- */
-static int jent_measure_jitter(struct rand_data *ec)
+/* Calculate log2 of given value assuming that the value is a power of 2 */
+static inline unsigned int jent_log2_simple(unsigned int val)
 {
-       uint64_t time = 0;
-       uint64_t current_delta = 0;
-       int stuck;
-
-       /* Invoke one noise source before time measurement to add variations */
-       jent_memaccess(ec, 0);
-
-       /*
-        * Get time stamp and calculate time delta to previous
-        * invocation to measure the timing variations
-        */
-       jent_get_nstime(&time);
-       current_delta = time - ec->prev_time;
-       ec->prev_time = time;
-
-       /* Now call the next noise sources which also injects the data */
-       jent_lfsr_time(ec, current_delta, 0);
-
-       /* Check whether we have a stuck measurement. */
-       stuck = jent_stuck(ec, current_delta);
+       unsigned int idx = 0;
 
-       /*
-        * Rotate the data buffer by a prime number (any odd number would
-        * do) to ensure that every bit position of the input time stamp
-        * has an even chance of being merged with a bit position in the
-        * entropy pool. We do not use one here as the adjacent bits in
-        * successive time deltas may have some form of dependency. The
-        * chosen value of 7 implies that the low 7 bits of the next
-        * time delta value is concatenated with the current time delta.
-        */
-       if (!stuck)
-               ec->data = rol64(ec->data, 7);
-
-       return stuck;
+       while (val >>= 1)
+               idx++;
+       return idx;
 }
 
-/**
- * Shuffle the pool a bit by mixing some value with a bijective function (XOR)
- * into the pool.
- *
- * The function generates a mixer value that depends on the bits set and the
- * location of the set bits in the random number generated by the entropy
- * source. Therefore, based on the generated random number, this mixer value
- * can have 2**64 different values. That mixer value is initialized with the
- * first two SHA-1 constants. After obtaining the mixer value, it is XORed into
- * the random number.
- *
- * The mixer value is not assumed to contain any entropy. But due to the XOR
- * operation, it can also not destroy any entropy present in the entropy pool.
- *
- * Input:
- * @entropy_collector Reference to entropy collector
- */
-static void jent_stir_pool(struct rand_data *entropy_collector)
+/* Increase the memory size by one step */
+static inline unsigned int jent_update_memsize(unsigned int flags)
 {
-       /*
-        * to shut up GCC on 32 bit, we have to initialize the 64 variable
-        * with two 32 bit variables
-        */
-       union c {
-               uint64_t uint64;
-               uint32_t uint32[2];
-       };
-       /*
-        * This constant is derived from the first two 32 bit initialization
-        * vectors of SHA-1 as defined in FIPS 180-4 section 5.3.1
-        */
-       union c constant;
-       /*
-        * The start value of the mixer variable is derived from the third
-        * and fourth 32 bit initialization vector of SHA-1 as defined in
-        * FIPS 180-4 section 5.3.1
-        */
-       union c mixer;
-       unsigned int i = 0;
+       unsigned int global_max = JENT_FLAGS_TO_MAX_MEMSIZE(
+                                                       JENT_MAX_MEMSIZE_MAX);
+       unsigned int max;
 
-       /* Ensure that the function implements a constant time operation. */
-       union c throw_away;
+       max = JENT_FLAGS_TO_MAX_MEMSIZE(flags);
 
-       /*
-        * Store the SHA-1 constants in reverse order to make up the 64 bit
-        * value -- this applies to a little endian system, on a big endian
-        * system, it reverses as expected. But this really does not matter
-        * as we do not rely on the specific numbers. We just pick the SHA-1
-        * constants as they have a good mix of bit set and unset.
-        */
-       constant.uint32[1] = 0x67452301;
-       constant.uint32[0] = 0xefcdab89;
-       mixer.uint32[1] = 0x98badcfe;
-       mixer.uint32[0] = 0x10325476;
-
-       for (i = 0; i < DATA_SIZE_BITS; i++) {
+       if (!max) {
                /*
-                * get the i-th bit of the input random number and only XOR
-                * the constant into the mixer value when that bit is set
+                * The safe starting value is the amount of memory we allocated
+                * last round.
                 */
-               if ((entropy_collector->data >> i) & 1)
-                       mixer.uint64 ^= constant.uint64;
-               else
-                       throw_away.uint64 ^= constant.uint64;
-               mixer.uint64 = rol64(mixer.uint64, 1);
+               max = jent_log2_simple(JENT_MEMORY_SIZE);
+               /* Adjust offset */
+               max = (max > JENT_MAX_MEMSIZE_OFFSET) ?
+                       max - JENT_MAX_MEMSIZE_OFFSET : 0;
+       } else {
+               max++;
        }
-       entropy_collector->data ^= mixer.uint64;
-}
 
-/**
- * Generator of one 64 bit random number
- * Function fills rand_data->data
- *
- * Input:
- * @ec Reference to entropy collector
- */
-static void jent_gen_entropy(struct rand_data *ec)
-{
-       unsigned int k = 0;
-
-       /* priming of the ->prev_time value */
-       jent_measure_jitter(ec);
+       max = (max > global_max) ? global_max : max;
 
-       while (1) {
-               /* If a stuck measurement is received, repeat measurement */
-               if (jent_measure_jitter(ec))
-                       continue;
+       /* Clear out the max size */
+       flags &= ~JENT_MAX_MEMSIZE_MASK;
+       /* Set the freshly calculated max size */
+       flags |= JENT_MAX_MEMSIZE_TO_FLAGS(max);
 
-               /*
-                * We multiply the loop value with ->osr to obtain the
-                * oversampling rate requested by the caller
-                */
-               if (++k >= (DATA_SIZE_BITS * ec->osr))
-                       break;
-       }
-       if (ec->stir)
-               jent_stir_pool(ec);
+       return flags;
 }
 
-/**
- * The continuous test required by FIPS 140-2 -- the function automatically
- * primes the test if needed.
- *
- * Return:
- * 0 if FIPS test passed
- * < 0 if FIPS test failed
- */
-static int jent_fips_test(struct rand_data *ec)
-{
-       if (ec->fips_enabled == -1)
-               return 0;
-
-       if (ec->fips_enabled == 0) {
-               if (!jent_fips_enabled()) {
-                       ec->fips_enabled = -1;
-                       return 0;
-               } else
-                       ec->fips_enabled = 1;
-       }
-
-       /* prime the FIPS test */
-       if (!ec->old_data) {
-               ec->old_data = ec->data;
-               jent_gen_entropy(ec);
-       }
-
-       if (ec->data == ec->old_data)
-               return -1;
-
-       ec->old_data = ec->data;
-
-       return 0;
-}
+/***************************************************************************
+ * Random Number Generation
+ ***************************************************************************/
 
 /**
  * Entry function: Obtain entropy for the caller.
@@ -513,34 +151,50 @@ static int jent_fips_test(struct rand_data *ec)
  * This function truncates the last 64 bit entropy value output to the exact
  * size specified by the caller.
  *
- * Input:
- * @ec Reference to entropy collector
- * @data pointer to buffer for storing random data -- buffer must already
- *        exist
- * @len size of the buffer, specifying also the requested number of random
- *       in bytes
+ * @ec [in] Reference to entropy collector
+ * @data [out] pointer to buffer for storing random data -- buffer must
+ *            already exist
+ * @len [in] size of the buffer, specifying also the requested number of random
+ *          in bytes
  *
  * @return number of bytes returned when request is fulfilled or an error
  *
  * The following error codes can occur:
  *     -1      entropy_collector is NULL
- *     -2      FIPS test failed
+ *     -2      RCT failed
+ *     -3      APT test failed
+ *     -4      The timer cannot be initialized
+ *     -5      LAG failure
  */
 JENT_PRIVATE_STATIC
 ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len)
 {
        char *p = data;
        size_t orig_len = len;
+       int ret = 0;
 
        if (NULL == ec)
                return -1;
 
-       while (0 < len) {
+       if (jent_notime_settick(ec))
+               return -4;
+
+       while (len > 0) {
                size_t tocopy;
+               unsigned int health_test_result;
+
+               jent_random_data(ec);
 
-               jent_gen_entropy(ec);
-               if (jent_fips_test(ec))
-                       return -2;
+               if ((health_test_result = jent_health_failure(ec))) {
+                       if (health_test_result & JENT_RCT_FAILURE)
+                               ret = -2;
+                       else if (health_test_result & JENT_APT_FAILURE)
+                               ret = -3;
+                       else
+                               ret = -5;
+
+                       goto err;
+               }
 
                if ((DATA_SIZE_BITS / 8) < len)
                        tocopy = (DATA_SIZE_BITS / 8);
@@ -567,91 +221,349 @@ ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len)
         * memory protects the entropy pool. Moreover, note that using this
         * call reduces the speed of the RNG by up to half
         */
-#ifndef CONFIG_CRYPTO_CPU_JITTERENTROPY_SECURE_MEMORY
-       jent_gen_entropy(ec);
+#ifndef JENT_CPU_JITTERENTROPY_SECURE_MEMORY
+       jent_random_data(ec);
 #endif
-       return orig_len;
+
+err:
+       jent_notime_unsettick(ec);
+       return ret ? ret : (ssize_t)orig_len;
+}
+
+static struct rand_data *_jent_entropy_collector_alloc(unsigned int osr,
+                                                      unsigned int flags);
+
+/**
+ * Entry function: Obtain entropy for the caller.
+ *
+ * This is a service function to jent_read_entropy() with the difference
+ * that it automatically re-allocates the entropy collector if a health
+ * test failure is observed. Before reallocation, a new power-on health test
+ * is performed. The allocation of the new entropy collector automatically
+ * increases the OSR by one. This is done based on the idea that a health
+ * test failure indicates that the assumed entropy rate is too high.
+ *
+ * Note the function returns with an health test error if the OSR is
+ * getting too large. If an error is returned by this function, the Jitter RNG
+ * is not safe to be used on the current system.
+ *
+ * @ec [in] Reference to entropy collector - this is a double pointer as
+ *         The entropy collector may be freed and reallocated.
+ * @data [out] pointer to buffer for storing random data -- buffer must
+ *            already exist
+ * @len [in] size of the buffer, specifying also the requested number of random
+ *          in bytes
+ *
+ * @return see jent_read_entropy()
+ */
+JENT_PRIVATE_STATIC
+ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len)
+{
+       char *p = data;
+       size_t orig_len = len;
+       ssize_t ret = 0;
+
+       if (!ec)
+               return -1;
+
+       while (len > 0) {
+               unsigned int osr, flags, max_mem_set;
+
+               ret = jent_read_entropy(*ec, p, len);
+
+               switch (ret) {
+               case -1:
+               case -4:
+                       return ret;
+               case -2:
+               case -3:
+               case -5:
+                       osr = (*ec)->osr + 1;
+                       flags = (*ec)->flags;
+                       max_mem_set = (*ec)->max_mem_set;
+
+                       /* generic arbitrary cutoff */
+                       if (osr > 20)
+                               return ret;
+
+                       /*
+                        * If the caller did not set any specific maximum value
+                        * let the Jitter RNG increase the maximum memory by
+                        * one step.
+                        */
+                       if (!max_mem_set)
+                               flags = jent_update_memsize(flags);
+
+                       /*
+                        * re-allocate entropy collector with higher OSR and
+                        * memory size
+                        */
+                       jent_entropy_collector_free(*ec);
+
+                       /* Perform new health test with updated OSR */
+                       if (jent_entropy_init_ex(osr, flags))
+                               return -1;
+
+                       *ec = _jent_entropy_collector_alloc(osr, flags);
+                       if (!*ec)
+                               return -1;
+
+                       /* Remember whether caller configured memory size */
+                       (*ec)->max_mem_set = !!max_mem_set;
+
+                       break;
+
+               default:
+                       len -= (size_t)ret;
+                       p += (size_t)ret;
+               }
+       }
+
+       return (ssize_t)orig_len;
 }
 
 /***************************************************************************
  * Initialization logic
  ***************************************************************************/
 
-JENT_PRIVATE_STATIC
-struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
-                                              unsigned int flags)
+/*
+ * Obtain memory size to allocate for memory access variations.
+ *
+ * The maximum variations we can get from the memory access is when we allocate
+ * a bit more memory than we have as data cache. But allocating as much
+ * memory as we have as data cache might strain the resources on the system
+ * more than necessary.
+ *
+ * On a lot of systems it is not necessary to need so much memory as the
+ * variations coming from the general Jitter RNG execution commonly provide
+ * large amount of variations.
+ *
+ * Thus, the default is:
+ *
+ * min(JENT_MEMORY_SIZE, data cache size)
+ *
+ * In case the data cache size cannot be obtained, use JENT_MEMORY_SIZE.
+ *
+ * If the caller provides a maximum memory size, use
+ * min(provided max memory, data cache size).
+ */
+static inline uint32_t jent_memsize(unsigned int flags)
+{
+       uint32_t memsize, max_memsize;
+
+       max_memsize = JENT_FLAGS_TO_MAX_MEMSIZE(flags);
+
+       if (max_memsize == 0) {
+               max_memsize = JENT_MEMORY_SIZE;
+       } else {
+               max_memsize = UINT32_C(1) << (max_memsize +
+                                             JENT_MAX_MEMSIZE_OFFSET);
+       }
+
+       /* Allocate memory for adding variations based on memory access */
+       memsize = jent_cache_size_roundup();
+
+       /* Limit the memory as defined by caller */
+       memsize = (memsize > max_memsize) ? max_memsize : memsize;
+
+       /* Set a value if none was found */
+       if (!memsize)
+               memsize = JENT_MEMORY_SIZE;
+
+       return memsize;
+}
+
+static int jent_selftest_run = 0;
+
+static struct rand_data
+*jent_entropy_collector_alloc_internal(unsigned int osr, unsigned int flags)
 {
        struct rand_data *entropy_collector;
 
+       /*
+        * Requesting disabling and forcing of internal timer
+        * makes no sense.
+        */
+       if ((flags & JENT_DISABLE_INTERNAL_TIMER) &&
+           (flags & JENT_FORCE_INTERNAL_TIMER))
+               return NULL;
+
+       /* Force the self test to be run */
+       if (!jent_selftest_run && jent_entropy_init_ex(osr, flags))
+               return NULL;
+
+       /*
+        * If the initial test code concludes to force the internal timer
+        * and the user requests it not to be used, do not allocate
+        * the Jitter RNG instance.
+        */
+       if (jent_notime_forced() && (flags & JENT_DISABLE_INTERNAL_TIMER))
+               return NULL;
+
        entropy_collector = jent_zalloc(sizeof(struct rand_data));
        if (NULL == entropy_collector)
                return NULL;
 
        if (!(flags & JENT_DISABLE_MEMORY_ACCESS)) {
-               /* Allocate memory for adding variations based on memory
-                * access
+               uint32_t memsize = jent_memsize(flags);
+
+               entropy_collector->mem = _gcry_calloc (1, memsize);
+
+#ifdef JENT_RANDOM_MEMACCESS
+               /*
+                * Transform the size into a mask - it is assumed that size is
+                * a power of 2.
                 */
-               entropy_collector->mem =
-                       (unsigned char *)jent_zalloc(JENT_MEMORY_SIZE);
-               if (NULL == entropy_collector->mem) {
-                       jent_zfree(entropy_collector, sizeof(struct rand_data));
-                       return NULL;
-               }
-               entropy_collector->memblocksize = JENT_MEMORY_BLOCKSIZE;
+               entropy_collector->memmask = memsize - 1;
+#else /* JENT_RANDOM_MEMACCESS */
+               entropy_collector->memblocksize = memsize / JENT_MEMORY_BLOCKS;
                entropy_collector->memblocks = JENT_MEMORY_BLOCKS;
+
+               /* sanity check */
+               if (entropy_collector->memblocksize *
+                   entropy_collector->memblocks != memsize)
+                       goto err;
+
+#endif /* JENT_RANDOM_MEMACCESS */
+
+               if (entropy_collector->mem == NULL)
+                       goto err;
                entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS;
        }
 
        /* verify and set the oversampling rate */
-       if (0 == osr)
-               osr = 1; /* minimum sampling rate is 1 */
+       if (osr < JENT_MIN_OSR)
+               osr = JENT_MIN_OSR;
        entropy_collector->osr = osr;
+       entropy_collector->flags = flags;
 
-       entropy_collector->stir = 1;
-       if (flags & JENT_DISABLE_STIR)
-               entropy_collector->stir = 0;
-       if (flags & JENT_DISABLE_UNBIAS)
-               entropy_collector->disable_unbias = 1;
+       if (jent_fips_enabled() || (flags & JENT_FORCE_FIPS))
+               entropy_collector->fips_enabled = 1;
 
-       /* fill the data pad with non-zero values */
-       jent_gen_entropy(entropy_collector);
+       /* Initialize the APT */
+       jent_apt_init(entropy_collector, osr);
+
+       /* Initialize the Lag Predictor Test */
+       jent_lag_init(entropy_collector, osr);
+
+       /* Was jent_entropy_init run (establishing the common GCD)? */
+       if (jent_gcd_get(&entropy_collector->jent_common_timer_gcd)) {
+               /*
+                * It was not. This should probably be an error, but this
+                * behavior breaks the test code. Set the gcd to a value that
+                * won't hurt anything.
+                */
+               entropy_collector->jent_common_timer_gcd = 1;
+       }
+
+       /*
+        * Use timer-less noise source - note, OSR must be set in
+        * entropy_collector!
+        */
+       if (!(flags & JENT_DISABLE_INTERNAL_TIMER)) {
+               if (jent_notime_enable(entropy_collector, flags))
+                       goto err;
+       }
 
        return entropy_collector;
+
+err:
+       if (entropy_collector->mem != NULL)
+               jent_zfree(entropy_collector->mem, JENT_MEMORY_SIZE);
+       jent_zfree(entropy_collector, sizeof(struct rand_data));
+       return NULL;
+}
+
+static struct rand_data *_jent_entropy_collector_alloc(unsigned int osr,
+                                                      unsigned int flags)
+{
+       struct rand_data *ec = jent_entropy_collector_alloc_internal(osr,
+                                                                    flags);
+
+       if (!ec)
+               return ec;
+
+       /* fill the data pad with non-zero values */
+       if (jent_notime_settick(ec)) {
+               jent_entropy_collector_free(ec);
+               return NULL;
+       }
+       jent_random_data(ec);
+       jent_notime_unsettick(ec);
+
+       return ec;
+}
+
+JENT_PRIVATE_STATIC
+struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
+                                              unsigned int flags)
+{
+       struct rand_data *ec = _jent_entropy_collector_alloc(osr, flags);
+
+       /* Remember that the caller provided a maximum size flag */
+       if (ec)
+               ec->max_mem_set = !!JENT_FLAGS_TO_MAX_MEMSIZE(flags);
+
+       return ec;
 }
 
 JENT_PRIVATE_STATIC
 void jent_entropy_collector_free(struct rand_data *entropy_collector)
 {
-       if (NULL != entropy_collector) {
-               if (NULL != entropy_collector->mem) {
-                       jent_zfree(entropy_collector->mem, JENT_MEMORY_SIZE);
+       if (entropy_collector != NULL) {
+               jent_notime_disable(entropy_collector);
+               if (entropy_collector->mem != NULL) {
+                       jent_zfree(entropy_collector->mem,
+                                  jent_memsize(entropy_collector->flags));
                        entropy_collector->mem = NULL;
                }
                jent_zfree(entropy_collector, sizeof(struct rand_data));
        }
 }
 
-JENT_PRIVATE_STATIC
-int jent_entropy_init(void)
+int jent_time_entropy_init(unsigned int osr, unsigned int flags)
 {
-       int i;
-       uint64_t delta_sum = 0;
-       uint64_t old_delta = 0;
-       int time_backwards = 0;
-       int count_mod = 0;
-       int count_stuck = 0;
-       struct rand_data ec;
+       struct rand_data *ec;
+       uint64_t *delta_history;
+       int i, time_backwards = 0, count_stuck = 0, ret = 0;
+       unsigned int health_test_result;
+
+       delta_history = jent_gcd_init(JENT_POWERUP_TESTLOOPCOUNT);
+       if (!delta_history)
+               return EMEM;
+
+       if (flags & JENT_FORCE_INTERNAL_TIMER)
+               jent_notime_force();
+       else
+               flags |= JENT_DISABLE_INTERNAL_TIMER;
+
+       /*
+        * If the start-up health tests (including the APT and RCT) are not
+        * run, then the entropy source is not 90B compliant. We could test if
+        * fips_enabled should be set using the jent_fips_enabled() function,
+        * but this can be overridden using the JENT_FORCE_FIPS flag, which
+        * isn't passed in yet. It is better to run the tests on the small
+        * amount of data that we have, which should not fail unless things
+        * are really bad.
+        */
+       flags |= JENT_FORCE_FIPS;
+       ec = jent_entropy_collector_alloc_internal(osr, flags);
+       if (!ec) {
+               ret = EMEM;
+               goto out;
+       }
+
+       if (jent_notime_settick(ec)) {
+               ret = EMEM;
+               goto out;
+       }
+
+       /* To initialize the prior time. */
+       jent_measure_jitter(ec, 0, NULL);
 
        /* We could perform statistical tests here, but the problem is
         * that we only have a few loop counts to do testing. These
-        * loop counts may show some slight skew and we produce
-        * false positives.
-        *
-        * Moreover, only old systems show potentially problematic
-        * jitter entropy that could potentially be caught here. But
-        * the RNG is intended for hardware that is available or widely
-        * used, but not old systems that are long out of favor. Thus,
-        * no statistical tests.
+        * loop counts may show some slight skew leading to false positives.
         */
 
        /*
@@ -660,38 +572,31 @@ int jent_entropy_init(void)
         * following sanity checks verify that we have a high-resolution
         * timer.
         */
-       /*
-        * TESTLOOPCOUNT needs some loops to identify edge systems. 100 is
-        * definitely too little.
-        */
-#define TESTLOOPCOUNT 300
 #define CLEARCACHE 100
-       for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
-               uint64_t time = 0;
-               uint64_t time2 = 0;
-               uint64_t delta = 0;
-               unsigned int lowdelta = 0;
-               int stuck;
+       for (i = -CLEARCACHE; i < JENT_POWERUP_TESTLOOPCOUNT; i++) {
+               uint64_t start_time = 0, end_time = 0, delta = 0;
+               unsigned int stuck;
 
                /* Invoke core entropy collection logic */
-               jent_get_nstime(&time);
-               ec.prev_time = time;
-               jent_lfsr_time(&ec, time, 0);
-               jent_get_nstime(&time2);
+               stuck = jent_measure_jitter(ec, 0, &delta);
+               end_time = ec->prev_time;
+               start_time = ec->prev_time - delta;
 
                /* test whether timer works */
-               if (!time || !time2)
-                       return ENOTIME;
-               delta = time2 - time;
+               if (!start_time || !end_time) {
+                       ret = ENOTIME;
+                       goto out;
+               }
+
                /*
                 * test whether timer is fine grained enough to provide
                 * delta even when called shortly after each other -- this
                 * implies that we also have a high resolution timer
                 */
-               if (!delta)
-                       return ECOARSETIME;
-
-               stuck = jent_stuck(&ec, delta);
+               if (!delta || (end_time == start_time)) {
+                       ret = ECOARSETIME;
+                       goto out;
+               }
 
                /*
                 * up to here we did not modify any variable that will be
@@ -700,32 +605,18 @@ int jent_entropy_init(void)
                 * etc. with the goal to clear it to get the worst case
                 * measurements.
                 */
-               if (CLEARCACHE > i)
+               if (i < 0)
                        continue;
 
                if (stuck)
                        count_stuck++;
 
                /* test whether we have an increasing timer */
-               if (!(time2 > time))
+               if (!(end_time > start_time))
                        time_backwards++;
 
-               /* use 32 bit value to ensure compilation on 32 bit arches */
-               lowdelta = time2 - time;
-               if (!(lowdelta % 100))
-                       count_mod++;
-
-               /*
-                * ensure that we have a varying delta timer which is necessary
-                * for the calculation of entropy -- perform this check
-                * only after the first loop is executed as we need to prime
-                * the old_data value
-                */
-               if (delta > old_delta)
-                       delta_sum += (delta - old_delta);
-               else
-                       delta_sum += (old_delta - delta);
-               old_delta = delta;
+               /* Watch for common adjacent GCD values */
+               jent_gcd_add_value(delta_history, delta, i);
        }
 
        /*
@@ -735,55 +626,109 @@ int jent_entropy_init(void)
         * should not fail. The value of 3 should cover the NTP case being
         * performed during our test run.
         */
-       if (3 < time_backwards)
-               return ENOMONOTONIC;
+       if (time_backwards > 3) {
+               ret = ENOMONOTONIC;
+               goto out;
+       }
 
-       /*
-        * Variations of deltas of time must on average be larger
-        * than 1 to ensure the entropy estimation
-        * implied with 1 is preserved
-        */
-       if ((delta_sum) <= 1)
-               return EMINVARVAR;
+       /* First, did we encounter a health test failure? */
+       if ((health_test_result = jent_health_failure(ec))) {
+               ret = (health_test_result & JENT_RCT_FAILURE) ? ERCT : EHEALTH;
+               goto out;
+       }
 
-       /*
-        * Ensure that we have variations in the time stamp below 10 for at least
-        * 10% of all checks -- on some platforms, the counter increments in
-        * multiples of 100, but not always
-        */
-       if ((TESTLOOPCOUNT/10 * 9) < count_mod)
-               return ECOARSETIME;
+       ret = jent_gcd_analyze(delta_history, JENT_POWERUP_TESTLOOPCOUNT);
+       if (ret)
+               goto out;
 
        /*
         * If we have more than 90% stuck results, then this Jitter RNG is
         * likely to not work well.
         */
-       if (JENT_STUCK_INIT_THRES(TESTLOOPCOUNT) < count_stuck)
-               return ESTUCK;
+       if (JENT_STUCK_INIT_THRES(JENT_POWERUP_TESTLOOPCOUNT) < count_stuck)
+               ret = ESTUCK;
+
+out:
+       jent_gcd_fini(delta_history, JENT_POWERUP_TESTLOOPCOUNT);
+
+       if ((flags & JENT_FORCE_INTERNAL_TIMER) && ec)
+               jent_notime_unsettick(ec);
+
+       jent_entropy_collector_free(ec);
 
-       return 0;
+       return ret;
 }
 
-/***************************************************************************
- * Statistical test logic not compiled for regular operation
- ***************************************************************************/
+static inline int jent_entropy_init_common_pre(void)
+{
+       int ret;
+
+       jent_notime_block_switch();
+
+       if (sha3_tester())
+               return EHASH;
+
+       ret = jent_gcd_selftest();
+
+       jent_selftest_run = 1;
+
+       return ret;
+}
+
+static inline int jent_entropy_init_common_post(int ret)
+{
+       /* Unmark the execution of the self tests if they failed. */
+       if (ret)
+               jent_selftest_run = 0;
+
+       return ret;
+}
 
-#ifdef CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT
-/*
- * Statistical test: return the time duration for the folding operation. If min
- * is set, perform the given number of LFSR ops. Otherwise, allow the
- * loop count shuffling to define the number of LFSR ops.
- */
 JENT_PRIVATE_STATIC
-uint64_t jent_lfsr_var_stat(struct rand_data *ec, unsigned int min)
+int jent_entropy_init(void)
 {
-       uint64_t time = 0;
-       uint64_t time2 = 0;
-
-       jent_get_nstime(&time);
-       jent_memaccess(ec, min);
-       jent_lfsr_time(ec, time, min);
-       jent_get_nstime(&time2);
-       return ((time2 - time));
+       int ret = jent_entropy_init_common_pre();
+
+       if (ret)
+               return ret;
+
+       ret = jent_time_entropy_init(0, JENT_DISABLE_INTERNAL_TIMER);
+
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+       if (ret)
+               ret = jent_time_entropy_init(0, JENT_FORCE_INTERNAL_TIMER);
+#endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */
+
+       return jent_entropy_init_common_post(ret);
 }
-#endif /* CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT */
+
+JENT_PRIVATE_STATIC
+int jent_entropy_init_ex(unsigned int osr, unsigned int flags)
+{
+       int ret = jent_entropy_init_common_pre();
+
+       if (ret)
+               return ret;
+
+       /* Test without internal timer unless caller does not want it */
+       if (!(flags & JENT_FORCE_INTERNAL_TIMER))
+               ret = jent_time_entropy_init(osr,
+                                       flags | JENT_DISABLE_INTERNAL_TIMER);
+
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+       /* Test with internal timer unless caller does not want it */
+       if (ret && !(flags & JENT_DISABLE_INTERNAL_TIMER))
+               ret = jent_time_entropy_init(osr,
+                                            flags | JENT_FORCE_INTERNAL_TIMER);
+#endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */
+
+       return jent_entropy_init_common_post(ret);
+}
+
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+JENT_PRIVATE_STATIC
+int jent_entropy_switch_notime_impl(struct jent_notime_thread *new_thread)
+{
+       return jent_notime_switch(new_thread);
+}
+#endif
diff --git a/random/jitterentropy-base.h b/random/jitterentropy-base.h
new file mode 100644 (file)
index 0000000..85d417c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef JITTERENTROPY_BASE_H
+#define JITTERENTROPY_BASE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int jent_time_entropy_init(unsigned int osr, unsigned int flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JITTERENTROPY_BASE_H */
diff --git a/random/jitterentropy-gcd.c b/random/jitterentropy-gcd.c
new file mode 100644 (file)
index 0000000..aa9c679
--- /dev/null
@@ -0,0 +1,188 @@
+/* Jitter RNG: GCD health test
+ *
+ * Copyright (C) 2021, Joshua E. Hill <josh@keypair.us>
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "jitterentropy.h"
+#include "jitterentropy-gcd.h"
+
+/* The common divisor for all timestamp deltas */
+static uint64_t jent_common_timer_gcd = 0;
+
+static inline int jent_gcd_tested(void)
+{
+       return (jent_common_timer_gcd != 0);
+}
+
+/* A straight forward implementation of the Euclidean algorithm for GCD. */
+static inline uint64_t jent_gcd64(uint64_t a, uint64_t b)
+{
+       /* Make a greater a than or equal b. */
+       if (a < b) {
+               uint64_t c = a;
+               a = b;
+               b = c;
+       }
+
+       /* Now perform the standard inner-loop for this algorithm.*/
+       while (b != 0) {
+               uint64_t r;
+
+               r = a % b;
+
+               a = b;
+               b = r;
+       }
+
+       return a;
+}
+
+static int jent_gcd_analyze_internal(uint64_t *delta_history, size_t nelem,
+                                    uint64_t *running_gcd_out,
+                                    uint64_t *delta_sum_out)
+{
+       uint64_t running_gcd, delta_sum = 0;
+       size_t i;
+
+       if (!delta_history)
+               return -EAGAIN;
+
+       running_gcd = delta_history[0];
+
+       /* Now perform the analysis on the accumulated delta data. */
+       for (i = 1; i < nelem; i++) {
+               /*
+                * ensure that we have a varying delta timer which is necessary
+                * for the calculation of entropy -- perform this check
+                * only after the first loop is executed as we need to prime
+                * the old_data value
+                */
+               if (delta_history[i] >= delta_history[i - 1])
+                       delta_sum +=  delta_history[i] - delta_history[i - 1];
+               else
+                       delta_sum +=  delta_history[i - 1] - delta_history[i];
+
+               /*
+                * This calculates the gcd of all the delta values. that is
+                * gcd(delta_1, delta_2, ..., delta_nelem)
+
+                * Some timers increment by a fixed (non-1) amount each step.
+                * This code checks for such increments, and allows the library
+                * to output the number of such changes have occurred.
+                */
+               running_gcd = jent_gcd64(delta_history[i], running_gcd);
+       }
+
+       *running_gcd_out = running_gcd;
+       *delta_sum_out = delta_sum;
+
+       return 0;
+}
+
+int jent_gcd_analyze(uint64_t *delta_history, size_t nelem)
+{
+       uint64_t running_gcd, delta_sum;
+       int ret = jent_gcd_analyze_internal(delta_history, nelem, &running_gcd,
+                                           &delta_sum);
+
+       if (ret == -EAGAIN)
+               return 0;
+
+       /*
+        * Variations of deltas of time must on average be larger than 1 to
+        * ensure the entropy estimation implied with 1 is preserved.
+        */
+       if (delta_sum <= nelem - 1) {
+               ret = EMINVARVAR;
+               goto out;
+       }
+
+       /*
+        * Ensure that we have variations in the time stamp below 100 for at
+        * least 10% of all checks -- on some platforms, the counter increments
+        * in multiples of 100, but not always
+        */
+       if (running_gcd >= 100) {
+               ret = ECOARSETIME;
+               goto out;
+       }
+
+       /*  Adjust all deltas by the observed (small) common factor. */
+       if (!jent_gcd_tested())
+               jent_common_timer_gcd = running_gcd;
+
+out:
+       return ret;
+}
+
+uint64_t *jent_gcd_init(size_t nelem)
+{
+       uint64_t *delta_history;
+
+       delta_history = jent_zalloc(nelem * sizeof(uint64_t));
+       if (!delta_history)
+               return NULL;
+
+       return delta_history;
+}
+
+void jent_gcd_fini(uint64_t *delta_history, size_t nelem)
+{
+       if (delta_history)
+               jent_zfree(delta_history,
+                          (unsigned int)(nelem * sizeof(uint64_t)));
+}
+
+int jent_gcd_get(uint64_t *value)
+{
+       if (!jent_gcd_tested())
+               return 1;
+
+       *value = jent_common_timer_gcd;
+       return 0;
+}
+
+int jent_gcd_selftest(void)
+{
+#define JENT_GCD_SELFTEST_ELEM 10
+#define JENT_GCD_SELFTEST_EXP 3ULL
+       uint64_t *gcd = jent_gcd_init(JENT_GCD_SELFTEST_ELEM);
+       uint64_t running_gcd, delta_sum;
+       unsigned int i;
+       int ret = EGCD;
+
+       if (!gcd)
+               return EMEM;
+
+       for (i = 0; i < JENT_GCD_SELFTEST_ELEM; i++)
+               jent_gcd_add_value(gcd, i * JENT_GCD_SELFTEST_EXP, i);
+
+       if (jent_gcd_analyze_internal(gcd, JENT_GCD_SELFTEST_ELEM,
+                                     &running_gcd, &delta_sum))
+               goto out;
+
+       if (running_gcd != JENT_GCD_SELFTEST_EXP)
+               goto out;
+
+       ret = 0;
+
+out:
+       jent_gcd_fini(gcd, JENT_GCD_SELFTEST_ELEM);
+       return ret;
+}
diff --git a/random/jitterentropy-gcd.h b/random/jitterentropy-gcd.h
new file mode 100644 (file)
index 0000000..4459956
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef JITTERENTROPY_GCD_H
+#define JITTERENTROPY_GCD_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int jent_gcd_analyze(uint64_t *delta_history, size_t nelem);
+uint64_t *jent_gcd_init(size_t nelem);
+void jent_gcd_fini(uint64_t *delta_history, size_t nelem);
+int jent_gcd_get(uint64_t *value);
+int jent_gcd_selftest(void);
+
+/* Watch for common adjacent GCD values */
+#define jent_gcd_add_value(delta_history, delta, idx)                  \
+       delta_history[idx] = delta;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JITTERENTROPY_GCD_H */
diff --git a/random/jitterentropy-health.c b/random/jitterentropy-health.c
new file mode 100644 (file)
index 0000000..a0b0e3e
--- /dev/null
@@ -0,0 +1,438 @@
+/* Jitter RNG: Health Tests
+ *
+ * Copyright (C) 2021, Joshua E. Hill <josh@keypair.us>
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "jitterentropy.h"
+#include "jitterentropy-health.h"
+
+/***************************************************************************
+ * Lag Predictor Test
+ *
+ * This test is a vendor-defined conditional test that is designed to detect
+ * a known failure mode where the result becomes mostly deterministic
+ * Note that (lag_observations & JENT_LAG_MASK) is the index where the next
+ * value provided will be stored.
+ ***************************************************************************/
+
+#ifdef JENT_HEALTH_LAG_PREDICTOR
+
+/*
+ * These cutoffs are configured using an entropy estimate of 1/osr under an
+ * alpha=2^(-22) for a window size of 131072. The other health tests use
+ * alpha=2^-30, but operate on much smaller window sizes. This larger selection
+ * of alpha makes the behavior per-lag-window similar to the APT test.
+ *
+ * The global cutoffs are calculated using the
+ * InverseBinomialCDF(n=(JENT_LAG_WINDOW_SIZE-JENT_LAG_HISTORY_SIZE), p=2^(-1/osr); 1-alpha)
+ * The local cutoffs are somewhat more complicated. For background, see Feller's
+ * _Introduction to Probability Theory and It's Applications_ Vol. 1,
+ * Chapter 13, section 7 (in particular see equation 7.11, where x is a root
+ * of the denominator of equation 7.6).
+ *
+ * We'll proceed using the notation of SP 800-90B Section 6.3.8 (which is
+ * developed in Kelsey-McKay-Turan paper "Predictive Models for Min-entropy
+ * Estimation".)
+ *
+ * Here, we set p=2^(-1/osr), seeking a run of successful guesses (r) with
+ * probability of less than (1-alpha). That is, it is very very likely
+ * (probability 1-alpha) that there is _no_ run of length r in a block of size
+ * JENT_LAG_WINDOW_SIZE-JENT_LAG_HISTORY_SIZE.
+ *
+ * We have to iteratively look for an appropriate value for the cutoff r.
+ */
+static const unsigned int jent_lag_global_cutoff_lookup[20] =
+       { 66443,  93504, 104761, 110875, 114707, 117330, 119237, 120686, 121823,
+        122739, 123493, 124124, 124660, 125120, 125520, 125871, 126181, 126457,
+        126704, 126926 };
+static const unsigned int jent_lag_local_cutoff_lookup[20] =
+       {  38,  75, 111, 146, 181, 215, 250, 284, 318, 351,
+         385, 419, 452, 485, 518, 551, 584, 617, 650, 683 };
+
+void jent_lag_init(struct rand_data *ec, unsigned int osr)
+{
+       /*
+        * Establish the lag global and local cutoffs based on the presumed
+        * entropy rate of 1/osr.
+        */
+       if (osr > ARRAY_SIZE(jent_lag_global_cutoff_lookup)) {
+               ec->lag_global_cutoff =
+                       jent_lag_global_cutoff_lookup[
+                               ARRAY_SIZE(jent_lag_global_cutoff_lookup) - 1];
+       } else {
+               ec->lag_global_cutoff = jent_lag_global_cutoff_lookup[osr - 1];
+       }
+
+       if (osr > ARRAY_SIZE(jent_lag_local_cutoff_lookup)) {
+               ec->lag_local_cutoff =
+                       jent_lag_local_cutoff_lookup[
+                               ARRAY_SIZE(jent_lag_local_cutoff_lookup) - 1];
+       } else {
+               ec->lag_local_cutoff = jent_lag_local_cutoff_lookup[osr - 1];
+       }
+}
+
+/**
+ * Reset the lag counters
+ *
+ * @ec [in] Reference to entropy collector
+ */
+static void jent_lag_reset(struct rand_data *ec)
+{
+       unsigned int i;
+
+       /* Reset Lag counters */
+       ec->lag_prediction_success_count = 0;
+       ec->lag_prediction_success_run = 0;
+       ec->lag_best_predictor = 0; //The first guess is basically arbitrary.
+       ec->lag_observations = 0;
+
+       for (i = 0; i < JENT_LAG_HISTORY_SIZE; i++) {
+               ec->lag_scoreboard[i] = 0;
+               ec->lag_delta_history[i] = 0;
+       }
+}
+
+/*
+ * A macro for accessing the history. Index 0 is the last observed symbol
+ * index 1 is the symbol observed two inputs ago, etc.
+ */
+#define JENT_LAG_HISTORY(EC,LOC)                                              \
+       ((EC)->lag_delta_history[((EC)->lag_observations - (LOC) - 1) &        \
+        JENT_LAG_MASK])
+
+/**
+ * Insert a new entropy event into the lag predictor test
+ *
+ * @ec [in] Reference to entropy collector
+ * @current_delta [in] Current time delta
+ */
+static void jent_lag_insert(struct rand_data *ec, uint64_t current_delta)
+{
+       uint64_t prediction;
+       unsigned int i;
+
+       /* Initialize the delta_history */
+       if (ec->lag_observations < JENT_LAG_HISTORY_SIZE) {
+               ec->lag_delta_history[ec->lag_observations] = current_delta;
+               ec->lag_observations++;
+               return;
+       }
+
+       /*
+        * The history is initialized. First make a guess and examine the
+        * results.
+        */
+       prediction = JENT_LAG_HISTORY(ec, ec->lag_best_predictor);
+
+       if (prediction == current_delta) {
+               /* The prediction was correct. */
+               ec->lag_prediction_success_count++;
+               ec->lag_prediction_success_run++;
+
+               if ((ec->lag_prediction_success_run >= ec->lag_local_cutoff) ||
+                   (ec->lag_prediction_success_count >= ec->lag_global_cutoff))
+                       ec->health_failure |= JENT_LAG_FAILURE;
+       } else {
+               /* The prediction wasn't correct. End any run of successes.*/
+               ec->lag_prediction_success_run = 0;
+       }
+
+       /* Now update the predictors using the current data. */
+       for (i = 0; i < JENT_LAG_HISTORY_SIZE; i++) {
+               if (JENT_LAG_HISTORY(ec, i) == current_delta) {
+                       /*
+                        * The ith predictor (which guesses i + 1 symbols in
+                        * the past) successfully guessed.
+                        */
+                       ec->lag_scoreboard[i] ++;
+
+                       /*
+                        * Keep track of the best predictor (tie goes to the
+                        * shortest lag)
+                        */
+                       if (ec->lag_scoreboard[i] >
+                           ec->lag_scoreboard[ec->lag_best_predictor])
+                               ec->lag_best_predictor = i;
+               }
+       }
+
+       /*
+        * Finally, update the lag_delta_history array with the newly input
+        * value.
+        */
+       ec->lag_delta_history[(ec->lag_observations) & JENT_LAG_MASK] =
+                                                               current_delta;
+       ec->lag_observations++;
+
+       /*
+        * lag_best_predictor now is the index of the predictor with the largest
+        * number of correct guesses.
+        * This establishes our next guess.
+        */
+
+       /* Do we now need a new window? */
+       if (ec->lag_observations >= JENT_LAG_WINDOW_SIZE)
+               jent_lag_reset(ec);
+}
+
+static inline uint64_t jent_delta2(struct rand_data *ec, uint64_t current_delta)
+{
+       /* Note that delta2_n = delta_n - delta_{n-1} */
+       return jent_delta(JENT_LAG_HISTORY(ec, 0), current_delta);
+}
+
+static inline uint64_t jent_delta3(struct rand_data *ec, uint64_t delta2)
+{
+       /*
+        * Note that delta3_n = delta2_n - delta2_{n-1}
+        *                    = delta2_n - (delta_{n-1} - delta_{n-2})
+        */
+       return jent_delta(jent_delta(JENT_LAG_HISTORY(ec, 1),
+                                    JENT_LAG_HISTORY(ec, 0)), delta2);
+}
+
+#else /* JENT_HEALTH_LAG_PREDICTOR */
+
+static inline void jent_lag_insert(struct rand_data *ec, uint64_t current_delta)
+{
+       (void)ec;
+       (void)current_delta;
+}
+
+static inline uint64_t jent_delta2(struct rand_data *ec, uint64_t current_delta)
+{
+       uint64_t delta2 = jent_delta(ec->last_delta, current_delta);
+
+       ec->last_delta = current_delta;
+       return delta2;
+}
+
+static inline uint64_t jent_delta3(struct rand_data *ec, uint64_t delta2)
+{
+       uint64_t delta3 = jent_delta(ec->last_delta2, delta2);
+
+       ec->last_delta2 = delta2;
+       return delta3;
+}
+
+#endif /* JENT_HEALTH_LAG_PREDICTOR */
+
+/***************************************************************************
+ * Adaptive Proportion Test
+ *
+ * This test complies with SP800-90B section 4.4.2.
+ ***************************************************************************/
+
+/*
+ * See the SP 800-90B comment #10b for the corrected cutoff for the SP 800-90B
+ * APT.
+ * http://www.untruth.org/~josh/sp80090b/UL%20SP800-90B-final%20comments%20v1.9%2020191212.pdf
+ * In in the syntax of R, this is C = 2 + qbinom(1 - 2^(-30), 511, 2^(-1/osr)).
+ * (The original formula wasn't correct because the first symbol must
+ * necessarily have been observed, so there is no chance of observing 0 of these
+ * symbols.)
+ *
+ * For any value above 14, this yields the maximal allowable value of 512
+ * (by FIPS 140-2 IG 7.19 Resolution # 16, we cannot choose a cutoff value that
+ * renders the test unable to fail).
+ */
+static const unsigned int jent_apt_cutoff_lookup[15]=
+       { 325, 422, 459, 477, 488, 494, 499, 502,
+         505, 507, 508, 509, 510, 511, 512 };
+
+void jent_apt_init(struct rand_data *ec, unsigned int osr)
+{
+       /*
+        * Establish the apt_cutoff based on the presumed entropy rate of
+        * 1/osr.
+        */
+       if (osr >= ARRAY_SIZE(jent_apt_cutoff_lookup)) {
+               ec->apt_cutoff = jent_apt_cutoff_lookup[
+                                       ARRAY_SIZE(jent_apt_cutoff_lookup) - 1];
+       } else {
+               ec->apt_cutoff = jent_apt_cutoff_lookup[osr - 1];
+       }
+}
+
+/**
+ * Reset the APT counter
+ *
+ * @ec [in] Reference to entropy collector
+ */
+static void jent_apt_reset(struct rand_data *ec)
+{
+       /* When reset, accept the _next_ value input as the new base. */
+       ec->apt_base_set = 0;
+}
+
+/**
+ * Insert a new entropy event into APT
+ *
+ * @ec [in] Reference to entropy collector
+ * @current_delta [in] Current time delta
+ */
+static void jent_apt_insert(struct rand_data *ec, uint64_t current_delta)
+{
+       /* Initialize the base reference */
+       if (!ec->apt_base_set) {
+               ec->apt_base = current_delta;   // APT Step 1
+               ec->apt_base_set = 1;           // APT Step 2
+
+               /*
+                * Reset APT counter
+                * Note that we've taken in the first symbol in the window.
+                */
+               ec->apt_count = 1;              // B = 1
+               ec->apt_observations = 1;
+
+               return;
+       }
+
+       if (current_delta == ec->apt_base) {
+               ec->apt_count++;                // B = B + 1
+
+               /* Note, ec->apt_count starts with one. */
+               if (ec->apt_count >= ec->apt_cutoff)
+                       ec->health_failure |= JENT_APT_FAILURE;
+       }
+
+       ec->apt_observations++;
+
+       /* Completed one window, the next symbol input will be new apt_base. */
+       if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
+               jent_apt_reset(ec);             // APT Step 4
+}
+
+/***************************************************************************
+ * Stuck Test and its use as Repetition Count Test
+ *
+ * The Jitter RNG uses an enhanced version of the Repetition Count Test
+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
+ * back-to-back values, the input to the RCT is the counting of the stuck
+ * values during the generation of one Jitter RNG output block.
+ *
+ * The RCT is applied with an alpha of 2^{-30} compliant to FIPS 140-2 IG 9.8.
+ *
+ * During the counting operation, the Jitter RNG always calculates the RCT
+ * cut-off value of C. If that value exceeds the allowed cut-off value,
+ * the Jitter RNG output block will be calculated completely but discarded at
+ * the end. The caller of the Jitter RNG is informed with an error code.
+ ***************************************************************************/
+
+/**
+ * Repetition Count Test as defined in SP800-90B section 4.4.1
+ *
+ * @ec [in] Reference to entropy collector
+ * @stuck [in] Indicator whether the value is stuck
+ */
+static void jent_rct_insert(struct rand_data *ec, int stuck)
+{
+       /*
+        * If we have a count less than zero, a previous RCT round identified
+        * a failure. We will not overwrite it.
+        */
+       if (ec->rct_count < 0)
+               return;
+
+       if (stuck) {
+               ec->rct_count++;
+
+               /*
+                * The cutoff value is based on the following consideration:
+                * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
+                * In addition, we require an entropy value H of 1/osr as this
+                * is the minimum entropy required to provide full entropy.
+                * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr
+                * deltas for inserting them into the entropy pool which should
+                * then have (close to) DATA_SIZE_BITS bits of entropy in the
+                * conditioned output.
+                *
+                * Note, ec->rct_count (which equals to value B in the pseudo
+                * code of SP800-90B section 4.4.1) starts with zero. Hence
+                * we need to subtract one from the cutoff value as calculated
+                * following SP800-90B. Thus C = ceil(-log_2(alpha)/H) = 30*osr.
+                */
+               if ((unsigned int)ec->rct_count >= (30 * ec->osr)) {
+                       ec->rct_count = -1;
+                       ec->health_failure |= JENT_RCT_FAILURE;
+               }
+       } else {
+               ec->rct_count = 0;
+       }
+}
+
+/**
+ * Stuck test by checking the:
+ *     1st derivative of the jitter measurement (time delta)
+ *     2nd derivative of the jitter measurement (delta of time deltas)
+ *     3rd derivative of the jitter measurement (delta of delta of time deltas)
+ *
+ * All values must always be non-zero.
+ *
+ * @ec [in] Reference to entropy collector
+ * @current_delta [in] Jitter time delta
+ *
+ * @return
+ *     0 jitter measurement not stuck (good bit)
+ *     1 jitter measurement stuck (reject bit)
+ */
+unsigned int jent_stuck(struct rand_data *ec, uint64_t current_delta)
+{
+       uint64_t delta2 = jent_delta2(ec, current_delta);
+       uint64_t delta3 = jent_delta3(ec, delta2);
+
+       /*
+        * Insert the result of the comparison of two back-to-back time
+        * deltas.
+        */
+       jent_apt_insert(ec, current_delta);
+       jent_lag_insert(ec, current_delta);
+
+       if (!current_delta || !delta2 || !delta3) {
+               /* RCT with a stuck bit */
+               jent_rct_insert(ec, 1);
+               return 1;
+       }
+
+       /* RCT with a non-stuck bit */
+       jent_rct_insert(ec, 0);
+
+       return 0;
+}
+
+/**
+ * Report any health test failures
+ *
+ * @ec [in] Reference to entropy collector
+ *
+ * @return a bitmask indicating which tests failed
+ *     0 No health test failure
+ *     1 RCT failure
+ *     2 APT failure
+ *     4 Lag predictor test failure
+ */
+unsigned int jent_health_failure(struct rand_data *ec)
+{
+       /* Test is only enabled in FIPS mode */
+       if (!ec->fips_enabled)
+               return 0;
+
+       return ec->health_failure;
+}
diff --git a/random/jitterentropy-health.h b/random/jitterentropy-health.h
new file mode 100644 (file)
index 0000000..7754629
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef JITTERENTROPY_HEALTH_H
+#define JITTERENTROPY_HEALTH_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+static inline uint64_t jent_delta(uint64_t prev, uint64_t next)
+{
+       return (next - prev);
+}
+
+#ifdef JENT_HEALTH_LAG_PREDICTOR
+void jent_lag_init(struct rand_data *ec, unsigned int osr);
+#else /* JENT_HEALTH_LAG_PREDICTOR */
+static inline void jent_lag_init(struct rand_data *ec, unsigned int osr)
+{
+       (void)ec;
+       (void)osr;
+}
+#endif /* JENT_HEALTH_LAG_PREDICTOR */
+
+void jent_apt_init(struct rand_data *ec, unsigned int osr);
+unsigned int jent_stuck(struct rand_data *ec, uint64_t current_delta);
+unsigned int jent_health_failure(struct rand_data *ec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JITTERENTROPY_HEALTH_H */
diff --git a/random/jitterentropy-noise.c b/random/jitterentropy-noise.c
new file mode 100644 (file)
index 0000000..9cb1b39
--- /dev/null
@@ -0,0 +1,387 @@
+/* Jitter RNG: Noise Sources
+ *
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "jitterentropy-noise.h"
+#include "jitterentropy-health.h"
+#include "jitterentropy-timer.h"
+#include "jitterentropy-sha3.h"
+
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+
+/***************************************************************************
+ * Noise sources
+ ***************************************************************************/
+
+/**
+ * Update of the loop count used for the next round of
+ * an entropy collection.
+ *
+ * @ec [in] entropy collector struct -- may be NULL
+ * @bits [in] is the number of low bits of the timer to consider
+ * @min [in] is the number of bits we shift the timer value to the right at
+ *          the end to make sure we have a guaranteed minimum value
+ *
+ * @return Newly calculated loop counter
+ */
+static uint64_t jent_loop_shuffle(struct rand_data *ec,
+                                 unsigned int bits, unsigned int min)
+{
+#ifdef JENT_CONF_DISABLE_LOOP_SHUFFLE
+
+       (void)ec;
+       (void)bits;
+
+       return (UINT64_C(1)<<min);
+
+#else /* JENT_CONF_DISABLE_LOOP_SHUFFLE */
+
+       uint64_t time = 0;
+       uint64_t shuffle = 0;
+       uint64_t mask = (UINT64_C(1)<<bits) - 1;
+       unsigned int i = 0;
+
+       /*
+        * Mix the current state of the random number into the shuffle
+        * calculation to balance that shuffle a bit more.
+        */
+       if (ec) {
+               jent_get_nstime_internal(ec, &time);
+               time ^= ec->data[0];
+       }
+
+       /*
+        * We fold the time value as much as possible to ensure that as many
+        * bits of the time stamp are included as possible.
+        */
+       for (i = 0; ((DATA_SIZE_BITS + bits - 1) / bits) > i; i++) {
+               shuffle ^= time & mask;
+               time = time >> bits;
+       }
+
+       /*
+        * We add a lower boundary value to ensure we have a minimum
+        * RNG loop count.
+        */
+       return (shuffle + (UINT64_C(1)<<min));
+
+#endif /* JENT_CONF_DISABLE_LOOP_SHUFFLE */
+}
+
+/**
+ * CPU Jitter noise source -- this is the noise source based on the CPU
+ *                           execution time jitter
+ *
+ * This function injects the individual bits of the time value into the
+ * entropy pool using a hash.
+ *
+ * @ec [in] entropy collector struct -- may be NULL
+ * @time [in] time stamp to be injected
+ * @loop_cnt [in] if a value not equal to 0 is set, use the given value as
+ *               number of loops to perform the hash operation
+ * @stuck [in] Is the time stamp identified as stuck?
+ *
+ * Output:
+ * updated hash context
+ */
+static void jent_hash_time(struct rand_data *ec, uint64_t time,
+                          uint64_t loop_cnt, unsigned int stuck)
+{
+       HASH_CTX_ON_STACK(ctx);
+       uint8_t itermediary[SHA3_256_SIZE_DIGEST];
+       uint64_t j = 0;
+       uint64_t hash_loop_cnt;
+#define MAX_HASH_LOOP 3
+#define MIN_HASH_LOOP 0
+
+       /* Ensure that macros cannot overflow jent_loop_shuffle() */
+       BUILD_BUG_ON((MAX_HASH_LOOP + MIN_HASH_LOOP) > 63);
+       hash_loop_cnt =
+               jent_loop_shuffle(ec, MAX_HASH_LOOP, MIN_HASH_LOOP);
+
+       sha3_256_init(&ctx);
+
+       /*
+        * testing purposes -- allow test app to set the counter, not
+        * needed during runtime
+        */
+       if (loop_cnt)
+               hash_loop_cnt = loop_cnt;
+
+       /*
+        * This loop basically slows down the SHA-3 operation depending
+        * on the hash_loop_cnt. Each iteration of the loop generates the
+        * same result.
+        */
+       for (j = 0; j < hash_loop_cnt; j++) {
+               sha3_update(&ctx, ec->data, SHA3_256_SIZE_DIGEST);
+               sha3_update(&ctx, (uint8_t *)&time, sizeof(uint64_t));
+               sha3_update(&ctx, (uint8_t *)&j, sizeof(uint64_t));
+
+               /*
+                * If the time stamp is stuck, do not finally insert the value
+                * into the entropy pool. Although this operation should not do
+                * any harm even when the time stamp has no entropy, SP800-90B
+                * requires that any conditioning operation to have an identical
+                * amount of input data according to section 3.1.5.
+                */
+
+               /*
+                * The sha3_final operations re-initialize the context for the
+                * next loop iteration.
+                */
+               if (stuck || (j < hash_loop_cnt - 1))
+                       sha3_final(&ctx, itermediary);
+               else
+                       sha3_final(&ctx, ec->data);
+       }
+
+       jent_memset_secure(&ctx, SHA_MAX_CTX_SIZE);
+       jent_memset_secure(itermediary, sizeof(itermediary));
+}
+
+#define MAX_ACC_LOOP_BIT 7
+#define MIN_ACC_LOOP_BIT 0
+#ifdef JENT_RANDOM_MEMACCESS
+
+static inline uint32_t uint32rotl(const uint32_t x, int k)
+{
+       return (x << k) | (x >> (32 - k));
+}
+
+static inline uint32_t xoshiro128starstar(uint32_t *s)
+{
+       const uint32_t result = uint32rotl(s[1] * 5, 7) * 9;
+       const uint32_t t = s[1] << 9;
+
+       s[2] ^= s[0];
+       s[3] ^= s[1];
+       s[1] ^= s[2];
+       s[0] ^= s[3];
+
+       s[2] ^= t;
+
+       s[3] = uint32rotl(s[3], 11);
+
+       return result;
+}
+
+static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt)
+{
+       uint64_t i = 0;
+       union {
+               uint32_t u[4];
+               uint8_t b[sizeof(uint32_t) * 4];
+       } prngState = { .u = {0x8e93eec0, 0xce65608a, 0xa8d46b46, 0xe83cef69} };
+       uint32_t addressMask;
+        uint64_t acc_loop_cnt;
+
+       if (NULL == ec || NULL == ec->mem)
+               return;
+
+       addressMask =  ec->memmask;
+
+       /* Ensure that macros cannot overflow jent_loop_shuffle() */
+       BUILD_BUG_ON((MAX_ACC_LOOP_BIT + MIN_ACC_LOOP_BIT) > 63);
+       acc_loop_cnt =
+               jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
+
+       /*
+        * Mix the current data into prngState
+        *
+        * Any time you see a PRNG in a noise source, you should be concerned.
+        *
+        * The PRNG doesn't directly produce the raw noise, it just adjusts the
+        * location being updated. The timing of the update is part of the raw
+        * sample. The main thing this process gets you isn't better
+        * "per-update: timing, it gets you mostly independent "per-update"
+        * timing, so we can now benefit from the Central Limit Theorem!
+        */
+       for (i = 0; i < sizeof(prngState); i++)
+               prngState.b[i] ^= ec->data[i];
+
+       /*
+        * testing purposes -- allow test app to set the counter, not
+        * needed during runtime
+        */
+       if (loop_cnt)
+               acc_loop_cnt = loop_cnt;
+
+       for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) {
+               /* Take PRNG output to find the memory location to update. */
+               unsigned char *tmpval = ec->mem +
+                                       (xoshiro128starstar(prngState.u) &
+                                        addressMask);
+
+               /*
+                * memory access: just add 1 to one byte,
+                * wrap at 255 -- memory access implies read
+                * from and write to memory location
+                */
+               *tmpval = (unsigned char)((*tmpval + 1) & 0xff);
+       }
+}
+
+#else /* JENT_RANDOM_MEMACCESS */
+
+/**
+ * Memory Access noise source -- this is a noise source based on variations in
+ *                              memory access times
+ *
+ * This function performs memory accesses which will add to the timing
+ * variations due to an unknown amount of CPU wait states that need to be
+ * added when accessing memory. The memory size should be larger than the L1
+ * caches as outlined in the documentation and the associated testing.
+ *
+ * The L1 cache has a very high bandwidth, albeit its access rate is  usually
+ * slower than accessing CPU registers. Therefore, L1 accesses only add minimal
+ * variations as the CPU has hardly to wait. Starting with L2, significant
+ * variations are added because L2 typically does not belong to the CPU any more
+ * and therefore a wider range of CPU wait states is necessary for accesses.
+ * L3 and real memory accesses have even a wider range of wait states. However,
+ * to reliably access either L3 or memory, the ec->mem memory must be quite
+ * large which is usually not desirable.
+ *
+ * @ec [in] Reference to the entropy collector with the memory access data -- if
+ *         the reference to the memory block to be accessed is NULL, this noise
+ *         source is disabled
+ * @loop_cnt [in] if a value not equal to 0 is set, use the given value as
+ *               number of loops to perform the hash operation
+ */
+static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt)
+{
+       unsigned int wrap = 0;
+       uint64_t i = 0;
+
+       /* Ensure that macros cannot overflow jent_loop_shuffle() */
+       BUILD_BUG_ON((MAX_ACC_LOOP_BIT + MIN_ACC_LOOP_BIT) > 63);
+       uint64_t acc_loop_cnt =
+               jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
+
+       if (NULL == ec || NULL == ec->mem)
+               return;
+       wrap = ec->memblocksize * ec->memblocks;
+
+       /*
+        * testing purposes -- allow test app to set the counter, not
+        * needed during runtime
+        */
+       if (loop_cnt)
+               acc_loop_cnt = loop_cnt;
+       for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) {
+               unsigned char *tmpval = ec->mem + ec->memlocation;
+               /*
+                * memory access: just add 1 to one byte,
+                * wrap at 255 -- memory access implies read
+                * from and write to memory location
+                */
+               *tmpval = (unsigned char)((*tmpval + 1) & 0xff);
+               /*
+                * Addition of memblocksize - 1 to pointer
+                * with wrap around logic to ensure that every
+                * memory location is hit evenly
+                */
+               ec->memlocation = ec->memlocation + ec->memblocksize - 1;
+               ec->memlocation = ec->memlocation % wrap;
+       }
+}
+
+#endif /* JENT_RANDOM_MEMACCESS */
+
+/***************************************************************************
+ * Start of entropy processing logic
+ ***************************************************************************/
+
+/**
+ * This is the heart of the entropy generation: calculate time deltas and
+ * use the CPU jitter in the time deltas. The jitter is injected into the
+ * entropy pool.
+ *
+ * WARNING: ensure that ->prev_time is primed before using the output
+ *         of this function! This can be done by calling this function
+ *         and not using its result.
+ *
+ * @ec [in] Reference to entropy collector
+ * @loop_cnt [in] see jent_hash_time
+ * @ret_current_delta [out] Test interface: return time delta - may be NULL
+ *
+ * @return: result of stuck test
+ */
+unsigned int jent_measure_jitter(struct rand_data *ec,
+                                uint64_t loop_cnt,
+                                uint64_t *ret_current_delta)
+{
+       uint64_t time = 0;
+       uint64_t current_delta = 0;
+       unsigned int stuck;
+
+       /* Invoke one noise source before time measurement to add variations */
+       jent_memaccess(ec, loop_cnt);
+
+       /*
+        * Get time stamp and calculate time delta to previous
+        * invocation to measure the timing variations
+        */
+       jent_get_nstime_internal(ec, &time);
+       current_delta = jent_delta(ec->prev_time, time) /
+                                               ec->jent_common_timer_gcd;
+       ec->prev_time = time;
+
+       /* Check whether we have a stuck measurement. */
+       stuck = jent_stuck(ec, current_delta);
+
+       /* Now call the next noise sources which also injects the data */
+       jent_hash_time(ec, current_delta, loop_cnt, stuck);
+
+       /* return the raw entropy value */
+       if (ret_current_delta)
+               *ret_current_delta = current_delta;
+
+       return stuck;
+}
+
+/**
+ * Generator of one 256 bit random number
+ * Function fills rand_data->data
+ *
+ * @ec [in] Reference to entropy collector
+ */
+void jent_random_data(struct rand_data *ec)
+{
+       unsigned int k = 0, safety_factor = ENTROPY_SAFETY_FACTOR;
+
+       if (!ec->fips_enabled)
+               safety_factor = 0;
+
+       /* priming of the ->prev_time value */
+       jent_measure_jitter(ec, 0, NULL);
+
+       while (1) {
+               /* If a stuck measurement is received, repeat measurement */
+               if (jent_measure_jitter(ec, 0, NULL))
+                       continue;
+
+               /*
+                * We multiply the loop value with ->osr to obtain the
+                * oversampling rate requested by the caller
+                */
+               if (++k >= ((DATA_SIZE_BITS + safety_factor) * ec->osr))
+                       break;
+       }
+}
diff --git a/random/jitterentropy-noise.h b/random/jitterentropy-noise.h
new file mode 100644 (file)
index 0000000..3998fbf
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef JITTERENTROPY_NOISE_H
+#define JITTERENTROPY_NOISE_H
+
+#include "jitterentropy.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+unsigned int jent_measure_jitter(struct rand_data *ec,
+                                uint64_t loop_cnt,
+                                uint64_t *ret_current_delta);
+void jent_random_data(struct rand_data *ec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JITTERENTROPY_NOISE_H */
diff --git a/random/jitterentropy-sha3.c b/random/jitterentropy-sha3.c
new file mode 100644 (file)
index 0000000..59fbb74
--- /dev/null
@@ -0,0 +1,382 @@
+/* Jitter RNG: SHA-3 Implementation
+ *
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "jitterentropy-sha3.h"
+
+/***************************************************************************
+ * Message Digest Implementation
+ ***************************************************************************/
+
+/*
+ * Conversion of Little-Endian representations in byte streams - the data
+ * representation in the integer values is the host representation.
+ */
+static inline uint32_t ptr_to_le32(const uint8_t *p)
+{
+       return (uint32_t)p[0]       | (uint32_t)p[1] << 8 |
+              (uint32_t)p[2] << 16 | (uint32_t)p[3] << 24;
+}
+
+static inline uint64_t ptr_to_le64(const uint8_t *p)
+{
+       return (uint64_t)ptr_to_le32(p) | (uint64_t)ptr_to_le32(p + 4) << 32;
+}
+
+static inline void le32_to_ptr(uint8_t *p, const uint32_t value)
+{
+       p[0] = (uint8_t)(value);
+       p[1] = (uint8_t)(value >> 8);
+       p[2] = (uint8_t)(value >> 16);
+       p[3] = (uint8_t)(value >> 24);
+}
+
+static inline void le64_to_ptr(uint8_t *p, const uint64_t value)
+{
+       le32_to_ptr(p + 4, (uint32_t)(value >> 32));
+       le32_to_ptr(p,     (uint32_t)(value));
+}
+
+/*********************************** Keccak ***********************************/
+/* state[x + y*5] */
+#define A(x, y) (x + 5 * y)
+
+static inline void keccakp_theta(uint64_t s[25])
+{
+       uint64_t C[5], D[5];
+
+       /* Step 1 */
+       C[0] = s[A(0, 0)] ^ s[A(0, 1)] ^ s[A(0, 2)] ^ s[A(0, 3)] ^ s[A(0, 4)];
+       C[1] = s[A(1, 0)] ^ s[A(1, 1)] ^ s[A(1, 2)] ^ s[A(1, 3)] ^ s[A(1, 4)];
+       C[2] = s[A(2, 0)] ^ s[A(2, 1)] ^ s[A(2, 2)] ^ s[A(2, 3)] ^ s[A(2, 4)];
+       C[3] = s[A(3, 0)] ^ s[A(3, 1)] ^ s[A(3, 2)] ^ s[A(3, 3)] ^ s[A(3, 4)];
+       C[4] = s[A(4, 0)] ^ s[A(4, 1)] ^ s[A(4, 2)] ^ s[A(4, 3)] ^ s[A(4, 4)];
+
+       /* Step 2 */
+       D[0] = C[4] ^ rol64(C[1], 1);
+       D[1] = C[0] ^ rol64(C[2], 1);
+       D[2] = C[1] ^ rol64(C[3], 1);
+       D[3] = C[2] ^ rol64(C[4], 1);
+       D[4] = C[3] ^ rol64(C[0], 1);
+
+       /* Step 3 */
+       s[A(0, 0)] ^= D[0];
+       s[A(1, 0)] ^= D[1];
+       s[A(2, 0)] ^= D[2];
+       s[A(3, 0)] ^= D[3];
+       s[A(4, 0)] ^= D[4];
+
+       s[A(0, 1)] ^= D[0];
+       s[A(1, 1)] ^= D[1];
+       s[A(2, 1)] ^= D[2];
+       s[A(3, 1)] ^= D[3];
+       s[A(4, 1)] ^= D[4];
+
+       s[A(0, 2)] ^= D[0];
+       s[A(1, 2)] ^= D[1];
+       s[A(2, 2)] ^= D[2];
+       s[A(3, 2)] ^= D[3];
+       s[A(4, 2)] ^= D[4];
+
+       s[A(0, 3)] ^= D[0];
+       s[A(1, 3)] ^= D[1];
+       s[A(2, 3)] ^= D[2];
+       s[A(3, 3)] ^= D[3];
+       s[A(4, 3)] ^= D[4];
+
+       s[A(0, 4)] ^= D[0];
+       s[A(1, 4)] ^= D[1];
+       s[A(2, 4)] ^= D[2];
+       s[A(3, 4)] ^= D[3];
+       s[A(4, 4)] ^= D[4];
+}
+
+static inline void keccakp_rho(uint64_t s[25])
+{
+       /* Step 1 */
+       /* s[A(0, 0)] = s[A(0, 0)]; */
+
+#define RHO_ROL(t)     (((t + 1) * (t + 2) / 2) % 64)
+       /* Step 3 */
+       s[A(1, 0)] = rol64(s[A(1, 0)], RHO_ROL(0));
+       s[A(0, 2)] = rol64(s[A(0, 2)], RHO_ROL(1));
+       s[A(2, 1)] = rol64(s[A(2, 1)], RHO_ROL(2));
+       s[A(1, 2)] = rol64(s[A(1, 2)], RHO_ROL(3));
+       s[A(2, 3)] = rol64(s[A(2, 3)], RHO_ROL(4));
+       s[A(3, 3)] = rol64(s[A(3, 3)], RHO_ROL(5));
+       s[A(3, 0)] = rol64(s[A(3, 0)], RHO_ROL(6));
+       s[A(0, 1)] = rol64(s[A(0, 1)], RHO_ROL(7));
+       s[A(1, 3)] = rol64(s[A(1, 3)], RHO_ROL(8));
+       s[A(3, 1)] = rol64(s[A(3, 1)], RHO_ROL(9));
+       s[A(1, 4)] = rol64(s[A(1, 4)], RHO_ROL(10));
+       s[A(4, 4)] = rol64(s[A(4, 4)], RHO_ROL(11));
+       s[A(4, 0)] = rol64(s[A(4, 0)], RHO_ROL(12));
+       s[A(0, 3)] = rol64(s[A(0, 3)], RHO_ROL(13));
+       s[A(3, 4)] = rol64(s[A(3, 4)], RHO_ROL(14));
+       s[A(4, 3)] = rol64(s[A(4, 3)], RHO_ROL(15));
+       s[A(3, 2)] = rol64(s[A(3, 2)], RHO_ROL(16));
+       s[A(2, 2)] = rol64(s[A(2, 2)], RHO_ROL(17));
+       s[A(2, 0)] = rol64(s[A(2, 0)], RHO_ROL(18));
+       s[A(0, 4)] = rol64(s[A(0, 4)], RHO_ROL(19));
+       s[A(4, 2)] = rol64(s[A(4, 2)], RHO_ROL(20));
+       s[A(2, 4)] = rol64(s[A(2, 4)], RHO_ROL(21));
+       s[A(4, 1)] = rol64(s[A(4, 1)], RHO_ROL(22));
+       s[A(1, 1)] = rol64(s[A(1, 1)], RHO_ROL(23));
+}
+
+static inline void keccakp_pi(uint64_t s[25])
+{
+       uint64_t t = s[A(4, 4)];
+
+       /* Step 1 */
+       /* s[A(0, 0)] = s[A(0, 0)]; */
+       s[A(4, 4)] = s[A(1, 4)];
+       s[A(1, 4)] = s[A(3, 1)];
+       s[A(3, 1)] = s[A(1, 3)];
+       s[A(1, 3)] = s[A(0, 1)];
+       s[A(0, 1)] = s[A(3, 0)];
+       s[A(3, 0)] = s[A(3, 3)];
+       s[A(3, 3)] = s[A(2, 3)];
+       s[A(2, 3)] = s[A(1, 2)];
+       s[A(1, 2)] = s[A(2, 1)];
+       s[A(2, 1)] = s[A(0, 2)];
+       s[A(0, 2)] = s[A(1, 0)];
+       s[A(1, 0)] = s[A(1, 1)];
+       s[A(1, 1)] = s[A(4, 1)];
+       s[A(4, 1)] = s[A(2, 4)];
+       s[A(2, 4)] = s[A(4, 2)];
+       s[A(4, 2)] = s[A(0, 4)];
+       s[A(0, 4)] = s[A(2, 0)];
+       s[A(2, 0)] = s[A(2, 2)];
+       s[A(2, 2)] = s[A(3, 2)];
+       s[A(3, 2)] = s[A(4, 3)];
+       s[A(4, 3)] = s[A(3, 4)];
+       s[A(3, 4)] = s[A(0, 3)];
+       s[A(0, 3)] = s[A(4, 0)];
+       s[A(4, 0)] = t;
+}
+
+static inline void keccakp_chi(uint64_t s[25])
+{
+       uint64_t t0[5], t1[5];
+
+       t0[0] = s[A(0, 0)];
+       t0[1] = s[A(0, 1)];
+       t0[2] = s[A(0, 2)];
+       t0[3] = s[A(0, 3)];
+       t0[4] = s[A(0, 4)];
+
+       t1[0] = s[A(1, 0)];
+       t1[1] = s[A(1, 1)];
+       t1[2] = s[A(1, 2)];
+       t1[3] = s[A(1, 3)];
+       t1[4] = s[A(1, 4)];
+
+       s[A(0, 0)] ^= ~s[A(1, 0)] & s[A(2, 0)];
+       s[A(0, 1)] ^= ~s[A(1, 1)] & s[A(2, 1)];
+       s[A(0, 2)] ^= ~s[A(1, 2)] & s[A(2, 2)];
+       s[A(0, 3)] ^= ~s[A(1, 3)] & s[A(2, 3)];
+       s[A(0, 4)] ^= ~s[A(1, 4)] & s[A(2, 4)];
+
+       s[A(1, 0)] ^= ~s[A(2, 0)] & s[A(3, 0)];
+       s[A(1, 1)] ^= ~s[A(2, 1)] & s[A(3, 1)];
+       s[A(1, 2)] ^= ~s[A(2, 2)] & s[A(3, 2)];
+       s[A(1, 3)] ^= ~s[A(2, 3)] & s[A(3, 3)];
+       s[A(1, 4)] ^= ~s[A(2, 4)] & s[A(3, 4)];
+
+       s[A(2, 0)] ^= ~s[A(3, 0)] & s[A(4, 0)];
+       s[A(2, 1)] ^= ~s[A(3, 1)] & s[A(4, 1)];
+       s[A(2, 2)] ^= ~s[A(3, 2)] & s[A(4, 2)];
+       s[A(2, 3)] ^= ~s[A(3, 3)] & s[A(4, 3)];
+       s[A(2, 4)] ^= ~s[A(3, 4)] & s[A(4, 4)];
+
+       s[A(3, 0)] ^= ~s[A(4, 0)] & t0[0];
+       s[A(3, 1)] ^= ~s[A(4, 1)] & t0[1];
+       s[A(3, 2)] ^= ~s[A(4, 2)] & t0[2];
+       s[A(3, 3)] ^= ~s[A(4, 3)] & t0[3];
+       s[A(3, 4)] ^= ~s[A(4, 4)] & t0[4];
+
+       s[A(4, 0)] ^= ~t0[0] & t1[0];
+       s[A(4, 1)] ^= ~t0[1] & t1[1];
+       s[A(4, 2)] ^= ~t0[2] & t1[2];
+       s[A(4, 3)] ^= ~t0[3] & t1[3];
+       s[A(4, 4)] ^= ~t0[4] & t1[4];
+}
+
+static const uint64_t keccakp_iota_vals[] = {
+       0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
+       0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
+       0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
+       0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
+       0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
+       0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
+       0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
+       0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
+};
+
+static inline void keccakp_iota(uint64_t s[25], unsigned int round)
+{
+       s[0] ^= keccakp_iota_vals[round];
+}
+
+static inline void keccakp_1600(uint64_t s[25])
+{
+       unsigned int round;
+
+       for (round = 0; round < 24; round++) {
+               keccakp_theta(s);
+               keccakp_rho(s);
+               keccakp_pi(s);
+               keccakp_chi(s);
+               keccakp_iota(s, round);
+       }
+}
+
+/*********************************** SHA-3 ************************************/
+
+static inline void sha3_init(struct sha_ctx *ctx)
+{
+       unsigned int i;
+
+       for (i = 0; i < 25; i++)
+               ctx->state[i] = 0;
+       ctx->msg_len = 0;
+}
+
+void sha3_256_init(struct sha_ctx *ctx)
+{
+       sha3_init(ctx);
+       ctx->r = SHA3_256_SIZE_BLOCK;
+       ctx->rword = SHA3_256_SIZE_BLOCK / sizeof(uint64_t);
+       ctx->digestsize = SHA3_256_SIZE_DIGEST;
+}
+
+static inline void sha3_fill_state(struct sha_ctx *ctx, const uint8_t *in)
+{
+       unsigned int i;
+
+       for (i = 0; i < ctx->rword; i++) {
+               ctx->state[i]  ^= ptr_to_le64(in);
+               in += 8;
+       }
+}
+
+void sha3_update(struct sha_ctx *ctx, const uint8_t *in, size_t inlen)
+{
+       size_t partial = ctx->msg_len % ctx->r;
+
+       ctx->msg_len += inlen;
+
+       /* Sponge absorbing phase */
+
+       /* Check if we have a partial block stored */
+       if (partial) {
+               size_t todo = ctx->r - partial;
+
+               /*
+                * If the provided data is small enough to fit in the partial
+                * buffer, copy it and leave it unprocessed.
+                */
+               if (inlen < todo) {
+                       memcpy(ctx->partial + partial, in, inlen);
+                       return;
+               }
+
+               /*
+                * The input data is large enough to fill the entire partial
+                * block buffer. Thus, we fill it and transform it.
+                */
+               memcpy(ctx->partial + partial, in, todo);
+               inlen -= todo;
+               in += todo;
+
+               sha3_fill_state(ctx, ctx->partial);
+               keccakp_1600(ctx->state);
+       }
+
+       /* Perform a transformation of full block-size messages */
+       for (; inlen >= ctx->r; inlen -= ctx->r, in += ctx->r) {
+               sha3_fill_state(ctx, in);
+               keccakp_1600(ctx->state);
+       }
+
+       /* If we have data left, copy it into the partial block buffer */
+       memcpy(ctx->partial, in, inlen);
+}
+
+void sha3_final(struct sha_ctx *ctx, uint8_t *digest)
+{
+       size_t partial = ctx->msg_len % ctx->r;
+       unsigned int i;
+
+       /* Final round in sponge absorbing phase */
+
+       /* Fill the unused part of the partial buffer with zeros */
+       memset(ctx->partial + partial, 0, ctx->r - partial);
+
+       /*
+        * Add the leading and trailing bit as well as the 01 bits for the
+        * SHA-3 suffix.
+        */
+       ctx->partial[partial] = 0x06;
+       ctx->partial[ctx->r - 1] |= 0x80;
+
+       /* Final transformation */
+       sha3_fill_state(ctx, ctx->partial);
+       keccakp_1600(ctx->state);
+
+       /*
+        * Sponge squeeze phase - the digest size is always smaller as the
+        * state size r which implies we only have one squeeze round.
+        */
+       for (i = 0; i < ctx->digestsize / 8; i++, digest += 8)
+               le64_to_ptr(digest, ctx->state[i]);
+
+       /* Add remaining 4 bytes if we use SHA3-224 */
+       if (ctx->digestsize % 8)
+               le32_to_ptr(digest, (uint32_t)(ctx->state[i]));
+
+       memset(ctx->partial, 0, ctx->r);
+       sha3_init(ctx);
+}
+
+int sha3_tester(void)
+{
+       HASH_CTX_ON_STACK(ctx);
+       static const uint8_t msg_256[] = { 0x5E, 0x5E, 0xD6 };
+       static const uint8_t exp_256[] = { 0xF1, 0x6E, 0x66, 0xC0, 0x43, 0x72,
+                                          0xB4, 0xA3, 0xE1, 0xE3, 0x2E, 0x07,
+                                          0xC4, 0x1C, 0x03, 0x40, 0x8A, 0xD5,
+                                          0x43, 0x86, 0x8C, 0xC4, 0x0E, 0xC5,
+                                          0x5E, 0x00, 0xBB, 0xBB, 0xBD, 0xF5,
+                                          0x91, 0x1E };
+       uint8_t act[SHA3_256_SIZE_DIGEST] = { 0 };
+       unsigned int i;
+
+       sha3_256_init(&ctx);
+       sha3_update(&ctx, msg_256, 3);
+       sha3_final(&ctx, act);
+
+       for (i = 0; i < SHA3_256_SIZE_DIGEST; i++) {
+               if (exp_256[i] != act[i])
+                       return 1;
+       }
+
+       return 0;
+}
diff --git a/random/jitterentropy-sha3.h b/random/jitterentropy-sha3.h
new file mode 100644 (file)
index 0000000..27deb22
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef JITTERENTROPY_SHA3_H
+#define JITTERENTROPY_SHA3_H
+
+#include "jitterentropy.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define SHA3_SIZE_BLOCK(bits)  ((1600 - 2 * bits) >> 3)
+#define SHA3_256_SIZE_BLOCK    SHA3_SIZE_BLOCK(SHA3_256_SIZE_DIGEST_BITS)
+#define SHA3_MAX_SIZE_BLOCK    SHA3_256_SIZE_BLOCK
+
+struct sha_ctx {
+       uint64_t state[25];
+       size_t msg_len;
+       unsigned int r;
+       unsigned int rword;
+       unsigned int digestsize;
+       uint8_t partial[SHA3_MAX_SIZE_BLOCK];
+};
+
+#define SHA_MAX_CTX_SIZE       (sizeof(struct sha_ctx))
+#define HASH_CTX_ON_STACK(name)                                                       \
+       struct sha_ctx name
+
+void sha3_256_init(struct sha_ctx *ctx);
+void sha3_update(struct sha_ctx *ctx, const uint8_t *in, size_t inlen);
+void sha3_final(struct sha_ctx *ctx, uint8_t *digest);
+int sha3_tester(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JITTERENTROPY_SHA3_H */
diff --git a/random/jitterentropy-timer.c b/random/jitterentropy-timer.c
new file mode 100644 (file)
index 0000000..72b17ce
--- /dev/null
@@ -0,0 +1,234 @@
+/* Jitter RNG: Internal timer implementation
+ *
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "jitterentropy-base.h"
+#include "jitterentropy-timer.h"
+
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+
+/***************************************************************************
+ * Thread handler
+ ***************************************************************************/
+
+JENT_PRIVATE_STATIC
+int jent_notime_init(void **ctx)
+{
+       struct jent_notime_ctx *thread_ctx;
+       long ncpu = jent_ncpu();
+
+       if (ncpu < 0)
+               return (int)ncpu;
+
+       /* We need at least two CPUs to enable the timer thread */
+       if (ncpu < 2)
+               return -EOPNOTSUPP;
+
+       thread_ctx = calloc(1, sizeof(struct jent_notime_ctx));
+       if (!thread_ctx)
+               return -errno;
+
+       *ctx = thread_ctx;
+
+       return 0;
+}
+
+JENT_PRIVATE_STATIC
+void jent_notime_fini(void *ctx)
+{
+       struct jent_notime_ctx *thread_ctx = (struct jent_notime_ctx *)ctx;
+
+       if (thread_ctx)
+               free(thread_ctx);
+}
+
+static int jent_notime_start(void *ctx,
+                            void *(*start_routine) (void *), void *arg)
+{
+       struct jent_notime_ctx *thread_ctx = (struct jent_notime_ctx *)ctx;
+       int ret;
+
+       if (!thread_ctx)
+               return -EINVAL;
+
+       ret = -pthread_attr_init(&thread_ctx->notime_pthread_attr);
+       if (ret)
+               return ret;
+
+       return -pthread_create(&thread_ctx->notime_thread_id,
+                              &thread_ctx->notime_pthread_attr,
+                              start_routine, arg);
+}
+
+static void jent_notime_stop(void *ctx)
+{
+       struct jent_notime_ctx *thread_ctx = (struct jent_notime_ctx *)ctx;
+
+       pthread_join(thread_ctx->notime_thread_id, NULL);
+       pthread_attr_destroy(&thread_ctx->notime_pthread_attr);
+}
+
+static struct jent_notime_thread jent_notime_thread_builtin = {
+       .jent_notime_init  = jent_notime_init,
+       .jent_notime_fini  = jent_notime_fini,
+       .jent_notime_start = jent_notime_start,
+       .jent_notime_stop  = jent_notime_stop
+};
+
+/***************************************************************************
+ * Timer-less timer replacement
+ *
+ * If there is no high-resolution hardware timer available, we create one
+ * ourselves. This logic is only used when the initialization identifies
+ * that no suitable time source is available.
+ ***************************************************************************/
+
+static int jent_force_internal_timer = 0;
+static int jent_notime_switch_blocked = 0;
+
+void jent_notime_block_switch(void)
+{
+       jent_notime_switch_blocked = 1;
+}
+
+static struct jent_notime_thread *notime_thread = &jent_notime_thread_builtin;
+
+/**
+ * Timer-replacement loop
+ *
+ * @brief The measurement loop triggers the read of the value from the
+ * counter function. It conceptually acts as the low resolution
+ * samples timer from a ring oscillator.
+ */
+static void *jent_notime_sample_timer(void *arg)
+{
+       struct rand_data *ec = (struct rand_data *)arg;
+
+       ec->notime_timer = 0;
+
+       while (1) {
+               if (ec->notime_interrupt)
+                       return NULL;
+
+               ec->notime_timer++;
+       }
+
+       return NULL;
+}
+
+/*
+ * Enable the clock: spawn a new thread that holds a counter.
+ *
+ * Note, although creating a thread is expensive, we do that every time a
+ * caller wants entropy from us and terminate the thread afterwards. This
+ * is to ensure an attacker cannot easily identify the ticking thread.
+ */
+int jent_notime_settick(struct rand_data *ec)
+{
+       if (!ec->enable_notime || !notime_thread)
+               return 0;
+
+       ec->notime_interrupt = 0;
+       ec->notime_prev_timer = 0;
+       ec->notime_timer = 0;
+
+       return notime_thread->jent_notime_start(ec->notime_thread_ctx,
+                                              jent_notime_sample_timer, ec);
+}
+
+void jent_notime_unsettick(struct rand_data *ec)
+{
+       if (!ec->enable_notime || !notime_thread)
+               return;
+
+       ec->notime_interrupt = 1;
+       notime_thread->jent_notime_stop(ec->notime_thread_ctx);
+}
+
+void jent_get_nstime_internal(struct rand_data *ec, uint64_t *out)
+{
+       if (ec->enable_notime) {
+               /*
+                * Allow the counting thread to be initialized and guarantee
+                * that it ticked since last time we looked.
+                *
+                * Note, we do not use an atomic operation here for reading
+                * jent_notime_timer since if this integer is garbled, it even
+                * adds to entropy. But on most architectures, read/write
+                * of an uint64_t should be atomic anyway.
+                */
+               while (ec->notime_timer == ec->notime_prev_timer)
+                       jent_yield();
+
+               ec->notime_prev_timer = ec->notime_timer;
+               *out = ec->notime_prev_timer;
+       } else {
+               jent_get_nstime(out);
+       }
+}
+
+static inline int jent_notime_enable_thread(struct rand_data *ec)
+{
+       if (notime_thread)
+               return notime_thread->jent_notime_init(&ec->notime_thread_ctx);
+       return 0;
+}
+
+void jent_notime_disable(struct rand_data *ec)
+{
+       if (notime_thread)
+               notime_thread->jent_notime_fini(ec->notime_thread_ctx);
+}
+
+int jent_notime_enable(struct rand_data *ec, unsigned int flags)
+{
+       /* Use internal timer */
+       if (jent_force_internal_timer || (flags & JENT_FORCE_INTERNAL_TIMER)) {
+               /* Self test not run yet */
+               if (!jent_force_internal_timer &&
+                   jent_time_entropy_init(flags | JENT_FORCE_INTERNAL_TIMER,
+                                          ec->osr))
+                       return EHEALTH;
+
+               ec->enable_notime = 1;
+               return jent_notime_enable_thread(ec);
+       }
+
+       return 0;
+}
+
+int jent_notime_switch(struct jent_notime_thread *new_thread)
+{
+       if (jent_notime_switch_blocked)
+               return -EAGAIN;
+       notime_thread = new_thread;
+       return 0;
+}
+
+void jent_notime_force(void)
+{
+       jent_force_internal_timer = 1;
+}
+
+int jent_notime_forced(void)
+{
+       return jent_force_internal_timer;
+}
+
+#endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */
diff --git a/random/jitterentropy-timer.h b/random/jitterentropy-timer.h
new file mode 100644 (file)
index 0000000..039f233
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de>
+ *
+ * License: see LICENSE file in root directory
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#ifndef JITTERENTROPY_TIMER_H
+#define JITTERENTROPY_TIMER_H
+
+#include "jitterentropy.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+
+void jent_notime_block_switch(void);
+int jent_notime_settick(struct rand_data *ec);
+void jent_notime_unsettick(struct rand_data *ec);
+void jent_get_nstime_internal(struct rand_data *ec, uint64_t *out);
+int jent_notime_enable(struct rand_data *ec, unsigned int flags);
+void jent_notime_disable(struct rand_data *ec);
+int jent_notime_switch(struct jent_notime_thread *new_thread);
+void jent_notime_force(void);
+int jent_notime_forced(void);
+
+#else /* JENT_CONF_ENABLE_INTERNAL_TIMER */
+
+static inline void jent_notime_block_switch(void) { }
+
+static inline int jent_notime_settick(struct rand_data *ec)
+{
+       (void)ec;
+       return 0;
+}
+
+static inline void jent_notime_unsettick(struct rand_data *ec) { (void)ec; }
+
+static inline void jent_get_nstime_internal(struct rand_data *ec, uint64_t *out)
+{
+       (void)ec;
+       jent_get_nstime(out);
+}
+
+static inline int jent_notime_enable(struct rand_data *ec, unsigned int flags)
+{
+       (void)ec;
+
+       /* If we force the timer-less noise source, we return an error */
+       if (flags & JENT_FORCE_INTERNAL_TIMER)
+               return EHEALTH;
+
+       return 0;
+}
+
+static inline void jent_notime_disable(struct rand_data *ec)
+{
+       (void)ec;
+}
+
+static inline int jent_notime_switch(struct jent_notime_thread *new_thread)
+{
+       (void)new_thread;
+       return -EOPNOTSUPP;
+}
+
+static inline void jent_notime_force(void) { }
+
+static inline int jent_notime_forced(void) { return 0; }
+
+#endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* JITTERENTROPY-TIMER_H */
index 3b7d14a..97579bd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Non-physical true random number generator based on timing jitter.
  *
- * Copyright Stephan Mueller <smueller@chronox.de>, 2014
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014 - 2021
  *
  * License
  * =======
 #ifndef _JITTERENTROPY_H
 #define _JITTERENTROPY_H
 
-#ifdef __KERNEL__
-#include "jitterentropy-base-kernel.h"
-#else
+/***************************************************************************
+ * Jitter RNG Configuration Section
+ *
+ * You may alter the following options
+ ***************************************************************************/
+
+/*
+ * Enable timer-less timer support
+ *
+ * In case the hardware is identified to not provide a high-resolution time
+ * stamp, this option enables a built-in high-resolution time stamp mechanism.
+ *
+ * The timer-less noise source is based on threads. This noise source requires
+ * the linking with the POSIX threads library. I.e. the executing environment
+ * must offer POSIX threads. If this option is disabled, no linking
+ * with the POSIX threads library is needed.
+ */
+#undef JENT_CONF_ENABLE_INTERNAL_TIMER
+
+/*
+ * Disable the loop shuffle operation
+ *
+ * The shuffle operation enlarges the timing of the conditioning function
+ * by a variable length defined by the LSB of a time stamp. Some mathematicians
+ * are concerned that this pseudo-random selection of the loop iteration count
+ * may create some form of dependency between the different loop counts
+ * and the associated time duration of the conditioning function. It
+ * also complicates entropy assessment because it effectively combines a bunch
+ * of shifted/scaled copies the same distribution and masks failures from the
+ * health testing.
+ *
+ * By enabling this flag, the loop shuffle operation is disabled and
+ * the entropy collection operates in a way that honor the concerns.
+ *
+ * By enabling this flag, the time of collecting entropy may be enlarged.
+ */
+#define JENT_CONF_DISABLE_LOOP_SHUFFLE
+
+/*
+ * Shall the LAG predictor health test be enabled?
+ */
+#define JENT_HEALTH_LAG_PREDICTOR
+
+/*
+ * Shall the jent_memaccess use a (statistically) random selection for the
+ * memory to update?
+ */
+#define JENT_RANDOM_MEMACCESS
+
+/***************************************************************************
+ * Jitter RNG State Definition Section
+ ***************************************************************************/
+
 #include "jitterentropy-base-user.h"
-#endif /* __KERNEL__ */
+
+#define SHA3_256_SIZE_DIGEST_BITS      256
+#define SHA3_256_SIZE_DIGEST           (SHA3_256_SIZE_DIGEST_BITS >> 3)
+
+/*
+ * The output 256 bits can receive more than 256 bits of min entropy,
+ * of course, but the 256-bit output of SHA3-256(M) can only asymptotically
+ * approach 256 bits of min entropy, not attain that bound. Random maps will
+ * tend to have output collisions, which reduces the creditable output entropy
+ * (that is what SP 800-90B Section 3.1.5.1.2 attempts to bound).
+ *
+ * The value "64" is justified in Appendix A.4 of the current 90C draft,
+ * and aligns with NIST's in "epsilon" definition in this document, which is
+ * that a string can be considered "full entropy" if you can bound the min
+ * entropy in each bit of output to at least 1-epsilon, where epsilon is
+ * required to be <= 2^(-32).
+ */
+#define ENTROPY_SAFETY_FACTOR          64
+
+/**
+ * Function pointer data structure to register an external thread handler
+ * used for the timer-less mode of the Jitter RNG.
+ *
+ * The external caller provides these function pointers to handle the
+ * management of the timer thread that is spawned by the Jitter RNG.
+ *
+ * @var jent_notime_init This function is intended to initialze the threading
+ *     support. All data that is required by the threading code must be
+ *     held in the data structure @param ctx. The Jitter RNG maintains the
+ *     data structure and uses it for every invocation of the following calls.
+ *
+ * @var jent_notime_fini This function shall terminate the threading support.
+ *     The function must dispose of all memory and resources used for the
+ *     threading operation. It must also dispose of the @param ctx memory.
+ *
+ * @var jent_notime_start This function is called when the Jitter RNG wants
+ *     to start a thread. Besides providing a pointer to the @param ctx
+ *     allocated during initialization time, the Jitter RNG provides a
+ *     pointer to the function the thread shall execute and the argument
+ *     the function shall be invoked with. These two parameters have the
+ *     same purpose as the trailing two parameters of pthread_create(3).
+ *
+ * @var jent_notime_stop This function is invoked by the Jitter RNG when the
+ *     thread should be stopped. Note, the Jitter RNG intends to start/stop
+ *     the thread frequently.
+ *
+ * An example implementation is found in the Jitter RNG itself with its
+ * default thread handler of jent_notime_thread_builtin.
+ *
+ * If the caller wants to register its own thread handler, it must be done
+ * with the API call jent_entropy_switch_notime_impl as the first
+ * call to interact with the Jitter RNG, even before jent_entropy_init.
+ * After jent_entropy_init is called, changing of the threading implementation
+ * is not allowed.
+ */
+struct jent_notime_thread {
+       int (*jent_notime_init)(void **ctx);
+       void (*jent_notime_fini)(void *ctx);
+       int (*jent_notime_start)(void *ctx,
+                                void *(*start_routine) (void *), void *arg);
+       void (*jent_notime_stop)(void *ctx);
+};
 
 /* The entropy pool */
 struct rand_data
@@ -55,35 +166,179 @@ struct rand_data
         * of the RNG are marked as SENSITIVE. A user must not
         * access that information while the RNG executes its loops to
         * calculate the next random value. */
-       uint64_t data;          /* SENSITIVE Actual random number */
-       uint64_t old_data;      /* SENSITIVE Previous random number */
-       uint64_t prev_time;     /* SENSITIVE Previous time stamp */
-#define DATA_SIZE_BITS ((sizeof(uint64_t)) * 8)
-       uint64_t last_delta;    /* SENSITIVE stuck test */
-       int64_t last_delta2;    /* SENSITIVE stuck test */
-       unsigned int osr;       /* Oversample rate */
-       int fips_enabled;       /* FIPS enabled? */
-       unsigned int stir:1;            /* Post-processing stirring */
-       unsigned int disable_unbias:1;  /* Deactivate Von-Neuman unbias */
-#define JENT_MEMORY_BLOCKS 64
-#define JENT_MEMORY_BLOCKSIZE 32
+       uint8_t data[SHA3_256_SIZE_DIGEST]; /* SENSITIVE Actual random number */
+       uint64_t prev_time;             /* SENSITIVE Previous time stamp */
+#define DATA_SIZE_BITS (SHA3_256_SIZE_DIGEST_BITS)
+
+#ifndef JENT_HEALTH_LAG_PREDICTOR
+       uint64_t last_delta;            /* SENSITIVE stuck test */
+       uint64_t last_delta2;           /* SENSITIVE stuck test */
+#endif /* JENT_HEALTH_LAG_PREDICTOR */
+
+       unsigned int flags;             /* Flags used to initialize */
+       unsigned int osr;               /* Oversampling rate */
+
+#ifdef JENT_RANDOM_MEMACCESS
+  /* The step size should be larger than the cacheline size. */
+# ifndef JENT_MEMORY_BITS
+#  define JENT_MEMORY_BITS 17
+# endif
+# ifndef JENT_MEMORY_SIZE
+#  define JENT_MEMORY_SIZE (UINT32_C(1)<<JENT_MEMORY_BITS)
+# endif
+#else /* JENT_RANDOM_MEMACCESS */
+# ifndef JENT_MEMORY_BLOCKS
+#  define JENT_MEMORY_BLOCKS 512
+# endif
+# ifndef JENT_MEMORY_BLOCKSIZE
+#  define JENT_MEMORY_BLOCKSIZE 128
+# endif
+# ifndef JENT_MEMORY_SIZE
+#  define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
+# endif
+#endif /* JENT_RANDOM_MEMACCESS */
+
 #define JENT_MEMORY_ACCESSLOOPS 128
-#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
-       unsigned char *mem;     /* Memory access location with size of
-                                * memblocks * memblocksize */
-       unsigned int memlocation; /* Pointer to byte in *mem */
-       unsigned int memblocks; /* Number of memory blocks in *mem */
-       unsigned int memblocksize; /* Size of one memory block in bytes */
-       unsigned int memaccessloops; /* Number of memory accesses per random
-                                     * bit generation */
+       unsigned char *mem;             /* Memory access location with size of
+                                        * JENT_MEMORY_SIZE or memsize */
+#ifdef JENT_RANDOM_MEMACCESS
+       uint32_t memmask;               /* Memory mask (size of memory - 1) */
+#else
+       unsigned int memlocation;       /* Pointer to byte in *mem */
+       unsigned int memblocks;         /* Number of memory blocks in *mem */
+       unsigned int memblocksize;      /* Size of one memory block in bytes */
+#endif
+       unsigned int memaccessloops;    /* Number of memory accesses per random
+                                        * bit generation */
+
+       /* Repetition Count Test */
+       int rct_count;                  /* Number of stuck values */
+
+       /* Adaptive Proportion Test for a significance level of 2^-30 */
+       unsigned int apt_cutoff;        /* Calculated using a corrected version
+                                        * of the SP800-90B sec 4.4.2 formula */
+#define JENT_APT_WINDOW_SIZE   512     /* Data window size */
+       unsigned int apt_observations;  /* Number of collected observations in
+                                        * current window. */
+       unsigned int apt_count;         /* The number of times the reference
+                                        * symbol been encountered in the
+                                        * window. */
+       uint64_t apt_base;              /* APT base reference */
+       unsigned int health_failure;    /* Permanent health failure */
+
+       unsigned int apt_base_set:1;    /* APT base reference set? */
+       unsigned int fips_enabled:1;
+       unsigned int enable_notime:1;   /* Use internal high-res timer */
+       unsigned int max_mem_set:1;     /* Maximum memory configured by user */
+
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+       volatile uint8_t notime_interrupt;      /* indicator to interrupt ctr */
+       volatile uint64_t notime_timer;         /* high-res timer mock-up */
+       uint64_t notime_prev_timer;             /* previous timer value */
+       void *notime_thread_ctx;                /* register thread data */
+#endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */
+
+       uint64_t jent_common_timer_gcd; /* Common divisor for all time deltas */
+
+#ifdef JENT_HEALTH_LAG_PREDICTOR
+       /* Lag predictor test to look for re-occurring patterns. */
+
+       /* The lag global cutoff selected based on the selection of osr. */
+       unsigned int lag_global_cutoff;
+
+       /* The lag local cutoff selected based on the selection of osr. */
+       unsigned int lag_local_cutoff;
+
+       /*
+        * The number of times the lag predictor was correct. Compared to the
+        * global cutoff.
+        */
+       unsigned int lag_prediction_success_count;
+
+       /*
+        * The size of the current run of successes. Compared to the local
+        * cutoff.
+        */
+       unsigned int lag_prediction_success_run;
+
+       /*
+        * The total number of collected observations since the health test was
+        * last reset.
+        */
+       unsigned int lag_best_predictor;
+
+       /*
+        * The total number of collected observations since the health test was
+        * last reset.
+        */
+       unsigned int lag_observations;
+
+       /*
+        * This is the size of the window used by the predictor. The predictor
+        * is reset between windows.
+        */
+#define JENT_LAG_WINDOW_SIZE (1U<<17)
+
+       /*
+        * The amount of history to base predictions on. This must be a power
+        * of 2. Must be 4 or greater.
+        */
+#define JENT_LAG_HISTORY_SIZE 8
+#define JENT_LAG_MASK (JENT_LAG_HISTORY_SIZE - 1)
+
+       /* The delta history for the lag predictor. */
+       uint64_t lag_delta_history[JENT_LAG_HISTORY_SIZE];
+
+       /* The scoreboard that tracks how successful each predictor lag is. */
+       unsigned int lag_scoreboard[JENT_LAG_HISTORY_SIZE];
+#endif /* JENT_HEALTH_LAG_PREDICTOR */
 };
 
 /* Flags that can be used to initialize the RNG */
-#define JENT_DISABLE_STIR (1<<0) /* Disable stirring the entropy pool */
-#define JENT_DISABLE_UNBIAS (1<<1) /* Disable the Von-Neuman Unbiaser */
+#define JENT_DISABLE_STIR (1<<0)       /* UNUSED */
+#define JENT_DISABLE_UNBIAS (1<<1)     /* UNUSED */
 #define JENT_DISABLE_MEMORY_ACCESS (1<<2) /* Disable memory access for more
                                             entropy, saves MEMORY_SIZE RAM for
                                             entropy collector */
+#define JENT_FORCE_INTERNAL_TIMER (1<<3)  /* Force the use of the internal
+                                            timer */
+#define JENT_DISABLE_INTERNAL_TIMER (1<<4)  /* Disable the potential use of
+                                              the internal timer. */
+#define JENT_FORCE_FIPS (1<<5)           /* Force FIPS compliant mode
+                                            including full SP800-90B
+                                            compliance. */
+
+/* Flags field limiting the amount of memory to be used for memory access */
+#define JENT_FLAGS_TO_MEMSIZE_SHIFT    28
+#define JENT_FLAGS_TO_MAX_MEMSIZE(val) (val >> JENT_FLAGS_TO_MEMSIZE_SHIFT)
+#define JENT_MAX_MEMSIZE_TO_FLAGS(val) (val << JENT_FLAGS_TO_MEMSIZE_SHIFT)
+#define JENT_MAX_MEMSIZE_32kB          JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 1))
+#define JENT_MAX_MEMSIZE_64kB          JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 2))
+#define JENT_MAX_MEMSIZE_128kB         JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 3))
+#define JENT_MAX_MEMSIZE_256kB         JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 4))
+#define JENT_MAX_MEMSIZE_512kB         JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 5))
+#define JENT_MAX_MEMSIZE_1MB           JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 6))
+#define JENT_MAX_MEMSIZE_2MB           JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 7))
+#define JENT_MAX_MEMSIZE_4MB           JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 8))
+#define JENT_MAX_MEMSIZE_8MB           JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C( 9))
+#define JENT_MAX_MEMSIZE_16MB          JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(10))
+#define JENT_MAX_MEMSIZE_32MB          JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(11))
+#define JENT_MAX_MEMSIZE_64MB          JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(12))
+#define JENT_MAX_MEMSIZE_128MB         JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(13))
+#define JENT_MAX_MEMSIZE_256MB         JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(14))
+#define JENT_MAX_MEMSIZE_512MB         JENT_MAX_MEMSIZE_TO_FLAGS(UINT32_C(15))
+#define JENT_MAX_MEMSIZE_MAX           JENT_MAX_MEMSIZE_512MB
+#define JENT_MAX_MEMSIZE_MASK          JENT_MAX_MEMSIZE_MAX
+/* We start at 32kB -> offset is log2(32768) */
+#define JENT_MAX_MEMSIZE_OFFSET                14
+
+#ifdef JENT_CONF_DISABLE_LOOP_SHUFFLE
+# define JENT_MIN_OSR  3
+#else
+# define JENT_MIN_OSR  1
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
 /* -- BEGIN Main interface functions -- */
 
@@ -94,19 +349,21 @@ struct rand_data
  *
  * It is allowed to change this value as required for the intended environment.
  */
-#define JENT_STUCK_INIT_THRES(x) (x/10 * 9)
+#define JENT_STUCK_INIT_THRES(x) ((x*9) / 10)
 #endif
 
 #ifdef JENT_PRIVATE_COMPILE
 # define JENT_PRIVATE_STATIC static
 #else /* JENT_PRIVATE_COMPILE */
-# define JENT_PRIVATE_STATIC
+# define JENT_PRIVATE_STATIC __attribute__((visibility("default")))
 #endif
 
 /* Number of low bits of the time value that we want to consider */
 /* get raw entropy */
 JENT_PRIVATE_STATIC
 ssize_t jent_read_entropy(struct rand_data *ec, char *data, size_t len);
+JENT_PRIVATE_STATIC
+ssize_t jent_read_entropy_safe(struct rand_data **ec, char *data, size_t len);
 /* initialize an instance of the entropy collector */
 JENT_PRIVATE_STATIC
 struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
@@ -118,13 +375,47 @@ void jent_entropy_collector_free(struct rand_data *entropy_collector);
 /* initialization of entropy collector */
 JENT_PRIVATE_STATIC
 int jent_entropy_init(void);
+JENT_PRIVATE_STATIC
+int jent_entropy_init_ex(unsigned int osr, unsigned int flags);
 
 /* return version number of core library */
 JENT_PRIVATE_STATIC
 unsigned int jent_version(void);
 
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+/* Set a different thread handling logic for the notimer support */
+JENT_PRIVATE_STATIC
+int jent_entropy_switch_notime_impl(struct jent_notime_thread *new_thread);
+#endif
+
 /* -- END of Main interface functions -- */
 
+/* -- BEGIN timer-less threading support functions to prevent code dupes -- */
+
+struct jent_notime_ctx {
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+       pthread_attr_t notime_pthread_attr;     /* pthreads library */
+       pthread_t notime_thread_id;             /* pthreads thread ID */
+#endif
+};
+
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+
+JENT_PRIVATE_STATIC
+int jent_notime_init(void **ctx);
+
+JENT_PRIVATE_STATIC
+void jent_notime_fini(void *ctx);
+
+#else
+
+static inline int jent_notime_init(void **ctx) { (void)ctx; return 0; }
+static inline void jent_notime_fini(void *ctx) { (void)ctx; }
+
+#endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */
+
+/* -- END timer-less threading support functions to prevent code dupes -- */
+
 /* -- BEGIN error codes for init function -- */
 #define ENOTIME        1 /* Timer service not available */
 #define ECOARSETIME    2 /* Timer too coarse for RNG */
@@ -135,6 +426,18 @@ unsigned int jent_version(void);
 #define EMINVARVAR     6 /* Timer variations of variations is too small */
 #define EPROGERR       7 /* Programming error */
 #define ESTUCK         8 /* Too many stuck results during init. */
+#define EHEALTH                9 /* Health test failed during initialization */
+#define ERCT           10 /* RCT failed during initialization */
+#define EHASH          11 /* Hash self test failed */
+#define EMEM           12 /* Can't allocate memory for initialization */
+#define EGCD           13 /* GCD self-test failed */
+/* -- END error codes for init function -- */
+
+/* -- BEGIN error masks for health tests -- */
+#define JENT_RCT_FAILURE       1 /* Failure in RCT health test. */
+#define JENT_APT_FAILURE       2 /* Failure in APT health test. */
+#define JENT_LAG_FAILURE       4 /* Failure in Lag predictor health test. */
+/* -- END error masks for health tests -- */
 
 /* -- BEGIN statistical test functions only complied with CONFIG_CRYPTO_CPU_JITTERENTROPY_STAT -- */
 
index 2bc05f4..2d2b890 100644 (file)
@@ -51,8 +51,6 @@ void _gcry_rngcsprng_close_fds (void);
 void _gcry_rngcsprng_dump_stats (void);
 void _gcry_rngcsprng_secure_alloc (void);
 void _gcry_rngcsprng_enable_quick_gen (void);
-void _gcry_rngcsprng_set_daemon_socket (const char *socketname);
-int  _gcry_rngcsprng_use_daemon (int onoff);
 int  _gcry_rngcsprng_is_faked (void);
 gcry_error_t _gcry_rngcsprng_add_bytes (const void *buf, size_t buflen,
                                         int quality);
@@ -89,11 +87,17 @@ void _gcry_rngsystem_randomize (void *buffer, size_t length,
 
 
 
-/*-- rndlinux.c --*/
-int _gcry_rndlinux_gather_random (void (*add) (const void *, size_t,
-                                               enum random_origins),
-                                   enum random_origins origin,
-                                  size_t length, int level);
+/*-- rndgetentropy.c --*/
+int _gcry_rndgetentropy_gather_random (void (*add) (const void *, size_t,
+                                                    enum random_origins),
+                                       enum random_origins origin,
+                                       size_t length, int level);
+
+/*-- rndoldlinux.c --*/
+int _gcry_rndoldlinux_gather_random (void (*add) (const void *, size_t,
+                                                  enum random_origins),
+                                     enum random_origins origin,
+                                     size_t length, int level);
 
 /*-- rndunix.c --*/
 int _gcry_rndunix_gather_random (void (*add) (const void *, size_t,
@@ -132,6 +136,7 @@ size_t _gcry_rndjent_poll (void (*add)(const void*,
                            enum random_origins origin,
                            size_t length);
 void _gcry_rndjent_dump_stats (void);
+void _gcry_rndjent_fini (void);
 
 /*-- rndhw.c --*/
 int _gcry_rndhw_failed_p (void);
@@ -140,7 +145,7 @@ void _gcry_rndhw_poll_fast (void (*add)(const void*, size_t,
                             enum random_origins origin);
 size_t _gcry_rndhw_poll_slow (void (*add)(const void*, size_t,
                                           enum random_origins),
-                              enum random_origins origin);
+                              enum random_origins origin, size_t req_length);
 
 
 
index 8cb35e7..85d1178 100644 (file)
@@ -55,6 +55,9 @@
 #ifdef __MINGW32__
 #include <process.h>
 #endif
+#ifdef HAVE_W32_SYSTEM
+#include <windows.h>
+#endif
 #include "g10lib.h"
 #include "random.h"
 #include "rand-internal.h"
@@ -140,7 +143,7 @@ static int pool_balance;
 static int just_mixed;
 
 /* The name of the seed file or NULL if no seed file has been defined.
-   The seed file needs to be regsitered at initialiation time.  We
+   The seed file needs to be registered at initialization time.  We
    keep a malloced copy here.  */
 static char *seed_file_name;
 
@@ -201,26 +204,6 @@ static struct
 
 
 
-/* --- Stuff pertaining to the random daemon support. --- */
-#ifdef USE_RANDOM_DAEMON
-
-/* If ALLOW_DAEMON is true, the module will try to use the random
-   daemon first.  If the daemon has failed, this variable is set to
-   back to false and the code continues as normal.  Note, we don't
-   test this flag in a locked state because a wrong value does not
-   harm and the trhead will find out itself that the daemon does not
-   work and set it (again) to false.  */
-static int allow_daemon;
-
-/* During initialization, the user may set a non-default socket name
-   for accessing the random daemon.  If this value is NULL, the
-   default name will be used. */
-static char *daemon_socket_name;
-
-#endif /*USE_RANDOM_DAEMON*/
-
-
-
 /* ---  Prototypes  --- */
 static void read_pool (byte *buffer, size_t length, int level );
 static void add_randomness (const void *buffer, size_t length,
@@ -255,10 +238,6 @@ initialize_basics(void)
     {
       initialized = 1;
 
-#ifdef USE_RANDOM_DAEMON
-      _gcry_daemon_initialize_basics ();
-#endif /*USE_RANDOM_DAEMON*/
-
       /* Make sure that we are still using the values we have
          traditionally used for the random levels.  */
       gcry_assert (GCRY_WEAK_RANDOM == 0
@@ -344,15 +323,28 @@ _gcry_rngcsprng_initialize (int full)
 
 
 /* Try to close the FDs of the random gather module.  This is
-   currently only implemented for rndlinux. */
+   currently only implemented for rndgetentropy/rndoldlinux. */
 void
 _gcry_rngcsprng_close_fds (void)
 {
   lock_pool ();
-#if USE_RNDLINUX
-  _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
-  pool_filled = 0; /* Force re-open on next use.  */
+#if USE_RNDGETENTROPY
+  _gcry_rndgetentropy_gather_random (NULL, 0, 0, 0);
 #endif
+#if USE_RNDOLDLINUX
+  _gcry_rndoldlinux_gather_random (NULL, 0, 0, 0);
+#endif
+  pool_writepos = 0;
+  pool_readpos = 0;
+  pool_filled = 0;
+  pool_filled_counter = 0;
+  did_initial_extra_seeding = 0;
+  pool_balance = 0;
+  just_mixed = 0;
+  xfree (rndpool);
+  xfree (keypool);
+  rndpool = NULL;
+  keypool = NULL;
   unlock_pool ();
 }
 
@@ -393,45 +385,6 @@ _gcry_rngcsprng_enable_quick_gen (void)
 }
 
 
-void
-_gcry_rngcsprng_set_daemon_socket (const char *socketname)
-{
-#ifdef USE_RANDOM_DAEMON
-  if (daemon_socket_name)
-    BUG ();
-
-  daemon_socket_name = gcry_xstrdup (socketname);
-#else /*!USE_RANDOM_DAEMON*/
-  (void)socketname;
-#endif /*!USE_RANDOM_DAEMON*/
-}
-
-/* With ONOFF set to 1, enable the use of the daemon.  With ONOFF set
-   to 0, disable the use of the daemon.  With ONOF set to -1, return
-   whether the daemon has been enabled. */
-int
-_gcry_rngcsprng_use_daemon (int onoff)
-{
-#ifdef USE_RANDOM_DAEMON
-  int last;
-
-  /* This is not really thread safe.  However it is expected that this
-     function is being called during initialization and at that point
-     we are for other reasons not really thread safe.  We do not want
-     to lock it because we might eventually decide that this function
-     may even be called prior to gcry_check_version.  */
-  last = allow_daemon;
-  if (onoff != -1)
-    allow_daemon = onoff;
-
-  return last;
-#else /*!USE_RANDOM_DAEMON*/
-  (void)onoff;
-  return 0;
-#endif /*!USE_RANDOM_DAEMON*/
-}
-
-
 /* This function returns true if no real RNG is available or the
    quality of the RNG has been degraded for test purposes.  */
 int
@@ -507,13 +460,6 @@ _gcry_rngcsprng_randomize (void *buffer, size_t length,
   /* Make sure the level is okay. */
   level &= 3;
 
-#ifdef USE_RANDOM_DAEMON
-  if (allow_daemon
-      && !_gcry_daemon_randomize (daemon_socket_name, buffer, length, level))
-    return; /* The daemon succeeded. */
-  allow_daemon = 0; /* Daemon failed - switch off. */
-#endif /*USE_RANDOM_DAEMON*/
-
   /* Acquire the pool lock. */
   lock_pool ();
 
@@ -667,6 +613,88 @@ _gcry_rngcsprng_set_seed_file (const char *name)
 }
 
 
+
+/* Helper for my_open.
+ * Return a malloced wide char string from an UTF-8 encoded input
+ * string STRING.  Caller must free this value.  Returns NULL and sets
+ * ERRNO on failure.  Calling this function with STRING set to NULL is
+ * not defined.  */
+#ifdef HAVE_W32_SYSTEM
+static wchar_t *
+utf8_to_wchar (const char *string)
+{
+  int n;
+  size_t nbytes;
+  wchar_t *result;
+
+  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
+  if (n < 0)
+    {
+      gpg_err_set_errno (EINVAL);
+      return NULL;
+    }
+
+  nbytes = (size_t)(n+1) * sizeof(*result);
+  if (nbytes / sizeof(*result) != (n+1))
+    {
+      gpg_err_set_errno (ENOMEM);
+      return NULL;
+    }
+  result = xtrymalloc (nbytes);
+  if (!result)
+    return NULL;
+
+  n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
+  if (n < 0)
+    {
+      xfree (result);
+      gpg_err_set_errno (EINVAL);
+      result = NULL;
+    }
+  return result;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* Helper for my_open.  */
+#ifdef HAVE_W32_SYSTEM
+static int
+any8bitchar (const char *string)
+{
+  if (string)
+    for ( ; *string; string++)
+      if ((*string & 0x80))
+        return 1;
+  return 0;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* A wrapper around open to handle Unicode file names under Windows.  */
+static int
+my_open (const char *name, int flags, unsigned int mode)
+{
+#ifdef HAVE_W32_SYSTEM
+  if (any8bitchar (name))
+    {
+      wchar_t *wname;
+      int ret;
+
+      wname = utf8_to_wchar (name);
+      if (!wname)
+        return -1;
+      ret = _wopen (wname, flags, mode);
+      xfree (wname);
+      return ret;
+    }
+  else
+    return open (name, flags, mode);
+#else
+  return open (name, flags, mode);
+#endif
+}
+
+
 /* Lock an open file identified by file descriptor FD and wait a
    reasonable time to succeed.  With FOR_WRITE set to true a write
    lock will be taken.  FNAME is used only for diagnostics. Returns 0
@@ -704,6 +732,10 @@ lock_seed_file (int fd, const char *fname, int for_write)
       if (backoff < 10)
         backoff++ ;
     }
+#else
+  (void)fd;
+  (void)fname;
+  (void)for_write;
 #endif /*!LOCK_SEED_FILE*/
   return 0;
 }
@@ -738,9 +770,9 @@ read_seed_file (void)
     return 0;
 
 #ifdef HAVE_DOSISH_SYSTEM
-  fd = open( seed_file_name, O_RDONLY | O_BINARY );
+  fd = my_open (seed_file_name, O_RDONLY | O_BINARY, 0);
 #else
-  fd = open( seed_file_name, O_RDONLY );
+  fd = my_open (seed_file_name, O_RDONLY, 0);
 #endif
   if( fd == -1 && errno == ENOENT)
     {
@@ -869,13 +901,13 @@ _gcry_rngcsprng_update_seed_file (void)
   mix_pool(keypool); rndstats.mixkey++;
 
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
-  fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
-             S_IRUSR|S_IWUSR );
+  fd = my_open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
+                S_IRUSR|S_IWUSR );
 #else
 # if LOCK_SEED_FILE
-    fd = open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
+    fd = my_open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
 # else
-    fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
+    fd = my_open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
 # endif
 #endif
 
@@ -1115,11 +1147,16 @@ getfnc_gather_random (void))(void (*)(const void*, size_t,
   int (*fnc)(void (*)(const void*, size_t, enum random_origins),
              enum random_origins, size_t, int);
 
-#if USE_RNDLINUX
+#if USE_RNDGETENTROPY
+  fnc = _gcry_rndgetentropy_gather_random;
+  return fnc;
+#endif
+
+#if USE_RNDOLDLINUX
   if ( !access (NAME_OF_DEV_RANDOM, R_OK)
        && !access (NAME_OF_DEV_URANDOM, R_OK))
     {
-      fnc = _gcry_rndlinux_gather_random;
+      fnc = _gcry_rndoldlinux_gather_random;
       return fnc;
     }
 #endif
diff --git a/random/random-daemon.c b/random/random-daemon.c
deleted file mode 100644 (file)
index 8ea4df2..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-/* random-daemon.c  - Access to the external random daemon
- * Copyright (C) 2006  Free Software Foundation, Inc.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-/*
-   The functions here are used by random.c to divert calls to an
-   external random number daemon.  The actual daemon we use is
-   gcryptrnd.  Such a daemon is useful to keep a persistent pool in
-   memory over invocations of a single application and to allow
-   prioritizing access to the actual entropy sources.  The drawback is
-   that we need to use IPC (i.e. unix domain socket) to convey
-   sensitive data.
- */
-
-#include <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include "g10lib.h"
-#include "random.h"
-
-\f
-
-/* This is default socket name we use in case the provided socket name
-   is NULL.  */
-#define RANDOM_DAEMON_SOCKET "/var/run/libgcrypt/S.gcryptrnd"
-
-/* The lock serializing access to the daemon.  */
-GPGRT_LOCK_DEFINE (daemon_lock);
-
-/* The socket connected to the daemon.  */
-static int daemon_socket = -1;
-
-/* Creates a socket connected to the daemon.  On success, store the
-   socket fd in *SOCK.  Returns error code.  */
-static gcry_error_t
-connect_to_socket (const char *socketname, int *sock)
-{
-  struct sockaddr_un *srvr_addr;
-  socklen_t addrlen;
-  gcry_error_t err;
-  int fd;
-  int rc;
-
-  srvr_addr = NULL;
-
-  /* Create a socket. */
-  fd = socket (AF_UNIX, SOCK_STREAM, 0);
-  if (fd == -1)
-    {
-      log_error ("can't create socket: %s\n", strerror (errno));
-      err = gcry_error_from_errno (errno);
-      goto out;
-    }
-
-  /* Set up address.  */
-  srvr_addr = gcry_malloc (sizeof *srvr_addr);
-  if (! srvr_addr)
-    {
-      log_error ("malloc failed: %s\n", strerror (errno));
-      err = gcry_error_from_errno (errno);
-      goto out;
-    }
-  memset (srvr_addr, 0, sizeof *srvr_addr);
-  srvr_addr->sun_family = AF_UNIX;
-  if (strlen (socketname) + 1 >= sizeof (srvr_addr->sun_path))
-    {
-      log_error ("socket name `%s' too long\n", socketname);
-      err = gcry_error (GPG_ERR_ENAMETOOLONG);
-      goto out;
-    }
-  strcpy (srvr_addr->sun_path, socketname);
-  addrlen = (offsetof (struct sockaddr_un, sun_path)
-             + strlen (srvr_addr->sun_path) + 1);
-
-  /* Connect socket.  */
-  rc = connect (fd, (struct sockaddr *) srvr_addr, addrlen);
-  if (rc == -1)
-    {
-      log_error ("error connecting socket `%s': %s\n",
-                srvr_addr->sun_path, strerror (errno));
-      err = gcry_error_from_errno (errno);
-      goto out;
-    }
-
-  err = 0;
-
- out:
-
-  gcry_free (srvr_addr);
-  if (err)
-    {
-      close (fd);
-      fd = -1;
-    }
-  *sock = fd;
-
-  return err;
-}
-
-
-/* Initialize basics of this module. This should be viewed as a
-   constructor to prepare locking. */
-void
-_gcry_daemon_initialize_basics (void)
-{
-  /* Not anymore required.  */
-}
-
-
-
-/* Send LENGTH bytes of BUFFER to file descriptor FD.  Returns 0 on
-   success or another value on write error. */
-static int
-writen (int fd, const void *buffer, size_t length)
-{
-  ssize_t n;
-
-  while (length)
-    {
-      do
-        n = ath_write (fd, buffer, length);
-      while (n < 0 && errno == EINTR);
-      if (n < 0)
-         {
-           log_error ("write error: %s\n", strerror (errno));
-           return -1; /* write error */
-         }
-      length -= n;
-      buffer = (const char*)buffer + n;
-    }
-  return 0;  /* Okay */
-}
-
-static int
-readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
-{
-  size_t nleft = buflen;
-  int nread;
-  char *p;
-
-  p = buf;
-  while (nleft > 0)
-    {
-      nread = ath_read (fd, buf, nleft);
-      if (nread < 0)
-        {
-          if (nread == EINTR)
-            nread = 0;
-          else
-            return -1;
-        }
-      else if (!nread)
-        break; /* EOF */
-      nleft -= nread;
-      buf = (char*)buf + nread;
-    }
-  if (ret_nread)
-    *ret_nread = buflen - nleft;
-  return 0;
-}
-
-/* This functions requests REQ_NBYTES from the daemon.  If NONCE is
-   true, the data should be suited for a nonce.  If NONCE is FALSE,
-   data of random level LEVEL will be generated.  The retrieved random
-   data will be stored in BUFFER.  Returns error code.  */
-static gcry_error_t
-call_daemon (const char *socketname,
-             void *buffer, size_t req_nbytes, int nonce,
-            enum gcry_random_level level)
-{
-  static int initialized;
-  unsigned char buf[255];
-  gcry_error_t err = 0;
-  size_t nbytes;
-  size_t nread;
-  int rc;
-
-  if (!req_nbytes)
-    return 0;
-
-  gpgrt_lock_lock (&daemon_lock);
-
-  /* Open the socket if that has not been done. */
-  if (!initialized)
-    {
-      initialized = 1;
-      err = connect_to_socket (socketname ? socketname : RANDOM_DAEMON_SOCKET,
-                              &daemon_socket);
-      if (err)
-        {
-          daemon_socket = -1;
-          log_info ("not using random daemon\n");
-          gpgrt_lock_unlock (&daemon_lock);
-          return err;
-        }
-    }
-
-  /* Check that we have a valid socket descriptor. */
-  if ( daemon_socket == -1 )
-    {
-      gpgrt_lock_unlock (&daemon_lock);
-      return gcry_error (GPG_ERR_INTERNAL);
-    }
-
-
-  /* Do the real work.  */
-
-  do
-    {
-      /* Process in chunks.  */
-      nbytes = req_nbytes > sizeof (buf) ? sizeof (buf) : req_nbytes;
-      req_nbytes -= nbytes;
-
-      /* Construct request.  */
-      buf[0] = 3;
-      if (nonce)
-       buf[1] = 10;
-      else if (level == GCRY_VERY_STRONG_RANDOM)
-       buf[1] = 12;
-      else if (level == GCRY_STRONG_RANDOM)
-       buf[1] = 11;
-      buf[2] = nbytes;
-
-      /* Send request.  */
-      rc = writen (daemon_socket, buf, 3);
-      if (rc == -1)
-       {
-         err = gcry_error_from_errno (errno);
-         break;
-       }
-
-      /* Retrieve response.  */
-
-      rc = readn (daemon_socket, buf, 2, &nread);
-      if (rc == -1)
-       {
-         err = gcry_error_from_errno (errno);
-         log_error ("read error: %s\n", _gcry_strerror (err));
-         break;
-       }
-      if (nread && buf[0])
-       {
-         log_error ("random daemon returned error code %d\n", buf[0]);
-         err = gcry_error (GPG_ERR_INTERNAL); /* ? */
-         break;
-       }
-      if (nread != 2)
-       {
-         log_error ("response too small\n");
-         err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
-         break;
-       }
-
-      /*      if (1)*/                 /* Do this in verbose mode? */
-      /*       log_info ("received response with %d bytes of data\n", buf[1]);*/
-
-      if (buf[1] < nbytes)
-       {
-         log_error ("error: server returned less bytes than requested\n");
-         err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
-         break;
-       }
-      else if (buf[1] > nbytes)
-       {
-         log_error ("warning: server returned more bytes than requested\n");
-         err = gcry_error (GPG_ERR_PROTOCOL_VIOLATION); /* ? */
-         break;
-       }
-
-      assert (nbytes <= sizeof (buf));
-
-      rc = readn (daemon_socket, buf, nbytes, &nread);
-      if (rc == -1)
-       {
-         err = gcry_error_from_errno (errno);
-         log_error ("read error: %s\n", _gcry_strerror (err));
-         break;
-       }
-
-      if (nread != nbytes)
-       {
-         log_error ("too little random data read\n");
-         err = gcry_error (GPG_ERR_INTERNAL);
-         break;
-       }
-
-      /* Successfuly read another chunk of data.  */
-      memcpy (buffer, buf, nbytes);
-      buffer = ((char *) buffer) + nbytes;
-    }
-  while (req_nbytes);
-
-  gpgrt_lock_unlock (&daemon_lock);
-
-  return err;
-}
-
-/* Internal function to fill BUFFER with LENGTH bytes of random.  We
-   support GCRY_STRONG_RANDOM and GCRY_VERY_STRONG_RANDOM here.
-   Return 0 on success. */
-int
-_gcry_daemon_randomize (const char *socketname,
-                        void *buffer, size_t length,
-                        enum gcry_random_level level)
-{
-  gcry_error_t err;
-
-  err = call_daemon (socketname, buffer, length, 0, level);
-
-  return err ? -1 : 0;
-}
-
-/* END */
index 7f66997..a42b9ce 100644 (file)
  * gcry_randomize(outbuf, OUTLEN, GCRY_STRONG_RANDOM);
  */
 
+#include <config.h>
+
 #include <string.h>
 #include <unistd.h>
 #include <stdint.h>
 
-#include <config.h>
-
 #include "g10lib.h"
 #include "random.h"
 #include "rand-internal.h"
 #define DRBG_DEFAULT_TYPE    DRBG_NOPR_HMACSHA256
 
 
+#define DRBG_CTR_NULL_LEN 128
+
 \f
 /******************************************************************
  * Common data structures
@@ -313,8 +315,6 @@ struct drbg_state_s
                                 * operation -- allocated during init */
   void *priv_data;             /* Cipher handle */
   gcry_cipher_hd_t ctr_handle; /* CTR mode cipher handle */
-#define DRBG_CTR_NULL_LEN 128
-  unsigned char *ctr_null;     /* CTR mode zero buffer */
   int seeded:1;                        /* DRBG fully seeded? */
   int pr:1;                    /* Prediction resistance enabled? */
   /* Taken from libgcrypt ANSI X9.31 DRNG: We need to keep track of the
@@ -618,9 +618,12 @@ drbg_get_entropy (drbg_state_t drbg, unsigned char *buffer,
   read_cb_buffer = buffer;
   read_cb_size = len;
   read_cb_len = 0;
-#if USE_RNDLINUX
-  rc = _gcry_rndlinux_gather_random (drbg_read_cb, 0, len,
-                                    GCRY_VERY_STRONG_RANDOM);
+#if USE_RNDGETENTROPY
+  rc = _gcry_rndgetentropy_gather_random (drbg_read_cb, 0, len,
+                                          GCRY_VERY_STRONG_RANDOM);
+#elif USE_RNDOLDLINUX
+  rc = _gcry_rndoldlinux_gather_random (drbg_read_cb, 0, len,
+                                        GCRY_VERY_STRONG_RANDOM);
 #elif USE_RNDUNIX
   rc = _gcry_rndunix_gather_random (drbg_read_cb, 0, len,
                                    GCRY_VERY_STRONG_RANDOM);
@@ -951,6 +954,7 @@ drbg_ctr_generate (drbg_state_t drbg,
                    unsigned char *buf, unsigned int buflen,
                    drbg_string_t *addtl)
 {
+  static const unsigned char drbg_ctr_null[DRBG_CTR_NULL_LEN] = { 0, };
   gpg_err_code_t ret = 0;
 
   memset (drbg->scratchpad, 0, drbg_blocklen (drbg));
@@ -965,7 +969,7 @@ drbg_ctr_generate (drbg_state_t drbg,
     }
 
   /* 10.2.1.5.2 step 4.1 */
-  ret = drbg_sym_ctr (drbg, drbg->ctr_null, DRBG_CTR_NULL_LEN, buf, buflen);
+  ret = drbg_sym_ctr (drbg, drbg_ctr_null, sizeof(drbg_ctr_null), buf, buflen);
   if (ret)
     goto out;
 
@@ -1859,16 +1863,26 @@ _gcry_rngdrbg_reinit (const char *flagstr, gcry_buffer_t *pers, int npers)
   return ret;
 }
 
-/* Try to close the FDs of the random gather module.  This is
- * currently only implemented for rndlinux. */
+/* Release resources used by this DRBG module.  That is, close the FDs
+ * of the random gather module (if any), and release memory used.
+ */
 void
 _gcry_rngdrbg_close_fds (void)
 {
-#if USE_RNDLINUX
   drbg_lock ();
-  _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
-  drbg_unlock ();
+#if USE_RNDGETENTROPY
+  _gcry_rndgetentropy_gather_random (NULL, 0, 0, 0);
 #endif
+#if USE_RNDOLDLINUX
+  _gcry_rndoldlinux_gather_random (NULL, 0, 0, 0);
+#endif
+  if (drbg_state)
+    {
+      drbg_uninstantiate (drbg_state);
+      xfree (drbg_state);
+      drbg_state = NULL;
+    }
+  drbg_unlock ();
 }
 
 /* Print some statistics about the RNG.  */
@@ -2582,8 +2596,6 @@ drbg_sym_fini (drbg_state_t drbg)
     _gcry_cipher_close (hd);
   if (drbg->ctr_handle)
     _gcry_cipher_close (drbg->ctr_handle);
-  if (drbg->ctr_null)
-    free(drbg->ctr_null);
 }
 
 static gpg_err_code_t
@@ -2592,10 +2604,6 @@ drbg_sym_init (drbg_state_t drbg)
   gcry_cipher_hd_t hd;
   gpg_error_t err;
 
-  drbg->ctr_null = calloc(1, DRBG_CTR_NULL_LEN);
-  if (!drbg->ctr_null)
-    return GPG_ERR_ENOMEM;
-
   err = _gcry_cipher_open (&hd, drbg->core->backend_cipher,
                           GCRY_CIPHER_MODE_ECB, 0);
   if (err)
index 8b79511..a1d17ad 100644 (file)
@@ -147,8 +147,10 @@ get_random (void *buffer, size_t length, int level)
   read_cb_size   = length;
   read_cb_len    = 0;
 
-#if USE_RNDLINUX
-  rc = _gcry_rndlinux_gather_random (read_cb, 0, length, level);
+#if USE_RNDGETENTROPY
+  rc = _gcry_rndgetentropy_gather_random (read_cb, 0, length, level);
+#elif USE_RNDOLDLINUX
+  rc = _gcry_rndoldlinux_gather_random (read_cb, 0, length, level);
 #elif USE_RNDUNIX
   rc = _gcry_rndunix_gather_random (read_cb, 0, length, level);
 #elif USE_RNDW32
@@ -188,13 +190,16 @@ _gcry_rngsystem_initialize (int full)
 
 
 /* Try to close the FDs of the random gather module.  This is
-   currently only implemented for rndlinux. */
+   currently only implemented for rndgetentropy/rndoldlinux. */
 void
 _gcry_rngsystem_close_fds (void)
 {
   lock_rng ();
-#if USE_RNDLINUX
-  _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
+#if USE_RNDGETENTROPY
+  _gcry_rndgetentropy_gather_random (NULL, 0, 0, 0);
+#endif
+#if USE_RNDOLDLINUX
+  _gcry_rndoldlinux_gather_random (NULL, 0, 0, 0);
 #endif
   unlock_rng ();
 }
index 9aab789..c0435d7 100644 (file)
@@ -307,28 +307,6 @@ _gcry_enable_quick_random_gen (void)
 }
 
 
-void
-_gcry_set_random_daemon_socket (const char *socketname)
-{
-  if (fips_mode ())
-    ;  /* Not used.  */
-  else
-    _gcry_rngcsprng_set_daemon_socket (socketname);
-}
-
-/* With ONOFF set to 1, enable the use of the daemon.  With ONOFF set
-   to 0, disable the use of the daemon.  With ONOF set to -1, return
-   whether the daemon has been enabled. */
-int
-_gcry_use_random_daemon (int onoff)
-{
-  if (fips_mode ())
-    return 0; /* Never enabled in fips mode.  */
-  else
-    return _gcry_rngcsprng_use_daemon (onoff);
-}
-
-
 /* This function returns true if no real RNG is available or the
    quality of the RNG has been degraded for test purposes.  */
 int
index af99346..eedf1d0 100644 (file)
@@ -35,12 +35,9 @@ void _gcry_random_dump_stats(void);
 void _gcry_secure_random_alloc(void);
 void _gcry_enable_quick_random_gen (void);
 int  _gcry_random_is_faked(void);
-void _gcry_set_random_daemon_socket (const char *socketname);
-int  _gcry_use_random_daemon (int onoff);
 void _gcry_set_random_seed_file (const char *name);
 void _gcry_update_random_seed_file (void);
 
-byte *_gcry_get_random_bits( size_t nbits, int level, int secure );
 void _gcry_fast_random_poll( void );
 
 gcry_err_code_t _gcry_random_init_external_test (void **r_context,
@@ -69,12 +66,4 @@ gpg_error_t _gcry_rndegd_set_socket_name (const char *name);
 unsigned int _gcry_rndjent_get_version (int *r_active);
 
 
-/*-- random-daemon.c (only used from random.c) --*/
-#ifdef USE_RANDOM_DAEMON
-void _gcry_daemon_initialize_basics (void);
-int _gcry_daemon_randomize (const char *socketname,
-                            void *buffer, size_t length,
-                            enum gcry_random_level level);
-#endif /*USE_RANDOM_DAEMON*/
-
 #endif /*G10_RANDOM_H*/
diff --git a/random/rndgetentropy.c b/random/rndgetentropy.c
new file mode 100644 (file)
index 0000000..7580873
--- /dev/null
@@ -0,0 +1,105 @@
+/* rndgetentropy.c  -  raw random number for OSes by getentropy function.
+ * Copyright (C) 1998, 2001, 2002, 2003, 2007,
+ *               2009  Free Software Foundation, Inc.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_RANDOM_H
+#include <sys/random.h>
+#endif
+
+#include "types.h"
+#include "g10lib.h"
+#include "rand-internal.h"
+
+/* The function returns 0 on success or true on failure (in which case
+ * the caller will signal a fatal error).  */
+int
+_gcry_rndgetentropy_gather_random (void (*add)(const void*, size_t,
+                                               enum random_origins),
+                                   enum random_origins origin,
+                                   size_t length, int level)
+{
+  byte buffer[256];
+
+  if (!add)
+    {
+      /* Special mode to release resouces.  */
+      _gcry_rndjent_fini ();
+      return 0;
+    }
+
+  /* When using a blocking random generator try to get some entropy
+   * from the jitter based RNG.  In this case we take up to 50% of the
+   * remaining requested bytes.  */
+  if (level >= GCRY_VERY_STRONG_RANDOM)
+    {
+      size_t n;
+
+      n = _gcry_rndjent_poll (add, origin, length/2);
+      if (n > length/2)
+        n = length/2;
+      if (length > 1)
+        length -= n;
+    }
+
+  /* Enter the loop.  */
+  while (length)
+    {
+      int ret;
+      size_t nbytes;
+
+      /* For a modern operating system, we use the new getentropy
+       * function.  That call guarantees that the kernel's RNG has
+       * been properly seeded before returning any data.  This is
+       * different from /dev/urandom which may, due to its
+       * non-blocking semantics, return data even if the kernel has
+       * not been properly seeded.  And it differs from /dev/random by
+       * never blocking once the kernel is seeded.  */
+      do
+        {
+          nbytes = length < sizeof (buffer)? length : sizeof (buffer);
+          _gcry_pre_syscall ();
+          ret = getentropy (buffer, nbytes);
+          _gcry_post_syscall ();
+        }
+      while (ret == -1 && errno == EINTR);
+
+      if (ret == -1 && errno == ENOSYS)
+        log_fatal ("getentropy is not supported: %s\n", strerror (errno));
+      else
+        { /* getentropy is supported.  Some sanity checks.  */
+          if (ret == -1)
+            log_fatal ("unexpected error from getentropy: %s\n",
+                       strerror (errno));
+
+          (*add) (buffer, nbytes, origin);
+          length -= nbytes;
+        }
+    }
+  wipememory (buffer, sizeof buffer);
+
+  return 0; /* success */
+}
index 2829382..3cf9acc 100644 (file)
@@ -198,24 +198,33 @@ _gcry_rndhw_poll_fast (void (*add)(const void*, size_t, enum random_origins),
 
 
 /* Read 64 bytes from a hardware RNG and return the number of bytes
-   actually read.  */
+   actually read.  However hardware source is let account only
+   for up to 50% (or 25% for RDRAND) of the requested bytes.  */
 size_t
 _gcry_rndhw_poll_slow (void (*add)(const void*, size_t, enum random_origins),
-                       enum random_origins origin)
+                       enum random_origins origin, size_t req_length)
 {
   size_t nbytes = 0;
 
   (void)add;
   (void)origin;
 
+  req_length /= 2; /* Up to 50%. */
+
 #ifdef USE_DRNG
   if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND))
-    nbytes += poll_drng (add, origin, 0);
+    {
+      req_length /= 2; /* Up to 25%. */
+      nbytes += poll_drng (add, origin, 0);
+    }
 #endif
 #ifdef USE_PADLOCK
   if ((_gcry_get_hw_features () & HWF_PADLOCK_RNG))
     nbytes += poll_padlock (add, origin, 0);
 #endif
 
+  if (nbytes > req_length)
+    nbytes = req_length;
+
   return nbytes;
 }
index 3740ddd..14d2379 100644 (file)
@@ -43,6 +43,8 @@
 #ifdef HAVE_STDINT_H
 # include <stdint.h>
 #endif
+#include <unistd.h>
+#include <errno.h>
 
 #include "types.h"
 #include "g10lib.h"
@@ -57,7 +59,7 @@
 #define JENT_USES_GETTIME 2
 #define JENT_USES_READ_REAL_TIME 3
 #ifdef ENABLE_JENT_SUPPORT
-# if defined (__i386__) || defined(__x86_64__)
+# if (defined (__i386__) || defined(__x86_64__)) && defined(HAVE_CPU_ARCH_X86)
 #   define USE_JENT JENT_USES_RDTSC
 # elif defined (HAVE_CLOCK_GETTIME)
 #  if _AIX
 #define JENT_PRIVATE_COMPILE 1
 
 #include "jitterentropy-base.c"
-
+#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
+#include <pthread.h>
+#endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */
+#include "jitterentropy-gcd.c"
+#include "jitterentropy-health.c"
+#include "jitterentropy-noise.c"
+#include "jitterentropy-sha3.c"
+#include "jitterentropy-timer.c"
 
 /* This is the lock we use to serialize access to this RNG.  The extra
  * integer variable is only used to check the locking state; that is,
@@ -291,7 +300,7 @@ _gcry_rndjent_poll (void (*add)(const void*, size_t, enum random_origins),
               size_t n = length < sizeof(buffer)? length : sizeof (buffer);
 
               jent_rng_totalcalls++;
-              rc = jent_read_entropy (jent_rng_collector, buffer, n);
+              rc = jent_read_entropy_safe (&jent_rng_collector, buffer, n);
               if (rc < 0)
                 break;
               /* We need to hash the output to conform to the BSI
@@ -370,3 +379,20 @@ _gcry_rndjent_dump_stats (void)
     }
 #endif /*USE_JENT*/
 }
+
+
+void
+_gcry_rndjent_fini (void)
+{
+#ifdef USE_JENT
+  lock_rng ();
+
+  if (jent_rng_is_initialized)
+    {
+      jent_entropy_collector_free (jent_rng_collector);
+      jent_rng_collector = NULL;
+    }
+
+  unlock_rng ();
+#endif
+}
similarity index 73%
rename from random/rndlinux.c
rename to random/rndoldlinux.c
index fefc3c3..c0bb9a3 100644 (file)
@@ -1,4 +1,4 @@
-/* rndlinux.c  -  raw random number for OSes with /dev/random
+/* rndoldlinux.c  -  raw random number for OSes with /dev/random
  * Copyright (C) 1998, 2001, 2002, 2003, 2007,
  *               2009  Free Software Foundation, Inc.
  *
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <sys/time.h>
 #include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_GETTIMEOFDAY
-# include <sys/times.h>
-#endif
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
-#if defined(__linux__) && defined(HAVE_SYSCALL)
+#include <poll.h>
+#if defined(__APPLE__) && defined(__MACH__)
+#include <Availability.h>
+#ifdef __MAC_10_11
+#include <TargetConditionals.h>
+#if !defined(TARGET_OS_IPHONE) || TARGET_OS_IPHONE == 0
+extern int getentropy (void *buf, size_t buflen) __attribute__ ((weak_import));
+#define HAVE_GETENTROPY
+#endif
+#endif
+#endif
+#if defined(__linux__) || !defined(HAVE_GETENTROPY)
+#ifdef HAVE_SYSCALL
 # include <sys/syscall.h>
+# ifdef __NR_getrandom
+# define getentropy(buf,buflen) syscall (__NR_getrandom, buf, buflen, 0)
+# endif
+#endif
 #endif
 
 #include "types.h"
@@ -73,12 +84,8 @@ open_device (const char *name, int retry)
   fd = open (name, O_RDONLY);
   if (fd == -1 && retry)
     {
-      struct timeval tv;
-
-      tv.tv_sec = 5;
-      tv.tv_usec = 0;
-      _gcry_random_progress ("wait_dev_random", 'X', 0, (int)tv.tv_sec);
-      select (0, NULL, NULL, NULL, &tv);
+      _gcry_random_progress ("wait_dev_random", 'X', 0, 5);
+      poll (NULL, 0, 5000);
       goto again;
     }
   if (fd == -1)
@@ -109,10 +116,10 @@ open_device (const char *name, int retry)
  * error).  This function should be entered only by one thread at a
  * time. */
 int
-_gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
-                                          enum random_origins),
-                              enum random_origins origin,
-                              size_t length, int level )
+_gcry_rndoldlinux_gather_random (void (*add)(const void*, size_t,
+                                             enum random_origins),
+                                 enum random_origins origin,
+                                 size_t length, int level )
 {
   static int fd_urandom = -1;
   static int fd_random = -1;
@@ -156,6 +163,8 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
           close (fd_urandom);
           fd_urandom = -1;
         }
+
+      _gcry_rndjent_fini ();
       return 0;
     }
 
@@ -179,19 +188,10 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
     }
 
 
-  /* First read from a hardware source.  However let it account only
-     for up to 50% (or 25% for RDRAND) of the requested bytes.  */
-  n_hw = _gcry_rndhw_poll_slow (add, origin);
-  if ((_gcry_get_hw_features () & HWF_INTEL_RDRAND))
-    {
-      if (n_hw > length/4)
-        n_hw = length/4;
-    }
-  else
-    {
-      if (n_hw > length/2)
-        n_hw = length/2;
-    }
+  /* First read from a hardware source.  Note that _gcry_rndhw_poll_slow lets
+     it account only for up to 50% (or 25% for RDRAND) of the requested
+     bytes.  */
+  n_hw = _gcry_rndhw_poll_slow (add, origin, length);
   if (length > 1)
     length -= n_hw;
 
@@ -241,20 +241,20 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
                  return with something we will actually use 100ms. */
   while (length)
     {
-      fd_set rfds;
-      struct timeval tv;
       int rc;
+      struct pollfd pfd;
 
-      /* If we have a modern Linux kernel, we first try to use the new
-       * getrandom syscall.  That call guarantees that the kernel's
+      /* If we have a modern operating system, we first try to use the new
+       * getentropy function.  That call guarantees that the kernel's
        * RNG has been properly seeded before returning any data.  This
        * is different from /dev/urandom which may, due to its
        * non-blocking semantics, return data even if the kernel has
        * not been properly seeded.  And it differs from /dev/random by never
-       * blocking once the kernel is seeded. Unfortunately we need to use a
-       * syscall and not a new device and thus we are not able to use
-       * select(2) to have a timeout. */
-#if defined(__linux__) && defined(HAVE_SYSCALL) && defined(__NR_getrandom)
+       * blocking once the kernel is seeded.  */
+#if defined(HAVE_GETENTROPY) || defined(__NR_getrandom)
+#if defined(__APPLE__) && defined(__MACH__)
+      if (&getentropy != NULL)
+#endif
         {
           long ret;
           size_t nbytes;
@@ -265,21 +265,22 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
               if (nbytes > 256)
                 nbytes = 256;
               _gcry_pre_syscall ();
-              ret = syscall (__NR_getrandom,
-                             (void*)buffer, (size_t)nbytes, (unsigned int)0);
+              ret = getentropy (buffer, nbytes);
               _gcry_post_syscall ();
             }
           while (ret == -1 && errno == EINTR);
           if (ret == -1 && errno == ENOSYS)
-            ; /* The syscall is not supported - fallback to pulling from fd.  */
+            ; /* getentropy is not supported - fallback to pulling from fd.  */
           else
-            { /* The syscall is supported.  Some sanity checks.  */
+            { /* getentropy is supported.  Some sanity checks.  */
               if (ret == -1)
-                log_fatal ("unexpected error from getrandom: %s\n",
+                log_fatal ("unexpected error from getentropy: %s\n",
                            strerror (errno));
+#ifdef __NR_getrandom
               else if (ret != nbytes)
-                log_fatal ("getrandom returned only"
+                log_fatal ("getentropy returned only"
                            " %ld of %zu requested bytes\n", ret, nbytes);
+#endif
 
               (*add)(buffer, nbytes, origin);
               length -= nbytes;
@@ -289,7 +290,7 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
 #endif
 
       /* If we collected some bytes update the progress indicator.  We
-         do this always and not just if the select timed out because
+         do this always and not just if the poll timed out because
          often just a few bytes are gathered within the timeout
          period.  */
       if (any_need_entropy || last_so_far != (want - length) )
@@ -300,36 +301,25 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
           any_need_entropy = 1;
         }
 
-      /* If the system has no limit on the number of file descriptors
-         and we encounter an fd which is larger than the fd_set size,
-         we don't use the select at all.  The select code is only used
-         to emit progress messages.  A better solution would be to
-         fall back to poll() if available.  */
-#ifdef FD_SETSIZE
-      if (fd < FD_SETSIZE)
-#endif
+      pfd.fd = fd;
+      pfd.events = POLLIN;
+
+      _gcry_pre_syscall ();
+      rc = poll (&pfd, 1, delay);
+      _gcry_post_syscall ();
+      if (!rc)
         {
-          FD_ZERO(&rfds);
-          FD_SET(fd, &rfds);
-          tv.tv_sec = delay;
-          tv.tv_usec = delay? 0 : 100000;
-          _gcry_pre_syscall ();
-          rc = select (fd+1, &rfds, NULL, NULL, &tv);
-          _gcry_post_syscall ();
-          if (!rc)
-            {
-              any_need_entropy = 1;
-              delay = 3; /* Use 3 seconds henceforth.  */
-              continue;
-            }
-          else if( rc == -1 )
-            {
-              log_error ("select() error: %s\n", strerror(errno));
-              if (!delay)
-                delay = 1; /* Use 1 second if we encounter an error before
-                              we have ever blocked.  */
-              continue;
-            }
+          any_need_entropy = 1;
+          delay = 3000; /* Use 3 seconds henceforth.  */
+          continue;
+        }
+      else if( rc == -1 )
+        {
+          log_error ("poll() error: %s\n", strerror (errno));
+          if (!delay)
+            delay = 1000; /* Use 1 second if we encounter an error before
+                             we have ever blocked.  */
+          continue;
         }
 
       do
index fcb45b7..aff2f85 100644 (file)
@@ -894,7 +894,7 @@ _gcry_rndunix_gather_random (void (*add)(const void*, size_t,
     /* now read from the gatherer */
     while( length ) {
        int goodness;
-       ulong subtract;
+       unsigned long subtract;
 
        if( read_a_msg( pipedes[0], &msg ) ) {
            log_error("reading from gatherer pipe failed: %s\n",
@@ -928,7 +928,7 @@ _gcry_rndunix_gather_random (void (*add)(const void*, size_t,
        (*add)( msg.data, n, origin );
 
        /* this is the trick how we cope with the goodness */
-       subtract = (ulong)n * goodness / 100;
+       subtract = (unsigned long)n * goodness / 100;
        /* subtract at least 1 byte to avoid infinite loops */
        length -= subtract ? subtract : 1;
     }
index 08a8867..b3f63d2 100644 (file)
@@ -845,10 +845,10 @@ _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
      We discard the upper 32-bit of those values.  */
 
   {
-    byte buffer[20*sizeof(ulong)], *bufptr;
+    byte buffer[20*sizeof(unsigned long)], *bufptr;
 
     bufptr = buffer;
-#define ADDINT(f)  do { ulong along = (ulong)(f);                  \
+#define ADDINT(f)  do { unsigned long along = (unsigned long)(f);  \
                         memcpy (bufptr, &along, sizeof (along) );  \
                         bufptr += sizeof (along);                  \
                       } while (0)
index b485eef..873e846 100644 (file)
@@ -115,7 +115,7 @@ _gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
       memcpy (bufptr, &along, sizeof (along));                     \
       bufptr += sizeof (along);                                    \
     } while (0)
-    unsigned char buffer[20*sizeof(ulong)], *bufptr;
+    unsigned char buffer[20*sizeof(unsigned long)], *bufptr;
 
     bufptr = buffer;
     ADD (HWND,   GetActiveWindow ());
index 3cc4a55..aa3548f 100644 (file)
 
 ## Process this file with automake to produce Makefile.in
 
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libgcrypt.pc
+
 EXTRA_DIST = libgcrypt-config.in libgcrypt.m4 libgcrypt.vers \
-             gcrypt.h.in libgcrypt.def
+             gcrypt.h.in libgcrypt.def libgcrypt.pc.in gen-note-integrity.sh
 
 bin_SCRIPTS = libgcrypt-config
 m4datadir = $(datadir)/aclocal
@@ -30,10 +33,10 @@ nodist_include_HEADERS = gcrypt.h
 
 lib_LTLIBRARIES = libgcrypt.la
 bin_PROGRAMS = dumpsexp hmac256 mpicalc
-if USE_RANDOM_DAEMON
+if ENABLE_RANDOM_DAEMON
 sbin_PROGRAMS = gcryptrnd
 bin_PROGRAMS += getrandom
-endif USE_RANDOM_DAEMON
+endif ENABLE_RANDOM_DAEMON
 
 # Depending on the architecture some targets require libgpg-error.
 if HAVE_W32CE_SYSTEM
@@ -53,17 +56,17 @@ else
   libgcrypt_version_script_cmd =
 endif
 
-libgcrypt_la_CFLAGS = $(GPG_ERROR_CFLAGS)
+libgcrypt_la_CFLAGS = $(GPG_ERROR_CFLAGS) @DEF_HMAC_BINARY_CHECK@
 libgcrypt_la_SOURCES = \
         gcrypt-int.h g10lib.h visibility.c visibility.h types.h \
        gcrypt-testapi.h cipher.h cipher-proto.h \
        misc.c global.c sexp.c hwfeatures.c hwf-common.h \
        stdmem.c stdmem.h secmem.c secmem.h \
        mpi.h missing-string.c fips.c \
-       hmac256.c hmac256.h context.c context.h \
+       context.c context.h \
        ec-context.h
 
-EXTRA_libgcrypt_la_SOURCES = hwf-x86.c hwf-arm.c
+EXTRA_libgcrypt_la_SOURCES = hwf-x86.c hwf-arm.c hwf-ppc.c hwf-s390x.c
 gcrypt_hwf_modules = @GCRYPT_HWF_MODULES@
 
 
@@ -122,7 +125,7 @@ libgcrypt_la_LIBADD = $(gcrypt_res) \
        ../cipher/libcipher.la \
        ../random/librandom.la \
        ../mpi/libmpi.la \
-       ../compat/libcompat.la  $(GPG_ERROR_LIBS)
+       ../compat/libcompat.la $(DL_LIBS) $(GPG_ERROR_LIBS)
 
 
 dumpsexp_SOURCES = dumpsexp.c
@@ -131,29 +134,41 @@ dumpsexp_LDADD = $(arch_gpg_error_libs)
 
 mpicalc_SOURCES = mpicalc.c
 mpicalc_CFLAGS = $(GPG_ERROR_CFLAGS)
-mpicalc_LDADD = libgcrypt.la $(DL_LIBS) $(GPG_ERROR_LIBS)
+mpicalc_LDADD = libgcrypt.la $(GPG_ERROR_LIBS)
+EXTRA_mpicalc_DEPENDENCIES = libgcrypt.la.done
 
-hmac256_SOURCES = hmac256.c
-hmac256_CFLAGS = -DSTANDALONE $(arch_gpg_error_cflags)
+hmac256_SOURCES = hmac256.c hmac256.h
+hmac256_CFLAGS = -DSTANDALONE @DEF_HMAC_BINARY_CHECK@ \
+       $(arch_gpg_error_cflags)
 hmac256_LDADD = $(arch_gpg_error_libs)
 
-if USE_RANDOM_DAEMON
+if ENABLE_RANDOM_DAEMON
 gcryptrnd_SOURCES = gcryptrnd.c
 gcryptrnd_CFLAGS = $(GPG_ERROR_CFLAGS) $(PTH_CFLAGS)
 gcryptrnd_LDADD = libgcrypt.la $(GPG_ERROR_LIBS) $(PTH_LIBS)
 
 getrandom_SOURCES = getrandom.c
-endif USE_RANDOM_DAEMON
-
+endif ENABLE_RANDOM_DAEMON
+
+CLEANFILES = libgcrypt.la.done
+if USE_HMAC_BINARY_CHECK
+CLEANFILES += libgcrypt.so.hmac
+
+libgcrypt.la.done: libgcrypt.so.hmac
+       $(OBJCOPY) --add-section .note.fdo.integrity=libgcrypt.so.hmac \
+         --set-section-flags .note.fdo.integrity=noload,readonly \
+         .libs/libgcrypt.so .libs/libgcrypt.so.new
+       mv -f .libs/libgcrypt.so.new .libs/libgcrypt.so.*.*
+       @touch libgcrypt.la.done
+
+libgcrypt.so.hmac: hmac256 libgcrypt.la
+       ECHO_N=$(ECHO_N) READELF=$(READELF) AWK=$(AWK) \
+       $(srcdir)/gen-note-integrity.sh > $@
+else !USE_HMAC_BINARY_CHECK
+libgcrypt.la.done: libgcrypt.la
+       @touch libgcrypt.la.done
+endif !USE_HMAC_BINARY_CHECK
 
 install-data-local: install-def-file
 
 uninstall-local: uninstall-def-file
-
-# FIXME: We need to figure out how to get the actual name (parsing
-# libgcrypt.la?) and how to create the hmac file already at link time
-# so that it can be used without installing libgcrypt first.
-#install-exec-hook:
-#      ./hmac256 "What am I, a doctor or a moonshuttle conductor?" \
-#          < $(DESTDIR)$(libdir)/libgcrypt.so.11.5.0 \
-#          > $(DESTDIR)$(libdir)/.libgcrypt.so.11.5.0.hmac
diff --git a/src/Makefile.in b/src/Makefile.in
deleted file mode 100644 (file)
index d020ea6..0000000
+++ /dev/null
@@ -1,1236 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Makefile.am - for gcrypt/src
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-#               2006, 2007  Free Software Foundation, Inc.
-#
-# 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 General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-
-
-
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-bin_PROGRAMS = dumpsexp$(EXEEXT) hmac256$(EXEEXT) mpicalc$(EXEEXT) \
-       $(am__EXEEXT_1)
-@USE_RANDOM_DAEMON_TRUE@sbin_PROGRAMS = gcryptrnd$(EXEEXT)
-@USE_RANDOM_DAEMON_TRUE@am__append_1 = getrandom
-subdir = src
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-       $(srcdir)/gcrypt.h.in $(srcdir)/libgcrypt-config.in \
-       $(srcdir)/versioninfo.rc.in $(top_srcdir)/build-aux/depcomp
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES = gcrypt.h libgcrypt-config versioninfo.rc
-CONFIG_CLEAN_VPATH_FILES =
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
-    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
-    *) f=$$p;; \
-  esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
-  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
-  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
-  for p in $$list; do echo "$$p $$p"; done | \
-  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
-  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
-    if (++n[$$2] == $(am__install_max)) \
-      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
-    END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
-  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
-  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
-  test -z "$$files" \
-    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
-    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
-         $(am__cd) "$$dir" && rm -f $$files; }; \
-  }
-am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
-       "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" \
-       "$(DESTDIR)$(m4datadir)" "$(DESTDIR)$(includedir)"
-LTLIBRARIES = $(lib_LTLIBRARIES)
-@HAVE_W32_SYSTEM_TRUE@am__DEPENDENCIES_1 = versioninfo.lo
-am__DEPENDENCIES_2 =
-am_libgcrypt_la_OBJECTS = libgcrypt_la-visibility.lo \
-       libgcrypt_la-misc.lo libgcrypt_la-global.lo \
-       libgcrypt_la-sexp.lo libgcrypt_la-hwfeatures.lo \
-       libgcrypt_la-stdmem.lo libgcrypt_la-secmem.lo \
-       libgcrypt_la-missing-string.lo libgcrypt_la-fips.lo \
-       libgcrypt_la-hmac256.lo libgcrypt_la-context.lo
-libgcrypt_la_OBJECTS = $(am_libgcrypt_la_OBJECTS)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-libgcrypt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libgcrypt_la_CFLAGS) \
-       $(CFLAGS) $(libgcrypt_la_LDFLAGS) $(LDFLAGS) -o $@
-@USE_RANDOM_DAEMON_TRUE@am__EXEEXT_1 = getrandom$(EXEEXT)
-PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
-am_dumpsexp_OBJECTS = dumpsexp-dumpsexp.$(OBJEXT)
-dumpsexp_OBJECTS = $(am_dumpsexp_OBJECTS)
-@HAVE_W32CE_SYSTEM_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2)
-dumpsexp_DEPENDENCIES = $(am__DEPENDENCIES_3)
-dumpsexp_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(dumpsexp_CFLAGS) \
-       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-am__gcryptrnd_SOURCES_DIST = gcryptrnd.c
-@USE_RANDOM_DAEMON_TRUE@am_gcryptrnd_OBJECTS =  \
-@USE_RANDOM_DAEMON_TRUE@       gcryptrnd-gcryptrnd.$(OBJEXT)
-gcryptrnd_OBJECTS = $(am_gcryptrnd_OBJECTS)
-@USE_RANDOM_DAEMON_TRUE@gcryptrnd_DEPENDENCIES = libgcrypt.la \
-@USE_RANDOM_DAEMON_TRUE@       $(am__DEPENDENCIES_2) \
-@USE_RANDOM_DAEMON_TRUE@       $(am__DEPENDENCIES_2)
-gcryptrnd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(gcryptrnd_CFLAGS) \
-       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-am__getrandom_SOURCES_DIST = getrandom.c
-@USE_RANDOM_DAEMON_TRUE@am_getrandom_OBJECTS = getrandom.$(OBJEXT)
-getrandom_OBJECTS = $(am_getrandom_OBJECTS)
-getrandom_LDADD = $(LDADD)
-am_hmac256_OBJECTS = hmac256-hmac256.$(OBJEXT)
-hmac256_OBJECTS = $(am_hmac256_OBJECTS)
-hmac256_DEPENDENCIES = $(am__DEPENDENCIES_3)
-hmac256_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(hmac256_CFLAGS) \
-       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-am_mpicalc_OBJECTS = mpicalc-mpicalc.$(OBJEXT)
-mpicalc_OBJECTS = $(am_mpicalc_OBJECTS)
-mpicalc_DEPENDENCIES = libgcrypt.la $(am__DEPENDENCIES_2) \
-       $(am__DEPENDENCIES_2)
-mpicalc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(mpicalc_CFLAGS) \
-       $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-SCRIPTS = $(bin_SCRIPTS)
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-       $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = $(libgcrypt_la_SOURCES) $(EXTRA_libgcrypt_la_SOURCES) \
-       $(dumpsexp_SOURCES) $(gcryptrnd_SOURCES) $(getrandom_SOURCES) \
-       $(hmac256_SOURCES) $(mpicalc_SOURCES)
-DIST_SOURCES = $(libgcrypt_la_SOURCES) $(EXTRA_libgcrypt_la_SOURCES) \
-       $(dumpsexp_SOURCES) $(am__gcryptrnd_SOURCES_DIST) \
-       $(am__getrandom_SOURCES_DIST) $(hmac256_SOURCES) \
-       $(mpicalc_SOURCES)
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-DATA = $(m4data_DATA)
-HEADERS = $(nodist_include_HEADERS)
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-EXTRA_DIST = libgcrypt-config.in libgcrypt.m4 libgcrypt.vers \
-             gcrypt.h.in libgcrypt.def
-
-bin_SCRIPTS = libgcrypt-config
-m4datadir = $(datadir)/aclocal
-m4data_DATA = libgcrypt.m4
-nodist_include_HEADERS = gcrypt.h
-lib_LTLIBRARIES = libgcrypt.la
-@HAVE_W32CE_SYSTEM_FALSE@arch_gpg_error_cflags = 
-
-# Depending on the architecture some targets require libgpg-error.
-@HAVE_W32CE_SYSTEM_TRUE@arch_gpg_error_cflags = $(GPG_ERROR_CFLAGS)
-@HAVE_W32CE_SYSTEM_FALSE@arch_gpg_error_libs = 
-@HAVE_W32CE_SYSTEM_TRUE@arch_gpg_error_libs = $(GPG_ERROR_LIBS)
-AM_CFLAGS = $(GPG_ERROR_CFLAGS)
-AM_CCASFLAGS = $(NOEXECSTACK_FLAGS)
-@HAVE_LD_VERSION_SCRIPT_FALSE@libgcrypt_version_script_cmd = 
-@HAVE_LD_VERSION_SCRIPT_TRUE@libgcrypt_version_script_cmd = -Wl,--version-script=$(srcdir)/libgcrypt.vers
-libgcrypt_la_CFLAGS = $(GPG_ERROR_CFLAGS)
-libgcrypt_la_SOURCES = \
-        gcrypt-int.h g10lib.h visibility.c visibility.h types.h \
-       gcrypt-testapi.h cipher.h cipher-proto.h \
-       misc.c global.c sexp.c hwfeatures.c hwf-common.h \
-       stdmem.c stdmem.h secmem.c secmem.h \
-       mpi.h missing-string.c fips.c \
-       hmac256.c hmac256.h context.c context.h \
-       ec-context.h
-
-EXTRA_libgcrypt_la_SOURCES = hwf-x86.c hwf-arm.c
-gcrypt_hwf_modules = @GCRYPT_HWF_MODULES@
-@HAVE_W32_SYSTEM_TRUE@RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
-@HAVE_W32_SYSTEM_TRUE@ $(libgcrypt_la_CPPFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS)
-
-@HAVE_W32_SYSTEM_TRUE@LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE)
-@HAVE_W32_SYSTEM_TRUE@SUFFIXES = .rc .lo
-@HAVE_W32_SYSTEM_FALSE@gcrypt_res = 
-@HAVE_W32_SYSTEM_TRUE@gcrypt_res = versioninfo.lo
-@HAVE_W32_SYSTEM_FALSE@no_undefined = 
-@HAVE_W32_SYSTEM_TRUE@no_undefined = -no-undefined
-@HAVE_W32_SYSTEM_FALSE@export_symbols = 
-@HAVE_W32_SYSTEM_TRUE@export_symbols = -export-symbols $(srcdir)/libgcrypt.def
-@HAVE_W32_SYSTEM_FALSE@extra_ltoptions = 
-@HAVE_W32_SYSTEM_TRUE@extra_ltoptions = -XCClinker -static-libgcc
-@HAVE_W32_SYSTEM_FALSE@gcrypt_deps = 
-@HAVE_W32_SYSTEM_TRUE@gcrypt_deps = $(gcrypt_res) libgcrypt.def
-@HAVE_W32_SYSTEM_FALSE@gcrypt_res_ldflag = 
-libgcrypt_la_LDFLAGS = $(no_undefined) $(export_symbols) $(extra_ltoptions) \
-       $(libgcrypt_version_script_cmd) -version-info \
-       @LIBGCRYPT_LT_CURRENT@:@LIBGCRYPT_LT_REVISION@:@LIBGCRYPT_LT_AGE@
-
-libgcrypt_la_DEPENDENCIES = \
-         $(gcrypt_hwf_modules) \
-       ../cipher/libcipher.la \
-       ../random/librandom.la \
-       ../mpi/libmpi.la \
-       ../compat/libcompat.la \
-       $(srcdir)/libgcrypt.vers $(gcrypt_deps)
-
-libgcrypt_la_LIBADD = $(gcrypt_res) \
-        $(gcrypt_hwf_modules) \
-       ../cipher/libcipher.la \
-       ../random/librandom.la \
-       ../mpi/libmpi.la \
-       ../compat/libcompat.la  $(GPG_ERROR_LIBS)
-
-dumpsexp_SOURCES = dumpsexp.c
-dumpsexp_CFLAGS = $(arch_gpg_error_cflags)
-dumpsexp_LDADD = $(arch_gpg_error_libs)
-mpicalc_SOURCES = mpicalc.c
-mpicalc_CFLAGS = $(GPG_ERROR_CFLAGS)
-mpicalc_LDADD = libgcrypt.la $(DL_LIBS) $(GPG_ERROR_LIBS)
-hmac256_SOURCES = hmac256.c
-hmac256_CFLAGS = -DSTANDALONE $(arch_gpg_error_cflags)
-hmac256_LDADD = $(arch_gpg_error_libs)
-@USE_RANDOM_DAEMON_TRUE@gcryptrnd_SOURCES = gcryptrnd.c
-@USE_RANDOM_DAEMON_TRUE@gcryptrnd_CFLAGS = $(GPG_ERROR_CFLAGS) $(PTH_CFLAGS)
-@USE_RANDOM_DAEMON_TRUE@gcryptrnd_LDADD = libgcrypt.la $(GPG_ERROR_LIBS) $(PTH_LIBS)
-@USE_RANDOM_DAEMON_TRUE@getrandom_SOURCES = getrandom.c
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .rc .lo .c .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-               && { if test -f $@; then exit 0; else break; fi; }; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu src/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-gcrypt.h: $(top_builddir)/config.status $(srcdir)/gcrypt.h.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-libgcrypt-config: $(top_builddir)/config.status $(srcdir)/libgcrypt-config.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-versioninfo.rc: $(top_builddir)/config.status $(srcdir)/versioninfo.rc.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-
-install-libLTLIBRARIES: $(lib_LTLIBRARIES)
-       @$(NORMAL_INSTALL)
-       @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
-       list2=; for p in $$list; do \
-         if test -f $$p; then \
-           list2="$$list2 $$p"; \
-         else :; fi; \
-       done; \
-       test -z "$$list2" || { \
-         echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
-         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
-         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
-       }
-
-uninstall-libLTLIBRARIES:
-       @$(NORMAL_UNINSTALL)
-       @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
-       for p in $$list; do \
-         $(am__strip_dir) \
-         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
-         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
-       done
-
-clean-libLTLIBRARIES:
-       -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
-       @list='$(lib_LTLIBRARIES)'; \
-       locs=`for p in $$list; do echo $$p; done | \
-             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
-             sort -u`; \
-       test -z "$$locs" || { \
-         echo rm -f $${locs}; \
-         rm -f $${locs}; \
-       }
-
-libgcrypt.la: $(libgcrypt_la_OBJECTS) $(libgcrypt_la_DEPENDENCIES) $(EXTRA_libgcrypt_la_DEPENDENCIES) 
-       $(AM_V_CCLD)$(libgcrypt_la_LINK) -rpath $(libdir) $(libgcrypt_la_OBJECTS) $(libgcrypt_la_LIBADD) $(LIBS)
-install-binPROGRAMS: $(bin_PROGRAMS)
-       @$(NORMAL_INSTALL)
-       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
-       fi; \
-       for p in $$list; do echo "$$p $$p"; done | \
-       sed 's/$(EXEEXT)$$//' | \
-       while read p p1; do if test -f $$p \
-        || test -f $$p1 \
-         ; then echo "$$p"; echo "$$p"; else :; fi; \
-       done | \
-       sed -e 'p;s,.*/,,;n;h' \
-           -e 's|.*|.|' \
-           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
-       sed 'N;N;N;s,\n, ,g' | \
-       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
-         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
-           if ($$2 == $$4) files[d] = files[d] " " $$1; \
-           else { print "f", $$3 "/" $$4, $$1; } } \
-         END { for (d in files) print "f", d, files[d] }' | \
-       while read type dir files; do \
-           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
-           test -z "$$files" || { \
-           echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
-           $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
-           } \
-       ; done
-
-uninstall-binPROGRAMS:
-       @$(NORMAL_UNINSTALL)
-       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
-       files=`for p in $$list; do echo "$$p"; done | \
-         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-             -e 's/$$/$(EXEEXT)/' \
-       `; \
-       test -n "$$list" || exit 0; \
-       echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
-       cd "$(DESTDIR)$(bindir)" && rm -f $$files
-
-clean-binPROGRAMS:
-       @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
-       echo " rm -f" $$list; \
-       rm -f $$list || exit $$?; \
-       test -n "$(EXEEXT)" || exit 0; \
-       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
-       echo " rm -f" $$list; \
-       rm -f $$list
-install-sbinPROGRAMS: $(sbin_PROGRAMS)
-       @$(NORMAL_INSTALL)
-       @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
-       fi; \
-       for p in $$list; do echo "$$p $$p"; done | \
-       sed 's/$(EXEEXT)$$//' | \
-       while read p p1; do if test -f $$p \
-        || test -f $$p1 \
-         ; then echo "$$p"; echo "$$p"; else :; fi; \
-       done | \
-       sed -e 'p;s,.*/,,;n;h' \
-           -e 's|.*|.|' \
-           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
-       sed 'N;N;N;s,\n, ,g' | \
-       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
-         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
-           if ($$2 == $$4) files[d] = files[d] " " $$1; \
-           else { print "f", $$3 "/" $$4, $$1; } } \
-         END { for (d in files) print "f", d, files[d] }' | \
-       while read type dir files; do \
-           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
-           test -z "$$files" || { \
-           echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
-           $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
-           } \
-       ; done
-
-uninstall-sbinPROGRAMS:
-       @$(NORMAL_UNINSTALL)
-       @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
-       files=`for p in $$list; do echo "$$p"; done | \
-         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-             -e 's/$$/$(EXEEXT)/' \
-       `; \
-       test -n "$$list" || exit 0; \
-       echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
-       cd "$(DESTDIR)$(sbindir)" && rm -f $$files
-
-clean-sbinPROGRAMS:
-       @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
-       echo " rm -f" $$list; \
-       rm -f $$list || exit $$?; \
-       test -n "$(EXEEXT)" || exit 0; \
-       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
-       echo " rm -f" $$list; \
-       rm -f $$list
-
-dumpsexp$(EXEEXT): $(dumpsexp_OBJECTS) $(dumpsexp_DEPENDENCIES) $(EXTRA_dumpsexp_DEPENDENCIES) 
-       @rm -f dumpsexp$(EXEEXT)
-       $(AM_V_CCLD)$(dumpsexp_LINK) $(dumpsexp_OBJECTS) $(dumpsexp_LDADD) $(LIBS)
-
-gcryptrnd$(EXEEXT): $(gcryptrnd_OBJECTS) $(gcryptrnd_DEPENDENCIES) $(EXTRA_gcryptrnd_DEPENDENCIES) 
-       @rm -f gcryptrnd$(EXEEXT)
-       $(AM_V_CCLD)$(gcryptrnd_LINK) $(gcryptrnd_OBJECTS) $(gcryptrnd_LDADD) $(LIBS)
-
-getrandom$(EXEEXT): $(getrandom_OBJECTS) $(getrandom_DEPENDENCIES) $(EXTRA_getrandom_DEPENDENCIES) 
-       @rm -f getrandom$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(getrandom_OBJECTS) $(getrandom_LDADD) $(LIBS)
-
-hmac256$(EXEEXT): $(hmac256_OBJECTS) $(hmac256_DEPENDENCIES) $(EXTRA_hmac256_DEPENDENCIES) 
-       @rm -f hmac256$(EXEEXT)
-       $(AM_V_CCLD)$(hmac256_LINK) $(hmac256_OBJECTS) $(hmac256_LDADD) $(LIBS)
-
-mpicalc$(EXEEXT): $(mpicalc_OBJECTS) $(mpicalc_DEPENDENCIES) $(EXTRA_mpicalc_DEPENDENCIES) 
-       @rm -f mpicalc$(EXEEXT)
-       $(AM_V_CCLD)$(mpicalc_LINK) $(mpicalc_OBJECTS) $(mpicalc_LDADD) $(LIBS)
-install-binSCRIPTS: $(bin_SCRIPTS)
-       @$(NORMAL_INSTALL)
-       @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
-       fi; \
-       for p in $$list; do \
-         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
-       done | \
-       sed -e 'p;s,.*/,,;n' \
-           -e 'h;s|.*|.|' \
-           -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
-       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
-         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
-           if ($$2 == $$4) { files[d] = files[d] " " $$1; \
-             if (++n[d] == $(am__install_max)) { \
-               print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
-           else { print "f", d "/" $$4, $$1 } } \
-         END { for (d in files) print "f", d, files[d] }' | \
-       while read type dir files; do \
-            if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
-            test -z "$$files" || { \
-              echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
-              $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
-            } \
-       ; done
-
-uninstall-binSCRIPTS:
-       @$(NORMAL_UNINSTALL)
-       @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
-       files=`for p in $$list; do echo "$$p"; done | \
-              sed -e 's,.*/,,;$(transform)'`; \
-       dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
-
-mostlyclean-compile:
-       -rm -f *.$(OBJEXT)
-
-distclean-compile:
-       -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dumpsexp-dumpsexp.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcryptrnd-gcryptrnd.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getrandom.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac256-hmac256.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-context.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-fips.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-global.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-hmac256.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-hwf-arm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-hwf-x86.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-hwfeatures.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-misc.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-missing-string.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-secmem.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-sexp.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-stdmem.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcrypt_la-visibility.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpicalc-mpicalc.Po@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-libgcrypt_la-visibility.lo: visibility.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-visibility.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-visibility.Tpo -c -o libgcrypt_la-visibility.lo `test -f 'visibility.c' || echo '$(srcdir)/'`visibility.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-visibility.Tpo $(DEPDIR)/libgcrypt_la-visibility.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='visibility.c' object='libgcrypt_la-visibility.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-visibility.lo `test -f 'visibility.c' || echo '$(srcdir)/'`visibility.c
-
-libgcrypt_la-misc.lo: misc.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-misc.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-misc.Tpo -c -o libgcrypt_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-misc.Tpo $(DEPDIR)/libgcrypt_la-misc.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='misc.c' object='libgcrypt_la-misc.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
-
-libgcrypt_la-global.lo: global.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-global.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-global.Tpo -c -o libgcrypt_la-global.lo `test -f 'global.c' || echo '$(srcdir)/'`global.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-global.Tpo $(DEPDIR)/libgcrypt_la-global.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='global.c' object='libgcrypt_la-global.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-global.lo `test -f 'global.c' || echo '$(srcdir)/'`global.c
-
-libgcrypt_la-sexp.lo: sexp.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-sexp.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-sexp.Tpo -c -o libgcrypt_la-sexp.lo `test -f 'sexp.c' || echo '$(srcdir)/'`sexp.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-sexp.Tpo $(DEPDIR)/libgcrypt_la-sexp.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='sexp.c' object='libgcrypt_la-sexp.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-sexp.lo `test -f 'sexp.c' || echo '$(srcdir)/'`sexp.c
-
-libgcrypt_la-hwfeatures.lo: hwfeatures.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-hwfeatures.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-hwfeatures.Tpo -c -o libgcrypt_la-hwfeatures.lo `test -f 'hwfeatures.c' || echo '$(srcdir)/'`hwfeatures.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-hwfeatures.Tpo $(DEPDIR)/libgcrypt_la-hwfeatures.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='hwfeatures.c' object='libgcrypt_la-hwfeatures.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-hwfeatures.lo `test -f 'hwfeatures.c' || echo '$(srcdir)/'`hwfeatures.c
-
-libgcrypt_la-stdmem.lo: stdmem.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-stdmem.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-stdmem.Tpo -c -o libgcrypt_la-stdmem.lo `test -f 'stdmem.c' || echo '$(srcdir)/'`stdmem.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-stdmem.Tpo $(DEPDIR)/libgcrypt_la-stdmem.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='stdmem.c' object='libgcrypt_la-stdmem.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-stdmem.lo `test -f 'stdmem.c' || echo '$(srcdir)/'`stdmem.c
-
-libgcrypt_la-secmem.lo: secmem.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-secmem.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-secmem.Tpo -c -o libgcrypt_la-secmem.lo `test -f 'secmem.c' || echo '$(srcdir)/'`secmem.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-secmem.Tpo $(DEPDIR)/libgcrypt_la-secmem.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='secmem.c' object='libgcrypt_la-secmem.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-secmem.lo `test -f 'secmem.c' || echo '$(srcdir)/'`secmem.c
-
-libgcrypt_la-missing-string.lo: missing-string.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-missing-string.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-missing-string.Tpo -c -o libgcrypt_la-missing-string.lo `test -f 'missing-string.c' || echo '$(srcdir)/'`missing-string.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-missing-string.Tpo $(DEPDIR)/libgcrypt_la-missing-string.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='missing-string.c' object='libgcrypt_la-missing-string.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-missing-string.lo `test -f 'missing-string.c' || echo '$(srcdir)/'`missing-string.c
-
-libgcrypt_la-fips.lo: fips.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-fips.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-fips.Tpo -c -o libgcrypt_la-fips.lo `test -f 'fips.c' || echo '$(srcdir)/'`fips.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-fips.Tpo $(DEPDIR)/libgcrypt_la-fips.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='fips.c' object='libgcrypt_la-fips.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-fips.lo `test -f 'fips.c' || echo '$(srcdir)/'`fips.c
-
-libgcrypt_la-hmac256.lo: hmac256.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-hmac256.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-hmac256.Tpo -c -o libgcrypt_la-hmac256.lo `test -f 'hmac256.c' || echo '$(srcdir)/'`hmac256.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-hmac256.Tpo $(DEPDIR)/libgcrypt_la-hmac256.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='hmac256.c' object='libgcrypt_la-hmac256.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-hmac256.lo `test -f 'hmac256.c' || echo '$(srcdir)/'`hmac256.c
-
-libgcrypt_la-context.lo: context.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-context.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-context.Tpo -c -o libgcrypt_la-context.lo `test -f 'context.c' || echo '$(srcdir)/'`context.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-context.Tpo $(DEPDIR)/libgcrypt_la-context.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='context.c' object='libgcrypt_la-context.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-context.lo `test -f 'context.c' || echo '$(srcdir)/'`context.c
-
-libgcrypt_la-hwf-x86.lo: hwf-x86.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-hwf-x86.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-hwf-x86.Tpo -c -o libgcrypt_la-hwf-x86.lo `test -f 'hwf-x86.c' || echo '$(srcdir)/'`hwf-x86.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-hwf-x86.Tpo $(DEPDIR)/libgcrypt_la-hwf-x86.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='hwf-x86.c' object='libgcrypt_la-hwf-x86.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-hwf-x86.lo `test -f 'hwf-x86.c' || echo '$(srcdir)/'`hwf-x86.c
-
-libgcrypt_la-hwf-arm.lo: hwf-arm.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -MT libgcrypt_la-hwf-arm.lo -MD -MP -MF $(DEPDIR)/libgcrypt_la-hwf-arm.Tpo -c -o libgcrypt_la-hwf-arm.lo `test -f 'hwf-arm.c' || echo '$(srcdir)/'`hwf-arm.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libgcrypt_la-hwf-arm.Tpo $(DEPDIR)/libgcrypt_la-hwf-arm.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='hwf-arm.c' object='libgcrypt_la-hwf-arm.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgcrypt_la_CFLAGS) $(CFLAGS) -c -o libgcrypt_la-hwf-arm.lo `test -f 'hwf-arm.c' || echo '$(srcdir)/'`hwf-arm.c
-
-dumpsexp-dumpsexp.o: dumpsexp.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dumpsexp_CFLAGS) $(CFLAGS) -MT dumpsexp-dumpsexp.o -MD -MP -MF $(DEPDIR)/dumpsexp-dumpsexp.Tpo -c -o dumpsexp-dumpsexp.o `test -f 'dumpsexp.c' || echo '$(srcdir)/'`dumpsexp.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/dumpsexp-dumpsexp.Tpo $(DEPDIR)/dumpsexp-dumpsexp.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='dumpsexp.c' object='dumpsexp-dumpsexp.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dumpsexp_CFLAGS) $(CFLAGS) -c -o dumpsexp-dumpsexp.o `test -f 'dumpsexp.c' || echo '$(srcdir)/'`dumpsexp.c
-
-dumpsexp-dumpsexp.obj: dumpsexp.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dumpsexp_CFLAGS) $(CFLAGS) -MT dumpsexp-dumpsexp.obj -MD -MP -MF $(DEPDIR)/dumpsexp-dumpsexp.Tpo -c -o dumpsexp-dumpsexp.obj `if test -f 'dumpsexp.c'; then $(CYGPATH_W) 'dumpsexp.c'; else $(CYGPATH_W) '$(srcdir)/dumpsexp.c'; fi`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/dumpsexp-dumpsexp.Tpo $(DEPDIR)/dumpsexp-dumpsexp.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='dumpsexp.c' object='dumpsexp-dumpsexp.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(dumpsexp_CFLAGS) $(CFLAGS) -c -o dumpsexp-dumpsexp.obj `if test -f 'dumpsexp.c'; then $(CYGPATH_W) 'dumpsexp.c'; else $(CYGPATH_W) '$(srcdir)/dumpsexp.c'; fi`
-
-gcryptrnd-gcryptrnd.o: gcryptrnd.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gcryptrnd_CFLAGS) $(CFLAGS) -MT gcryptrnd-gcryptrnd.o -MD -MP -MF $(DEPDIR)/gcryptrnd-gcryptrnd.Tpo -c -o gcryptrnd-gcryptrnd.o `test -f 'gcryptrnd.c' || echo '$(srcdir)/'`gcryptrnd.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/gcryptrnd-gcryptrnd.Tpo $(DEPDIR)/gcryptrnd-gcryptrnd.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='gcryptrnd.c' object='gcryptrnd-gcryptrnd.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gcryptrnd_CFLAGS) $(CFLAGS) -c -o gcryptrnd-gcryptrnd.o `test -f 'gcryptrnd.c' || echo '$(srcdir)/'`gcryptrnd.c
-
-gcryptrnd-gcryptrnd.obj: gcryptrnd.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gcryptrnd_CFLAGS) $(CFLAGS) -MT gcryptrnd-gcryptrnd.obj -MD -MP -MF $(DEPDIR)/gcryptrnd-gcryptrnd.Tpo -c -o gcryptrnd-gcryptrnd.obj `if test -f 'gcryptrnd.c'; then $(CYGPATH_W) 'gcryptrnd.c'; else $(CYGPATH_W) '$(srcdir)/gcryptrnd.c'; fi`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/gcryptrnd-gcryptrnd.Tpo $(DEPDIR)/gcryptrnd-gcryptrnd.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='gcryptrnd.c' object='gcryptrnd-gcryptrnd.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gcryptrnd_CFLAGS) $(CFLAGS) -c -o gcryptrnd-gcryptrnd.obj `if test -f 'gcryptrnd.c'; then $(CYGPATH_W) 'gcryptrnd.c'; else $(CYGPATH_W) '$(srcdir)/gcryptrnd.c'; fi`
-
-hmac256-hmac256.o: hmac256.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hmac256_CFLAGS) $(CFLAGS) -MT hmac256-hmac256.o -MD -MP -MF $(DEPDIR)/hmac256-hmac256.Tpo -c -o hmac256-hmac256.o `test -f 'hmac256.c' || echo '$(srcdir)/'`hmac256.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/hmac256-hmac256.Tpo $(DEPDIR)/hmac256-hmac256.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='hmac256.c' object='hmac256-hmac256.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hmac256_CFLAGS) $(CFLAGS) -c -o hmac256-hmac256.o `test -f 'hmac256.c' || echo '$(srcdir)/'`hmac256.c
-
-hmac256-hmac256.obj: hmac256.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hmac256_CFLAGS) $(CFLAGS) -MT hmac256-hmac256.obj -MD -MP -MF $(DEPDIR)/hmac256-hmac256.Tpo -c -o hmac256-hmac256.obj `if test -f 'hmac256.c'; then $(CYGPATH_W) 'hmac256.c'; else $(CYGPATH_W) '$(srcdir)/hmac256.c'; fi`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/hmac256-hmac256.Tpo $(DEPDIR)/hmac256-hmac256.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='hmac256.c' object='hmac256-hmac256.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(hmac256_CFLAGS) $(CFLAGS) -c -o hmac256-hmac256.obj `if test -f 'hmac256.c'; then $(CYGPATH_W) 'hmac256.c'; else $(CYGPATH_W) '$(srcdir)/hmac256.c'; fi`
-
-mpicalc-mpicalc.o: mpicalc.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpicalc_CFLAGS) $(CFLAGS) -MT mpicalc-mpicalc.o -MD -MP -MF $(DEPDIR)/mpicalc-mpicalc.Tpo -c -o mpicalc-mpicalc.o `test -f 'mpicalc.c' || echo '$(srcdir)/'`mpicalc.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/mpicalc-mpicalc.Tpo $(DEPDIR)/mpicalc-mpicalc.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='mpicalc.c' object='mpicalc-mpicalc.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpicalc_CFLAGS) $(CFLAGS) -c -o mpicalc-mpicalc.o `test -f 'mpicalc.c' || echo '$(srcdir)/'`mpicalc.c
-
-mpicalc-mpicalc.obj: mpicalc.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpicalc_CFLAGS) $(CFLAGS) -MT mpicalc-mpicalc.obj -MD -MP -MF $(DEPDIR)/mpicalc-mpicalc.Tpo -c -o mpicalc-mpicalc.obj `if test -f 'mpicalc.c'; then $(CYGPATH_W) 'mpicalc.c'; else $(CYGPATH_W) '$(srcdir)/mpicalc.c'; fi`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/mpicalc-mpicalc.Tpo $(DEPDIR)/mpicalc-mpicalc.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='mpicalc.c' object='mpicalc-mpicalc.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mpicalc_CFLAGS) $(CFLAGS) -c -o mpicalc-mpicalc.obj `if test -f 'mpicalc.c'; then $(CYGPATH_W) 'mpicalc.c'; else $(CYGPATH_W) '$(srcdir)/mpicalc.c'; fi`
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-install-m4dataDATA: $(m4data_DATA)
-       @$(NORMAL_INSTALL)
-       @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(m4datadir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(m4datadir)" || exit 1; \
-       fi; \
-       for p in $$list; do \
-         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; \
-       done | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(m4datadir)'"; \
-         $(INSTALL_DATA) $$files "$(DESTDIR)$(m4datadir)" || exit $$?; \
-       done
-
-uninstall-m4dataDATA:
-       @$(NORMAL_UNINSTALL)
-       @list='$(m4data_DATA)'; test -n "$(m4datadir)" || list=; \
-       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-       dir='$(DESTDIR)$(m4datadir)'; $(am__uninstall_files_from_dir)
-install-nodist_includeHEADERS: $(nodist_include_HEADERS)
-       @$(NORMAL_INSTALL)
-       @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
-       if test -n "$$list"; then \
-         echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
-         $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
-       fi; \
-       for p in $$list; do \
-         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
-         echo "$$d$$p"; \
-       done | $(am__base_list) | \
-       while read files; do \
-         echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
-         $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
-       done
-
-uninstall-nodist_includeHEADERS:
-       @$(NORMAL_UNINSTALL)
-       @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
-       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
-       dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
-
-ID: $(am__tagged_files)
-       $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       set x; \
-       here=`pwd`; \
-       $(am__define_uniq_tagged_files); \
-       shift; \
-       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-         test -n "$$unique" || unique=$$empty_fix; \
-         if test $$# -gt 0; then \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             "$$@" $$unique; \
-         else \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             $$unique; \
-         fi; \
-       fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       $(am__define_uniq_tagged_files); \
-       test -z "$(CTAGS_ARGS)$$unique" \
-         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$unique
-
-GTAGS:
-       here=`$(am__cd) $(top_builddir) && pwd` \
-         && $(am__cd) $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-       list='$(am__tagged_files)'; \
-       case "$(srcdir)" in \
-         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-         *) sdir=$(subdir)/$(srcdir) ;; \
-       esac; \
-       for i in $$list; do \
-         if test -f "$$i"; then \
-           echo "$(subdir)/$$i"; \
-         else \
-           echo "$$sdir/$$i"; \
-         fi; \
-       done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) \
-               $(HEADERS)
-install-binPROGRAMS: install-libLTLIBRARIES
-
-installdirs:
-       for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(m4datadir)" "$(DESTDIR)$(includedir)"; do \
-         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
-       done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
-       clean-libtool clean-sbinPROGRAMS mostlyclean-am
-
-distclean: distclean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-       distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am: install-data-local install-m4dataDATA \
-       install-nodist_includeHEADERS
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am: install-binPROGRAMS install-binSCRIPTS \
-       install-libLTLIBRARIES install-sbinPROGRAMS
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
-       uninstall-libLTLIBRARIES uninstall-local uninstall-m4dataDATA \
-       uninstall-nodist_includeHEADERS uninstall-sbinPROGRAMS
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
-       clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
-       clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \
-       distclean distclean-compile distclean-generic \
-       distclean-libtool distclean-tags distdir dvi dvi-am html \
-       html-am info info-am install install-am install-binPROGRAMS \
-       install-binSCRIPTS install-data install-data-am \
-       install-data-local install-dvi install-dvi-am install-exec \
-       install-exec-am install-html install-html-am install-info \
-       install-info-am install-libLTLIBRARIES install-m4dataDATA \
-       install-man install-nodist_includeHEADERS install-pdf \
-       install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \
-       install-strip installcheck installcheck-am installdirs \
-       maintainer-clean maintainer-clean-generic mostlyclean \
-       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
-       pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
-       uninstall-binPROGRAMS uninstall-binSCRIPTS \
-       uninstall-libLTLIBRARIES uninstall-local uninstall-m4dataDATA \
-       uninstall-nodist_includeHEADERS uninstall-sbinPROGRAMS
-
-
-@HAVE_W32_SYSTEM_TRUE@.rc.lo:
-@HAVE_W32_SYSTEM_TRUE@ $(LTRCCOMPILE) -i "$<" -o "$@"
-
-@HAVE_W32_SYSTEM_TRUE@install-def-file:
-@HAVE_W32_SYSTEM_TRUE@ -$(INSTALL) -d $(DESTDIR)$(libdir)
-@HAVE_W32_SYSTEM_TRUE@ $(INSTALL) $(srcdir)/libgcrypt.def $(DESTDIR)$(libdir)/libgcrypt.def
-
-@HAVE_W32_SYSTEM_TRUE@uninstall-def-file:
-@HAVE_W32_SYSTEM_TRUE@ -rm $(DESTDIR)$(libdir)/libgcrypt.def
-@HAVE_W32_SYSTEM_FALSE@install-def-file:
-@HAVE_W32_SYSTEM_FALSE@uninstall-def-file:
-
-install-data-local: install-def-file
-
-uninstall-local: uninstall-def-file
-
-# FIXME: We need to figure out how to get the actual name (parsing
-# libgcrypt.la?) and how to create the hmac file already at link time
-# so that it can be used without installing libgcrypt first.
-#install-exec-hook:
-#      ./hmac256 "What am I, a doctor or a moonshuttle conductor?" \
-#          < $(DESTDIR)$(libdir)/libgcrypt.so.11.5.0 \
-#          > $(DESTDIR)$(libdir)/.libgcrypt.so.11.5.0.hmac
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
index d1ddc5d..3672916 100644 (file)
@@ -129,10 +129,13 @@ typedef struct gcry_pk_spec
  *
  */
 
+struct cipher_bulk_ops;
+
 /* Type for the cipher_setkey function.  */
 typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c,
                                                 const unsigned char *key,
-                                                unsigned keylen);
+                                                unsigned keylen,
+                                                struct cipher_bulk_ops *bulk_ops);
 
 /* Type for the cipher_encrypt function.  */
 typedef unsigned int (*gcry_cipher_encrypt_t) (void *c,
@@ -181,7 +184,7 @@ typedef struct gcry_cipher_spec
   } flags;
   const char *name;
   const char **aliases;
-  gcry_cipher_oid_spec_t *oids;
+  const gcry_cipher_oid_spec_t *oids;
   size_t blocksize;
   size_t keylen;
   size_t contextsize;
@@ -218,6 +221,11 @@ 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_buffers function. */
+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
 {
   const char *oidstring;
@@ -232,15 +240,16 @@ typedef struct gcry_md_spec
     unsigned int fips:1;
   } flags;
   const char *name;
-  unsigned char *asnoid;
+  const unsigned char *asnoid;
   int asnlen;
-  gcry_md_oid_spec_t *oids;
+  const gcry_md_oid_spec_t *oids;
   int mdlen;
   gcry_md_init_t init;
   gcry_md_write_t write;
   gcry_md_final_t final;
   gcry_md_read_t read;
   gcry_md_extract_t extract;
+  gcry_md_hash_buffers_t hash_buffers;
   size_t contextsize; /* allocate this amount of context */
   selftest_func_t selftest;
 } gcry_md_spec_t;
@@ -254,8 +263,10 @@ gcry_error_t _gcry_md_selftest (int algo, int extended,
                                 selftest_report_func_t report);
 gcry_error_t _gcry_pk_selftest (int algo, int extended,
                                 selftest_report_func_t report);
-gcry_error_t _gcry_hmac_selftest (int algo, int extended,
-                                  selftest_report_func_t report);
+gcry_error_t _gcry_mac_selftest (int algo, int extended,
+                                 selftest_report_func_t report);
+gcry_error_t _gcry_kdf_selftest (int algo, int extended,
+                                 selftest_report_func_t report);
 
 gcry_error_t _gcry_random_selftest (selftest_report_func_t report);
 
index f2acb55..87f8c4d 100644 (file)
@@ -42,6 +42,8 @@
 #define PUBKEY_FLAG_GOST           (1 << 13)
 #define PUBKEY_FLAG_NO_KEYTEST     (1 << 14)
 #define PUBKEY_FLAG_DJB_TWEAK      (1 << 15)
+#define PUBKEY_FLAG_SM2            (1 << 16)
+#define PUBKEY_FLAG_PREHASH        (1 << 17)
 
 
 enum pk_operation
@@ -112,140 +114,15 @@ 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);
 
 /*-- blake2.c --*/
 gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags,
                                           const unsigned char *key,
                                           size_t keylen, int algo);
 
-/*-- rijndael.c --*/
-void _gcry_aes_cfb_enc (void *context, unsigned char *iv,
-                        void *outbuf, const void *inbuf,
-                        size_t nblocks);
-void _gcry_aes_cfb_dec (void *context, unsigned char *iv,
-                        void *outbuf_arg, const void *inbuf_arg,
-                        size_t nblocks);
-void _gcry_aes_cbc_enc (void *context, unsigned char *iv,
-                        void *outbuf_arg, const void *inbuf_arg,
-                        size_t nblocks, int cbc_mac);
-void _gcry_aes_cbc_dec (void *context, unsigned char *iv,
-                        void *outbuf_arg, const void *inbuf_arg,
-                        size_t nblocks);
-void _gcry_aes_ctr_enc (void *context, unsigned char *ctr,
-                        void *outbuf_arg, const void *inbuf_arg,
-                        size_t nblocks);
-size_t _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
-                           const void *inbuf_arg, size_t nblocks, int encrypt);
-size_t _gcry_aes_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
-                          size_t nblocks);
-
-/*-- blowfish.c --*/
-void _gcry_blowfish_cfb_dec (void *context, unsigned char *iv,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-
-void _gcry_blowfish_cbc_dec (void *context, unsigned char *iv,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-
-void _gcry_blowfish_ctr_enc (void *context, unsigned char *ctr,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-
-/*-- cast5.c --*/
-void _gcry_cast5_cfb_dec (void *context, unsigned char *iv,
-                         void *outbuf_arg, const void *inbuf_arg,
-                         size_t nblocks);
-
-void _gcry_cast5_cbc_dec (void *context, unsigned char *iv,
-                         void *outbuf_arg, const void *inbuf_arg,
-                         size_t nblocks);
-
-void _gcry_cast5_ctr_enc (void *context, unsigned char *ctr,
-                         void *outbuf_arg, const void *inbuf_arg,
-                         size_t nblocks);
-
-/*-- camellia-glue.c --*/
-void _gcry_camellia_ctr_enc (void *context, unsigned char *ctr,
-                             void *outbuf_arg, const void *inbuf_arg,
-                             size_t nblocks);
-void _gcry_camellia_cbc_dec (void *context, unsigned char *iv,
-                             void *outbuf_arg, const void *inbuf_arg,
-                             size_t nblocks);
-void _gcry_camellia_cfb_dec (void *context, unsigned char *iv,
-                             void *outbuf_arg, const void *inbuf_arg,
-                             size_t nblocks);
-size_t _gcry_camellia_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
-                                const void *inbuf_arg, size_t nblocks,
-                                int encrypt);
-size_t _gcry_camellia_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
-                               size_t nblocks);
-
-/*-- des.c --*/
-void _gcry_3des_ctr_enc (void *context, unsigned char *ctr,
-                         void *outbuf_arg, const void *inbuf_arg,
-                         size_t nblocks);
-
-void _gcry_3des_cbc_dec (void *context, unsigned char *iv,
-                         void *outbuf_arg, const void *inbuf_arg,
-                         size_t nblocks);
-
-void _gcry_3des_cfb_dec (void *context, unsigned char *iv,
-                         void *outbuf_arg, const void *inbuf_arg,
-                         size_t nblocks);
-
-/*-- serpent.c --*/
-void _gcry_serpent_ctr_enc (void *context, unsigned char *ctr,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-void _gcry_serpent_cbc_dec (void *context, unsigned char *iv,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-void _gcry_serpent_cfb_dec (void *context, unsigned char *iv,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-size_t _gcry_serpent_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
-                               const void *inbuf_arg, size_t nblocks,
-                               int encrypt);
-size_t _gcry_serpent_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
-                              size_t nblocks);
-
-/*-- twofish.c --*/
-void _gcry_twofish_ctr_enc (void *context, unsigned char *ctr,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-void _gcry_twofish_cbc_dec (void *context, unsigned char *iv,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-void _gcry_twofish_cfb_dec (void *context, unsigned char *iv,
-                            void *outbuf_arg, const void *inbuf_arg,
-                            size_t nblocks);
-size_t _gcry_twofish_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
-                               const void *inbuf_arg, size_t nblocks,
-                               int encrypt);
-size_t _gcry_twofish_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
-                              size_t nblocks);
-
 /*-- dsa.c --*/
 void _gcry_register_pk_dsa_progress (gcry_handler_progress_t cbc, void *cb_data);
 
@@ -289,43 +166,48 @@ extern gcry_cipher_spec_t _gcry_cipher_spec_idea;
 extern gcry_cipher_spec_t _gcry_cipher_spec_salsa20;
 extern gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12;
 extern gcry_cipher_spec_t _gcry_cipher_spec_gost28147;
+extern gcry_cipher_spec_t _gcry_cipher_spec_gost28147_mesh;
 extern gcry_cipher_spec_t _gcry_cipher_spec_chacha20;
+extern gcry_cipher_spec_t _gcry_cipher_spec_sm4;
 
 /* Declarations for the digest specifications.  */
-extern gcry_md_spec_t _gcry_digest_spec_crc32;
-extern gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510;
-extern gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440;
-extern gcry_md_spec_t _gcry_digest_spec_gost3411_94;
-extern gcry_md_spec_t _gcry_digest_spec_gost3411_cp;
-extern gcry_md_spec_t _gcry_digest_spec_stribog_256;
-extern gcry_md_spec_t _gcry_digest_spec_stribog_512;
-extern gcry_md_spec_t _gcry_digest_spec_md2;
-extern gcry_md_spec_t _gcry_digest_spec_md4;
-extern gcry_md_spec_t _gcry_digest_spec_md5;
-extern gcry_md_spec_t _gcry_digest_spec_rmd160;
-extern gcry_md_spec_t _gcry_digest_spec_sha1;
-extern gcry_md_spec_t _gcry_digest_spec_sha224;
-extern gcry_md_spec_t _gcry_digest_spec_sha256;
-extern gcry_md_spec_t _gcry_digest_spec_sha384;
-extern gcry_md_spec_t _gcry_digest_spec_sha512;
-extern gcry_md_spec_t _gcry_digest_spec_sha3_224;
-extern gcry_md_spec_t _gcry_digest_spec_sha3_256;
-extern gcry_md_spec_t _gcry_digest_spec_sha3_512;
-extern gcry_md_spec_t _gcry_digest_spec_sha3_384;
-extern gcry_md_spec_t _gcry_digest_spec_shake128;
-extern gcry_md_spec_t _gcry_digest_spec_shake256;
-extern gcry_md_spec_t _gcry_digest_spec_tiger;
-extern gcry_md_spec_t _gcry_digest_spec_tiger1;
-extern gcry_md_spec_t _gcry_digest_spec_tiger2;
-extern gcry_md_spec_t _gcry_digest_spec_whirlpool;
-extern gcry_md_spec_t _gcry_digest_spec_blake2b_512;
-extern gcry_md_spec_t _gcry_digest_spec_blake2b_384;
-extern gcry_md_spec_t _gcry_digest_spec_blake2b_256;
-extern gcry_md_spec_t _gcry_digest_spec_blake2b_160;
-extern gcry_md_spec_t _gcry_digest_spec_blake2s_256;
-extern gcry_md_spec_t _gcry_digest_spec_blake2s_224;
-extern gcry_md_spec_t _gcry_digest_spec_blake2s_160;
-extern gcry_md_spec_t _gcry_digest_spec_blake2s_128;
+extern const gcry_md_spec_t _gcry_digest_spec_crc32;
+extern const gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510;
+extern const gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440;
+extern const gcry_md_spec_t _gcry_digest_spec_gost3411_94;
+extern const gcry_md_spec_t _gcry_digest_spec_gost3411_cp;
+extern const gcry_md_spec_t _gcry_digest_spec_stribog_256;
+extern const gcry_md_spec_t _gcry_digest_spec_stribog_512;
+extern const gcry_md_spec_t _gcry_digest_spec_md2;
+extern const gcry_md_spec_t _gcry_digest_spec_md4;
+extern const gcry_md_spec_t _gcry_digest_spec_md5;
+extern const gcry_md_spec_t _gcry_digest_spec_rmd160;
+extern const gcry_md_spec_t _gcry_digest_spec_sha1;
+extern const gcry_md_spec_t _gcry_digest_spec_sha224;
+extern const gcry_md_spec_t _gcry_digest_spec_sha256;
+extern const gcry_md_spec_t _gcry_digest_spec_sha384;
+extern const gcry_md_spec_t _gcry_digest_spec_sha512;
+extern const gcry_md_spec_t _gcry_digest_spec_sha512_224;
+extern const gcry_md_spec_t _gcry_digest_spec_sha512_256;
+extern const gcry_md_spec_t _gcry_digest_spec_sha3_224;
+extern const gcry_md_spec_t _gcry_digest_spec_sha3_256;
+extern const gcry_md_spec_t _gcry_digest_spec_sha3_512;
+extern const gcry_md_spec_t _gcry_digest_spec_sha3_384;
+extern const gcry_md_spec_t _gcry_digest_spec_shake128;
+extern const gcry_md_spec_t _gcry_digest_spec_shake256;
+extern const gcry_md_spec_t _gcry_digest_spec_tiger;
+extern const gcry_md_spec_t _gcry_digest_spec_tiger1;
+extern const gcry_md_spec_t _gcry_digest_spec_tiger2;
+extern const gcry_md_spec_t _gcry_digest_spec_whirlpool;
+extern const gcry_md_spec_t _gcry_digest_spec_blake2b_512;
+extern const gcry_md_spec_t _gcry_digest_spec_blake2b_384;
+extern const gcry_md_spec_t _gcry_digest_spec_blake2b_256;
+extern const gcry_md_spec_t _gcry_digest_spec_blake2b_160;
+extern const gcry_md_spec_t _gcry_digest_spec_blake2s_256;
+extern const gcry_md_spec_t _gcry_digest_spec_blake2s_224;
+extern const gcry_md_spec_t _gcry_digest_spec_blake2s_160;
+extern const gcry_md_spec_t _gcry_digest_spec_blake2s_128;
+extern const gcry_md_spec_t _gcry_digest_spec_sm3;
 
 /* Declarations for the pubkey cipher specifications.  */
 extern gcry_pk_spec_t _gcry_pubkey_spec_rsa;
index f77878b..da9948a 100644 (file)
@@ -58,6 +58,7 @@ _gcry_ctx_alloc (int type, size_t length, void (*deinit)(void*))
   switch (type)
     {
     case CONTEXT_TYPE_EC:
+    case CONTEXT_TYPE_RANDOM_OVERRIDE:
       break;
     default:
       log_bug ("bad context type %d given to _gcry_ctx_alloc\n", type);
@@ -125,6 +126,7 @@ _gcry_ctx_release (gcry_ctx_t ctx)
   switch (ctx->type)
     {
     case CONTEXT_TYPE_EC:
+    case CONTEXT_TYPE_RANDOM_OVERRIDE:
       break;
     default:
       log_fatal ("bad context type %d detected in gcry_ctx_relase\n",
index 875de24..5be367b 100644 (file)
@@ -22,7 +22,7 @@
 
 /* Context types as used in struct gcry_context.  */
 #define CONTEXT_TYPE_EC 1  /* The context is used with EC functions.  */
-
+#define CONTEXT_TYPE_RANDOM_OVERRIDE 2  /* Used with pubkey functions.  */
 
 gcry_ctx_t _gcry_ctx_alloc (int type, size_t length, void (*deinit)(void*));
 void *_gcry_ctx_get_pointer (gcry_ctx_t ctx, int type);
index 5aeb77d..cedc4f4 100644 (file)
@@ -1,18 +1,19 @@
 /* dumpsexp.c - Dump S-expressions.
  * Copyright (C) 2007, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2010 g10 Code GmbH.
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 3 of the License,
- * or (at your option) any later version.
+ * 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.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -43,8 +44,8 @@ print_version (int with_help)
 {
   fputs (MYVERSION_LINE "\n"
          "Copyright (C) 2010 Free Software Foundation, Inc.\n"
-         "License GPLv3+: GNU GPL version 3 or later "
-         "<http://gnu.org/licenses/gpl.html>\n"
+         "License LGPLv2.1+: GNU LGPL version 2.1 or later "
+         "<http://gnu.org/licenses/>\n"
          "This is free software: you are free to change and redistribute it.\n"
          "There is NO WARRANTY, to the extent permitted by law.\n",
          stdout);
index d74fb69..479862f 100644 (file)
@@ -38,12 +38,13 @@ struct mpi_ec_ctx_s
   gcry_mpi_t b;         /* Second coefficient of the Weierstrass equation.  */
   gcry_mpi_point_t G;   /* Base point (generator).  */
   gcry_mpi_t n;         /* Order of G.  */
-  gcry_mpi_t h;         /* Cofactor.  */
+  unsigned int h;       /* Cofactor.  */
 
   /* The actual key.  May not be set.  */
   gcry_mpi_point_t Q;   /* Public key.   */
   gcry_mpi_t d;         /* Private key.  */
 
+  const char *name;      /* Name of the curve.  */
 
   /* This structure is private to mpi/ec.c! */
   struct {
@@ -66,6 +67,14 @@ struct mpi_ec_ctx_s
     /*   gcry_mpi_t s[10]; */
     /*   gcry_mpi_t c; */
   } t;
+
+  /* Curve specific computation routines for the field.  */
+  void (* addm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx);
+  void (* subm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ec);
+  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);
 };
 
 
@@ -82,7 +91,8 @@ gpg_err_code_t   _gcry_ecc_set_point (const char *name,
                                       gcry_mpi_point_t newvalue, mpi_ec_t ec);
 
 /*-- cipher/ecc-misc.c --*/
-gcry_err_code_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value);
+gpg_err_code_t _gcry_ecc_sec_decodepoint (gcry_mpi_t value, mpi_ec_t ec,
+                                          mpi_point_t result);
 gpg_err_code_t _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx,
                                            mpi_point_t result);
 
index af3fe2c..89f8204 100644 (file)
 #include <string.h>
 #ifdef ENABLE_HMAC_BINARY_CHECK
 # include <dlfcn.h>
+# include <elf.h>
+# include <limits.h>
+# include <link.h>
 #endif
 #ifdef HAVE_SYSLOG
 # include <syslog.h>
 #endif /*HAVE_SYSLOG*/
 
-#include "g10lib.h"
-#include "cipher-proto.h"
-#include "hmac256.h"
-
-
 /* The name of the file used to force libgcrypt into fips mode. */
 #define FIPS_FORCE_FILE "/etc/gcrypt/fips_enabled"
 
+#include "g10lib.h"
+#include "cipher-proto.h"
+#include "../random/random.h"
 
 /* The states of the finite state machine used in fips mode.  */
 enum module_states
@@ -57,15 +58,7 @@ enum module_states
    that fips mode is the default unless changed by the initialization
    code. To check whether fips mode is enabled, use the function
    fips_mode()! */
-static int no_fips_mode_required;
-
-/* Flag to indicate that we are in the enforced FIPS mode.  */
-static int enforced_fips_mode;
-
-/* If this flag is set, the application may no longer assume that the
-   process is running in FIPS mode.  This flag is protected by the
-   FSM_LOCK.  */
-static int inactive_fips_mode;
+int _gcry_no_fips_mode_required;
 
 /* This is the lock we use to protect the FSM.  */
 GPGRT_LOCK_DEFINE (fsm_lock);
@@ -91,36 +84,18 @@ static void fips_new_state (enum module_states new_state);
 
 
 \f
-/* Check whether the OS is in FIPS mode and record that in a module
-   local variable.  If FORCE is passed as true, fips mode will be
-   enabled anyway. Note: This function is not thread-safe and should
-   be called before any threads are created.  This function may only
-   be called once.  */
-void
-_gcry_initialize_fips_mode (int force)
+/*
+ * Returns 1 if the FIPS mode is to be activated based on the
+ * environment variable LIBGCRYPT_FORCE_FIPS_MODE, the file defined by
+ * FIPS_FORCE_FILE, or /proc/sys/crypto/fips_enabled.
+ * This function aborts on misconfigured filesystems.
+ */
+static int
+check_fips_system_setting (void)
 {
-  static int done;
-  gpg_error_t err;
-
-  /* Make sure we are not accidentally called twice.  */
-  if (done)
-    {
-      if ( fips_mode () )
-        {
-          fips_new_state (STATE_FATALERROR);
-          fips_noreturn ();
-        }
-      /* If not in fips mode an assert is sufficient.  */
-      gcry_assert (!done);
-    }
-  done = 1;
-
-  /* If the calling application explicitly requested fipsmode, do so.  */
-  if (force)
-    {
-      gcry_assert (!no_fips_mode_required);
-      goto leave;
-    }
+  /* Do we have the environment variable set?  */
+  if (getenv ("LIBGCRYPT_FORCE_FIPS_MODE"))
+    return 1;
 
   /* For testing the system it is useful to override the system
      provided detection of the FIPS mode and force FIPS mode using a
@@ -128,10 +103,7 @@ _gcry_initialize_fips_mode (int force)
      confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is
      actually used.  The file itself may be empty.  */
   if ( !access (FIPS_FORCE_FILE, F_OK) )
-    {
-      gcry_assert (!no_fips_mode_required);
-      goto leave;
-    }
+    return 1;
 
   /* Checking based on /proc file properties.  */
   {
@@ -148,8 +120,7 @@ _gcry_initialize_fips_mode (int force)
           {
             /* System is in fips mode.  */
             fclose (fp);
-            gcry_assert (!no_fips_mode_required);
-            goto leave;
+            return 1;
           }
         fclose (fp);
       }
@@ -170,14 +141,65 @@ _gcry_initialize_fips_mode (int force)
       }
   }
 
+  return 0;
+}
+
+/*
+ * Initial check if the FIPS mode should be activated on startup.
+ * Called by the constructor at the initialization of the library.
+ */
+int
+_gcry_fips_to_activate (void)
+{
+  return check_fips_system_setting ();
+}
+
+
+/* Check whether the OS is in FIPS mode and record that in a module
+   local variable.  If FORCE is passed as true, fips mode will be
+   enabled anyway. Note: This function is not thread-safe and should
+   be called before any threads are created.  This function may only
+   be called once.  */
+void
+_gcry_initialize_fips_mode (int force)
+{
+  static int done;
+  gpg_error_t err;
+
+  /* Make sure we are not accidentally called twice.  */
+  if (done)
+    {
+      if ( fips_mode () )
+        {
+          fips_new_state (STATE_FATALERROR);
+          fips_noreturn ();
+        }
+      /* If not in fips mode an assert is sufficient.  */
+      gcry_assert (!done);
+    }
+  done = 1;
+
+  /* If the calling application explicitly requested fipsmode, do so.  */
+  if (force)
+    {
+      gcry_assert (!_gcry_no_fips_mode_required);
+      goto leave;
+    }
+
+  /* If the system explicitly requested fipsmode, do so.  */
+  if (check_fips_system_setting ())
+    {
+      gcry_assert (!_gcry_no_fips_mode_required);
+      goto leave;
+    }
+
   /* Fips not not requested, set flag.  */
-  no_fips_mode_required = 1;
+  _gcry_no_fips_mode_required = 1;
 
  leave:
-  if (!no_fips_mode_required)
+  if (!_gcry_no_fips_mode_required)
     {
       /* Yes, we are in FIPS mode.  */
-      FILE *fp;
 
       /* Intitialize the lock to protect the FSM.  */
       err = gpgrt_lock_init (&fsm_lock);
@@ -196,23 +218,10 @@ _gcry_initialize_fips_mode (int force)
           abort ();
         }
 
-
-      /* If the FIPS force files exists, is readable and has a number
-         != 0 on its first line, we enable the enforced fips mode.  */
-      fp = fopen (FIPS_FORCE_FILE, "r");
-      if (fp)
-        {
-          char line[256];
-
-          if (fgets (line, sizeof line, fp) && atoi (line))
-            enforced_fips_mode = 1;
-          fclose (fp);
-        }
-
       /* Now get us into the INIT state.  */
       fips_new_state (STATE_INIT);
-
     }
+
   return;
 }
 
@@ -255,84 +264,6 @@ unlock_fsm (void)
 }
 
 
-/* This function returns true if fips mode is enabled.  This is
-   independent of the fips required finite state machine and only used
-   to enable fips specific code.  Please use the fips_mode macro
-   instead of calling this function directly. */
-int
-_gcry_fips_mode (void)
-{
-  /* No locking is required because we have the requirement that this
-     variable is only initialized once with no other threads
-     existing.  */
-  return !no_fips_mode_required;
-}
-
-
-/* Return a flag telling whether we are in the enforced fips mode.  */
-int
-_gcry_enforced_fips_mode (void)
-{
-  if (!_gcry_fips_mode ())
-    return 0;
-  return enforced_fips_mode;
-}
-
-/* Set a flag telling whether we are in the enforced fips mode.  */
-void
-_gcry_set_enforced_fips_mode (void)
-{
-  enforced_fips_mode = 1;
-}
-
-/* If we do not want to enforce the fips mode, we can set a flag so
-   that the application may check whether it is still in fips mode.
-   TEXT will be printed as part of a syslog message.  This function
-   may only be be called if in fips mode. */
-void
-_gcry_inactivate_fips_mode (const char *text)
-{
-  gcry_assert (_gcry_fips_mode ());
-
-  if (_gcry_enforced_fips_mode () )
-    {
-      /* Get us into the error state. */
-      fips_signal_error (text);
-      return;
-    }
-
-  lock_fsm ();
-  if (!inactive_fips_mode)
-    {
-      inactive_fips_mode = 1;
-      unlock_fsm ();
-#ifdef HAVE_SYSLOG
-      syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
-              "%s - FIPS mode inactivated", text);
-#endif /*HAVE_SYSLOG*/
-    }
-  else
-    unlock_fsm ();
-}
-
-
-/* Return the FIPS mode inactive flag.  If it is true the FIPS mode is
-   not anymore active.  */
-int
-_gcry_is_fips_mode_inactive (void)
-{
-  int flag;
-
-  if (!_gcry_fips_mode ())
-    return 0;
-  lock_fsm ();
-  flag = inactive_fips_mode;
-  unlock_fsm ();
-  return flag;
-}
-
-
-
 static const char *
 state2str (enum module_states state)
 {
@@ -381,6 +312,9 @@ _gcry_fips_is_operational (void)
              our FSM make sure that we won't oversee any error. */
           unlock_fsm ();
           _gcry_fips_run_selftests (0);
+
+          /* Release resources for random.  */
+          _gcry_random_close_fds ();
           lock_fsm ();
         }
 
@@ -410,6 +344,52 @@ _gcry_fips_test_operational (void)
   return result;
 }
 
+int
+_gcry_fips_indicator_cipher (va_list arg_ptr)
+{
+  enum gcry_cipher_algos alg = va_arg (arg_ptr, enum gcry_cipher_algos);
+  enum gcry_cipher_modes mode;
+
+  switch (alg)
+    {
+    case GCRY_CIPHER_AES:
+    case GCRY_CIPHER_AES192:
+    case GCRY_CIPHER_AES256:
+      mode = va_arg (arg_ptr, enum gcry_cipher_modes);
+      switch (mode)
+        {
+        case GCRY_CIPHER_MODE_ECB:
+        case GCRY_CIPHER_MODE_CBC:
+        case GCRY_CIPHER_MODE_CFB:
+        case GCRY_CIPHER_MODE_CFB8:
+        case GCRY_CIPHER_MODE_OFB:
+        case GCRY_CIPHER_MODE_CTR:
+        case GCRY_CIPHER_MODE_CCM:
+        case GCRY_CIPHER_MODE_GCM:
+        case GCRY_CIPHER_MODE_XTS:
+          return GPG_ERR_NO_ERROR;
+        default:
+          return GPG_ERR_NOT_SUPPORTED;
+        }
+    default:
+      return GPG_ERR_NOT_SUPPORTED;
+    }
+}
+
+int
+_gcry_fips_indicator_kdf (va_list arg_ptr)
+{
+  enum gcry_kdf_algos alg = va_arg (arg_ptr, enum gcry_kdf_algos);
+
+  switch (alg)
+    {
+    case GCRY_KDF_PBKDF2:
+      return GPG_ERR_NO_ERROR;
+    default:
+      return GPG_ERR_NOT_SUPPORTED;
+    }
+}
+
 
 /* This is a test on whether the library is in the error or
    operational state. */
@@ -455,7 +435,6 @@ run_cipher_selftests (int extended)
 {
   static int algos[] =
     {
-      GCRY_CIPHER_3DES,
       GCRY_CIPHER_AES128,
       GCRY_CIPHER_AES192,
       GCRY_CIPHER_AES256,
@@ -486,7 +465,9 @@ run_digest_selftests (int extended)
     {
       GCRY_MD_SHA1,
       GCRY_MD_SHA224,
+#ifndef ENABLE_HMAC_BINARY_CHECK
       GCRY_MD_SHA256,
+#endif
       GCRY_MD_SHA384,
       GCRY_MD_SHA512,
       0
@@ -507,21 +488,24 @@ run_digest_selftests (int extended)
 }
 
 
-/* Run self-tests for all HMAC algorithms.  Return 0 on success. */
+/* Run self-tests for MAC algorithms.  Return 0 on success. */
 static int
-run_hmac_selftests (int extended)
+run_mac_selftests (int extended)
 {
   static int algos[] =
     {
-      GCRY_MD_SHA1,
-      GCRY_MD_SHA224,
-      GCRY_MD_SHA256,
-      GCRY_MD_SHA384,
-      GCRY_MD_SHA512,
-      GCRY_MD_SHA3_224,
-      GCRY_MD_SHA3_256,
-      GCRY_MD_SHA3_384,
-      GCRY_MD_SHA3_512,
+      GCRY_MAC_HMAC_SHA1,
+      GCRY_MAC_HMAC_SHA224,
+#ifndef ENABLE_HMAC_BINARY_CHECK
+      GCRY_MAC_HMAC_SHA256,
+#endif
+      GCRY_MAC_HMAC_SHA384,
+      GCRY_MAC_HMAC_SHA512,
+      GCRY_MAC_HMAC_SHA3_224,
+      GCRY_MAC_HMAC_SHA3_256,
+      GCRY_MAC_HMAC_SHA3_384,
+      GCRY_MAC_HMAC_SHA3_512,
+      GCRY_MAC_CMAC_AES,
       0
     };
   int idx;
@@ -530,8 +514,8 @@ run_hmac_selftests (int extended)
 
   for (idx=0; algos[idx]; idx++)
     {
-      err = _gcry_hmac_selftest (algos[idx], extended, reporter);
-      reporter ("hmac", algos[idx], NULL,
+      err = _gcry_mac_selftest (algos[idx], extended, reporter);
+      reporter ("mac", algos[idx], NULL,
                 err? gpg_strerror (err):NULL);
       if (err)
         anyerr = 1;
@@ -539,6 +523,29 @@ run_hmac_selftests (int extended)
   return anyerr;
 }
 
+/* Run self-tests for all KDF algorithms.  Return 0 on success. */
+static int
+run_kdf_selftests (int extended)
+{
+  static int algos[] =
+    {
+      GCRY_KDF_PBKDF2,
+      0
+    };
+  int idx;
+  gpg_error_t err;
+  int anyerr = 0;
+
+  for (idx=0; algos[idx]; idx++)
+    {
+      err = _gcry_kdf_selftest (algos[idx], extended, reporter);
+      reporter ("kdf", algos[idx], NULL, err? gpg_strerror (err):NULL);
+      if (err)
+        anyerr = 1;
+    }
+  return anyerr;
+}
+
 
 /* Run self-tests for all required public key algorithms.  Return 0 on
    success. */
@@ -548,7 +555,6 @@ run_pubkey_selftests (int extended)
   static int algos[] =
     {
       GCRY_PK_RSA,
-      GCRY_PK_DSA,
       GCRY_PK_ECC,
       0
     };
@@ -581,100 +587,266 @@ run_random_selftests (void)
   return !!err;
 }
 
+#ifdef ENABLE_HMAC_BINARY_CHECK
+# ifndef KEY_FOR_BINARY_CHECK
+# define KEY_FOR_BINARY_CHECK "What am I, a doctor or a moonshuttle conductor?"
+# endif
+#define HMAC_LEN 32
+
+/*
+ * In the ELF file opened as FP, fill the ELF header to the pointer
+ * EHDR_P, determine the maximum offset of segments in R_OFFSET.
+ * Also, find the section which contains the hmac value and return it
+ * in HMAC.  Rewinds FP to the beginning on success.
+ */
+static gpg_error_t
+get_file_offset (FILE *fp, ElfW (Ehdr) *ehdr_p,
+                 unsigned long *r_offset, unsigned char hmac[HMAC_LEN])
+{
+  ElfW (Phdr) phdr;
+  ElfW (Shdr) shdr;
+  int i;
+  unsigned long off_segment = 0;
+
+  /* Read the ELF header */
+  if (fseek (fp, 0, SEEK_SET) != 0)
+    return gpg_error_from_syserror ();
+  if (fread (ehdr_p, sizeof (*ehdr_p), 1, fp) != 1)
+    return gpg_error_from_syserror ();
+
+  /* The program header entry size should match the size of the phdr struct */
+  if (ehdr_p->e_phentsize != sizeof (phdr))
+    return gpg_error (GPG_ERR_INV_OBJ);
+  if (ehdr_p->e_phoff == 0)
+    return gpg_error (GPG_ERR_INV_OBJ);
+
+  /* Jump to the first program header */
+  if (fseek (fp, ehdr_p->e_phoff, SEEK_SET) != 0)
+    return gpg_error_from_syserror ();
+
+  /* Iterate over the program headers, determine the last offset of
+     segments.  */
+  for (i = 0; i < ehdr_p->e_phnum; i++)
+    {
+      unsigned long off;
+
+      if (fread (&phdr, sizeof (phdr), 1, fp) != 1)
+        return gpg_error_from_syserror ();
+
+      off = phdr.p_offset + phdr.p_filesz;
+      if (off_segment < off)
+        off_segment = off;
+    }
+
+  if (!off_segment)
+    /* No segment found in the file */
+    return gpg_error (GPG_ERR_INV_OBJ);
+
+  /* The section header entry size should match the size of the shdr struct */
+  if (ehdr_p->e_shentsize != sizeof (shdr))
+    return gpg_error (GPG_ERR_INV_OBJ);
+  if (ehdr_p->e_shoff == 0)
+    return gpg_error (GPG_ERR_INV_OBJ);
+
+  /* Jump to the first section header */
+  if (fseek (fp, ehdr_p->e_shoff, SEEK_SET) != 0)
+    return gpg_error_from_syserror ();
+
+  /* Iterate over the section headers, determine the note section,
+     read the hmac value.  */
+  for (i = 0; i < ehdr_p->e_shnum; i++)
+    {
+      long off;
+
+      if (fread (&shdr, sizeof (shdr), 1, fp) != 1)
+        return gpg_error_from_syserror ();
+
+      off = ftell (fp);
+      if (shdr.sh_type == SHT_NOTE && shdr.sh_flags == 0 && shdr.sh_size == 48)
+        {
+          const char header_of_the_note[] = {
+            0x04, 0x00, 0x00, 0x00,
+            0x20, 0x00, 0x00, 0x00,
+            0xca, 0xfe, 0x2a, 0x8e,
+            'F', 'D', 'O', 0x00
+          };
+          unsigned char header[16];
+
+          /* Jump to the note section.  */
+          if (fseek (fp, shdr.sh_offset, SEEK_SET) != 0)
+            return gpg_error_from_syserror ();
+
+          if (fread (header, sizeof (header), 1, fp) != 1)
+            return gpg_error_from_syserror ();
+
+          if (!memcmp (header, header_of_the_note, 16))
+            {
+              /* Found.  Read the hmac value into HMAC.  */
+              if (fread (hmac, HMAC_LEN, 1, fp) != 1)
+                return gpg_error_from_syserror ();
+              break;
+            }
+
+          /* Back to the next section header.  */
+          if (fseek (fp, off, SEEK_SET) != 0)
+            return gpg_error_from_syserror ();
+        }
+    }
+
+  if (i == ehdr_p->e_shnum)
+    /* The note section not found.  */
+    return gpg_error (GPG_ERR_INV_OBJ);
+
+  /* Fix up the ELF header, clean all section information.  */
+  ehdr_p->e_shoff = 0;
+  ehdr_p->e_shentsize = 0;
+  ehdr_p->e_shnum = 0;
+  ehdr_p->e_shstrndx = 0;
+
+  *r_offset = off_segment;
+  if (fseek (fp, 0, SEEK_SET) != 0)
+    return gpg_error_from_syserror ();
+
+  return 0;
+}
+
+static gpg_error_t
+hmac256_check (const char *filename, const char *key)
+{
+  gpg_error_t err;
+  FILE *fp;
+  gcry_md_hd_t hd;
+  const size_t buffer_size = 32768;
+  size_t nread;
+  char *buffer;
+  unsigned long offset = 0;
+  unsigned long pos = 0;
+  ElfW (Ehdr) ehdr;
+  unsigned char hmac[HMAC_LEN];
+
+  fp = fopen (filename, "rb");
+  if (!fp)
+    return gpg_error (GPG_ERR_INV_OBJ);
+
+  err = get_file_offset (fp, &ehdr, &offset, hmac);
+  if (err)
+    {
+      fclose (fp);
+      return err;
+    }
+
+  err = _gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+  if (err)
+    {
+      fclose (fp);
+      return err;
+    }
+
+  err = _gcry_md_setkey (hd, key, strlen (key));
+  if (err)
+    {
+      fclose (fp);
+      _gcry_md_close (hd);
+      return err;
+    }
+
+  buffer = xtrymalloc (buffer_size);
+  if (!buffer)
+    {
+      err = gpg_error_from_syserror ();
+      fclose (fp);
+      _gcry_md_close (hd);
+      return err;
+    }
+
+  while (1)
+    {
+      nread = fread (buffer, 1, buffer_size, fp);
+      if (pos + nread >= offset)
+        nread = offset - pos;
+
+      /* Copy the fixed ELF header at the beginning.  */
+      if (pos == 0)
+        memcpy (buffer, &ehdr, sizeof (ehdr));
+
+      _gcry_md_write (hd, buffer, nread);
+
+      if (nread < buffer_size)
+        break;
+
+      pos += nread;
+    }
+
+  if (ferror (fp))
+    err = gpg_error (GPG_ERR_INV_HANDLE);
+  else
+    {
+      unsigned char *digest;
+
+      digest = _gcry_md_read (hd, 0);
+      if (!memcmp (digest, hmac, HMAC_LEN))
+        /* Success.  */
+        err = 0;
+      else
+        err = gpg_error (GPG_ERR_CHECKSUM);
+    }
+
+  _gcry_md_close (hd);
+  xfree (buffer);
+  fclose (fp);
+
+  return err;
+}
+
 /* Run an integrity check on the binary.  Returns 0 on success.  */
 static int
 check_binary_integrity (void)
 {
-#ifdef ENABLE_HMAC_BINARY_CHECK
   gpg_error_t err;
   Dl_info info;
-  unsigned char digest[32];
-  int dlen;
-  char *fname = NULL;
-  const char key[] = "What am I, a doctor or a moonshuttle conductor?";
+  const char *key = KEY_FOR_BINARY_CHECK;
 
-  if (!dladdr ("gcry_check_version", &info))
+  if (!dladdr (hmac256_check, &info))
     err = gpg_error_from_syserror ();
   else
-    {
-      dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname,
-                                 key, strlen (key));
-      if (dlen < 0)
-        err = gpg_error_from_syserror ();
-      else if (dlen != 32)
-        err = gpg_error (GPG_ERR_INTERNAL);
-      else
-        {
-          fname = xtrymalloc (strlen (info.dli_fname) + 1 + 5 + 1 );
-          if (!fname)
-            err = gpg_error_from_syserror ();
-          else
-            {
-              FILE *fp;
-              char *p;
-
-              /* Prefix the basename with a dot.  */
-              strcpy (fname, info.dli_fname);
-              p = strrchr (fname, '/');
-              if (p)
-                p++;
-              else
-                p = fname;
-              memmove (p+1, p, strlen (p)+1);
-              *p = '.';
-              strcat (fname, ".hmac");
-
-              /* Open the file.  */
-              fp = fopen (fname, "r");
-              if (!fp)
-                err = gpg_error_from_syserror ();
-              else
-                {
-                  /* A buffer of 64 bytes plus one for a LF and one to
-                     detect garbage.  */
-                  unsigned char buffer[64+1+1];
-                  const unsigned char *s;
-                  int n;
-
-                  /* The HMAC files consists of lowercase hex digits
-                     with an optional trailing linefeed or optional
-                     with two trailing spaces.  The latter format
-                     allows the use of the usual sha1sum format.  Fail
-                     if there is any garbage.  */
-                  err = gpg_error (GPG_ERR_SELFTEST_FAILED);
-                  n = fread (buffer, 1, sizeof buffer, fp);
-                  if (n == 64
-                      || (n == 65 && buffer[64] == '\n')
-                      || (n == 66 && buffer[64] == ' ' && buffer[65] == ' '))
-                    {
-                      buffer[64] = 0;
-                      for (n=0, s= buffer;
-                           n < 32 && loxdigit_p (s) && loxdigit_p (s+1);
-                           n++, s += 2)
-                        buffer[n] = loxtoi_2 (s);
-                      if ( n == 32 && !memcmp (digest, buffer, 32) )
-                        err = 0;
-                    }
-                  fclose (fp);
-                }
-            }
-        }
-    }
-  reporter ("binary", 0, fname, err? gpg_strerror (err):NULL);
+    err = hmac256_check (info.dli_fname, key);
+
+  reporter ("binary", 0, NULL, err? gpg_strerror (err):NULL);
 #ifdef HAVE_SYSLOG
   if (err)
     syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
-            "integrity check using `%s' failed: %s",
-            fname? fname:"[?]", gpg_strerror (err));
+            "integrity check failed: %s",
+            gpg_strerror (err));
 #endif /*HAVE_SYSLOG*/
-  xfree (fname);
   return !!err;
-#else
-  return 0;
-#endif
 }
 
 
+/* Run self-tests for HMAC-SHA256 algorithm before verifying library integrity.
+ * Return 0 on success. */
+static int
+run_hmac_sha256_selftests (int extended)
+{
+  gpg_error_t err;
+  int anyerr = 0;
+
+  err = _gcry_md_selftest (GCRY_MD_SHA256, extended, reporter);
+  reporter ("digest", GCRY_MD_SHA256, NULL,
+            err? gpg_strerror (err):NULL);
+  if (err)
+    anyerr = 1;
+
+  err = _gcry_mac_selftest (GCRY_MAC_HMAC_SHA256, extended, reporter);
+  reporter ("mac", GCRY_MAC_HMAC_SHA256, NULL,
+            err? gpg_strerror (err):NULL);
+  if (err)
+    anyerr = 1;
+
+  return anyerr;
+}
+#endif
+
+
 /* Run the self-tests.  If EXTENDED is true, extended versions of the
    selftest are run, that is more tests than required by FIPS.  */
 gpg_err_code_t
@@ -686,13 +858,29 @@ _gcry_fips_run_selftests (int extended)
   if (fips_mode ())
     fips_new_state (STATE_SELFTEST);
 
+#ifdef ENABLE_HMAC_BINARY_CHECK
+  if (run_hmac_sha256_selftests (extended))
+    goto leave;
+
+  if (fips_mode ())
+    {
+      /* Now check the integrity of the binary.  We do this this after
+         having checked the HMAC code.  */
+      if (check_binary_integrity ())
+        goto leave;
+    }
+#endif
+
   if (run_cipher_selftests (extended))
     goto leave;
 
   if (run_digest_selftests (extended))
     goto leave;
 
-  if (run_hmac_selftests (extended))
+  if (run_mac_selftests (extended))
+    goto leave;
+
+  if (run_kdf_selftests (extended))
     goto leave;
 
   /* Run random tests before the pubkey tests because the latter
@@ -703,11 +891,6 @@ _gcry_fips_run_selftests (int extended)
   if (run_pubkey_selftests (extended))
     goto leave;
 
-  /* Now check the integrity of the binary.  We do this this after
-     having checked the HMAC code.  */
-  if (check_binary_integrity ())
-    goto leave;
-
   /* All selftests passed.  */
   result = STATE_OPERATIONAL;
   ec = 0;
index 961b515..bfaf509 100644 (file)
 #define GCC_ATTR_UNUSED
 #endif
 
+#if __GNUC__ > 3
+#define NOINLINE_FUNC     __attribute__((noinline))
+#else
+#define NOINLINE_FUNC
+#endif
+
 #if __GNUC__ >= 3
-#define LIKELY( expr )    __builtin_expect( !!(expr), 1 )
-#define UNLIKELY( expr )  __builtin_expect( !!(expr), 0 )
+#define LIKELY(expr)      __builtin_expect( !!(expr), 1 )
+#define UNLIKELY(expr)    __builtin_expect( !!(expr), 0 )
+#define CONSTANT_P(expr)  __builtin_constant_p( expr )
 #else
-#define LIKELY( expr )    (!!(expr))
-#define UNLIKELY( expr )  (!!(expr))
+#define LIKELY(expr)      (!!(expr))
+#define UNLIKELY(expr)    (!!(expr))
+#define CONSTANT_P(expr)  (0)
 #endif
 
 /* Gettext macros.  */
 \f
 
 /*-- src/global.c -*/
+extern int _gcry_global_any_init_done;
 int _gcry_global_is_operational (void);
 gcry_err_code_t _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr);
 void _gcry_check_heap (const void *a);
@@ -208,6 +217,8 @@ char **_gcry_strtokenize (const char *string, const char *delim);
 
 
 /*-- src/hwfeatures.c --*/
+#if defined(HAVE_CPU_ARCH_X86)
+
 #define HWF_PADLOCK_RNG         (1 << 0)
 #define HWF_PADLOCK_AES         (1 << 1)
 #define HWF_PADLOCK_SHA         (1 << 2)
@@ -224,16 +235,34 @@ char **_gcry_strtokenize (const char *string, const char *delim);
 #define HWF_INTEL_AVX           (1 << 12)
 #define HWF_INTEL_AVX2          (1 << 13)
 #define HWF_INTEL_FAST_VPGATHER (1 << 14)
+#define HWF_INTEL_RDTSC         (1 << 15)
+#define HWF_INTEL_SHAEXT        (1 << 16)
+#define HWF_INTEL_VAES_VPCLMUL  (1 << 17)
+
+#elif defined(HAVE_CPU_ARCH_ARM)
 
-#define HWF_ARM_NEON            (1 << 15)
-#define HWF_ARM_AES             (1 << 16)
-#define HWF_ARM_SHA1            (1 << 17)
-#define HWF_ARM_SHA2            (1 << 18)
-#define HWF_ARM_PMULL           (1 << 19)
+#define HWF_ARM_NEON            (1 << 0)
+#define HWF_ARM_AES             (1 << 1)
+#define HWF_ARM_SHA1            (1 << 2)
+#define HWF_ARM_SHA2            (1 << 3)
+#define HWF_ARM_PMULL           (1 << 4)
 
-#define HWF_INTEL_RDTSC         (1 << 20)
+#elif defined(HAVE_CPU_ARCH_PPC)
 
+#define HWF_PPC_VCRYPTO         (1 << 0)
+#define HWF_PPC_ARCH_3_00       (1 << 1)
+#define HWF_PPC_ARCH_2_07       (1 << 2)
+#define HWF_PPC_ARCH_3_10       (1 << 3)
 
+#elif defined(HAVE_CPU_ARCH_S390X)
+
+#define HWF_S390X_MSA           (1 << 0)
+#define HWF_S390X_MSA_4         (1 << 1)
+#define HWF_S390X_MSA_8         (1 << 2)
+#define HWF_S390X_MSA_9         (1 << 3)
+#define HWF_S390X_VX            (1 << 4)
+
+#endif
 
 gpg_err_code_t _gcry_disable_hw_feature (const char *name);
 void _gcry_detect_hw_features (void);
@@ -331,62 +360,34 @@ void __gcry_burn_stack (unsigned int bytes);
        do { __gcry_burn_stack (bytes); \
             __gcry_burn_stack_dummy (); } while(0)
 
-
-/* To avoid that a compiler optimizes certain memset calls away, these
-   macros may be used instead. */
-#define wipememory2(_ptr,_set,_len) do { \
-              volatile char *_vptr=(volatile char *)(_ptr); \
-              size_t _vlen=(_len); \
-              unsigned char _vset=(_set); \
-              fast_wipememory2(_vptr,_vset,_vlen); \
-              while(_vlen) { *_vptr=(_vset); _vptr++; _vlen--; } \
-                  } while(0)
-#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
-
-#define FASTWIPE_T u64
-#define FASTWIPE_MULT (U64_C(0x0101010101010101))
-
-/* Following architectures can handle unaligned accesses fast.  */
-#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
-    defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
-    defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS) && \
-    (defined(__i386__) || defined(__x86_64__) || \
-     defined(__powerpc__) || defined(__powerpc64__) || \
-     (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \
-     defined(__aarch64__))
-#define fast_wipememory2_unaligned_head(_ptr,_set,_len) /*do nothing*/
-typedef struct fast_wipememory_s
-{
-  FASTWIPE_T a;
-} __attribute__((packed, aligned(1), may_alias)) fast_wipememory_t;
+/* To avoid that a compiler optimizes certain memset calls away, this
+   macro may be used instead.  For constant length buffers, memory
+   wiping is inlined.  Dead store elimination of inlined memset is
+   avoided here by using assembly block after memset.  For non-constant
+   length buffers, memory is wiped through _gcry_fast_wipememory.  */
+#ifdef HAVE_GCC_ASM_VOLATILE_MEMORY
+#define fast_wipememory2_inline(_ptr,_set,_len) do { \
+             memset((_ptr), (_set), (_len)); \
+             asm volatile ("\n" :: "r" (_ptr) : "memory"); \
+           } while(0)
 #else
-#define fast_wipememory2_unaligned_head(_vptr,_vset,_vlen) do { \
-              while(UNLIKELY((size_t)(_vptr)&(sizeof(FASTWIPE_T)-1)) && _vlen) \
-                { *_vptr=(_vset); _vptr++; _vlen--; } \
-                  } while(0)
-typedef struct fast_wipememory_s
-{
-  FASTWIPE_T a;
-} fast_wipememory_t;
+#define fast_wipememory2_inline(_ptr,_set,_len) \
+           _gcry_fast_wipememory2((void *)_ptr, _set, _len)
 #endif
-
-/* fast_wipememory2 may leave tail bytes unhandled, in which case tail bytes
-   are handled by wipememory2. */
-#define fast_wipememory2(_vptr,_vset,_vlen) do { \
-              FASTWIPE_T _vset_long = _vset; \
-              fast_wipememory2_unaligned_head(_vptr,_vset,_vlen); \
-              if (_vlen < sizeof(FASTWIPE_T)) \
-                break; \
-              _vset_long *= FASTWIPE_MULT; \
-              do { \
-                volatile fast_wipememory_t *_vptr_long = \
-                  (volatile void *)_vptr; \
-                _vptr_long->a = _vset_long; \
-                _vlen -= sizeof(FASTWIPE_T); \
-                _vptr += sizeof(FASTWIPE_T); \
-              } while (_vlen >= sizeof(FASTWIPE_T)); \
-                  } while (0)
-
+#define wipememory2(_ptr,_set,_len) do { \
+             if (!CONSTANT_P(_len) || !CONSTANT_P(_set)) { \
+               if (CONSTANT_P(_set) && (_set) == 0) \
+                 _gcry_fast_wipememory((void *)(_ptr), (_len)); \
+               else \
+                 _gcry_fast_wipememory2((void *)(_ptr), (_set), (_len)); \
+             } else { \
+               fast_wipememory2_inline((void *)(_ptr), (_set), (_len)); \
+             } \
+           } while(0)
+#define wipememory(_ptr,_len) wipememory2((_ptr),0,(_len))
+
+void _gcry_fast_wipememory(void *ptr, size_t len);
+void _gcry_fast_wipememory2(void *ptr, int set, size_t len);
 
 /* Digit predicates.  */
 
@@ -422,17 +423,19 @@ gpg_err_code_t _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
 
 /*-- fips.c --*/
 
-void _gcry_initialize_fips_mode (int force);
-
-int _gcry_fips_mode (void);
-#define fips_mode() _gcry_fips_mode ()
+extern int _gcry_no_fips_mode_required;
 
-int _gcry_enforced_fips_mode (void);
+void _gcry_initialize_fips_mode (int force);
+int _gcry_fips_to_activate (void);
 
-void _gcry_set_enforced_fips_mode (void);
+/* This macro returns true if fips mode is enabled.  This is
+   independent of the fips required finite state machine and only used
+   to enable fips specific code.
 
-void _gcry_inactivate_fips_mode (const char *text);
-int _gcry_is_fips_mode_inactive (void);
+   No locking is required because we have the requirement that this
+   variable is only initialized once with no other threads
+   existing.  */
+#define fips_mode() (!_gcry_no_fips_mode_required)
 
 
 void _gcry_fips_signal_error (const char *srcfile,
@@ -452,8 +455,17 @@ void _gcry_fips_signal_error (const char *srcfile,
            _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 1, (a))
 #endif
 
+int _gcry_fips_indicator_cipher (va_list arg_ptr);
+int _gcry_fips_indicator_kdf (va_list arg_ptr);
+
 int _gcry_fips_is_operational (void);
-#define fips_is_operational()   (_gcry_global_is_operational ())
+
+/* Return true if the library is in the operational state.  */
+#define fips_is_operational()   \
+        (!_gcry_global_any_init_done ? \
+                _gcry_global_is_operational() : \
+                (!fips_mode () || _gcry_global_is_operational ()))
+
 #define fips_not_operational()  (GPG_ERR_NOT_OPERATIONAL)
 
 int _gcry_fips_test_operational (void);
index a69618c..08977d3 100644 (file)
@@ -109,7 +109,22 @@ const char *_gcry_pk_get_curve (gcry_sexp_t key, int iterator,
 gcry_sexp_t _gcry_pk_get_param (int algo, const char *name);
 gpg_err_code_t _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp,
                                       int mode, gcry_ctx_t ctx);
-
+unsigned int _gcry_ecc_get_algo_keylen (int algo);
+gpg_error_t _gcry_ecc_mul_point (int algo, unsigned char *result,
+                                 const unsigned char *scalar,
+                                 const unsigned char *point);
+gcry_err_code_t _gcry_pk_sign_md (gcry_sexp_t *r_sig, const char *tmpl,
+                                  gcry_md_hd_t hd, gcry_sexp_t s_skey,
+                                  gcry_ctx_t ctx);
+gcry_err_code_t _gcry_pk_verify_md (gcry_sexp_t s_sig, const char *tmpl,
+                                    gcry_md_hd_t hd, gcry_sexp_t s_pkey,
+                                    gcry_ctx_t ctx);
+gpg_err_code_t _gcry_pk_random_override_new (gcry_ctx_t *r_ctx,
+                                             const unsigned char *p,
+                                             size_t len);
+gpg_err_code_t _gcry_pk_get_random_override (gcry_ctx_t ctx,
+                                             const unsigned char **r_p,
+                                             size_t *r_len);
 \f
 gpg_err_code_t _gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags);
 void _gcry_md_close (gcry_md_hd_t hd);
@@ -124,6 +139,10 @@ gpg_err_code_t _gcry_md_extract (gcry_md_hd_t hd, int algo, void *buffer,
                                  size_t length);
 void _gcry_md_hash_buffer (int algo, void *digest,
                            const void *buffer, size_t length);
+gpg_err_code_t _gcry_md_hash_buffers_extract (int algo, unsigned int flags,
+                                              void *digest, int digestlen,
+                                              const gcry_buffer_t *iov,
+                                              int iovcnt);
 gpg_err_code_t _gcry_md_hash_buffers (int algo, unsigned int flags,
                                       void *digest,
                                       const gcry_buffer_t *iov, int iovcnt);
@@ -188,6 +207,18 @@ gpg_err_code_t _gcry_kdf_derive (const void *passphrase, size_t passphraselen,
                                  unsigned long iterations,
                                  size_t keysize, void *keybuffer);
 
+gpg_err_code_t _gcry_kdf_open (gcry_kdf_hd_t *hd, int algo, int subalgo,
+                               const unsigned long *param,
+                               unsigned int paramlen,
+                               const void *passphrase, size_t passphraselen,
+                               const void *salt, size_t saltlen,
+                               const void *key, size_t keylen,
+                               const void *ad, size_t adlen);
+gcry_error_t _gcry_kdf_compute (gcry_kdf_hd_t h,
+                                const struct gcry_kdf_thread_ops *ops);
+gpg_err_code_t _gcry_kdf_final (gcry_kdf_hd_t h, size_t resultlen, void *result);
+void _gcry_kdf_close (gcry_kdf_hd_t h);
+
 \f
 gpg_err_code_t _gcry_prime_generate (gcry_mpi_t *prime,
                                      unsigned int prime_bits,
@@ -362,7 +393,7 @@ gcry_mpi_t _gcry_mpi_copy (const gcry_mpi_t a);
 void _gcry_mpi_snatch (gcry_mpi_t w, gcry_mpi_t u);
 gcry_mpi_t _gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
 gcry_mpi_t _gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
-gcry_err_code_t _gcry_mpi_get_ui (gcry_mpi_t w, ulong *u);
+gcry_err_code_t _gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u);
 void _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
 int _gcry_mpi_is_neg (gcry_mpi_t a);
 void _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u);
@@ -417,6 +448,7 @@ gcry_mpi_point_t _gcry_mpi_ec_get_point (const char *name,
                                         gcry_ctx_t ctx, int copy);
 int _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_point_t point,
                              mpi_ec_t ctx);
+void _gcry_mpi_ec_point_resize (gcry_mpi_point_t p, mpi_ec_t ctx);
 void _gcry_mpi_ec_dup (gcry_mpi_point_t w, gcry_mpi_point_t u, gcry_ctx_t ctx);
 void _gcry_mpi_ec_add (gcry_mpi_point_t w,
                        gcry_mpi_point_t u, gcry_mpi_point_t v, mpi_ec_t ctx);
@@ -465,7 +497,7 @@ int _gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
 #define mpi_snatch( w, u)      _gcry_mpi_snatch( (w), (u) )
 #define mpi_set( w, u)         _gcry_mpi_set( (w), (u) )
 #define mpi_set_ui( w, u)      _gcry_mpi_set_ui( (w), (u) )
-#define mpi_get_ui(a,b)        _gcry_mpi_get_ui( (a), (b) )
+#define mpi_get_ui(w,u)        _gcry_mpi_get_ui( (w), (u) )
 #define mpi_swap(a,b)          _gcry_mpi_swap ((a),(b))
 #define mpi_abs( w )           _gcry_mpi_abs( (w) )
 #define mpi_neg( w, u)         _gcry_mpi_neg( (w), (u) )
@@ -509,6 +541,7 @@ int _gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag);
 #define mpi_point_set(p,x,y,z)        _gcry_mpi_point_set((p),(x),(y),(z))
 #define mpi_point_snatch_set(p,x,y,z) _gcry_mpi_point_snatch_set((p),(x), \
                                                                  (y),(z))
+#define mpi_point_resize(p,ctx) _gcry_mpi_ec_point_resize (p, ctx)
 
 #define mpi_get_nbits(a)       _gcry_mpi_get_nbits ((a))
 #define mpi_test_bit(a,b)      _gcry_mpi_test_bit ((a),(b))
index 75c49a0..b136412 100644 (file)
@@ -1,6 +1,7 @@
 /* gcrypt.h -  GNU Cryptographic Library Interface              -*- c -*-
- * Copyright (C) 1998-2017 Free Software Foundation, Inc.
- * Copyright (C) 2012-2017 g10 Code GmbH
+ * Copyright (C) 2012-2022 g10 Code GmbH
+ * Copyright (C) 2013-2022 Jussi Kivilinna
+ * Copyright (C) 1998-2018 Free Software Foundation, Inc.
  *
  * This file is part of Libgcrypt.
  *
 #include <sys/types.h>
 
 #if defined _WIN32 || defined __WIN32__
-# include <winsock2.h>
-# include <ws2tcpip.h>
-# include <time.h>
 # ifndef __GNUC__
   typedef long ssize_t;
   typedef int  pid_t;
 # endif /*!__GNUC__*/
-#else
-# include <sys/socket.h>
-# include <sys/time.h>
-#@INSERT_SYS_SELECT_H@
-#endif /*!_WIN32*/
-
-@FALLBACK_SOCKLEN_T@
+#endif /*_WIN32*/
 
 /* This is required for error code compatibility. */
 #define _GCRY_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_GCRYPT
@@ -127,7 +119,7 @@ extern "C" {
 #ifdef _GCRYPT_IN_LIBGCRYPT
 #define _GCRY_ATTR_INTERNAL
 #else
-#define _GCRY_ATTR_INTERNAL    _GCRY_GCC_ATTR_DEPRECATED
+#define _GCRY_ATTR_INTERNAL     _GCRY_GCC_ATTR_DEPRECATED
 #endif
 
 /* Wrappers for the libgpg-error library.  */
@@ -332,7 +324,13 @@ enum gcry_ctl_cmds
     GCRYCTL_DRBG_REINIT = 74,
     GCRYCTL_SET_TAGLEN = 75,
     GCRYCTL_GET_TAGLEN = 76,
-    GCRYCTL_REINIT_SYSCALL_CLAMP = 77
+    GCRYCTL_REINIT_SYSCALL_CLAMP = 77,
+    GCRYCTL_AUTO_EXPAND_SECMEM = 78,
+    GCRYCTL_SET_ALLOW_WEAK_KEY = 79,
+    GCRYCTL_SET_DECRYPTION_TAG = 80,
+    GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER = 81,
+    GCRYCTL_FIPS_SERVICE_INDICATOR_KDF = 82,
+    GCRYCTL_NO_FIPS_MODE = 83
   };
 
 /* Perform various operations defined by CMD. */
@@ -386,7 +384,7 @@ gcry_error_t gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff,
 /* Like gcry_sexp_build, but uses an array instead of variable
    function arguments.  */
 gcry_error_t gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
-                                   const char *format, void **arg_list);
+                                    const char *format, void **arg_list);
 
 /* Release the S-expression object SEXP */
 void gcry_sexp_release (gcry_sexp_t sexp);
@@ -587,6 +585,9 @@ gcry_mpi_t gcry_mpi_set (gcry_mpi_t w, const gcry_mpi_t u);
 /* Store the unsigned integer value U in W. */
 gcry_mpi_t gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u);
 
+/* Store U as an unsigned int at W or return GPG_ERR_ERANGE. */
+gpg_error_t gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u);
+
 /* Swap the values of A and B. */
 void gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b);
 
@@ -840,6 +841,7 @@ gcry_mpi_t _gcry_mpi_get_const (int no);
 #define mpi_snatch( w, u)      gcry_mpi_snatch( (w), (u) )
 #define mpi_set( w, u)         gcry_mpi_set( (w), (u) )
 #define mpi_set_ui( w, u)      gcry_mpi_set_ui( (w), (u) )
+#define mpi_get_ui( w, u)      gcry_mpi_get_ui( (w), (u) )
 #define mpi_abs( w )           gcry_mpi_abs( (w) )
 #define mpi_neg( w, u)         gcry_mpi_neg( (w), (u) )
 #define mpi_cmp( u, v )        gcry_mpi_cmp( (u), (v) )
@@ -939,7 +941,9 @@ enum gcry_cipher_algos
     GCRY_CIPHER_SALSA20     = 313,
     GCRY_CIPHER_SALSA20R12  = 314,
     GCRY_CIPHER_GOST28147   = 315,
-    GCRY_CIPHER_CHACHA20    = 316
+    GCRY_CIPHER_CHACHA20    = 316,
+    GCRY_CIPHER_GOST28147_MESH   = 317, /* With CryptoPro key meshing.  */
+    GCRY_CIPHER_SM4         = 318
   };
 
 /* The Rijndael algorithm is basically AES, so provide some macros. */
@@ -966,7 +970,10 @@ enum gcry_cipher_modes
     GCRY_CIPHER_MODE_POLY1305 = 10,  /* Poly1305 based AEAD mode. */
     GCRY_CIPHER_MODE_OCB      = 11,  /* OCB3 mode.  */
     GCRY_CIPHER_MODE_CFB8     = 12,  /* Cipher feedback (8 bit mode). */
-    GCRY_CIPHER_MODE_XTS      = 13  /* XTS mode.  */
+    GCRY_CIPHER_MODE_XTS      = 13,  /* XTS mode.  */
+    GCRY_CIPHER_MODE_EAX      = 14,  /* EAX mode.  */
+    GCRY_CIPHER_MODE_SIV      = 15,  /* SIV mode.  */
+    GCRY_CIPHER_MODE_GCM_SIV  = 16   /* GCM-SIV mode.  */
   };
 
 /* Flags used with the open function. */
@@ -975,7 +982,8 @@ enum gcry_cipher_flags
     GCRY_CIPHER_SECURE      = 1,  /* Allocate in secure memory. */
     GCRY_CIPHER_ENABLE_SYNC = 2,  /* Enable CFB sync mode. */
     GCRY_CIPHER_CBC_CTS     = 4,  /* Enable CBC cipher text stealing (CTS). */
-    GCRY_CIPHER_CBC_MAC     = 8   /* Enable CBC message auth. code (MAC). */
+    GCRY_CIPHER_CBC_MAC     = 8,  /* Enable CBC message auth. code (MAC).  */
+    GCRY_CIPHER_EXTENDED    = 16  /* Enable extended AES-WRAP.  */
   };
 
 /* GCM works only with blocks of 128 bits */
@@ -990,6 +998,9 @@ enum gcry_cipher_flags
 /* XTS works only with blocks of 128 bits.  */
 #define GCRY_XTS_BLOCK_LEN  (128 / 8)
 
+/* SIV and GCM-SIV works only with blocks of 128 bits */
+#define GCRY_SIV_BLOCK_LEN  (128 / 8)
+
 /* Create a handle for algorithm ALGO to be used in MODE.  FLAGS may
    be given as an bitwise OR of the gcry_cipher_flags values. */
 gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle,
@@ -1092,6 +1103,11 @@ size_t gcry_cipher_get_algo_blklen (int algo);
 #define gcry_cipher_test_algo(a) \
             gcry_cipher_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL )
 
+/* Setup tag for decryption (for SIV and GCM-SIV mode). */
+#define gcry_cipher_set_decryption_tag(a, tag, taglen) \
+            gcry_cipher_ctl ((a), GCRYCTL_SET_DECRYPTION_TAG, \
+                             (void *)(tag), (taglen))
+
 \f
 /************************************
  *                                  *
@@ -1191,6 +1207,28 @@ gcry_sexp_t gcry_pk_get_param (int algo, const char *name);
 /* Return an S-expression representing the context CTX.  */
 gcry_error_t gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp,
                                    int mode, gcry_ctx_t ctx);
+\f
+/************************************
+ *                                  *
+ *    Modern ECC Functions          *
+ *                                  *
+ ************************************/
+
+/* The curves we support.  */
+enum gcry_ecc_curves
+  {
+    GCRY_ECC_CURVE25519 = 1,
+    GCRY_ECC_CURVE448   = 2
+  };
+
+/* Get the length of point to prepare buffer for the result.  */
+unsigned int gcry_ecc_get_algo_keylen (int curveid);
+
+/* Convenience function to compute scalar multiplication of the
+ * Montgomery form of curve.  */
+gpg_error_t gcry_ecc_mul_point (int curveid, unsigned char *result,
+                                const unsigned char *scalar,
+                                const unsigned char *point);
 
 \f
 
@@ -1240,7 +1278,10 @@ enum gcry_md_algos
     GCRY_MD_BLAKE2S_256   = 322,
     GCRY_MD_BLAKE2S_224   = 323,
     GCRY_MD_BLAKE2S_160   = 324,
-    GCRY_MD_BLAKE2S_128   = 325
+    GCRY_MD_BLAKE2S_128   = 325,
+    GCRY_MD_SM3           = 326,
+    GCRY_MD_SHA512_256    = 327,
+    GCRY_MD_SHA512_224    = 328
   };
 
 /* Flags used with the open function.  */
@@ -1407,6 +1448,7 @@ typedef struct gcry_mac_handle *gcry_mac_hd_t;
 enum gcry_mac_algos
   {
     GCRY_MAC_NONE               = 0,
+    GCRY_MAC_GOST28147_IMIT     = 1,
 
     GCRY_MAC_HMAC_SHA256        = 101,
     GCRY_MAC_HMAC_SHA224        = 102,
@@ -1426,6 +1468,18 @@ enum gcry_mac_algos
     GCRY_MAC_HMAC_SHA3_256      = 116,
     GCRY_MAC_HMAC_SHA3_384      = 117,
     GCRY_MAC_HMAC_SHA3_512      = 118,
+    GCRY_MAC_HMAC_GOSTR3411_CP  = 119,
+    GCRY_MAC_HMAC_BLAKE2B_512   = 120,
+    GCRY_MAC_HMAC_BLAKE2B_384   = 121,
+    GCRY_MAC_HMAC_BLAKE2B_256   = 122,
+    GCRY_MAC_HMAC_BLAKE2B_160   = 123,
+    GCRY_MAC_HMAC_BLAKE2S_256   = 124,
+    GCRY_MAC_HMAC_BLAKE2S_224   = 125,
+    GCRY_MAC_HMAC_BLAKE2S_160   = 126,
+    GCRY_MAC_HMAC_BLAKE2S_128   = 127,
+    GCRY_MAC_HMAC_SM3           = 128,
+    GCRY_MAC_HMAC_SHA512_256    = 129,
+    GCRY_MAC_HMAC_SHA512_224    = 130,
 
     GCRY_MAC_CMAC_AES           = 201,
     GCRY_MAC_CMAC_3DES          = 202,
@@ -1438,6 +1492,7 @@ enum gcry_mac_algos
     GCRY_MAC_CMAC_RFC2268       = 209,
     GCRY_MAC_CMAC_IDEA          = 210,
     GCRY_MAC_CMAC_GOST28147     = 211,
+    GCRY_MAC_CMAC_SM4           = 212,
 
     GCRY_MAC_GMAC_AES           = 401,
     GCRY_MAC_GMAC_CAMELLIA      = 402,
@@ -1537,7 +1592,16 @@ enum gcry_kdf_algos
     GCRY_KDF_ITERSALTED_S2K = 19,
     GCRY_KDF_PBKDF1 = 33,
     GCRY_KDF_PBKDF2 = 34,
-    GCRY_KDF_SCRYPT = 48
+    GCRY_KDF_SCRYPT = 48,
+    GCRY_KDF_ARGON2   = 64,
+    GCRY_KDF_BALLOON  = 65
+  };
+
+enum gcry_kdf_subalgo_argon2
+  {
+    GCRY_KDF_ARGON2D  = 0,
+    GCRY_KDF_ARGON2I  = 1,
+    GCRY_KDF_ARGON2ID = 2
   };
 
 /* Derive a key from a passphrase.  */
@@ -1547,8 +1611,33 @@ gpg_error_t gcry_kdf_derive (const void *passphrase, size_t passphraselen,
                              unsigned long iterations,
                              size_t keysize, void *keybuffer);
 
+/* Another API to derive a key from a passphrase.  */
+typedef struct gcry_kdf_handle *gcry_kdf_hd_t;
 
+typedef void (*gcry_kdf_job_fn_t) (void *priv);
+typedef int (*gcry_kdf_dispatch_job_fn_t) (void *jobs_context,
+                                           gcry_kdf_job_fn_t job_fn,
+                                           void *job_priv);
+typedef int (*gcry_kdf_wait_all_jobs_fn_t) (void *jobs_context);
 
+/* Exposed structure for KDF computation to decouple thread functionality.  */
+typedef struct gcry_kdf_thread_ops
+{
+  void *jobs_context;
+  gcry_kdf_dispatch_job_fn_t dispatch_job;
+  gcry_kdf_wait_all_jobs_fn_t wait_all_jobs;
+} gcry_kdf_thread_ops_t;
+
+gcry_error_t gcry_kdf_open (gcry_kdf_hd_t *hd, int algo, int subalgo,
+                            const unsigned long *param, unsigned int paramlen,
+                            const void *passphrase, size_t passphraselen,
+                            const void *salt, size_t saltlen,
+                            const void *key, size_t keylen,
+                            const void *ad, size_t adlen);
+gcry_error_t gcry_kdf_compute (gcry_kdf_hd_t h,
+                               const gcry_kdf_thread_ops_t *ops);
+gcry_error_t gcry_kdf_final (gcry_kdf_hd_t h, size_t resultlen, void *result);
+void gcry_kdf_close (gcry_kdf_hd_t h);
 \f
 /************************************
  *                                  *
@@ -1599,8 +1688,7 @@ void *gcry_random_bytes (size_t nbytes, enum gcry_random_level level)
                          _GCRY_GCC_ATTR_MALLOC;
 
 /* Return NBYTES of allocated random using a random numbers of quality
-   LEVEL.  The random numbers are created returned in "secure"
-   memory. */
+   LEVEL.  The random is returned in "secure" memory.  */
 void *gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level)
                                 _GCRY_GCC_ATTR_MALLOC;
 
@@ -1783,6 +1871,32 @@ int gcry_is_secure (const void *a) _GCRY_GCC_ATTR_PURE;
 /* Return true if Libgcrypt is in FIPS mode.  */
 #define gcry_fips_mode_active()  !!gcry_control (GCRYCTL_FIPS_MODE_P, 0)
 
+/* Variant of gcry_pk_sign which takes as additional parameter a HD
+ * handle for hash and an optional context.  The hash algorithm used by the
+ * handle needs to be enabled and input needs to be supplied beforehand.
+ * DATA-TMPL specifies a template to compose an S-expression to be signed.
+ * A template should include '(hash %s %b)' or '(hash ALGONAME %b)'.
+ * For the former case, '%s' is substituted by the string of algorithm
+ * of gcry_md_get_algo (HD) and when gcry_md_read is called, ALGO=0 is
+ * used internally.  For the latter case, hash algorithm by ALGONAME
+ * is used when gcry_md_read is called internally.
+ * The hash handle must not yet been finalized; the function
+ * takes a copy of the state and does a finalize on the copy.  This
+ * function shall be used if a policy requires that hashing and signing
+ * is done by the same function.  CTX is currently not used and should
+ * be passed as NULL.  */
+gcry_error_t gcry_pk_hash_sign (gcry_sexp_t *result,
+                                const char *data_tmpl, gcry_sexp_t skey,
+                                gcry_md_hd_t hd, gcry_ctx_t ctx);
+
+/* Variant of gcry_pk_verify which takes as additional parameter a HD
+ * handle for hash and an optional context.  Similar to gcry_pk_hash_sign.  */
+gcry_error_t gcry_pk_hash_verify (gcry_sexp_t sigval,
+                                  const char *data_tmpl, gcry_sexp_t pkey,
+                                  gcry_md_hd_t hd, gcry_ctx_t ctx);
+
+gcry_error_t gcry_pk_random_override_new (gcry_ctx_t *r_ctx,
+                                          const unsigned char *p, size_t len);
 
 #if 0 /* (Keep Emacsens' auto-indent happy.) */
 {
diff --git a/src/gen-note-integrity.sh b/src/gen-note-integrity.sh
new file mode 100755 (executable)
index 0000000..50071bf
--- /dev/null
@@ -0,0 +1,123 @@
+#! /bin/sh
+
+#
+# gen-note-integrity.sh - Build tool to generate hmac hash section
+#
+# Copyright (C) 2022  g10 Code GmbH
+#
+# 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 <https://www.gnu.org/licenses/>.
+#
+
+set -e
+
+#
+# Following variables should be defined to invoke this script
+#
+#   READELF
+#   AWK
+#   ECHO_N
+#
+
+######## Emit ElfN_Nhdr for note.fdo.integrity ########
+
+NOTE_NAME="FDO"
+
+# n_namesz = 4 including NUL
+printf '%b' '\004'
+printf '%b' '\000'
+printf '%b' '\000'
+printf '%b' '\000'
+
+# n_descsz = 32
+printf '%b' '\040'
+printf '%b' '\000'
+printf '%b' '\000'
+printf '%b' '\000'
+
+# n_type: NT_FDO_INTEGRITY=0xCAFE2A8E
+printf '%b' '\312'
+printf '%b' '\376'
+printf '%b' '\052'
+printf '%b' '\216'
+
+# the name
+echo $ECHO_N $NOTE_NAME
+printf '%b' '\000'
+
+# Here comes the alignment.  As the size of name is 4, it's none.
+# NO PADDING HERE.
+
+######## Rest is to generate hmac hash ########
+
+AWK_VERSION_OUTPUT=$($AWK 'BEGIN { print PROCINFO["version"] }')
+if test -n "$AWK_VERSION_OUTPUT"; then
+    # It's GNU awk, which supports PROCINFO.
+    AWK_OPTION=--non-decimal-data
+fi
+
+FILE=.libs/libgcrypt.so
+
+#
+# Fixup the ELF header to clean up section information
+#
+BYTE002=$(printf '%b' '\002')
+CLASS_BYTE=$(dd ibs=1 skip=4 count=1 if=$FILE status=none)
+if test "$CLASS_BYTE" = "$BYTE002"; then
+    CLASS=64
+    HEADER_SIZE=64
+else
+    CLASS=32
+    HEADER_SIZE=52
+fi
+
+if test $CLASS -eq 64; then
+    dd ibs=1         count=40 if=$FILE     status=none
+    dd ibs=1         count=8  if=/dev/zero status=none
+    dd ibs=1 skip=48 count=10 if=$FILE     status=none
+    dd ibs=1         count=6  if=/dev/zero status=none
+else
+    dd ibs=1         count=32 if=$FILE     status=none
+    dd ibs=1         count=4  if=/dev/zero status=none
+    dd ibs=1 skip=36 count=10 if=$FILE     status=none
+    dd ibs=1         count=6  if=/dev/zero status=none
+fi > header-fixed.bin
+
+#
+# Compute the end of segments, and emit the COUNT to read
+# (For each segment in program headers, calculate the offset
+#  and select the maximum)
+#
+# This require computation in hexadecimal, and GNU awk needs
+# --non-decimal-data option
+#
+COUNT=$($READELF --wide --program-headers $FILE | \
+         $AWK $AWK_OPTION \
+"BEGIN { max_offset=0 }
+/^\$/ { if (program_headers_start) program_headers_end=1 }
+(program_headers_start && !program_headers_end) { offset = \$2 + \$5 }
+(max_offset < offset) { max_offset = offset }
+/^  Type/ { program_headers_start=1 }
+END { print max_offset- $HEADER_SIZE }")
+
+#
+# Feed the header fixed and all segments to HMAC256
+# to generate hmac hash of the FILE
+#
+(cat header-fixed.bin; \
+ dd ibs=1 skip=$HEADER_SIZE count=$COUNT if=$FILE status=none) \
+ | ./hmac256 --stdkey --binary
+
+rm -f header-fixed.bin
index cd3d9d9..7cf40e4 100644 (file)
@@ -54,7 +54,7 @@ static unsigned int debug_flags;
 static int force_fips_mode;
 
 /* Controlled by global_init().  */
-static int any_init_done;
+int _gcry_global_any_init_done;
 
 /*
  * Functions called before and after blocking syscalls.
@@ -91,9 +91,9 @@ global_init (void)
 {
   gcry_error_t err = 0;
 
-  if (any_init_done)
+  if (_gcry_global_any_init_done)
     return;
-  any_init_done = 1;
+  _gcry_global_any_init_done = 1;
 
   /* Tell the random module that we have seen an init call.  */
   _gcry_set_preferred_rng_type (0);
@@ -140,6 +140,25 @@ global_init (void)
   BUG ();
 }
 
+#ifdef ENABLE_HMAC_BINARY_CHECK
+# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7 )
+# define GCC_ATTR_CONSTRUCTOR  __attribute__ ((__constructor__))
+
+static void GCC_ATTR_CONSTRUCTOR
+_gcry_global_constructor (void)
+{
+  force_fips_mode = _gcry_fips_to_activate ();
+  if (force_fips_mode)
+    {
+      no_secure_memory = 1;
+      global_init ();
+      _gcry_fips_run_selftests (0);
+      _gcry_random_close_fds ();
+      no_secure_memory = 0;
+    }
+}
+# endif
+#endif /* ENABLE_HMAC_BINARY_CHECK */
 
 /* This function is called by the macro fips_is_operational and makes
    sure that the minimal initialization has been done.  This is far
@@ -161,7 +180,7 @@ global_init (void)
 int
 _gcry_global_is_operational (void)
 {
-  if (!any_init_done)
+  if (!_gcry_global_any_init_done)
     {
 #ifdef HAVE_SYSLOG
       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
@@ -261,7 +280,8 @@ _gcry_check_version (const char *req_version)
     /* Compare version numbers.  */
     if ( my_major > rq_major
        || (my_major == rq_major && my_minor > rq_minor)
-       || (my_major == rq_major && my_minor == rq_minor                                                         && my_micro > rq_micro)
+       || (my_major == rq_major && my_minor == rq_minor
+           && my_micro > rq_micro)
        || (my_major == rq_major && my_minor == rq_minor
                                  && my_micro == rq_micro))
       {
@@ -316,8 +336,11 @@ print_config (const char *what, gpgrt_stream_t fp)
 #if USE_RNDEGD
                      "egd:"
 #endif
-#if USE_RNDLINUX
-                     "linux:"
+#if USE_RNDGETENTROPY
+                     "getentropy:"
+#endif
+#if USE_RNDOLDLINUX
+                     "oldlinux:"
 #endif
 #if USE_RNDUNIX
                      "unix:"
@@ -368,10 +391,19 @@ print_config (const char *what, gpgrt_stream_t fp)
     {
       /* We use y/n instead of 1/0 for the stupid reason that
        * Emacsen's compile error parser would accidentally flag that
-       * line when printed during "make check" as an error.  */
-      gpgrt_fprintf (fp, "fips-mode:%c:%c:\n",
+       * line when printed during "make check" as an error.  The
+       * second field is obsolete and thus empty (used to be used for
+       * a so-called enforced-fips-mode).  The third field has an
+       * option static string describing the module versions; this is
+       * an optional configure option.  */
+      gpgrt_fprintf (fp, "fips-mode:%c::%s:\n",
                      fips_mode ()? 'y':'n',
-                     _gcry_enforced_fips_mode ()? 'y':'n' );
+#ifdef FIPS_MODULE_VERSION
+                     fips_mode () ? FIPS_MODULE_VERSION : ""
+#else
+                     ""
+#endif /* FIPS_MODULE_VERSION */
+                     );
     }
 
   if (!what || !strcmp (what, "rng-type"))
@@ -391,6 +423,21 @@ print_config (const char *what, gpgrt_stream_t fp)
       jver = _gcry_rndjent_get_version (&active);
       gpgrt_fprintf (fp, "rng-type:%s:%d:%u:%d:\n", s, i, jver, active);
     }
+
+  if (!what || !strcmp (what, "compliance"))
+    {
+      /* Right now we have no certification for 1.9 so we return an
+       * empty string.  As soon as this version has been approved for
+       * VS-Nfd we will put the string "de-vs" into the second
+       * field. If further specifications are required they are added
+       * as parameters to that field.  Other certifications will go
+       * into field 3 and so on.
+       *  field 1: keyword "compliance"
+       *  field 2: German VS-Nfd is marked with "de-vs"
+       *  field 3: reserved for FIPS.
+       */
+      gpgrt_fprintf (fp, "compliance:%s::\n", "");
+    }
 }
 
 
@@ -418,6 +465,13 @@ _gcry_get_config (int mode, const char *what)
     return NULL;
 
   print_config (what, fp);
+
+  if (!what)
+    {
+      /* Null-terminate bulk output. */
+      gpgrt_fwrite ("\0", 1, 1, fp);
+    }
+
   if (gpgrt_ferror (fp))
     {
       save_errno = errno;
@@ -453,6 +507,11 @@ _gcry_get_config (int mode, const char *what)
 
 \f
 
+#if _GCRY_GCC_VERSION >= 40200
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wswitch"
+#endif
+
 /* Command dispatcher function, acting as general control
    function.  */
 gcry_err_code_t
@@ -498,7 +557,9 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
 
     case GCRYCTL_DISABLE_SECMEM:
       global_init ();
-      no_secure_memory = 1;
+      /* When FIPS enabled, no effect at all.  */
+      if (!fips_mode ())
+        no_secure_memory = 1;
       break;
 
     case GCRYCTL_INIT_SECMEM:
@@ -531,7 +592,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
                               & ~GCRY_SECMEM_FLAG_SUSPEND_WARNING));
       break;
 
-    case 78: /* GCRYCTL_AUTO_EXPAND_SECMEM (backport from 1.9) */
+    case GCRYCTL_AUTO_EXPAND_SECMEM:
       _gcry_secmem_set_auto_expand (va_arg (arg_ptr, unsigned int));
       break;
 
@@ -570,7 +631,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       break;
 
     case GCRYCTL_ANY_INITIALIZATION_P:
-      if (any_init_done)
+      if (_gcry_global_any_init_done)
        rc = GPG_ERR_GENERAL;
       break;
 
@@ -624,16 +685,11 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       break;
 
     case GCRYCTL_SET_RANDOM_DAEMON_SOCKET:
-      _gcry_set_preferred_rng_type (0);
-      _gcry_set_random_daemon_socket (va_arg (arg_ptr, const char *));
+      rc = GPG_ERR_NOT_SUPPORTED;
       break;
 
     case GCRYCTL_USE_RANDOM_DAEMON:
-      /* We need to do make sure that the random pool is really
-         initialized so that the poll function is not a NOP. */
-      _gcry_set_preferred_rng_type (0);
-      _gcry_random_initialize (1);
-      _gcry_use_random_daemon (!! va_arg (arg_ptr, int));
+      rc = GPG_ERR_NOT_SUPPORTED;
       break;
 
     case GCRYCTL_CLOSE_RANDOM_DEVICE:
@@ -670,9 +726,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       break;
 
     case GCRYCTL_FIPS_MODE_P:
-      if (fips_mode ()
-          && !_gcry_is_fips_mode_inactive ()
-          && !no_secure_memory)
+      if (fips_mode ())
        rc = GPG_ERR_GENERAL; /* Used as TRUE value */
       break;
 
@@ -682,7 +736,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
          selftest is triggered.  It is not possible to put the libraty
          into fips mode after having passed the initialization. */
       _gcry_set_preferred_rng_type (0);
-      if (!any_init_done)
+      if (!_gcry_global_any_init_done)
         {
           /* Not yet initialized at all.  Set a flag so that we are put
              into fips mode during initialization.  */
@@ -700,6 +754,27 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       }
       break;
 
+    case GCRYCTL_NO_FIPS_MODE:
+      /* Performing this command puts the library into non-fips mode,
+         even if system has fips setting.  It is not possible to put
+         the libraty into non-fips mode after having passed the
+         initialization. */
+      _gcry_set_preferred_rng_type (0);
+      if (!_gcry_global_any_init_done)
+        {
+          /* Not yet initialized at all.  Set a flag so that we are put
+             into non-fips mode during initialization.  */
+          force_fips_mode = 0;
+        }
+      else if (!init_finished)
+        {
+          /* Already initialized.  */
+          _gcry_no_fips_mode_required = 1;
+        }
+      else
+       rc = GPG_ERR_GENERAL;
+      break;
+
     case GCRYCTL_SELFTEST:
       /* Run a selftest.  This works in fips mode as well as in
          standard mode.  In contrast to the power-up tests, we use an
@@ -709,10 +784,19 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       rc = _gcry_fips_run_selftests (1);
       break;
 
-#if _GCRY_GCC_VERSION >= 40600
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wswitch"
-#endif
+    case GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER:
+      /* Get FIPS Service Indicator for a given symmetric algorithm and
+       * optional mode. Returns GPG_ERR_NO_ERROR if algorithm is allowed or
+       * GPG_ERR_NOT_SUPPORTED otherwise */
+      rc = _gcry_fips_indicator_cipher (arg_ptr);
+      break;
+
+    case GCRYCTL_FIPS_SERVICE_INDICATOR_KDF:
+      /* Get FIPS Service Indicator for a given KDF. Returns GPG_ERR_NO_ERROR
+       * if algorithm is allowed or GPG_ERR_NOT_SUPPORTED otherwise */
+      rc = _gcry_fips_indicator_kdf (arg_ptr);
+      break;
+
     case PRIV_CTL_INIT_EXTRNG_TEST:  /* Init external random test.  */
       rc = GPG_ERR_NOT_SUPPORTED;
       break;
@@ -737,9 +821,6 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
     case PRIV_CTL_DUMP_SECMEM_STATS:
       _gcry_secmem_dump_stats (1);
       break;
-#if _GCRY_GCC_VERSION >= 40600
-# pragma GCC diagnostic pop
-#endif
 
     case GCRYCTL_DISABLE_HWF:
       {
@@ -749,14 +830,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       break;
 
     case GCRYCTL_SET_ENFORCED_FIPS_FLAG:
-      if (!any_init_done)
-        {
-          /* Not yet initialized at all.  Set the enforced fips mode flag */
-          _gcry_set_preferred_rng_type (0);
-          _gcry_set_enforced_fips_mode ();
-        }
-      else
-        rc = GPG_ERR_GENERAL;
+      /* Obsolete - ignore  */
       break;
 
     case GCRYCTL_SET_PREFERRED_RNG_TYPE:
@@ -773,7 +847,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       {
         int *ip = va_arg (arg_ptr, int*);
         if (ip)
-          *ip = _gcry_get_rng_type (!any_init_done);
+          *ip = _gcry_get_rng_type (!_gcry_global_any_init_done);
       }
       break;
 
@@ -801,7 +875,8 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
         int npers = va_arg (arg_ptr, int);
         if (va_arg (arg_ptr, void *) || npers < 0)
           rc = GPG_ERR_INV_ARG;
-        else if (_gcry_get_rng_type (!any_init_done) != GCRY_RNG_TYPE_FIPS)
+        else if (_gcry_get_rng_type (!_gcry_global_any_init_done)
+                 != GCRY_RNG_TYPE_FIPS)
           rc = GPG_ERR_NOT_SUPPORTED;
         else
           rc = _gcry_rngdrbg_reinit (flagstr, pers, npers);
@@ -821,6 +896,9 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
   return rc;
 }
 
+#if _GCRY_GCC_VERSION >= 40200
+# pragma GCC diagnostic pop
+#endif
 
 
 /* Set custom allocation handlers.  This is in general not useful
@@ -838,10 +916,11 @@ _gcry_set_allocation_handler (gcry_handler_alloc_t new_alloc_func,
 
   if (fips_mode ())
     {
-      /* We do not want to enforce the fips mode, but merely set a
-         flag so that the application may check whether it is still in
-         fips mode.  */
-      _gcry_inactivate_fips_mode ("custom allocation handler");
+      /* In FIPS mode, we can not use custom allocation handlers because
+       * fips requires explicit zeroization and we can not guarantee that
+       * with custom free functions (and we can not do it transparently as
+       * in free we do not know the zize). */
+      return;
     }
 
   alloc_func = new_alloc_func;
@@ -882,20 +961,6 @@ _gcry_set_outofcore_handler (int (*f)(void*, size_t, unsigned int), void *value)
   outofcore_handler_value = value;
 }
 
-/* Return the no_secure_memory flag.  */
-static int
-get_no_secure_memory (void)
-{
-  if (!no_secure_memory)
-    return 0;
-  if (_gcry_enforced_fips_mode ())
-    {
-      no_secure_memory = 0;
-      return 0;
-    }
-  return no_secure_memory;
-}
-
 
 static gcry_err_code_t
 do_malloc (size_t n, unsigned int flags, void **mem)
@@ -903,7 +968,7 @@ do_malloc (size_t n, unsigned int flags, void **mem)
   gcry_err_code_t err = 0;
   void *m;
 
-  if ((flags & GCRY_ALLOC_FLAG_SECURE) && !get_no_secure_memory ())
+  if ((flags & GCRY_ALLOC_FLAG_SECURE) && !no_secure_memory)
     {
       if (alloc_secure_func)
        m = (*alloc_secure_func) (n);
@@ -962,7 +1027,7 @@ _gcry_malloc_secure (size_t n)
 int
 _gcry_is_secure (const void *a)
 {
-  if (get_no_secure_memory ())
+  if (no_secure_memory)
     return 0;
   if (is_secure_func)
     return is_secure_func (a) ;
@@ -1032,7 +1097,7 @@ _gcry_free (void *p)
   else
     _gcry_private_free (p);
 
-  if (save_errno)
+  if (save_errno && save_errno != errno)
     gpg_err_set_errno (save_errno);
 }
 
index 2d66079..899e6d1 100644 (file)
@@ -35,7 +35,7 @@
      WORDS_BIGENDIAN       Defined to 1 on big endian systems.
      inline                If defined, it should yield the keyword used
                            to inline a function.
-     HAVE_U32_TYPEDEF      Defined if the u32 type is available.
+     HAVE_TYPE_U32         Defined if the u32 type is available.
      SIZEOF_UNSIGNED_INT   Defined to the size in bytes of an unsigned int.
      SIZEOF_UNSIGNED_LONG  Defined to the size in bytes of an unsigned long.
 
  */
 
 #ifdef STANDALONE
+# ifndef KEY_FOR_BINARY_CHECK
+# define KEY_FOR_BINARY_CHECK "What am I, a doctor or a moonshuttle conductor?"
+# endif
 #include <stdint.h>
-#define HAVE_U32_TYPEDEF 1
+#define HAVE_TYPE_U32 1
 typedef uint32_t u32;
 #define VERSION "standalone"
 /* For GCC, we can detect endianness.  If not GCC, please define manually.  */
@@ -70,6 +73,7 @@ typedef uint32_t u32;
 #ifdef STANDALONE
 #define xtrymalloc(a) malloc((a))
 #define gpg_err_set_errno(a) (errno = (a))
+#define xfree(a) free((a))
 #else
 #include "g10lib.h"
 #endif
@@ -78,7 +82,7 @@ typedef uint32_t u32;
 
 
 
-#ifndef HAVE_U32_TYPEDEF
+#ifndef HAVE_TYPE_U32
 # undef u32 /* Undef a possible macro with that name.  */
 # if SIZEOF_UNSIGNED_INT == 4
    typedef unsigned int u32;
@@ -87,7 +91,7 @@ typedef uint32_t u32;
 # else
 #  error no typedef for u32
 # endif
-# define HAVE_U32_TYPEDEF
+# define HAVE_TYPE_U32
 #endif
 
 
@@ -341,7 +345,7 @@ _gcry_hmac256_new (const void *key, size_t keylen)
           tmphd = _gcry_hmac256_new (NULL, 0);
           if (!tmphd)
             {
-              free (hd);
+              xfree (hd);
               return NULL;
             }
           _gcry_hmac256_update (tmphd, key, keylen);
@@ -373,7 +377,7 @@ _gcry_hmac256_release (hmac256_context_t ctx)
       /* Note: We need to take care not to modify errno.  */
       if (ctx->use_hmac)
         my_wipememory (ctx->opad, 64);
-      free (ctx);
+      xfree (ctx);
     }
 }
 
@@ -489,7 +493,7 @@ _gcry_hmac256_file (void *result, size_t resultsize, const char *filename,
   while ( (nread = fread (buffer, 1, buffer_size, fp)))
     _gcry_hmac256_update (hd, buffer, nread);
 
-  free (buffer);
+  xfree (buffer);
 
   if (ferror (fp))
     {
@@ -706,9 +710,9 @@ main (int argc, char **argv)
         }
     }
 
-  if (argc < 1)
+  if (argc < 1 && !use_stdkey)
     {
-      fprintf (stderr, "usage: %s [--binary] [--stdkey] key [filename]\n", pgm);
+      fprintf (stderr, "usage: %s [--binary] [--stdkey|key] [filename]\n", pgm);
       exit (1);
     }
 
@@ -717,8 +721,13 @@ main (int argc, char **argv)
     setmode (fileno (stdout), O_BINARY);
 #endif
 
-  key = use_stdkey? "What am I, a doctor or a moonshuttle conductor?" : *argv;
-  argc--, argv++;
+  if (use_stdkey)
+    key = KEY_FOR_BINARY_CHECK;
+  else
+    {
+      key = *argv;
+      argc--, argv++;
+    }
   keylen = strlen (key);
   use_stdin = !argc;
 
@@ -771,6 +780,7 @@ main (int argc, char **argv)
                        pgm, strerror (errno));
               exit (1);
             }
+          _gcry_hmac256_release (hd);
           if (use_stdin)
             break;
         }
index a762b5e..4118858 100644 (file)
@@ -1,5 +1,5 @@
 /* hwf-arm.c - Detect hardware features - ARM part
- * Copyright (C) 2013  Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2013,2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
 #include <string.h>
 #include <stdarg.h>
 #include <unistd.h>
+#include <errno.h>
+#if defined(HAVE_SYS_AUXV_H) && (defined(HAVE_GETAUXVAL) || \
+    defined(HAVE_ELF_AUX_INFO))
+#include <sys/auxv.h>
+#endif
 
 #include "g10lib.h"
 #include "hwf-common.h"
 # error Module build for wrong CPU.
 #endif
 
+
+#if defined(HAVE_SYS_AUXV_H) && defined(HAVE_ELF_AUX_INFO) && \
+    !defined(HAVE_GETAUXVAL) && defined(AT_HWCAP)
+#define HAVE_GETAUXVAL
+static unsigned long getauxval(unsigned long type)
+{
+  unsigned long auxval = 0;
+  int err;
+
+  /* FreeBSD provides 'elf_aux_info' function that does the same as
+   * 'getauxval' on Linux. */
+
+  err = elf_aux_info (type, &auxval, sizeof(auxval));
+  if (err)
+    {
+      errno = err;
+      auxval = 0;
+    }
+
+  return auxval;
+}
+#endif
+
+
 #undef HAS_SYS_AT_HWCAP
-#undef HAS_PROC_CPUINFO
-#ifdef __linux__
+#if defined(__linux__) || \
+    (defined(HAVE_SYS_AUXV_H) && defined(HAVE_GETAUXVAL))
+#define HAS_SYS_AT_HWCAP 1
 
 struct feature_map_s {
   unsigned int hwcap_flag;
@@ -42,20 +72,32 @@ struct feature_map_s {
   unsigned int hwf_flag;
 };
 
-#define HAS_SYS_AT_HWCAP 1
-#define HAS_PROC_CPUINFO 1
-
 #ifdef __arm__
 
-#define AT_HWCAP      16
-#define AT_HWCAP2     26
+/* Note: These macros have same values on Linux and FreeBSD. */
+#ifndef AT_HWCAP
+# define AT_HWCAP      16
+#endif
+#ifndef AT_HWCAP2
+# define AT_HWCAP2     26
+#endif
 
-#define HWCAP_NEON    4096
+#ifndef HWCAP_NEON
+# define HWCAP_NEON    4096
+#endif
 
-#define HWCAP2_AES    1
-#define HWCAP2_PMULL  2
-#define HWCAP2_SHA1   3
-#define HWCAP2_SHA2   4
+#ifndef HWCAP2_AES
+# define HWCAP2_AES    1
+#endif
+#ifndef HWCAP2_PMULL
+# define HWCAP2_PMULL  2
+#endif
+#ifndef HWCAP2_SHA1
+# define HWCAP2_SHA1   4
+#endif
+#ifndef HWCAP2_SHA2
+# define HWCAP2_SHA2   8
+#endif
 
 static const struct feature_map_s arm_features[] =
   {
@@ -72,14 +114,29 @@ static const struct feature_map_s arm_features[] =
 
 #elif defined(__aarch64__)
 
-#define AT_HWCAP    16
-#define AT_HWCAP2   -1
+/* Note: These macros have same values on Linux and FreeBSD. */
+#ifndef AT_HWCAP
+# define AT_HWCAP    16
+#endif
+#ifndef AT_HWCAP2
+# define AT_HWCAP2   -1
+#endif
 
-#define HWCAP_ASIMD 2
-#define HWCAP_AES   8
-#define HWCAP_PMULL 16
-#define HWCAP_SHA1  32
-#define HWCAP_SHA2  64
+#ifndef HWCAP_ASIMD
+# define HWCAP_ASIMD 2
+#endif
+#ifndef HWCAP_AES
+# define HWCAP_AES   8
+#endif
+#ifndef HWCAP_PMULL
+# define HWCAP_PMULL 16
+#endif
+#ifndef HWCAP_SHA1
+# define HWCAP_SHA1  32
+#endif
+#ifndef HWCAP_SHA2
+# define HWCAP_SHA2  64
+#endif
 
 static const struct feature_map_s arm_features[] =
   {
@@ -113,6 +170,34 @@ get_hwcap(unsigned int *hwcap, unsigned int *hwcap2)
       return 0;
     }
 
+#if defined(HAVE_SYS_AUXV_H) && defined(HAVE_GETAUXVAL)
+  errno = 0;
+  auxv.a_val = getauxval (AT_HWCAP);
+  if (errno == 0)
+    {
+      stored_hwcap |= auxv.a_val;
+      hwcap_initialized = 1;
+    }
+
+  if (AT_HWCAP2 >= 0)
+    {
+      errno = 0;
+      auxv.a_val = getauxval (AT_HWCAP2);
+      if (errno == 0)
+       {
+         stored_hwcap2 |= auxv.a_val;
+         hwcap_initialized = 1;
+       }
+    }
+
+  if (hwcap_initialized && (stored_hwcap || stored_hwcap2))
+    {
+      *hwcap = stored_hwcap;
+      *hwcap2 = stored_hwcap2;
+      return 0;
+    }
+#endif
+
   f = fopen("/proc/self/auxv", "r");
   if (!f)
     {
@@ -125,13 +210,13 @@ get_hwcap(unsigned int *hwcap, unsigned int *hwcap2)
     {
       if (auxv.a_type == AT_HWCAP)
         {
-          stored_hwcap = auxv.a_val;
+          stored_hwcap |= auxv.a_val;
           hwcap_initialized = 1;
         }
 
       if (auxv.a_type == AT_HWCAP2)
         {
-          stored_hwcap2 = auxv.a_val;
+          stored_hwcap2 |= auxv.a_val;
           hwcap_initialized = 1;
         }
     }
@@ -168,6 +253,12 @@ detect_arm_at_hwcap(void)
   return features;
 }
 
+#endif
+
+#undef HAS_PROC_CPUINFO
+#ifdef __linux__
+#define HAS_PROC_CPUINFO 1
+
 static unsigned int
 detect_arm_proc_cpuinfo(unsigned int *broken_hwfs)
 {
index 8f156b5..b10f86b 100644 (file)
@@ -22,6 +22,7 @@
 
 unsigned int _gcry_hwf_detect_x86 (void);
 unsigned int _gcry_hwf_detect_arm (void);
-
+unsigned int _gcry_hwf_detect_ppc (void);
+unsigned int _gcry_hwf_detect_s390x (void);
 
 #endif /*HWF_COMMON_H*/
diff --git a/src/hwf-ppc.c b/src/hwf-ppc.c
new file mode 100644 (file)
index 0000000..7801f8b
--- /dev/null
@@ -0,0 +1,246 @@
+/* hwf-ppc.c - Detect hardware features - PPC part
+ * Copyright (C) 2013,2019 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2019 Shawn Landden <shawn@git.icu>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#if defined(HAVE_SYS_AUXV_H) && (defined(HAVE_GETAUXVAL) || \
+    defined(HAVE_ELF_AUX_INFO))
+#include <sys/auxv.h>
+#endif
+
+#include "g10lib.h"
+#include "hwf-common.h"
+
+#if !defined (__powerpc__) && !defined (__powerpc64__)
+# error Module build for wrong CPU.
+#endif
+
+
+#if defined(HAVE_SYS_AUXV_H) && defined(HAVE_ELF_AUX_INFO) && \
+    !defined(HAVE_GETAUXVAL) && defined(AT_HWCAP)
+#define HAVE_GETAUXVAL
+static unsigned long getauxval(unsigned long type)
+{
+  unsigned long auxval = 0;
+  int err;
+
+  /* FreeBSD provides 'elf_aux_info' function that does the same as
+   * 'getauxval' on Linux. */
+
+  err = elf_aux_info (type, &auxval, sizeof(auxval));
+  if (err)
+    {
+      errno = err;
+      auxval = 0;
+    }
+
+  return auxval;
+}
+#endif
+
+
+#undef HAS_SYS_AT_HWCAP
+#if defined(__linux__) || \
+    (defined(HAVE_SYS_AUXV_H) && defined(HAVE_GETAUXVAL))
+#define HAS_SYS_AT_HWCAP 1
+
+struct feature_map_s
+  {
+    unsigned int hwcap_flag;
+    unsigned int hwcap2_flag;
+    unsigned int hwf_flag;
+  };
+
+#if defined(__powerpc__) || defined(__powerpc64__)
+
+/* Note: These macros have same values on Linux and FreeBSD. */
+#ifndef AT_HWCAP
+# define AT_HWCAP      16
+#endif
+#ifndef AT_HWCAP2
+# define AT_HWCAP2     26
+#endif
+
+#ifndef PPC_FEATURE2_ARCH_2_07
+# define PPC_FEATURE2_ARCH_2_07     0x80000000
+#endif
+#ifndef PPC_FEATURE2_VEC_CRYPTO
+# define PPC_FEATURE2_VEC_CRYPTO    0x02000000
+#endif
+#ifndef PPC_FEATURE2_ARCH_3_00
+# define PPC_FEATURE2_ARCH_3_00     0x00800000
+#endif
+#ifndef PPC_FEATURE2_ARCH_3_10
+# define PPC_FEATURE2_ARCH_3_10     0x00040000
+#endif
+
+static const struct feature_map_s ppc_features[] =
+  {
+    { 0, PPC_FEATURE2_ARCH_2_07, HWF_PPC_ARCH_2_07 },
+#ifdef ENABLE_PPC_CRYPTO_SUPPORT
+    { 0, PPC_FEATURE2_VEC_CRYPTO, HWF_PPC_VCRYPTO },
+#endif
+    { 0, PPC_FEATURE2_ARCH_3_00, HWF_PPC_ARCH_3_00 },
+  };
+#endif
+
+static int
+get_hwcap(unsigned int *hwcap, unsigned int *hwcap2)
+{
+  struct { unsigned long a_type; unsigned long a_val; } auxv;
+  FILE *f;
+  int err = -1;
+  static int hwcap_initialized = 0;
+  static unsigned int stored_hwcap = 0;
+  static unsigned int stored_hwcap2 = 0;
+
+  if (hwcap_initialized)
+    {
+      *hwcap = stored_hwcap;
+      *hwcap2 = stored_hwcap2;
+      return 0;
+    }
+
+#if 0 // TODO: configure.ac detection for __builtin_cpu_supports
+      // TODO: move to 'detect_ppc_builtin_cpu_supports'
+#if defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ >= 6
+  /* __builtin_cpu_supports returns 0 if glibc support doesn't exist, so
+   * we can only trust positive results. */
+#ifdef ENABLE_PPC_CRYPTO_SUPPORT
+  if (__builtin_cpu_supports("vcrypto")) /* TODO: Configure.ac */
+    {
+      stored_hwcap2 |= PPC_FEATURE2_VEC_CRYPTO;
+      hwcap_initialized = 1;
+    }
+#endif
+
+  if (__builtin_cpu_supports("arch_3_00")) /* TODO: Configure.ac */
+    {
+      stored_hwcap2 |= PPC_FEATURE2_ARCH_3_00;
+      hwcap_initialized = 1;
+    }
+#endif
+#endif
+
+#if defined(HAVE_SYS_AUXV_H) && defined(HAVE_GETAUXVAL)
+  errno = 0;
+  auxv.a_val = getauxval (AT_HWCAP);
+  if (errno == 0)
+    {
+      stored_hwcap |= auxv.a_val;
+      hwcap_initialized = 1;
+    }
+
+  if (AT_HWCAP2 >= 0)
+    {
+      errno = 0;
+      auxv.a_val = getauxval (AT_HWCAP2);
+      if (errno == 0)
+       {
+         stored_hwcap2 |= auxv.a_val;
+         hwcap_initialized = 1;
+       }
+    }
+
+  if (hwcap_initialized && (stored_hwcap || stored_hwcap2))
+    {
+      *hwcap = stored_hwcap;
+      *hwcap2 = stored_hwcap2;
+      return 0;
+    }
+#endif
+
+  f = fopen("/proc/self/auxv", "r");
+  if (!f)
+    {
+      *hwcap = stored_hwcap;
+      *hwcap2 = stored_hwcap2;
+      return -1;
+    }
+
+  while (fread(&auxv, sizeof(auxv), 1, f) > 0)
+    {
+      if (auxv.a_type == AT_HWCAP)
+        {
+          stored_hwcap |= auxv.a_val;
+          hwcap_initialized = 1;
+        }
+
+      if (auxv.a_type == AT_HWCAP2)
+        {
+          stored_hwcap2 |= auxv.a_val;
+          hwcap_initialized = 1;
+        }
+    }
+
+  if (hwcap_initialized)
+      err = 0;
+
+  fclose(f);
+
+  *hwcap = stored_hwcap;
+  *hwcap2 = stored_hwcap2;
+  return err;
+}
+
+static unsigned int
+detect_ppc_at_hwcap(void)
+{
+  unsigned int hwcap;
+  unsigned int hwcap2;
+  unsigned int features = 0;
+  unsigned int i;
+
+  if (get_hwcap(&hwcap, &hwcap2) < 0)
+      return features;
+
+  for (i = 0; i < DIM(ppc_features); i++)
+    {
+      if (hwcap & ppc_features[i].hwcap_flag)
+        features |= ppc_features[i].hwf_flag;
+
+      if (hwcap2 & ppc_features[i].hwcap2_flag)
+        features |= ppc_features[i].hwf_flag;
+    }
+
+  return features;
+}
+
+#endif
+
+unsigned int
+_gcry_hwf_detect_ppc (void)
+{
+  unsigned int ret = 0;
+  unsigned int broken_hwfs = 0;
+
+#if defined (HAS_SYS_AT_HWCAP)
+  ret |= detect_ppc_at_hwcap ();
+#endif
+
+  ret &= ~broken_hwfs;
+
+  return ret;
+}
diff --git a/src/hwf-s390x.c b/src/hwf-s390x.c
new file mode 100644 (file)
index 0000000..74590fc
--- /dev/null
@@ -0,0 +1,231 @@
+/* hwf-s390x.c - Detect hardware features - s390x/zSeries part
+ * Copyright (C) 2020 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#if defined(HAVE_SYS_AUXV_H) && (defined(HAVE_GETAUXVAL) || \
+    defined(HAVE_ELF_AUX_INFO))
+#include <sys/auxv.h>
+#endif
+
+#include "g10lib.h"
+#include "hwf-common.h"
+
+#if !defined (__s390x__)
+# error Module build for wrong CPU.
+#endif
+
+#undef HAVE_STFLE
+#ifdef HAVE_GCC_INLINE_ASM_S390X
+# define HAVE_STFLE 1
+#endif
+
+#ifndef AT_HWCAP
+# define AT_HWCAP         16
+#endif
+#ifndef HWCAP_S390_STFLE
+# define HWCAP_S390_STFLE 4
+#endif
+#ifndef HWCAP_S390_VXRS
+# define HWCAP_S390_VXRS  2048
+#endif
+
+struct feature_map_s
+  {
+    unsigned int facilities_bit;
+    unsigned int hwcap_flag;
+    unsigned int hwf_flag;
+  };
+
+static const struct feature_map_s s390x_features[] =
+  {
+    { 17,  0, HWF_S390X_MSA },
+    { 77,  0, HWF_S390X_MSA_4 },
+    { 146, 0, HWF_S390X_MSA_8 },
+    { 155, 0, HWF_S390X_MSA_9 },
+#ifdef HAVE_GCC_INLINE_ASM_S390X_VX
+    { 129, HWCAP_S390_VXRS, HWF_S390X_VX },
+#endif
+  };
+
+#if defined(HAVE_SYS_AUXV_H) && defined(HAVE_ELF_AUX_INFO) && \
+    !defined(HAVE_GETAUXVAL) && defined(AT_HWCAP)
+#define HAVE_GETAUXVAL
+static unsigned long getauxval(unsigned long type)
+{
+  unsigned long auxval = 0;
+  int err;
+
+  /* FreeBSD provides 'elf_aux_info' function that does the same as
+   * 'getauxval' on Linux. */
+
+  err = elf_aux_info (type, &auxval, sizeof(auxval));
+  if (err)
+    {
+      errno = err;
+      auxval = 0;
+    }
+
+  return auxval;
+}
+#endif
+
+
+#undef HAS_SYS_AT_HWCAP
+#if defined(__linux__) || \
+    (defined(HAVE_SYS_AUXV_H) && defined(HAVE_GETAUXVAL))
+#define HAS_SYS_AT_HWCAP 1
+
+struct facilities_s
+  {
+    u64 bits[3];
+  };
+
+static int
+get_hwcap(unsigned int *hwcap)
+{
+  struct { unsigned long a_type; unsigned long a_val; } auxv;
+  FILE *f;
+  int err = -1;
+  static int hwcap_initialized = 0;
+  static unsigned int stored_hwcap = 0;
+
+  if (hwcap_initialized)
+    {
+      *hwcap = stored_hwcap;
+      return 0;
+    }
+
+#if defined(HAVE_SYS_AUXV_H) && defined(HAVE_GETAUXVAL)
+  errno = 0;
+  auxv.a_val = getauxval (AT_HWCAP);
+  if (errno == 0)
+    {
+      stored_hwcap |= auxv.a_val;
+      hwcap_initialized = 1;
+    }
+
+  if (hwcap_initialized && stored_hwcap)
+    {
+      *hwcap = stored_hwcap;
+      return 0;
+    }
+#endif
+
+  f = fopen("/proc/self/auxv", "r");
+  if (!f)
+    {
+      *hwcap = stored_hwcap;
+      return -1;
+    }
+
+  while (fread(&auxv, sizeof(auxv), 1, f) > 0)
+    {
+      if (auxv.a_type == AT_HWCAP)
+        {
+          stored_hwcap |= auxv.a_val;
+          hwcap_initialized = 1;
+        }
+    }
+
+  if (hwcap_initialized)
+      err = 0;
+
+  fclose(f);
+
+  *hwcap = stored_hwcap;
+  return err;
+}
+#endif
+
+#ifdef HAVE_STFLE
+static void
+get_stfle(struct facilities_s *out)
+{
+  static int stfle_initialized = 0;
+  static struct facilities_s stored_facilities;
+
+  if (!stfle_initialized)
+    {
+      register unsigned long reg0 asm("0") = DIM(stored_facilities.bits) - 1;
+
+      asm ("stfle %1\n\t"
+          : "+d" (reg0),
+            "=Q" (stored_facilities.bits[0])
+          :
+          : "cc", "memory");
+
+      stfle_initialized = 1;
+    }
+
+  *out = stored_facilities;
+}
+#endif
+
+static unsigned int
+detect_s390x_features(void)
+{
+  struct facilities_s facilities = { { 0, } };
+  unsigned int hwcap = 0;
+  unsigned int features = 0;
+  unsigned int i;
+
+#if defined (HAS_SYS_AT_HWCAP)
+  if (get_hwcap(&hwcap) < 0)
+    return features;
+#endif
+
+  if ((hwcap & HWCAP_S390_STFLE) == 0)
+    return features;
+
+#ifdef HAVE_STFLE
+  get_stfle(&facilities);
+#endif
+
+  for (i = 0; i < DIM(s390x_features); i++)
+    {
+      if (s390x_features[i].hwcap_flag == 0 ||
+         (s390x_features[i].hwcap_flag & hwcap))
+       {
+         unsigned int idx = s390x_features[i].facilities_bit;
+         unsigned int u64_idx = idx / 64;
+         unsigned int u64_bit = 63 - (idx % 64);
+
+         if (facilities.bits[u64_idx] & (U64_C(1) << u64_bit))
+           features |= s390x_features[i].hwf_flag;
+       }
+    }
+
+  return features;
+}
+
+unsigned int
+_gcry_hwf_detect_s390x (void)
+{
+  unsigned int ret = 0;
+
+  ret |= detect_s390x_features ();
+
+  return ret;
+}
index 0d3a1f4..a1aa02e 100644 (file)
 #if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__)
 # define HAS_X86_CPUID 1
 
-static int
+#if _GCRY_GCC_VERSION >= 40700 /* 4.7 */
+# define FORCE_FUNC_FRAME_POINTER \
+       __attribute__ ((optimize("no-omit-frame-pointer")))
+#else
+# define FORCE_FUNC_FRAME_POINTER
+#endif
+
+static FORCE_FUNC_FRAME_POINTER int
 is_cpuid_available(void)
 {
   int has_cpuid = 0;
@@ -63,7 +70,7 @@ is_cpuid_available(void)
      ".Lno_cpuid%=:\n\t"
      : "+r" (has_cpuid)
      :
-     : "%eax", "%ecx", "cc"
+     : "%eax", "%ecx", "cc", "memory"
      );
 
   return has_cpuid;
@@ -76,11 +83,9 @@ get_cpuid(unsigned int in, unsigned int *eax, unsigned int *ebx,
   unsigned int regs[4];
 
   asm volatile
-    ("pushl %%ebx\n\t"           /* Save GOT register.  */
-     "movl %1, %%ebx\n\t"
+    ("xchgl %%ebx, %1\n\t"     /* Save GOT register.  */
      "cpuid\n\t"
-     "movl %%ebx, %1\n\t"
-     "popl %%ebx\n\t"            /* Restore GOT register. */
+     "xchgl %%ebx, %1\n\t"     /* Restore GOT register. */
      : "=a" (regs[0]), "=D" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
      : "0" (in), "1" (0), "2" (0), "3" (0)
      : "cc"
@@ -294,6 +299,29 @@ detect_x86_gnuc (void)
       avoid_vpgather |= 1;
     }
 
+#ifdef ENABLE_FORCE_SOFT_HWFEATURES
+  /* Soft HW features mark functionality that is available on all systems
+   * but not feasible to use because of slow HW implementation. */
+
+  /* SHLD is faster at rotating register than actual ROR/ROL instructions
+   * on older Intel systems (~sandy-bridge era). However, SHLD is very
+   * slow on almost anything else and later Intel processors have faster
+   * ROR/ROL. Therefore in regular build HWF_INTEL_FAST_SHLD is enabled
+   * only for those Intel processors that benefit from the SHLD
+   * instruction. Enabled here unconditionally as requested. */
+  result |= HWF_INTEL_FAST_SHLD;
+
+  /* VPGATHER instructions are used for look-up table based
+   * implementations which require VPGATHER to be fast enough to beat
+   * regular parallelized look-up table implementations (see Twofish).
+   * So far, only Intel processors beginning with skylake have had
+   * VPGATHER fast enough to be enabled. AMD Zen3 comes close to
+   * being feasible, but not quite (where twofish-avx2 is few percent
+   * slower than twofish-3way). Enable VPGATHER here unconditionally
+   * as requested. */
+  avoid_vpgather = 0;
+#endif
+
 #ifdef ENABLE_PCLMUL_SUPPORT
   /* Test bit 1 for PCLMUL.  */
   if (features & 0x00000002)
@@ -342,7 +370,7 @@ detect_x86_gnuc (void)
   if (max_cpuid_level >= 7 && (features & 0x00000001))
     {
       /* Get CPUID:7 contains further Intel feature flags. */
-      get_cpuid(7, NULL, &features, NULL, NULL);
+      get_cpuid(7, NULL, &features, &features2, NULL);
 
       /* Test bit 8 for BMI2.  */
       if (features & 0x00000100)
@@ -357,6 +385,17 @@ detect_x86_gnuc (void)
       if ((result & HWF_INTEL_AVX2) && !avoid_vpgather)
         result |= HWF_INTEL_FAST_VPGATHER;
 #endif /*ENABLE_AVX_SUPPORT*/
+
+      /* Test bit 29 for SHA Extensions. */
+      if (features & (1 << 29))
+        result |= HWF_INTEL_SHAEXT;
+
+#if defined(ENABLE_AVX2_SUPPORT) && defined(ENABLE_AESNI_SUPPORT) && \
+    defined(ENABLE_PCLMUL_SUPPORT)
+      /* Test bit 9 for VAES and bit 10 for VPCLMULDQD */
+      if ((features2 & 0x00000200) && (features2 & 0x00000400))
+        result |= HWF_INTEL_VAES_VPCLMUL;
+#endif
     }
 
   return result;
index 1cad546..97e67b3 100644 (file)
 /* The name of a file used to globally disable selected features. */
 #define HWF_DENY_FILE "/etc/gcrypt/hwf.deny"
 
-/* A table to map hardware features to a string.  */
+/* A table to map hardware features to a string.
+ * Note: Remember to add new HW features to 'doc/gcrypt.texi'.  */
 static struct
 {
   unsigned int flag;
   const char *desc;
 } hwflist[] =
   {
+#if defined(HAVE_CPU_ARCH_X86)
     { HWF_PADLOCK_RNG,         "padlock-rng" },
     { HWF_PADLOCK_AES,         "padlock-aes" },
     { HWF_PADLOCK_SHA,         "padlock-sha" },
@@ -58,11 +60,26 @@ static struct
     { HWF_INTEL_AVX2,          "intel-avx2" },
     { HWF_INTEL_FAST_VPGATHER, "intel-fast-vpgather" },
     { HWF_INTEL_RDTSC,         "intel-rdtsc" },
+    { HWF_INTEL_SHAEXT,        "intel-shaext" },
+    { HWF_INTEL_VAES_VPCLMUL,  "intel-vaes-vpclmul" },
+#elif defined(HAVE_CPU_ARCH_ARM)
     { HWF_ARM_NEON,            "arm-neon" },
     { HWF_ARM_AES,             "arm-aes" },
     { HWF_ARM_SHA1,            "arm-sha1" },
     { HWF_ARM_SHA2,            "arm-sha2" },
-    { HWF_ARM_PMULL,           "arm-pmull" }
+    { HWF_ARM_PMULL,           "arm-pmull" },
+#elif defined(HAVE_CPU_ARCH_PPC)
+    { HWF_PPC_VCRYPTO,         "ppc-vcrypto" },
+    { HWF_PPC_ARCH_3_00,       "ppc-arch_3_00" },
+    { HWF_PPC_ARCH_2_07,       "ppc-arch_2_07" },
+    { HWF_PPC_ARCH_3_10,       "ppc-arch_3_10" },
+#elif defined(HAVE_CPU_ARCH_S390X)
+    { HWF_S390X_MSA,           "s390x-msa" },
+    { HWF_S390X_MSA_4,         "s390x-msa-4" },
+    { HWF_S390X_MSA_8,         "s390x-msa-8" },
+    { HWF_S390X_MSA_9,         "s390x-msa-9" },
+    { HWF_S390X_VX,            "s390x-vx" },
+#endif
   };
 
 /* A bit vector with the hardware features which shall not be used.
@@ -198,21 +215,24 @@ _gcry_detect_hw_features (void)
 {
   hw_features = 0;
 
-  if (fips_mode ())
-    return; /* Hardware support is not to be evaluated.  */
-
   parse_hwf_deny_file ();
 
 #if defined (HAVE_CPU_ARCH_X86)
   {
     hw_features = _gcry_hwf_detect_x86 ();
   }
-#endif /* HAVE_CPU_ARCH_X86 */
-#if defined (HAVE_CPU_ARCH_ARM)
+#elif defined (HAVE_CPU_ARCH_ARM)
   {
     hw_features = _gcry_hwf_detect_arm ();
   }
-#endif /* HAVE_CPU_ARCH_ARM */
-
+#elif defined (HAVE_CPU_ARCH_PPC)
+  {
+    hw_features = _gcry_hwf_detect_ppc ();
+  }
+#elif defined (HAVE_CPU_ARCH_S390X)
+  {
+    hw_features = _gcry_hwf_detect_s390x ();
+  }
+#endif
   hw_features &= ~disabled_hw_features;
 }
index c052638..6b3b356 100644 (file)
@@ -14,7 +14,7 @@
 # General.
 prefix="@prefix@"
 exec_prefix="@exec_prefix@"
-version="@VERSION@"
+version="@PACKAGE_VERSION@"
 includedir="@includedir@"
 libdir="@libdir@"
 gpg_error_libs="@GPG_ERROR_LIBS@"
@@ -96,7 +96,19 @@ while test $# -gt 0; do
        --exec-prefix)
            echo_exec_prefix=yes
            ;;
-       --version)
+        --variable=*)
+            case "${1#*=}" in
+                prefix) echo "$prefix" ;;
+                exec_prefix) echo "$exec_prefix" ;;
+                host) echo "$my_host" ;;
+                api_version) echo "$api_version" ;;
+               symmetric_ciphers) echo "$symmetric_ciphers" ;;
+               asymmetric_ciphers) echo "$asymmetric_ciphers" ;;
+               digests) echo "$digests" ;;
+            esac
+            exit 0
+            ;;
+       --modversion|--version)
            echo_version=yes
            ;;
         --api-version)
index a76b377..d6de731 100644 (file)
@@ -118,7 +118,7 @@ EXPORTS
       gcry_mpi_set_flag  @88
       gcry_mpi_clear_flag  @89
       gcry_mpi_get_flag  @90
-
+      gcry_mpi_get_ui    @91
 
       gcry_cipher_open  @92
       gcry_cipher_close  @93
@@ -286,4 +286,16 @@ EXPORTS
 
       gcry_mpi_point_copy       @248
 
+      gcry_ecc_get_algo_keylen  @249
+      gcry_ecc_mul_point        @250
+
+      gcry_pk_hash_sign         @255
+      gcry_pk_hash_verify       @256
+      gcry_pk_random_override_new @257
+
+      gcry_kdf_open             @258
+      gcry_kdf_compute          @259
+      gcry_kdf_final            @260
+      gcry_kdf_close            @261
+
 ;; end of file with public symbols for Windows.
index c67cfec..19d514f 100644 (file)
@@ -1,5 +1,5 @@
 # libgcrypt.m4 - Autoconf macros to detect libgcrypt
-# Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH
+# Copyright (C) 2002, 2003, 2004, 2011, 2014, 2018, 2020 g10 Code GmbH
 #
 # This file is free software; as a special exception the author gives
 # unlimited permission to copy and/or distribute it, with or without
@@ -9,15 +9,15 @@
 # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 #
-# Last-changed: 2014-10-02
+# Last-changed: 2020-09-27
 
 
 dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION,
 dnl                   [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
 dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS.
-dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
+dnl MINIMUM-VERSION is a string with the version number optionally prefixed
 dnl with the API version to also check the API compatibility. Example:
-dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed
+dnl a MINIMUM-VERSION of 1:1.2.5 won't pass the test unless the installed
 dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1.  Using
 dnl this features allows to prevent build against newer versions of libgcrypt
 dnl with a changed API.
@@ -30,14 +30,26 @@ dnl
 AC_DEFUN([AM_PATH_LIBGCRYPT],
 [ AC_REQUIRE([AC_CANONICAL_HOST])
   AC_ARG_WITH(libgcrypt-prefix,
-            AC_HELP_STRING([--with-libgcrypt-prefix=PFX],
+            AS_HELP_STRING([--with-libgcrypt-prefix=PFX],
                            [prefix where LIBGCRYPT is installed (optional)]),
      libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="")
   if test x"${LIBGCRYPT_CONFIG}" = x ; then
      if test x"${libgcrypt_config_prefix}" != x ; then
         LIBGCRYPT_CONFIG="${libgcrypt_config_prefix}/bin/libgcrypt-config"
-     else
-       case "${SYSROOT}" in
+     fi
+  fi
+
+  use_gpgrt_config=""
+  if test x"${LIBGCRYPT_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then
+    if $GPGRT_CONFIG libgcrypt --exists; then
+      LIBGCRYPT_CONFIG="$GPGRT_CONFIG libgcrypt"
+      AC_MSG_NOTICE([Use gpgrt-config as libgcrypt-config])
+      use_gpgrt_config=yes
+    fi
+  fi
+  if test -z "$use_gpgrt_config"; then
+    if test x"${LIBGCRYPT_CONFIG}" = x ; then
+      case "${SYSROOT}" in
          /*)
            if test -x "${SYSROOT}/bin/libgcrypt-config" ; then
              LIBGCRYPT_CONFIG="${SYSROOT}/bin/libgcrypt-config"
@@ -48,11 +60,11 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
           *)
            AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.])
            ;;
-       esac
-     fi
+      esac
+    fi
+    AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no)
   fi
 
-  AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no)
   tmp=ifelse([$1], ,1:1.2.0,$1)
   if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
      req_libgcrypt_api=`echo "$tmp"     | sed 's/\(.*\):\(.*\)/\1/'`
@@ -71,7 +83,11 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
     req_micro=`echo $min_libgcrypt_version | \
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
-    libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
+    if test -z "$use_gpgrt_config"; then
+      libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
+    else
+      libgcrypt_config_version=`$LIBGCRYPT_CONFIG --modversion`
+    fi
     major=`echo $libgcrypt_config_version | \
                sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
     minor=`echo $libgcrypt_config_version | \
@@ -103,7 +119,11 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
      # If we have a recent libgcrypt, we should also check that the
      # API is compatible
      if test "$req_libgcrypt_api" -gt 0 ; then
-        tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+        if test -z "$use_gpgrt_config"; then
+           tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+       else
+           tmp=`$LIBGCRYPT_CONFIG --variable=api_version 2>/dev/null || echo 0`
+       fi
         if test "$tmp" -gt 0 ; then
            AC_MSG_CHECKING([LIBGCRYPT API version])
            if test "$req_libgcrypt_api" -eq "$tmp" ; then
@@ -119,12 +139,16 @@ AC_DEFUN([AM_PATH_LIBGCRYPT],
     LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
     LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
     ifelse([$2], , :, [$2])
-    libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
+    if test -z "$use_gpgrt_config"; then
+      libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
+    else
+      libgcrypt_config_host=`$LIBGCRYPT_CONFIG --variable=host 2>/dev/null || echo none`
+    fi
     if test x"$libgcrypt_config_host" != xnone ; then
       if test x"$libgcrypt_config_host" != x"$host" ; then
   AC_MSG_WARN([[
 ***
-*** The config script $LIBGCRYPT_CONFIG was
+*** The config script "$LIBGCRYPT_CONFIG" was
 *** built for $libgcrypt_config_host and thus may not match the
 *** used host $host.
 *** You may want to use the configure option --with-libgcrypt-prefix
diff --git a/src/libgcrypt.pc.in b/src/libgcrypt.pc.in
new file mode 100644 (file)
index 0000000..325f5c2
--- /dev/null
@@ -0,0 +1,18 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+includedir=@includedir@
+libdir=@libdir@
+host=@LIBGCRYPT_CONFIG_HOST@
+api_version=@LIBGCRYPT_CONFIG_API_VERSION@
+symmetric_ciphers="@LIBGCRYPT_CIPHERS@"
+asymmetric_ciphers="@LIBGCRYPT_PUBKEY_CIPHERS@"
+digests="@LIBGCRYPT_DIGESTS@"
+
+Name: libgcrypt
+Description: General purpose cryptographic library
+Requires.private: gpg-error
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir} @LIBGCRYPT_CONFIG_CFLAGS@
+Libs: -L${libdir} @LIBGCRYPT_CONFIG_LIBS@
+Libs.private: @DL_LIBS@
+URL: https://www.gnupg.org/software/libgcrypt/index.html
index 1aa830f..2e274f6 100644 (file)
@@ -67,6 +67,9 @@ GCRYPT_1.6 {
 
     gcry_pubkey_get_sexp;
 
+    gcry_ecc_get_algo_keylen;
+    gcry_ecc_mul_point;
+
     gcry_kdf_derive;
 
     gcry_prime_check; gcry_prime_generate;
@@ -108,6 +111,7 @@ GCRYPT_1.6 {
     gcry_mpi_ec_dup; gcry_mpi_ec_add; gcry_mpi_ec_sub; gcry_mpi_ec_mul;
     gcry_mpi_ec_curve_point; gcry_mpi_ec_decode_point;
     gcry_mpi_point_copy;
+    gcry_mpi_get_ui;
 
     gcry_log_debug;
     gcry_log_debughex; gcry_log_debugmpi; gcry_log_debugpnt; gcry_log_debugsxp;
@@ -118,6 +122,9 @@ GCRYPT_1.6 {
 
     gcry_ctx_release;
 
+    gcry_pk_hash_sign; gcry_pk_hash_verify; gcry_pk_random_override_new;
+
+    gcry_kdf_open; gcry_kdf_compute; gcry_kdf_final; gcry_kdf_close;
   local:
     *;
 
index 002a84f..4db2d9a 100644 (file)
 
 static int verbosity_level = 0;
 
+#ifndef HAVE_EXPLICIT_MEMSET
+/* Prevent compiler from optimizing away the call to memset by accessing
+   memset through volatile pointer. */
+static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
+#endif
+
 static void (*fatal_error_handler)(void*,int, const char*) = NULL;
 static void *fatal_error_handler_value = 0;
 static void (*log_handler)(void*,int, const char*, va_list) = NULL;
@@ -498,21 +504,63 @@ _gcry_strtokenize (const char *string, const char *delim)
 
 
 void
+_gcry_fast_wipememory (void *ptr, size_t len)
+{
+  /* Note: This function is called from wipememory/wipememory2 only if LEN
+     is large or unknown at compile time. New wipe function alternatives
+     need to be checked before adding to this function. New implementations
+     need to be faster than wipememory/wipememory2 macros in 'g10lib.h'.
+
+     Following implementations were found to have suboptimal performance:
+
+     - [_WIN32/mingw32] SecureZeroMemory; Inline function, equivalent to
+       volatile byte buffer set: while(buflen--) (volatile char *)(buf++)=set;
+   */
+#ifdef HAVE_EXPLICIT_BZERO
+  explicit_bzero (ptr, len);
+#elif defined(HAVE_EXPLICIT_MEMSET)
+  explicit_memset (ptr, 0, len);
+#else
+  memset_ptr (ptr, 0, len);
+#endif
+}
+
+
+void
+_gcry_fast_wipememory2 (void *ptr, int set, size_t len)
+{
+#ifdef HAVE_EXPLICIT_MEMSET
+  explicit_memset (ptr, set, len);
+#else
+#ifdef HAVE_EXPLICIT_BZERO
+  if (set == 0)
+    {
+      explicit_bzero (ptr, len);
+      return;
+    }
+#endif
+
+  memset_ptr (ptr, set, len);
+#endif
+}
+
+
+void NOINLINE_FUNC
 __gcry_burn_stack (unsigned int bytes)
 {
 #ifdef HAVE_VLA
-    /* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
-    unsigned int buflen = ((!bytes + bytes) + 63) & ~63;
-    volatile char buf[buflen];
+  /* (bytes == 0 ? 1 : bytes) == (!bytes + bytes) */
+  unsigned int buflen = ((!bytes + bytes) + 63) & ~63;
+  char buf[buflen];
 
-    wipememory (buf, sizeof buf);
+  _gcry_fast_wipememory (buf, buflen);
 #else
-    volatile char buf[64];
+  volatile char buf[64];
 
-    wipememory (buf, sizeof buf);
+  _gcry_fast_wipememory (buf, sizeof buf);
 
-    if (bytes > sizeof buf)
-        _gcry_burn_stack (bytes - sizeof buf);
+  if (bytes > sizeof buf)
+      _gcry_burn_stack (bytes - sizeof buf);
 #endif
 }
 
index aeba7f8..9e234ef 100644 (file)
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -121,6 +121,7 @@ void _gcry_mpi_immutable_failed (void);
 #define mpi_const(n)          _gcry_mpi_const ((n))
 #define mpi_swap_cond(a,b,sw)  _gcry_mpi_swap_cond ((a),(b),(sw))
 #define mpi_set_cond(w,u,set)  _gcry_mpi_set_cond ((w),(u),(set))
+#define mpi_set_bit_cond(a,n,set) _gcry_mpi_set_bit_cond ((a),(n),(set))
 
 void _gcry_mpi_clear( gcry_mpi_t a );
 gcry_mpi_t _gcry_mpi_set_cond (gcry_mpi_t w, const gcry_mpi_t u,
@@ -130,6 +131,7 @@ gcry_mpi_t  _gcry_mpi_alloc_set_ui( unsigned long u);
 void _gcry_mpi_m_check( gcry_mpi_t a );
 void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b);
 void _gcry_mpi_swap_cond (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap);
+void _gcry_mpi_set_bit_cond (gcry_mpi_t a, unsigned int n, unsigned long set);
 gcry_mpi_t _gcry_mpi_new (unsigned int nbits);
 gcry_mpi_t _gcry_mpi_snew (unsigned int nbits);
 gcry_mpi_t _gcry_mpi_set_opaque_copy (gcry_mpi_t a,
@@ -182,14 +184,14 @@ gpg_err_code_t _gcry_mpi_to_octet_string (unsigned char **r_frame,
 #define mpi_tdiv_q_2exp(a,b,c) _gcry_mpi_tdiv_q_2exp((a),(b),(c))
 #define mpi_divisible_ui(a,b)  _gcry_mpi_divisible_ui((a),(b))
 
-ulong _gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor );
+unsigned long _gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, unsigned long divisor );
 void  _gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor );
 void  _gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor );
 void  _gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor );
 void  _gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den);
 void  _gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den);
 void  _gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned count );
-int   _gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor );
+int   _gcry_mpi_divisible_ui(gcry_mpi_t dividend, unsigned long divisor );
 
 
 /*-- mpi-mod.c --*/
@@ -266,7 +268,8 @@ enum gcry_mpi_ec_models
 enum ecc_dialects
   {
     ECC_DIALECT_STANDARD = 0,
-    ECC_DIALECT_ED25519
+    ECC_DIALECT_ED25519,
+    ECC_DIALECT_SAFECURVE
   };
 
 
@@ -314,6 +317,10 @@ gpg_err_code_t _gcry_mpi_ec_decode_point (mpi_point_t result,
 /*-- ecc-curves.c --*/
 gpg_err_code_t _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
                                  gcry_sexp_t keyparam, const char *curvename);
+gpg_err_code_t _gcry_mpi_ec_internal_new (mpi_ec_t *r_ec, int *r_flags,
+                                          const char *name_op,
+                                          gcry_sexp_t keyparam,
+                                          const char *curvename);
 
 
 
index 11246f3..0903e0a 100644 (file)
@@ -313,7 +313,7 @@ print_help (void)
   fputs ("+   add           [0] := [1] + [0]          {-1}\n"
          "-   subtract      [0] := [1] - [0]          {-1}\n"
          "*   multiply      [0] := [1] * [0]          {-1}\n"
-         "/   divide        [0] := [1] - [0]          {-1}\n"
+         "/   divide        [0] := [1] / [0]          {-1}\n"
          "%   modulo        [0] := [1] % [0]          {-1}\n"
          "<   left shift    [0] := [0] << 1           {0}\n"
          ">   right shift   [0] := [0] >> 1           {0}\n"
index 3e091d8..b36c44f 100644 (file)
@@ -64,7 +64,7 @@ typedef struct pooldesc_s
 {
   /* A link to the next pool.  This is used to connect the overflow
    * pools.  */
-  struct pooldesc_s *next;
+  struct pooldesc_s * volatile next;
 
   /* A memory buffer used as allocation pool.  */
   void *mem;
@@ -118,6 +118,36 @@ GPGRT_LOCK_DEFINE (secmem_lock);
 #define ADDR_TO_BLOCK(addr) \
   (memblock_t *) (void *) ((char *) addr - BLOCK_HEAD_SIZE)
 
+/* Prototypes. */
+static void secmem_dump_stats_internal (int extended);
+
+
+/*
+ * Functions
+ */
+
+/* Memory barrier */
+static inline void
+memory_barrier(void)
+{
+#ifdef HAVE_SYNC_SYNCHRONIZE
+#ifdef HAVE_GCC_ASM_VOLATILE_MEMORY
+  asm volatile ("":::"memory");
+#endif
+  /* Use GCC / clang intrinsic for memory barrier. */
+  __sync_synchronize();
+#else
+  /* Slow portable alternative, implement memory barrier by using mutex. */
+  gpgrt_lock_t tmp;
+  memset (&tmp, 0, sizeof(tmp));
+  gpgrt_lock_init (&tmp);
+  gpgrt_lock_lock (&tmp);
+  gpgrt_lock_unlock (&tmp);
+  gpgrt_lock_destroy (&tmp);
+#endif
+}
+
+
 /* Check whether P points into POOL.  */
 static inline int
 ptr_into_pool_p (pooldesc_t *pool, const void *p)
@@ -520,7 +550,7 @@ _gcry_secmem_get_flags (void)
 }
 
 
-/* This function initializes the main memory pool MAINPOOL.  Itis
+/* This function initializes the main memory pool MAINPOOL.  It is
  * expected to be called with the secmem lock held.  */
 static void
 _gcry_secmem_init_internal (size_t n)
@@ -634,11 +664,18 @@ _gcry_secmem_malloc_internal (size_t size, int xhint)
       return &mb->aligned.c;
     }
 
-  /* If we are called from xmalloc style function resort to the
+  /* If we are called from xmalloc style functions resort to the
    * overflow pools to return memory.  We don't do this in FIPS mode,
-   * though. */
+   * though.  If the auto-expand option is active we do the expanding
+   * also for the standard malloc functions.
+   *
+   * The idea of using them by default only for the xmalloc function
+   * is so that a user can control whether memory will be allocated in
+   * the initial created mlock protected secmem area or may also be
+   * allocated from the overflow pools.  */
   if ((xhint || auto_expand) && !fips_mode ())
     {
+      /* Check whether we can allocate from the overflow pools.  */
       for (pool = pool->next; pool; pool = pool->next)
         {
           mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
@@ -670,8 +707,12 @@ _gcry_secmem_malloc_internal (size_t size, int xhint)
       pool->okay = 1;
 
       /* Take care: in _gcry_private_is_secure we do not lock and thus
-       * we assume that the second assignment below is atomic.  */
+       * we assume that the second assignment below is atomic.  Memory
+       * barrier prevents reordering of stores to new pool structure after
+       * MAINPOOL.NEXT assigment and prevents _gcry_private_is_secure seeing
+       * non-initialized POOL->NEXT pointers.  */
       pool->next = mainpool.next;
+      memory_barrier();
       mainpool.next = pool;
 
       /* After the first time we allocated an overflow pool, print a
@@ -811,9 +852,13 @@ _gcry_private_is_secure (const void *p)
 {
   pooldesc_t *pool;
 
-  /* We do no lock here because once a pool is allocatred it will not
-   * be removed anymore (except for gcry_secmem_term).  Further,
-   * adding a new pool to the list should be atomic.  */
+  /* We do no lock here because once a pool is allocated it will not
+   * be removed anymore (except for gcry_secmem_term).  Further, as
+   * assigment of POOL->NEXT in new pool structure is visible in
+   * this thread before assigment of MAINPOOL.NEXT, pool list can be
+   * iterated locklessly.  This visiblity is ensured by memory barrier
+   * between POOL->NEXT and MAINPOOL.NEXT assignments in
+   * _gcry_secmem_malloc_internal. */
   for (pool = &mainpool; pool; pool = pool->next)
     if (pool->okay && ptr_into_pool_p (pool, p))
       return 1;
@@ -869,12 +914,19 @@ _gcry_secmem_term ()
 void
 _gcry_secmem_dump_stats (int extended)
 {
+  SECMEM_LOCK;
+  secmem_dump_stats_internal (extended);
+  SECMEM_UNLOCK;
+}
+
+
+static void
+secmem_dump_stats_internal (int extended)
+{
   pooldesc_t *pool;
   memblock_t *mb;
   int i, poolno;
 
-  SECMEM_LOCK;
-
   for (pool = &mainpool, poolno = 0; pool; pool = pool->next, poolno++)
     {
       if (!extended)
@@ -897,5 +949,4 @@ _gcry_secmem_dump_stats (int extended)
                       mb->size);
         }
     }
-  SECMEM_UNLOCK;
 }
index f2a164c..864916b 100644 (file)
@@ -1112,8 +1112,9 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
   const char *disphint = NULL;
   const char *percent = NULL;
   int hexcount = 0;
+  int b64count = 0;
   int quoted_esc = 0;
-  int datalen = 0;
+  size_t datalen = 0;
   size_t dummy_erroff;
   struct make_space_ctx c;
   int arg_counter = 0;
@@ -1327,9 +1328,61 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
            }
        }
       else if (base64)
-       {
-         if (*p == '|')
-           base64 = NULL;
+        {
+          if (digitp (p) || alphap (p) || *p == '+' || *p == '/' || *p == '=')
+            b64count++;
+          else if (*p == '|')
+            {
+              gpgrt_b64state_t b64state;
+              char *b64buf;
+              int i;
+
+              base64++;         /* Skip beginning '|' */
+              b64buf = xtrymalloc (b64count);
+              if (!b64buf)
+                {
+                  err = gpg_err_code_from_syserror ();
+                  goto leave;
+                }
+              memcpy (b64buf, base64, b64count);
+
+              b64state = gpgrt_b64dec_start (NULL);
+              if (!b64state)
+                {
+                  err = gpg_err_code_from_syserror ();
+                  xfree (b64buf);
+                  goto leave;
+                }
+              err = gpgrt_b64dec_proc (b64state, b64buf, b64count,
+                                       &datalen);
+              if (err && gpg_err_code (err) != GPG_ERR_EOF)
+                {
+                  xfree (b64state);
+                  xfree (b64buf);
+                  goto leave;
+                }
+              err = gpgrt_b64dec_finish (b64state);
+              if (err)
+                {
+                  xfree (b64buf);
+                  goto leave;
+                }
+
+              MAKE_SPACE (datalen);
+              *c.pos++ = ST_DATA;
+              STORE_LEN (c.pos, datalen);
+              for (i = 0; i < datalen; i++)
+                *c.pos++ = b64buf[i];
+
+              xfree (b64buf);
+              base64 = NULL;
+            }
+          else
+            {
+              *erroff = p - buffer;
+              err = GPG_ERR_SEXP_BAD_CHARACTER;
+              goto leave;
+            }
        }
       else if (digptr)
        {
@@ -1367,11 +1420,12 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
              hexfmt = p;
              hexcount = 0;
            }
-         else if (*p == '|')
-           {
-             digptr = NULL; /* We ignore the optional length.  */
-             base64 = p;
-           }
+          else if (*p == '|')
+            {
+              digptr = NULL; /* We ignore the optional length.  */
+              base64 = p;
+              b64count = 0;
+            }
          else
            {
              *erroff = p - buffer;
@@ -1429,6 +1483,12 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
                 }
               else
                 {
+                  if (mpifmt == GCRYMPI_FMT_USG && mpi_cmp_ui (m, 0) < 0)
+                    {
+                      err = GPG_ERR_INV_ARG;
+                      goto leave;
+                    }
+
                   err = _gcry_mpi_print (mpifmt, NULL, 0, &nm, m);
                   if (err)
                     goto leave;
@@ -1487,6 +1547,13 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
              ARG_NEXT (alen, int);
              ARG_NEXT (astr, const char *);
 
+              if (alen < 0)
+                {
+                  *erroff = p - buffer;
+                 err = GPG_ERR_INV_ARG;
+                  goto leave;
+                }
+
              MAKE_SPACE (alen);
              if (alen
                   && !_gcry_is_secure (c.sexp->d)
@@ -1616,7 +1683,10 @@ do_vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
          hexcount = 0;
        }
       else if (*p == '|')
-       base64 = p;
+        {
+          base64 = p;
+          b64count = 0;
+        }
       else if (*p == '[')
        {
          if (disphint)
@@ -2182,11 +2252,18 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
  * names of these parameters are given by the string LIST.  Some
  * special characters may be given to control the conversion:
  *
- *    + :: Switch to unsigned integer format (default).
- *    - :: Switch to standard signed format.
- *    / :: Switch to opaque format.
- *    & :: Switch to buffer descriptor mode - see below.
- *    ? :: The previous parameter is optional.
+ *   +   :: Switch to unsigned integer format (default).
+ *   -   :: Switch to standard signed format.
+ *   /   :: Switch to opaque format
+ *   &   :: Switch to buffer descriptor mode - see below.
+ *   %s  :: Switch to allocated string arguments.
+ *   %#s :: Switch to allocated string arguments for a list of string flags.
+ *   %u  :: Switch to unsigned integer arguments.
+ *   %lu :: Switch to unsigned long integer arguments.
+ *   %zu :: Switch to size_t arguments.
+ *   %d  :: Switch to signed integer arguments.
+ *   %ld :: Switch to signed long integer arguments.
+ *   ?   :: The previous parameter is optional.
  *
  * In general parameter names are single letters.  To use a string for
  * a parameter name, enclose the name in single quotes.
@@ -2213,6 +2290,9 @@ _gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
  * is too small, the function immediately returns with an error code
  * (and LEN set to 0).
  *
+ * For a flag list ("%#s") which has other lists as elements these
+ * sub-lists are skipped and a indicated by "()" in the output.
+ *
  * PATH is an optional string used to locate a token.  The exclamation
  * mark separated tokens are used to via gcry_sexp_find_token to find
  * a start point inside SEXP.
@@ -2229,13 +2309,22 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
 {
   gpg_err_code_t rc;
   const char *s, *s2;
-  gcry_mpi_t *array[20];
+  void **array[20];
   char arrayisdesc[20];
-  int idx;
+  int idx, i;
   gcry_sexp_t l1 = NULL;
   int mode = '+'; /* Default to GCRYMPI_FMT_USG.  */
+  int submode = 0;
   gcry_sexp_t freethis = NULL;
-
+  char *tmpstr = NULL;
+
+  /* Values in ARRAYISDESC describing what the ARRAY holds.
+   *  0  - MPI
+   *  1  - gcry_buffer_t provided by caller.
+   *  2  - gcry_buffer_t allocated by us.
+   * 's' - String allocated by us.
+   * 'x' - Ignore
+   */
   memset (arrayisdesc, 0, sizeof arrayisdesc);
 
   /* First copy all the args into an array.  This is required so that
@@ -2245,6 +2334,17 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
     {
       if (*s == '&' || *s == '+' || *s == '-' || *s == '/' || *s == '?')
         ;
+      else if (*s == '%')
+        {
+          s++;
+          if (*s == 'l' && (s[1] == 'u' || s[1] == 'd'))
+            s++;
+          else if (*s == 'z' && s[1] == 'u')
+            s++;
+          else if (*s == '#' && s[1] == 's')
+            s++;
+          continue;
+        }
       else if (whitespacep (s))
         ;
       else
@@ -2260,7 +2360,7 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
                 }
               s = s2;
             }
-          array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
+          array[idx] = va_arg (arg_ptr, void *);
           if (!array[idx])
             return GPG_ERR_MISSING_VALUE; /* NULL pointer given.  */
           idx++;
@@ -2304,6 +2404,36 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
     {
       if (*s == '&' || *s == '+' || *s == '-' || *s == '/')
         mode = *s;
+      else if (*s == '%')
+        {
+          s++;
+          if (!*s)
+            continue;  /* Ignore at end of format.  */
+          if (*s == 's' || *s == 'd' || *s == 'u')
+            {
+              mode = *s;
+              submode = 0;
+            }
+          else if (*s == 'l' && (s[1] == 'u' || s[1] == 'd'))
+            {
+              mode = s[1];
+              submode = 'l';
+              s++;
+            }
+          else if (*s == 'z' && s[1] == 'u')
+            {
+              mode = s[1];
+              submode = 'z';
+              s++;
+            }
+          else if (*s == '#' && s[1] == 's')
+            {
+              mode = s[1];
+              submode = '#';
+              s++;
+            }
+          continue;
+        }
       else if (whitespacep (s))
         ;
       else if (*s == '?')
@@ -2340,6 +2470,29 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
                     }
                   spec->len = 0;
                 }
+              else if (mode == 's')
+                {
+                  *array[idx] = NULL;
+                  arrayisdesc[idx] = 's';
+                }
+              else if (mode == 'd')
+                {
+                  if (submode == 'l')
+                    *(long *)array[idx] = 0;
+                  else
+                    *(int *)array[idx] = 0;
+                  arrayisdesc[idx] = 'x';
+                }
+              else if (mode == 'u')
+                {
+                  if (submode == 'l')
+                    *(unsigned long *)array[idx] = 0;
+                  else if (submode == 'z')
+                    *(size_t *)array[idx] = 0;
+                  else
+                    *(unsigned int *)array[idx] = 0;
+                  arrayisdesc[idx] = 'x';
+                }
               else
                 *array[idx] = NULL;
             }
@@ -2387,27 +2540,118 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
                       arrayisdesc[idx] = 2;
                     }
                 }
-              else if (mode == '/')
-                *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
-              else if (mode == '-')
-                *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_STD);
+              else if (mode == 's')
+                {
+                  if (submode == '#')
+                    {
+                      size_t needed = 0;
+                      size_t n;
+                      int l1len;
+                      char *p;
+
+                      l1len = l1? sexp_length (l1) : 0;
+                      for (i = 1; i < l1len; i++)
+                        {
+                          s2 = sexp_nth_data (l1, i, &n);
+                          if (!s2)
+                            n = 2; /* Not a data element; we use "()". */
+                          needed += n + 1;
+                        }
+                      if (!needed)
+                        {
+                          *array[idx] = p = xtrymalloc (1);
+                          if (p)
+                            *p = 0;
+                        }
+                      else if ((*array[idx] = p = xtrymalloc (needed)))
+                        {
+                          for (i = 1; i < l1len; i++)
+                            {
+                              s2 = sexp_nth_data (l1, i, &n);
+                              if (!s2)
+                                memcpy (p, "()", (n=2));
+                              else
+                                memcpy (p, s2, n);
+                              p[n] = ' ';
+                              p += n + 1;
+                            }
+                          if (p != *array[idx])
+                            p[-1] = 0;
+                        }
+                    }
+                  else
+                    *array[idx] = _gcry_sexp_nth_string (l1, 1);
+                  if (!*array[idx])
+                    {
+                      rc = gpg_err_code_from_syserror ();
+                      goto cleanup;
+                    }
+                  arrayisdesc[idx] = 's';
+                }
+              else if (mode == 'd')
+                {
+                  long along;
+
+                  xfree (tmpstr);
+                  tmpstr = _gcry_sexp_nth_string (l1, 1);
+                  if (!tmpstr)
+                    {
+                      rc = gpg_err_code_from_syserror ();
+                      goto cleanup;
+                    }
+                  along = strtol (tmpstr, NULL, 10);
+                  if (submode == 'l')
+                    *(long *)array[idx] = along;
+                  else
+                    *(int *)array[idx] = along;
+                  arrayisdesc[idx] = 'x';
+                }
+              else if (mode == 'u')
+                {
+                  long aulong;
+
+                  xfree (tmpstr);
+                  tmpstr = _gcry_sexp_nth_string (l1, 1);
+                  if (!tmpstr)
+                    {
+                      rc = gpg_err_code_from_syserror ();
+                      goto cleanup;
+                    }
+                  aulong = strtoul (tmpstr, NULL, 10);
+                  if (submode == 'l')
+                    *(unsigned long *)array[idx] = aulong;
+                  else if (submode == 'z')
+                    *(size_t *)array[idx] = aulong;
+                  else
+                    *(unsigned int *)array[idx] = aulong;
+                  arrayisdesc[idx] = 'x';
+                }
               else
-                *array[idx] = _gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
-              sexp_release (l1); l1 = NULL;
-              if (!*array[idx])
                 {
-                  rc = GPG_ERR_INV_OBJ;  /* Conversion failed.  */
-                  goto cleanup;
+                  if (mode == '/')
+                    *array[idx] = _gcry_sexp_nth_mpi (l1,1,GCRYMPI_FMT_OPAQUE);
+                  else if (mode == '-')
+                    *array[idx] = _gcry_sexp_nth_mpi (l1,1,GCRYMPI_FMT_STD);
+                  else
+                    *array[idx] = _gcry_sexp_nth_mpi (l1,1,GCRYMPI_FMT_USG);
+                  if (!*array[idx])
+                    {
+                      rc = GPG_ERR_INV_OBJ;  /* Conversion failed.  */
+                      goto cleanup;
+                    }
                 }
+              sexp_release (l1); l1 = NULL;
             }
           idx++;
         }
     }
 
+  xfree (tmpstr);
   sexp_release (freethis);
   return 0;
 
  cleanup:
+  xfree (tmpstr);
   sexp_release (freethis);
   sexp_release (l1);
   while (idx--)
@@ -2423,7 +2667,7 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
           gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
           spec->len = 0;
         }
-      else
+      else if (arrayisdesc[idx] == 2)
         {
           /* We might have allocated a buffer.  */
           gcry_buffer_t *spec = (gcry_buffer_t*)array[idx];
@@ -2431,6 +2675,12 @@ _gcry_sexp_vextract_param (gcry_sexp_t sexp, const char *path,
           spec->data = NULL;
           spec->size = spec->off = spec->len = 0;
         }
+      else if (arrayisdesc[idx] == 's')
+        {
+          /* We might have allocated a buffer.  */
+          xfree (*array[idx]);
+          *array[idx] = NULL;
+        }
      }
   return rc;
 }
index cbda8d8..04ce64f 100644 (file)
@@ -224,19 +224,23 @@ void
 _gcry_private_free (void *a)
 {
   unsigned char *p = a;
+  unsigned char *freep;
 
   if (!p)
     return;
-  if (use_m_guard )
+  if (use_m_guard)
     {
-      _gcry_private_check_heap(p);
-      if (! _gcry_secmem_free (p - EXTRA_ALIGN - 4))
-        {
-          free (p - EXTRA_ALIGN - 4);
-       }
+      _gcry_private_check_heap (p);
+      freep = p - EXTRA_ALIGN - 4;
+    }
+  else
+    {
+      freep = p;
     }
-  else if (!_gcry_secmem_free (p))
+
+  if (!_gcry_private_is_secure (freep) ||
+      !_gcry_secmem_free (freep))
     {
-      free(p);
+      free (freep);
     }
 }
index 645ddd6..b4f28bc 100644 (file)
 
 
 
-#ifndef HAVE_BYTE_TYPEDEF
+#ifndef HAVE_TYPE_BYTE
 # undef byte   /* In case there is a macro with that name.  */
 # if !(defined(_WIN32) && defined(cbNDRContext))
    /* Windows typedefs byte in the rpc headers.  Avoid warning about
       double definition.  */
    typedef unsigned char byte;
 # endif
-# define HAVE_BYTE_TYPEDEF
+# define HAVE_TYPE_BYTE
 #endif
 
-#ifndef HAVE_USHORT_TYPEDEF
+#ifndef HAVE_TYPE_USHORT
 # undef ushort  /* In case there is a macro with that name.  */
   typedef unsigned short ushort;
-# define HAVE_USHORT_TYPEDEF
+# define HAVE_TYPE_USHORT
 #endif
 
-#ifndef HAVE_ULONG_TYPEDEF
-# undef ulong   /* In case there is a macro with that name.  */
-  typedef unsigned long ulong;
-# define HAVE_ULONG_TYPEDEF
-#endif
-
-#ifndef HAVE_U16_TYPEDEF
+#ifndef HAVE_TYPE_U16
 # undef u16    /* In case there is a macro with that name.  */
 # if SIZEOF_UNSIGNED_INT == 2
    typedef unsigned int   u16;
 # else
 #  error no typedef for u16
 # endif
-# define HAVE_U16_TYPEDEF
+# define HAVE_TYPE_U16
 #endif
 
-#ifndef HAVE_U32_TYPEDEF
+#ifndef HAVE_TYPE_U32
 # undef u32    /* In case there is a macro with that name.  */
 # if SIZEOF_UNSIGNED_INT == 4
    typedef unsigned int  u32;
@@ -97,7 +91,7 @@
 # else
 #  error no typedef for u32
 # endif
-# define HAVE_U32_TYPEDEF
+# define HAVE_TYPE_U32
 #endif
 
 /*
  * the dummy code in cipher/md.c is not available.  Examples are
  * Solaris and IRIX.
  */
-#ifndef HAVE_U64_TYPEDEF
+#ifndef HAVE_TYPE_U64
 # undef u64    /* In case there is a macro with that name.  */
-# if SIZEOF_UNSIGNED_INT == 8
+# if SIZEOF_UINT64_T == 8
+   typedef uint64_t u64;
+#  define U64_C(c) (UINT64_C(c))
+#  define HAVE_TYPE_U64
+# elif SIZEOF_UNSIGNED_INT == 8
    typedef unsigned int u64;
 #  define U64_C(c) (c ## U)
-#  define HAVE_U64_TYPEDEF
+#  define HAVE_TYPE_U64
 # elif SIZEOF_UNSIGNED_LONG == 8
    typedef unsigned long u64;
 #  define U64_C(c) (c ## UL)
-#  define HAVE_U64_TYPEDEF
+#  define HAVE_TYPE_U64
 # elif SIZEOF_UNSIGNED_LONG_LONG == 8
    typedef unsigned long long u64;
 #  define U64_C(c) (c ## ULL)
-#  define HAVE_U64_TYPEDEF
-# elif SIZEOF_UINT64_T == 8
-   typedef uint64_t u64;
-#  define U64_C(c) (UINT64_C(c))
-#  define HAVE_U64_TYPEDEF
+#  define HAVE_TYPE_U64
 # else
 #  error No way to declare a 64 bit integer type
 # endif
index ea06612..6b588ed 100644 (file)
@@ -39,7 +39,7 @@ BEGIN
             VALUE "FileDescription", "Libgcrypt - The GNU Crypto Library\0"
             VALUE "FileVersion", "@LIBGCRYPT_LT_CURRENT@.@LIBGCRYPT_LT_AGE@.@LIBGCRYPT_LT_REVISION@.@BUILD_REVISION@\0"
             VALUE "InternalName", "libgcrypt\0"
-            VALUE "LegalCopyright", "Copyright © 2018 Free Software Foundation, Inc.\0"
+            VALUE "LegalCopyright", "Copyright © 2022 g10 Code GmbH\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "libgcrypt.dll\0"
             VALUE "PrivateBuild", "\0"
index 104c70d..c98247d 100644 (file)
@@ -26,6 +26,7 @@
 #include "cipher-proto.h"
 #include "context.h"
 #include "mpi.h"
+#include "ec-context.h"
 
 const char *
 gcry_strerror (gcry_error_t err)
@@ -308,7 +309,7 @@ gcry_mpi_set_ui (gcry_mpi_t w, unsigned long u)
 }
 
 gcry_error_t
-gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
+gcry_mpi_get_ui (unsigned int *w, gcry_mpi_t u)
 {
   return gpg_error (_gcry_mpi_get_ui (w, u));
 }
@@ -570,23 +571,47 @@ gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_point_t point,
 void
 gcry_mpi_ec_dup (gcry_mpi_point_t w, gcry_mpi_point_t u, gcry_ctx_t ctx)
 {
-  _gcry_mpi_ec_dup_point (w, u, _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
+  mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+
+  if (ec->model == MPI_EC_EDWARDS || ec->model == MPI_EC_MONTGOMERY)
+    {
+      mpi_point_resize (w, ec);
+      mpi_point_resize (u, ec);
+    }
+
+  _gcry_mpi_ec_dup_point (w, u, ec);
 }
 
 void
 gcry_mpi_ec_add (gcry_mpi_point_t w,
                  gcry_mpi_point_t u, gcry_mpi_point_t v, gcry_ctx_t ctx)
 {
-  _gcry_mpi_ec_add_points (w, u, v,
-                           _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
+  mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+
+  if (ec->model == MPI_EC_EDWARDS || ec->model == MPI_EC_MONTGOMERY)
+    {
+      mpi_point_resize (w, ec);
+      mpi_point_resize (u, ec);
+      mpi_point_resize (v, ec);
+    }
+
+  _gcry_mpi_ec_add_points (w, u, v, ec);
 }
 
 void
 gcry_mpi_ec_sub (gcry_mpi_point_t w,
                  gcry_mpi_point_t u, gcry_mpi_point_t v, gcry_ctx_t ctx)
 {
-  _gcry_mpi_ec_sub_points (w, u, v,
-                           _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC));
+  mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+
+  if (ec->model == MPI_EC_EDWARDS || ec->model == MPI_EC_MONTGOMERY)
+    {
+      mpi_point_resize (w, ec);
+      mpi_point_resize (u, ec);
+      mpi_point_resize (v, ec);
+    }
+
+  _gcry_mpi_ec_sub_points (w, u, v, ec);
 }
 
 void
@@ -898,7 +923,7 @@ gcry_mac_get_algo_keylen (int algo)
 
 gcry_error_t
 gcry_mac_open (gcry_mac_hd_t *handle, int algo, unsigned int flags,
-              gcry_ctx_t ctx)
+               gcry_ctx_t ctx)
 {
   if (!fips_is_operational ())
     {
@@ -1003,6 +1028,13 @@ gcry_pk_sign (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t skey)
 }
 
 gcry_error_t
+gcry_pk_hash_sign (gcry_sexp_t *result, const char *data_tmpl, gcry_sexp_t skey,
+                   gcry_md_hd_t hd, gcry_ctx_t ctx)
+{
+  return gpg_error (_gcry_pk_sign_md (result, data_tmpl, hd, skey, ctx));
+}
+
+gcry_error_t
 gcry_pk_verify (gcry_sexp_t sigval, gcry_sexp_t data, gcry_sexp_t pkey)
 {
   if (!fips_is_operational ())
@@ -1011,6 +1043,19 @@ gcry_pk_verify (gcry_sexp_t sigval, gcry_sexp_t data, gcry_sexp_t pkey)
 }
 
 gcry_error_t
+gcry_pk_hash_verify (gcry_sexp_t sigval, const char *data_tmpl, gcry_sexp_t pkey,
+                     gcry_md_hd_t hd, gcry_ctx_t ctx)
+{
+  return gpg_error (_gcry_pk_verify_md (sigval, data_tmpl, hd, pkey, ctx));
+}
+
+gcry_error_t
+gcry_pk_random_override_new (gcry_ctx_t *r_ctx, const unsigned char *p, size_t len)
+{
+  return gpg_error (_gcry_pk_random_override_new (r_ctx, p, len));
+}
+
+gcry_error_t
 gcry_pk_testkey (gcry_sexp_t key)
 {
   if (!fips_is_operational ())
@@ -1112,6 +1157,19 @@ gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx)
   return gpg_error (_gcry_pubkey_get_sexp (r_sexp, mode, ctx));
 }
 
+unsigned int
+gcry_ecc_get_algo_keylen (int curveid)
+{
+  return _gcry_ecc_get_algo_keylen (curveid);
+}
+
+gpg_error_t
+gcry_ecc_mul_point (int curveid, unsigned char *result,
+                    const unsigned char *scalar, const unsigned char *point)
+{
+  return _gcry_ecc_mul_point (curveid, result, scalar, point);
+}
+
 gcry_error_t
 gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
 {
@@ -1294,11 +1352,50 @@ gcry_kdf_derive (const void *passphrase, size_t passphraselen,
                  unsigned long iterations,
                  size_t keysize, void *keybuffer)
 {
+  if (!fips_is_operational ())
+    return gpg_error (fips_not_operational ());
   return gpg_error (_gcry_kdf_derive (passphrase, passphraselen, algo, hashalgo,
                                       salt, saltlen, iterations,
                                       keysize, keybuffer));
 }
 
+gpg_error_t
+gcry_kdf_open (gcry_kdf_hd_t *hd, int algo, int subalgo,
+               const unsigned long *param, unsigned int paramlen,
+               const void *passphrase, size_t passphraselen,
+               const void *salt, size_t saltlen,
+               const void *key, size_t keylen,
+               const void *ad, size_t adlen)
+{
+  if (!fips_is_operational ())
+    return gpg_error (fips_not_operational ());
+  return gpg_error (_gcry_kdf_open (hd, algo, subalgo, param, paramlen,
+                                    passphrase, passphraselen, salt, saltlen,
+                                    key, keylen, ad, adlen));
+}
+
+gcry_error_t
+gcry_kdf_compute (gcry_kdf_hd_t h, const struct gcry_kdf_thread_ops *ops)
+{
+  if (!fips_is_operational ())
+    return gpg_error (fips_not_operational ());
+  return gpg_error (_gcry_kdf_compute (h, ops));
+}
+
+gcry_error_t
+gcry_kdf_final (gcry_kdf_hd_t h, size_t resultlen, void *result)
+{
+  if (!fips_is_operational ())
+    return gpg_error (fips_not_operational ());
+  return gpg_error (_gcry_kdf_final (h, resultlen, result));
+}
+
+void
+gcry_kdf_close (gcry_kdf_hd_t h)
+{
+  _gcry_kdf_close (h);
+}
+
 void
 gcry_randomize (void *buffer, size_t length, enum gcry_random_level level)
 {
@@ -1349,6 +1446,13 @@ void
 gcry_mpi_randomize (gcry_mpi_t w,
                     unsigned int nbits, enum gcry_random_level level)
 {
+  if (!fips_is_operational ())
+    {
+      (void)fips_not_operational ();
+      fips_signal_fatal_error ("called in non-operational state");
+      fips_noreturn ();
+    }
+
   _gcry_mpi_randomize (w, nbits, level);
 }
 
@@ -1374,6 +1478,8 @@ gcry_prime_generate (gcry_mpi_t *prime,
                      gcry_random_level_t random_level,
                      unsigned int flags)
 {
+  if (!fips_is_operational ())
+    return gpg_error (fips_not_operational ());
   return gpg_error (_gcry_prime_generate (prime, prime_bits, factor_bits,
                                           factors, cb_func, cb_arg,
                                           random_level, flags));
@@ -1384,6 +1490,8 @@ gcry_prime_group_generator (gcry_mpi_t *r_g,
                             gcry_mpi_t prime, gcry_mpi_t *factors,
                             gcry_mpi_t start_g)
 {
+  if (!fips_is_operational ())
+    return gpg_error (fips_not_operational ());
   return gpg_error (_gcry_prime_group_generator (r_g, prime, factors, start_g));
 }
 
index df2caf6..14bf624 100644 (file)
@@ -165,8 +165,17 @@ MARK_VISIBLEX (gcry_pk_sign)
 MARK_VISIBLEX (gcry_pk_testkey)
 MARK_VISIBLEX (gcry_pk_verify)
 MARK_VISIBLEX (gcry_pubkey_get_sexp)
+MARK_VISIBLEX (gcry_ecc_get_algo_keylen)
+MARK_VISIBLEX (gcry_ecc_mul_point)
+MARK_VISIBLEX (gcry_pk_hash_sign)
+MARK_VISIBLEX (gcry_pk_hash_verify)
+MARK_VISIBLEX (gcry_pk_random_override_new)
 
 MARK_VISIBLEX (gcry_kdf_derive)
+MARK_VISIBLEX (gcry_kdf_open)
+MARK_VISIBLEX (gcry_kdf_compute)
+MARK_VISIBLEX (gcry_kdf_final)
+MARK_VISIBLEX (gcry_kdf_close)
 
 MARK_VISIBLEX (gcry_prime_check)
 MARK_VISIBLEX (gcry_prime_generate)
@@ -265,6 +274,7 @@ MARK_VISIBLEX (gcry_mpi_set_highbit)
 MARK_VISIBLEX (gcry_mpi_set_opaque)
 MARK_VISIBLEX (gcry_mpi_set_opaque_copy)
 MARK_VISIBLEX (gcry_mpi_set_ui)
+MARK_VISIBLEX (gcry_mpi_get_ui)
 MARK_VISIBLEX (gcry_mpi_snew)
 MARK_VISIBLEX (gcry_mpi_sub)
 MARK_VISIBLEX (gcry_mpi_sub_ui)
@@ -361,6 +371,11 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
 #define gcry_pk_testkey             _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_pk_verify              _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_pubkey_get_sexp        _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_ecc_get_algo_keylen    _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_ecc_mul_point          _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_pk_hash_sign           _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_pk_hash_verify         _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_pk_random_override_new _gcry_USE_THE_UNDERSCORED_FUNCTION
 
 #define gcry_md_algo_info           _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_md_algo_name           _gcry_USE_THE_UNDERSCORED_FUNCTION
@@ -401,6 +416,10 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
 #define gcry_mac_ctl                _gcry_USE_THE_UNDERSCORED_FUNCTION
 
 #define gcry_kdf_derive             _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_kdf_open               _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_kdf_compute            _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_kdf_final              _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_kdf_close              _gcry_USE_THE_UNDERSCORED_FUNCTION
 
 #define gcry_prime_check            _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_prime_generate         _gcry_USE_THE_UNDERSCORED_FUNCTION
@@ -484,6 +503,7 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
 #define gcry_mpi_set_highbit        _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_set_opaque         _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_set_ui             _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_mpi_get_ui             _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_snatch             _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_snew               _gcry_USE_THE_UNDERSCORED_FUNCTION
 #define gcry_mpi_sub                _gcry_USE_THE_UNDERSCORED_FUNCTION
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
index eee24fa..e6953fd 100644 (file)
 
 ## Process this file with automake to produce Makefile.in
 
+# Note: Please keep these tests in sync with those in testdrv.c.
+# We will eventually switch over to the the new driver but as of now
+# the driver is only used for cross-compiling.
 tests_bin = \
         version t-secmem mpitests t-sexp t-convert \
        t-mpi-bit t-mpi-point curves t-lock \
        prime basic keygen pubkey hmac hashtest t-kdf keygrip \
-       fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 t-ed25519 t-cv25519
+       fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 \
+       t-dsa t-ecdsa t-rsa-pss t-rsa-15 \
+       t-ed25519 t-cv25519 t-x448 t-ed448
 
 tests_bin_last = benchmark bench-slope
 
@@ -47,21 +52,67 @@ AM_CFLAGS = $(GPG_ERROR_CFLAGS)
 AM_LDFLAGS = -no-install
 
 standard_ldadd = \
-       ../src/libgcrypt.la $(DL_LIBS) \
+       ../src/libgcrypt.la \
         ../compat/libcompat.la
 
 EXTRA_PROGRAMS = testapi pkbench
-noinst_PROGRAMS = $(tests_bin) $(tests_bin_last) fipsdrv rsacvt genhashdata \
-                 gchash
+noinst_PROGRAMS = testdrv $(tests_bin) $(tests_bin_last) \
+                  fipsdrv rsacvt genhashdata gchash
 noinst_HEADERS = t-common.h
 
-EXTRA_DIST = README rsa-16k.key cavs_tests.sh cavs_driver.pl \
+CLEANFILES = testdrv-build
+
+EXTRA_DIST = README rsa-16k.key \
             pkcs1v2-oaep.h pkcs1v2-pss.h pkcs1v2-v15c.h pkcs1v2-v15s.h \
-            t-ed25519.inp stopwatch.h hashtest-256g.in \
-            sha3-224.h sha3-256.h sha3-384.h sha3-512.h \
-            blake2b.h blake2s.h \
+            t-ed25519.inp t-ed448.inp t-dsa.inp t-ecdsa.inp t-rsa-15.inp \
+            t-rsa-pss.inp stopwatch.h hashtest-256g.in sha3-224.h \
+            sha3-256.h sha3-384.h sha3-512.h blake2b.h blake2s.h \
             basic-disable-all-hwf.in basic_all_hwfeature_combinations.sh
 
-LDADD = $(standard_ldadd) $(GPG_ERROR_LIBS)
-t_lock_LDADD = $(standard_ldadd) $(GPG_ERROR_MT_LIBS)
+LDADD = $(standard_ldadd) $(GPG_ERROR_LIBS) @LDADD_FOR_TESTS_KLUDGE@
+pkbench_LDADD = $(standard_ldadd) @LDADD_FOR_TESTS_KLUDGE@
+prime_LDADD = $(standard_ldadd) @LDADD_FOR_TESTS_KLUDGE@
+t_mpi_bit_LDADD = $(standard_ldadd) @LDADD_FOR_TESTS_KLUDGE@
+t_secmem_LDADD = $(standard_ldadd) @LDADD_FOR_TESTS_KLUDGE@
+testapi_LDADD = $(standard_ldadd) @LDADD_FOR_TESTS_KLUDGE@
+t_lock_LDADD = $(standard_ldadd) $(GPG_ERROR_MT_LIBS) @LDADD_FOR_TESTS_KLUDGE@
 t_lock_CFLAGS = $(GPG_ERROR_MT_CFLAGS)
+testdrv_LDADD = $(LDADD_FOR_TESTS_KLUDGE)
+
+# Build a version of the test driver for the build platform.
+testdrv-build: testdrv.c
+       $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \
+         $(CPPFLAGS_FOR_BUILD) -DTESTDRV_EXEEXT=\"$(EXEEXT)\" \
+          -o $@ $(srcdir)/testdrv.c
+
+if HAVE_W32_SYSTEM
+xtestsuite_libs = ../src/.libs/libgcrypt-20.dll \
+                  $(prefix)/bin/libgpg-error*-0.dll
+xtestsuite_driver = .libs/testdrv.exe
+t_kdf_LDADD = $(standard_ldadd) $(GPG_ERROR_LIBS) @LDADD_FOR_TESTS_KLUDGE@
+t_kdf_CFLAGS = $(GPG_ERROR_CFLAGS)
+else
+xtestsuite_libs = ../src/.libs/libgcrypt.so*
+xtestsuite_driver = testdrv
+t_kdf_LDADD = $(standard_ldadd) $(GPG_ERROR_MT_LIBS) @LDADD_FOR_TESTS_KLUDGE@
+t_kdf_CFLAGS = $(GPG_ERROR_MT_CFLAGS)
+endif
+
+# xcheck uses our new testdrv instead of the automake test runner.
+.PHONY: xcheck xtestsuite
+xcheck: testdrv$(EXEEXT)
+       srcdir=$(srcdir) ./testdrv$(EXEEXT) --verbose
+
+# Make a tarballs with all the tests.
+xtestsuite: testdrv$(EXEEXT) testdrv-build $(TESTS)
+       +(set -e; \
+         name="$(PACKAGE_TARNAME)-tests-$(PACKAGE_VERSION)";\
+        xname="$$name/$(host)" ;\
+        rm -rf $$name; mkdir $$name ; mkdir $$xname ;\
+        cp -L $(xtestsuite_driver) \
+           $$(srcdir=$(srcdir) ./testdrv-build --files|sort|uniq) $$xname/ ;\
+         cp -P $(xtestsuite_libs) $$xname/ ;\
+        touch $$xname/libgcrypt-standalone-tests ;\
+         $(AMTAR) czf "$(PACKAGE_TARNAME)-tests-$(PACKAGE_VERSION)".tar.gz \
+             $$name ;\
+        )
diff --git a/tests/Makefile.in b/tests/Makefile.in
deleted file mode 100644 (file)
index 9dc0244..0000000
+++ /dev/null
@@ -1,1115 +0,0 @@
-# Makefile.in generated by automake 1.14.1 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
-
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
-#
-# 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, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-
-VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
-am__make_running_with_option = \
-  case $${target_option-} in \
-      ?) ;; \
-      *) echo "am__make_running_with_option: internal error: invalid" \
-              "target option '$${target_option-}' specified" >&2; \
-         exit 1;; \
-  esac; \
-  has_opt=no; \
-  sane_makeflags=$$MAKEFLAGS; \
-  if $(am__is_gnu_make); then \
-    sane_makeflags=$$MFLAGS; \
-  else \
-    case $$MAKEFLAGS in \
-      *\\[\ \  ]*) \
-        bs=\\; \
-        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
-          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
-    esac; \
-  fi; \
-  skip_next=no; \
-  strip_trailopt () \
-  { \
-    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
-  }; \
-  for flg in $$sane_makeflags; do \
-    test $$skip_next = yes && { skip_next=no; continue; }; \
-    case $$flg in \
-      *=*|--*) continue;; \
-        -*I) strip_trailopt 'I'; skip_next=yes;; \
-      -*I?*) strip_trailopt 'I';; \
-        -*O) strip_trailopt 'O'; skip_next=yes;; \
-      -*O?*) strip_trailopt 'O';; \
-        -*l) strip_trailopt 'l'; skip_next=yes;; \
-      -*l?*) strip_trailopt 'l';; \
-      -[dEDm]) skip_next=yes;; \
-      -[JT]) skip_next=yes;; \
-    esac; \
-    case $$flg in \
-      *$$target_option*) has_opt=yes; break;; \
-    esac; \
-  done; \
-  test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
-pkgdatadir = $(datadir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkglibexecdir = $(libexecdir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-TESTS = $(am__EXEEXT_1) $(tests_sh) $(am__EXEEXT_2) $(tests_sh_last)
-EXTRA_PROGRAMS = testapi$(EXEEXT) pkbench$(EXEEXT)
-noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) fipsdrv$(EXEEXT) \
-       rsacvt$(EXEEXT) genhashdata$(EXEEXT) gchash$(EXEEXT)
-subdir = tests
-DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
-       $(srcdir)/hashtest-256g.in $(srcdir)/basic-disable-all-hwf.in \
-       $(top_srcdir)/build-aux/depcomp $(noinst_HEADERS) README
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gpg-error.m4 \
-       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
-       $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
-       $(top_srcdir)/m4/lt~obsolete.m4 \
-       $(top_srcdir)/m4/noexecstack.m4 $(top_srcdir)/m4/onceonly.m4 \
-       $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sys_socket_h.m4 \
-       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
-       $(ACLOCAL_M4)
-mkinstalldirs = $(install_sh) -d
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES = hashtest-256g basic-disable-all-hwf
-CONFIG_CLEAN_VPATH_FILES =
-am__EXEEXT_1 = version$(EXEEXT) t-secmem$(EXEEXT) mpitests$(EXEEXT) \
-       t-sexp$(EXEEXT) t-convert$(EXEEXT) t-mpi-bit$(EXEEXT) \
-       t-mpi-point$(EXEEXT) curves$(EXEEXT) t-lock$(EXEEXT) \
-       prime$(EXEEXT) basic$(EXEEXT) keygen$(EXEEXT) pubkey$(EXEEXT) \
-       hmac$(EXEEXT) hashtest$(EXEEXT) t-kdf$(EXEEXT) \
-       keygrip$(EXEEXT) fips186-dsa$(EXEEXT) aeswrap$(EXEEXT) \
-       pkcs1v2$(EXEEXT) random$(EXEEXT) dsa-rfc6979$(EXEEXT) \
-       t-ed25519$(EXEEXT) t-cv25519$(EXEEXT)
-am__EXEEXT_2 = benchmark$(EXEEXT) bench-slope$(EXEEXT)
-PROGRAMS = $(noinst_PROGRAMS)
-aeswrap_SOURCES = aeswrap.c
-aeswrap_OBJECTS = aeswrap.$(OBJEXT)
-aeswrap_LDADD = $(LDADD)
-am__DEPENDENCIES_1 =
-am__DEPENDENCIES_2 = ../src/libgcrypt.la $(am__DEPENDENCIES_1) \
-       ../compat/libcompat.la
-aeswrap_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-AM_V_lt = $(am__v_lt_@AM_V@)
-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
-am__v_lt_0 = --silent
-am__v_lt_1 = 
-basic_SOURCES = basic.c
-basic_OBJECTS = basic.$(OBJEXT)
-basic_LDADD = $(LDADD)
-basic_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-bench_slope_SOURCES = bench-slope.c
-bench_slope_OBJECTS = bench-slope.$(OBJEXT)
-bench_slope_LDADD = $(LDADD)
-bench_slope_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-benchmark_SOURCES = benchmark.c
-benchmark_OBJECTS = benchmark.$(OBJEXT)
-benchmark_LDADD = $(LDADD)
-benchmark_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-curves_SOURCES = curves.c
-curves_OBJECTS = curves.$(OBJEXT)
-curves_LDADD = $(LDADD)
-curves_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-dsa_rfc6979_SOURCES = dsa-rfc6979.c
-dsa_rfc6979_OBJECTS = dsa-rfc6979.$(OBJEXT)
-dsa_rfc6979_LDADD = $(LDADD)
-dsa_rfc6979_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-fips186_dsa_SOURCES = fips186-dsa.c
-fips186_dsa_OBJECTS = fips186-dsa.$(OBJEXT)
-fips186_dsa_LDADD = $(LDADD)
-fips186_dsa_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-fipsdrv_SOURCES = fipsdrv.c
-fipsdrv_OBJECTS = fipsdrv.$(OBJEXT)
-fipsdrv_LDADD = $(LDADD)
-fipsdrv_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-gchash_SOURCES = gchash.c
-gchash_OBJECTS = gchash.$(OBJEXT)
-gchash_LDADD = $(LDADD)
-gchash_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-genhashdata_SOURCES = genhashdata.c
-genhashdata_OBJECTS = genhashdata.$(OBJEXT)
-genhashdata_LDADD = $(LDADD)
-genhashdata_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-hashtest_SOURCES = hashtest.c
-hashtest_OBJECTS = hashtest.$(OBJEXT)
-hashtest_LDADD = $(LDADD)
-hashtest_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-hmac_SOURCES = hmac.c
-hmac_OBJECTS = hmac.$(OBJEXT)
-hmac_LDADD = $(LDADD)
-hmac_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-keygen_SOURCES = keygen.c
-keygen_OBJECTS = keygen.$(OBJEXT)
-keygen_LDADD = $(LDADD)
-keygen_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-keygrip_SOURCES = keygrip.c
-keygrip_OBJECTS = keygrip.$(OBJEXT)
-keygrip_LDADD = $(LDADD)
-keygrip_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-mpitests_SOURCES = mpitests.c
-mpitests_OBJECTS = mpitests.$(OBJEXT)
-mpitests_LDADD = $(LDADD)
-mpitests_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-pkbench_SOURCES = pkbench.c
-pkbench_OBJECTS = pkbench.$(OBJEXT)
-pkbench_LDADD = $(LDADD)
-pkbench_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-pkcs1v2_SOURCES = pkcs1v2.c
-pkcs1v2_OBJECTS = pkcs1v2.$(OBJEXT)
-pkcs1v2_LDADD = $(LDADD)
-pkcs1v2_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-prime_SOURCES = prime.c
-prime_OBJECTS = prime.$(OBJEXT)
-prime_LDADD = $(LDADD)
-prime_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-pubkey_SOURCES = pubkey.c
-pubkey_OBJECTS = pubkey.$(OBJEXT)
-pubkey_LDADD = $(LDADD)
-pubkey_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-random_SOURCES = random.c
-random_OBJECTS = random.$(OBJEXT)
-random_LDADD = $(LDADD)
-random_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-rsacvt_SOURCES = rsacvt.c
-rsacvt_OBJECTS = rsacvt.$(OBJEXT)
-rsacvt_LDADD = $(LDADD)
-rsacvt_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_convert_SOURCES = t-convert.c
-t_convert_OBJECTS = t-convert.$(OBJEXT)
-t_convert_LDADD = $(LDADD)
-t_convert_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_cv25519_SOURCES = t-cv25519.c
-t_cv25519_OBJECTS = t-cv25519.$(OBJEXT)
-t_cv25519_LDADD = $(LDADD)
-t_cv25519_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_ed25519_SOURCES = t-ed25519.c
-t_ed25519_OBJECTS = t-ed25519.$(OBJEXT)
-t_ed25519_LDADD = $(LDADD)
-t_ed25519_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_kdf_SOURCES = t-kdf.c
-t_kdf_OBJECTS = t-kdf.$(OBJEXT)
-t_kdf_LDADD = $(LDADD)
-t_kdf_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_lock_SOURCES = t-lock.c
-t_lock_OBJECTS = t_lock-t-lock.$(OBJEXT)
-t_lock_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_lock_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(t_lock_CFLAGS) $(CFLAGS) \
-       $(AM_LDFLAGS) $(LDFLAGS) -o $@
-t_mpi_bit_SOURCES = t-mpi-bit.c
-t_mpi_bit_OBJECTS = t-mpi-bit.$(OBJEXT)
-t_mpi_bit_LDADD = $(LDADD)
-t_mpi_bit_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_mpi_point_SOURCES = t-mpi-point.c
-t_mpi_point_OBJECTS = t-mpi-point.$(OBJEXT)
-t_mpi_point_LDADD = $(LDADD)
-t_mpi_point_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_secmem_SOURCES = t-secmem.c
-t_secmem_OBJECTS = t-secmem.$(OBJEXT)
-t_secmem_LDADD = $(LDADD)
-t_secmem_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-t_sexp_SOURCES = t-sexp.c
-t_sexp_OBJECTS = t-sexp.$(OBJEXT)
-t_sexp_LDADD = $(LDADD)
-t_sexp_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-testapi_SOURCES = testapi.c
-testapi_OBJECTS = testapi.$(OBJEXT)
-testapi_LDADD = $(LDADD)
-testapi_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-version_SOURCES = version.c
-version_OBJECTS = version.$(OBJEXT)
-version_LDADD = $(LDADD)
-version_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
-AM_V_P = $(am__v_P_@AM_V@)
-am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
-am__v_P_0 = false
-am__v_P_1 = :
-AM_V_GEN = $(am__v_GEN_@AM_V@)
-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
-am__v_GEN_0 = @echo "  GEN     " $@;
-am__v_GEN_1 = 
-AM_V_at = $(am__v_at_@AM_V@)
-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
-am__v_at_0 = @
-am__v_at_1 = 
-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
-am__depfiles_maybe = depfiles
-am__mv = mv -f
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
-       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
-       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
-       $(AM_CFLAGS) $(CFLAGS)
-AM_V_CC = $(am__v_CC_@AM_V@)
-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
-am__v_CC_0 = @echo "  CC      " $@;
-am__v_CC_1 = 
-CCLD = $(CC)
-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
-       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
-       $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
-am__v_CCLD_0 = @echo "  CCLD    " $@;
-am__v_CCLD_1 = 
-SOURCES = aeswrap.c basic.c bench-slope.c benchmark.c curves.c \
-       dsa-rfc6979.c fips186-dsa.c fipsdrv.c gchash.c genhashdata.c \
-       hashtest.c hmac.c keygen.c keygrip.c mpitests.c pkbench.c \
-       pkcs1v2.c prime.c pubkey.c random.c rsacvt.c t-convert.c \
-       t-cv25519.c t-ed25519.c t-kdf.c t-lock.c t-mpi-bit.c \
-       t-mpi-point.c t-secmem.c t-sexp.c testapi.c version.c
-DIST_SOURCES = aeswrap.c basic.c bench-slope.c benchmark.c curves.c \
-       dsa-rfc6979.c fips186-dsa.c fipsdrv.c gchash.c genhashdata.c \
-       hashtest.c hmac.c keygen.c keygrip.c mpitests.c pkbench.c \
-       pkcs1v2.c prime.c pubkey.c random.c rsacvt.c t-convert.c \
-       t-cv25519.c t-ed25519.c t-kdf.c t-lock.c t-mpi-bit.c \
-       t-mpi-point.c t-secmem.c t-sexp.c testapi.c version.c
-am__can_run_installinfo = \
-  case $$AM_UPDATE_INFO_DIR in \
-    n|no|NO) false;; \
-    *) (install-info --version) >/dev/null 2>&1;; \
-  esac
-HEADERS = $(noinst_HEADERS)
-am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
-# Read a list of newline-separated strings from the standard input,
-# and print each of them once, without duplicates.  Input order is
-# *not* preserved.
-am__uniquify_input = $(AWK) '\
-  BEGIN { nonempty = 0; } \
-  { items[$$0] = 1; nonempty = 1; } \
-  END { if (nonempty) { for (i in items) print i; }; } \
-'
-# Make sure the list of sources is unique.  This is necessary because,
-# e.g., the same source file might be shared among _SOURCES variables
-# for different programs/libraries.
-am__define_uniq_tagged_files = \
-  list='$(am__tagged_files)'; \
-  unique=`for i in $$list; do \
-    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
-  done | $(am__uniquify_input)`
-ETAGS = etags
-CTAGS = ctags
-am__tty_colors_dummy = \
-  mgn= red= grn= lgn= blu= brg= std=; \
-  am__color_tests=no
-am__tty_colors = { \
-  $(am__tty_colors_dummy); \
-  if test "X$(AM_COLOR_TESTS)" = Xno; then \
-    am__color_tests=no; \
-  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
-    am__color_tests=yes; \
-  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
-    am__color_tests=yes; \
-  fi; \
-  if test $$am__color_tests = yes; then \
-    red='\e[0;31m'; \
-    grn='\e[0;32m'; \
-    lgn='\e[1;32m'; \
-    blu='\e[1;34m'; \
-    mgn='\e[0;35m'; \
-    brg='\e[1m'; \
-    std='\e[m'; \
-  fi; \
-}
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
-AR = @AR@
-AS = @AS@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-BUILD_FILEVERSION = @BUILD_FILEVERSION@
-BUILD_REVISION = @BUILD_REVISION@
-BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
-CC = @CC@
-CCAS = @CCAS@
-CCASDEPMODE = @CCASDEPMODE@
-CCASFLAGS = @CCASFLAGS@
-CCDEPMODE = @CCDEPMODE@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-DLLTOOL = @DLLTOOL@
-DL_LIBS = @DL_LIBS@
-DSYMUTIL = @DSYMUTIL@
-DUMPBIN = @DUMPBIN@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-FALLBACK_SOCKLEN_T = @FALLBACK_SOCKLEN_T@
-FGREP = @FGREP@
-GCRYPT_CIPHERS = @GCRYPT_CIPHERS@
-GCRYPT_DIGESTS = @GCRYPT_DIGESTS@
-GCRYPT_HWF_MODULES = @GCRYPT_HWF_MODULES@
-GCRYPT_KDFS = @GCRYPT_KDFS@
-GCRYPT_PUBKEY_CIPHERS = @GCRYPT_PUBKEY_CIPHERS@
-GCRYPT_RANDOM = @GCRYPT_RANDOM@
-GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
-GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
-GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
-GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
-GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
-GREP = @GREP@
-INSERT_SYS_SELECT_H = @INSERT_SYS_SELECT_H@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-LD = @LD@
-LDFLAGS = @LDFLAGS@
-LIBGCRYPT_CIPHERS = @LIBGCRYPT_CIPHERS@
-LIBGCRYPT_CONFIG_API_VERSION = @LIBGCRYPT_CONFIG_API_VERSION@
-LIBGCRYPT_CONFIG_CFLAGS = @LIBGCRYPT_CONFIG_CFLAGS@
-LIBGCRYPT_CONFIG_HOST = @LIBGCRYPT_CONFIG_HOST@
-LIBGCRYPT_CONFIG_LIBS = @LIBGCRYPT_CONFIG_LIBS@
-LIBGCRYPT_DIGESTS = @LIBGCRYPT_DIGESTS@
-LIBGCRYPT_LT_AGE = @LIBGCRYPT_LT_AGE@
-LIBGCRYPT_LT_CURRENT = @LIBGCRYPT_LT_CURRENT@
-LIBGCRYPT_LT_REVISION = @LIBGCRYPT_LT_REVISION@
-LIBGCRYPT_PUBKEY_CIPHERS = @LIBGCRYPT_PUBKEY_CIPHERS@
-LIBGCRYPT_THREAD_MODULES = @LIBGCRYPT_THREAD_MODULES@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LIBTOOL = @LIBTOOL@
-LIPO = @LIPO@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MANIFEST_TOOL = @MANIFEST_TOOL@
-MKDIR_P = @MKDIR_P@
-MPI_SFLAGS = @MPI_SFLAGS@
-NM = @NM@
-NMEDIT = @NMEDIT@
-NOEXECSTACK_FLAGS = @NOEXECSTACK_FLAGS@
-OBJDUMP = @OBJDUMP@
-OBJEXT = @OBJEXT@
-OTOOL = @OTOOL@
-OTOOL64 = @OTOOL64@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_URL = @PACKAGE_URL@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PTH_CFLAGS = @PTH_CFLAGS@
-PTH_CONFIG = @PTH_CONFIG@
-PTH_LIBS = @PTH_LIBS@
-RANLIB = @RANLIB@
-RC = @RC@
-RUN_LARGE_DATA_TESTS = @RUN_LARGE_DATA_TESTS@
-SED = @SED@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-SYSROOT = @SYSROOT@
-SYS_SOCKET_H = @SYS_SOCKET_H@
-VERSION = @VERSION@
-VERSION_NUMBER = @VERSION_NUMBER@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_AR = @ac_ct_AR@
-ac_ct_CC = @ac_ct_CC@
-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-emacs_local_vars_begin = @emacs_local_vars_begin@
-emacs_local_vars_end = @emacs_local_vars_end@
-emacs_local_vars_read_only = @emacs_local_vars_read_only@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-htmldir = @htmldir@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_build_prefix = @top_build_prefix@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-tests_bin = \
-        version t-secmem mpitests t-sexp t-convert \
-       t-mpi-bit t-mpi-point curves t-lock \
-       prime basic keygen pubkey hmac hashtest t-kdf keygrip \
-       fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 t-ed25519 t-cv25519
-
-tests_bin_last = benchmark bench-slope
-tests_sh = basic-disable-all-hwf
-tests_sh_last = hashtest-256g
-TESTS_ENVIRONMENT = GCRYPT_IN_REGRESSION_TEST=1
-
-# Need to include ../src in addition to top_srcdir because gcrypt.h is
-# a built header.
-AM_CPPFLAGS = -I../src -I$(top_srcdir)/src
-AM_CFLAGS = $(GPG_ERROR_CFLAGS)
-AM_LDFLAGS = -no-install
-standard_ldadd = \
-       ../src/libgcrypt.la $(DL_LIBS) \
-        ../compat/libcompat.la
-
-noinst_HEADERS = t-common.h
-EXTRA_DIST = README rsa-16k.key cavs_tests.sh cavs_driver.pl \
-            pkcs1v2-oaep.h pkcs1v2-pss.h pkcs1v2-v15c.h pkcs1v2-v15s.h \
-            t-ed25519.inp stopwatch.h hashtest-256g.in \
-            sha3-224.h sha3-256.h sha3-384.h sha3-512.h \
-            blake2b.h blake2s.h \
-            basic-disable-all-hwf.in basic_all_hwfeature_combinations.sh
-
-LDADD = $(standard_ldadd) $(GPG_ERROR_LIBS)
-t_lock_LDADD = $(standard_ldadd) $(GPG_ERROR_MT_LIBS)
-t_lock_CFLAGS = $(GPG_ERROR_MT_CFLAGS)
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .lo .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
-       @for dep in $?; do \
-         case '$(am__configure_deps)' in \
-           *$$dep*) \
-             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
-               && { if test -f $@; then exit 0; else break; fi; }; \
-             exit 1;; \
-         esac; \
-       done; \
-       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \
-       $(am__cd) $(top_srcdir) && \
-         $(AUTOMAKE) --gnu tests/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
-       @case '$?' in \
-         *config.status*) \
-           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
-         *) \
-           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
-           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
-       esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
-       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(am__aclocal_m4_deps):
-hashtest-256g: $(top_builddir)/config.status $(srcdir)/hashtest-256g.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-basic-disable-all-hwf: $(top_builddir)/config.status $(srcdir)/basic-disable-all-hwf.in
-       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-
-clean-noinstPROGRAMS:
-       @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
-       echo " rm -f" $$list; \
-       rm -f $$list || exit $$?; \
-       test -n "$(EXEEXT)" || exit 0; \
-       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
-       echo " rm -f" $$list; \
-       rm -f $$list
-
-aeswrap$(EXEEXT): $(aeswrap_OBJECTS) $(aeswrap_DEPENDENCIES) $(EXTRA_aeswrap_DEPENDENCIES) 
-       @rm -f aeswrap$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(aeswrap_OBJECTS) $(aeswrap_LDADD) $(LIBS)
-
-basic$(EXEEXT): $(basic_OBJECTS) $(basic_DEPENDENCIES) $(EXTRA_basic_DEPENDENCIES) 
-       @rm -f basic$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(basic_OBJECTS) $(basic_LDADD) $(LIBS)
-
-bench-slope$(EXEEXT): $(bench_slope_OBJECTS) $(bench_slope_DEPENDENCIES) $(EXTRA_bench_slope_DEPENDENCIES) 
-       @rm -f bench-slope$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(bench_slope_OBJECTS) $(bench_slope_LDADD) $(LIBS)
-
-benchmark$(EXEEXT): $(benchmark_OBJECTS) $(benchmark_DEPENDENCIES) $(EXTRA_benchmark_DEPENDENCIES) 
-       @rm -f benchmark$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(benchmark_OBJECTS) $(benchmark_LDADD) $(LIBS)
-
-curves$(EXEEXT): $(curves_OBJECTS) $(curves_DEPENDENCIES) $(EXTRA_curves_DEPENDENCIES) 
-       @rm -f curves$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(curves_OBJECTS) $(curves_LDADD) $(LIBS)
-
-dsa-rfc6979$(EXEEXT): $(dsa_rfc6979_OBJECTS) $(dsa_rfc6979_DEPENDENCIES) $(EXTRA_dsa_rfc6979_DEPENDENCIES) 
-       @rm -f dsa-rfc6979$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(dsa_rfc6979_OBJECTS) $(dsa_rfc6979_LDADD) $(LIBS)
-
-fips186-dsa$(EXEEXT): $(fips186_dsa_OBJECTS) $(fips186_dsa_DEPENDENCIES) $(EXTRA_fips186_dsa_DEPENDENCIES) 
-       @rm -f fips186-dsa$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(fips186_dsa_OBJECTS) $(fips186_dsa_LDADD) $(LIBS)
-
-fipsdrv$(EXEEXT): $(fipsdrv_OBJECTS) $(fipsdrv_DEPENDENCIES) $(EXTRA_fipsdrv_DEPENDENCIES) 
-       @rm -f fipsdrv$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(fipsdrv_OBJECTS) $(fipsdrv_LDADD) $(LIBS)
-
-gchash$(EXEEXT): $(gchash_OBJECTS) $(gchash_DEPENDENCIES) $(EXTRA_gchash_DEPENDENCIES) 
-       @rm -f gchash$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(gchash_OBJECTS) $(gchash_LDADD) $(LIBS)
-
-genhashdata$(EXEEXT): $(genhashdata_OBJECTS) $(genhashdata_DEPENDENCIES) $(EXTRA_genhashdata_DEPENDENCIES) 
-       @rm -f genhashdata$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(genhashdata_OBJECTS) $(genhashdata_LDADD) $(LIBS)
-
-hashtest$(EXEEXT): $(hashtest_OBJECTS) $(hashtest_DEPENDENCIES) $(EXTRA_hashtest_DEPENDENCIES) 
-       @rm -f hashtest$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(hashtest_OBJECTS) $(hashtest_LDADD) $(LIBS)
-
-hmac$(EXEEXT): $(hmac_OBJECTS) $(hmac_DEPENDENCIES) $(EXTRA_hmac_DEPENDENCIES) 
-       @rm -f hmac$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(hmac_OBJECTS) $(hmac_LDADD) $(LIBS)
-
-keygen$(EXEEXT): $(keygen_OBJECTS) $(keygen_DEPENDENCIES) $(EXTRA_keygen_DEPENDENCIES) 
-       @rm -f keygen$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(keygen_OBJECTS) $(keygen_LDADD) $(LIBS)
-
-keygrip$(EXEEXT): $(keygrip_OBJECTS) $(keygrip_DEPENDENCIES) $(EXTRA_keygrip_DEPENDENCIES) 
-       @rm -f keygrip$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(keygrip_OBJECTS) $(keygrip_LDADD) $(LIBS)
-
-mpitests$(EXEEXT): $(mpitests_OBJECTS) $(mpitests_DEPENDENCIES) $(EXTRA_mpitests_DEPENDENCIES) 
-       @rm -f mpitests$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(mpitests_OBJECTS) $(mpitests_LDADD) $(LIBS)
-
-pkbench$(EXEEXT): $(pkbench_OBJECTS) $(pkbench_DEPENDENCIES) $(EXTRA_pkbench_DEPENDENCIES) 
-       @rm -f pkbench$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(pkbench_OBJECTS) $(pkbench_LDADD) $(LIBS)
-
-pkcs1v2$(EXEEXT): $(pkcs1v2_OBJECTS) $(pkcs1v2_DEPENDENCIES) $(EXTRA_pkcs1v2_DEPENDENCIES) 
-       @rm -f pkcs1v2$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(pkcs1v2_OBJECTS) $(pkcs1v2_LDADD) $(LIBS)
-
-prime$(EXEEXT): $(prime_OBJECTS) $(prime_DEPENDENCIES) $(EXTRA_prime_DEPENDENCIES) 
-       @rm -f prime$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(prime_OBJECTS) $(prime_LDADD) $(LIBS)
-
-pubkey$(EXEEXT): $(pubkey_OBJECTS) $(pubkey_DEPENDENCIES) $(EXTRA_pubkey_DEPENDENCIES) 
-       @rm -f pubkey$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(pubkey_OBJECTS) $(pubkey_LDADD) $(LIBS)
-
-random$(EXEEXT): $(random_OBJECTS) $(random_DEPENDENCIES) $(EXTRA_random_DEPENDENCIES) 
-       @rm -f random$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(random_OBJECTS) $(random_LDADD) $(LIBS)
-
-rsacvt$(EXEEXT): $(rsacvt_OBJECTS) $(rsacvt_DEPENDENCIES) $(EXTRA_rsacvt_DEPENDENCIES) 
-       @rm -f rsacvt$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(rsacvt_OBJECTS) $(rsacvt_LDADD) $(LIBS)
-
-t-convert$(EXEEXT): $(t_convert_OBJECTS) $(t_convert_DEPENDENCIES) $(EXTRA_t_convert_DEPENDENCIES) 
-       @rm -f t-convert$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(t_convert_OBJECTS) $(t_convert_LDADD) $(LIBS)
-
-t-cv25519$(EXEEXT): $(t_cv25519_OBJECTS) $(t_cv25519_DEPENDENCIES) $(EXTRA_t_cv25519_DEPENDENCIES) 
-       @rm -f t-cv25519$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(t_cv25519_OBJECTS) $(t_cv25519_LDADD) $(LIBS)
-
-t-ed25519$(EXEEXT): $(t_ed25519_OBJECTS) $(t_ed25519_DEPENDENCIES) $(EXTRA_t_ed25519_DEPENDENCIES) 
-       @rm -f t-ed25519$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(t_ed25519_OBJECTS) $(t_ed25519_LDADD) $(LIBS)
-
-t-kdf$(EXEEXT): $(t_kdf_OBJECTS) $(t_kdf_DEPENDENCIES) $(EXTRA_t_kdf_DEPENDENCIES) 
-       @rm -f t-kdf$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(t_kdf_OBJECTS) $(t_kdf_LDADD) $(LIBS)
-
-t-lock$(EXEEXT): $(t_lock_OBJECTS) $(t_lock_DEPENDENCIES) $(EXTRA_t_lock_DEPENDENCIES) 
-       @rm -f t-lock$(EXEEXT)
-       $(AM_V_CCLD)$(t_lock_LINK) $(t_lock_OBJECTS) $(t_lock_LDADD) $(LIBS)
-
-t-mpi-bit$(EXEEXT): $(t_mpi_bit_OBJECTS) $(t_mpi_bit_DEPENDENCIES) $(EXTRA_t_mpi_bit_DEPENDENCIES) 
-       @rm -f t-mpi-bit$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(t_mpi_bit_OBJECTS) $(t_mpi_bit_LDADD) $(LIBS)
-
-t-mpi-point$(EXEEXT): $(t_mpi_point_OBJECTS) $(t_mpi_point_DEPENDENCIES) $(EXTRA_t_mpi_point_DEPENDENCIES) 
-       @rm -f t-mpi-point$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(t_mpi_point_OBJECTS) $(t_mpi_point_LDADD) $(LIBS)
-
-t-secmem$(EXEEXT): $(t_secmem_OBJECTS) $(t_secmem_DEPENDENCIES) $(EXTRA_t_secmem_DEPENDENCIES) 
-       @rm -f t-secmem$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(t_secmem_OBJECTS) $(t_secmem_LDADD) $(LIBS)
-
-t-sexp$(EXEEXT): $(t_sexp_OBJECTS) $(t_sexp_DEPENDENCIES) $(EXTRA_t_sexp_DEPENDENCIES) 
-       @rm -f t-sexp$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(t_sexp_OBJECTS) $(t_sexp_LDADD) $(LIBS)
-
-testapi$(EXEEXT): $(testapi_OBJECTS) $(testapi_DEPENDENCIES) $(EXTRA_testapi_DEPENDENCIES) 
-       @rm -f testapi$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(testapi_OBJECTS) $(testapi_LDADD) $(LIBS)
-
-version$(EXEEXT): $(version_OBJECTS) $(version_DEPENDENCIES) $(EXTRA_version_DEPENDENCIES) 
-       @rm -f version$(EXEEXT)
-       $(AM_V_CCLD)$(LINK) $(version_OBJECTS) $(version_LDADD) $(LIBS)
-
-mostlyclean-compile:
-       -rm -f *.$(OBJEXT)
-
-distclean-compile:
-       -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aeswrap.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bench-slope.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/benchmark.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curves.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsa-rfc6979.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fips186-dsa.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fipsdrv.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gchash.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genhashdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashtest.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hmac.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygen.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygrip.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpitests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkbench.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs1v2.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prime.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pubkey.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsacvt.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-convert.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-cv25519.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-ed25519.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-kdf.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-mpi-bit.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-mpi-point.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-secmem.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-sexp.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_lock-t-lock.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testapi.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
-
-.c.obj:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-
-t_lock-t-lock.o: t-lock.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_lock_CFLAGS) $(CFLAGS) -MT t_lock-t-lock.o -MD -MP -MF $(DEPDIR)/t_lock-t-lock.Tpo -c -o t_lock-t-lock.o `test -f 't-lock.c' || echo '$(srcdir)/'`t-lock.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/t_lock-t-lock.Tpo $(DEPDIR)/t_lock-t-lock.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='t-lock.c' object='t_lock-t-lock.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_lock_CFLAGS) $(CFLAGS) -c -o t_lock-t-lock.o `test -f 't-lock.c' || echo '$(srcdir)/'`t-lock.c
-
-t_lock-t-lock.obj: t-lock.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_lock_CFLAGS) $(CFLAGS) -MT t_lock-t-lock.obj -MD -MP -MF $(DEPDIR)/t_lock-t-lock.Tpo -c -o t_lock-t-lock.obj `if test -f 't-lock.c'; then $(CYGPATH_W) 't-lock.c'; else $(CYGPATH_W) '$(srcdir)/t-lock.c'; fi`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/t_lock-t-lock.Tpo $(DEPDIR)/t_lock-t-lock.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='t-lock.c' object='t_lock-t-lock.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(t_lock_CFLAGS) $(CFLAGS) -c -o t_lock-t-lock.obj `if test -f 't-lock.c'; then $(CYGPATH_W) 't-lock.c'; else $(CYGPATH_W) '$(srcdir)/t-lock.c'; fi`
-
-mostlyclean-libtool:
-       -rm -f *.lo
-
-clean-libtool:
-       -rm -rf .libs _libs
-
-ID: $(am__tagged_files)
-       $(am__define_uniq_tagged_files); mkid -fID $$unique
-tags: tags-am
-TAGS: tags
-
-tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       set x; \
-       here=`pwd`; \
-       $(am__define_uniq_tagged_files); \
-       shift; \
-       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
-         test -n "$$unique" || unique=$$empty_fix; \
-         if test $$# -gt 0; then \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             "$$@" $$unique; \
-         else \
-           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
-             $$unique; \
-         fi; \
-       fi
-ctags: ctags-am
-
-CTAGS: ctags
-ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
-       $(am__define_uniq_tagged_files); \
-       test -z "$(CTAGS_ARGS)$$unique" \
-         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
-            $$unique
-
-GTAGS:
-       here=`$(am__cd) $(top_builddir) && pwd` \
-         && $(am__cd) $(top_srcdir) \
-         && gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: cscopelist-am
-
-cscopelist-am: $(am__tagged_files)
-       list='$(am__tagged_files)'; \
-       case "$(srcdir)" in \
-         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
-         *) sdir=$(subdir)/$(srcdir) ;; \
-       esac; \
-       for i in $$list; do \
-         if test -f "$$i"; then \
-           echo "$(subdir)/$$i"; \
-         else \
-           echo "$$sdir/$$i"; \
-         fi; \
-       done >> $(top_builddir)/cscope.files
-
-distclean-tags:
-       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-check-TESTS: $(TESTS)
-       @failed=0; all=0; xfail=0; xpass=0; skip=0; \
-       srcdir=$(srcdir); export srcdir; \
-       list=' $(TESTS) '; \
-       $(am__tty_colors); \
-       if test -n "$$list"; then \
-         for tst in $$list; do \
-           if test -f ./$$tst; then dir=./; \
-           elif test -f $$tst; then dir=; \
-           else dir="$(srcdir)/"; fi; \
-           if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
-             all=`expr $$all + 1`; \
-             case " $(XFAIL_TESTS) " in \
-             *[\ \     ]$$tst[\ \      ]*) \
-               xpass=`expr $$xpass + 1`; \
-               failed=`expr $$failed + 1`; \
-               col=$$red; res=XPASS; \
-             ;; \
-             *) \
-               col=$$grn; res=PASS; \
-             ;; \
-             esac; \
-           elif test $$? -ne 77; then \
-             all=`expr $$all + 1`; \
-             case " $(XFAIL_TESTS) " in \
-             *[\ \     ]$$tst[\ \      ]*) \
-               xfail=`expr $$xfail + 1`; \
-               col=$$lgn; res=XFAIL; \
-             ;; \
-             *) \
-               failed=`expr $$failed + 1`; \
-               col=$$red; res=FAIL; \
-             ;; \
-             esac; \
-           else \
-             skip=`expr $$skip + 1`; \
-             col=$$blu; res=SKIP; \
-           fi; \
-           echo "$${col}$$res$${std}: $$tst"; \
-         done; \
-         if test "$$all" -eq 1; then \
-           tests="test"; \
-           All=""; \
-         else \
-           tests="tests"; \
-           All="All "; \
-         fi; \
-         if test "$$failed" -eq 0; then \
-           if test "$$xfail" -eq 0; then \
-             banner="$$All$$all $$tests passed"; \
-           else \
-             if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
-             banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
-           fi; \
-         else \
-           if test "$$xpass" -eq 0; then \
-             banner="$$failed of $$all $$tests failed"; \
-           else \
-             if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
-             banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
-           fi; \
-         fi; \
-         dashes="$$banner"; \
-         skipped=""; \
-         if test "$$skip" -ne 0; then \
-           if test "$$skip" -eq 1; then \
-             skipped="($$skip test was not run)"; \
-           else \
-             skipped="($$skip tests were not run)"; \
-           fi; \
-           test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
-             dashes="$$skipped"; \
-         fi; \
-         report=""; \
-         if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
-           report="Please report to $(PACKAGE_BUGREPORT)"; \
-           test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
-             dashes="$$report"; \
-         fi; \
-         dashes=`echo "$$dashes" | sed s/./=/g`; \
-         if test "$$failed" -eq 0; then \
-           col="$$grn"; \
-         else \
-           col="$$red"; \
-         fi; \
-         echo "$${col}$$dashes$${std}"; \
-         echo "$${col}$$banner$${std}"; \
-         test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
-         test -z "$$report" || echo "$${col}$$report$${std}"; \
-         echo "$${col}$$dashes$${std}"; \
-         test "$$failed" -eq 0; \
-       else :; fi
-
-distdir: $(DISTFILES)
-       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
-       list='$(DISTFILES)'; \
-         dist_files=`for file in $$list; do echo $$file; done | \
-         sed -e "s|^$$srcdirstrip/||;t" \
-             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
-       case $$dist_files in \
-         */*) $(MKDIR_P) `echo "$$dist_files" | \
-                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
-                          sort -u` ;; \
-       esac; \
-       for file in $$dist_files; do \
-         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
-         if test -d $$d/$$file; then \
-           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
-           if test -d "$(distdir)/$$file"; then \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
-             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
-             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
-           fi; \
-           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
-         else \
-           test -f "$(distdir)/$$file" \
-           || cp -p $$d/$$file "$(distdir)/$$file" \
-           || exit 1; \
-         fi; \
-       done
-check-am: all-am
-       $(MAKE) $(AM_MAKEFLAGS) check-TESTS
-check: check-am
-all-am: Makefile $(PROGRAMS) $(HEADERS)
-installdirs:
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
-       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
-       if test -z '$(STRIP)'; then \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-             install; \
-       else \
-         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
-           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
-           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
-       fi
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
-       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
-
-maintainer-clean-generic:
-       @echo "This command is intended for maintainers to use"
-       @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
-       mostlyclean-am
-
-distclean: distclean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
-       distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-html-am:
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-dvi-am:
-
-install-exec-am:
-
-install-html: install-html-am
-
-install-html-am:
-
-install-info: install-info-am
-
-install-info-am:
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-pdf-am:
-
-install-ps: install-ps-am
-
-install-ps-am:
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
-       -rm -rf ./$(DEPDIR)
-       -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am:
-
-.MAKE: check-am install-am install-strip
-
-.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
-       clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \
-       ctags ctags-am distclean distclean-compile distclean-generic \
-       distclean-libtool distclean-tags distdir dvi dvi-am html \
-       html-am info info-am install install-am install-data \
-       install-data-am install-dvi install-dvi-am install-exec \
-       install-exec-am install-html install-html-am install-info \
-       install-info-am install-man install-pdf install-pdf-am \
-       install-ps install-ps-am install-strip installcheck \
-       installcheck-am installdirs maintainer-clean \
-       maintainer-clean-generic mostlyclean mostlyclean-compile \
-       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
-       tags tags-am uninstall uninstall-am
-
-
-# Force sequential run of some tests.
-bench-slope.log:    benchmark.log
-hashtest-256g.log:  bench-slope.log
-
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
index 90add11..ed4453b 100644 (file)
 
 
 static void
-check (int algo,
-       const void *kek, size_t keklen,
-       const void *data, size_t datalen,
-       const void *expected, size_t expectedlen)
+check_one (int algo,
+           const void *kek, size_t keklen,
+           const void *data, size_t datalen,
+           const void *expected, size_t expectedlen,
+           int inplace)
 {
   gcry_error_t err;
   gcry_cipher_hd_t hd;
@@ -57,9 +58,19 @@ check (int algo,
 
   outbuflen = datalen + 8;
   if (outbuflen > sizeof outbuf)
-    err = gpg_error (GPG_ERR_INTERNAL);
+    {
+      err = gpg_error (GPG_ERR_INTERNAL);
+    }
+  else if (inplace)
+    {
+      memcpy (outbuf, data, datalen);
+      err = gcry_cipher_encrypt (hd, outbuf, outbuflen, outbuf, datalen);
+    }
   else
-    err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, datalen);
+    {
+      err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, datalen);
+    }
+
   if (err)
     {
       fail ("gcry_cipher_encrypt failed: %s\n", gpg_strerror (err));
@@ -71,7 +82,7 @@ check (int algo,
       const unsigned char *s;
       int i;
 
-      fail ("mismatch at encryption!\n");
+      fail ("mismatch at encryption!%s\n", inplace ? " (inplace)" : "");
       fprintf (stderr, "computed: ");
       for (i = 0; i < outbuflen; i++)
        fprintf (stderr, "%02x ", outbuf[i]);
@@ -84,9 +95,19 @@ check (int algo,
 
   outbuflen = expectedlen - 8;
   if (outbuflen > sizeof outbuf)
-    err = gpg_error (GPG_ERR_INTERNAL);
+    {
+      err = gpg_error (GPG_ERR_INTERNAL);
+    }
+  else if (inplace)
+    {
+      memcpy (outbuf, expected, expectedlen);
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, outbuf, expectedlen);
+    }
   else
-    err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+    {
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+    }
+
   if (err)
     {
       fail ("gcry_cipher_decrypt failed: %s\n", gpg_strerror (err));
@@ -98,7 +119,7 @@ check (int algo,
       const unsigned char *s;
       int i;
 
-      fail ("mismatch at decryption!\n");
+      fail ("mismatch at decryption!%s\n", inplace ? " (inplace)" : "");
       fprintf (stderr, "computed: ");
       for (i = 0; i < outbuflen; i++)
        fprintf (stderr, "%02x ", outbuf[i]);
@@ -113,9 +134,19 @@ check (int algo,
 
   outbuflen = expectedlen - 8;
   if (outbuflen > sizeof outbuf)
-    err = gpg_error (GPG_ERR_INTERNAL);
+    {
+      err = gpg_error (GPG_ERR_INTERNAL);
+    }
+  else if (inplace)
+    {
+      memcpy (outbuf, expected, expectedlen);
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, outbuf, expectedlen);
+    }
   else
-    err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+    {
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+    }
+
   if (err)
     {
       fail ("gcry_cipher_decrypt(2) failed: %s\n", gpg_strerror (err));
@@ -123,14 +154,24 @@ check (int algo,
     }
 
   if (outbuflen != datalen || memcmp (outbuf, data, datalen))
-    fail ("mismatch at decryption(2)!\n");
+    fail ("mismatch at decryption(2)!%s\n", inplace ? " (inplace)" : "");
 
-  /* And once ore without a key reset. */
+  /* And once more without a key reset. */
   outbuflen = expectedlen - 8;
   if (outbuflen > sizeof outbuf)
-    err = gpg_error (GPG_ERR_INTERNAL);
+    {
+      err = gpg_error (GPG_ERR_INTERNAL);
+    }
+  else if (inplace)
+    {
+      memcpy (outbuf, expected, expectedlen);
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, outbuf, expectedlen);
+    }
   else
-    err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+    {
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+    }
+
   if (err)
     {
       fail ("gcry_cipher_decrypt(3) failed: %s\n", gpg_strerror (err));
@@ -138,7 +179,179 @@ check (int algo,
     }
 
   if (outbuflen != datalen || memcmp (outbuf, data, datalen))
-    fail ("mismatch at decryption(3)!\n");
+    fail ("mismatch at decryption(3)!%s\n", inplace ? " (inplace)" : "");
+
+  gcry_cipher_close (hd);
+}
+
+
+static void
+check (int algo,
+       const void *kek, size_t keklen,
+       const void *data, size_t datalen,
+       const void *expected, size_t expectedlen)
+{
+  check_one (algo, kek, keklen, data, datalen, expected, expectedlen, 0);
+  check_one (algo, kek, keklen, data, datalen, expected, expectedlen, 1);
+}
+
+
+static void
+check_one_with_padding (int algo,
+                        const void *kek, size_t keklen,
+                        const void *data, size_t datalen,
+                        const void *expected, size_t expectedlen)
+{
+  gcry_error_t err;
+  gcry_cipher_hd_t hd;
+  unsigned char outbuf[4*16];
+  size_t outbuflen;
+
+  err = gcry_cipher_open (&hd, algo, GCRY_CIPHER_MODE_AESWRAP,
+                          GCRY_CIPHER_EXTENDED);
+  if (err)
+    {
+      fail ("gcry_cipher_open failed: %s\n", gpg_strerror (err));
+      return;
+    }
+
+  err = gcry_cipher_setkey (hd, kek, keklen);
+  if (err)
+    {
+      fail ("gcry_cipher_setkey failed: %s\n", gpg_strerror (err));
+      return;
+    }
+
+  outbuflen = ((datalen+7)/8) * 8 + 8;
+  if (outbuflen > sizeof outbuf)
+    {
+      err = gpg_error (GPG_ERR_INTERNAL);
+    }
+  else
+    {
+      err = gcry_cipher_encrypt (hd, outbuf, outbuflen, data, datalen);
+    }
+
+  if (err)
+    {
+      fail ("gcry_cipher_encrypt failed: %s\n", gpg_strerror (err));
+      return;
+    }
+
+  if (outbuflen != expectedlen || memcmp (outbuf, expected, expectedlen))
+    {
+      const unsigned char *s;
+      int i;
+
+      fail ("mismatch at encryption!(padding)\n");
+      fprintf (stderr, "computed: ");
+      for (i = 0; i < outbuflen; i++)
+       fprintf (stderr, "%02x ", outbuf[i]);
+      fprintf (stderr, "\nexpected: ");
+      for (s = expected, i = 0; i < expectedlen; s++, i++)
+        fprintf (stderr, "%02x ", *s);
+      putc ('\n', stderr);
+    }
+
+  outbuflen = ((datalen+7)/8) * 8 + 8;
+  if (outbuflen > sizeof outbuf)
+    {
+      err = gpg_error (GPG_ERR_INTERNAL);
+    }
+  else
+    {
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+      if (!err)
+        {
+          unsigned char plen[4];
+          size_t nbytes;
+          err = gcry_cipher_info (hd, GCRYCTL_GET_KEYLEN, plen, &nbytes);
+          if (!err)
+            outbuflen = (plen[0] << 24) | (plen[1] << 16)
+              | (plen[2] << 8) | plen[3];
+        }
+    }
+
+  if (err)
+    {
+      fail ("gcry_cipher_decrypt failed: %s\n", gpg_strerror (err));
+      return;
+    }
+
+  if (outbuflen != datalen || memcmp (outbuf, data, datalen))
+    {
+      const unsigned char *s;
+      int i;
+
+      fail ("mismatch at decryption!(padding)\n");
+      fprintf (stderr, "computed: ");
+      for (i = 0; i < outbuflen; i++)
+       fprintf (stderr, "%02x ", outbuf[i]);
+      fprintf (stderr, "\nexpected: ");
+      for (s = data, i = 0; i < datalen; s++, i++)
+        fprintf (stderr, "%02x ", *s);
+      putc ('\n', stderr);
+    }
+
+  /* Now the last step again with a key reset. */
+  gcry_cipher_reset (hd);
+
+  outbuflen = ((datalen+7)/8) * 8 + 8;
+  if (outbuflen > sizeof outbuf)
+    {
+      err = gpg_error (GPG_ERR_INTERNAL);
+    }
+  else
+    {
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+      if (!err)
+        {
+          unsigned char plen[4];
+          size_t nbytes;
+          err = gcry_cipher_info (hd, GCRYCTL_GET_KEYLEN, plen, &nbytes);
+          if (!err)
+            outbuflen = (plen[0] << 24) | (plen[1] << 16)
+              | (plen[2] << 8) | plen[3];
+        }
+    }
+
+  if (err)
+    {
+      fail ("gcry_cipher_decrypt(2) failed: %s\n", gpg_strerror (err));
+      return;
+    }
+
+  if (outbuflen != datalen || memcmp (outbuf, data, datalen))
+    fail ("mismatch at decryption(2)(padding)!\n");
+
+  /* And once more without a key reset. */
+  outbuflen = ((datalen+7)/8) * 8 + 8;
+  if (outbuflen > sizeof outbuf)
+    {
+      err = gpg_error (GPG_ERR_INTERNAL);
+    }
+  else
+    {
+      err = gcry_cipher_decrypt (hd, outbuf, outbuflen, expected, expectedlen);
+      if (!err)
+        {
+          unsigned char plen[4];
+          size_t nbytes;
+          err = gcry_cipher_info (hd, GCRYCTL_GET_KEYLEN, plen, &nbytes);
+          if (!err)
+            outbuflen = (plen[0] << 24) | (plen[1] << 16)
+              | (plen[2] << 8) | plen[3];
+        }
+    }
+
+  if (err)
+    {
+      fail ("gcry_cipher_decrypt(3) failed: %s\n", gpg_strerror (err));
+      return;
+    }
+
+  if (outbuflen != datalen || memcmp (outbuf, data, datalen))
+    fail ("mismatch at decryption(3)(padding)!\n");
 
   gcry_cipher_close (hd);
 }
@@ -209,6 +422,26 @@ check_all (void)
      "\x28\xC9\xF4\x04\xC4\xB8\x10\xF4\xCB\xCC\xB3\x5C\xFB\x87\xF8\x26"
      "\x3F\x57\x86\xE2\xD8\x0E\xD3\x26\xCB\xC7\xF0\xE7\x1A\x99\xF4\x3B"
      "\xFB\x98\x8B\x9B\x7A\x02\xDD\x21", 40);
+
+  if (verbose)
+    fprintf (stderr, "6 Wrap 160 bits of Key Data with a 192-bit KEK\n");
+  check_one_with_padding
+    (GCRY_CIPHER_AES192,
+     "\x58\x40\xdf\x6e\x29\xb0\x2a\xf1\xab\x49\x3b\x70\x5b\xf1\x6e\xa1"
+     "\xae\x83\x38\xf4\xdc\xc1\x76\xa8", 24,
+     "\xc3\x7b\x7e\x64\x92\x58\x43\x40\xbe\xd1\x22\x07\x80\x89\x41\x15"
+     "\x50\x68\xf7\x38", 20,
+     "\x13\x8b\xde\xaa\x9b\x8f\xa7\xfc\x61\xf9\x77\x42\xe7\x22\x48\xee"
+     "\x5a\xe6\xae\x53\x60\xd1\xae\x6a\x5f\x54\xf3\x73\xfa\x54\x3b\x6a", 32);
+
+  if (verbose)
+    fprintf (stderr, "6 Wrap 56 bits of Key Data with a 192-bit KEK\n");
+  check_one_with_padding
+    (GCRY_CIPHER_AES192,
+     "\x58\x40\xdf\x6e\x29\xb0\x2a\xf1\xab\x49\x3b\x70\x5b\xf1\x6e\xa1"
+     "\xae\x83\x38\xf4\xdc\xc1\x76\xa8", 24,
+     "\x46\x6f\x72\x50\x61\x73\x69", 7,
+     "\xaf\xbe\xb0\xf0\x7d\xfb\xf5\x41\x92\x00\xf2\xcc\xb5\x0b\xb2\x4f", 16);
 }
 
 int
@@ -222,10 +455,10 @@ main (int argc, char **argv)
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
   check_all ();
 
   return error_count ? 1 : 0;
index 034ef8d..a0ad33e 100644 (file)
 #define PGM "basic"
 #include "t-common.h"
 
+#if __GNUC__ >= 4
+#  define ALWAYS_INLINE __attribute__((always_inline))
+#else
+#  define ALWAYS_INLINE
+#endif
+
 typedef struct test_spec_pubkey_key
 {
   const char *secret;
@@ -49,13 +55,15 @@ typedef struct test_spec_pubkey
 }
 test_spec_pubkey_t;
 
-#define FLAG_CRYPT (1 << 0)
-#define FLAG_SIGN  (1 << 1)
-#define FLAG_GRIP  (1 << 2)
+#define FLAG_CRYPT  (1 << 0)
+#define FLAG_SIGN   (1 << 1)
+#define FLAG_GRIP   (1 << 2)
+#define FLAG_NOFIPS (1 << 3)
+#define FLAG_CFB8   (1 << 4)
 
 static int in_fips_mode;
 
-#define MAX_DATA_LEN 128
+#define MAX_DATA_LEN 1040
 
 
 static void
@@ -191,7 +199,7 @@ show_mac_not_available (int algo)
 
 
 
-void
+static void
 progress_handler (void *cb_data, const char *what, int printchar,
                  int current, int total)
 {
@@ -207,6 +215,239 @@ progress_handler (void *cb_data, const char *what, int printchar,
   fflush (stdout);
 }
 
+
+#if defined(__x86_64__) && defined(HAVE_GCC_INLINE_ASM_SSSE3) && \
+    (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
+     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
+# define CLUTTER_VECTOR_REGISTER_AMD64 1
+# define CLUTTER_VECTOR_REGISTER_COUNT 16
+#elif defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ >= 4 && \
+      defined(HAVE_GCC_INLINE_ASM_SSSE3)
+# define CLUTTER_VECTOR_REGISTER_I386 1
+# define CLUTTER_VECTOR_REGISTER_COUNT 8
+#elif defined(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS) && \
+      defined(HAVE_GCC_INLINE_ASM_AARCH64_NEON) && \
+      defined(__ARM_NEON)
+# define CLUTTER_VECTOR_REGISTER_AARCH64 1
+# define CLUTTER_VECTOR_REGISTER_COUNT 32
+#elif defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
+      defined(HAVE_GCC_INLINE_ASM_NEON) && \
+      defined(__ARM_NEON)
+# define CLUTTER_VECTOR_REGISTER_NEON 1
+# define CLUTTER_VECTOR_REGISTER_COUNT 16
+#endif
+
+
+#ifdef CLUTTER_VECTOR_REGISTER_COUNT
+static void
+prepare_vector_data(unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16])
+{
+  static unsigned char basedata[16] =
+  {
+    0xd7, 0xfe, 0x5c, 0x4b, 0x58, 0xfe, 0xf4, 0xb6,
+    0xed, 0x2f, 0x31, 0xc9, 0x1d, 0xd3, 0x62, 0x8d
+  };
+  int j, i;
+
+  for (i = 0; i < CLUTTER_VECTOR_REGISTER_COUNT; i++)
+    {
+      for (j = 0; j < 16; j++)
+       {
+         data[i][j] = basedata[(i + j) % 16];
+       }
+
+      for (j = 0; j < 16; j++)
+       {
+         basedata[j] -= j;
+       }
+    }
+}
+#endif
+
+
+static inline ALWAYS_INLINE void
+clutter_vector_registers(void)
+{
+#ifdef CLUTTER_VECTOR_REGISTER_COUNT
+  unsigned char data[CLUTTER_VECTOR_REGISTER_COUNT][16];
+#if defined(CLUTTER_VECTOR_REGISTER_AARCH64) || \
+    defined(CLUTTER_VECTOR_REGISTER_NEON)
+  static int init;
+  static int have_neon;
+
+  if (!init)
+    {
+      char *string;
+
+      string = gcry_get_config (0, "hwflist");
+      if (string)
+       {
+         have_neon = (strstr(string, "arm-neon:") != NULL);
+         xfree(string);
+       }
+      init = 1;
+    }
+
+  if (!have_neon)
+    return;
+#elif defined(CLUTTER_VECTOR_REGISTER_I386)
+  static int init;
+  static int have_ssse3;
+
+  if (!init)
+    {
+      char *string;
+
+      string = gcry_get_config (0, "hwflist");
+      if (string)
+       {
+         have_ssse3 = (strstr(string, "intel-ssse3:") != NULL);
+         xfree(string);
+       }
+      init = 1;
+    }
+
+  if (!have_ssse3)
+    return;
+#endif
+
+  prepare_vector_data(data);
+
+#if defined(CLUTTER_VECTOR_REGISTER_AMD64)
+  asm volatile("movdqu %[data0], %%xmm0\n"
+              "movdqu %[data1], %%xmm1\n"
+              "movdqu %[data2], %%xmm2\n"
+              "movdqu %[data3], %%xmm3\n"
+              "movdqu %[data4], %%xmm4\n"
+              "movdqu %[data5], %%xmm5\n"
+              "movdqu %[data6], %%xmm6\n"
+              "movdqu %[data7], %%xmm7\n"
+              "movdqu %[data8], %%xmm8\n"
+              "movdqu %[data9], %%xmm9\n"
+              "movdqu %[data10], %%xmm10\n"
+              "movdqu %[data11], %%xmm11\n"
+              "movdqu %[data12], %%xmm12\n"
+              "movdqu %[data13], %%xmm13\n"
+              "movdqu %[data14], %%xmm14\n"
+              "movdqu %[data15], %%xmm15\n"
+             :
+             : [data0] "m" (*data[0]),
+               [data1] "m" (*data[1]),
+               [data2] "m" (*data[2]),
+               [data3] "m" (*data[3]),
+               [data4] "m" (*data[4]),
+               [data5] "m" (*data[5]),
+               [data6] "m" (*data[6]),
+               [data7] "m" (*data[7]),
+               [data8] "m" (*data[8]),
+               [data9] "m" (*data[9]),
+               [data10] "m" (*data[10]),
+               [data11] "m" (*data[11]),
+               [data12] "m" (*data[12]),
+               [data13] "m" (*data[13]),
+               [data14] "m" (*data[14]),
+               [data15] "m" (*data[15])
+             : "memory"
+#ifdef __SSE2__
+              ,"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
+               "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14",
+               "xmm15"
+#endif
+             );
+#elif defined(CLUTTER_VECTOR_REGISTER_I386)
+  asm volatile("movdqu %[data0], %%xmm0\n"
+              "movdqu %[data1], %%xmm1\n"
+              "movdqu %[data2], %%xmm2\n"
+              "movdqu %[data3], %%xmm3\n"
+              "movdqu %[data4], %%xmm4\n"
+              "movdqu %[data5], %%xmm5\n"
+              "movdqu %[data6], %%xmm6\n"
+              "movdqu %[data7], %%xmm7\n"
+             :
+             : [data0] "m" (*data[0]),
+               [data1] "m" (*data[1]),
+               [data2] "m" (*data[2]),
+               [data3] "m" (*data[3]),
+               [data4] "m" (*data[4]),
+               [data5] "m" (*data[5]),
+               [data6] "m" (*data[6]),
+               [data7] "m" (*data[7])
+             : "memory"
+#ifdef __SSE2__
+              ,"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
+#endif
+             );
+#elif defined(CLUTTER_VECTOR_REGISTER_AARCH64)
+  asm volatile("mov x0, %[ptr]\n"
+              "ld1 {v0.16b}, [x0], #16\n"
+              "ld1 {v1.16b}, [x0], #16\n"
+              "ld1 {v2.16b}, [x0], #16\n"
+              "ld1 {v3.16b}, [x0], #16\n"
+              "ld1 {v4.16b}, [x0], #16\n"
+              "ld1 {v5.16b}, [x0], #16\n"
+              "ld1 {v6.16b}, [x0], #16\n"
+              "ld1 {v7.16b}, [x0], #16\n"
+              "ld1 {v8.16b}, [x0], #16\n"
+              "ld1 {v9.16b}, [x0], #16\n"
+              "ld1 {v10.16b}, [x0], #16\n"
+              "ld1 {v11.16b}, [x0], #16\n"
+              "ld1 {v12.16b}, [x0], #16\n"
+              "ld1 {v13.16b}, [x0], #16\n"
+              "ld1 {v14.16b}, [x0], #16\n"
+              "ld1 {v15.16b}, [x0], #16\n"
+              "ld1 {v16.16b}, [x0], #16\n"
+              "ld1 {v17.16b}, [x0], #16\n"
+              "ld1 {v18.16b}, [x0], #16\n"
+              "ld1 {v19.16b}, [x0], #16\n"
+              "ld1 {v20.16b}, [x0], #16\n"
+              "ld1 {v21.16b}, [x0], #16\n"
+              "ld1 {v22.16b}, [x0], #16\n"
+              "ld1 {v23.16b}, [x0], #16\n"
+              "ld1 {v24.16b}, [x0], #16\n"
+              "ld1 {v25.16b}, [x0], #16\n"
+              "ld1 {v26.16b}, [x0], #16\n"
+              "ld1 {v27.16b}, [x0], #16\n"
+              "ld1 {v28.16b}, [x0], #16\n"
+              "ld1 {v29.16b}, [x0], #16\n"
+              "ld1 {v30.16b}, [x0], #16\n"
+              "ld1 {v31.16b}, [x0], #16\n"
+              :
+              : [ptr] "r" (data)
+              : "x0", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+                "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+                "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+                "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+                "memory");
+#elif defined(CLUTTER_VECTOR_REGISTER_NEON)
+  asm volatile("mov r0, %[ptr]\n"
+              "vld1.64 {q0}, [r0]!\n"
+              "vld1.64 {q1}, [r0]!\n"
+              "vld1.64 {q2}, [r0]!\n"
+              "vld1.64 {q3}, [r0]!\n"
+              "vld1.64 {q4}, [r0]!\n"
+              "vld1.64 {q5}, [r0]!\n"
+              "vld1.64 {q6}, [r0]!\n"
+              "vld1.64 {q7}, [r0]!\n"
+              "vld1.64 {q8}, [r0]!\n"
+              "vld1.64 {q9}, [r0]!\n"
+              "vld1.64 {q10}, [r0]!\n"
+              "vld1.64 {q11}, [r0]!\n"
+              "vld1.64 {q12}, [r0]!\n"
+              "vld1.64 {q13}, [r0]!\n"
+              "vld1.64 {q14}, [r0]!\n"
+              "vld1.64 {q15}, [r0]!\n"
+              :
+              : [ptr] "r" (data)
+              : "r0", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
+                "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
+                "memory");
+#endif
+
+#endif /* CLUTTER_VECTOR_REGISTER_COUNT */
+}
+
+
+
 static void
 check_cbc_mac_cipher (void)
 {
@@ -224,6 +465,7 @@ check_cbc_mac_cipher (void)
        "chicken teriyaki",
        "This is a sample plaintext for CBC MAC of sixtyfour bytes.......",
        0, "\x23\x8f\x6d\xc7\x53\x6a\x62\x97\x11\xc4\xa5\x16\x43\xea\xb0\xb6" },
+#if USE_DES
       { GCRY_CIPHER_3DES,
        "abcdefghABCDEFGH01234567",
        "This is a sample plaintext for CBC MAC of sixtyfour bytes.......",
@@ -232,6 +474,7 @@ check_cbc_mac_cipher (void)
        "abcdefgh",
        "This is a sample plaintext for CBC MAC of sixtyfour bytes.......",
        0, "\xfa\x4b\xdf\x9d\xfa\xab\x01\x70" }
+#endif /* USE_DES */
     };
   gcry_cipher_hd_t hd;
   unsigned char out[MAX_DATA_LEN];
@@ -243,11 +486,23 @@ check_cbc_mac_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
-      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                     tv[i].algo);
+          if (in_fips_mode && tv[i].algo != GCRY_CIPHER_AES)
+            {
+              if (verbose)
+                fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                         tv[i].algo);
+            }
+          else
+            fail ("cbc-mac algo %d, gcry_cipher_test_algo failed: %s\n",
+                  tv[i].algo, gpg_strerror (err));
+          continue;
+        }
+      else if (in_fips_mode && tv[i].algo != GCRY_CIPHER_AES)
+        {
+          fail ("cbc-mac algo %d, gcry_cipher_test_algo did not fail as expected in FIPS mode\n",
+                tv[i].algo);
           continue;
         }
 
@@ -447,23 +702,379 @@ check_aes128_cbc_cts_cipher (void)
 }
 
 static void
+check_ecb_cipher (void)
+{
+  /* ECB cipher check. Mainly for testing underlying block cipher. */
+  static const struct tv
+  {
+    int algo;
+    const char *key;
+    int is_weak_key;
+    int flags;
+    struct
+    {
+      const char *plaintext;
+      int keylen;
+      int inlen;
+      const char *out;
+    } data[MAX_DATA_LEN];
+  } tv[] =
+    {
+#if USE_BLOWFISH
+      /* Test vectors from OpenSSL for key lengths of 8 to 200 bits */
+      { GCRY_CIPHER_BLOWFISH,
+       "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
+       "\x00\x11\x22\x33\x44\x55\x66\x77\x88",
+       0, FLAG_NOFIPS,
+       { { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           1,
+           8,
+           "\xf9\xad\x59\x7c\x49\xdb\x00\x5e" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           2,
+           8,
+           "\xe9\x1d\x21\xc1\xd9\x61\xa6\xd6" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           3,
+           8,
+           "\xe9\xc2\xb7\x0a\x1b\xc6\x5c\xf3" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           4,
+           8,
+           "\xbe\x1e\x63\x94\x08\x64\x0f\x05" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           5,
+           8,
+           "\xb3\x9e\x44\x48\x1b\xdb\x1e\x6e" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           6,
+           8,
+           "\x94\x57\xaa\x83\xb1\x92\x8c\x0d" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           7,
+           8,
+           "\x8b\xb7\x70\x32\xf9\x60\x62\x9d" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           8,
+           8,
+           "\xe8\x7a\x24\x4e\x2c\xc8\x5e\x82" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           9,
+           8,
+           "\x15\x75\x0e\x7a\x4f\x4e\xc5\x77" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           10,
+           8,
+           "\x12\x2b\xa7\x0b\x3a\xb6\x4a\xe0" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           11,
+           8,
+           "\x3a\x83\x3c\x9a\xff\xc5\x37\xf6" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           12,
+           8,
+           "\x94\x09\xda\x87\xa9\x0f\x6b\xf2" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           13,
+           8,
+           "\x88\x4f\x80\x62\x50\x60\xb8\xb4" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           14,
+           8,
+           "\x1f\x85\x03\x1c\x19\xe1\x19\x68" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           15,
+           8,
+           "\x79\xd9\x37\x3a\x71\x4c\xa3\x4f" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           16,
+           8,
+           "\x93\x14\x28\x87\xee\x3b\xe1\x5c" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           17,
+           8,
+           "\x03\x42\x9e\x83\x8c\xe2\xd1\x4b" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           18,
+           8,
+           "\xa4\x29\x9e\x27\x46\x9f\xf6\x7b" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           19,
+           8,
+           "\xaf\xd5\xae\xd1\xc1\xbc\x96\xa8" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           20,
+           8,
+           "\x10\x85\x1c\x0e\x38\x58\xda\x9f" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           21,
+           8,
+           "\xe6\xf5\x1e\xd7\x9b\x9d\xb2\x1f" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           22,
+           8,
+           "\x64\xa6\xe1\x4a\xfd\x36\xb4\x6f" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           23,
+           8,
+           "\x80\xc7\xd7\xd4\x5a\x54\x79\xad" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           24,
+           8,
+           "\x05\x04\x4b\x62\xfa\x52\xd0\x80" },
+         { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           0, /* test default key length of 128-bits */
+           8,
+           "\x93\x14\x28\x87\xee\x3b\xe1\x5c" },
+         { }
+       }
+      },
+      /* Test vector from Linux kernel for key length of 448 bits */
+      { GCRY_CIPHER_BLOWFISH,
+       "\xf0\xe1\xd2\xc3\xb4\xa5\x96\x87\x78\x69\x5a\x4b\x3c\x2d\x1e\x0f"
+       "\x00\x11\x22\x33\x44\x55\x66\x77\x04\x68\x91\x04\xc2\xfd\x3b\x2f"
+       "\x58\x40\x23\x64\x1a\xba\x61\x76\x1f\x1f\x1f\x1f\x0e\x0e\x0e\x0e"
+       "\xff\xff\xff\xff\xff\xff\xff\xff",
+       0, FLAG_NOFIPS,
+       { { "\xfe\xdc\xba\x98\x76\x54\x32\x10",
+           56,
+           8,
+           "\xc0\x45\x04\x01\x2e\x4e\x1f\x53" },
+         { }
+       }
+      },
+#endif /* USE_BLOWFISH */
+#if USE_DES
+      /* Weak-key testing */
+      { GCRY_CIPHER_DES,
+       "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+       1, FLAG_NOFIPS,
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00",
+           8,
+           8,
+           "\xca\xaa\xaf\x4d\xea\xf1\xdb\xae" },
+         { }
+       }
+      },
+      /* Weak-key testing */
+      { GCRY_CIPHER_DES,
+       "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe",
+       2, FLAG_NOFIPS,
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00",
+           8,
+           8,
+           "\xca\xaa\xaf\x4d\xea\xf1\xdb\xae" },
+         { }
+       }
+      },
+#endif /* USE_DES */
+#if USE_SM4
+      { GCRY_CIPHER_SM4,
+       "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10",
+       0, FLAG_NOFIPS,
+       { { "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd"
+           "\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb",
+           16,
+           32,
+           "\x5e\xc8\x14\x3d\xe5\x09\xcf\xf7\xb5\x17\x9f\x8f\x47\x4b\x86\x19"
+           "\x2f\x1d\x30\x5a\x7f\xb1\x7d\xf9\x85\xf8\x1c\x84\x82\x19\x23\x04" },
+         { }
+       }
+      },
+      { GCRY_CIPHER_SM4,
+       "\xfe\xdc\xba\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xab\xcd\xef",
+       0, FLAG_NOFIPS,
+       { { "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd"
+           "\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb",
+           16,
+           32,
+           "\xc5\x87\x68\x97\xe4\xa5\x9b\xbb\xa7\x2a\x10\xc8\x38\x72\x24\x5b"
+           "\x12\xdd\x90\xbc\x2d\x20\x06\x92\xb5\x29\xa4\x15\x5a\xc9\xe6\x00" },
+         { }
+       }
+      },
+#endif /* USE_SM4 */
+    };
+  gcry_cipher_hd_t hde, hdd;
+  unsigned char out[MAX_DATA_LEN];
+  int i, j, keylen, algo;
+  gcry_error_t err = 0;
+  gcry_error_t err2 = 0;
+
+  if (verbose)
+    fprintf (stderr, "  Starting ECB checks.\n");
+
+  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+    {
+      algo = tv[i].algo;
+
+      if ((err = gcry_cipher_test_algo (algo)))
+        {
+          if (in_fips_mode && (tv[0].flags & FLAG_NOFIPS))
+            {
+              if (verbose)
+                fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                         algo);
+            }
+          else
+            fail ("algorithm %d, gcry_cipher_test_algo unexpectedly failed: %s\n",
+                  algo, gpg_strerror (err));
+          continue;
+        }
+      else if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+        {
+          fail ("algorithm %d, gcry_cipher_test_algo did not fail as expected\n",
+                algo);
+          continue;
+        }
+
+      if (verbose)
+       fprintf (stderr, "    checking ECB mode for %s [%i]\n",
+                gcry_cipher_algo_name (algo),
+                algo);
+      err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_ECB, 0);
+      if (!err)
+       err2 = gcry_cipher_open (&hdd, algo, GCRY_CIPHER_MODE_ECB, 0);
+      if (err || err2)
+       {
+         fail ("ecb-algo:%d-tv:%d, gcry_cipher_open failed: %s\n", algo, i,
+               gpg_strerror (err ? err : err2));
+         if (err2)
+           gcry_cipher_close (hde);
+         return;
+       }
+
+      if (tv[i].is_weak_key == 2)
+       {
+         err = gcry_cipher_ctl(hde, GCRYCTL_SET_ALLOW_WEAK_KEY, NULL, 1);
+         if (!err)
+           err = gcry_cipher_ctl(hdd, GCRYCTL_SET_ALLOW_WEAK_KEY, NULL, 1);
+         if (err)
+           {
+             fail ("ecb-algo:%d-tv:%d, gcry_cipher_ctl failed: %s\n",
+                   algo, i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
+
+      for (j = 0; tv[i].data[j].inlen; j++)
+       {
+         keylen = tv[i].data[j].keylen;
+         if (!keylen)
+           {
+             keylen = gcry_cipher_get_algo_keylen(algo);
+             if (!keylen)
+               {
+                 fail ("ecb-algo:%d-tv:%d-data:%d, gcry_cipher_get_algo_keylen failed\n",
+                       algo, i, j);
+                 gcry_cipher_close (hde);
+                 gcry_cipher_close (hdd);
+                 return;
+               }
+           }
+
+         err = gcry_cipher_setkey (hde, tv[i].key, keylen);
+         if (!err || (gcry_err_code(err) == GPG_ERR_WEAK_KEY
+                      && tv[i].is_weak_key == 2))
+           err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
+         if (tv[i].is_weak_key == 1)
+           {
+             if (gcry_err_code(err) != GPG_ERR_WEAK_KEY)
+               {
+                 fail ("ecb-algo:%d-tv:%d-data:%d, expected gcry_cipher_setkey to fail, but got: %s\n",
+                       algo, i, j, gpg_strerror (err));
+                 gcry_cipher_close (hde);
+                 gcry_cipher_close (hdd);
+                 return;
+               }
+             else
+               {
+                 continue;
+               }
+           }
+         else if (tv[i].is_weak_key == 2)
+           {
+             if (gcry_err_code(err) != GPG_ERR_WEAK_KEY)
+               {
+                 fail ("ecb-algo:%d-tv:%d-data:%d, expected gcry_cipher_setkey to fail, but got: %s\n",
+                       algo, i, j, gpg_strerror (err));
+                 gcry_cipher_close (hde);
+                 gcry_cipher_close (hdd);
+                 return;
+               }
+           }
+         else if (err)
+           {
+             fail ("ecb-algo:%d-tv:%d-data:%d, gcry_cipher_setkey failed: %s\n",
+                   algo, i, j, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
+                                    tv[i].data[j].plaintext,
+                                    tv[i].data[j].inlen);
+         if (err)
+           {
+             fail ("ecb-algo:%d-tv:%d-data:%d, gcry_cipher_encrypt failed: %s\n",
+                   algo, i, j, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].data[j].out, out, tv[i].data[j].inlen))
+           {
+             fail ("ecb-algo:%d-tv:%d-data:%d, encrypt mismatch entry\n",
+                   algo, i, j);
+           }
+
+         err = gcry_cipher_decrypt (hdd, out, tv[i].data[j].inlen, NULL, 0);
+         if (err)
+           {
+             fail ("ecb-algo:%d-tv:%d-data:%d, gcry_cipher_decrypt failed: %s\n",
+                   algo, i, j, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].data[j].plaintext, out, tv[i].data[j].inlen))
+           {
+             fail ("ecb-algo:%d-tv:%d-data:%d, decrypt mismatch entry\n",
+                   algo, i, j);
+           }
+       }
+
+      gcry_cipher_close (hde);
+      gcry_cipher_close (hdd);
+    }
+  if (verbose)
+    fprintf (stderr, "  Completed ECB checks.\n");
+}
+
+static void
 check_ctr_cipher (void)
 {
   static const struct tv
   {
     int algo;
+    int flags;
     char key[MAX_DATA_LEN];
     char ctr[MAX_DATA_LEN];
     struct data
     {
-      unsigned char plaintext[MAX_DATA_LEN];
+      const char *plaintext;
       int inlen;
-      char out[MAX_DATA_LEN];
+      const char *out;
     } data[8];
   } tv[] =
     {
       /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
-      {        GCRY_CIPHER_AES,
+      {        GCRY_CIPHER_AES, 0,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
        { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
@@ -482,7 +1093,7 @@ check_ctr_cipher (void)
           { "", 0, "" }
        }
       },
-      {        GCRY_CIPHER_AES192,
+      {        GCRY_CIPHER_AES192, 0,
        "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b"
        "\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
@@ -501,7 +1112,7 @@ check_ctr_cipher (void)
           { "", 0, "" }
        }
       },
-      {        GCRY_CIPHER_AES256,
+      {        GCRY_CIPHER_AES256, 0,
        "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
        "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
@@ -522,7 +1133,7 @@ check_ctr_cipher (void)
       },
       /* Some truncation tests.  With a truncated second block and
          also with a single truncated block.  */
-      {        GCRY_CIPHER_AES,
+      {        GCRY_CIPHER_AES, 0,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
        {{"\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
@@ -534,7 +1145,7 @@ check_ctr_cipher (void)
          {"", 0, "" }
        }
       },
-      {        GCRY_CIPHER_AES,
+      {        GCRY_CIPHER_AES, 0,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
        {{"\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
@@ -546,7 +1157,7 @@ check_ctr_cipher (void)
          {"", 0, "" }
        }
       },
-      {        GCRY_CIPHER_AES,
+      {        GCRY_CIPHER_AES, 0,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
        {{"\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17",
@@ -555,7 +1166,7 @@ check_ctr_cipher (void)
          {"", 0, "" }
        }
       },
-      {        GCRY_CIPHER_AES,
+      {        GCRY_CIPHER_AES, 0,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
        {{"\x6b",
@@ -565,7 +1176,7 @@ check_ctr_cipher (void)
        }
       },
       /* Tests to see whether it works correctly as a stream cipher.  */
-      {        GCRY_CIPHER_AES,
+      {        GCRY_CIPHER_AES, 0,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
        {{"\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
@@ -584,7 +1195,7 @@ check_ctr_cipher (void)
           { "", 0, "" }
        }
       },
-      {        GCRY_CIPHER_AES,
+      {        GCRY_CIPHER_AES, 0,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
        {{"\x6b",
@@ -612,9 +1223,886 @@ check_ctr_cipher (void)
           { "", 0, "" }
        }
       },
+      /* Tests for counter overflow across 32-bit, 64-bit, 96-bit and 128-bit
+       * boundaries. Large buffer sizes are used to allow these vectors to be
+       * passed down to bulk CTR functions. */
+      { GCRY_CIPHER_AES, 0,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\x74\x54\x1d\x36\x3b\x1f\x40\xb7\x96\xec\x54\xdf\x37\xe1\xd1\x38"
+           "\xfe\xdf\x13\x08\xdc\xf4\xc6\xeb\x10\xff\x0c\xc9\x2a\x1d\xd0\xb2"
+           "\x38\xdd\xa8\x86\xbb\x58\x72\x2a\xd1\x3a\x4b\x74\x99\x98\x1c\xf9"
+           "\xf5\xe7\x71\x0d\xcc\x44\x40\x76\x26\xe2\xe9\xa5\x3b\xe7\xee\x63"
+           "\x0b\x30\x76\x75\x21\x14\xf7\xd0\xec\x5b\x82\x83\x03\x66\x68\xd1"
+           "\x57\x94\x1f\xf3\x41\x58\x81\xa0\xb2\xa7\x91\x7a\xc5\xfa\x33\xb8"
+           "\x42\x6c\x76\x8f\xaa\x41\x0b\x72\xab\x10\x39\x51\x25\x9b\xa1\x4a"
+           "\xd4\x82\x67\x74\xd1\x18\xc5\x35\x1a\xa4\x81\x13\x69\x0c\x39\x73"
+           "\xba\xd5\xaf\x63\xcd\xe9\xca\x2e\x4e\x44\x44\xfc\x23\xa5\x0e\x24"
+           "\xdc\xb7\x69\x3b\xf7\x57\x07\xd7\xbe\xd0\x19\xca\x2a\xd2\xa5\x32"
+           "\x49\xa3\xb6\xd7\x3f\x02\xbc\xbb\x41\x63\x4a\xc5\x8f\x5c\x51\x0a"
+           "\x59\x16\x2f\x9a\xd7\x58\x88\x1b\x51\x46\xe6\xe3\x37\xd6\x36\xbb"
+           "\x1e\xc9\x89\x8f\xd0\x8d\xa8\x77\xa2\xee\xfc\x4c\x65\xc2\x8a\x3c"
+           "\xf4\xad\x0d\x6b\x80\x04\x32\xc9\x39\x9e\x24\xd9\x99\xf7\x26\x93"
+           "\xe3\x8f\x97\x38\xb6\x2e\xa6\xf1\xe3\x8a\x7c\xfe\x4f\xed\xfe\xcb"
+           "\xff\x4e\x4a\x7a\x34\xc3\x1a\x92\x7c\x35\xdd\xd4\xc0\xf3\x1c\x51"
+           "\x4c\x52\x08\xe3\x78\xa3\x6a\x6b\x98\x40\xae\x3c\xf9\xcb\xa3\x85"
+           "\x0d\xbf\xdb\xf0\x6e\x53\xb2\xcc\xf7\x77\x37\xa9\x33\x1a\x1c\xed"
+           "\x26\x3f\x79\x30\x3f\x82\x9c\x3f\xd8\x72\x98\x17\x4b\x57\xa9\xd1"
+           "\xbd\x74\xa7\xab\x18\x85\xc6\x4c\x5a\x29\x9a\x41\xad\xae\x52\x87"
+           "\x8d\x72\x77\xfe\x91\xd9\x1f\xca\x02\x1e\x30\xa5\x4c\x8f\x74\xd6"
+           "\x71\xeb\x4d\xd9\x63\xaa\x90\xbf\x08\xa0\x38\x3c\x98\x46\x7a\x82"
+           "\xfd\x0d\xb3\x78\xbf\xf5\xcd\x25\xfb\x05\x4d\x39\x9c\x53\x35\xb4"
+           "\x34\x1b\x4b\x44\xf8\xfb\xb0\xf4\x56\xaa\xbd\x16\xba\xd1\x2b\x8d"
+           "\x62\x4b\x56\x70\x91\x1a\x77\x0f\x2b\x6a\x0e\xf4\x4b\x83\x8f\x89"
+           "\xa3\xe1\x5d\x3d\x0b\x1e\xb2\x43\xc6\x36\x98\x7a\xd7\xd4\x00\x09"
+           "\xa1\x09\x0b\x49\xa2\x72\xeb\x24\x16\x70\x15\x21\x82\x17\x48\x11"
+           "\x81\x93\xc9\x5a\x86\x2f\xd2\x96\x42\xb4\xb4\x08\x81\x85\xe5\x76"
+           "\xa6\xc5\x10\x15\xfe\x4e\x84\x00\x64\xb5\xeb\x92\x22\x40\x97\xbb"
+           "\xcf\xab\xc2\xf1\xbf\x44\xee\xb7\x7a\xaa\xe2\x5d\x1b\xa4\xeb\x3d"
+           "\x65\x5b\x84\xd8\xf4\xb6\x04\xf8\x62\xe3\x6b\xd9\xc6\xf3\x99\x89"
+           "\x11\xa0\xd4\x3f\x64\x4d\xfd\xac\x17\x80\x8e\x0d\x96\x2f\x4d\x69"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_AES, 0,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\xe3\x4c\xbe\xd8\xfd\x49\x8d\x84\xfc\x35\xe1\x1c\x56\x88\x6a\xf3"
+           "\x78\x22\x42\x79\xa5\xd5\x74\xb9\x19\xc3\x1b\x9a\x2e\x18\x57\xcc"
+           "\x27\x91\x03\xa2\x5d\xb8\xf7\xb7\x3a\xe2\x32\x4a\x77\x4c\x9c\xf7"
+           "\xfc\x54\xa5\x75\xec\xff\x99\x59\x73\x66\xf8\xd7\xe7\x46\xf9\xba"
+           "\x36\xcb\xe8\xa7\x19\xcf\xc8\x0c\x71\xb2\x8f\x97\xa7\xbd\xbd\x05"
+           "\x39\xa7\xef\x0a\x0a\x58\x52\xa8\xbf\xd2\x03\x23\x44\xbf\x94\x12"
+           "\x13\x18\x9a\x6a\xe4\xab\x07\xae\x70\xa3\xaa\xbd\x30\xbe\x99\xde"
+           "\x8f\x94\x29\x44\x4c\x8f\x4b\x35\x99\x42\x12\x35\xb5\x10\xdf\x3d"
+           "\x94\x54\x46\x34\x1c\x6f\x59\x71\xfe\x0e\xb6\x62\xb1\xfb\x99\x50"
+           "\xdd\xa6\x6f\x25\x1c\xfd\xb9\xdc\x9f\xce\xf7\xc9\x33\xba\x82\x8a"
+           "\xb8\x82\xd4\xbc\x28\x56\xf6\x42\x71\x85\x7a\x6a\xb1\xcc\xa0\xa1"
+           "\xa5\xe6\x36\xee\x73\xd7\x1c\x6c\xa0\x6c\xe2\x15\xa5\x82\x69\x46"
+           "\x2d\x94\x7b\xb1\xc1\x5f\xbb\x96\x03\xb1\x33\x27\x8f\xe1\xc3\x7a"
+           "\x62\x78\xad\x78\x11\x49\x93\x73\xce\xa1\xd8\xc5\x59\xe3\x54\x79"
+           "\xca\xaf\xc9\xe2\xde\x11\x83\x6d\x66\x39\xe1\x06\xa7\x41\x74\xe9"
+           "\x24\x54\xa5\x5b\x1c\x07\xdd\x2d\xf5\xc0\x27\xdc\x7e\x1d\xfa\x44"
+           "\x21\xd3\xe9\x4c\x3a\x2a\xb7\xbe\x4f\x37\x9f\xbe\x3d\x1a\x41\x6f"
+           "\xba\x4d\x0a\x72\xb2\x18\x83\x75\x17\x87\xf9\x22\x8a\x7c\x9d\x2a"
+           "\x8b\xc8\xda\xde\xda\xa0\xda\x56\x60\x02\x11\x4b\xca\xe0\x4f\xa4"
+           "\xbd\x71\x9a\x85\x7c\xd3\xf7\xbb\xc3\x4e\x10\x7d\x14\xbb\xa5\x10"
+           "\x10\xea\x35\x59\xe3\x17\x0a\x8d\x6e\x22\xe4\xc2\x83\x3f\x60\x6a"
+           "\x53\x19\xf2\xfa\xd8\x86\x5d\x44\xc3\xef\xd9\x2a\x0a\x71\xe0\x46"
+           "\xee\xa5\xad\xd2\xba\x80\x7d\xb1\x35\x3f\xe7\x4f\x24\xe1\x6a\x6b"
+           "\xe1\xc9\xe0\xc9\x2a\x27\x27\xa9\x63\x15\x1c\x01\xb1\x06\xaa\xca"
+           "\x20\x15\xe5\xa9\xba\xab\xbf\xa9\x06\x02\xac\x09\x2a\x55\x8d\xc6"
+           "\x22\x93\xfd\x50\x2f\xac\x02\x97\x0d\xea\xfc\xa0\x5a\x1a\x30\x9c"
+           "\xf7\x77\x91\x46\xea\x5a\x94\x79\x5e\xad\xff\x91\x58\x6a\xed\x3f"
+           "\xba\x48\xa9\x3b\xd7\xff\x63\x39\x1e\x67\x8e\x23\xe8\xe3\x62\x45"
+           "\x08\xe0\xea\x64\xa2\x6a\x3d\x6c\xdf\x30\x0d\x00\xa1\x88\x13\x2b"
+           "\x57\x30\x3e\xea\x6b\xb2\x57\xfb\x16\x65\xf1\x26\x81\x7c\xbf\xb6"
+           "\x53\x90\xff\x75\xcb\x3e\xb5\x97\x1d\x52\xbe\x67\x58\xbe\x50\x45"
+           "\x69\x3a\x29\x52\x1e\xb6\xb4\x70\x82\xb8\x1a\x0d\x6f\x3b\xbe\x14"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_AES, 0,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+       "\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\xf1\x51\x2c\xa5\xd9\x8a\xeb\xa2\xa9\xfc\xe2\x24\x73\x69\xaa\x7d"
+           "\x1d\xae\xbf\xca\xae\xed\xf9\x2c\x97\x03\xa3\xef\x3f\x7c\xec\xeb"
+           "\x45\x69\x4a\x66\x9b\xde\xbf\x46\x01\x28\xf1\xde\xed\xb2\xa4\x7e"
+           "\xa3\x52\xe1\x85\x9c\x6b\xcf\x6b\x42\xba\xce\x02\x1c\xee\x35\x6a"
+           "\xfa\x18\x46\xf0\x90\xc9\x80\x1a\xc6\xbe\x02\x65\xf1\x77\xe8\xcf"
+           "\x5a\x4b\x94\xa8\x55\xcc\x21\x39\xe3\xae\xb7\x2a\xcc\x8d\xc7\x9f"
+           "\x95\x03\xe3\xa2\x24\x5a\x2b\xe4\x3c\x98\x74\xed\xfe\x1b\xed\x9e"
+           "\xfe\x1a\x92\xed\x86\xf1\x06\x6a\xf9\x79\x48\x5c\xd2\x5a\x98\x47"
+           "\x63\x81\xfd\xfc\x9a\xef\xaf\xea\x3a\xff\x5c\xd8\xd7\xab\xef\x8c"
+           "\x88\x91\x34\x5a\x2c\x05\x6a\xf2\x2e\xf6\xd0\x01\x59\x35\x28\x95"
+           "\x61\x3a\x1a\x31\xb3\x64\xc4\x8c\xa3\x5d\xe0\xf9\x09\xed\x58\x47"
+           "\xa0\x85\xe1\x06\x0b\xc0\xc0\x1e\x7f\x3f\x5e\x56\x71\x17\x8b\xa0"
+           "\x95\x8f\x3d\x29\x16\x89\xd1\xfb\xe9\x49\xa5\x7d\xea\xe8\x50\xc1"
+           "\x95\x2d\xbd\x6d\x80\x0c\x74\x8d\x6c\xcd\xc2\x75\x94\x40\xb7\x24"
+           "\xf3\xf8\xe4\xf2\x1c\xeb\x1b\x58\x0c\x1a\x06\x0a\xad\x48\x4f\x13"
+           "\x12\x94\x7a\xa0\x03\xa2\x4b\x0f\xbc\xd7\xd4\xa0\x8d\x45\xab\xf1"
+           "\xd9\x1b\x1d\x1a\xa7\x9e\x5f\xe3\x07\xfd\xd4\xad\xa9\xf3\x95\xaa"
+           "\x47\xf8\x25\x2e\xca\x60\x7c\x14\x35\x8e\xb6\x23\x15\xe4\x96\x3c"
+           "\xdf\xb6\x86\xd8\x87\xe0\xf1\x7e\x04\x2a\xc2\xb7\x39\x74\x10\x52"
+           "\x18\xe7\x2d\x63\xe2\x40\xe4\xfd\xe8\x1a\xee\xb9\xdf\xe2\xf5\xcb"
+           "\x2d\x2d\x8f\x71\x38\x9e\x8a\x8b\xc9\xb3\xf8\xb0\x25\xaa\xb9\xf2"
+           "\x08\x7c\xa2\x6b\x16\x75\x65\x98\x7c\x72\x7c\x86\x7f\xba\xe3\x2b"
+           "\x68\x6e\x37\xf9\x4c\x17\xf3\xfe\xc8\xc5\xf7\x38\xfb\xe2\x33\xfd"
+           "\x62\xb8\x59\x46\x65\xf6\xc3\x06\x56\x02\xb3\x93\x17\x37\xd6\x3e"
+           "\x2d\x47\x96\x3e\xd8\x01\x97\x3a\x29\x5a\x39\x17\x58\xcb\x6b\x2e"
+           "\xf4\x6a\xeb\x4c\xb1\xff\xde\xc6\x86\x9e\x7a\x2f\xe9\x63\x4e\x99"
+           "\x58\x0d\xb3\x33\x38\x4c\xd0\xe6\x0f\x1b\x88\xe0\x87\x29\xf1\x4c"
+           "\x25\x6a\x18\x62\x93\x58\xf1\x7e\xf9\xbf\x38\x1a\x7b\x41\xf3\xa7"
+           "\xee\x39\x07\x4a\x1e\xf9\x57\x16\x41\x38\xe1\xc5\xce\x4c\x8c\xae"
+           "\xf9\x74\xc2\x40\x76\x84\xa0\x86\xec\xd3\xe3\xd6\xcc\x64\xc8\x8a"
+           "\x67\x06\x75\x54\x89\x32\xf2\x6e\xee\x96\x84\x38\xbd\xf3\xd7\xd7"
+           "\x8a\x83\x7e\xee\x9d\xb5\xcf\xb6\x91\x0b\x98\xb5\xbf\xc0\x1d\x60"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_AES, 0,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\x72\x93\xe9\x78\x6b\xd1\x11\x41\xd8\x52\x32\x0c\x8b\x5f\xc3\x93"
+           "\x0a\xae\x0e\xdc\x96\x0a\xa5\x0a\x5b\x95\x7c\xc6\xad\x30\xd0\x98"
+           "\xea\xd3\x71\xe6\x4b\x1b\x3e\xb6\xd0\xfb\x94\x23\x6b\x54\x40\xff"
+           "\xf1\xc2\x60\xb3\x2d\x20\xf9\xae\xfb\x32\x86\xf8\xc2\x05\xa7\x12"
+           "\x96\xe0\x3e\x48\x73\x56\x58\xc2\xa3\x99\x9e\xa2\xb4\x6f\xa9\x7a"
+           "\x32\x6e\xe7\xf6\xb8\x1c\x58\x2f\x55\xc6\xcd\xb5\xe5\xd2\x2f\xc8"
+           "\xff\x05\x59\x37\x75\x6c\xad\xce\x69\x74\xed\x4b\x8c\x98\x7d\xae"
+           "\xc2\x81\x9b\x7a\x46\x14\x73\x72\x34\x85\x15\x64\x96\xed\xb8\xb9"
+           "\xf1\xce\x2d\xd4\x8b\x7e\xd1\x81\xd5\x91\x9c\x10\x37\xe9\x98\x4d"
+           "\xeb\x5d\x8a\x78\xf3\x85\x6f\xc0\xb0\x85\x0b\x75\xf6\x07\xa0\x11"
+           "\xd2\x8e\x7b\x63\x23\xba\xdc\xc0\xec\x4d\xac\xeb\xde\x41\x29\x66"
+           "\x6c\x5a\x9e\x88\x69\xba\x33\xb3\x3d\x5f\x78\xb3\x36\x8b\x2d\xf3"
+           "\x37\x7e\x13\xe6\x93\x3e\xce\x00\xcf\x12\x47\x64\x55\xfe\xbd\xb6"
+           "\xa6\xd9\x41\x50\x0a\x42\x1f\xfd\xc7\xea\x6c\xc3\xac\x0f\x3d\x91"
+           "\xe5\xa1\x95\x5b\x4e\x24\xe5\x34\x1e\x03\x10\x3f\x9d\xa0\x89\x74"
+           "\xea\x26\x5c\x23\x1b\x5b\x8b\x08\x49\xce\xd8\xa8\x10\xf3\x88\x37"
+           "\x38\xc2\x9d\xba\x75\x2b\x5e\xec\xf1\xf1\x3c\x90\xab\xae\x88\xe2"
+           "\x49\xf9\xb8\xad\x7b\x8e\x30\x96\xaf\x48\xec\x37\x11\x52\xef\x49"
+           "\xea\xcb\x97\x16\x13\x7b\xf4\x03\x50\x61\x6a\xd4\x09\xfd\x66\x1d"
+           "\x56\x13\x48\x9b\xe3\x5d\xfe\x60\x47\x0a\x62\xfd\xae\xbc\x15\xc2"
+           "\x0f\xbd\xc0\xb8\x70\x4d\x89\x2d\x4e\xa5\x7b\x36\xfc\xda\xdc\xc3"
+           "\x47\x45\x8e\x86\xa8\xa6\xd3\x51\x0e\xaa\x90\x30\xef\x02\x53\x04"
+           "\x89\x92\xcc\x36\x33\x00\x9f\xdc\xa3\x7d\xbf\x0d\x10\x4f\x50\xe7"
+           "\x84\x72\xfa\x76\x57\xa6\xbd\x65\x8f\xc7\x04\xef\x03\xaf\xff\xf0"
+           "\x8c\x6f\x98\x58\xac\x95\xe7\x7e\xeb\x4d\x24\xfb\x37\xbc\x9b\x19"
+           "\x1a\x48\x2b\x86\xe4\x21\x24\xf5\x1a\xb1\x8a\xcb\x0d\x14\x6e\x4e"
+           "\x3d\x39\xed\x95\x73\xeb\xaa\x31\x56\xbe\x4d\x32\x02\x15\xf1\x24"
+           "\x9f\x23\xa6\xd8\xf4\x52\x4b\xfd\x9c\xc0\x45\x5c\xc4\xb0\xae\x4b"
+           "\x39\xca\x17\x7a\xfb\xc0\xdb\x8c\x92\x52\xd4\x37\x93\x29\x7c\x2e"
+           "\x77\xcd\x8d\x2a\xbd\x6e\x4d\x23\xe2\xff\x84\xa5\x1a\x2a\xd2\x4a"
+           "\x19\xd7\xef\x1d\xea\xcf\x79\x8f\x81\x48\x2d\x5d\x72\x58\x99\x11"
+           "\xec\x95\xda\x65\x73\x35\x34\xb1\x28\x10\x07\x94\xe8\xc1\x1e\x17"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_AES256, 0,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\x0c\x39\xef\x9d\x9b\x85\x05\x78\x93\x92\x13\xc4\xe9\xc7\x0b\x12"
+           "\x36\x73\x18\xfa\x58\x33\x09\x7f\xf4\xd2\xf8\x93\x46\x5a\xd0\xdd"
+           "\x8d\x48\x2e\x6b\xb1\xf9\x9b\xc2\x0c\x66\x88\x48\x93\xaf\x0d\xac"
+           "\x47\x3f\xbb\x84\xc5\xf8\x8d\xc1\x7c\xfe\xb8\xb9\x9f\xcc\x86\x3c"
+           "\xfd\x9f\xa3\xf9\x2c\x22\xeb\xa1\x9a\x68\x6b\xb9\x24\xf6\xe6\x74"
+           "\xb9\xc2\x73\x98\x10\xcb\xa1\x57\xa9\xfe\x6a\x10\x8c\x6e\x56\x9e"
+           "\x64\x1d\x1a\x3a\x80\xbe\xcf\xf6\xf0\xf3\x8f\x97\x64\xfd\xcf\x96"
+           "\x36\x7e\xf8\x28\x88\x31\x55\x74\x08\xe1\x02\x95\x0a\x16\xe2\x6a"
+           "\x15\xd6\xbf\xfc\x44\xf4\x30\x1e\x0e\x2e\x51\x39\xec\xa6\x3a\xf7"
+           "\x15\x9f\x1c\x54\x64\xb2\x54\x84\x73\x00\x03\xd9\x26\x30\x73\x5e"
+           "\x3a\x96\x67\xf1\x28\x2c\x84\x3c\x59\xdf\xc3\x01\x6c\xe4\x07\x33"
+           "\x2e\x16\x53\x92\xfd\xee\x1d\x47\xbe\x15\x1d\x65\x58\xb5\x9b\x08"
+           "\x04\x71\x65\xfa\x11\x49\x9d\xc6\xca\xab\x34\xb1\x40\x39\x98\xe9"
+           "\xd4\xa5\xda\x17\x74\x5e\x80\x18\xc3\xf9\xcd\x60\x34\x5c\x68\x09"
+           "\x4c\xf7\xa1\x3a\x5c\xdb\xf6\xc5\x06\xe2\x70\x98\x3b\xea\x0f\x77"
+           "\x43\x1a\x0b\x4f\x74\x54\xe8\x7c\xd6\xb2\x02\xcc\xc9\x11\x49\x65"
+           "\x4c\xb2\x2b\x5a\x39\x13\xdb\xcf\x07\x77\x27\x69\x90\xa9\xe6\x7a"
+           "\xd2\xa0\x3e\xd9\xa8\x4c\x6b\x8d\x2f\x39\x10\x67\xea\x4c\x10\xc7"
+           "\xac\x70\xf9\x50\x1d\xe7\xfd\x88\x66\xf1\xed\x36\x5c\xa1\x5f\x92"
+           "\xf6\xcb\xd2\xe1\xb0\x9d\x55\x45\xe4\x62\x3d\xec\x11\x33\x6e\x3e"
+           "\x7f\x87\x06\x1b\x4c\x71\xf0\xe5\x0f\xed\xde\xa0\x47\x85\x59\xa5"
+           "\xf4\x03\xde\x25\x8c\x23\x42\x47\x94\x1b\xa5\xbb\x2e\x09\x54\xe2"
+           "\xf8\x75\x29\xb6\xa6\x3b\x86\x1d\xa0\x4d\xbc\x5c\x49\xf1\x38\x3f"
+           "\x23\x12\x63\x98\x26\xa7\x7a\xe6\x48\x0a\x14\x1a\xcc\xd6\xf0\xc7"
+           "\xd8\x69\x1e\x39\x0a\xf5\x79\xed\x82\x79\x43\x54\x65\x15\x90\x44"
+           "\xb8\xcf\x52\x51\x7a\x9a\x32\x16\x2a\x36\xcb\x9c\xde\x48\x10\xdc"
+           "\x97\x70\x72\xc8\x83\x0f\x66\xaf\x95\x59\xfb\xca\x06\x46\x6f\x8e"
+           "\x49\xbd\x72\xcd\x8b\xa3\x69\xaa\xde\xc3\xaa\xf0\x4e\x65\x7c\x8b"
+           "\x93\xa7\xa9\x85\xdb\xf9\x7d\xdf\x6a\x52\xda\xcf\x42\xb8\x9c\x17"
+           "\x6c\xc4\xa1\x5e\x5c\x69\x76\x5d\x26\x95\x1e\x13\xdc\xa3\x57\x7a"
+           "\xb7\x8a\x4c\xb8\x88\xaa\x74\x78\xbb\xd3\xee\xfd\xc3\xa4\xa9\xf1"
+           "\x6b\x34\x1a\x79\x67\x9c\xb1\xfd\xd4\xd9\x8b\xf4\x28\xfe\xff\xc1"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_AES256, 0,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\x16\x2e\x03\x23\x3e\xa6\x2e\xd7\x51\xf9\x56\xfc\x19\xea\x01\xfe"
+           "\x81\x26\x0e\xb3\x01\x39\xa7\xb7\x06\xda\x7c\x85\xbd\xed\x14\x3f"
+           "\x1c\x01\xf4\x55\x76\x7d\xa7\x22\x15\xb4\xd8\x4d\x1d\x2c\x59\x6b"
+           "\x52\x00\x85\x00\x35\xc4\x5a\x90\x9e\xb6\xc0\x6d\x61\xca\x6d\x1f"
+           "\xed\xbd\x96\x2b\xd9\x87\xbc\xfd\xf6\x1d\xd6\x3c\xa8\x2d\x92\xb9"
+           "\xa6\xfb\xdb\x5c\xfd\xe0\x7d\x1b\x58\xfd\x36\x21\x77\xbc\xff\xdf"
+           "\x51\x1d\xd5\xef\x9a\x68\x2b\x7d\xa4\x9f\x91\xc8\x6c\x4f\x7a\xc3"
+           "\x40\xc5\x3c\xef\x92\xef\x2d\x64\x3f\x63\x8b\x82\x22\xdb\x1e\x85"
+           "\x31\x0b\x64\x7d\x31\x9d\xdc\x92\xe4\x53\x9e\x9b\xbe\x37\x07\x8d"
+           "\xeb\xe3\xae\xfb\xff\xe3\xba\xcc\xa3\x4f\x42\x54\x3e\xbb\x9f\xb6"
+           "\xa8\xf3\x6e\x76\x9a\x45\xa0\xf1\xbc\x19\x34\x26\xab\xad\x8c\x60"
+           "\x3b\x9b\x31\x7f\xb5\xf1\xbb\x8c\xbc\x71\x43\xcb\xb8\xc6\xfb\xe6"
+           "\x9c\x9b\xf0\x3f\x66\x65\xc2\xd9\x1a\x13\xd8\xea\x53\xa7\x24\xb9"
+           "\xf8\x98\xce\x2c\xc8\xee\xe7\x18\x29\x91\xdf\x6e\x27\x1d\xc2\x46"
+           "\xc2\x66\x3f\x2b\xcc\xbb\x57\xd8\xb9\x5c\xbe\xf3\x88\x4e\xa9\x99"
+           "\x95\x50\x22\xa5\xbe\x51\xe4\x37\x1a\xfa\x20\x61\x25\x2c\x7c\xac"
+           "\x42\x0e\xdb\xbd\x0f\x3c\x1a\x4f\xda\x57\x52\x61\x3a\x5a\x1e\x35"
+           "\x1f\x6d\xb7\x26\x61\x5e\xa9\x23\xc3\x56\x47\xe9\xb1\xb8\x70\x1d"
+           "\x0f\x67\xfd\x7e\x88\x15\xe2\x16\xd7\xdd\x32\x9f\x81\xfe\xe5\x97"
+           "\x05\x19\x93\xc5\xd0\x88\x32\x62\x60\x82\xc7\xb8\x65\xa5\x75\x4c"
+           "\xaf\x1e\x44\x0f\x03\x24\x09\xe2\x91\x87\xbd\xf8\xd1\x1f\x37\x77"
+           "\x7e\xe3\xa8\xdb\x23\x8b\x49\xa1\x4b\xa7\xe6\x30\x36\x01\xcc\x69"
+           "\xb4\x4a\x20\x20\x23\xdb\xcc\xcd\x57\x44\xd3\xfd\x88\xf8\xbe\x90"
+           "\x08\xb3\xed\x2d\x6c\x7b\x3d\x3d\xaf\xc6\xf4\xe6\x2d\x31\x7f\xfc"
+           "\x84\xc2\x4e\xa6\x04\xda\x96\x3a\x95\xf7\x7b\x31\x0c\x25\x1f\x0e"
+           "\x9e\xbe\xf4\x78\xc1\xcb\x3a\x6d\xab\x60\x5d\xe5\x56\x1d\x4c\x1c"
+           "\xed\xff\x40\x38\xed\xea\x89\x40\x46\x49\x47\x0a\x52\x93\x7a\x71"
+           "\x0a\xba\x8d\x12\xbe\x8f\x0b\xc6\x31\x9f\x2d\x8a\x42\x66\x06\x66"
+           "\x34\x93\xf0\x58\x1c\x9c\xc6\x41\xfc\x5e\x46\x2c\x7d\x85\x22\x82"
+           "\x28\x03\x80\x89\xfc\x05\x8e\x18\x01\x85\x38\xe5\x6a\x90\xd9\x28"
+           "\x0a\x25\xd2\xf7\xb5\x6d\x07\x21\x94\x11\x6f\xc1\xef\x9a\x89\xd9"
+           "\x02\xce\xc6\x97\x43\x29\x9a\x1f\xfd\x29\x61\x04\xe2\x64\xf2\xca"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_AES256, 0,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+       "\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\xc8\x1a\x9c\x1e\xa9\x44\x9f\x3f\x3a\xf2\x34\x91\x8e\x41\x14\xea"
+           "\xec\x88\x5e\xd0\x8c\x19\xe9\xa8\xef\x33\x0f\x43\xd8\x17\xe7\x02"
+           "\x15\xed\xfe\x3b\xbc\x97\xcc\x1d\x61\xb0\x64\xa1\x87\x6f\x72\x0c"
+           "\xed\x60\x0d\x75\x77\x12\x38\xb6\x2b\x31\xaf\x5a\x5e\x06\x2e\x85"
+           "\x01\x75\x99\x06\xf8\x94\xf0\xb5\xb6\xe9\x78\xe4\x51\x6c\x42\x8b"
+           "\x1f\xe1\x38\x68\xb5\x87\x1c\xa5\x5d\x2a\x84\xaa\xa4\xbf\x06\x8c"
+           "\x9d\xba\x41\xa7\x77\xf3\xb4\x6a\x37\xb7\xaa\xae\x49\xd6\xdf\x8d"
+           "\x19\x7b\x1d\x24\xed\x7a\xcc\x26\x78\x85\x9d\xf9\x22\xc3\xb5\xcb"
+           "\x44\x36\xcd\xaa\x0c\x5a\xf4\xa8\x5f\x3c\x65\x90\xa9\xbd\x35\x80"
+           "\x67\x3f\xc9\xc0\xde\xf4\x3c\x0e\xb1\x9c\x80\x96\x0e\x6d\x3e\xd0"
+           "\xfc\xd6\x8a\x65\xc1\xe5\x2d\x96\x23\x5b\x08\x37\xd9\xde\x82\x87"
+           "\xaa\x83\xb8\x8a\x1c\xae\xbd\x99\x24\x28\x7f\xc5\x99\x54\xff\xc0"
+           "\x85\x28\xa5\xdf\xf3\xec\x77\x69\x22\xb8\x0f\xd7\x0e\xcf\xbd\x95"
+           "\xff\xda\x89\x03\xaf\x14\x06\x47\x6e\x7a\xae\x2f\xb4\x97\x23\xae"
+           "\x42\xc6\x31\x14\xa6\x8f\xc2\x4c\xcc\x4d\x1f\xc7\x2b\xb2\x93\x71"
+           "\x80\x70\xa1\x6f\x92\xf9\xde\x5b\x1f\xb0\xc7\xa8\x8b\xe1\xeb\x3b"
+           "\x51\x74\x02\xb2\x39\xfc\xf3\xe3\x68\x80\x7b\x73\x1d\x8e\x62\x99"
+           "\x1c\xe8\x58\x18\xfa\x41\x9e\x21\x66\x9e\x24\xea\x53\xc1\x9d\x06"
+           "\x20\x86\xd6\x78\x34\xef\x9c\xb1\x49\x11\xdf\x93\xe6\xc8\x8e\xde"
+           "\xc8\x29\x99\x1a\x31\x6a\xb6\xd5\x7d\xfd\x4f\x1c\xab\xf4\x4d\xc9"
+           "\xaa\x2a\x44\xf0\x0b\x5e\x35\x0c\xab\x51\xbb\xc3\xe4\xbd\x33\xe9"
+           "\x25\xec\x7b\xf1\x04\x38\x3c\x3e\x4a\xd1\x59\x1e\x65\x20\x60\xdd"
+           "\x66\x31\x7a\xbf\x7f\x8e\x5f\xfe\x5c\x45\xdc\xb4\xd6\x92\x59\x0c"
+           "\xbf\xd6\x97\xf2\x7a\xfe\x77\x33\x40\x47\x1f\xe2\xb6\xac\x31\x8d"
+           "\x68\xaa\x76\x7e\xdc\xc6\x02\x35\xf0\x94\xcd\xc7\xcf\xc3\x86\x17"
+           "\x14\xcb\x70\x6d\x9c\x7a\x4c\xaf\xc5\xa5\xcd\x65\xb9\x7c\x1b\xd9"
+           "\x89\x77\x69\x8a\xed\xec\x38\x29\xe2\xc9\x63\x42\x84\xad\x86\x7c"
+           "\x55\x47\x84\x7a\x06\x99\x25\xaf\xef\x5a\xfd\x19\x69\x6c\x66\xd0"
+           "\x19\x89\x2a\xd1\xff\xba\x51\xd9\x84\x1c\x52\xca\x50\x11\xe6\xd4"
+           "\x73\x67\xc6\xc6\xe1\xc4\x34\x9f\x1d\x2c\x9f\x71\xa0\x42\xe9\x72"
+           "\x9e\x28\x2a\x7c\xb7\x00\xb3\x71\xc8\x77\xd2\x94\x0a\x72\x39\x62"
+           "\x7b\x2b\xaf\x8f\xd2\x17\xbc\x6a\x83\xb2\x8b\x22\xea\xf1\x2d\x98"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_AES256, 0,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\xa0\x45\x6a\x19\xf3\x06\x20\x7f\x14\xce\x28\x0f\xe3\xdf\x44\x09"
+           "\x15\x8d\xe1\xff\x64\x74\xfb\xdd\xb9\x96\x61\xd3\x57\xae\xaa\x46"
+           "\x73\xa3\x98\x8d\x07\x66\xd7\xb2\xe8\xd9\xb5\xd8\xb5\xb5\x52\x72"
+           "\x52\x33\x83\x4a\x9c\xc0\x06\x51\x38\x8c\x73\x67\xb9\xbe\x0c\x0b"
+           "\x8f\xd1\xf4\xa7\xdb\xd0\x35\x96\xcb\xeb\x63\x80\x5c\x33\x7e\xa8"
+           "\x5b\x4d\x10\x22\x33\x4b\x8c\x62\xb1\x9b\x3c\xc9\xf2\xf5\x45\x94"
+           "\x80\xf8\x18\x12\xba\xb8\xc1\x19\xdb\x4c\x70\xda\x9d\x98\xc8\x89"
+           "\xd8\x79\xe1\x25\x20\x52\xa1\x8e\xa1\x4f\x5e\x3d\xe6\xad\xe7\x35"
+           "\x3a\x81\xef\xc9\x60\xbb\xde\xc6\x8b\x5e\xae\xd1\x2c\x2e\xa3\x4c"
+           "\xb0\xd3\xe3\x12\xf7\x44\x3f\xe1\x34\x5c\xbf\xcd\xec\xa4\x1f\x45"
+           "\x47\x13\x44\xec\xee\x4f\x7b\x7c\x53\x2f\xc4\x34\x3b\x6d\x70\x34"
+           "\xd5\x9f\x61\xd5\xb4\x25\x07\xcc\x06\xfd\xc4\x34\x2a\x97\x16\xad"
+           "\x24\xa3\xa0\xd0\x3a\xc4\xd3\xb4\x22\xa8\x73\xf5\xcd\x3f\x72\x9f"
+           "\xae\x51\x6c\x7f\x3a\x5a\xfa\xdd\xdb\xbe\xcc\x09\xc8\xf8\x0a\x25"
+           "\x87\x66\x8c\x90\xe1\xdf\xff\x37\xc5\x66\xc5\x26\xe1\x42\x5f\x8d"
+           "\x18\x6a\x08\x54\xf2\x88\x2b\xc4\x12\x5f\x9d\x06\x9e\x3e\xbd\x44"
+           "\x1e\xfb\x9a\x55\x53\xcc\x21\xef\x6c\x74\x60\x04\x64\x61\xc4\x86"
+           "\x9d\x36\xdc\x2b\x68\x80\x0e\x8a\x99\x17\x07\xd3\x03\x7e\x44\x79"
+           "\xd0\x30\xec\x72\x68\xef\x34\x72\x80\xee\xb8\x86\xc1\x4e\x51\x6f"
+           "\xd3\xbd\xce\x04\x48\xbf\x0c\x40\xad\xa8\x7d\xd0\xfa\x12\xba\x64"
+           "\x0c\xc3\x83\x37\xc1\xc1\xf7\x31\x7e\x59\x1f\x8e\xa3\x81\x64\xdd"
+           "\x94\xef\xd6\xb1\xf6\xc3\x66\x58\x43\x4c\x25\xdc\x72\x6b\xf7\x37"
+           "\x0b\x68\x85\x4d\x3b\x48\x1f\x04\x1e\x44\xff\x7a\xf0\x60\x89\xf7"
+           "\xe8\x6e\x38\x9b\xa1\x63\x43\x47\xe1\x7e\x5c\xc0\xbe\x29\xb0\x75"
+           "\xe7\xf3\x19\x22\x94\xf1\xa8\x4b\x05\xf4\xb2\x5b\xa4\x24\xdd\xbf"
+           "\x19\xce\x7d\x1f\x13\x25\xde\xfa\xb9\x0b\x29\x49\x00\xa3\xfc\x13"
+           "\xd2\x76\xf9\x98\x3b\x64\x30\xb6\xa3\xb3\xc0\xa2\x25\x70\xe0\x65"
+           "\x25\x8e\xfd\xb1\x85\xd7\xd5\xc8\x4f\x52\xb5\x9e\x93\x84\xbf\xc9"
+           "\x6f\x5c\xe5\xbd\x04\xe2\xfa\xa8\xea\xfe\xa6\x63\xb0\xa7\x75\x9c"
+           "\x7c\xec\x3d\xbf\xb1\x28\xae\x1f\xd1\xdd\x57\x7b\x69\x36\xa9\xaf"
+           "\xe6\x09\xf3\x46\x5e\x7d\xc6\x4e\x7b\xec\x3c\xc9\x26\x11\xae\x20"
+           "\xe8\x6f\x27\xa8\x09\x60\xbe\xf0\xb0\xf7\x80\x71\x61\x57\x0b\xe2"
+         },
+         { "", 0, "" }
+       }
+      },
+#if USE_CAMELLIA
+      { GCRY_CIPHER_CAMELLIA256, FLAG_NOFIPS,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\x6e\x85\xe1\x26\xf0\x1a\x70\x5b\x62\x4e\x94\xa3\x07\x70\xb8\xc7"
+           "\x07\x20\x67\xc8\xd1\x30\xec\x82\x0c\x28\x0d\x01\x09\xd0\xef\x85"
+           "\xf5\xea\x24\xee\x3d\xa6\x99\x00\x78\x19\xf5\x30\x57\x6f\x43\x52"
+           "\xd2\xfc\xb5\x07\x0a\xe7\x6e\xd4\xd2\x76\x47\x6e\x5b\xb7\x28\x03"
+           "\x62\x01\xe9\xaf\xe1\x29\xf9\x3c\x86\xc7\x50\xb1\xfb\xac\x76\xf8"
+           "\x7b\x4a\x7b\x67\x63\xd8\xf1\xbc\xba\x9c\xfe\xaf\x7c\x00\xff\x51"
+           "\x82\xd8\x3d\x99\xd6\xf9\x64\xfc\xcd\x97\x6c\x4e\x30\xa3\xd8\x66"
+           "\x2d\x29\x38\x5f\x07\x67\x7e\x16\x6d\xd1\xe6\xd4\xcd\xaa\xe8\x0a"
+           "\x1d\x5e\x47\x66\x9d\x28\xf6\xb0\xf4\x1e\xe6\xff\x1c\x2e\x03\x20"
+           "\x31\x45\x24\x92\xcb\xd4\x59\xb9\xe8\x8a\xed\x3d\x01\xe2\xaa\x09"
+           "\xa4\xb8\x78\x0d\x72\xa0\x5c\x4c\x48\x82\x20\xe1\xa4\xe9\xc1\xf9"
+           "\x5c\xd5\x0d\xda\x2c\x01\x41\x94\xa3\x34\x2a\x22\xac\xf6\x1e\xc3"
+           "\xfb\x92\x70\x7f\x12\xb1\x0a\x7e\xac\x61\xbe\xce\xc1\xa6\xb4\x17"
+           "\xfd\x7e\xa7\x95\x97\xc1\x38\xc7\x20\x88\xe7\x64\x3a\xca\x90\x87"
+           "\x5e\xa5\x71\x0d\xfc\x7d\x50\x91\x71\xa0\xb9\xc2\x9a\x34\xa9\x80"
+           "\x05\x77\x30\xf5\x61\x15\x4b\x12\xa7\x6f\x19\x9a\xd3\x3a\x8c\xe9"
+           "\x8c\xf7\x65\x5f\xde\x84\x18\x20\xe6\x35\x51\x32\xab\x4a\x85\x67"
+           "\x29\xec\xb2\x82\xf4\x70\x9d\x77\x21\x0e\x4a\x80\x80\x67\x3c\x76"
+           "\x70\x34\xa7\x00\x65\xaa\xcc\x54\x97\x46\x12\xd9\xfb\x1d\xef\x04"
+           "\x58\xe3\x75\x0e\xf9\x24\x9d\xf2\x4e\xe1\x61\x7a\x7e\xc3\x32\xb2"
+           "\xfb\x80\x5f\x77\x18\x4c\x8b\xc4\xd3\xe2\xe3\x13\xc4\xe3\x98\x9b"
+           "\x86\xfe\xb2\x76\xc5\xbc\x18\xe2\xaa\x6d\x70\xe4\xfe\xf7\x10\x39"
+           "\xdd\xc7\x9f\x34\x99\x3b\x46\xa5\xf1\xf7\x80\xab\x7a\x03\x33\xfb"
+           "\x44\x74\x62\x84\xe5\x83\x05\x34\x13\x60\x1c\xfe\xc2\x34\xf5\x58"
+           "\x0e\xdd\x33\x32\x3d\xab\x1a\xfe\x83\x33\x7c\x33\x84\x85\xaa\x8c"
+           "\x69\x0c\xb0\x72\xdd\x4b\xd4\x6f\x03\x62\xf8\x59\x65\x4c\xe9\x07"
+           "\x8b\xcc\x24\x04\x6c\x05\xc9\x1d\xb7\xd5\xea\xb8\x34\x83\x23\x29"
+           "\x5e\x1f\xc9\xc8\xbf\xd9\x1e\xbf\x4d\x84\x41\x27\xf1\x51\xb3\x11"
+           "\x2a\x40\x5b\xbe\xa1\x70\xd9\x47\x65\x35\xd3\xc8\xcf\xea\x96\xbf"
+           "\xb2\x84\xda\x85\x72\xeb\x3d\xb9\x7d\xb0\x75\xfe\xdb\x6f\xa4\xe3"
+           "\xce\xa9\xdb\xa3\x95\x7a\xa8\x2c\xbf\x94\x97\x89\x29\xd8\x1b\x4d"
+           "\x44\xba\x92\x30\x80\x1c\x88\x06\xe8\xb7\x0c\xf4\x11\xfe\x66\xf2"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_CAMELLIA256, FLAG_NOFIPS,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\xdf\xe6\x82\xe0\xec\x70\x2f\x6f\xd5\x61\xd8\x31\xe7\xf3\xfb\x18"
+           "\x4f\xd3\x58\xb0\x5a\xa6\xf2\x2b\x3d\x6e\xdd\xb8\xfb\x9f\x02\x3c"
+           "\xf5\xb7\xc5\xa1\x17\xd3\x07\x8b\x3f\x07\x56\x90\xbd\x9c\x24\xa4"
+           "\x2c\x1f\x45\x93\x1e\x37\xf2\x04\xbc\x34\xae\x7d\x13\x57\xe9\xc0"
+           "\x30\x48\xad\xc1\x81\x8e\xee\x9a\xed\x8e\x0f\x9b\x16\x20\x57\x72"
+           "\xc6\x74\x40\x2e\x60\xde\x49\x40\xc2\x22\xa0\xd7\xb8\xfb\x3d\xd0"
+           "\xfc\x25\x37\x4d\xd2\x8e\x7e\x96\xd9\xdc\x19\x32\xc1\xe7\x9c\xe5"
+           "\x13\x8a\xa6\x15\xd9\x3c\xba\xa6\x8f\x80\x69\x75\x74\xaf\x91\xf3"
+           "\xac\xd2\xdf\xcd\x78\xce\x49\xb0\x59\x29\x77\x68\x7c\x35\x35\x14"
+           "\x7a\xf7\x5a\x46\x25\x9a\x1d\x6b\x97\x7c\xee\x9a\x45\x85\x05\xff"
+           "\xfc\xc9\x0c\x12\x8a\xa7\xee\xec\xaa\x8a\x5e\x43\x04\x0d\x2d\xdb"
+           "\x14\x54\xbe\x3d\x63\xe6\x90\x1e\x0c\x46\xb8\x1a\xe5\xd3\x0c\xae"
+           "\xac\xb9\xdd\xec\xab\xb9\x2f\x8a\xf5\x27\xf0\xd0\xf6\x43\x80\x72"
+           "\x04\x23\x5b\xc3\xdc\x97\xdd\x7d\x3e\xf1\x5b\xc7\xbc\xd1\x96\xfc"
+           "\xcc\xf3\xa6\x20\x76\x34\x26\xb7\x18\x59\xa4\x3e\xb2\xd1\xe3\x82"
+           "\x24\xe9\xf4\x9c\xaa\x0f\x63\xd2\xfc\x7b\x73\x35\x92\x4c\x14\x6f"
+           "\x3f\x2a\x71\xf8\x50\xf2\xaa\x09\xb6\xb1\x0c\xf8\x7b\xe1\x9f\xce"
+           "\x63\x2e\x58\x47\xdf\x9d\x58\xb0\x59\xd2\xe0\x12\x33\x00\xd9\x57"
+           "\x75\xf8\x06\xba\x58\x87\xd0\x9d\x3d\x7a\x9e\x1b\x9c\x9c\xa1\x79"
+           "\xdc\x96\x41\xff\x3a\xb6\x44\xda\x70\xad\xa3\x66\x2d\x9e\xad\xc5"
+           "\xb1\xb1\x48\xdb\x02\xf1\x26\x74\x8f\x10\x36\x19\xcc\x3b\x56\x91"
+           "\x7f\x00\x1d\x32\x79\xb3\xdd\x31\x84\x75\xf1\xf0\xb9\x6e\xcb\x09"
+           "\x0e\x3c\xb1\xe8\x1d\x72\xf9\xdf\x91\xda\x79\x09\x18\xcb\x67\xde"
+           "\xb4\x60\xea\x48\x0b\x45\xbf\x79\xeb\xc3\x86\x72\xc4\x44\x81\x51"
+           "\xcd\x93\xb4\xce\xc3\x64\xef\xaa\x1f\x66\x39\x24\x2c\xc7\x5a\xcc"
+           "\xee\x09\x9a\x60\xfb\xcc\xb2\x2e\x7a\x8b\x4f\x90\x67\x40\xba\x4c"
+           "\x67\xa4\x2b\x40\xd0\x30\xb7\xb3\x66\x56\x63\xf4\x77\x1d\x5e\x59"
+           "\xd5\x42\xec\x7a\x35\x01\xde\xf9\x50\x64\x84\x60\x06\x8c\x65\xf1"
+           "\x64\xef\x4f\x2f\xc7\xc4\x0e\xb1\x3f\xcf\x7e\x4a\x4e\x12\x21\x9c"
+           "\xc5\xe3\xc2\x9e\xa8\x4c\xee\x55\x2d\x87\xa3\x46\x20\x83\x79\x88"
+           "\x37\x82\x13\x94\x4a\x22\xaf\x1e\x10\xc1\xba\x5c\xd3\xc8\x27\x48"
+           "\x4e\x57\xb0\x3a\x22\xfc\xab\xc2\x4d\x7b\x30\xa5\xdb\x93\xb4\xe6"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_CAMELLIA256, FLAG_NOFIPS,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+       "\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\xc0\x06\xd1\xed\x3e\xe9\x12\x44\xed\x8d\x15\xb2\x7a\x92\x95\x21"
+           "\xa7\x86\x5c\x2f\xca\x3b\xa4\x1b\x0e\x7b\x96\xcd\xef\x2f\xf9\x1d"
+           "\x9f\xd9\xeb\x5b\xa0\xec\x77\x2b\x20\x81\x99\xe6\x4a\xc6\x10\x0e"
+           "\xd9\xff\x0e\xe1\x54\x5e\x28\xdc\xcf\xb2\xd1\xbb\x66\x37\x74\x3b"
+           "\xa6\x3e\x85\x6b\xe1\x4f\xb3\xb2\x9a\xff\xba\x45\x02\xd0\xa6\x0b"
+           "\x51\x9a\x15\x09\xf2\xb9\xfa\xe2\xc2\x11\x93\x09\xcf\xcb\x1e\x83"
+           "\x9e\xd1\xfb\x92\xa5\xaa\x54\xcf\x26\xeb\x53\x60\xb0\xc2\x81\xe6"
+           "\x09\x11\x18\x92\x62\xa6\x81\xce\xad\x4f\xe2\x10\x07\x40\xb0\xb2"
+           "\x0b\x54\xd7\x6b\x71\xd1\xa9\x8c\x7e\x72\x1b\xe1\x65\x18\x47\x32"
+           "\xdb\xc7\x95\xc7\x18\x22\xca\xb8\xc9\xd2\x91\xe7\x6f\xf4\x89\xe2"
+           "\x20\xf5\xd9\x90\xe6\x32\x30\xd0\x4b\x69\x03\x35\x51\x82\x54\x9a"
+           "\xde\x41\xbe\x3e\x68\x02\x9f\xa0\x82\x0b\xa6\x13\xa7\x3b\xfd\x87"
+           "\xeb\x0b\xb9\x8e\x2b\x2b\x10\x84\x05\xeb\x6b\xde\x64\xcc\xda\xe9"
+           "\x7b\x3c\x98\x4f\x0b\x22\x2e\xa2\x58\xce\xc2\xd3\x83\x23\x90\xb2"
+           "\xf8\x2b\xfe\xb0\xa9\x83\xe7\x92\xb2\x7d\x40\x41\xc2\x03\xac\x3a"
+           "\xc2\xa3\x62\x41\x10\x5c\x75\x39\xe1\x19\x7a\x41\xc9\x26\x5b\x37"
+           "\x0c\x80\x39\x86\x56\xa1\x5c\xe8\x88\x20\x74\xed\x7e\xe3\xf2\x96"
+           "\x73\x6e\xaf\x83\x7f\xea\x48\xb9\x2b\x8e\xb3\x0e\x38\xbb\xb6\x4c"
+           "\xb8\xc4\x41\x57\xef\x19\x0e\x3d\x6b\xc1\xbf\x4e\xac\xd6\x8e\x54"
+           "\xc2\xfa\x23\x4f\x74\x58\x58\xdd\xde\x66\x40\xea\xaf\xca\x8e\x2c"
+           "\x08\xf8\x86\xb5\x7a\x98\x93\xa9\x16\x9d\xb2\x90\x1e\xcb\x74\x0e"
+           "\x87\xae\xc3\xc3\x7b\xdf\xd4\x85\x52\xc5\x0c\xa5\x4e\xfc\xa4\x9d"
+           "\xb2\x4e\xc3\xb1\xb1\xf9\xb4\x61\x13\x8c\x2c\xbf\x54\xc6\x30\x07"
+           "\x2b\x68\xc1\x94\xc0\xe3\x2f\xdb\xe5\x8d\x11\x81\x32\xa6\x00\x29"
+           "\x91\x05\x0e\x9b\x2d\xaf\x5f\x7c\x36\xac\x02\x35\xa0\x10\xea\xf2"
+           "\x9a\x10\x73\xf0\xc6\xd2\x22\x0f\xc6\x41\xa0\xac\xbc\xc7\x98\x37"
+           "\x7f\xb4\xfc\x4a\x34\xb2\x77\x12\x61\x58\x30\xc2\x9c\x96\x6e\xd9"
+           "\xc2\x8d\xb0\x81\x7a\x68\x1e\xb0\x93\xf6\x4e\xeb\x2b\xa0\xcb\x44"
+           "\x07\x85\x58\xe7\x57\x68\xfd\x0d\xd2\xf7\x01\x79\xbd\x86\x75\x09"
+           "\x13\x96\xf3\x8c\xa9\x1b\x30\x06\x9d\x8a\x53\x84\x7d\x24\x02\xe2"
+           "\x14\x7f\x76\x5f\x91\xad\x88\xe2\x53\xdc\xbe\x6a\x13\x78\xb7\xd5"
+           "\xa9\x79\x56\xa8\x5b\x08\xce\xb6\x86\xd9\x1e\x0e\x26\x7f\x67\xf5"
+         },
+         { "", 0, "" }
+       }
+      },
+      { GCRY_CIPHER_CAMELLIA256, FLAG_NOFIPS,
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xfa",
+       { { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+           32 * 16,
+           "\xac\xc5\xeb\x09\x8b\x1c\x42\xa6\x46\x50\xeb\x19\xe9\x93\xbc\x39"
+           "\x50\x93\xdb\x3d\x2c\x34\x92\xad\xba\x29\xf2\x03\x19\xb4\xda\xf4"
+           "\xe0\x3f\x10\xb4\x07\x9e\xa4\x0a\xab\xd5\xd2\x46\x13\x79\x8b\xf9"
+           "\xd0\x76\x6c\x3e\xb3\x39\x09\x68\x2c\x60\x87\x34\x3c\x66\x72\x06"
+           "\x0d\xab\xb4\xf1\xe3\x8c\x05\xfb\x58\x73\xbe\x2b\x5e\x0f\x0d\xba"
+           "\xa2\xeb\x21\x33\x22\x98\x24\x88\xd7\xf4\x4e\x9b\xa3\x81\xe5\xcb"
+           "\xaa\x84\xd3\xa6\x29\x3f\x0e\x07\x2f\x2d\xea\x0a\xf1\x13\xaf\x5d"
+           "\x5d\x62\x3d\x35\x8d\x50\xd4\x49\xf9\x39\x37\xea\x57\xc5\x2e\x35"
+           "\x5b\xf9\xa7\xd9\x2e\xc0\x2d\x39\x27\xcb\x83\x03\x3f\x2b\x17\x18"
+           "\xcd\xb4\x67\x63\xd3\xf5\x28\xfd\x00\xb9\x96\xb8\xa7\xaf\x94\x9f"
+           "\x5e\xd7\xca\x26\x9b\xd3\x8e\x83\x65\x8f\xa0\xcb\x83\x86\xae\x70"
+           "\xaa\x04\x76\x54\x79\xef\x89\x5e\x81\x78\x7f\x49\x05\xab\x45\x70"
+           "\x01\x6f\x87\x9d\xdc\x2a\xb2\xd6\xd7\x00\xc7\x61\xea\xb7\xb5\xf5"
+           "\x98\x56\x20\x70\xa5\x8d\x8d\x7f\x91\xd2\xee\xe5\xf0\x7c\xf7\xd0"
+           "\x12\x27\x03\x8d\x24\x06\x54\x81\x5a\x6b\xe8\x2f\xf9\x4c\xd6\xa4"
+           "\x03\x4f\xd8\xee\x18\x8b\xef\x27\x89\xb2\x2a\x51\xde\xa1\xa8\x55"
+           "\xa6\x1e\xd7\x4c\xcd\x22\x65\x20\xac\xf1\x17\xaf\xf5\x0a\x50\x05"
+           "\xaf\x93\x26\xb5\xa3\x37\xf6\x87\x83\x5f\xde\x4e\x18\xe2\x2f\xae"
+           "\xc6\x57\x56\x4f\x33\x16\xbc\xdc\xad\x89\xf2\x9d\xe8\x7c\x6c\x33"
+           "\x70\x51\xe2\x9c\x29\x16\x2e\x57\x47\x14\x8c\xc4\x98\x2a\x12\x92"
+           "\xb8\xc0\x85\x70\xa2\xd8\x33\x80\x38\xb0\x95\xae\x47\x26\x40\x88"
+           "\x48\x0a\xa8\xfe\x35\x29\x9a\xdb\x41\x1d\x5a\xdc\xf0\xa1\x9e\xaf"
+           "\x44\xae\x53\xb7\xd9\xe8\x2c\xe9\x0a\xe7\x88\xb7\x95\x9e\x40\xd1"
+           "\xf4\x48\x20\x2d\x93\xcf\x03\xc8\xa6\x22\x95\x35\x7a\xef\x80\xa5"
+           "\x8c\x37\x23\x83\x97\x31\xea\xdf\x73\x63\xa8\xc6\xa2\x92\xd8\x92"
+           "\x3f\x89\xaa\x90\x61\xef\x8c\x4b\x3d\xfe\x07\xb0\x9e\xf2\x0c\xee"
+           "\x94\x1d\x53\x70\x54\xf9\xdf\x92\x78\x88\xe5\x27\x3f\x8c\x4f\x8c"
+           "\xe3\xc6\x50\xe4\x94\x5b\x40\x9b\xc6\x92\x7f\x61\xa8\x17\xdf\x38"
+           "\xc0\x7d\x6d\x65\x71\x53\xb9\xa6\xad\x43\x9d\xc0\x3b\x7b\xa2\xc6"
+           "\x14\x82\xe3\x11\xce\x15\x5d\xc4\xa4\x0c\x1a\x29\xcd\x2b\x43\x8e"
+           "\xb5\x80\x16\xe5\x0d\xed\x06\xc9\x4d\x03\x79\x93\x45\x13\xee\x37"
+           "\xcf\x8d\x18\x7c\x19\xc0\x8c\x15\xa6\x2f\x64\xed\xa5\x6f\x5f\x61"
+         },
+         { "", 0, "" }
+       }
+      },
+#endif /*USE_CAMELLIA*/
 #if USE_CAST5
       /* A selfmade test vector using an 64 bit block cipher.  */
-      {        GCRY_CIPHER_CAST5,
+      {        GCRY_CIPHER_CAST5, FLAG_NOFIPS,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8",
         {{"\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
@@ -633,7 +2121,41 @@ check_ctr_cipher (void)
        }
       },
 #endif /*USE_CAST5*/
-      {        0,
+#if USE_SM4
+      {        GCRY_CIPHER_SM4, FLAG_NOFIPS,
+        "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        { { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb"
+            "\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+            "\xee\xee\xee\xee\xee\xee\xee\xee\xff\xff\xff\xff\xff\xff\xff\xff"
+            "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb",
+            64,
+            "\xac\x32\x36\xcb\x97\x0c\xc2\x07\x91\x36\x4c\x39\x5a\x13\x42\xd1"
+            "\xa3\xcb\xc1\x87\x8c\x6f\x30\xcd\x07\x4c\xce\x38\x5c\xdd\x70\xc7"
+            "\xf2\x34\xbc\x0e\x24\xc1\x19\x80\xfd\x12\x86\x31\x0c\xe3\x7b\x92"
+            "\x6e\x02\xfc\xd0\xfa\xa0\xba\xf3\x8b\x29\x33\x85\x1d\x82\x45\x14" },
+
+          { "", 0, "" }
+        }
+      },
+      {        GCRY_CIPHER_SM4, FLAG_NOFIPS,
+        "\xfe\xdc\xba\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xab\xcd\xef",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        { { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb"
+            "\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+            "\xee\xee\xee\xee\xee\xee\xee\xee\xff\xff\xff\xff\xff\xff\xff\xff"
+            "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb",
+            64,
+            "\x5d\xcc\xcd\x25\xb9\x5a\xb0\x74\x17\xa0\x85\x12\xee\x16\x0e\x2f"
+            "\x8f\x66\x15\x21\xcb\xba\xb4\x4c\xc8\x71\x38\x44\x5b\xc2\x9e\x5c"
+            "\x0a\xe0\x29\x72\x05\xd6\x27\x04\x17\x3b\x21\x23\x9b\x88\x7f\x6c"
+            "\x8c\xb5\xb8\x00\x91\x7a\x24\x88\x28\x4b\xde\x9e\x16\xea\x29\x06" },
+
+          { "", 0, "" }
+        }
+      },
+#endif /* USE_SM4 */
+      {        0, 0,
        "",
        "",
        {
@@ -642,7 +2164,7 @@ check_ctr_cipher (void)
       }
     };
   gcry_cipher_hd_t hde, hdd;
-  unsigned char out[MAX_DATA_LEN];
+  unsigned char out[32 * 16];
   int i, j, keylen, blklen;
   gcry_error_t err = 0;
   size_t taglen2;
@@ -654,11 +2176,23 @@ check_ctr_cipher (void)
       if (!tv[i].algo)
         continue;
 
-      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    tv[i].algo);
+          if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+            {
+              if (verbose)
+                fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                        tv[i].algo);
+            }
+          else
+           fail ("algo %d CTR, gcry_cipher_test_algo unexpectedly failed: %s\n",
+                  tv[i].algo, gpg_strerror (err));
+          continue;
+        }
+      else if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+        {
+         fail ("algo %d CTR, gcry_cipher_test_algo did not fail as expected\n",
+                tv[i].algo);
           continue;
         }
 
@@ -726,7 +2260,7 @@ check_ctr_cipher (void)
                 tv[i].algo);
       for (j = 0; tv[i].data[j].inlen; j++)
        {
-         err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
+         err = gcry_cipher_encrypt (hde, out, sizeof(out),
                                     tv[i].data[j].plaintext,
                                     tv[i].data[j].inlen == -1 ?
                                     strlen ((char*)tv[i].data[j].plaintext) :
@@ -768,7 +2302,7 @@ check_ctr_cipher (void)
 
       /* Now check that we get valid return codes back for good and
          bad inputs.  */
-      err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
+      err = gcry_cipher_encrypt (hde, out, sizeof(out),
                                  "1234567890123456", 16);
       if (err)
         fail ("aes-ctr, encryption failed for valid input");
@@ -792,7 +2326,7 @@ check_ctr_cipher (void)
               gpg_strerror (err));
 
       /* Again, now for decryption.  */
-      err = gcry_cipher_decrypt (hde, out, MAX_DATA_LEN,
+      err = gcry_cipher_decrypt (hde, out, sizeof(out),
                                  "1234567890123456", 16);
       if (err)
         fail ("aes-ctr, decryption failed for valid input");
@@ -828,7 +2362,7 @@ check_cfb_cipher (void)
   static const struct tv
   {
     int algo;
-    int cfb8;
+    int flags;
     char key[MAX_DATA_LEN];
     char iv[MAX_DATA_LEN];
     struct data
@@ -838,6 +2372,7 @@ check_cfb_cipher (void)
       char out[MAX_DATA_LEN];
     }
     data[MAX_DATA_LEN];
+    const char *oid; /* For gost 28147 param sets */
   } tv[] =
     {
       /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
@@ -894,7 +2429,7 @@ check_cfb_cipher (void)
             "\x75\xa3\x85\x74\x1a\xb9\xce\xf8\x20\x31\x62\x3d\x55\xb1\xe4\x71" }
         }
       },
-      { GCRY_CIPHER_AES, 1,
+      { GCRY_CIPHER_AES, FLAG_CFB8,
        "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
        { { "\x6b",
@@ -911,7 +2446,7 @@ check_cfb_cipher (void)
            "\x4c"},
        }
       },
-      { GCRY_CIPHER_AES192, 1,
+      { GCRY_CIPHER_AES192, FLAG_CFB8,
        "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5"
        "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
@@ -929,7 +2464,7 @@ check_cfb_cipher (void)
            "\x1e"},
         }
       },
-      { GCRY_CIPHER_AES256, 1,
+      { GCRY_CIPHER_AES256, FLAG_CFB8,
        "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
        "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
@@ -947,7 +2482,7 @@ check_cfb_cipher (void)
            "\x85"},
         }
       },
-      { GCRY_CIPHER_AES, 1,
+      { GCRY_CIPHER_AES, FLAG_CFB8,
        "\x3a\x6f\x91\x59\x26\x3f\xa6\xce\xf2\xa0\x75\xca\xfa\xce\x58\x17",
        "\x0f\xc2\x36\x62\xb7\xdb\xf7\x38\x27\xf0\xc7\xde\x32\x1c\xa3\x6e",
        { { "\x87\xef\xeb\x8d\x55\x9e\xd3\x36\x77\x28",
@@ -955,7 +2490,7 @@ check_cfb_cipher (void)
            "\x8e\x9c\x50\x42\x56\x14\xd5\x40\xce\x11"},
        }
       },
-      { GCRY_CIPHER_AES192, 1,
+      { GCRY_CIPHER_AES192, FLAG_CFB8,
        "\x53\x7e\x7b\xf6\x61\xfd\x40\x24\xa0\x24\x61\x3f\x15\xb1\x36\x90"
        "\xf7\xd0\xc8\x47\xc1\xe1\x89\x65",
        "\x3a\x81\xf9\xd9\xd3\xc1\x55\xb0\xca\xad\x5d\x73\x34\x94\x76\xfc",
@@ -964,7 +2499,7 @@ check_cfb_cipher (void)
            "\x38\x79\xfe\xa7\x2a\xc9\x99\x29\xe5\x3a"},
        }
       },
-      { GCRY_CIPHER_AES256, 1,
+      { GCRY_CIPHER_AES256, FLAG_CFB8,
        "\xeb\xbb\x45\x66\xb5\xe1\x82\xe0\xf0\x72\x46\x6b\x0b\x31\x1d\xf3"
        "\x8f\x91\x75\xbc\x02\x13\xa5\x53\x0b\xce\x2e\xc4\xd7\x4f\x40\x0d",
        "\x09\x56\xa4\x8e\x01\x00\x2c\x9e\x16\x37\x6d\x6e\x30\x8d\xba\xd1",
@@ -973,7 +2508,8 @@ check_cfb_cipher (void)
            "\x63\x8c\x68\x23\xe7\x25\x6f\xb5\x62\x6e"},
        }
       },
-      { GCRY_CIPHER_3DES, 1,
+#if USE_DES
+      { GCRY_CIPHER_3DES, FLAG_CFB8 | FLAG_NOFIPS,
        "\xe3\x34\x7a\x6b\x0b\xc1\x15\x2c\x64\x2a\x25\xcb\xd3\xbc\x31\xab"
        "\xfb\xa1\x62\xa8\x1f\x19\x7c\x15",
        "\xb7\x40\xcc\x21\xe9\x25\xe3\xc8",
@@ -982,7 +2518,7 @@ check_cfb_cipher (void)
            "\xf4\x80\x1a\x8d\x03\x9d\xb4\xca\x8f\xf6"},
        }
       },
-      { GCRY_CIPHER_3DES, 1,
+      { GCRY_CIPHER_3DES, FLAG_CFB8 | FLAG_NOFIPS,
        "\x7c\xa2\x89\x38\xba\x6b\xec\x1f\xfe\xc7\x8f\x7c\xd6\x97\x61\x94"
        "\x7c\xa2\x89\x38\xba\x6b\xec\x1f",
        "\x95\x38\x96\x58\x6e\x49\xd3\x8f",
@@ -991,6 +2527,170 @@ check_cfb_cipher (void)
            "\xf2\x0e\x53\x66\x74\xa6\x6f\xa7\x38\x05"},
        }
       },
+#endif /* USE_DES */
+#if USE_GOST28147
+      { GCRY_CIPHER_GOST28147_MESH, FLAG_NOFIPS,
+       "\x48\x0c\x74\x1b\x02\x6b\x55\xd5\xb6\x6d\xd7\x1d\x40\x48\x05\x6b"
+       "\x6d\xeb\x3c\x29\x0f\x84\x80\x23\xee\x0d\x47\x77\xe3\xfe\x61\xc9",
+       "\x1f\x3f\x82\x1e\x0d\xd8\x1e\x22",
+       { { "\x8c\x9c\x44\x35\xfb\xe9\xa5\xa3\xa0\xae\x28\x56\x91\x10\x8e\x1e"
+           "\xd2\xbb\x18\x53\x81\x27\x0d\xa6\x68\x59\x36\xc5\x81\x62\x9a\x8e"
+           "\x7d\x50\xf1\x6f\x97\x62\x29\xec\x80\x51\xe3\x7d\x6c\xc4\x07\x95"
+           "\x28\x63\xdc\xb4\xb9\x2d\xb8\x13\xb1\x05\xb5\xf9\xeb\x75\x37\x4e"
+           "\xf7\xbf\x51\xf1\x98\x86\x43\xc4\xe4\x3d\x3e\xa7\x62\xec\x41\x59"
+           "\xe0\xbd\xfb\xb6\xfd\xec\xe0\x77\x13\xd2\x59\x90\xa1\xb8\x97\x6b"
+           "\x3d\x8b\x7d\xfc\x9d\xca\x82\x73\x32\x70\x0a\x74\x03\xc6\x0c\x26"
+           "\x7f\x56\xf0\x9d\xb2\xeb\x71\x40\xd7\xc3\xb1\xa7\xc5\x1e\x20\x17"
+           "\xb3\x50\x1d\x8a\x6e\x19\xcb\xbe\x20\x86\x2b\xd6\x1c\xfd\xb4\xb7"
+           "\x5d\x9a\xb3\xe3\x7d\x15\x7a\x35\x01\x9f\x5d\x65\x89\x4b\x34\xc6"
+           "\xf4\x81\x3f\x78\x30\xcf\xe9\x15\x90\x9a\xf9\xde\xba\x63\xd0\x19"
+           "\x14\x66\x3c\xb9\xa4\xb2\x84\x94\x02\xcf\xce\x20\xcf\x76\xe7\xc5"
+           "\x48\xf7\x69\x3a\x5d\xec\xaf\x41\xa7\x12\x64\x83\xf5\x99\x1e\x9e"
+           "\xb2\xab\x86\x16\x00\x23\x8e\xe6\xd9\x80\x0b\x6d\xc5\x93\xe2\x5c"
+           "\x8c\xd8\x5e\x5a\xae\x4a\x85\xfd\x76\x01\xea\x30\xf3\x78\x34\x10"
+           "\x72\x51\xbc\x9f\x76\xce\x1f\xd4\x8f\x33\x50\x34\xc7\x4d\x7b\xcf"
+           "\x91\x63\x7d\x82\x9e\xa1\x23\x45\xf5\x45\xac\x98\x7a\x48\xff\x64"
+           "\xd5\x59\x47\xde\x2b\x3f\xfa\xec\x50\xe0\x81\x60\x8b\xc3\xfc\x80"
+           "\x98\x17\xc7\xa3\xc2\x57\x3d\xab\x91\x67\xf5\xc4\xab\x92\xc8\xd6"
+           "\x3b\x6b\x3f\xff\x15\x6b\xcf\x53\x65\x02\xf1\x74\xca\xa9\xbe\x24"
+           "\xd2\xf0\xb7\x26\xa8\xd7\x6d\xed\x90\x36\x7b\x3e\x41\xa9\x7f\xa3"
+           "\x1b\xf4\x43\xc5\x51\xbe\x28\x59\xe9\x45\x26\x49\x38\x32\xf8\xf3"
+           "\x92\x6e\x30\xcc\xb0\xa0\xf9\x01\x14\xc8\xba\xd9\xf0\x2a\x29\xe2"
+           "\x52\x9a\x76\x95\x3a\x16\x32\xec\xf4\x10\xec\xee\x47\x00\x70\x19"
+           "\xe4\x72\x35\x66\x44\x53\x2d\xa2\xf3\xaa\x7e\x8a\x33\x13\xcd\xc8"
+           "\xbf\x0e\x40\x90\x00\xe4\x42\xc3\x09\x84\xe1\x66\x17\xa2\xaf\x03"
+           "\xab\x6b\xa1\xec\xfb\x17\x72\x81\xfe\x9a\x9f\xf4\xb2\x33\x1f\xae"
+           "\x0c\xd1\x6a\xae\x19\xb8\xaf\xec\xe3\xea\x00\xf8\xac\x87\x07\x5f"
+           "\x6d\xb0\xac\x6b\x22\x48\x36\xbf\x22\x18\xb0\x03\x9f\x6c\x70\x45"
+           "\x36\xf0\x6b\xc6\xc2\xa5\x72\x2c\xd8\xe0\x27\x3d\xec\x56\x07\x05"
+           "\x7d\x83\xa1\x65\x7d\x41\x5b\xcd\x77\x24\xe5\xaa\x76\x47\xd0\x50"
+           "\xf6\xe7\xb5\x59\x75\x31\x27\xef\xd8\xa6\x4e\x7f\xb8\x40\xb1\xdf"
+           "\x53\x14\xed\xf1\x68\x5f\xfc\x3f\x02\xdb\x05\xeb\x31\xe4\x2c\x7f"
+           "\x32\xb5\x70\x8e\x75\x85\xa4\x5c\x16\x23\x37\xf2\x10\x79\xcb\xdc"
+           "\xf8\x1c\x25\xc2\xa1\x3d\x9c\x33\x6c\xed\xc3\xe7\xf3\x02\x87\x82"
+           "\x4e\xfb\xac\xb3\x2d\xfc\xf8\x0d\x1d\x4a\x39\xd4\xb3\x09\xbb\xe9"
+           "\x25\xc7\xec\x6a\x87\x72\x84\xed\x12\x60\x19\x64\xeb\x16\x2a\x5b"
+           "\x10\x76\x27\xff\x7b\xe4\xae\xe5\xa4\x04\x02\x7f\xbb\x0a\xb5\xf4"
+           "\x05\xa5\x56\x1c\x53\x31\x7a\x93\xba\x16\x15\xab\x62\x60\xfc\xde"
+           "\x72\x36\x6e\x28\xaf\x98\x0d\xe6\xf4\xde\x60\xa7\x7e\x06\x07\x86"
+           "\xf3\x94\xb6\x6d\x0d\x93\xa6\xbc\x60\x70\x33\xac\x3f\xa1\xa8\x4a"
+           "\x20\x61\xb6\xb5\x43\xa3\x15\x5a\x00\xbe\x76\x98\x57\x72\xab\x7a"
+           "\x0e\x18\x93\x82\x3a\x18\x78\x6e\x71\x7b\x78\x4f\x7e\x8c\xde\x7a"
+           "\x62\xb5\x0a\x7c\x45\x1d\x16\xd5\xc3\x8c\x9b\x25\xb4\x50\x90\xcd"
+           "\x96\x93\xad\x0f\xd4\x43\xcb\x49\x0f\xfc\x5a\x31\xf4\x19\xb7\xd4"
+           "\xeb\x4d\x40\x58\xd0\x3b\xc8\xe0\x4a\x54\x2f\xdb\x22\xc3\x29\x7b"
+           "\x40\x90\x61\x43\xd3\x7e\xe2\x30\x2b\x48\x3c\xce\x90\x93\xb1\x8b"
+           "\x31\x96\x65\x6d\x57\x8b\x9d\x4d\x53\xf0\x83\x1c\xe5\xa1\x9d\x55"
+           "\xe3\xbf\x7e\xca\x1a\x74\x66\x14\xcc\x47\x43\xd9\xbb\xef\x97\x7d"
+           "\xb7\x6e\xff\xf1\x22\xf8\x10\x2d\x3f\xcd\x49\x96\xd9\x09\x11\xb8"
+           "\x33\xd0\x23\x9a\xfa\x16\xcb\x50\x26\x57\x24\x5c\x0e\xba\xf0\x3f"
+           "\x37\x2f\xa3\xf7\x18\x57\x48\x48\x95\xcf\xef\x87\x67\x2a\xe9\xb6"
+           "\x8a\x21\x36\x7f\xff\x48\x6c\x46\x35\x57\xf2\xbc\x48\x67\x8f\x63"
+           "\x23\x78\x11\x2b\xc2\x08\xde\x51\xe8\x8b\x92\x29\xf9\x9a\x9e\xad"
+           "\xed\x0f\xeb\xa2\xd2\x40\x92\xd4\xde\x62\x95\x76\xfd\x6e\x3c\xbf"
+           "\xc0\xd7\x0d\xe5\x1b\xa4\xc7\x18\xe1\x58\xa4\x56\xef\x2e\x17\x1b"
+           "\x75\xcb\xbc\xf9\x2a\x95\x71\xa7\x1d\x7f\xe7\x73\x63\x05\x6b\x19"
+           "\x4c\xf4\x22\x14\xc4\x59\x88\x66\x92\x86\x61\x5c\x6a\xae\xec\x58"
+           "\xff\xc9\xf2\x44\xd4\xa2\xf5\x98\xeb\x5f\x09\xbc\x8a\xbf\x3c\xb4"
+           "\x3e\xb1\x20\x05\x44\x96\x79\x0a\x40\x92\x7f\x9d\xd1\xaf\xbc\x90"
+           "\x95\x0a\x81\xd4\xa7\xc6\xb8\xe0\xe4\x39\x30\x1d\x79\xc0\xe5\xfa"
+           "\xb4\xe9\x63\xb4\x09\x72\x3b\x3e\xd9\xf6\xd9\x10\x21\x18\x7e\xe5"
+           "\xad\x81\xd7\xd5\x82\xd0\x8c\x3b\x38\x95\xf8\x92\x01\xa9\x92\x00"
+           "\x70\xd1\xa7\x88\x77\x1f\x3a\xeb\xb5\xe4\xf5\x9d\xc7\x37\x86\xb2"
+           "\x12\x46\x34\x19\x72\x8c\xf5\x8c\xf6\x78\x98\xe0\x7c\xd3\xf4",
+           1039,
+           "\x23\xc6\x7f\x20\xa1\x23\x58\xbc\x7b\x05\xdb\x21\x15\xcf\x96\x41"
+           "\xc7\x88\xef\x76\x5c\x49\xdb\x42\xbf\xf3\xc0\xf5\xbd\x5d\xd9\x8e"
+           "\xaf\x3d\xf4\xe4\xda\x88\xbd\xbc\x47\x5d\x76\x07\xc9\x5f\x54\x1d"
+           "\x1d\x6a\xa1\x2e\x18\xd6\x60\x84\x02\x18\x37\x92\x92\x15\xab\x21"
+           "\xee\x21\xcc\x71\x6e\x51\xd9\x2b\xcc\x81\x97\x3f\xeb\x45\x99\xb8"
+           "\x1b\xda\xff\x90\xd3\x41\x06\x9c\x3f\xfb\xe4\xb2\xdc\xc9\x03\x0d"
+           "\xa7\xae\xd7\x7d\x02\xb8\x32\xab\xf3\x65\xa3\x65\x6c\x4e\xe4\xa2"
+           "\x5e\x9e\xee\xcd\xde\x79\x36\x6b\x1b\xe1\x3c\xdf\x10\xad\x4f\x02"
+           "\xe1\x14\xaa\x09\xb4\x0b\x76\xeb\x69\x38\x20\x02\xcb\x8e\xc0\xdf"
+           "\xca\x48\x74\xc3\x31\xad\x42\x2c\x51\x9b\xd0\x6a\xc1\x36\xd7\x21"
+           "\xdf\xb0\x45\xba\xca\x7f\x35\x20\x28\xbb\xc1\x76\xfd\x43\x5d\x23"
+           "\x7d\x31\x84\x1a\x97\x4d\x83\xaa\x7e\xf1\xc4\xe6\x83\xac\x0d\xef"
+           "\xef\x3c\xa4\x7c\x48\xe4\xc8\xca\x0d\x7d\xea\x7c\x45\xd7\x73\x50"
+           "\x25\x1d\x01\xc4\x02\x1a\xcd\xe0\x38\x5b\xa8\x5a\x16\x9a\x10\x59"
+           "\x74\xd7\x19\xc6\xf3\xb5\x17\xf6\x59\x8d\x62\xaf\x44\xe8\xdc\xe9"
+           "\xc1\x76\xf1\xd0\xbd\x29\xd7\xec\x1d\xac\x57\xdb\x1a\x3f\xd8\xf6"
+           "\x6e\xb6\xe6\xdf\x36\xe7\x89\xce\x56\x35\x43\x1c\x7d\x57\x79\x0e"
+           "\xd8\xf4\xd7\xa7\x0d\xc6\x8f\x91\x66\x67\x82\x0f\x49\xc9\xc5\x65"
+           "\x81\xa1\x39\x5a\x53\x9f\x02\xa5\xd5\x36\x22\xa8\xa8\x1c\x37\x0e"
+           "\x76\x46\xdf\xbd\x6a\xdb\xfc\x1b\xbd\x10\xb8\xb1\xbc\x72\x4c\x58"
+           "\x4a\xda\x6d\x66\x00\xda\x7a\x66\xa0\xe7\x3b\x39\xa3\xf7\x05\x07"
+           "\xfa\x21\x4b\xc7\x94\xc0\xd3\x7b\x19\x02\x5d\x4a\x10\xf1\xc2\x0f"
+           "\x19\x68\x27\xc7\x7d\xbf\x55\x03\x57\x7d\xaf\x77\xae\x80\x2f\x7a"
+           "\xe6\x1f\x4b\xdc\x15\x18\xc0\x62\xa1\xe8\xd9\x1c\x9e\x8c\x96\x39"
+           "\xc1\xc4\x88\xf7\x0c\xe1\x04\x84\x68\x51\xce\xf1\x90\xda\x7f\x76"
+           "\xc8\xc0\x88\xef\x8e\x15\x25\x3e\x7b\xe4\x79\xb5\x66\x2d\x9c\xd1"
+           "\x13\xda\xd0\xd5\x46\xd5\x8d\x46\x18\x07\xee\xd8\xc9\x64\xe3\xbe"
+           "\x0e\x68\x27\x09\x96\x26\xf6\xe2\x19\x61\x3f\xf4\x58\x27\x0a\xeb"
+           "\xce\x7c\xb6\x68\x92\xe7\x12\x3b\x31\xd4\x48\xdf\x35\x8d\xf4\x86"
+           "\x42\x2a\x15\x4b\xe8\x19\x1f\x26\x65\x9b\xa8\xda\x4b\x79\x1f\x8e"
+           "\xe6\x13\x7e\x49\x8f\xc1\xce\xdc\x5e\x64\x74\xce\x02\x78\xe0\xcf"
+           "\xa0\xed\x5e\x31\x74\xd1\xd0\xb4\xee\x70\x19\x14\x3c\x8f\x16\xa6"
+           "\xcf\x12\x93\x15\x88\xeb\x91\x65\x76\x98\xfd\xa1\x94\x30\xba\x43"
+           "\x62\x65\x40\x04\x77\x9e\xd6\xab\x8b\x0d\x93\x80\x50\x5f\xa2\x76"
+           "\x20\xa7\xd6\x9c\x27\x15\x27\xbc\xa5\x5a\xbf\xe9\x92\x82\x05\xa8"
+           "\x41\xe9\xb5\x60\xd5\xc0\xd7\x4b\xad\x38\xb2\xe9\xd1\xe5\x51\x5f"
+           "\x24\x78\x24\x9a\x23\xd2\xc2\x48\xbd\x0e\xf1\x37\x72\x91\x87\xb0"
+           "\x4e\xbd\x99\x6b\x2c\x01\xb6\x79\x69\xec\x0c\xed\xe5\x3f\x50\x64"
+           "\x7c\xb9\xdd\xe1\x92\x81\xb5\xd0\xcb\x17\x83\x86\x8b\xea\x4f\x93"
+           "\x08\xbc\x22\x0c\xef\xe8\x0d\xf5\x9e\x23\xe1\xf9\xb7\x6b\x45\x0b"
+           "\xcb\xa9\xb6\x4d\x28\x25\xba\x3e\x86\xf2\x75\x47\x5d\x9d\x6b\xf6"
+           "\x8a\x05\x58\x73\x3d\x00\xde\xfd\x69\xb1\x61\x16\xf5\x2e\xb0\x9f"
+           "\x31\x6a\x00\xb9\xef\x71\x63\x47\xa3\xca\xe0\x40\xa8\x7e\x02\x04"
+           "\xfe\xe5\xce\x48\x73\xe3\x94\xcf\xe2\xff\x29\x7e\xf6\x32\xbb\xb7"
+           "\x55\x12\x21\x7a\x9c\x75\x04\x0c\xb4\x7c\xb0\x3d\x40\xb3\x11\x9a"
+           "\x7a\x9a\x13\xfb\x77\xa7\x51\x68\xf7\x05\x47\x3b\x0f\x52\x5c\xe6"
+           "\xc2\x99\x3a\x37\x54\x5c\x4f\x2b\xa7\x01\x08\x74\xbc\x91\xe3\xe2"
+           "\xfe\x65\x94\xfd\x3d\x18\xe0\xf0\x62\xed\xc2\x10\x82\x9c\x58\x7f"
+           "\xb2\xa3\x87\x8a\x74\xd9\xc1\xfb\x84\x28\x17\xc7\x2b\xcb\x53\x1f"
+           "\x4e\x8a\x82\xfc\xb4\x3f\xc1\x47\x25\xf3\x21\xdc\x4c\x2d\x08\xfa"
+           "\xe7\x0f\x03\xa9\x68\xde\x6b\x41\xa0\xf9\x41\x6c\x57\x4d\x3a\x0e"
+           "\xea\x51\xca\x9f\x97\x11\x7d\xf6\x8e\x88\x63\x67\xc9\x65\x13\xca"
+           "\x38\xed\x35\xbe\xf4\x27\xa9\xfc\xa9\xe6\xc3\x40\x86\x08\x39\x72"
+           "\x37\xee\xb2\x87\x09\x96\xb7\x40\x87\x36\x92\xc1\x5d\x6a\x2c\x43"
+           "\xca\x25\xc8\x35\x37\x2d\xb5\xa9\x27\x44\x50\xf2\x6d\x22\x75\x41"
+           "\x77\x2a\xdb\xb1\x8c\x6d\x05\xe8\xc9\x99\xc7\x08\xf9\x14\x8f\x78"
+           "\xa9\x8f\xc2\x5a\x7a\x65\xc5\xd8\x86\xbb\x72\x69\x6b\x6b\x45\x83"
+           "\x5b\xb1\xf7\xcd\x16\x73\xee\xe9\x80\x85\xfe\x8e\xe1\xae\x53\x8f"
+           "\xde\xbe\x48\x8b\x59\xef\xf6\x7e\xd8\xb5\xa8\x47\xc0\x4e\x15\x58"
+           "\xca\xd3\x2f\xf8\x6c\xa6\x3d\x78\x4d\x7a\x54\xd6\x10\xe5\xcc\x05"
+           "\xe2\x29\xb5\x86\x07\x39\x7d\x78\x8e\x5a\x8f\x83\x4c\xe7\x3d\x68"
+           "\x3e\xe5\x02\xe6\x64\x4f\x5e\xb4\x49\x77\xf0\xc0\xfa\x6f\xc8\xfb"
+           "\x9f\x84\x6f\x55\xfb\x30\x5e\x89\x93\xa9\xf3\xa6\xa3\xd7\x26\xbb"
+           "\xd8\xa8\xd9\x95\x1d\xfe\xfc\xd7\xa8\x93\x66\x2f\x04\x53\x06\x64"
+           "\x7f\x31\x29\xae\xb7\x9f\xba\xc4\x6d\x68\xd1\x24\x32\xf4\x11",
+         },
+       },
+       "1.2.643.2.2.31.2"
+      },
+#endif
+#if USE_SM4
+      { GCRY_CIPHER_SM4, FLAG_NOFIPS,
+        "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+       { { "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd"
+            "\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb",
+            32,
+            "\xac\x32\x36\xcb\x86\x1d\xd3\x16\xe6\x41\x3b\x4e\x3c\x75\x24\xb7"
+            "\x69\xd4\xc5\x4e\xd4\x33\xb9\xa0\x34\x60\x09\xbe\xb3\x7b\x2b\x3f" },
+       }
+      },
+      { GCRY_CIPHER_SM4, FLAG_NOFIPS,
+        "\xfe\xdc\xba\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xab\xcd\xef",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+       { { "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd"
+            "\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb",
+            32,
+            "\x5d\xcc\xcd\x25\xa8\x4b\xa1\x65\x60\xd7\xf2\x65\x88\x70\x68\x49"
+            "\x0d\x9b\x86\xff\x20\xc3\xbf\xe1\x15\xff\xa0\x2c\xa6\x19\x2c\xc5" },
+       }
+      },
+#endif /* USE_SM4 */
     };
   gcry_cipher_hd_t hde, hdd;
   unsigned char out[MAX_DATA_LEN];
@@ -1002,15 +2702,27 @@ check_cfb_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
-      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    tv[i].algo);
+          if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+            {
+              if (verbose)
+                fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                         tv[i].algo);
+            }
+          else
+            fail ("algo %d CFB, gcry_cipher_test_algo unexpectedly failed: %s\n",
+                  tv[i].algo, gpg_strerror (err));
+          continue;
+        }
+      else if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+        {
+          fail ("algo %d CFB, gcry_cipher_test_algo did not fail as expected\n",
+                tv[i].algo);
           continue;
         }
 
-      mode = tv[i].cfb8? GCRY_CIPHER_MODE_CFB8 : GCRY_CIPHER_MODE_CFB;
+      mode = (tv[i].flags & FLAG_CFB8) ? GCRY_CIPHER_MODE_CFB8 : GCRY_CIPHER_MODE_CFB;
 
       if (verbose)
         fprintf (stderr, "    checking CFB mode for %s [%i]\n",
@@ -1025,6 +2737,20 @@ check_cfb_cipher (void)
           return;
         }
 
+      if (tv[i].oid)
+       {
+         err = gcry_cipher_set_sbox (hde, tv[i].oid);
+         if (!err)
+           err = gcry_cipher_set_sbox (hdd, tv[i].oid);
+         if (err)
+           {
+             fail ("cfb, gcry_cipher_set_sbox failed: %s\n",
+                   gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
       keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
       if (!keylen)
         {
@@ -1107,19 +2833,20 @@ check_ofb_cipher (void)
   static const struct tv
   {
     int algo;
+    int flags;
     char key[MAX_DATA_LEN];
     char iv[MAX_DATA_LEN];
     struct data
     {
       unsigned char plaintext[MAX_DATA_LEN];
-      int inlen;
+      unsigned int inlen;
       char out[MAX_DATA_LEN];
     }
     data[MAX_DATA_LEN];
   } tv[] =
     {
       /* http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */
-      { GCRY_CIPHER_AES,
+      { GCRY_CIPHER_AES, 0,
         "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
         "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
         { { "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a",
@@ -1136,7 +2863,7 @@ check_ofb_cipher (void)
             "\x30\x4c\x65\x28\xf6\x59\xc7\x78\x66\xa5\x10\xd9\xc1\xd6\xae\x5e" },
         }
       },
-      { GCRY_CIPHER_AES192,
+      { GCRY_CIPHER_AES192, 0,
         "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b"
         "\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b",
         "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
@@ -1154,7 +2881,7 @@ check_ofb_cipher (void)
             "\x6d\x9f\x20\x08\x57\xca\x6c\x3e\x9c\xac\x52\x4b\xd9\xac\xc9\x2a" },
         }
       },
-      { GCRY_CIPHER_AES256,
+      { GCRY_CIPHER_AES256, 0,
         "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
         "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4",
         "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
@@ -1171,7 +2898,29 @@ check_ofb_cipher (void)
             16,
             "\x01\x26\x14\x1d\x67\xf3\x7b\xe8\x53\x8f\x5a\x8b\xe7\x40\xe4\x84" }
         }
+      },
+#if USE_SM4
+      { GCRY_CIPHER_SM4, FLAG_NOFIPS,
+        "\x01\x23\x45\x67\x89\xab\xcd\xef\xfe\xdc\xba\x98\x76\x54\x32\x10",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        { { "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd"
+            "\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb",
+            32,
+            "\xac\x32\x36\xcb\x86\x1d\xd3\x16\xe6\x41\x3b\x4e\x3c\x75\x24\xb7"
+            "\x1d\x01\xac\xa2\x48\x7c\xa5\x82\xcb\xf5\x46\x3e\x66\x98\x53\x9b" },
+        }
+      },
+      { GCRY_CIPHER_SM4, FLAG_NOFIPS,
+        "\xfe\xdc\xba\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xab\xcd\xef",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        { { "\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd"
+            "\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb",
+            32,
+            "\x5d\xcc\xcd\x25\xa8\x4b\xa1\x65\x60\xd7\xf2\x65\x88\x70\x68\x49"
+            "\x33\xfa\x16\xbd\x5c\xd9\xc8\x56\xca\xca\xa1\xe1\x01\x89\x7a\x97" },
+        }
       }
+#endif /* USE_SM4 */
     };
   gcry_cipher_hd_t hde, hdd;
   unsigned char out[MAX_DATA_LEN];
@@ -1183,11 +2932,23 @@ check_ofb_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
-      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    tv[i].algo);
+          if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+            {
+              if (verbose)
+                fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                         tv[i].algo);
+            }
+          else
+            fail ("algo %d OFB, gcry_cipher_test_algo unexpectedly failed: %s\n",
+                  tv[i].algo, gpg_strerror (err));
+          continue;
+        }
+      else if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+        {
+          fail ("algo %d OFB, gcry_cipher_test_algo did not fail as expected\n",
+                tv[i].algo);
           continue;
         }
 
@@ -1553,6 +3314,22 @@ _check_gcm_cipher (unsigned int step)
         "\x0f\xc0\xc3\xb7\x80\xf2\x44\x45\x2d\xa3\xeb\xf1\xc5\xd8\x2c\xde"
         "\xa2\x41\x89\x97\x20\x0e\xf8\x2e\x44\xae\x7e\x3f",
         "\xa4\x4a\x82\x66\xee\x1c\x8e\xb0\xc8\xb5\xd4\xcf\x5a\xe9\xf1\x9a" },
+      { GCRY_CIPHER_AES256,
+        "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+        "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08",
+        "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12,
+        "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef"
+        "\xab\xad\xda\xd2", 20,
+        "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+        "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+        "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+        "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39",
+        60,
+        "\x52\x2d\xc1\xf0\x99\x56\x7d\x07\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
+        "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
+        "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d\xa7\xb0\x8b\x10\x56\x82\x88\x38"
+        "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a\xbc\xc9\xf6\x62",
+        "\x76\xfc\x6e\xce\x0f\x4e\x17\x68\xcd\xdf\x88\x53\xbb\x2d\x55\x1b" },
       /* Test vectors for overflowing CTR. */
       /* After setiv, ctr_low: 0xffffffff */
       { GCRY_CIPHER_AES256,
@@ -2244,11 +4021,10 @@ _check_gcm_cipher (unsigned int step)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
-      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+      /* The AES algorithm is allowed in FIPS mode */
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    tv[i].algo);
+          fail ("aes-gcm, gcry_cipher_test_algo failed: %s\n", gpg_strerror (err));
           continue;
         }
 
@@ -2517,64 +4293,2066 @@ _check_gcm_cipher (unsigned int step)
           return;
         }
 
-      err = gcry_cipher_checktag (hdd, tag, 1);
-      if (!err)
-        {
-          fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid "
-               " tag length of '%d'\n", i, 1);
-          gcry_cipher_close (hde);
-          gcry_cipher_close (hdd);
-          return;
-        }
-      err = gcry_cipher_checktag (hdd, tag, 17);
-      if (!err)
-        {
-          fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid "
-               " tag length of '%d'\n", i, 17);
-          gcry_cipher_close (hde);
-          gcry_cipher_close (hdd);
-          return;
-        }
+      err = gcry_cipher_checktag (hdd, tag, 1);
+      if (!err)
+        {
+          fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid "
+               " tag length of '%d'\n", i, 1);
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+      err = gcry_cipher_checktag (hdd, tag, 17);
+      if (!err)
+        {
+          fail ("aes-gcm, gcry_cipher_checktag(%d) did not fail for invalid "
+               " tag length of '%d'\n", i, 17);
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      if (tv[i].should_fail)
+        {
+          fail ("aes-gcm, negative test succeeded %d\n", i);
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+    next_tv:
+      gcry_cipher_close (hde);
+      gcry_cipher_close (hdd);
+    }
+  if (verbose)
+    fprintf (stderr, "  Completed GCM checks.\n");
+}
+
+
+static void
+check_gcm_cipher (void)
+{
+  /* Large buffers, no splitting. */
+  _check_gcm_cipher(0xffffffff);
+  /* Split input to one byte buffers. */
+  _check_gcm_cipher(1);
+  /* Split input to 7 byte buffers. */
+  _check_gcm_cipher(7);
+  /* Split input to 15 byte buffers. */
+  _check_gcm_cipher(15);
+  /* Split input to 16 byte buffers. */
+  _check_gcm_cipher(16);
+  /* Split input to 17 byte buffers. */
+  _check_gcm_cipher(17);
+}
+
+
+static void
+_check_eax_cipher (unsigned int step)
+{
+  static const struct tv
+  {
+    int algo;
+    char key[MAX_DATA_LEN];
+    char nonce[MAX_DATA_LEN];
+    int noncelen;
+    unsigned char header[MAX_DATA_LEN];
+    int headerlen;
+    unsigned char plaintext[MAX_DATA_LEN];
+    int inlen;
+    char out[MAX_DATA_LEN];
+    char tag[MAX_DATA_LEN];
+    int taglen;
+    int should_fail;
+  } tv[] =
+    {
+      /* Test vectors from http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf */
+      { GCRY_CIPHER_AES,
+        "\x23\x39\x52\xDE\xE4\xD5\xED\x5F\x9B\x9C\x6D\x6F\xF8\x0F\xF4\x78",
+        "\x62\xEC\x67\xF9\xC3\xA4\xA4\x07\xFC\xB2\xA8\xC4\x90\x31\xA8\xB3", 16,
+        "\x6B\xFB\x91\x4F\xD0\x7E\xAE\x6B", 8,
+        "",
+        0,
+        "",
+        "\xE0\x37\x83\x0E\x83\x89\xF2\x7B\x02\x5A\x2D\x65\x27\xE7\x9D\x01", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\x91\x94\x5D\x3F\x4D\xCB\xEE\x0B\xF4\x5E\xF5\x22\x55\xF0\x95\xA4",
+        "\xBE\xCA\xF0\x43\xB0\xA2\x3D\x84\x31\x94\xBA\x97\x2C\x66\xDE\xBD", 16,
+        "\xFA\x3B\xFD\x48\x06\xEB\x53\xFA", 8,
+        "\xF7\xFB",
+        2,
+        "\x19\xDD",
+        "\x5C\x4C\x93\x31\x04\x9D\x0B\xDA\xB0\x27\x74\x08\xF6\x79\x67\xE5", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\x01\xF7\x4A\xD6\x40\x77\xF2\xE7\x04\xC0\xF6\x0A\xDA\x3D\xD5\x23",
+        "\x70\xC3\xDB\x4F\x0D\x26\x36\x84\x00\xA1\x0E\xD0\x5D\x2B\xFF\x5E", 16,
+        "\x23\x4A\x34\x63\xC1\x26\x4A\xC6", 8,
+        "\x1A\x47\xCB\x49\x33",
+        5,
+        "\xD8\x51\xD5\xBA\xE0",
+        "\x3A\x59\xF2\x38\xA2\x3E\x39\x19\x9D\xC9\x26\x66\x26\xC4\x0F\x80", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\xD0\x7C\xF6\xCB\xB7\xF3\x13\xBD\xDE\x66\xB7\x27\xAF\xD3\xC5\xE8",
+        "\x84\x08\xDF\xFF\x3C\x1A\x2B\x12\x92\xDC\x19\x9E\x46\xB7\xD6\x17", 16,
+        "\x33\xCC\xE2\xEA\xBF\xF5\xA7\x9D", 8,
+        "\x48\x1C\x9E\x39\xB1",
+        5,
+        "\x63\x2A\x9D\x13\x1A",
+        "\xD4\xC1\x68\xA4\x22\x5D\x8E\x1F\xF7\x55\x93\x99\x74\xA7\xBE\xDE", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\x35\xB6\xD0\x58\x00\x05\xBB\xC1\x2B\x05\x87\x12\x45\x57\xD2\xC2",
+        "\xFD\xB6\xB0\x66\x76\xEE\xDC\x5C\x61\xD7\x42\x76\xE1\xF8\xE8\x16", 16,
+        "\xAE\xB9\x6E\xAE\xBE\x29\x70\xE9", 8,
+        "\x40\xD0\xC0\x7D\xA5\xE4",
+        6,
+        "\x07\x1D\xFE\x16\xC6\x75",
+        "\xCB\x06\x77\xE5\x36\xF7\x3A\xFE\x6A\x14\xB7\x4E\xE4\x98\x44\xDD", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\xBD\x8E\x6E\x11\x47\x5E\x60\xB2\x68\x78\x4C\x38\xC6\x2F\xEB\x22",
+        "\x6E\xAC\x5C\x93\x07\x2D\x8E\x85\x13\xF7\x50\x93\x5E\x46\xDA\x1B", 16,
+        "\xD4\x48\x2D\x1C\xA7\x8D\xCE\x0F", 8,
+        "\x4D\xE3\xB3\x5C\x3F\xC0\x39\x24\x5B\xD1\xFB\x7D",
+        12,
+        "\x83\x5B\xB4\xF1\x5D\x74\x3E\x35\x0E\x72\x84\x14",
+        "\xAB\xB8\x64\x4F\xD6\xCC\xB8\x69\x47\xC5\xE1\x05\x90\x21\x0A\x4F", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\x7C\x77\xD6\xE8\x13\xBE\xD5\xAC\x98\xBA\xA4\x17\x47\x7A\x2E\x7D",
+        "\x1A\x8C\x98\xDC\xD7\x3D\x38\x39\x3B\x2B\xF1\x56\x9D\xEE\xFC\x19", 16,
+        "\x65\xD2\x01\x79\x90\xD6\x25\x28", 8,
+        "\x8B\x0A\x79\x30\x6C\x9C\xE7\xED\x99\xDA\xE4\xF8\x7F\x8D\xD6\x16\x36",
+        17,
+        "\x02\x08\x3E\x39\x79\xDA\x01\x48\x12\xF5\x9F\x11\xD5\x26\x30\xDA\x30",
+        "\x13\x73\x27\xD1\x06\x49\xB0\xAA\x6E\x1C\x18\x1D\xB6\x17\xD7\xF2", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\x5F\xFF\x20\xCA\xFA\xB1\x19\xCA\x2F\xC7\x35\x49\xE2\x0F\x5B\x0D",
+        "\xDD\xE5\x9B\x97\xD7\x22\x15\x6D\x4D\x9A\xFF\x2B\xC7\x55\x98\x26", 16,
+        "\x54\xB9\xF0\x4E\x6A\x09\x18\x9A", 8,
+        "\x1B\xDA\x12\x2B\xCE\x8A\x8D\xBA\xF1\x87\x7D\x96\x2B\x85\x92\xDD"
+        "\x2D\x56",
+        18,
+        "\x2E\xC4\x7B\x2C\x49\x54\xA4\x89\xAF\xC7\xBA\x48\x97\xED\xCD\xAE"
+        "\x8C\xC3",
+        "\x3B\x60\x45\x05\x99\xBD\x02\xC9\x63\x82\x90\x2A\xEF\x7F\x83\x2A", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\xA4\xA4\x78\x2B\xCF\xFD\x3E\xC5\xE7\xEF\x6D\x8C\x34\xA5\x61\x23",
+        "\xB7\x81\xFC\xF2\xF7\x5F\xA5\xA8\xDE\x97\xA9\xCA\x48\xE5\x22\xEC", 16,
+        "\x89\x9A\x17\x58\x97\x56\x1D\x7E", 8,
+        "\x6C\xF3\x67\x20\x87\x2B\x85\x13\xF6\xEA\xB1\xA8\xA4\x44\x38\xD5"
+        "\xEF\x11",
+        18,
+        "\x0D\xE1\x8F\xD0\xFD\xD9\x1E\x7A\xF1\x9F\x1D\x8E\xE8\x73\x39\x38"
+        "\xB1\xE8",
+        "\xE7\xF6\xD2\x23\x16\x18\x10\x2F\xDB\x7F\xE5\x5F\xF1\x99\x17\x00", 16,
+        0
+      },
+      { GCRY_CIPHER_AES,
+        "\x83\x95\xFC\xF1\xE9\x5B\xEB\xD6\x97\xBD\x01\x0B\xC7\x66\xAA\xC3",
+        "\x22\xE7\xAD\xD9\x3C\xFC\x63\x93\xC5\x7E\xC0\xB3\xC1\x7D\x6B\x44", 16,
+        "\x12\x67\x35\xFC\xC3\x20\xD2\x5A", 8,
+        "\xCA\x40\xD7\x44\x6E\x54\x5F\xFA\xED\x3B\xD1\x2A\x74\x0A\x65\x9F"
+        "\xFB\xBB\x3C\xEA\xB7",
+        21,
+        "\xCB\x89\x20\xF8\x7A\x6C\x75\xCF\xF3\x96\x27\xB5\x6E\x3E\xD1\x97"
+        "\xC5\x52\xD2\x95\xA7",
+        "\xCF\xC4\x6A\xFC\x25\x3B\x46\x52\xB1\xAF\x37\x95\xB1\x24\xAB\x6E", 16,
+        0
+      },
+      /* Negative test for bad tag. */
+      { GCRY_CIPHER_AES,
+        "\x23\x39\x52\xDE\xE4\xD5\xED\x5F\x9B\x9C\x6D\x6F\xF8\x0F\xF4\x78",
+        "\x62\xEC\x67\xF9\xC3\xA4\xA4\x07\xFC\xB2\xA8\xC4\x90\x31\xA8\xB3", 16,
+        "\x6B\xFB\x91\x4F\xD0\x7E\xAE\x6B", 8,
+        "",
+        0,
+        "",
+        "\x00\x37\x83\x0E\x83\x89\xF2\x7B\x02\x5A\x2D\x65\x27\xE7\x9D\x01", 16,
+        1
+      },
+      /* Test vectors from libtomcrypt. */
+      {
+        GCRY_CIPHER_AES,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        "", 0,
+        "", 0,
+        "",
+        0,
+        "",
+        "\x9a\xd0\x7e\x7d\xbf\xf3\x01\xf5\x05\xde\x59\x6b\x96\x15\xdf\xff", 16,
+        0
+      },
+      {
+        GCRY_CIPHER_AES,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+        "", 0,
+        "",
+        0,
+        "",
+        "\x1c\xe1\x0d\x3e\xff\xd4\xca\xdb\xe2\xe4\x4b\x58\xd6\x0a\xb9\xec", 16,
+        0
+      },
+      {
+        GCRY_CIPHER_AES,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        "", 0,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+        "",
+        0,
+        "",
+        "\x3a\x69\x8f\x7a\x27\x0e\x51\xb0\xf6\x5b\x3d\x3e\x47\x19\x3c\xff", 16,
+        0
+      },
+      {
+        GCRY_CIPHER_AES,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+        "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+        32,
+        "\x29\xd8\x78\xd1\xa3\xbe\x85\x7b\x6f\xb8\xc8\xea\x59\x50\xa7\x78"
+        "\x33\x1f\xbf\x2c\xcf\x33\x98\x6f\x35\xe8\xcf\x12\x1d\xcb\x30\xbc",
+        "\x4f\xbe\x03\x38\xbe\x1c\x8c\x7e\x1d\x7a\xe7\xe4\x5b\x92\xc5\x87", 16,
+        0
+      },
+      {
+        GCRY_CIPHER_AES,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e", 15,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d", 14,
+        "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+        "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c",
+        29,
+        "\xdd\x25\xc7\x54\xc5\xb1\x7c\x59\x28\xb6\x9b\x73\x15\x5f\x7b\xb8"
+        "\x88\x8f\xaf\x37\x09\x1a\xd9\x2c\x8a\x24\xdb\x86\x8b",
+        "\x0d\x1a\x14\xe5\x22\x24\xff\xd2\x3a\x05\xfa\x02\xcd\xef\x52\xda", 16,
+        0
+      },
+    };
+
+  gcry_cipher_hd_t hde, hdd;
+  unsigned char out[MAX_DATA_LEN];
+  unsigned char tag[16];
+  int i, keylen;
+  gcry_error_t err = 0;
+  size_t pos, poslen, taglen2;
+  int byteNum;
+
+  if (verbose)
+    fprintf (stderr, "  Starting EAX checks.\n");
+
+  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+    {
+      /* The AES algorithm is allowed in FIPS mode */
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
+        {
+          fail ("aes-eax, gcry_cipher_test_algo failed: %s\n", gpg_strerror (err));
+          continue;
+        }
+
+      if (verbose)
+        fprintf (stderr, "    checking EAX mode for %s [%i]\n",
+                 gcry_cipher_algo_name (tv[i].algo),
+                 tv[i].algo);
+      err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_EAX, 0);
+      if (!err)
+        err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_EAX, 0);
+      if (err)
+        {
+          fail ("aes-eax, gcry_cipher_open failed: %s\n", gpg_strerror (err));
+          return;
+        }
+
+      keylen = gcry_cipher_get_algo_keylen(tv[i].algo);
+      if (!keylen)
+        {
+          fail ("aes-eax, gcry_cipher_get_algo_keylen failed\n");
+          return;
+        }
+
+      err = gcry_cipher_setkey (hde, tv[i].key, keylen);
+      if (!err)
+        err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
+      if (err)
+        {
+          fail ("aes-eax, gcry_cipher_setkey failed: %s\n",
+                gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      err = gcry_cipher_setiv (hde, tv[i].nonce, tv[i].noncelen);
+      if (!err)
+        err = gcry_cipher_setiv (hdd, tv[i].nonce, tv[i].noncelen);
+      if (err)
+        {
+          fail ("aes-eax, gcry_cipher_setiv failed: %s\n",
+                gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      err = gcry_cipher_info (hde, GCRYCTL_GET_TAGLEN, NULL, &taglen2);
+      if (err)
+        {
+          fail ("cipher-eax, gcryctl_get_taglen failed (tv %d): %s\n",
+                i, gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+      if (taglen2 != 16)
+        {
+          fail ("cipher-eax, gcryctl_get_taglen returned bad length"
+                " (tv %d): got=%zu want=%d\n",
+                i, taglen2, 16);
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      for (pos = 0; pos < tv[i].headerlen; pos += step)
+        {
+          poslen = (pos + step < tv[i].headerlen) ?
+                    step : tv[i].headerlen - pos;
+
+          err = gcry_cipher_authenticate(hde, tv[i].header + pos, poslen);
+          if (err)
+            {
+              fail ("aes-eax, gcry_cipher_authenticate (%d) (%lu:%d) failed: "
+                    "%s\n", i, (unsigned long) pos, step, gpg_strerror (err));
+              gcry_cipher_close (hde);
+              gcry_cipher_close (hdd);
+              return;
+            }
+          err = gcry_cipher_authenticate(hdd, tv[i].header + pos, poslen);
+          if (err)
+            {
+              fail ("aes-eax, de gcry_cipher_authenticate (%d) (%lu:%d) failed: "
+                   "%s\n", i, (unsigned long) pos, step, gpg_strerror (err));
+              gcry_cipher_close (hde);
+              gcry_cipher_close (hdd);
+              return;
+            }
+        }
+
+      for (pos = 0; pos < tv[i].inlen; pos += step)
+        {
+          poslen = (pos + step < tv[i].inlen) ? step : tv[i].inlen - pos;
+
+          err = gcry_cipher_encrypt (hde, out + pos, poslen,
+                                     tv[i].plaintext + pos, poslen);
+          if (err)
+            {
+              fail ("aes-eax, gcry_cipher_encrypt (%d) (%lu:%d) failed: %s\n",
+                    i, (unsigned long) pos, step, gpg_strerror (err));
+              gcry_cipher_close (hde);
+              gcry_cipher_close (hdd);
+              return;
+            }
+        }
+
+      if (memcmp (tv[i].out, out, tv[i].inlen))
+        fail ("aes-eax, encrypt mismatch entry %d (step %d)\n", i, step);
+
+      for (pos = 0; pos < tv[i].inlen; pos += step)
+        {
+          poslen = (pos + step < tv[i].inlen) ? step : tv[i].inlen - pos;
+
+          err = gcry_cipher_decrypt (hdd, out + pos, poslen, NULL, 0);
+          if (err)
+            {
+              fail ("aes-eax, gcry_cipher_decrypt (%d) (%lu:%d) failed: %s\n",
+                    i, (unsigned long) pos, step, gpg_strerror (err));
+              gcry_cipher_close (hde);
+              gcry_cipher_close (hdd);
+              return;
+            }
+        }
+
+      if (memcmp (tv[i].plaintext, out, tv[i].inlen))
+        fail ("aes-eax, decrypt mismatch entry %d (step %d)\n", i, step);
+
+      taglen2 = tv[i].taglen ? tv[i].taglen : 16;
+
+      err = gcry_cipher_gettag (hde, out, taglen2);
+      if (err)
+        {
+          if (tv[i].should_fail)
+            goto next_tv;
+
+          fail ("aes-eax, gcry_cipher_gettag(%d) failed: %s\n",
+                i, gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      if ((memcmp (tv[i].tag, out, taglen2) != 0) ^ tv[i].should_fail)
+        fail ("aes-eax, encrypt tag mismatch entry %d\n", i);
+
+      err = gcry_cipher_checktag (hdd, tv[i].tag, taglen2);
+      if (err)
+        {
+          if (tv[i].should_fail)
+            goto next_tv;
+
+          fail ("aes-eax, gcry_cipher_checktag(%d) failed: %s\n",
+                i, gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      err = gcry_cipher_reset(hde);
+      if (!err)
+        err = gcry_cipher_reset(hdd);
+      if (err)
+        {
+          fail ("aes-eax, gcry_cipher_reset (%d) failed: %s\n",
+                i, gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      /* gcry_cipher_reset clears the IV */
+      err = gcry_cipher_setiv (hde, tv[i].nonce, tv[i].noncelen);
+      if (!err)
+        err = gcry_cipher_setiv (hdd, tv[i].nonce, tv[i].noncelen);
+      if (err)
+        {
+          fail ("aes-eax, gcry_cipher_setiv failed: %s\n",
+                gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      /* this time we authenticate, encrypt and decrypt one byte at a time */
+      for (byteNum = 0; byteNum < tv[i].headerlen; ++byteNum)
+        {
+          err = gcry_cipher_authenticate(hde, tv[i].header + byteNum, 1);
+          if (err)
+            {
+              fail ("aes-eax, gcry_cipher_authenticate (%d) (byte-buf) failed: "
+                    "%s\n", i, gpg_strerror (err));
+              gcry_cipher_close (hde);
+              gcry_cipher_close (hdd);
+              return;
+            }
+          err = gcry_cipher_authenticate(hdd, tv[i].header + byteNum, 1);
+          if (err)
+            {
+              fail ("aes-eax, de gcry_cipher_authenticate (%d) (byte-buf) "
+                   "failed: %s\n", i, gpg_strerror (err));
+              gcry_cipher_close (hde);
+              gcry_cipher_close (hdd);
+              return;
+            }
+        }
+
+      for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum)
+        {
+          err = gcry_cipher_encrypt (hde, out+byteNum, 1,
+                                     (tv[i].plaintext) + byteNum,
+                                     1);
+          if (err)
+            {
+              fail ("aes-eax, gcry_cipher_encrypt (%d) (byte-buf) failed: %s\n",
+                    i,  gpg_strerror (err));
+              gcry_cipher_close (hde);
+              gcry_cipher_close (hdd);
+              return;
+            }
+        }
+
+      if (memcmp (tv[i].out, out, tv[i].inlen))
+        fail ("aes-eax, encrypt mismatch entry %d, (byte-buf)\n", i);
+
+      /* Test output to larger than 16-byte buffer. */
+      taglen2 = tv[i].taglen ? tv[i].taglen : 16 + 1;
+
+      err = gcry_cipher_gettag (hde, tag, taglen2);
+      if (err)
+        {
+          if (tv[i].should_fail)
+            goto next_tv;
+
+          fail ("aes-eax, gcry_cipher_gettag(%d, %lu) (byte-buf) failed: %s\n",
+                i, (unsigned long) taglen2, gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      taglen2 = tv[i].taglen ? tv[i].taglen : 16;
+
+      if ((memcmp (tv[i].tag, tag, taglen2) != 0) ^ tv[i].should_fail)
+        fail ("aes-eax, encrypt tag mismatch entry %d, (byte-buf)\n", i);
+
+      for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum)
+        {
+          err = gcry_cipher_decrypt (hdd, out+byteNum, 1, NULL, 0);
+          if (err)
+            {
+              fail ("aes-eax, gcry_cipher_decrypt (%d) (byte-buf) failed: %s\n",
+                    i, gpg_strerror (err));
+              gcry_cipher_close (hde);
+              gcry_cipher_close (hdd);
+              return;
+            }
+        }
+
+      if (memcmp (tv[i].plaintext, out, tv[i].inlen))
+        fail ("aes-eax, decrypt mismatch entry %d\n", i);
+
+      err = gcry_cipher_checktag (hdd, tv[i].tag, taglen2);
+      if (err)
+        {
+          if (tv[i].should_fail)
+            goto next_tv;
+
+          fail ("aes-eax, gcry_cipher_checktag(%d) (byte-buf) failed: %s\n",
+                i, gpg_strerror (err));
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      err = gcry_cipher_checktag (hdd, tag, 17);
+      if (!err)
+        {
+          fail ("aes-eax, gcry_cipher_checktag(%d) did not fail for invalid "
+               " tag length of '%d'\n", i, 17);
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+      if (tv[i].should_fail)
+        {
+          fail ("aes-eax, negative test succeeded %d\n", i);
+          gcry_cipher_close (hde);
+          gcry_cipher_close (hdd);
+          return;
+        }
+
+    next_tv:
+      gcry_cipher_close (hde);
+      gcry_cipher_close (hdd);
+    }
+  if (verbose)
+    fprintf (stderr, "  Completed EAX checks.\n");
+}
+
+
+static void
+check_eax_cipher (void)
+{
+  /* Large buffers, no splitting. */
+  _check_eax_cipher(0xffffffff);
+  /* Split input to one byte buffers. */
+  _check_eax_cipher(1);
+  /* Split input to 7 byte buffers. */
+  _check_eax_cipher(7);
+  /* Split input to 16 byte buffers. */
+  _check_eax_cipher(16);
+}
+
+
+static void
+check_siv_cipher (void)
+{
+  static const struct tv
+  {
+    int algo;
+    char key[MAX_DATA_LEN];
+    char ad1[MAX_DATA_LEN];
+    int ad1len;
+    char ad2[MAX_DATA_LEN];
+    int ad2len;
+    char nonce[MAX_DATA_LEN];
+    int noncelen;
+    unsigned char plaintext[MAX_DATA_LEN];
+    int inlen;
+    char tag[MAX_DATA_LEN];
+    char out[MAX_DATA_LEN];
+  } tv[] =
+    {
+      /* Test vectors from RFC5297 */
+      {
+       GCRY_CIPHER_AES128,
+       "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
+       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+       "\x20\x21\x22\x23\x24\x25\x26\x27",
+       24,
+       "",
+       -1,
+       "",
+       -1,
+       "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee",
+       14,
+       "\x85\x63\x2d\x07\xc6\xe8\xf3\x7f\x95\x0a\xcd\x32\x0a\x2e\xcc\x93",
+       "\x40\xc0\x2b\x96\x90\xc4\xdc\x04\xda\xef\x7f\x6a\xfe\x5c"
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x7f\x7e\x7d\x7c\x7b\x7a\x79\x78\x77\x76\x75\x74\x73\x72\x71\x70"
+       "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
+       "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
+       "\xde\xad\xda\xda\xde\xad\xda\xda\xff\xee\xdd\xcc\xbb\xaa\x99\x88"
+       "\x77\x66\x55\x44\x33\x22\x11\x00",
+       40,
+       "\x10\x20\x30\x40\x50\x60\x70\x80\x90\xa0",
+       10,
+       "\x09\xf9\x11\x02\x9d\x74\xe3\x5b\xd8\x41\x56\xc5\x63\x56\x88\xc0",
+       16,
+       "\x74\x68\x69\x73\x20\x69\x73\x20\x73\x6f\x6d\x65\x20\x70\x6c\x61"
+       "\x69\x6e\x74\x65\x78\x74\x20\x74\x6f\x20\x65\x6e\x63\x72\x79\x70"
+       "\x74\x20\x75\x73\x69\x6e\x67\x20\x53\x49\x56\x2d\x41\x45\x53",
+       47,
+       "\x7b\xdb\x6e\x3b\x43\x26\x67\xeb\x06\xf4\xd1\x4b\xff\x2f\xbd\x0f",
+       "\xcb\x90\x0f\x2f\xdd\xbe\x40\x43\x26\x60\x19\x65\xc8\x89\xbf\x17"
+       "\xdb\xa7\x7c\xeb\x09\x4f\xa6\x63\xb7\xa3\xf7\x48\xba\x8a\xf8\x29"
+       "\xea\x64\xad\x54\x4a\x27\x2e\x9c\x48\x5b\x62\xa3\xfd\x5c\x0d"
+      },
+      /* From libaes_siv */
+      {
+       GCRY_CIPHER_AES256,
+       "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
+       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+       "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0",
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+       "\x20\x21\x22\x23\x24\x25\x26\x27",
+       24,
+       "",
+       -1,
+       "",
+       -1,
+       "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee",
+       14,
+       "\x72\x4d\xfb\x2e\xaf\x94\xdb\xb1\x9b\x0b\xa3\xa2\x99\xa0\x80\x1e",
+       "\xf3\xb0\x5a\x55\x49\x8e\xc2\x55\x26\x90\xb8\x98\x10\xe4"
+      },
+      /* From https://github.com/cryptomator/siv-mode */
+      { GCRY_CIPHER_AES128,
+       "\x90\xe5\x90\xae\xca\x19\x70\xed\xd1\x9f\xe5\x0f\xa6\x91\xae\x12"
+       "\x34\x2c\x49\x7a\x22\xc2\x4f\xaa\x9e\x87\x19\x2e\x34\x00\xfb\xce",
+       "\x2d\xdf\x87\xac\x97\x5d\x0c",
+       7,
+       "",
+       -1,
+       "",
+       -1,
+       "\x44",
+       1,
+       "\x7b\x0d\xdd\x88\x74\x39\x43\xc6\x44\xc1\xd1\xa2\x18\xa3\x1e\xdf",
+       "\x2e"
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\xf6\xde\x98\x19\x31\x1b\xd3\xde\x0b\xd1\x98\x70\x9d\xea\x9f\xdf"
+       "\xb8\x2e\x80\x44\xe4\x00\x13\x2a\x90\xff\xe9\xa9\xde\x81\x44\x75",
+       "\x7b\xd3\x6f\x24\x09\xfc\xd0\x0f\x5c\xcd\x9a\xf2\xe3\xf5\x76\x45"
+       "\xf7\xc5\x3f\x39\xf7\xad\xcb\xf0\x7a\x0e\x43\x30\x7e\x55\xa2\x53"
+       "\x47\x49\x48\x20\x20\x27\x6c\x8a\x20\x44\x22\xcd\x26\xbf\x7e\x89"
+       "\x88\x38\x0d\x94\xff\x12\xc5\x18\xfd\x20\x2c\x2a\x1b\x00\xb3",
+       63,
+       "",
+       -1,
+       "",
+       -1,
+       "",
+       0,
+       "\x4c\x0e\xc2\xcc\x61\x59\xb1\x17\xdb\x98\x6d\x9a\xa5\xb4\xa0\x11",
+       ""
+      },
+      /* From https://github.com/RustCrypto/AEADs */
+      {
+       GCRY_CIPHER_AES128,
+       "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
+       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+       "",
+       -1,
+       "",
+       -1,
+       "",
+       -1,
+       "",
+       0,
+       "\xf2\x00\x7a\x5b\xeb\x2b\x89\x00\xc5\x88\xa7\xad\xf5\x99\xf1\x72",
+       ""
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
+       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+       "",
+       -1,
+       "",
+       -1,
+       "",
+       -1,
+       "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+       16,
+       "\xf3\x04\xf9\x12\x86\x3e\x30\x3d\x5b\x54\x0e\x50\x57\xc7\x01\x0c",
+       "\x94\x2f\xfa\xf4\x5b\x0e\x5c\xa5\xfb\x9a\x56\xa5\x26\x3b\xb0\x65"
+      },
+      /* From nettle */
+      {
+       GCRY_CIPHER_AES128,
+       "\xff\xfe\xfd\xfc\xfb\xfa\xf9\xf8\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0"
+       "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+       "",
+       0,
+       "",
+       -1,
+       "\x01",
+       1,
+       "",
+       0,
+       "\xc6\x96\xf8\x4f\xdf\x92\xab\xa3\xc3\x1c\x23\xd5\xf2\x08\x75\x13",
+       ""
+      },
+      /* From botan */
+      {
+       GCRY_CIPHER_AES128,
+       "\x2a\x83\xf6\x10\xa1\xd1\x77\xec\x2e\x00\x89\x80\xdc\x02\xa6\x6e"
+       "\xeb\x75\xaf\x6c\xba\x44\xa4\xe0\x9f\x3d\x93\xea\x1f\xa2\x88\x67",
+       "",
+       0,
+       "",
+       -1,
+       "",
+       -1,
+       "",
+       0,
+       "\x6b\xc5\xca\x86\x32\x29\x66\x75\x18\xa9\xab\xbd\x5a\xe6\xc1\xd5",
+       ""
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x97\xef\x57\xd4\xe2\xe9\x2f\x14\xdf\x73\x31\xfb\xa3\xd9\xf3\x58"
+       "\x87\xdd\xe7\xad\x86\x91\xfb\x80\x17\x68\x58\xd6\x59\x20\x14\x27",
+       "",
+       0,
+       "",
+       -1,
+       "",
+       -1,
+       "\x75\x73\x97\x4d\x6f\xa7\x65\xbc\xd0\xe6\x23\x2c\x24\x0e\x82\x7e",
+       16,
+       "\x68\x60\xa9\xc7\xbf\x4a\x6b\x21\x92\x44\xd7\xa8\xea\xa1\xf5\x0c",
+       "\x6f\x97\x93\x82\xcd\xe6\x8d\xe6\x0a\xb2\xad\x09\x53\x60\x64\x85"
+      }
+    };
+
+  gcry_cipher_hd_t hde, hdd;
+  unsigned char out[MAX_DATA_LEN];
+  unsigned char tag[16];
+  int i, keylen;
+  gcry_error_t err = 0;
+  size_t taglen2;
+
+  if (verbose)
+    fprintf (stderr, "  Starting SIV checks.\n");
+
+  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+    {
+      /* The AES algorithm is allowed in FIPS mode */
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
+        {
+          fail ("aes-siv, gcry_cipher_test_algo failed: %s\n", gpg_strerror (err));
+          continue;
+        }
+
+      if (verbose)
+       fprintf (stderr, "    checking SIV mode for %s [%i]\n",
+                gcry_cipher_algo_name (tv[i].algo),
+                tv[i].algo);
+      err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_SIV, 0);
+      if (!err)
+       err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_SIV, 0);
+      if (err)
+       {
+         fail ("aes-siv, gcry_cipher_open failed: %s\n", gpg_strerror (err));
+         return;
+       }
+
+      keylen = gcry_cipher_get_algo_keylen (tv[i].algo) * 2;
+      if (!keylen)
+       {
+         fail ("aes-siv, gcry_cipher_get_algo_keylen failed\n");
+         return;
+       }
+
+      err = gcry_cipher_setkey (hde, tv[i].key, keylen);
+      if (!err)
+       err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
+      if (err)
+       {
+         fail ("aes-siv, gcry_cipher_setkey failed: %s\n",
+               gpg_strerror (err));
+         gcry_cipher_close (hde);
+         gcry_cipher_close (hdd);
+         return;
+       }
+
+      if (tv[i].ad1len >= 0)
+       {
+         err = gcry_cipher_authenticate (hde, tv[i].ad1, tv[i].ad1len);
+         if (!err)
+           err = gcry_cipher_authenticate (hdd, tv[i].ad1, tv[i].ad1len);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_authenticate failed: %s\n",
+                   gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
+
+      if (tv[i].ad2len >= 0)
+       {
+         err = gcry_cipher_authenticate (hde, tv[i].ad2, tv[i].ad2len);
+         if (!err)
+           err = gcry_cipher_authenticate (hdd, tv[i].ad2, tv[i].ad2len);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_authenticate failed: %s\n",
+                   gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
+
+      if (tv[i].noncelen >= 0)
+       {
+         err = gcry_cipher_setiv (hde, tv[i].nonce, tv[i].noncelen);
+         if (!err)
+           err = gcry_cipher_setiv (hdd, tv[i].nonce, tv[i].noncelen);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_setiv failed: %s\n",
+                   gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         /* Further AD not allowed after setting nonce. */
+         err = gcry_cipher_authenticate (hde, tv[i].nonce, tv[i].noncelen);
+         if (!err)
+           {
+             fail ("aes-siv, gcry_cipher_authenticate after setiv did not fail\n");
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
+
+      err = gcry_cipher_info (hde, GCRYCTL_GET_TAGLEN, NULL, &taglen2);
+      if (err)
+       {
+         fail ("cipher-siv, gcryctl_get_taglen failed (tv %d): %s\n",
+               i, gpg_strerror (err));
+         gcry_cipher_close (hde);
+         gcry_cipher_close (hdd);
+         return;
+       }
+      if (taglen2 != 16)
+       {
+         fail ("cipher-siv, gcryctl_get_taglen returned bad length"
+               " (tv %d): got=%zu want=%d\n",
+               i, taglen2, 16);
+         gcry_cipher_close (hde);
+         gcry_cipher_close (hdd);
+         return;
+       }
+
+      if (tv[i].inlen)
+       {
+         err = gcry_cipher_encrypt (hde, out, tv[i].inlen,
+                                    tv[i].plaintext, tv[i].inlen);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_encrypt (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].out, out, tv[i].inlen))
+           {
+             mismatch (tv[i].out, tv[i].inlen, out, tv[i].inlen);
+             fail ("aes-siv, encrypt mismatch entry %d\n", i);
+           }
+
+         err = gcry_cipher_gettag (hde, tag, taglen2);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_gettag(%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].tag, tag, taglen2))
+           {
+             mismatch (tv[i].tag, taglen2, tag, taglen2);
+             fail ("aes-siv, tag mismatch entry %d\n", i);
+           }
+
+         err = gcry_cipher_set_decryption_tag (hdd, tag, taglen2);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_set_decryption_tag (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         err = gcry_cipher_decrypt (hdd, out, tv[i].inlen, NULL, 0);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_decrypt (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].plaintext, out, tv[i].inlen))
+           fail ("aes-siv, decrypt mismatch entry %d\n", i);
+
+         err = gcry_cipher_checktag (hdd, tag, taglen2);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_checktag (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
+      else
+       {
+         err = gcry_cipher_gettag (hde, tag, taglen2);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_gettag(%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].tag, tag, taglen2))
+           {
+             mismatch (tv[i].tag, taglen2, tag, taglen2);
+             fail ("aes-siv, tag mismatch entry %d\n", i);
+           }
+
+         err = gcry_cipher_checktag (hdd, tv[i].tag, taglen2);
+         if (err)
+           {
+             fail ("aes-siv, gcry_cipher_checktag (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
+
+      gcry_cipher_close (hde);
+      gcry_cipher_close (hdd);
+    }
+  if (verbose)
+    fprintf (stderr, "  Completed SIV checks.\n");
+}
+
+
+static void
+check_gcm_siv_cipher (void)
+{
+  static const struct tv
+  {
+    int algo;
+    char key[MAX_DATA_LEN];
+    char nonce[12];
+    char ad[MAX_DATA_LEN];
+    int adlen;
+    unsigned char plaintext[MAX_DATA_LEN];
+    int inlen;
+    char out[MAX_DATA_LEN];
+    char tag[MAX_DATA_LEN];
+  } tv[] =
+    {
+      /* Test vectors from RFC8452 */
+      {
+       GCRY_CIPHER_AES128,
+       "\xee\x8e\x1e\xd9\xff\x25\x40\xae\x8f\x2b\xa9\xf5\x0b\xc2\xf2\x7c",
+       "\x75\x2a\xba\xd3\xe0\xaf\xb5\xf4\x34\xdc\x43\x10",
+       "example",
+       7,
+       "Hello world",
+       11,
+       "\x5d\x34\x9e\xad\x17\x5e\xf6\xb1\xde\xf6\xfd",
+       "\x4f\xbc\xde\xb7\xe4\x79\x3f\x4a\x1d\x7e\x4f\xaa\x70\x10\x0a\xf1"
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       -1,
+       "",
+       0,
+       "",
+       "\xdc\x20\xe2\xd8\x3f\x25\x70\x5b\xb4\x9e\x43\x9e\xca\x56\xde\x25"
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "",
+       0,
+       "",
+       "\xdc\x20\xe2\xd8\x3f\x25\x70\x5b\xb4\x9e\x43\x9e\xca\x56\xde\x25",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00",
+       8,
+       "\xb5\xd8\x39\x33\x0a\xc7\xb7\x86",
+       "\x57\x87\x82\xff\xf6\x01\x3b\x81\x5b\x28\x7c\x22\x49\x3a\x36\x4c",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       12,
+       "\x73\x23\xea\x61\xd0\x59\x32\x26\x00\x47\xd9\x42",
+       "\xa4\x97\x8d\xb3\x57\x39\x1a\x0b\xc4\xfd\xec\x8b\x0d\x10\x66\x39",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\x74\x3f\x7c\x80\x77\xab\x25\xf8\x62\x4e\x2e\x94\x85\x79\xcf\x77",
+       "\x30\x3a\xaf\x90\xf6\xfe\x21\x19\x9c\x60\x68\x57\x74\x37\xa0\xc4",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       32,
+       "\x84\xe0\x7e\x62\xba\x83\xa6\x58\x54\x17\x24\x5d\x7e\xc4\x13\xa9"
+       "\xfe\x42\x7d\x63\x15\xc0\x9b\x57\xce\x45\xf2\xe3\x93\x6a\x94\x45",
+       "\x1a\x8e\x45\xdc\xd4\x57\x8c\x66\x7c\xd8\x68\x47\xbf\x61\x55\xff",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       48,
+       "\x3f\xd2\x4c\xe1\xf5\xa6\x7b\x75\xbf\x23\x51\xf1\x81\xa4\x75\xc7"
+       "\xb8\x00\xa5\xb4\xd3\xdc\xf7\x01\x06\xb1\xee\xa8\x2f\xa1\xd6\x4d"
+       "\xf4\x2b\xf7\x22\x61\x22\xfa\x92\xe1\x7a\x40\xee\xaa\xc1\x20\x1b",
+       "\x5e\x6e\x31\x1d\xbf\x39\x5d\x35\xb0\xfe\x39\xc2\x71\x43\x88\xf8",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       64,
+       "\x24\x33\x66\x8f\x10\x58\x19\x0f\x6d\x43\xe3\x60\xf4\xf3\x5c\xd8"
+       "\xe4\x75\x12\x7c\xfc\xa7\x02\x8e\xa8\xab\x5c\x20\xf7\xab\x2a\xf0"
+       "\x25\x16\xa2\xbd\xcb\xc0\x8d\x52\x1b\xe3\x7f\xf2\x8c\x15\x2b\xba"
+       "\x36\x69\x7f\x25\xb4\xcd\x16\x9c\x65\x90\xd1\xdd\x39\x56\x6d\x3f",
+       "\x8a\x26\x3d\xd3\x17\xaa\x88\xd5\x6b\xdf\x39\x36\xdb\xa7\x5b\xb8",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00",
+       8,
+       "\x1e\x6d\xab\xa3\x56\x69\xf4\x27",
+       "\x3b\x0a\x1a\x25\x60\x96\x9c\xdf\x79\x0d\x99\x75\x9a\xbd\x15\x08",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       12,
+       "\x29\x6c\x78\x89\xfd\x99\xf4\x19\x17\xf4\x46\x20",
+       "\x08\x29\x9c\x51\x02\x74\x5a\xaa\x3a\x0c\x46\x9f\xad\x9e\x07\x5a",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\xe2\xb0\xc5\xda\x79\xa9\x01\xc1\x74\x5f\x70\x05\x25\xcb\x33\x5b",
+       "\x8f\x89\x36\xec\x03\x9e\x4e\x4b\xb9\x7e\xbd\x8c\x44\x57\x44\x1f",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       32,
+       "\x62\x00\x48\xef\x3c\x1e\x73\xe5\x7e\x02\xbb\x85\x62\xc4\x16\xa3"
+       "\x19\xe7\x3e\x4c\xaa\xc8\xe9\x6a\x1e\xcb\x29\x33\x14\x5a\x1d\x71",
+       "\xe6\xaf\x6a\x7f\x87\x28\x7d\xa0\x59\xa7\x16\x84\xed\x34\x98\xe1",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       48,
+       "\x50\xc8\x30\x3e\xa9\x39\x25\xd6\x40\x90\xd0\x7b\xd1\x09\xdf\xd9"
+       "\x51\x5a\x5a\x33\x43\x10\x19\xc1\x7d\x93\x46\x59\x99\xa8\xb0\x05"
+       "\x32\x01\xd7\x23\x12\x0a\x85\x62\xb8\x38\xcd\xff\x25\xbf\x9d\x1e",
+       "\x6a\x8c\xc3\x86\x5f\x76\x89\x7c\x2e\x4b\x24\x5c\xf3\x1c\x51\xf2",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       64,
+       "\x2f\x5c\x64\x05\x9d\xb5\x5e\xe0\xfb\x84\x7e\xd5\x13\x00\x37\x46"
+       "\xac\xa4\xe6\x1c\x71\x1b\x5d\xe2\xe7\xa7\x7f\xfd\x02\xda\x42\xfe"
+       "\xec\x60\x19\x10\xd3\x46\x7b\xb8\xb3\x6e\xbb\xae\xbc\xe5\xfb\xa3"
+       "\x0d\x36\xc9\x5f\x48\xa3\xe7\x98\x0f\x0e\x7a\xc2\x99\x33\x2a\x80",
+       "\xcd\xc4\x6a\xe4\x75\x56\x3d\xe0\x37\x00\x1e\xf8\x4a\xe2\x17\x44",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       12,
+       "\x02\x00\x00\x00",
+       4,
+       "\xa8\xfe\x3e\x87",
+       "\x07\xeb\x1f\x84\xfb\x28\xf8\xcb\x73\xde\x8e\x99\xe2\xf4\x8a\x14",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00",
+       18,
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00\x00\x00",
+       20,
+       "\x6b\xb0\xfe\xcf\x5d\xed\x9b\x77\xf9\x02\xc7\xd5\xda\x23\x6a\x43"
+       "\x91\xdd\x02\x97",
+       "\x24\xaf\xc9\x80\x5e\x97\x6f\x45\x1e\x6d\x87\xf6\xfe\x10\x65\x14",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00",
+       20,
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00",
+       18,
+       "\x44\xd0\xaa\xf6\xfb\x2f\x1f\x34\xad\xd5\xe8\x06\x4e\x83\xe1\x2a"
+       "\x2a\xda",
+       "\xbf\xf9\xb2\xef\x00\xfb\x47\x92\x0c\xc7\x2a\x0c\x0f\x13\xb9\xfd",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\xe6\x60\x21\xd5\xeb\x8e\x4f\x40\x66\xd4\xad\xb9\xc3\x35\x60\xe4",
+       "\xf4\x6e\x44\xbb\x3d\xa0\x01\x5c\x94\xf7\x08\x87",
+       "",
+       0,
+       "",
+       0,
+       "",
+       "\xa4\x19\x4b\x79\x07\x1b\x01\xa8\x7d\x65\xf7\x06\xe3\x94\x95\x78",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x36\x86\x42\x00\xe0\xea\xf5\x28\x4d\x88\x4a\x0e\x77\xd3\x16\x46",
+       "\xba\xe8\xe3\x7f\xc8\x34\x41\xb1\x60\x34\x56\x6b",
+       "\x46\xbb\x91\xc3\xc5",
+       5,
+       "\x7a\x80\x6c",
+       3,
+       "\xaf\x60\xeb",
+       "\x71\x1b\xd8\x5b\xc1\xe4\xd3\xe0\xa4\x62\xe0\x74\xee\xa4\x28\xa8",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\xae\xdb\x64\xa6\xc5\x90\xbc\x84\xd1\xa5\xe2\x69\xe4\xb4\x78\x01",
+       "\xaf\xc0\x57\x7e\x34\x69\x9b\x9e\x67\x1f\xdd\x4f",
+       "\xfc\x88\x0c\x94\xa9\x51\x98\x87\x42\x96",
+       10,
+       "\xbd\xc6\x6f\x14\x65\x45",
+       6,
+       "\xbb\x93\xa3\xe3\x4d\x3c",
+       "\xd6\xa9\xc4\x55\x45\xcf\xc1\x1f\x03\xad\x74\x3d\xba\x20\xf9\x66",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\xd5\xcc\x1f\xd1\x61\x32\x0b\x69\x20\xce\x07\x78\x7f\x86\x74\x3b",
+       "\x27\x5d\x1a\xb3\x2f\x6d\x1f\x04\x34\xd8\x84\x8c",
+       "\x04\x67\x87\xf3\xea\x22\xc1\x27\xaa\xf1\x95\xd1\x89\x47\x28",
+       15,
+       "\x11\x77\x44\x1f\x19\x54\x95\x86\x0f",
+       9,
+       "\x4f\x37\x28\x1f\x7a\xd1\x29\x49\xd0",
+       "\x1d\x02\xfd\x0c\xd1\x74\xc8\x4f\xc5\xda\xe2\xf6\x0f\x52\xfd\x2b",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\xb3\xfe\xd1\x47\x3c\x52\x8b\x84\x26\xa5\x82\x99\x59\x29\xa1\x49",
+       "\x9e\x9a\xd8\x78\x0c\x8d\x63\xd0\xab\x41\x49\xc0",
+       "\xc9\x88\x2e\x53\x86\xfd\x9f\x92\xec\x48\x9c\x8f\xde\x2b\xe2\xcf"
+       "\x97\xe7\x4e\x93",
+       20,
+       "\x9f\x57\x2c\x61\x4b\x47\x45\x91\x44\x74\xe7\xc7",
+       12,
+       "\xf5\x46\x73\xc5\xdd\xf7\x10\xc7\x45\x64\x1c\x8b",
+       "\xc1\xdc\x2f\x87\x1f\xb7\x56\x1d\xa1\x28\x6e\x65\x5e\x24\xb7\xb0",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\x2d\x4e\xd8\x7d\xa4\x41\x02\x95\x2e\xf9\x4b\x02\xb8\x05\x24\x9b",
+       "\xac\x80\xe6\xf6\x14\x55\xbf\xac\x83\x08\xa2\xd4",
+       "\x29\x50\xa7\x0d\x5a\x1d\xb2\x31\x6f\xd5\x68\x37\x8d\xa1\x07\xb5"
+       "\x2b\x0d\xa5\x52\x10\xcc\x1c\x1b\x0a",
+       25,
+       "\x0d\x8c\x84\x51\x17\x80\x82\x35\x5c\x9e\x94\x0f\xea\x2f\x58",
+       15,
+       "\xc9\xff\x54\x5e\x07\xb8\x8a\x01\x5f\x05\xb2\x74\x54\x0a\xa1",
+       "\x83\xb3\x44\x9b\x9f\x39\x55\x2d\xe9\x9d\xc2\x14\xa1\x19\x0b\x0b",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\xbd\xe3\xb2\xf2\x04\xd1\xe9\xf8\xb0\x6b\xc4\x7f\x97\x45\xb3\xd1",
+       "\xae\x06\x55\x6f\xb6\xaa\x78\x90\xbe\xbc\x18\xfe",
+       "\x18\x60\xf7\x62\xeb\xfb\xd0\x82\x84\xe4\x21\x70\x2d\xe0\xde\x18"
+       "\xba\xa9\xc9\x59\x62\x91\xb0\x84\x66\xf3\x7d\xe2\x1c\x7f",
+       30,
+       "\x6b\x3d\xb4\xda\x3d\x57\xaa\x94\x84\x2b\x98\x03\xa9\x6e\x07\xfb"
+       "\x6d\xe7",
+       18,
+       "\x62\x98\xb2\x96\xe2\x4e\x8c\xc3\x5d\xce\x0b\xed\x48\x4b\x7f\x30"
+       "\xd5\x80",
+       "\x3e\x37\x70\x94\xf0\x47\x09\xf6\x4d\x7b\x98\x53\x10\xa4\xdb\x84",
+      },
+      {
+       GCRY_CIPHER_AES128,
+       "\xf9\x01\xcf\xe8\xa6\x96\x15\xa9\x3f\xdf\x7a\x98\xca\xd4\x81\x79",
+       "\x62\x45\x70\x9f\xb1\x88\x53\xf6\x8d\x83\x36\x40",
+       "\x75\x76\xf7\x02\x8e\xc6\xeb\x5e\xa7\xe2\x98\x34\x2a\x94\xd4\xb2"
+       "\x02\xb3\x70\xef\x97\x68\xec\x65\x61\xc4\xfe\x6b\x7e\x72\x96\xfa"
+       "\x85\x9c\x21",
+       35,
+       "\xe4\x2a\x3c\x02\xc2\x5b\x64\x86\x9e\x14\x6d\x7b\x23\x39\x87\xbd"
+       "\xdf\xc2\x40\x87\x1d",
+       21,
+       "\x39\x1c\xc3\x28\xd4\x84\xa4\xf4\x64\x06\x18\x1b\xcd\x62\xef\xd9"
+       "\xb3\xee\x19\x7d\x05",
+       "\x2d\x15\x50\x6c\x84\xa9\xed\xd6\x5e\x13\xe9\xd2\x4a\x2a\x6e\x70",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "",
+       0,
+       "",
+       "\x07\xf5\xf4\x16\x9b\xbf\x55\xa8\x40\x0c\xd4\x7e\xa6\xfd\x40\x0f",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00",
+       8,
+       "\xc2\xef\x32\x8e\x5c\x71\xc8\x3b",
+       "\x84\x31\x22\x13\x0f\x73\x64\xb7\x61\xe0\xb9\x74\x27\xe3\xdf\x28",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       12,
+       "\x9a\xab\x2a\xeb\x3f\xaa\x0a\x34\xae\xa8\xe2\xb1",
+       "\x8c\xa5\x0d\xa9\xae\x65\x59\xe4\x8f\xd1\x0f\x6e\x5c\x9c\xa1\x7e",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\x85\xa0\x1b\x63\x02\x5b\xa1\x9b\x7f\xd3\xdd\xfc\x03\x3b\x3e\x76",
+       "\xc9\xea\xc6\xfa\x70\x09\x42\x70\x2e\x90\x86\x23\x83\xc6\xc3\x66",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       32,
+       "\x4a\x6a\x9d\xb4\xc8\xc6\x54\x92\x01\xb9\xed\xb5\x30\x06\xcb\xa8"
+       "\x21\xec\x9c\xf8\x50\x94\x8a\x7c\x86\xc6\x8a\xc7\x53\x9d\x02\x7f",
+       "\xe8\x19\xe6\x3a\xbc\xd0\x20\xb0\x06\xa9\x76\x39\x76\x32\xeb\x5d",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       48,
+       "\xc0\x0d\x12\x18\x93\xa9\xfa\x60\x3f\x48\xcc\xc1\xca\x3c\x57\xce"
+       "\x74\x99\x24\x5e\xa0\x04\x6d\xb1\x6c\x53\xc7\xc6\x6f\xe7\x17\xe3"
+       "\x9c\xf6\xc7\x48\x83\x7b\x61\xf6\xee\x3a\xdc\xee\x17\x53\x4e\xd5",
+       "\x79\x0b\xc9\x68\x80\xa9\x9b\xa8\x04\xbd\x12\xc0\xe6\xa2\x2c\xc4",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       64,
+       "\xc2\xd5\x16\x0a\x1f\x86\x83\x83\x49\x10\xac\xda\xfc\x41\xfb\xb1"
+       "\x63\x2d\x4a\x35\x3e\x8b\x90\x5e\xc9\xa5\x49\x9a\xc3\x4f\x96\xc7"
+       "\xe1\x04\x9e\xb0\x80\x88\x38\x91\xa4\xdb\x8c\xaa\xa1\xf9\x9d\xd0"
+       "\x04\xd8\x04\x87\x54\x07\x35\x23\x4e\x37\x44\x51\x2c\x6f\x90\xce",
+       "\x11\x28\x64\xc2\x69\xfc\x0d\x9d\x88\xc6\x1f\xa4\x7e\x39\xaa\x08",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00",
+       8,
+       "\x1d\xe2\x29\x67\x23\x7a\x81\x32",
+       "\x91\x21\x3f\x26\x7e\x3b\x45\x2f\x02\xd0\x1a\xe3\x3e\x4e\xc8\x54",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       12,
+       "\x16\x3d\x6f\x9c\xc1\xb3\x46\xcd\x45\x3a\x2e\x4c",
+       "\xc1\xa4\xa1\x9a\xe8\x00\x94\x1c\xcd\xc5\x7c\xc8\x41\x3c\x27\x7f",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\xc9\x15\x45\x82\x3c\xc2\x4f\x17\xdb\xb0\xe9\xe8\x07\xd5\xec\x17",
+       "\xb2\x92\xd2\x8f\xf6\x11\x89\xe8\xe4\x9f\x38\x75\xef\x91\xaf\xf7",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       32,
+       "\x07\xda\xd3\x64\xbf\xc2\xb9\xda\x89\x11\x6d\x7b\xef\x6d\xaa\xaf"
+       "\x6f\x25\x55\x10\xaa\x65\x4f\x92\x0a\xc8\x1b\x94\xe8\xba\xd3\x65",
+       "\xae\xa1\xba\xd1\x27\x02\xe1\x96\x56\x04\x37\x4a\xab\x96\xdb\xbc",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       48,
+       "\xc6\x7a\x1f\x0f\x56\x7a\x51\x98\xaa\x1f\xcc\x8e\x3f\x21\x31\x43"
+       "\x36\xf7\xf5\x1c\xa8\xb1\xaf\x61\xfe\xac\x35\xa8\x64\x16\xfa\x47"
+       "\xfb\xca\x3b\x5f\x74\x9c\xdf\x56\x45\x27\xf2\x31\x4f\x42\xfe\x25",
+       "\x03\x33\x27\x42\xb2\x28\xc6\x47\x17\x36\x16\xcf\xd4\x4c\x54\xeb",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01",
+       1,
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       64,
+       "\x67\xfd\x45\xe1\x26\xbf\xb9\xa7\x99\x30\xc4\x3a\xad\x2d\x36\x96"
+       "\x7d\x3f\x0e\x4d\x21\x7c\x1e\x55\x1f\x59\x72\x78\x70\xbe\xef\xc9"
+       "\x8c\xb9\x33\xa8\xfc\xe9\xde\x88\x7b\x1e\x40\x79\x99\x88\xdb\x1f"
+       "\xc3\xf9\x18\x80\xed\x40\x5b\x2d\xd2\x98\x31\x88\x58\x46\x7c\x89",
+       "\x5b\xde\x02\x85\x03\x7c\x5d\xe8\x1e\x5b\x57\x0a\x04\x9b\x62\xa0",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       12,
+       "\x02\x00\x00\x00",
+       4,
+       "\x22\xb3\xf4\xcd",
+       "\x18\x35\xe5\x17\x74\x1d\xfd\xdc\xcf\xa0\x7f\xa4\x66\x1b\x74\xcf",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00",
+       18,
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00\x00\x00",
+       20,
+       "\x43\xdd\x01\x63\xcd\xb4\x8f\x9f\xe3\x21\x2b\xf6\x1b\x20\x19\x76"
+       "\x06\x7f\x34\x2b",
+       "\xb8\x79\xad\x97\x6d\x82\x42\xac\xc1\x88\xab\x59\xca\xbf\xe3\x07",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00",
+       20,
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x04\x00",
+       18,
+       "\x46\x24\x01\x72\x4b\x5c\xe6\x58\x8d\x5a\x54\xaa\xe5\x37\x55\x13"
+       "\xa0\x75",
+       "\xcf\xcd\xf5\x04\x21\x12\xaa\x29\x68\x5c\x91\x2f\xc2\x05\x65\x43",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\xe6\x60\x21\xd5\xeb\x8e\x4f\x40\x66\xd4\xad\xb9\xc3\x35\x60\xe4"
+       "\xf4\x6e\x44\xbb\x3d\xa0\x01\x5c\x94\xf7\x08\x87\x36\x86\x42\x00",
+       "\xe0\xea\xf5\x28\x4d\x88\x4a\x0e\x77\xd3\x16\x46",
+       "",
+       0,
+       "",
+       0,
+       "",
+       "\x16\x9f\xbb\x2f\xbf\x38\x9a\x99\x5f\x63\x90\xaf\x22\x22\x8a\x62",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\xba\xe8\xe3\x7f\xc8\x34\x41\xb1\x60\x34\x56\x6b\x7a\x80\x6c\x46"
+       "\xbb\x91\xc3\xc5\xae\xdb\x64\xa6\xc5\x90\xbc\x84\xd1\xa5\xe2\x69",
+       "\xe4\xb4\x78\x01\xaf\xc0\x57\x7e\x34\x69\x9b\x9e",
+       "\x4f\xbd\xc6\x6f\x14",
+       5,
+       "\x67\x1f\xdd",
+       3,
+       "\x0e\xac\xcb",
+       "\x93\xda\x9b\xb8\x13\x33\xae\xe0\xc7\x85\xb2\x40\xd3\x19\x71\x9d",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x65\x45\xfc\x88\x0c\x94\xa9\x51\x98\x87\x42\x96\xd5\xcc\x1f\xd1"
+       "\x61\x32\x0b\x69\x20\xce\x07\x78\x7f\x86\x74\x3b\x27\x5d\x1a\xb3",
+       "\x2f\x6d\x1f\x04\x34\xd8\x84\x8c\x11\x77\x44\x1f",
+       "\x67\x87\xf3\xea\x22\xc1\x27\xaa\xf1\x95",
+       10,
+       "\x19\x54\x95\x86\x0f\x04",
+       6,
+       "\xa2\x54\xda\xd4\xf3\xf9",
+       "\x6b\x62\xb8\x4d\xc4\x0c\x84\x63\x6a\x5e\xc1\x20\x20\xec\x8c\x2c",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\xd1\x89\x47\x28\xb3\xfe\xd1\x47\x3c\x52\x8b\x84\x26\xa5\x82\x99"
+       "\x59\x29\xa1\x49\x9e\x9a\xd8\x78\x0c\x8d\x63\xd0\xab\x41\x49\xc0",
+       "\x9f\x57\x2c\x61\x4b\x47\x45\x91\x44\x74\xe7\xc7",
+       "\x48\x9c\x8f\xde\x2b\xe2\xcf\x97\xe7\x4e\x93\x2d\x4e\xd8\x7d",
+       15,
+       "\xc9\x88\x2e\x53\x86\xfd\x9f\x92\xec",
+       9,
+       "\x0d\xf9\xe3\x08\x67\x82\x44\xc4\x4b",
+       "\xc0\xfd\x3d\xc6\x62\x8d\xfe\x55\xeb\xb0\xb9\xfb\x22\x95\xc8\xc2",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\xa4\x41\x02\x95\x2e\xf9\x4b\x02\xb8\x05\x24\x9b\xac\x80\xe6\xf6"
+       "\x14\x55\xbf\xac\x83\x08\xa2\xd4\x0d\x8c\x84\x51\x17\x80\x82\x35",
+       "\x5c\x9e\x94\x0f\xea\x2f\x58\x29\x50\xa7\x0d\x5a",
+       "\x0d\xa5\x52\x10\xcc\x1c\x1b\x0a\xbd\xe3\xb2\xf2\x04\xd1\xe9\xf8"
+       "\xb0\x6b\xc4\x7f",
+       20,
+       "\x1d\xb2\x31\x6f\xd5\x68\x37\x8d\xa1\x07\xb5\x2b",
+       12,
+       "\x8d\xbe\xb9\xf7\x25\x5b\xf5\x76\x9d\xd5\x66\x92",
+       "\x40\x40\x99\xc2\x58\x7f\x64\x97\x9f\x21\x82\x67\x06\xd4\x97\xd5",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x97\x45\xb3\xd1\xae\x06\x55\x6f\xb6\xaa\x78\x90\xbe\xbc\x18\xfe"
+       "\x6b\x3d\xb4\xda\x3d\x57\xaa\x94\x84\x2b\x98\x03\xa9\x6e\x07\xfb",
+       "\x6d\xe7\x18\x60\xf7\x62\xeb\xfb\xd0\x82\x84\xe4",
+       "\xf3\x7d\xe2\x1c\x7f\xf9\x01\xcf\xe8\xa6\x96\x15\xa9\x3f\xdf\x7a"
+       "\x98\xca\xd4\x81\x79\x62\x45\x70\x9f",
+       25,
+       "\x21\x70\x2d\xe0\xde\x18\xba\xa9\xc9\x59\x62\x91\xb0\x84\x66",
+       15,
+       "\x79\x35\x76\xdf\xa5\xc0\xf8\x87\x29\xa7\xed\x3c\x2f\x1b\xff",
+       "\xb3\x08\x0d\x28\xf6\xeb\xb5\xd3\x64\x8c\xe9\x7b\xd5\xba\x67\xfd",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\xb1\x88\x53\xf6\x8d\x83\x36\x40\xe4\x2a\x3c\x02\xc2\x5b\x64\x86"
+       "\x9e\x14\x6d\x7b\x23\x39\x87\xbd\xdf\xc2\x40\x87\x1d\x75\x76\xf7",
+       "\x02\x8e\xc6\xeb\x5e\xa7\xe2\x98\x34\x2a\x94\xd4",
+       "\x9c\x21\x59\x05\x8b\x1f\x0f\xe9\x14\x33\xa5\xbd\xc2\x0e\x21\x4e"
+       "\xab\x7f\xec\xef\x44\x54\xa1\x0e\xf0\x65\x7d\xf2\x1a\xc7",
+       30,
+       "\xb2\x02\xb3\x70\xef\x97\x68\xec\x65\x61\xc4\xfe\x6b\x7e\x72\x96"
+       "\xfa\x85",
+       18,
+       "\x85\x7e\x16\xa6\x49\x15\xa7\x87\x63\x76\x87\xdb\x4a\x95\x19\x63"
+       "\x5c\xdd",
+       "\x45\x4f\xc2\xa1\x54\xfe\xa9\x1f\x83\x63\xa3\x9f\xec\x7d\x0a\x49",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x3c\x53\x5d\xe1\x92\xea\xed\x38\x22\xa2\xfb\xbe\x2c\xa9\xdf\xc8"
+       "\x82\x55\xe1\x4a\x66\x1b\x8a\xa8\x2c\xc5\x42\x36\x09\x3b\xbc\x23",
+       "\x68\x80\x89\xe5\x55\x40\xdb\x18\x72\x50\x4e\x1c",
+       "\x73\x43\x20\xcc\xc9\xd9\xbb\xbb\x19\xcb\x81\xb2\xaf\x4e\xcb\xc3"
+       "\xe7\x28\x34\x32\x1f\x7a\xa0\xf7\x0b\x72\x82\xb4\xf3\x3d\xf2\x3f"
+       "\x16\x75\x41",
+       35,
+       "\xce\xd5\x32\xce\x41\x59\xb0\x35\x27\x7d\x4d\xfb\xb7\xdb\x62\x96"
+       "\x8b\x13\xcd\x4e\xec",
+       21,
+       "\x62\x66\x60\xc2\x6e\xa6\x61\x2f\xb1\x7a\xd9\x1e\x8e\x76\x76\x39"
+       "\xed\xd6\xc9\xfa\xee",
+       "\x9d\x6c\x70\x29\x67\x5b\x89\xea\xf4\xba\x1d\xed\x1a\x28\x65\x94",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x4d\xb9\x23\xdc\x79\x3e\xe6\x49\x7c\x76\xdc\xc0\x3a\x98\xe1\x08",
+       32,
+       "\xf3\xf8\x0f\x2c\xf0\xcb\x2d\xd9\xc5\x98\x4f\xcd\xa9\x08\x45\x6c"
+       "\xc5\x37\x70\x3b\x5b\xa7\x03\x24\xa6\x79\x3a\x7b\xf2\x18\xd3\xea",
+       "\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      },
+      {
+       GCRY_CIPHER_AES256,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\xeb\x36\x40\x27\x7c\x7f\xfd\x13\x03\xc7\xa5\x42\xd0\x2d\x3e\x4c"
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       24,
+       "\x18\xce\x4f\x0b\x8c\xb4\xd0\xca\xc6\x5f\xea\x8f\x79\x25\x7b\x20"
+       "\x88\x8e\x53\xe7\x22\x99\xe5\x6d",
+       "\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+      },
+      /* Large block testing */
+      {
+       GCRY_CIPHER_AES128,
+       "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "",
+       0,
+       "\x72\x94\x7b\x5d\x3c\x14\xc0\xa6\x27\x8d\x8d\xee\xbd\xe8\x8c\x6a"
+       "\x21\x34\xce\x64\x8f\x01\x01\xc6\xe4\x5d\xed\x2e\xb9\xec\xac\x53"
+       "\xf2\x07\xed\x60\xc8\xa2\x2f\x2e\x83\x0e\xf2\xbc\x42\x51\x24\x3b"
+       "\x41\x4f\x26\x84\xf0\x25\x69\x3f\x38\x29\xfb\xe9\xbb\x1a\x94\xd1"
+       "\x94\x0c\xce\xad\x8e\x66\xeb\xda\xc9\x1c\x72\x5a\x7f\x95\x4f\x9c"
+       "\x02\x27\x79\x8f\xe7\x51\x51\x3d\x1e\x2c\x4e\xcd\x07\xe5\xd1\xf0"
+       "\x6c\x95\x82\x37\x00\x50\x5e\xff\x82\xfb\x69\x0b\x4e\x7f\x10\x12"
+       "\x7d\x18\x7f\xa8\x88\x59\xfb\x55\x9b\x70\x36\xfc\xde\x75\xed\x77"
+       "\xf9\x09\x87\x29\x30\x7c\x81\x41\x12\xc2\xbd\xcd\x9f\x86\x98\x38"
+       "\x96\x44\x4c\xda\x2e\xbe\x7a\xfb\xdd\x4a\x4e\xa0\x84\x94\xd5\x76"
+       "\xa6\xae\x02\xcb\x1b\xd4\xd8\xcb\xa5\x24\x28\xe1\x3c\x1e\xdc\x3d"
+       "\x25\x50\xe7\xfb\x92\xad\xd9\x80\x33\xe0\xb2\x50\x07\xd4\x43\x40"
+       "\x41\x63\x98\x63\xa6\x1a\xfc\x56\x84\x3f\xf7\x4f\x31\xe7\xfe\xc5"
+       "\x73\x52\xfd\x6d\x9b\xbb\x9b\xf8\x19\xf8\xdc\x9f\x3a\x88\xa6\x7c"
+       "\xf3\x6b\xbe\xde\xda\x05\x2e\x79\x54\xb9\x3e\x59\x43\x0a\x1b\x16"
+       "\xcf\x94\x97\x71\x03\x74\x12\x37\xaf\xd4\x0a\x4b\x30\x16\x9b\x8b"
+       "\x9f\xae\x78\x46\x83\xde\x34\xc5\x31\x71\x67\x5e\xdb\x8d\x93\x71"
+       "\x90\x03\x72\x00\x9f\x4e\x1e\x7d\xf3\x3f\xf8\x31\xe7\xf6\xb4\x6d"
+       "\x8d\xdc\xa0\x85\x32\x7b\x32\x40\x8c\xa9\x90\x69\xac\x03\xdb\xd4"
+       "\xa5\x62\x9c\xfd\x78\xde\xc8\x4a\x18\x67\xa0\xee\x5e\x1e\xad\x1a"
+       "\x1c\xee\x78\xbd\xea\xdc\xc8\x34\xd1\x92\x20\xa7\x0d\x12\x90\x88"
+       "\x91\xe4\x6c\x3c\x06\x78\x13\x00\xdc\xc7\x3e\xd7\x91\xf7\xc1\xd6"
+       "\x5a\x99\x95\x23\xb5\xd8\x3d\x0f\x12\xaf\x25\xd8\xcf\xe8\x27\x7f"
+       "\xbc\x7c\xe2\xad\x34\x66\x7f\xfb\xf5\xa8\x11\xc1\xe6\x04\x37\x41"
+       "\xaf\x96\xb3\xb7\xee\x05\xf5\xd7\x7c\xc6\xfe\x2e\xa9\x07\x47\x08"
+       "\xa4\x50\x65\xc0\x2e\xd7\x27\xd8\x70\x8c\xf1\x12\x30\x4a\x82\xf6"
+       "\xb7\x68\xdb\x9d\x73\xc2\x82\x3d\x44\xda\xfb\xdd\x03\xc1\xdc\xfc"
+       "\x3f\x7f\x2e\xe2\xd3\x73\x24\xaf\xd1\x35\xa9\x4f\x3a\xad\x9d\x5c"
+       "\xd7\xc6\xa3\xb1\x11\xf1\xbb\xa0\x23\xe1\x22\x88\x5b\x10\xb3\xd6"
+       "\x01\x78\x5f\x9e\x4d\x96\x7b\xeb\x81\x6b\xce\x2d\xf5\x6a\xd1\xa8"
+       "\xb7\x56\xdd\xd0\x4b\xb0\xc9\x64\x7a\x2f\x63\xcb\xd6\x61\x84\x4b"
+       "\x9e\x4d\x0b\x2c\x99\xbc\xa2\x94\xf5\x07\x20\xe6\xe9\xc2\xd2\xa6"
+       "\x1c\x37\xd5\x88\x01\x71\xe2\x16\xcd\x10\x7a\x07\x8b\xf3\xb5\x49"
+       "\x75\xbe\x0b\xe1\xb2\x28\x15\x88\x2b\xb4\xee\x34\xfd\x67\x30\xd8"
+       "\xdc\x38\x90\x66\xb6\x51\x90\xb3\xdb\xee\x4e\x66\xc3\x05\xdf\xee"
+       "\x32\xac\x8b\xa2\x00\xcc\xff\xa2\x52\x19\x79\x7e\x6c\xc9\x68\xb2"
+       "\xab\xe4\x69\x11\xea\x00\xc9\x2b\x58\x77\x8b\x6c\x28\x0e\x40\x42"
+       "\xcc\xa7\xb2\x58\xed\x5e\x0b\x19\x49\xe5\x5e\xb1\xb5\x24\x61\x63"
+       "\x7d\x5b\x6a\x7d\x3d\xc1\x6e\x09\x64\x43\x66\x31\x3c\xb0\x26\x2e"
+       "\xc8\x27\xf6\x5a\x5f\x22\x94\x42\x62\x2a\xf6\x5a\x7d\xc2\x4a\x0d"
+       "\xd2\xad\xaa\x0e\xb2\xa4\x29\x1c\xb8\x3b\xaa\xc9\x1d\x1a\x30\xf8"
+       "\x0b\x35\xb2\x84\x75\xc3\x08\x0c\xe5\x36\xa9\xff\xfe\xb9\xc2\xb7"
+       "\x51\xab\x2d\x9d\x3e\x1c\x08\x8c\x6c\x64\xe1\xd9\x97\xf4\xfc\x4d"
+       "\x77\x6d\x0e\xce\x73\x0b\x7f\x57\x41\xed\xdf\x96\x11\xb3\xcc\x61"
+       "\xe8\x12\x31\x16\x72\x4c\x10\xd4\x52\x14\x4c\x83\xaa\x3c\x29\x6c"
+       "\x51\x40\x9a\x4d\x9b\xd0\xe6\x7f\xad\x31\x54\x88\x90\xe1\xa8\x0e"
+       "\xd8\xf4\x84\x11\xdb\x02\x41\xff\xb0\x8a\x92\x95\x97\xd6\x98\x8a"
+       "\xa0\x43\xda\x70\xbb\x17\xd0\x5a\x81\x3e\xf7\xcf\xc9\x33\xd9\x76"
+       "\x2f\x53\xa2\xac\xa0\x8a\x73\xe4\x0c\x81\xbe\x26\x01\x3f\x6d\x79"
+       "\x8a\x37\x59\x5b\x0a\x9a\x10\x6b\x04\x30\xed\xda\x11\x73\x73\xd9"
+       "\xa2\x9a\xf8\x8e\x67\x82\x5a\x8d\xc0\x52\xe8\x42\x89\xcd\x9c\xb1"
+       "\x5c\x3d\xd4\x75\x03\x71\x03\x3f\xdc\x6b\x79\xb4\x02\xb6\xac\xc4"
+       "\x11\x0f\x61\xc8\xf7\x5d\xc6\xbf\x48\x02\xa3\xdc\xa8\x37\x10\x85"
+       "\xb2\x8d\xbd\xb0\x79\x09\xb0\x5f\x30\x6c\x40\xba\x03\xbb\x22\xcc"
+       "\x80\xa1\xc3\x91\x88\x25\x92\xbe\xa6\xfa\x14\x77\x56\xb3\xc0\xb5"
+       "\x69\x8c\x6f\xed\x21\xaf\x0c\x79\x07\x64\xa2\xea\xeb\x47\x2c\x1e"
+       "\x7d\x6c\x12\xae\x75\xc4\xee\x12\x46\x72\x87\x65\x73\x51\xee\xf8"
+       "\x08\x63\x20\xa1\x61\xca\x73\x8f\xdf\xcb\x97\xf8\xfc\xb0\x56\xea"
+       "\x34\x9d\xce\xb8\x91\xb8\xfc\xec\x76\xd0\x71\xb7\x92\xc9\xb2\x28"
+       "\xee\x0b\x5d\x7c\x4a\xf6\x73\x4d\xc2\x5b\x5b\xae\x7b\xa6\x9c\xba"
+       "\x29\x7d\x7d\x3c\x29\x01\x04\x2d\xd1\x6c\x8d\x8d\xe5\xb4\x6b\xf9"
+       "\x2a\x83\xb8\x14\x00\x1c\x91\x72\x5e\x8f\x13\x56\x6d\x9b\x6d\x27"
+       "\xe8\x22\x55\x4b\x2f\x8a\x31\x16\x98\x03\x51\x73\xa7\x2e\x18\x81"
+       "\x51\x0a\x8f\x6d\x17\xd0\xea\x04\x1c\x11\xb9\x6b\x8e\xaa\x76",
+       1023,
+       "\x24\x28\x57\xa0\x3c\x12\xe2\x6a\x65\x97\x96\x75\xb3\x75\x67\x4c"
+       "\xd0\xc8\xa7\x07\x7d\x55\x10\xbc\x11\xfe\x45\xbe\x74\x27\x74\xa3"
+       "\x8b\xb8\x51\x0d\x2e\xf0\x0c\x83\xed\xe4\x8b\x15\xf2\xae\xd8\xd5"
+       "\xed\xd8\x76\x0d\x0b\x5b\x7b\x5a\x17\x83\xf3\x37\xe5\x81\x90\xe8"
+       "\x15\xb4\xec\xf8\x5a\x00\x72\xf2\xbb\x68\x0a\xc9\x6c\x4a\x80\x45"
+       "\x04\xa5\x7e\xfa\xf3\x45\x08\x65\xd0\xd6\xcd\x08\xd1\x1f\x45\x6b"
+       "\x23\xa9\x0f\xe1\x10\x90\x26\x48\x23\x23\xd2\x60\xc4\x16\x31\x03"
+       "\x30\xbe\xf0\xd0\xa0\xa7\xcf\xaa\xe6\x27\x0e\xd6\x7b\x79\xf1\x2b"
+       "\x29\x27\x57\x5a\xb7\xf5\xf8\xb4\x35\x3c\xb5\x10\xb8\xbf\xbe\xad"
+       "\xdb\x9b\x3d\x35\x63\xac\x9b\xfe\x86\x69\x2c\x54\xf5\x7c\x7f\xd6"
+       "\xcd\x33\x9f\x57\x7f\xce\x72\x18\x60\x2e\x20\x33\xc9\x13\x9f\x60"
+       "\x5f\x67\x24\xc2\xbb\x9e\x63\x80\xcf\x96\xb9\xf0\xf1\x9e\xcc\x5a"
+       "\x61\x02\x6d\xab\x4c\xf7\x13\xe4\x48\x0f\x9f\xc9\x24\x8e\x40\x06"
+       "\x53\x30\xac\xd9\xe8\xf5\xcd\xd4\xcf\x99\x1f\x3c\x08\x74\x38\x7e"
+       "\x0b\x76\x0d\xc3\xbd\x2a\x75\x3a\x55\x0c\xc6\xd3\x50\x59\x53\xf2"
+       "\x14\x1d\x09\xb0\xfa\x8d\xc2\x5e\x6b\x79\xed\x5e\x10\xcc\x1c\xbe"
+       "\x03\x75\x6d\x23\x44\xe8\xd6\x4d\x8f\xe4\xd6\x1a\x16\x83\x79\x72"
+       "\xdc\x51\x25\x61\x75\xe7\x00\x09\xdf\xfe\x0c\x6c\x99\xa8\xb0\xfc"
+       "\xbf\xb6\x7f\xae\x0a\x75\x2e\xd4\x69\xfe\xf1\xb7\x68\xbe\x07\xf0"
+       "\x9c\xa3\x82\x1f\x4d\x06\xa7\x73\x53\xbd\x98\x99\x93\x1b\xc9\xb6"
+       "\x04\x5e\xc0\xc1\xd8\x53\x7e\x6f\xd9\x4e\xa0\x37\xab\x71\x92\xc7"
+       "\x97\x4b\x80\x40\x14\xd0\xd0\xee\x93\xfb\xd5\x76\xce\xd7\x9e\x74"
+       "\xee\x5d\xe6\x79\xb2\x92\xbb\xff\x63\x19\x61\x64\xcc\x60\x80\x8b"
+       "\x9c\x1f\x38\x01\x43\xf7\xa6\xcd\x20\x5d\x1d\x2a\x2a\x25\xf4\xd5"
+       "\x17\x3d\x9c\xd2\x56\x8c\x76\x4e\xa0\xba\x24\x55\x55\xd4\x87\x78"
+       "\xde\x30\xe8\x6f\x39\xa5\x22\x91\x2b\x7b\x20\x6f\xf6\x44\xff\xec"
+       "\x29\x4e\xc8\x30\xf7\x23\x18\xef\xb8\x33\xfb\x5f\xf2\xe2\xd8\xc1"
+       "\xe3\x0f\x24\x19\xff\x99\x7e\xa2\xdb\x78\xde\xc3\x92\x47\x9b\x32"
+       "\xd6\xfa\xb7\x34\x14\xa4\xde\xd0\xa4\x6f\x7b\x03\x90\x80\x7a\x1e"
+       "\xb7\xc7\xc3\x75\x98\xa6\x76\xfc\xa6\x38\xa3\xf6\x17\xe8\x90\x25"
+       "\x28\x66\x41\x78\xe9\x70\x44\xbc\x62\x64\xf5\xaa\xd8\x62\x09\xf3"
+       "\xff\x05\xd5\x4e\xea\x8d\xf0\x0e\x4e\x3c\x37\xbe\x30\xe6\x69\x15"
+       "\xc5\x7b\xa6\x67\x1a\x74\xca\x4f\x0f\x5c\xf3\xac\x20\xaa\xc3\xad"
+       "\xf5\xb3\x58\x8e\x22\x53\x3d\xe8\x0a\x1b\x33\x88\xf1\x8d\x9c\xc8"
+       "\x5a\xb6\xd3\xde\x1a\x7a\x21\x12\x1e\x70\x0e\x52\x90\x24\xe0\x1c"
+       "\xaa\x04\x79\xbc\x58\x42\xcb\xe1\x42\x82\xbe\xeb\x17\xd6\xd9\x8c"
+       "\xc5\xe8\x77\xde\x77\xb5\x31\xf5\x7f\x09\x8b\x7d\x59\x6e\xbd\xe0"
+       "\x7b\x0f\xe6\x29\x37\x7b\x19\x90\x69\x33\x0a\xbe\x50\xa5\x11\xba"
+       "\xc5\x90\x78\x31\xfc\x1e\x6c\x8e\x50\x99\x2b\xd9\x50\x39\xaa\x80"
+       "\x19\x59\xae\x1e\x7a\x7d\xea\xbe\x92\x0e\xc1\xd4\x99\x71\x50\xb2"
+       "\x46\x0e\x39\x73\x45\x92\x8e\xd7\xb3\xcd\xf7\x37\x8e\x78\x2b\x2b"
+       "\xba\x33\xc1\x3e\xdd\xac\x9d\x09\xcd\xb0\x7e\x78\x05\x70\x44\x98"
+       "\x8d\xcd\xf3\xf4\x55\x07\x6a\x75\x66\x6a\xd2\xf2\x4a\x95\x6b\x07"
+       "\xfc\x8d\x6d\xe9\x40\xc5\x94\x19\xb5\x29\x5c\xaa\xb0\x7b\x2b\x8d"
+       "\x64\x41\xfd\x10\x58\xba\x6c\x1f\x7e\x88\x5f\x77\x8c\xe0\x3a\xda"
+       "\x7d\xed\xc4\xf1\x30\xce\x8d\x47\xd8\xe2\x8c\xca\xea\xf8\xb7\x73"
+       "\x9d\xb4\xfc\x06\x09\x17\x20\x00\x96\xe4\xd2\x07\x01\x10\x44\xef"
+       "\x7e\x18\x74\xac\xba\xe3\x26\x0d\x11\x27\xbf\xf3\xbb\x06\x1c\x49"
+       "\xd7\xae\x79\xe1\xaf\xd8\x66\x48\x03\xb6\x08\x66\x79\x11\xc5\x68"
+       "\x47\xbc\x4b\xfe\xc4\xa6\x7b\x3a\x66\xcd\x9f\x93\x70\xc2\x42\xd9"
+       "\xac\x54\x36\x73\x1b\x3a\x89\x1f\x13\xc7\x63\x9e\x43\xbf\xdd\xd7"
+       "\x54\xc7\xda\x6f\x74\x83\x81\x27\x19\xb3\xde\x1a\x14\xec\x0b\x96"
+       "\xee\x12\x02\xd1\x9f\x30\xe1\xef\xb8\xb4\xe9\xa4\x72\xc1\x48\xbc"
+       "\x23\x21\x64\x32\x0d\xac\x49\x6e\x53\x80\x37\x10\x2d\xcf\x6f\x11"
+       "\xf3\xd0\xf3\x02\xb6\x9d\x6e\x3c\x44\x39\x4d\xee\x8b\x8f\xea\xfa"
+       "\x20\xf4\x98\x67\x9c\xe3\x12\x82\xa8\xbe\x1c\x3a\x1c\x51\x81\x9d"
+       "\xc0\xfe\x46\x79\xd0\x19\x6b\xf1\x5d\xbb\x4d\xde\x42\xc9\x72\x93"
+       "\x62\x65\xb5\x88\xb1\x5f\x92\xfe\x56\x56\x58\xfb\x7a\x81\x7c\x02"
+       "\xb0\xc0\x53\x84\x6f\x13\x20\x53\xec\x49\x93\xae\x7e\x3c\x3f\xdf"
+       "\xe7\xba\xa0\x40\x24\x10\xd4\xe6\xf5\xed\x65\xd3\x21\x36\xb1\xe6"
+       "\x11\x0a\x47\xbc\xd3\x21\x33\x30\x03\x37\x8c\x45\xe5\xdd\xb0\xd5"
+       "\xcb\x80\x42\xdd\x84\xd6\x70\xf0\xbb\x5b\x44\xe0\x84\x8b\x83\x7c"
+       "\xcb\xec\x6a\x28\xa3\xf3\x4a\x6c\x0d\xb0\x79\x34\x13\x10\x64\xfc"
+       "\xee\x12\x55\x82\x25\x25\x30\xb9\xa6\xf8\x3c\x81\x36\xcd\xef",
+       "\xce\xc3\x13\x6c\x40\x2a\xcc\x51\xa1\xce\xb3\xed\xe8\xa6\x5b\x04",
+      }
+    };
+
+  gcry_cipher_hd_t hde, hdd;
+  unsigned char out[MAX_DATA_LEN];
+  unsigned char tag[16];
+  int i, keylen;
+  gcry_error_t err = 0;
+  size_t taglen2;
+
+  if (verbose)
+    fprintf (stderr, "  Starting GCM-SIV checks.\n");
+
+  for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
+    {
+      /* The AES algorithm is allowed in FIPS mode */
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
+        {
+          fail ("aes-gcm-siv, gcry_cipher_test_algo failed: %s\n", gpg_strerror (err));
+          continue;
+        }
+
+      if (verbose)
+       fprintf (stderr, "    checking GCM-SIV mode for %s [%i]\n",
+                gcry_cipher_algo_name (tv[i].algo),
+                tv[i].algo);
+      err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_GCM_SIV, 0);
+      if (!err)
+       err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_GCM_SIV, 0);
+      if (err)
+       {
+          fail ("aes-gcm-siv, gcry_cipher_open failed: %s\n", gpg_strerror (err));
+         return;
+       }
+
+      keylen = gcry_cipher_get_algo_keylen (tv[i].algo);
+      if (!keylen)
+        {
+          fail ("aes-gcm-siv, gcry_cipher_get_algo_keylen failed\n");
+          return;
+        }
+
+      err = gcry_cipher_setkey (hde, tv[i].key, keylen);
+      if (!err)
+       err = gcry_cipher_setkey (hdd, tv[i].key, keylen);
+      if (err)
+       {
+         fail ("aes-gcm-siv, gcry_cipher_setkey failed: %s\n",
+               gpg_strerror (err));
+         gcry_cipher_close (hde);
+         gcry_cipher_close (hdd);
+         return;
+       }
+
+      err = gcry_cipher_setiv (hde, tv[i].nonce, 12);
+      if (!err)
+       err = gcry_cipher_setiv (hdd, tv[i].nonce, 12);
+      if (err)
+       {
+         fail ("aes-gcm-siv, gcry_cipher_setiv failed: %s\n",
+               gpg_strerror (err));
+         gcry_cipher_close (hde);
+         gcry_cipher_close (hdd);
+         return;
+       }
+
+      if (tv[i].adlen >= 0)
+       {
+         err = gcry_cipher_authenticate (hde, tv[i].ad, tv[i].adlen);
+         if (!err)
+           err = gcry_cipher_authenticate (hdd, tv[i].ad, tv[i].adlen);
+         if (err)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_authenticate failed: %s\n",
+                   gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
+
+      err = gcry_cipher_info (hde, GCRYCTL_GET_TAGLEN, NULL, &taglen2);
+      if (err)
+       {
+         fail ("cipher-siv, gcryctl_get_taglen failed (tv %d): %s\n",
+               i, gpg_strerror (err));
+         gcry_cipher_close (hde);
+         gcry_cipher_close (hdd);
+         return;
+       }
+      if (taglen2 != 16)
+       {
+         fail ("cipher-siv, gcryctl_get_taglen returned bad length"
+               " (tv %d): got=%zu want=%d\n",
+               i, taglen2, 16);
+         gcry_cipher_close (hde);
+         gcry_cipher_close (hdd);
+         return;
+       }
+
+      if (tv[i].inlen)
+       {
+         err = gcry_cipher_encrypt (hde, out, tv[i].inlen,
+                                    tv[i].plaintext, tv[i].inlen);
+         if (err)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_encrypt (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].out, out, tv[i].inlen))
+           {
+             mismatch (tv[i].out, tv[i].inlen, out, tv[i].inlen);
+             fail ("aes-gcm-siv, encrypt mismatch entry %d\n", i);
+           }
+
+         err = gcry_cipher_gettag (hde, tag, taglen2);
+         if (err)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_gettag(%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].tag, tag, taglen2))
+           {
+             mismatch (tv[i].tag, taglen2, tag, taglen2);
+             fail ("aes-gcm-siv, tag mismatch entry %d\n", i);
+           }
+
+         err = gcry_cipher_set_decryption_tag (hdd, tag, taglen2);
+         if (err)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_set_decryption_tag (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         err = gcry_cipher_decrypt (hdd, out, tv[i].inlen, NULL, 0);
+         if (err)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_decrypt (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].plaintext, out, tv[i].inlen))
+           fail ("aes-gcm-siv, decrypt mismatch entry %d\n", i);
+
+         err = gcry_cipher_checktag (hdd, tag, taglen2);
+         if (err)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_checktag (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
+      else
+       {
+         err = gcry_cipher_gettag (hde, tag, taglen2);
+         if (err)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_gettag(%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         if (memcmp (tv[i].tag, tag, taglen2))
+           {
+             mismatch (tv[i].tag, taglen2, tag, taglen2);
+             fail ("aes-gcm-siv, tag mismatch entry %d\n", i);
+           }
 
-      if (tv[i].should_fail)
-        {
-          fail ("aes-gcm, negative test succeeded %d\n", i);
-          gcry_cipher_close (hde);
-          gcry_cipher_close (hdd);
-          return;
-        }
+         err = gcry_cipher_checktag (hdd, tv[i].tag, taglen2);
+         if (err)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_checktag (%d) failed: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+
+         tag[13] ^= 0x4;
+         err = gcry_cipher_checktag (hdd, tag, taglen2);
+         if (gpg_err_code (err) != GPG_ERR_CHECKSUM)
+           {
+             fail ("aes-gcm-siv, gcry_cipher_checktag (%d) expected checksum fail: %s\n",
+                   i, gpg_strerror (err));
+             gcry_cipher_close (hde);
+             gcry_cipher_close (hdd);
+             return;
+           }
+       }
 
-    next_tv:
       gcry_cipher_close (hde);
       gcry_cipher_close (hdd);
     }
   if (verbose)
-    fprintf (stderr, "  Completed GCM checks.\n");
-}
-
-
-static void
-check_gcm_cipher (void)
-{
-  /* Large buffers, no splitting. */
-  _check_gcm_cipher(0xffffffff);
-  /* Split input to one byte buffers. */
-  _check_gcm_cipher(1);
-  /* Split input to 7 byte buffers. */
-  _check_gcm_cipher(7);
-  /* Split input to 15 byte buffers. */
-  _check_gcm_cipher(15);
-  /* Split input to 16 byte buffers. */
-  _check_gcm_cipher(16);
-  /* Split input to 17 byte buffers. */
-  _check_gcm_cipher(17);
+    fprintf (stderr, "  Completed GCM-SIV checks.\n");
 }
 
 
 static void
 _check_poly1305_cipher (unsigned int step)
 {
-  struct tv
+  static const struct tv
   {
     int algo;
     const char *key;
@@ -2646,10 +6424,146 @@ _check_poly1305_cipher (unsigned int step)
        "\x3f\xf4\xde\xf0\x8e\x4b\x7a\x9d\xe5\x76\xd2\x65\x86\xce\xc6\x4b"
        "\x61\x16",
        "\x1a\xe1\x0b\x59\x4f\x09\xe2\x6a\x7e\x90\x2e\xcb\xd0\x60\x06\x91" },
+      /* generated with c implementation */
+      { GCRY_CIPHER_CHACHA20,
+       "\x1c\x92\x40\xa5\xeb\x55\xd3\x8a\xf3\x33\x88\x86\x04\xf6\xb5\xf0"
+       "\x47\x39\x17\xc1\x40\x2b\x80\x09\x9d\xca\x5c\xbc\x20\x70\x75\xc0",
+       "\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08", 12,
+       "\xf3\x33\x88\x86\x00\x00\x00\x00\x00\x00\x4e\x91", 12,
+       "\xb0\x58\x83\x17\x3a\x8e\x69\xf2\x18\x9d\x71\xe4\x8a\x0b\x7a\xcd"
+       "\xe2\xd8\xb9\x8b\xdf\x99\xc2\x6d\x05\x4b\x44\x1e\x65\x5d\xda\xd5"
+       "\x79\xf0\x19\xab\x94\x50\xd0\xc5\x54\xfe\x76\xc8\xd9\xf3\x39\x33"
+       "\x9c\x0f\x27\x89\x85\x99\xe3\xed\x5c\x31\x04\xa6\x20\xab\xb3\x78"
+       "\xac\x31\xba\x21\x8c\xac\x70\xd1\xe2\x92\xd6\x50\x58\x69\xab\xd4"
+       "\x38\xdc\x9c\x71\x81\xf7\xf1\x68\x10\x50\x07\x09\x0e\x51\x49\xd2"
+       "\x10\x9a\x2e\x78\xfb\xc7\xd3\xc2\x84\xda\xf2\x52\x17\x2c\xa6\xe8"
+       "\x56\x60\x80\x46\xed\xfb\x9f\xab\xc2\x01\xf0\x06\x6b\x6e\xcc\xf6"
+       "\x55\x3e\x81\xc7\x71\x9f\x10\xf0\x8e\x5a\x4b\xf6\xae\x90\x75\x03"
+       "\x4f\xb3\xb4\xff\x66\xfa\xe3\xb6\x1c\xca\x0c\x75\x8a\x08\x3d\xce"
+       "\x58\x69\x9d\xa9\x19\x29\xda\x2f\xa1\xb2\xae\xa7\x83\xd5\x92\xc2"
+       "\x15\xdc\xef\x76\xd2\xd1\x9f\xb4\x7f\x3e\xb3\x7a\xa8\x3e\xba\xa3"
+       "\x9e\x2e\x73\xe3\x4d\xdc\x50\xba\x5b\xb0\x8b\x1a\x87\x21\x03\x93"
+       "\x74\x20\x01\xda\x38\x85\x1c\x3c\x57\x51\x09\x0e\xd8\xfc\x2b\xef"
+       "\x38\x8e\x11\xa4\x9e\x11\xcc\xc5\x9f\x4c\xc2\x0d\x3e\x5f\x73\x40"
+       "\x5a\xf4\x5b\x57\x84\x6e\xc7\xd0\x8e\xad\x1c\x1b\xae\x59\xba\xf5"
+       "\x77\xed\x44\x08\x9c\x9b\xfd\x88\xd9\x27\xe8\x43\xe8\xdd\x86\xfd"
+       "\x05\x3a\xc2\x11\x88\x98\x87\xcb\xa1\x72\xc2\x52\x5c\xd1\x1a\x40"
+       "\x80\xe2\x1e\xe8\x9b\x4e\x63\x9b\xfb\x58\x11\x44\x36\x35\x83\x9b"
+       "\x20\x9b\x4b\x58\xef\x1f\xfa\xe1\xb0\xe0\xb8\x60\x87\x0b\xdb\x83"
+       "\x6f\xeb\xc0\x80\x63\xa8\xc4\x22\x0f\x1d\xec\x9b\x44\xfa\xd3\x13"
+       "\x75\xb0\xfe\x74\x3c\xde\x9e\xb4\x91\x72\xc5\xf6\x36\x14\x18\x2d"
+       "\x15\x2e\x6b\x34\xcf\xed\x86\x4f\x1b\x56\xcf\x09\x8f\x3d\xd1\x8d"
+       "\x01\x7c\xba\x6a\xf4\x82\xdc\xf6\x9e\xc9\x79\xd4\x9e\x50\xc2\x9a"
+       "\x4f\x90\x10\x44\xd5\xcf\x6b\x1d\xb3\xce\x7c\xeb\x3f\x8f\xbc\xe6"
+       "\x76\xad\x78\x97\xee\xaf\x66\x73\xe4\x11\xb9\x6c\xf4\xc1\x1a\x76"
+       "\xd6\x54\x4c\x6c\x44\x58\xec\xd9\x8f\xf9\xc6\x7f\x71\x95\x04\xfe"
+       "\x6b\x42\xd6\x4f\xc6\xa8\xc1\xfa\x1e\x2c\xf2\x49\x6a\x5a\xe5\x28"
+       "\x34\x30\x05\xc1\x21\x3a\x5f\xfd\xaf\x61\x1f\xa0\x91\xd4\x17\xcf"
+       "\x65\x9d\xf5\xdb\x4b\xc2\x3d\x12\xed\xe1\x4e\xf1\x34\x50\x13\xa7"
+       "\x3f\xe6\x26\xcb\xc9\xb3\x64\x69\xa9\x82\x21\xec\x64\xa9\x2e\x83"
+       "\xa9\x9d\xa0\xbe\x20\xef\x5f\x71\x45\xe7\x9f\x75\xa3\x72\x16\xef"
+       "\x1b\xf7\x9a\x15\xe2\x75\x92\x39\xbb\xb1\x4f\x34\xf4\x88\x0d\xcf"
+       "\xbf\xd6\xfe\x5d\x61\x14\x45\x83\xf9\x6a\x3e\x81\x0f\x14\x78\xda"
+       "\x94\xe2\xce\x7d\x1c\x15\xd7\xe0\x95\x1d\xd8\x96\xc2\x11\xb1\x55"
+       "\xae\xc6\x95\x43\x38\x0a\x01\xc2\x30\xb8\x1b\x12\x39\x98\x58\x20"
+       "\xbd\x65\x50\x1d\x17\x13\x02\xb9\xe4\x88\x39\x72\xc8\x58\xa0\xa8"
+       "\x8f\xb9\xc2\x78\x82\x3a\x56\xe8\x0d\xf9\x1b\xbb\xfb\xf0\x5b\xc4"
+       "\x9a\x2d\xf0\xd5\x57\x6f\xce\x4b\xb6\x3e\x1b\xbf\x54\xb4\x3e\x4e"
+       "\x52\x5c\x2e\x6b\x5e\x01\xd1\xb3\xb5\x16\x67\xe4\x16\xad\x3c\x4d"
+       "\x1c\xb2\xc0\x54\xcc\xf9\xba\x11\x85\xdf\x43\x1a\xfb\x55\x9b\x88"
+       "\x27\x9e\x17\x29\x41\x7d\x2a\xb4\xf6\x61\x93\xa5\x1f\x5b\xb3\x06"
+       "\xbe\x86\x40\x11\xc6\xfc\x36\x44\xdb\xbf\x4c\x6b\x21\x15\xa9\x10"
+       "\x01\xdc\x53\x9c\x57\x27\xbe\x55\x19\x86\x17\x96\xfa\xdc\x4d\xf4"
+       "\xd9\x79\xbe\x6c\x29\x1b\xed\xbd\x09\x72\xb4\xbf\x88\xc7\x52\x39"
+       "\x5f\x62\x35\xad\x41\x87\xa6\xaa\x99\x20\xbc\x7d\x97\x67\x83\xa5"
+       "\xc3\x43\xc6\x7f\x31\xb9\x0c\xe1\x82\xa5\x66\x9a\x58\xe3\xaf\x6b"
+       "\x59\x09\x5b\xad\xed\xc2\x57\x66\x4e\x72\xb0\xaa\x0d\xeb\x9c\x48"
+       "\x3f\x0b\xaf\xc6\x46\x06\x54\x3a\x2a\x19\xb3\x9d\xde\xd9\xa0\xcf"
+       "\x71\x69\x33\xe8\x2c\xa8\x56\x8c\x0b\xae\x41\xc7\xb5\xfd\xca\xea"
+       "\x0f\xd1\xd7\xe0\x3e\xf6\xf5\xd1\xb2\x57\x21\x00\x32\xca\x02\x4d"
+       "\x18\xbe\x2c\x25\xe9\xbe\x0a\x34\x44\x92\xaa\x43\x09\xf7\xb4\x35"
+       "\xac\x65\xc3\xc1\x4c\x66\x74\x91\x9f\xae\xe2\x27\x37\x8a\xfe\x13"
+       "\x57\xf0\x39\x30\xf0\x06\xef\xa0\x5f\x90\xb7\xfa\xd9\x42\x3e\xcb"
+       "\xdc\x9c\x44\x36\x13\x8e\x66\xbc\x85\xe8\xfa\x2c\x73\xa5\x87\xbd"
+       "\x63\x98\x42\x56\x1a\xe9\xc4\x80\xa1\x0e\xd5\x9a\x27\xd2\x82\x20"
+       "\x08\xe5\x98\x60\x00\x6d\xd9\x53\x9b\xae\x67\xfb\x03\xff\x82\xf1"
+       "\xc6\x9b\x0b\xf1\x2c\x97\x89\x1c\x8e\x84\xd0\xb3\x2a\x44\xa3\xb2"
+       "\x77\x1d\xf2\x2e\x6a\xf7\x05\x67\x32\x21\xca\x39\x2e\x7f\x1a\x69"
+       "\x21\xdd\xaa\xfc\x19\xad\xc5\xf8\xfe\x6f\x17\x9e\x32\x64\xf8\xeb"
+       "\x98\x8a\x5e\x2e\x89\xea\xfb\xed\xd7\x09\x1a\x7f\xa5\xf6\xe3\xd4"
+       "\x33\x60\xbb\xc2\x2b\x1a\xd6\x4c\x03\xe1\xc3\xc6\x90\x0e\x7a\x89"
+       "\xe8\x50\x4b\x47\xc2\x91\x5d\x2a\x49\xf5\xb0\x5f\x69\xbb\x88\x51"
+       "\x0c\xa2\xc0\x88\x99\x91\xcd\x77\x11\x31\x3a\x8f\x99\x03\xd7\x5e",
+       1024,
+       "\x9d\x96\x71\x67\x3d\x66\x16\x72\x55\x29\x61\x42\x77\x99\x4a\x50"
+       "\xdd\x2a\x80\x56\x8f\xb7\x50\x82\x80\x63\x47\x7b\xc1\x44\x3b\x02"
+       "\x5b\xe8\x96\x93\x97\x6c\xff\x42\x90\x40\xf9\xe9\x93\xfe\x7e\xa3"
+       "\x4c\xd9\xe8\xdc\xda\xf7\x8f\xcd\xe7\xa7\x1f\xaa\x7c\x8b\x07\xda"
+       "\xf0\x70\x4d\x47\x8e\x87\x86\x71\x1e\x7a\x13\x7b\x9c\x42\x5d\x30"
+       "\x0c\x04\xfb\x7b\xe0\x0e\xa7\xb1\x5c\x89\xf7\xdd\x81\x0a\xe0\xe4"
+       "\xe2\x69\xa2\x36\x60\x45\x1c\xcc\x27\x2f\xaf\x70\x59\x6d\xc5\xb4"
+       "\x40\x04\x69\x1d\xe8\xf3\xf5\x7e\x49\xd7\x81\x12\x5b\xd3\xc6\x77"
+       "\x82\x5c\x9e\x91\x6b\x6b\x7d\xd7\x45\xb8\x39\x94\x0a\x1a\xb4\xc4"
+       "\xff\xba\x05\x7b\x0b\xba\xe1\x81\x90\x29\xdd\xb5\x58\x0b\x1f\x82"
+       "\x9e\x4d\xdd\x1b\xc1\x62\x14\x1a\x8f\xc1\x8c\xf6\x46\x07\xb2\xcd"
+       "\x6a\xb5\xa1\x06\x4c\xc3\xa3\x3f\x02\x08\xe2\x29\x3c\x05\xbd\xcb"
+       "\xf0\xfa\x27\xf1\x7b\x48\x45\x46\x62\x88\x01\xb8\xd3\x0a\x29\xbc"
+       "\xd6\xbb\x20\xee\x75\x5f\x29\x0c\x47\x9e\x0f\x1d\xdf\x81\x39\x9a"
+       "\x1c\x48\x69\x09\xeb\x42\xae\x71\x11\x4c\x53\x9c\x69\xa6\x71\x50"
+       "\x45\x4d\x31\x71\xdd\xdb\xb1\x64\x37\xbf\x03\x76\xb2\x44\xf9\xbb"
+       "\xa3\x25\x6b\xcf\xb0\x9f\x1d\x78\xdf\x93\xde\x2d\x57\x23\x6f\xff"
+       "\x02\xf8\xc6\xf5\x5f\x4b\xd5\x8a\x15\xc2\x5f\x9d\x47\x3b\x2f\x8f"
+       "\x36\x93\x4a\x96\xae\x57\xaa\xd7\x6e\xea\x45\x94\xfb\xa2\xab\x56"
+       "\xae\x7e\xb3\xc5\x87\xa5\xd4\x2d\xf0\x99\x1e\x0a\x05\xb8\x33\xe4"
+       "\x89\x6c\x9e\x6d\x8c\xf1\xb4\xaa\x1f\xaa\xfb\x4b\x40\x90\xc0\x50"
+       "\xf3\x7d\x2a\x67\x68\x25\x0a\x9a\x89\x1f\x90\xfd\xb0\x9d\x7d\xaf"
+       "\x72\x22\xeb\x22\xb9\x63\x5f\x2c\x54\x49\xa3\x99\xc4\x74\xab\xc0"
+       "\x2c\x85\x31\x26\x84\x57\xfd\xce\x34\x10\x63\x57\x9f\x0c\x0a\xa3"
+       "\x02\xb0\x87\x36\xf5\xf8\x1e\x66\x81\x74\x2c\x3e\x90\xc0\x10\xf1"
+       "\x53\xd4\xc3\x45\x9b\xe2\x58\xcf\x86\x2e\xf4\xb3\x11\xff\xe6\xc8"
+       "\x5c\x74\x6e\xb4\xd9\x52\x2c\x52\x71\x5e\xb4\xf1\xca\xa7\x1c\x09"
+       "\x6a\x2d\xc0\x20\x38\xf5\x61\xdc\xd9\x8d\x42\x71\x65\xf8\xce\xa7"
+       "\xcb\x2c\x44\x09\x87\x5a\x02\xdd\x8c\xe1\xec\xd0\xe1\xeb\x4d\x25"
+       "\x70\x57\xbd\xc7\x1b\xee\xb5\xc0\x81\xc5\x75\x45\xb8\xb7\xad\xfd"
+       "\x33\xdc\xbe\x09\x71\xd0\xd4\xee\xf7\x37\x4e\x6f\x80\x5f\xec\x3f"
+       "\x35\x75\x39\xaa\x41\xe6\x62\x17\xc5\x8f\xa4\xa7\x31\xd6\xd5\xe9"
+       "\x56\xc2\xc7\x1d\xf1\x58\xf6\xad\x3b\xbc\xbe\x65\x12\xd4\xfb\xe2"
+       "\x0a\x5a\x64\x9e\xad\x70\x1d\x95\xbd\x24\x1a\xa9\x99\xc0\x70\x74"
+       "\xb1\x79\x01\x4f\xfd\x5d\x76\xa7\xd9\x53\x3d\x87\x2b\x51\xb4\xf3"
+       "\x17\xa5\x41\xe9\x8b\xba\xd3\x69\xcd\xe6\x44\x0f\x18\x8f\x59\x0d"
+       "\xb0\xb8\x2a\x7f\xbb\x16\x51\xf5\xe8\xad\xda\x66\xaa\x3a\xb6\x7d"
+       "\x10\x13\x8d\xd9\x7d\x15\x09\x80\x7b\x00\x67\x96\x90\x21\x3e\xd4"
+       "\x1a\xe8\x3b\x1c\x78\x31\x9b\x63\x64\xb9\x1b\x50\x11\x93\x48\x13"
+       "\x89\xcb\xba\x57\x23\xcd\x95\x95\xd5\xee\x8b\x0d\xb4\xdf\x0c\x8a"
+       "\xae\xae\x55\x3f\x93\xad\xc1\x3e\xe5\x31\x20\x73\x58\xb0\x0b\xba"
+       "\xf5\x03\x7b\x50\x39\xa3\x66\xa9\x82\x47\x65\x29\xa8\x49\xd7\x5c"
+       "\x51\x89\x97\x03\x31\x11\x75\x83\x6e\x4e\x80\x2d\x57\x93\x88\xec"
+       "\x0e\x22\xa8\xde\x50\x99\x2c\xaa\xaf\x60\x3a\x74\xa0\x31\x16\x37"
+       "\xcd\x8a\x4d\xda\x40\x1d\x0c\xf1\xc4\x7a\xd0\xaa\xf4\xa7\x55\xe3"
+       "\xa4\xe3\x9d\x27\x4f\x81\xc6\x07\x74\x13\x8e\x4b\xd9\x6c\x33\xba"
+       "\x28\x8d\xb7\x79\x36\x29\xfc\x98\x91\x29\x87\xe7\xf6\x92\xb8\x7c"
+       "\xe4\xca\xb7\x21\x49\x8c\x01\x59\xad\x65\x37\x62\x9b\xba\x40\xc1"
+       "\x79\x87\xe5\x48\x58\xe3\x0e\x3a\xda\x31\x03\x55\x36\x64\x00\xda"
+       "\x61\x8a\x0a\x93\xdc\x82\xcc\x63\x40\xb5\x46\xde\xf0\x8c\x3f\x6d"
+       "\x3e\x32\xf2\xe6\x1d\x37\xf0\xd1\x7e\x33\x52\xb6\x97\xc3\x80\x64"
+       "\xa4\x0d\x5f\x97\xa5\xd8\xa3\x47\x1a\x83\x1f\xd0\x52\x81\xb9\xd9"
+       "\x7a\x32\xe6\xf1\x3e\x7d\xdc\x01\x5d\xb8\x44\x12\xc0\x1f\x72\x72"
+       "\x8b\x0e\xfa\x05\x37\x73\xbd\xc4\x06\x67\x18\xd7\xd4\x80\x2c\x2c"
+       "\x13\x06\xfe\x82\x5b\x65\x88\xe3\x0b\x06\x3c\xe6\xe4\xd0\x8f\x24"
+       "\x6a\x6a\x4d\x21\x4c\x2d\x05\x76\x12\xf9\xee\xbf\xb5\x5e\xcd\x03"
+       "\xf0\x5b\x35\x82\xb7\x1d\x7b\xca\xa6\x14\x40\x68\xd2\xa5\x49\x34"
+       "\x69\xb7\x05\x48\xf9\xdb\x93\xd4\x0b\x45\x8d\xb3\x1e\xa3\xf9\x5d"
+       "\x8c\x18\xc5\x40\x14\x67\xc5\x40\xbe\x61\x53\x74\x52\x94\x6c\x5e"
+       "\xc6\xdf\xd0\xe7\xe5\xbd\x4b\xca\x89\xca\xf6\xf4\xc5\x6f\xf6\x87"
+       "\x9e\x3a\x11\x5a\xa8\xcd\x83\x70\x19\x63\x8a\xaf\x08\xb1\x33\xa9"
+       "\x2a\xcc\xde\x7f\xd2\x63\xfb\x85\x40\x77\x40\x8f\x9d\xa0\x7c\xed"
+       "\x8d\xe5\xe5\x31\x05\x75\xf2\x7e\xab\x22\x54\xbf\xfe\xd3\x1f\x45"
+       "\x95\x0d\x6d\x07\x6a\x90\x06\xd6\x45\x97\xc0\x82\x88\xfc\xd8\xd0",
+       "\xf1\xef\xf4\x8d\x9c\xfa\x92\x10\xd9\x4f\x22\x3f\x2f\x75\xe1\x8b" },
     };
 
   gcry_cipher_hd_t hde, hdd;
-  unsigned char out[1024];
+  unsigned char out[2048];
   unsigned char tag[16];
   int i, keylen;
   gcry_error_t err = 0;
@@ -2661,6 +6575,22 @@ _check_poly1305_cipher (unsigned int step)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
+      if (gcry_cipher_test_algo (tv[i].algo))
+        {
+          if (in_fips_mode)
+            {
+              if (verbose)
+                fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                         tv[i].algo);
+            }
+          continue;
+        }
+      else if (in_fips_mode)
+        {
+          fail ("poly1305, gcry_cipher_test_algo worked in fips mode\n");
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking POLY1305 mode for %s [%i]\n",
                  gcry_cipher_algo_name (tv[i].algo),
@@ -2942,6 +6872,7 @@ check_ccm_cipher (void)
   static const struct tv
   {
     int algo;
+    int flags;
     int keylen;
     const char *key;
     int noncelen;
@@ -2955,7 +6886,7 @@ check_ccm_cipher (void)
   } tv[] =
     {
       /* RFC 3610 */
-      { GCRY_CIPHER_AES, /* Packet Vector #1 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #1 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x03\x02\x01\x00\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -2963,7 +6894,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
           31,
           "\x58\x8C\x97\x9A\x61\xC6\x63\xD2\xF0\x66\xD0\xC2\xC0\xF9\x89\x80\x6D\x5F\x6B\x61\xDA\xC3\x84\x17\xE8\xD1\x2C\xFD\xF9\x26\xE0"},
-      { GCRY_CIPHER_AES, /* Packet Vector #2 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #2 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x04\x03\x02\x01\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -2971,7 +6902,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
           32,
           "\x72\xC9\x1A\x36\xE1\x35\xF8\xCF\x29\x1C\xA8\x94\x08\x5C\x87\xE3\xCC\x15\xC4\x39\xC9\xE4\x3A\x3B\xA0\x91\xD5\x6E\x10\x40\x09\x16"},
-      { GCRY_CIPHER_AES, /* Packet Vector #3 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #3 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x05\x04\x03\x02\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -2979,7 +6910,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
           33,
           "\x51\xB1\xE5\xF4\x4A\x19\x7D\x1D\xA4\x6B\x0F\x8E\x2D\x28\x2A\xE8\x71\xE8\x38\xBB\x64\xDA\x85\x96\x57\x4A\xDA\xA7\x6F\xBD\x9F\xB0\xC5"},
-      { GCRY_CIPHER_AES, /* Packet Vector #4 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #4 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x06\x05\x04\x03\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -2987,7 +6918,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
           27,
           "\xA2\x8C\x68\x65\x93\x9A\x9A\x79\xFA\xAA\x5C\x4C\x2A\x9D\x4A\x91\xCD\xAC\x8C\x96\xC8\x61\xB9\xC9\xE6\x1E\xF1"},
-      { GCRY_CIPHER_AES, /* Packet Vector #5 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #5 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x07\x06\x05\x04\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -2995,7 +6926,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
           28,
           "\xDC\xF1\xFB\x7B\x5D\x9E\x23\xFB\x9D\x4E\x13\x12\x53\x65\x8A\xD8\x6E\xBD\xCA\x3E\x51\xE8\x3F\x07\x7D\x9C\x2D\x93"},
-      { GCRY_CIPHER_AES, /* Packet Vector #6 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #6 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x08\x07\x06\x05\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3003,7 +6934,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
           29,
           "\x6F\xC1\xB0\x11\xF0\x06\x56\x8B\x51\x71\xA4\x2D\x95\x3D\x46\x9B\x25\x70\xA4\xBD\x87\x40\x5A\x04\x43\xAC\x91\xCB\x94"},
-      { GCRY_CIPHER_AES, /* Packet Vector #7 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #7 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x09\x08\x07\x06\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3011,7 +6942,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
           33,
           "\x01\x35\xD1\xB2\xC9\x5F\x41\xD5\xD1\xD4\xFE\xC1\x85\xD1\x66\xB8\x09\x4E\x99\x9D\xFE\xD9\x6C\x04\x8C\x56\x60\x2C\x97\xAC\xBB\x74\x90"},
-      { GCRY_CIPHER_AES, /* Packet Vector #8 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #8 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0A\x09\x08\x07\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3019,7 +6950,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
           34,
           "\x7B\x75\x39\x9A\xC0\x83\x1D\xD2\xF0\xBB\xD7\x58\x79\xA2\xFD\x8F\x6C\xAE\x6B\x6C\xD9\xB7\xDB\x24\xC1\x7B\x44\x33\xF4\x34\x96\x3F\x34\xB4"},
-      { GCRY_CIPHER_AES, /* Packet Vector #9 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #9 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0B\x0A\x09\x08\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3027,7 +6958,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
           35,
           "\x82\x53\x1A\x60\xCC\x24\x94\x5A\x4B\x82\x79\x18\x1A\xB5\xC8\x4D\xF2\x1C\xE7\xF9\xB7\x3F\x42\xE1\x97\xEA\x9C\x07\xE5\x6B\x5E\xB1\x7E\x5F\x4E"},
-      { GCRY_CIPHER_AES, /* Packet Vector #10 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #10 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0C\x0B\x0A\x09\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3035,7 +6966,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
           29,
           "\x07\x34\x25\x94\x15\x77\x85\x15\x2B\x07\x40\x98\x33\x0A\xBB\x14\x1B\x94\x7B\x56\x6A\xA9\x40\x6B\x4D\x99\x99\x88\xDD"},
-      { GCRY_CIPHER_AES, /* Packet Vector #11 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #11 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0D\x0C\x0B\x0A\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3043,7 +6974,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
           30,
           "\x67\x6B\xB2\x03\x80\xB0\xE3\x01\xE8\xAB\x79\x59\x0A\x39\x6D\xA7\x8B\x83\x49\x34\xF5\x3A\xA2\xE9\x10\x7A\x8B\x6C\x02\x2C"},
-      { GCRY_CIPHER_AES, /* Packet Vector #12 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #12 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0E\x0D\x0C\x0B\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3051,7 +6982,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
           31,
           "\xC0\xFF\xA0\xD6\xF0\x5B\xDB\x67\xF2\x4D\x43\xA4\x33\x8D\x2A\xA4\xBE\xD7\xB2\x0E\x43\xCD\x1A\xA3\x16\x62\xE7\xAD\x65\xD6\xDB"},
-      { GCRY_CIPHER_AES, /* Packet Vector #13 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #13 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x41\x2B\x4E\xA9\xCD\xBE\x3C\x96\x96\x76\x6C\xFA",
           8, "\x0B\xE1\xA8\x8B\xAC\xE0\x18\xB1",
@@ -3059,7 +6990,7 @@ check_ccm_cipher (void)
           "\x08\xE8\xCF\x97\xD8\x20\xEA\x25\x84\x60\xE9\x6A\xD9\xCF\x52\x89\x05\x4D\x89\x5C\xEA\xC4\x7C",
           31,
           "\x4C\xB9\x7F\x86\xA2\xA4\x68\x9A\x87\x79\x47\xAB\x80\x91\xEF\x53\x86\xA6\xFF\xBD\xD0\x80\xF8\xE7\x8C\xF7\xCB\x0C\xDD\xD7\xB3"},
-      { GCRY_CIPHER_AES, /* Packet Vector #14 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #14 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x33\x56\x8E\xF7\xB2\x63\x3C\x96\x96\x76\x6C\xFA",
           8, "\x63\x01\x8F\x76\xDC\x8A\x1B\xCB",
@@ -3067,7 +6998,7 @@ check_ccm_cipher (void)
           "\x90\x20\xEA\x6F\x91\xBD\xD8\x5A\xFA\x00\x39\xBA\x4B\xAF\xF9\xBF\xB7\x9C\x70\x28\x94\x9C\xD0\xEC",
           32,
           "\x4C\xCB\x1E\x7C\xA9\x81\xBE\xFA\xA0\x72\x6C\x55\xD3\x78\x06\x12\x98\xC8\x5C\x92\x81\x4A\xBC\x33\xC5\x2E\xE8\x1D\x7D\x77\xC0\x8A"},
-      { GCRY_CIPHER_AES, /* Packet Vector #15 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #15 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x10\x3F\xE4\x13\x36\x71\x3C\x96\x96\x76\x6C\xFA",
           8, "\xAA\x6C\xFA\x36\xCA\xE8\x6B\x40",
@@ -3075,7 +7006,7 @@ check_ccm_cipher (void)
           "\xB9\x16\xE0\xEA\xCC\x1C\x00\xD7\xDC\xEC\x68\xEC\x0B\x3B\xBB\x1A\x02\xDE\x8A\x2D\x1A\xA3\x46\x13\x2E",
           33,
           "\xB1\xD2\x3A\x22\x20\xDD\xC0\xAC\x90\x0D\x9A\xA0\x3C\x61\xFC\xF4\xA5\x59\xA4\x41\x77\x67\x08\x97\x08\xA7\x76\x79\x6E\xDB\x72\x35\x06"},
-      { GCRY_CIPHER_AES, /* Packet Vector #16 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #16 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x76\x4C\x63\xB8\x05\x8E\x3C\x96\x96\x76\x6C\xFA",
           12, "\xD0\xD0\x73\x5C\x53\x1E\x1B\xEC\xF0\x49\xC2\x44",
@@ -3083,7 +7014,7 @@ check_ccm_cipher (void)
           "\x12\xDA\xAC\x56\x30\xEF\xA5\x39\x6F\x77\x0C\xE1\xA6\x6B\x21\xF7\xB2\x10\x1C",
           27,
           "\x14\xD2\x53\xC3\x96\x7B\x70\x60\x9B\x7C\xBB\x7C\x49\x91\x60\x28\x32\x45\x26\x9A\x6F\x49\x97\x5B\xCA\xDE\xAF"},
-      { GCRY_CIPHER_AES, /* Packet Vector #17 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #17 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\xF8\xB6\x78\x09\x4E\x3B\x3C\x96\x96\x76\x6C\xFA",
           12, "\x77\xB6\x0F\x01\x1C\x03\xE1\x52\x58\x99\xBC\xAE",
@@ -3091,7 +7022,7 @@ check_ccm_cipher (void)
           "\xE8\x8B\x6A\x46\xC7\x8D\x63\xE5\x2E\xB8\xC5\x46\xEF\xB5\xDE\x6F\x75\xE9\xCC\x0D",
           28,
           "\x55\x45\xFF\x1A\x08\x5E\xE2\xEF\xBF\x52\xB2\xE0\x4B\xEE\x1E\x23\x36\xC7\x3E\x3F\x76\x2C\x0C\x77\x44\xFE\x7E\x3C"},
-      { GCRY_CIPHER_AES, /* Packet Vector #18 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #18 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\xD5\x60\x91\x2D\x3F\x70\x3C\x96\x96\x76\x6C\xFA",
           12, "\xCD\x90\x44\xD2\xB7\x1F\xDB\x81\x20\xEA\x60\xC0",
@@ -3099,7 +7030,7 @@ check_ccm_cipher (void)
           "\x64\x35\xAC\xBA\xFB\x11\xA8\x2E\x2F\x07\x1D\x7C\xA4\xA5\xEB\xD9\x3A\x80\x3B\xA8\x7F",
           29,
           "\x00\x97\x69\xEC\xAB\xDF\x48\x62\x55\x94\xC5\x92\x51\xE6\x03\x57\x22\x67\x5E\x04\xC8\x47\x09\x9E\x5A\xE0\x70\x45\x51"},
-      { GCRY_CIPHER_AES, /* Packet Vector #19 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #19 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x42\xFF\xF8\xF1\x95\x1C\x3C\x96\x96\x76\x6C\xFA",
           8, "\xD8\x5B\xC7\xE6\x9F\x94\x4F\xB8",
@@ -3107,7 +7038,7 @@ check_ccm_cipher (void)
           "\x8A\x19\xB9\x50\xBC\xF7\x1A\x01\x8E\x5E\x67\x01\xC9\x17\x87\x65\x98\x09\xD6\x7D\xBE\xDD\x18",
           33,
           "\xBC\x21\x8D\xAA\x94\x74\x27\xB6\xDB\x38\x6A\x99\xAC\x1A\xEF\x23\xAD\xE0\xB5\x29\x39\xCB\x6A\x63\x7C\xF9\xBE\xC2\x40\x88\x97\xC6\xBA"},
-      { GCRY_CIPHER_AES, /* Packet Vector #20 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #20 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x92\x0F\x40\xE5\x6C\xDC\x3C\x96\x96\x76\x6C\xFA",
           8, "\x74\xA0\xEB\xC9\x06\x9F\x5B\x37",
@@ -3115,7 +7046,7 @@ check_ccm_cipher (void)
           "\x17\x61\x43\x3C\x37\xC5\xA3\x5F\xC1\xF3\x9F\x40\x63\x02\xEB\x90\x7C\x61\x63\xBE\x38\xC9\x84\x37",
           34,
           "\x58\x10\xE6\xFD\x25\x87\x40\x22\xE8\x03\x61\xA4\x78\xE3\xE9\xCF\x48\x4A\xB0\x4F\x44\x7E\xFF\xF6\xF0\xA4\x77\xCC\x2F\xC9\xBF\x54\x89\x44"},
-      { GCRY_CIPHER_AES, /* Packet Vector #21 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #21 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x27\xCA\x0C\x71\x20\xBC\x3C\x96\x96\x76\x6C\xFA",
           8, "\x44\xA3\xAA\x3A\xAE\x64\x75\xCA",
@@ -3123,7 +7054,7 @@ check_ccm_cipher (void)
           "\xA4\x34\xA8\xE5\x85\x00\xC6\xE4\x15\x30\x53\x88\x62\xD6\x86\xEA\x9E\x81\x30\x1B\x5A\xE4\x22\x6B\xFA",
           35,
           "\xF2\xBE\xED\x7B\xC5\x09\x8E\x83\xFE\xB5\xB3\x16\x08\xF8\xE2\x9C\x38\x81\x9A\x89\xC8\xE7\x76\xF1\x54\x4D\x41\x51\xA4\xED\x3A\x8B\x87\xB9\xCE"},
-      { GCRY_CIPHER_AES, /* Packet Vector #22 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #22 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x5B\x8C\xCB\xCD\x9A\xF8\x3C\x96\x96\x76\x6C\xFA",
           12, "\xEC\x46\xBB\x63\xB0\x25\x20\xC3\x3C\x49\xFD\x70",
@@ -3131,7 +7062,7 @@ check_ccm_cipher (void)
           "\xB9\x6B\x49\xE2\x1D\x62\x17\x41\x63\x28\x75\xDB\x7F\x6C\x92\x43\xD2\xD7\xC2",
           29,
           "\x31\xD7\x50\xA0\x9D\xA3\xED\x7F\xDD\xD4\x9A\x20\x32\xAA\xBF\x17\xEC\x8E\xBF\x7D\x22\xC8\x08\x8C\x66\x6B\xE5\xC1\x97"},
-      { GCRY_CIPHER_AES, /* Packet Vector #23 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #23 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x3E\xBE\x94\x04\x4B\x9A\x3C\x96\x96\x76\x6C\xFA",
           12, "\x47\xA6\x5A\xC7\x8B\x3D\x59\x42\x27\xE8\x5E\x71",
@@ -3139,7 +7070,7 @@ check_ccm_cipher (void)
           "\xE2\xFC\xFB\xB8\x80\x44\x2C\x73\x1B\xF9\x51\x67\xC8\xFF\xD7\x89\x5E\x33\x70\x76",
           30,
           "\xE8\x82\xF1\xDB\xD3\x8C\xE3\xED\xA7\xC2\x3F\x04\xDD\x65\x07\x1E\xB4\x13\x42\xAC\xDF\x7E\x00\xDC\xCE\xC7\xAE\x52\x98\x7D"},
-      { GCRY_CIPHER_AES, /* Packet Vector #24 */
+      { GCRY_CIPHER_AES, 0, /* Packet Vector #24 */
           16, "\xD7\x82\x8D\x13\xB2\xB0\xBD\xC3\x25\xA7\x62\x36\xDF\x93\xCC\x6B",
           13, "\x00\x8D\x49\x3B\x30\xAE\x8B\x3C\x96\x96\x76\x6C\xFA",
           12, "\x6E\x37\xA6\xEF\x54\x6D\x95\x5D\x34\xAB\x60\x59",
@@ -3147,8 +7078,9 @@ check_ccm_cipher (void)
           "\xAB\xF2\x1C\x0B\x02\xFE\xB8\x8F\x85\x6D\xF4\xA3\x73\x81\xBC\xE3\xCC\x12\x85\x17\xD4",
           31,
           "\xF3\x29\x05\xB8\x8A\x64\x1B\x04\xB9\xC9\xFF\xB5\x8C\xC3\x90\x90\x0F\x3D\xA1\x2A\xB1\x6D\xCE\x9E\x82\xEF\xA1\x6D\xA6\x20\x59"},
+#if USE_CAMELLIA
       /* RFC 5528 */
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #1 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #1 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x03\x02\x01\x00\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3156,7 +7088,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
           31,
           "\xBA\x73\x71\x85\xE7\x19\x31\x04\x92\xF3\x8A\x5F\x12\x51\xDA\x55\xFA\xFB\xC9\x49\x84\x8A\x0D\xFC\xAE\xCE\x74\x6B\x3D\xB9\xAD"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #2 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #2 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x04\x03\x02\x01\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3164,7 +7096,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
           32,
           "\x5D\x25\x64\xBF\x8E\xAF\xE1\xD9\x95\x26\xEC\x01\x6D\x1B\xF0\x42\x4C\xFB\xD2\xCD\x62\x84\x8F\x33\x60\xB2\x29\x5D\xF2\x42\x83\xE8"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #3 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #3 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x05\x04\x03\x02\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3172,7 +7104,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
           33,
           "\x81\xF6\x63\xD6\xC7\x78\x78\x17\xF9\x20\x36\x08\xB9\x82\xAD\x15\xDC\x2B\xBD\x87\xD7\x56\xF7\x92\x04\xF5\x51\xD6\x68\x2F\x23\xAA\x46"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #4 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #4 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x06\x05\x04\x03\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3180,7 +7112,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
           27,
           "\xCA\xEF\x1E\x82\x72\x11\xB0\x8F\x7B\xD9\x0F\x08\xC7\x72\x88\xC0\x70\xA4\xA0\x8B\x3A\x93\x3A\x63\xE4\x97\xA0"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #5 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #5 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x07\x06\x05\x04\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3188,7 +7120,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
           28,
           "\x2A\xD3\xBA\xD9\x4F\xC5\x2E\x92\xBE\x43\x8E\x82\x7C\x10\x23\xB9\x6A\x8A\x77\x25\x8F\xA1\x7B\xA7\xF3\x31\xDB\x09"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #6 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #6 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x08\x07\x06\x05\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3196,7 +7128,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
           29,
           "\xFE\xA5\x48\x0B\xA5\x3F\xA8\xD3\xC3\x44\x22\xAA\xCE\x4D\xE6\x7F\xFA\x3B\xB7\x3B\xAB\xAB\x36\xA1\xEE\x4F\xE0\xFE\x28"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #7 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #7 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x09\x08\x07\x06\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3204,7 +7136,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
           33,
           "\x54\x53\x20\x26\xE5\x4C\x11\x9A\x8D\x36\xD9\xEC\x6E\x1E\xD9\x74\x16\xC8\x70\x8C\x4B\x5C\x2C\xAC\xAF\xA3\xBC\xCF\x7A\x4E\xBF\x95\x73"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #8 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #8 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0A\x09\x08\x07\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3212,7 +7144,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
           34,
           "\x8A\xD1\x9B\x00\x1A\x87\xD1\x48\xF4\xD9\x2B\xEF\x34\x52\x5C\xCC\xE3\xA6\x3C\x65\x12\xA6\xF5\x75\x73\x88\xE4\x91\x3E\xF1\x47\x01\xF4\x41"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #9 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #9 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0B\x0A\x09\x08\xA0\xA1\xA2\xA3\xA4\xA5",
           8, "\x00\x01\x02\x03\x04\x05\x06\x07",
@@ -3220,7 +7152,7 @@ check_ccm_cipher (void)
           "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
           35,
           "\x5D\xB0\x8D\x62\x40\x7E\x6E\x31\xD6\x0F\x9C\xA2\xC6\x04\x74\x21\x9A\xC0\xBE\x50\xC0\xD4\xA5\x77\x87\x94\xD6\xE2\x30\xCD\x25\xC9\xFE\xBF\x87"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #10 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #10 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0C\x0B\x0A\x09\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3228,7 +7160,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E",
           29,
           "\xDB\x11\x8C\xCE\xC1\xB8\x76\x1C\x87\x7C\xD8\x96\x3A\x67\xD6\xF3\xBB\xBC\x5C\xD0\x92\x99\xEB\x11\xF3\x12\xF2\x32\x37"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #11 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #11 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0D\x0C\x0B\x0A\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3236,7 +7168,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F",
           30,
           "\x7C\xC8\x3D\x8D\xC4\x91\x03\x52\x5B\x48\x3D\xC5\xCA\x7E\xA9\xAB\x81\x2B\x70\x56\x07\x9D\xAF\xFA\xDA\x16\xCC\xCF\x2C\x4E"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #12 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #12 */
           16, "\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF",
           13, "\x00\x00\x00\x0E\x0D\x0C\x0B\xA0\xA1\xA2\xA3\xA4\xA5",
           12, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B",
@@ -3244,7 +7176,7 @@ check_ccm_cipher (void)
           "\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20",
           31,
           "\x2C\xD3\x5B\x88\x20\xD2\x3E\x7A\xA3\x51\xB0\xE9\x2F\xC7\x93\x67\x23\x8B\x2C\xC7\x48\xCB\xB9\x4C\x29\x47\x79\x3D\x64\xAF\x75"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #13 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #13 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\xA9\x70\x11\x0E\x19\x27\xB1\x60\xB6\xA3\x1C\x1C",
           8, "\x6B\x7F\x46\x45\x07\xFA\xE4\x96",
@@ -3252,7 +7184,7 @@ check_ccm_cipher (void)
           "\xC6\xB5\xF3\xE6\xCA\x23\x11\xAE\xF7\x47\x2B\x20\x3E\x73\x5E\xA5\x61\xAD\xB1\x7D\x56\xC5\xA3",
           31,
           "\xA4\x35\xD7\x27\x34\x8D\xDD\x22\x90\x7F\x7E\xB8\xF5\xFD\xBB\x4D\x93\x9D\xA6\x52\x4D\xB4\xF6\x45\x58\xC0\x2D\x25\xB1\x27\xEE"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #14 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #14 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\x83\xCD\x8C\xE0\xCB\x42\xB1\x60\xB6\xA3\x1C\x1C",
           8, "\x98\x66\x05\xB4\x3D\xF1\x5D\xE7",
@@ -3260,7 +7192,7 @@ check_ccm_cipher (void)
           "\x01\xF6\xCE\x67\x64\xC5\x74\x48\x3B\xB0\x2E\x6B\xBF\x1E\x0A\xBD\x26\xA2\x25\x72\xB4\xD8\x0E\xE7",
           32,
           "\x8A\xE0\x52\x50\x8F\xBE\xCA\x93\x2E\x34\x6F\x05\xE0\xDC\x0D\xFB\xCF\x93\x9E\xAF\xFA\x3E\x58\x7C\x86\x7D\x6E\x1C\x48\x70\x38\x06"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #15 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #15 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\x5F\x54\x95\x0B\x18\xF2\xB1\x60\xB6\xA3\x1C\x1C",
           8, "\x48\xF2\xE7\xE1\xA7\x67\x1A\x51",
@@ -3268,7 +7200,7 @@ check_ccm_cipher (void)
           "\xCD\xF1\xD8\x40\x6F\xC2\xE9\x01\x49\x53\x89\x70\x05\xFB\xFB\x8B\xA5\x72\x76\xF9\x24\x04\x60\x8E\x08",
           33,
           "\x08\xB6\x7E\xE2\x1C\x8B\xF2\x6E\x47\x3E\x40\x85\x99\xE9\xC0\x83\x6D\x6A\xF0\xBB\x18\xDF\x55\x46\x6C\xA8\x08\x78\xA7\x90\x47\x6D\xE5"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #16 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #16 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\xEC\x60\x08\x63\x31\x9A\xB1\x60\xB6\xA3\x1C\x1C",
           12, "\xDE\x97\xDF\x3B\x8C\xBD\x6D\x8E\x50\x30\xDA\x4C",
@@ -3276,7 +7208,7 @@ check_ccm_cipher (void)
           "\xB0\x05\xDC\xFA\x0B\x59\x18\x14\x26\xA9\x61\x68\x5A\x99\x3D\x8C\x43\x18\x5B",
           27,
           "\x63\xB7\x8B\x49\x67\xB1\x9E\xDB\xB7\x33\xCD\x11\x14\xF6\x4E\xB2\x26\x08\x93\x68\xC3\x54\x82\x8D\x95\x0C\xC5"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #17 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #17 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\x60\xCF\xF1\xA3\x1E\xA1\xB1\x60\xB6\xA3\x1C\x1C",
           12, "\xA5\xEE\x93\xE4\x57\xDF\x05\x46\x6E\x78\x2D\xCF",
@@ -3284,7 +7216,7 @@ check_ccm_cipher (void)
           "\x2E\x20\x21\x12\x98\x10\x5F\x12\x9D\x5E\xD9\x5B\x93\xF7\x2D\x30\xB2\xFA\xCC\xD7",
           28,
           "\x0B\xC6\xBB\xE2\xA8\xB9\x09\xF4\x62\x9E\xE6\xDC\x14\x8D\xA4\x44\x10\xE1\x8A\xF4\x31\x47\x38\x32\x76\xF6\x6A\x9F"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #18 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #18 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\x0F\x85\xCD\x99\x5C\x97\xB1\x60\xB6\xA3\x1C\x1C",
           12, "\x24\xAA\x1B\xF9\xA5\xCD\x87\x61\x82\xA2\x50\x74",
@@ -3292,7 +7224,7 @@ check_ccm_cipher (void)
           "\x26\x45\x94\x1E\x75\x63\x2D\x34\x91\xAF\x0F\xC0\xC9\x87\x6C\x3B\xE4\xAA\x74\x68\xC9",
           29,
           "\x22\x2A\xD6\x32\xFA\x31\xD6\xAF\x97\x0C\x34\x5F\x7E\x77\xCA\x3B\xD0\xDC\x25\xB3\x40\xA1\xA3\xD3\x1F\x8D\x4B\x44\xB7"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #19 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #19 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\xC2\x9B\x2C\xAA\xC4\xCD\xB1\x60\xB6\xA3\x1C\x1C",
           8, "\x69\x19\x46\xB9\xCA\x07\xBE\x87",
@@ -3300,7 +7232,7 @@ check_ccm_cipher (void)
           "\x07\x01\x35\xA6\x43\x7C\x9D\xB1\x20\xCD\x61\xD8\xF6\xC3\x9C\x3E\xA1\x25\xFD\x95\xA0\xD2\x3D",
           33,
           "\x05\xB8\xE1\xB9\xC4\x9C\xFD\x56\xCF\x13\x0A\xA6\x25\x1D\xC2\xEC\xC0\x6C\xCC\x50\x8F\xE6\x97\xA0\x06\x6D\x57\xC8\x4B\xEC\x18\x27\x68"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #20 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #20 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\x2C\x6B\x75\x95\xEE\x62\xB1\x60\xB6\xA3\x1C\x1C",
           8, "\xD0\xC5\x4E\xCB\x84\x62\x7D\xC4",
@@ -3308,7 +7240,7 @@ check_ccm_cipher (void)
           "\xC8\xC0\x88\x0E\x6C\x63\x6E\x20\x09\x3D\xD6\x59\x42\x17\xD2\xE1\x88\x77\xDB\x26\x4E\x71\xA5\xCC",
           34,
           "\x54\xCE\xB9\x68\xDE\xE2\x36\x11\x57\x5E\xC0\x03\xDF\xAA\x1C\xD4\x88\x49\xBD\xF5\xAE\x2E\xDB\x6B\x7F\xA7\x75\xB1\x50\xED\x43\x83\xC5\xA9"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #21 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #21 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\xC5\x3C\xD4\xC2\xAA\x24\xB1\x60\xB6\xA3\x1C\x1C",
           8, "\xE2\x85\xE0\xE4\x80\x8C\xDA\x3D",
@@ -3316,7 +7248,7 @@ check_ccm_cipher (void)
           "\xF7\x5D\xAA\x07\x10\xC4\xE6\x42\x97\x79\x4D\xC2\xB7\xD2\xA2\x07\x57\xB1\xAA\x4E\x44\x80\x02\xFF\xAB",
           35,
           "\xB1\x40\x45\x46\xBF\x66\x72\x10\xCA\x28\xE3\x09\xB3\x9B\xD6\xCA\x7E\x9F\xC8\x28\x5F\xE6\x98\xD4\x3C\xD2\x0A\x02\xE0\xBD\xCA\xED\x20\x10\xD3"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #22 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #22 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\xBE\xE9\x26\x7F\xBA\xDC\xB1\x60\xB6\xA3\x1C\x1C",
           12, "\x6C\xAE\xF9\x94\x11\x41\x57\x0D\x7C\x81\x34\x05",
@@ -3324,7 +7256,7 @@ check_ccm_cipher (void)
           "\xC2\x38\x82\x2F\xAC\x5F\x98\xFF\x92\x94\x05\xB0\xAD\x12\x7A\x4E\x41\x85\x4E",
           29,
           "\x94\xC8\x95\x9C\x11\x56\x9A\x29\x78\x31\xA7\x21\x00\x58\x57\xAB\x61\xB8\x7A\x2D\xEA\x09\x36\xB6\xEB\x5F\x62\x5F\x5D"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #23 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #23 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\xDF\xA8\xB1\x24\x50\x07\xB1\x60\xB6\xA3\x1C\x1C",
           12, "\x36\xA5\x2C\xF1\x6B\x19\xA2\x03\x7A\xB7\x01\x1E",
@@ -3332,7 +7264,7 @@ check_ccm_cipher (void)
           "\x4D\xBF\x3E\x77\x4A\xD2\x45\xE5\xD5\x89\x1F\x9D\x1C\x32\xA0\xAE\x02\x2C\x85\xD7",
           30,
           "\x58\x69\xE3\xAA\xD2\x44\x7C\x74\xE0\xFC\x05\xF9\xA4\xEA\x74\x57\x7F\x4D\xE8\xCA\x89\x24\x76\x42\x96\xAD\x04\x11\x9C\xE7"},
-      { GCRY_CIPHER_CAMELLIA128, /* Packet Vector #24 */
+      { GCRY_CIPHER_CAMELLIA128, FLAG_NOFIPS, /* Packet Vector #24 */
           16, "\xD7\x5C\x27\x78\x07\x8C\xA9\x3D\x97\x1F\x96\xFD\xE7\x20\xF4\xCD",
           13, "\x00\x3B\x8F\xD8\xD3\xA9\x37\xB1\x60\xB6\xA3\x1C\x1C",
           12, "\xA4\xD4\x99\xF7\x84\x19\x72\x8C\x19\x17\x8B\x0C",
@@ -3340,6 +7272,7 @@ check_ccm_cipher (void)
           "\x9D\xC9\xED\xAE\x2F\xF5\xDF\x86\x36\xE8\xC6\xDE\x0E\xED\x55\xF7\x86\x7E\x33\x33\x7D",
           31,
           "\x4B\x19\x81\x56\x39\x3B\x0F\x77\x96\x08\x6A\xAF\xB4\x54\xF8\xC3\xF0\x34\xCC\xA9\x66\x94\x5F\x1F\xCE\xA7\xE1\x1B\xEE\x6A\x2F"}
+#endif /* USE_CAMELLIA */
     };
   static const int cut[] = { 0, 1, 8, 10, 16, 19, -1 };
   gcry_cipher_hd_t hde, hdd;
@@ -3354,11 +7287,22 @@ check_ccm_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
-      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    tv[i].algo);
+          if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+            {
+              if (verbose)
+                fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                         tv[i].algo);
+            }
+          else
+            fail ("cipher-ccm, gcry_cipher_test_algo failed: %s\n",
+                  gpg_strerror (err));
+          continue;
+        }
+      else if (in_fips_mode && (tv[i].flags & FLAG_NOFIPS))
+        {
+          fail ("cipher-ccm, gcry_cipher_test_algo unexpectedly worked\n");
           continue;
         }
 
@@ -3878,11 +7822,114 @@ do_check_ocb_cipher (int inplace)
       "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1"
       "A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD"
       "AC4F02AA"
+    },
+    { GCRY_CIPHER_AES, 12, "0F0E0D0C0B0A09080706050403020100",
+      "BBAA9988776655443322110D",
+      "000102030405060708090A0B0C0D0E0F1011121314151617"
+      "18191A1B1C1D1E1F2021222324252627",
+      /* test vector for checksumming */
+      "01000000000000000000000000000000"
+      "02000000000000000000000000000000"
+      "04000000000000000000000000000000"
+      "08000000000000000000000000000000"
+      "10000000000000000000000000000000"
+      "20000000000000000000000000000000"
+      "40000000000000000000000000000000"
+      "80000000000000000000000000000000"
+      "00010000000000000000000000000000"
+      "00020000000000000000000000000000"
+      "00040000000000000000000000000000"
+      "00080000000000000000000000000000"
+      "00100000000000000000000000000000"
+      "00200000000000000000000000000000"
+      "00400000000000000000000000000000"
+      "00800000000000000000000000000000"
+      "00000100000000000000000000000000"
+      "00000200000000000000000000000000"
+      "00000400000000000000000000000000"
+      "00000800000000000000000000000000"
+      "00001000000000000000000000000000"
+      "00002000000000000000000000000000"
+      "00004000000000000000000000000000"
+      "00008000000000000000000000000000"
+      "00000001000000000000000000000000"
+      "00000002000000000000000000000000"
+      "00000004000000000000000000000000"
+      "00000008000000000000000000000000"
+      "00000010000000000000000000000000"
+      "00000020000000000000000000000000"
+      "00000040000000000000000000000000"
+      "00000080000000000000000000000000"
+      "00000000010000000000000000000000"
+      "00000000020000000000000000000000"
+      "00000000040000000000000000000000"
+      "00000000080000000000000000000000"
+      "00000000100000000000000000000000"
+      "00000000200000000000000000000000"
+      "00000000400000000000000000000000"
+      "00000000800000000000000000000000"
+      "00000000000100000000000000000000"
+      "00000000000200000000000000000000"
+      "00000000000400000000000000000000"
+      "00000000000800000000000000000000"
+      "00000000001000000000000000000000"
+      "00000000002000000000000000000000"
+      "00000000004000000000000000000000"
+      "00000000008000000000000000000000",
+      "01105c6e36f6ac480f022c51e31ed702"
+      "90fda4b7b783194d4b4be8e4e1e2dff4"
+      "6a0804d1c5f9f808ea7933e31c063233"
+      "2bf65a22b20bb13cde3b80b3682ba965"
+      "b1207c58916f7856fa9968b410e50dee"
+      "98b35c071163d1b352b9bbccd09fde29"
+      "b850f40e71a8ae7d2e2d577f5ee39c46"
+      "7fa28130b50a123c29958e4665dda9a5"
+      "e0793997f8f19633a96392141d6e0e88"
+      "77850ed4364065d1d2f8746e2f1d5fd1"
+      "996cdde03215306503a30e41f58ef3c4"
+      "400365cfea4fa6381157c12a46598edf"
+      "18604854462ec66e3d3cf26d4723cb6a"
+      "9d801095048086a606fdb9192760889b"
+      "a8ce2e70e1b55a469137a9e2e6734565"
+      "283cb1e2c74f37e0854d03e33f8ba499"
+      "ef5d9af4edfce077c6280338f0a64286"
+      "2e6bc27ebd5a4c91b3778e22631251c8"
+      "c5bb75a10945597a9d6c274fc82d3338"
+      "b403a0a549d1375f26e71ef22bce0941"
+      "93ea87e2ed72fce0546148c351eec3be"
+      "867bb1b96070c377fff3c98e21562beb"
+      "475cfe28abcaaedf49981f6599b15140"
+      "ea6130d24407079f18ba9d4a8960b082"
+      "b39c57320e2e064f02fde88c23112146"
+      "1cac3655868aef584714826ee4f361fb"
+      "e6d692e1589cbb9dd3c74fa628df2a1f"
+      "3b0029b1d62b7e9978013ed3c793c1dd"
+      "1f184c8f7022a853cac40b74ac749aa3"
+      "f33f0d14732dfda0f2c3c20591bf1f5a"
+      "710ec0d0bca342baa5146068a78ff58c"
+      "66316312b7a98af35a0f4e92799b4047"
+      "f047ae61f25c28d232ce5c168cc745d6"
+      "6da13cb0f9e38a696635dba7a21571cf"
+      "cd64ec8cc33db7879f59a90d9edd00f6"
+      "a899e39ab36b9269a3ac04ebad9326bf"
+      "53cd9b400168a61714cd628a4056d236"
+      "bd8622c76daa54cb65f5db2fe03bafbe"
+      "0b23549ae31136f607293e8093a21934"
+      "74fd5e9c2451b4c8e0499e6ad34fafc8"
+      "ab77722a282f7f84b14ddebf7e696300"
+      "c1ef92d4a0263c6cca104530f996e272"
+      "f58992ff68d642b071a5848dc4acf2ae"
+      "28fb1f27ae0f297d5136a7a0a4a03e89"
+      "b588755b8217a1c62773790e69261269"
+      "19f45daf7b3ccf18e3fc590a9a0e172f"
+      "033ac4d13c3decc4c62d7de718ace802"
+      "140452dc850989f6762e3578bbb04be3"
+      "1a237c599c4649f4e586b2de"
     }
   };
   gpg_error_t err = 0;
   gcry_cipher_hd_t hde, hdd;
-  unsigned char out[MAX_DATA_LEN];
+  unsigned char out[1024];
   unsigned char tag[16];
   int tidx;
 
@@ -3914,6 +7961,16 @@ do_check_ocb_cipher (int inplace)
       assert (tv[tidx].taglen <= ciphlen);
       assert (tv[tidx].taglen <= sizeof tag);
 
+      /* Verify the FIPS indicator marks this as non-approved */
+      if (in_fips_mode)
+        {
+          err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                              tv[tidx].algo, GCRY_CIPHER_MODE_OCB);
+          if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
+            fail ("cipher-ocb, gcry_control did not fail as expected (tv %d): %s\n",
+                  tidx, gpg_strerror (err));
+        }
+
       err = gcry_cipher_open (&hde, tv[tidx].algo, GCRY_CIPHER_MODE_OCB, 0);
       if (!err)
         err = gcry_cipher_open (&hdd, tv[tidx].algo, GCRY_CIPHER_MODE_OCB, 0);
@@ -4015,7 +8072,7 @@ do_check_ocb_cipher (int inplace)
             }
           else
             {
-              err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN,
+              err = gcry_cipher_encrypt (hde, out, sizeof(out),
                                          plain, plainlen);
             }
         }
@@ -4072,7 +8129,7 @@ do_check_ocb_cipher (int inplace)
             }
           else
             {
-              unsigned char tmp[MAX_DATA_LEN];
+              unsigned char tmp[sizeof(out)];
 
               memcpy(tmp, out, plainlen);
               err = gcry_cipher_decrypt (hdd, out, plainlen, tmp, plainlen);
@@ -4162,8 +8219,42 @@ check_ocb_cipher_largebuf_split (int algo, int keylen, const char *tagexpect,
       return;
     }
 
-  for (i = 0; i < buflen; i++)
-    inbuf[i] = 'a';
+  for (i = 0; i < buflen; i += 16)
+    {
+      unsigned char hash[20];
+      unsigned char ctr[4];
+
+      ctr[0] = (i >> 0) & 0xff;
+      ctr[1] = (i >> 8) & 0xff;
+      ctr[2] = (i >> 16) & 0xff;
+      ctr[3] = (i >> 24) & 0xff;
+      gcry_md_hash_buffer (GCRY_MD_SHA1, hash, ctr, sizeof(ctr));
+      memcpy(inbuf + i, hash, 16);
+    }
+
+  if ((err = gcry_cipher_test_algo (algo)))
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                     algo);
+        }
+      else
+        fail ("cipher-ocb, gcry_cipher_test_algo failed (large, algo %d): %s\n",
+              algo, gpg_strerror (err));
+      goto out_free;
+    }
+
+  /* Verify the FIPS indicator marks this as non-approved */
+  if (in_fips_mode)
+    {
+      err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                          algo, GCRY_CIPHER_MODE_OCB);
+      if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
+        fail ("cipher-ocb, gcry_control did not fail as expected (large, algo %d): %s\n",
+              algo, gpg_strerror (err));
+    }
 
   err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0);
   if (!err)
@@ -4322,6 +8413,185 @@ out_free:
 
 
 static void
+check_ocb_cipher_checksum (int algo, int keylen)
+{
+  static const unsigned char key[32] =
+       "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
+       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
+  static const unsigned char nonce[12] =
+       "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x00\x01\x02\x03";
+  const size_t buflen = 128 * 16;
+  unsigned char *inbuf, *outbuf;
+  gpg_error_t err = 0;
+  gcry_cipher_hd_t hde, hde2, hdd;
+  unsigned char tag[16];
+  unsigned char tag2[16];
+  unsigned char tag3[16];
+  int i;
+
+  inbuf = xmalloc(buflen);
+  if (!inbuf)
+    {
+      fail ("out-of-memory\n");
+      return;
+    }
+  outbuf = xmalloc(buflen);
+  if (!inbuf)
+    {
+      fail ("out-of-memory\n");
+      xfree(inbuf);
+      return;
+    }
+
+  memset(inbuf, 0, buflen);
+  for (i = 0; i < 128; i += 16)
+    {
+      unsigned char *blk = inbuf + i;
+      int bit2set = i / 16;
+      int byteidx = bit2set / 8;
+      int bitpos = bit2set % 8;
+
+      blk[byteidx] |= 1 << bitpos;
+    }
+
+  if ((err = gcry_cipher_test_algo (algo)))
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                     algo);
+        }
+      else
+        fail ("cipher-ocb, gcry_cipher_test_algo failed (checksum, algo %d): %s\n",
+              algo, gpg_strerror (err));
+      goto out_free;
+    }
+
+  /* Verify the FIPS indicator marks this as non-approved */
+  if (in_fips_mode)
+    {
+      err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                          algo, GCRY_CIPHER_MODE_OCB);
+      if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
+        fail ("cipher-ocb, gcry_control did not fail as expected (checksum, algo %d): %s\n",
+              algo, gpg_strerror (err));
+    }
+
+  err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0);
+  if (!err)
+    err = gcry_cipher_open (&hde2, algo, GCRY_CIPHER_MODE_OCB, 0);
+  if (!err)
+    err = gcry_cipher_open (&hdd, algo, GCRY_CIPHER_MODE_OCB, 0);
+  if (err)
+    {
+      fail ("cipher-ocb, gcry_cipher_open failed (checksum, algo %d): %s\n",
+            algo, gpg_strerror (err));
+      goto out_free;
+    }
+
+  err = gcry_cipher_setkey (hde, key, keylen);
+  if (!err)
+    err = gcry_cipher_setkey (hde2, key, keylen);
+  if (!err)
+    err = gcry_cipher_setkey (hdd, key, keylen);
+  if (err)
+    {
+      fail ("cipher-ocb, gcry_cipher_setkey failed (checksum, algo %d): %s\n",
+           algo, gpg_strerror (err));
+      gcry_cipher_close (hde);
+      gcry_cipher_close (hde2);
+      gcry_cipher_close (hdd);
+      goto out_free;
+    }
+
+  err = gcry_cipher_setiv (hde, nonce, 12);
+  if (!err)
+    err = gcry_cipher_setiv (hde2, nonce, 12);
+  if (!err)
+    err = gcry_cipher_setiv (hdd, nonce, 12);
+  if (err)
+    {
+      fail ("cipher-ocb, gcry_cipher_setiv failed (checksum, algo %d): %s\n",
+           algo, gpg_strerror (err));
+      gcry_cipher_close (hde);
+      gcry_cipher_close (hde2);
+      gcry_cipher_close (hdd);
+      goto out_free;
+    }
+
+  err = gcry_cipher_final (hde);
+  if (!err)
+    {
+      err = gcry_cipher_encrypt (hde, outbuf, buflen, inbuf, buflen);
+    }
+  for (i = 0; i < buflen && !err; i += 16)
+    {
+      if (i + 16 == buflen)
+       err = gcry_cipher_final (hde2);
+      if (!err)
+       err = gcry_cipher_encrypt (hde2, outbuf + i, 16, inbuf + i, 16);
+    }
+  if (!err)
+    {
+      err = gcry_cipher_final (hdd);
+    }
+  if (!err)
+    {
+      err = gcry_cipher_decrypt (hdd, outbuf, buflen, outbuf, buflen);
+    }
+
+  if (err)
+    {
+      fail ("cipher-ocb, gcry_cipher_encrypt failed (checksum, algo %d): %s\n",
+           algo, gpg_strerror (err));
+      gcry_cipher_close (hde);
+      gcry_cipher_close (hde2);
+      gcry_cipher_close (hdd);
+      goto out_free;
+    }
+
+  /* Check that the tag matches. */
+  err = gcry_cipher_gettag (hde, tag, 16);
+  if (err)
+    {
+      fail ("cipher_ocb, gcry_cipher_gettag failed (checksum, algo %d): %s\n",
+           algo, gpg_strerror (err));
+    }
+  err = gcry_cipher_gettag (hde2, tag2, 16);
+  if (err)
+    {
+      fail ("cipher_ocb, gcry_cipher_gettag failed (checksum2, algo %d): %s\n",
+           algo, gpg_strerror (err));
+    }
+  err = gcry_cipher_gettag (hdd, tag3, 16);
+  if (err)
+    {
+      fail ("cipher_ocb, gcry_cipher_gettag failed (checksum3, algo %d): %s\n",
+           algo, gpg_strerror (err));
+    }
+  if (memcmp (tag, tag2, 16))
+    {
+      mismatch (tag, 16, tag2, 16);
+      fail ("cipher-ocb, encrypt tag mismatch (checksum, algo %d)\n", algo);
+    }
+  if (memcmp (tag, tag3, 16))
+    {
+      mismatch (tag, 16, tag3, 16);
+      fail ("cipher-ocb, decrypt tag mismatch (checksum, algo %d)\n", algo);
+    }
+
+  gcry_cipher_close (hde);
+  gcry_cipher_close (hde2);
+  gcry_cipher_close (hdd);
+
+out_free:
+  xfree(inbuf);
+  xfree(outbuf);
+}
+
+
+static void
 check_ocb_cipher_largebuf (int algo, int keylen, const char *tagexpect)
 {
   unsigned int split;
@@ -4330,6 +8600,8 @@ check_ocb_cipher_largebuf (int algo, int keylen, const char *tagexpect)
     {
       check_ocb_cipher_largebuf_split(algo, keylen, tagexpect, split);
     }
+
+  check_ocb_cipher_checksum(algo, keylen);
 }
 
 
@@ -4474,6 +8746,16 @@ check_ocb_cipher_splitaad (void)
       aad[2] = tv[tidx].aad2? hex2buffer (tv[tidx].aad2, aadlen+2) : NULL;
       aad[3] = tv[tidx].aad3? hex2buffer (tv[tidx].aad3, aadlen+3) : NULL;
 
+      /* Verify the FIPS indicator marks this as non-approved */
+      if (in_fips_mode)
+        {
+          err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                              GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OCB);
+          if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
+            fail ("cipher-ocb-splitaad, gcry_control did not fail as expected: %s\n",
+                  gpg_strerror (err));
+        }
+
       err = gcry_cipher_open (&hde, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OCB, 0);
       if (err)
         {
@@ -4575,35 +8857,35 @@ check_ocb_cipher (void)
 
   /* Check large buffer encryption/decryption. */
   check_ocb_cipher_largebuf(GCRY_CIPHER_AES, 16,
-                           "\xf5\xf3\x12\x7d\x58\x2d\x96\xe8"
-                           "\x33\xfd\x7a\x4f\x42\x60\x5d\x20");
+    "\x4a\x00\x7f\x8d\xbe\x38\x32\x48\xb2\x2f\x7f\x27\xd8\x15\x7f\xb0");
   check_ocb_cipher_largebuf(GCRY_CIPHER_AES256, 32,
-                           "\xfa\x26\xa5\xbf\xf6\x7d\x3a\x8d"
-                           "\xfe\x96\x67\xc9\xc8\x41\x03\x51");
+    "\xec\xc5\xe9\x2b\x24\x91\xba\x64\xbc\xe3\x62\xb6\x83\x20\xad\xbd");
+#if USE_CAMELLIA
   check_ocb_cipher_largebuf(GCRY_CIPHER_CAMELLIA128, 16,
-                           "\x28\x23\x38\x45\x2b\xfd\x42\x45"
-                           "\x43\x64\x7e\x67\x7f\xf4\x8b\xcd");
+    "\xd5\xbd\x76\xec\x75\x4a\xab\x6c\x13\xec\x87\x95\x11\xd4\xf0\x3d");
   check_ocb_cipher_largebuf(GCRY_CIPHER_CAMELLIA192, 24,
-                           "\xee\xca\xe5\x39\x27\x2d\x33\xe7"
-                           "\x79\x74\xb0\x1d\x37\x12\xd5\x6c");
+    "\xde\xdd\x6b\xbf\xce\x15\x01\x39\x7c\xc5\x69\x19\x72\xa2\x67\x23");
   check_ocb_cipher_largebuf(GCRY_CIPHER_CAMELLIA256, 32,
-                           "\x39\x39\xd0\x2d\x05\x68\x74\xee"
-                           "\x18\x6b\xea\x3d\x0b\xd3\x58\xae");
+    "\x0c\xf3\xd5\x82\x20\x73\xee\x0f\xbd\x6b\x32\x38\xf9\x10\xef\xe5");
+#endif /* USE_CAMELLIA */
+#if USE_TWOFISH
   check_ocb_cipher_largebuf(GCRY_CIPHER_TWOFISH, 16,
-                           "\x63\xe3\x0e\xb9\x11\x6f\x14\xba"
-                           "\x79\xe4\xa7\x9e\xad\x3c\x02\x0c");
+    "\x54\x87\x68\xb6\x17\xe6\xd7\xa6\x76\x0d\x7e\x9f\x57\x8b\xec\x88");
   check_ocb_cipher_largebuf(GCRY_CIPHER_TWOFISH, 32,
-                           "\xf6\xd4\xfe\x4e\x50\x85\x13\x59"
-                           "\x69\x0e\x4c\x67\x3e\xdd\x47\x90");
+    "\x0b\xc3\x93\x52\xfa\x97\x22\xe6\x88\x6e\x29\x4d\x77\x35\x48\x84");
+#endif /* USE_TWOFISH */
+#if USE_SERPENT
   check_ocb_cipher_largebuf(GCRY_CIPHER_SERPENT128, 16,
-                           "\x3c\xfb\x66\x14\x3c\xc8\x6c\x67"
-                           "\x26\xb8\x23\xeb\xaf\x43\x98\x69");
+    "\x7e\x49\x3b\xd6\xde\x6e\x9e\x53\x67\xcd\x00\xad\xc9\xd9\xa5\xbc");
   check_ocb_cipher_largebuf(GCRY_CIPHER_SERPENT192, 24,
-                           "\x5e\x62\x27\xc5\x32\xc3\x1d\xe6"
-                           "\x2e\x65\xe7\xd6\xfb\x05\xd7\xb2");
+    "\x1e\x33\x0e\x06\xc8\x27\x6a\x0b\x41\x5e\x93\xae\x39\xf4\x50\x12");
   check_ocb_cipher_largebuf(GCRY_CIPHER_SERPENT256, 32,
-                           "\xe7\x8b\xe6\xd4\x2f\x7a\x36\x4c"
-                           "\xba\xee\x20\xe2\x68\xf4\xcb\xcc");
+    "\x6b\x4c\x3f\x8f\x77\x75\xf2\x4d\xaf\xde\x2c\x5f\x1a\x80\xb8\x4d");
+#endif /* USE_SERPENT */
+#if USE_SM4
+  check_ocb_cipher_largebuf(GCRY_CIPHER_SM4, 16,
+    "\x3c\x32\x54\x5d\xc5\x17\xa1\x16\x3f\x8e\xc7\x1d\x8d\x8b\x2d\xb0");
+#endif /* USE_SM4 */
 
   /* Check that the AAD data is correctly buffered.  */
   check_ocb_cipher_splitaad ();
@@ -4947,7 +9229,7 @@ check_xts_cipher (void)
 
 
 static void
-check_gost28147_cipher (void)
+check_gost28147_cipher_basic (enum gcry_cipher_algos algo)
 {
 #if USE_GOST28147
   static const struct {
@@ -5022,9 +9304,28 @@ check_gost28147_cipher (void)
   int i, keylen;
   gcry_error_t err = 0;
 
-  if (verbose)
-    fprintf (stderr, "  Starting GOST28147 cipher checks.\n");
-  keylen = gcry_cipher_get_algo_keylen(GCRY_CIPHER_GOST28147);
+  if (verbose)
+    fprintf (stderr, "  Starting GOST28147 cipher checks.\n");
+
+  if ((err = gcry_cipher_test_algo (algo)))
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                     algo);
+        }
+      else
+        fail ("gost28147, gcry_cipher_test_algo failed: %s\n", gpg_strerror (err));
+      return;
+    }
+  else if (in_fips_mode)
+    {
+      fail ("gost28147, gcry_cipher_test_algo did not fail as expcected\n");
+      return;
+    }
+
+  keylen = gcry_cipher_get_algo_keylen(algo);
   if (!keylen)
     {
       fail ("gost28147, gcry_cipher_get_algo_keylen failed\n");
@@ -5033,10 +9334,10 @@ check_gost28147_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
-      err = gcry_cipher_open (&hde, GCRY_CIPHER_GOST28147,
+      err = gcry_cipher_open (&hde, algo,
                               GCRY_CIPHER_MODE_ECB, 0);
       if (!err)
-        err = gcry_cipher_open (&hdd, GCRY_CIPHER_GOST28147,
+        err = gcry_cipher_open (&hdd, algo,
                                 GCRY_CIPHER_MODE_ECB, 0);
       if (err)
         {
@@ -5113,6 +9414,12 @@ check_gost28147_cipher (void)
 #endif
 }
 
+static void
+check_gost28147_cipher (void)
+{
+       check_gost28147_cipher_basic (GCRY_CIPHER_GOST28147);
+       check_gost28147_cipher_basic (GCRY_CIPHER_GOST28147_MESH);
+}
 
 static void
 check_stream_cipher (void)
@@ -5127,12 +9434,12 @@ check_stream_cipher (void)
     const char *iv;
     struct data
     {
-      int inlen;
+      unsigned int inlen;
       const char *plaintext;
       const char *out;
     } data[MAX_DATA_LEN];
   } tv[] = {
-#ifdef USE_SALSA20
+#if USE_SALSA20
     {
       "Salsa20 128 bit, test 1",
       GCRY_CIPHER_SALSA20, 16, 8,
@@ -5304,7 +9611,7 @@ check_stream_cipher (void)
       }
     },
 #endif /*USE_SALSA20*/
-#ifdef USE_CHACHA20
+#if USE_CHACHA20
     /* From draft-strombergson-chacha-test-vectors-01 */
     {
       "ChaCha20 128 bit, TC1",
@@ -5640,13 +9947,24 @@ check_stream_cipher (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
-      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    tv[i].algo);
+          if (in_fips_mode)
+            {
+              if (verbose)
+                fprintf (stderr, "    algorithm %d not available in fips mode\n",
+                         tv[i].algo);
+            }
+          else
+            fail ("stream, gcry_cipher_test_algo: failed: %s\n", gpg_strerror (err));
           continue;
         }
+      else if (in_fips_mode)
+        {
+          fail ("stream, gcry_cipher_test_algo: did not fail as expected\n");
+          continue;
+        }
+
       if (verbose)
         fprintf (stderr, "    checking stream mode for %s [%i] (%s)\n",
                 gcry_cipher_algo_name (tv[i].algo), tv[i].algo, tv[i].name);
@@ -5802,7 +10120,7 @@ check_stream_cipher_large_block (void)
       const char *result;
     } data[MAX_DATA_LEN];
   } tv[] = {
-#ifdef USE_SALSA20
+#if USE_SALSA20
     {
       "Salsa20 256 bit, ecrypt verified, set 6, vector 0",
       GCRY_CIPHER_SALSA20, 32, 8,
@@ -6091,11 +10409,21 @@ check_stream_cipher_large_block (void)
 
   for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++)
     {
-      if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (tv[i].algo)))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    tv[i].algo);
+          if (in_fips_mode)
+            {
+              if (verbose)
+                fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                         tv[i].algo);
+            }
+          else
+            fail ("stream, gcry_cipher_test_algo: failed: %s\n", gpg_strerror (err));
+          continue;
+        }
+      else if (in_fips_mode)
+        {
+          fail ("stream, gcry_cipher_test_algo: did not fail as expected\n");
           continue;
         }
 
@@ -6362,7 +10690,28 @@ check_bulk_cipher_modes (void)
 /*[16]*/
       { 0x8e, 0xbc, 0xa5, 0x21, 0x0a, 0x4b, 0x53, 0x14, 0x79, 0x81,
         0x25, 0xad, 0x24, 0x45, 0x98, 0xbd, 0x9f, 0x27, 0x5f, 0x01 }
-    }
+    },
+    { GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OFB,
+      "abcdefghijklmnop", 16,
+      "1234567890123456", 16,
+/*[17]*/
+      { 0x65, 0xfe, 0xde, 0x48, 0xd0, 0xa1, 0xa6, 0xf9, 0x24, 0x6b,
+        0x52, 0x5f, 0x21, 0x8a, 0x6f, 0xc7, 0x70, 0x3b, 0xd8, 0x4a }
+    },
+    { GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_OFB,
+      "abcdefghijklmnopABCDEFG", 24,
+      "1234567890123456", 16,
+/*[18]*/
+      { 0x59, 0x5b, 0x02, 0xa2, 0x88, 0xc0, 0xbe, 0x94, 0x43, 0xaa,
+        0x39, 0xf6, 0xbd, 0xcc, 0x83, 0x99, 0xee, 0x00, 0xa1, 0x91 }
+    },
+    { GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB,
+      "abcdefghijklmnopABCDEFGHIJKLMNOP", 32,
+      "1234567890123456", 16,
+/*[19]*/
+      { 0x38, 0x8c, 0xe1, 0xe2, 0xbe, 0x67, 0x60, 0xe8, 0xeb, 0xce,
+        0xd0, 0xc6, 0xaa, 0xd6, 0xf6, 0x26, 0x15, 0x56, 0xd0, 0x2b }
+    },
   };
   gcry_cipher_hd_t hde = NULL;
   gcry_cipher_hd_t hdd = NULL;
@@ -6389,6 +10738,17 @@ check_bulk_cipher_modes (void)
         fprintf (stderr, "    checking bulk encryption for %s [%i], mode %d\n",
                 gcry_cipher_algo_name (tv[i].algo),
                 tv[i].algo, tv[i].mode);
+
+      /* Verify the FIPS indicator marks approved cipher/modes combinations */
+      if (in_fips_mode)
+        {
+          err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER,
+                              tv[i].algo, tv[i].mode);
+          if (gpg_err_code (err) != GPG_ERR_NO_ERROR)
+            fail ("gcry_control unexpectedly failed for algo = %s, mode = %d : %s\n",
+                 gcry_cipher_algo_name (tv[i].algo), tv[i].mode, gpg_strerror (err));
+        }
+
       err = gcry_cipher_open (&hde, tv[i].algo, tv[i].mode, 0);
       if (!err)
         err = gcry_cipher_open (&hdd, tv[i].algo, tv[i].mode, 0);
@@ -6405,7 +10765,9 @@ check_bulk_cipher_modes (void)
           goto leave;
         }
 
+      clutter_vector_registers();
       err = gcry_cipher_setkey (hde, tv[i].key, tv[i].keylen);
+      clutter_vector_registers();
       if (!err)
         err = gcry_cipher_setkey (hdd, tv[i].key, tv[i].keylen);
       if (err)
@@ -6421,7 +10783,9 @@ check_bulk_cipher_modes (void)
           goto leave;
         }
 
+      clutter_vector_registers();
       err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen);
+      clutter_vector_registers();
       if (!err)
         err = gcry_cipher_setiv (hdd, tv[i].iv,  tv[i].ivlen);
       if (err)
@@ -6434,6 +10798,7 @@ check_bulk_cipher_modes (void)
       for (j=0; j < buflen; j++)
         buffer[j] = ((j & 0xff) ^ ((j >> 8) & 0xff));
 
+      clutter_vector_registers();
       err = gcry_cipher_encrypt (hde, outbuf, buflen, buffer, buflen);
       if (err)
         {
@@ -6455,6 +10820,7 @@ check_bulk_cipher_modes (void)
         fail ("encrypt mismatch (algo %d, mode %d)\n",
               tv[i].algo, tv[i].mode);
 
+      clutter_vector_registers();
       err = gcry_cipher_decrypt (hdd, outbuf, buflen, NULL, 0);
       if (err)
         {
@@ -6492,8 +10858,11 @@ get_algo_mode_blklen (int algo, int mode)
     case GCRY_CIPHER_MODE_STREAM:
     case GCRY_CIPHER_MODE_OFB:
     case GCRY_CIPHER_MODE_CTR:
+    case GCRY_CIPHER_MODE_CFB:
+    case GCRY_CIPHER_MODE_CFB8:
     case GCRY_CIPHER_MODE_CCM:
     case GCRY_CIPHER_MODE_GCM:
+    case GCRY_CIPHER_MODE_EAX:
     case GCRY_CIPHER_MODE_POLY1305:
       return 1;
     }
@@ -6502,6 +10871,23 @@ get_algo_mode_blklen (int algo, int mode)
 }
 
 
+static unsigned int
+get_algo_mode_taglen (int algo, int mode)
+{
+  switch (mode)
+    {
+    case GCRY_CIPHER_MODE_CCM:
+    case GCRY_CIPHER_MODE_GCM:
+    case GCRY_CIPHER_MODE_POLY1305:
+      return 16;
+    case GCRY_CIPHER_MODE_EAX:
+      return gcry_cipher_get_algo_blklen(algo);
+    }
+
+  return 0;
+}
+
+
 static int
 check_one_cipher_core_reset (gcry_cipher_hd_t hd, int algo, int mode, int pass,
                              int nplain)
@@ -6514,6 +10900,7 @@ check_one_cipher_core_reset (gcry_cipher_hd_t hd, int algo, int mode, int pass,
 
   if (mode == GCRY_CIPHER_MODE_OCB || mode == GCRY_CIPHER_MODE_CCM)
     {
+      clutter_vector_registers();
       err = gcry_cipher_setiv (hd, iv, sizeof(iv));
       if (err)
         {
@@ -6555,27 +10942,40 @@ check_one_cipher_core (int algo, int mode, int flags,
                        int bufshift, int pass)
 {
   gcry_cipher_hd_t hd;
-  unsigned char in_buffer[1040+1], out_buffer[1040+1];
-  unsigned char enc_result[1040];
+  unsigned char *in_buffer, *out_buffer;
+  unsigned char *enc_result;
+  unsigned char tag_result[16];
+  unsigned char tag[16];
   unsigned char *in, *out;
   int keylen;
   gcry_error_t err = 0;
   unsigned int blklen;
   unsigned int piecelen;
   unsigned int pos;
+  unsigned int taglen;
+
+  in_buffer = malloc (nplain + 1);
+  out_buffer = malloc (nplain + 1);
+  enc_result = malloc (nplain);
+  if (!in_buffer || !out_buffer || !enc_result)
+    {
+      fail ("pass %d, algo %d, mode %d, malloc failed\n",
+           pass, algo, mode);
+      goto err_out_free;
+    }
 
   blklen = get_algo_mode_blklen(algo, mode);
+  taglen = get_algo_mode_taglen(algo, mode);
 
   assert (nkey == 64);
-  assert (nplain == 1040);
-  assert (sizeof(in_buffer) == nplain + 1);
-  assert (sizeof(out_buffer) == sizeof(in_buffer));
+  assert (nplain > 0);
+  assert ((nplain % 16) == 0);
   assert (blklen > 0);
 
   if ((mode == GCRY_CIPHER_MODE_CBC && (flags & GCRY_CIPHER_CBC_CTS)) ||
       mode == GCRY_CIPHER_MODE_XTS)
     {
-      /* Input cannot be split in to multiple operations with CTS . */
+      /* Input cannot be split in to multiple operations with CTS. */
       blklen = nplain;
     }
 
@@ -6605,13 +11005,13 @@ check_one_cipher_core (int algo, int mode, int flags,
     {
       fail ("pass %d, algo %d, mode %d, gcry_cipher_get_algo_keylen failed\n",
            pass, algo, mode);
-      return -1;
+      goto err_out_free;
     }
 
   if (keylen < 40 / 8 || keylen > 32)
     {
       fail ("pass %d, algo %d, mode %d, keylength problem (%d)\n", pass, algo, mode, keylen);
-      return -1;
+      goto err_out_free;
     }
 
   if (mode == GCRY_CIPHER_MODE_XTS)
@@ -6623,43 +11023,82 @@ check_one_cipher_core (int algo, int mode, int flags,
   if (err)
     {
       fail ("pass %d, algo %d, mode %d, gcry_cipher_open failed: %s\n",
-           pass, algo, mode, gpg_strerror (err));
-      return -1;
+            pass, algo, mode, gpg_strerror (err));
+      goto err_out_free;
     }
 
+  clutter_vector_registers();
   err = gcry_cipher_setkey (hd, key, keylen);
   if (err)
     {
       fail ("pass %d, algo %d, mode %d, gcry_cipher_setkey failed: %s\n",
            pass, algo, mode, gpg_strerror (err));
       gcry_cipher_close (hd);
-      return -1;
+      goto err_out_free;
     }
 
   if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
-    return -1;
+    goto err_out_free;
 
+  clutter_vector_registers();
   err = gcry_cipher_encrypt (hd, out, nplain, plain, nplain);
+  if (in_fips_mode && mode == GCRY_CIPHER_MODE_GCM)
+    {
+      if (!err)
+        fail ("pass %d, algo %d, mode %d, gcry_cipher_encrypt is expected to "
+              "fail in FIPS mode: %s\n", pass, algo, mode, gpg_strerror (err));
+      gcry_cipher_close (hd);
+      goto err_out_free;
+    }
   if (err)
     {
       fail ("pass %d, algo %d, mode %d, gcry_cipher_encrypt failed: %s\n",
            pass, algo, mode, gpg_strerror (err));
       gcry_cipher_close (hd);
-      return -1;
+      goto err_out_free;
+    }
+
+  if (taglen > 0)
+    {
+      clutter_vector_registers();
+      err = gcry_cipher_gettag (hd, tag, taglen);
+      if (err)
+       {
+         fail ("pass %d, algo %d, mode %d, gcry_cipher_gettag failed: %s\n",
+               pass, algo, mode, gpg_strerror (err));
+         gcry_cipher_close (hd);
+         goto err_out_free;
+       }
+
+      memcpy(tag_result, tag, taglen);
     }
 
   memcpy (enc_result, out, nplain);
 
   if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
-    return -1;
+    goto err_out_free;
 
+  clutter_vector_registers();
   err = gcry_cipher_decrypt (hd, in, nplain, out, nplain);
   if (err)
     {
       fail ("pass %d, algo %d, mode %d, gcry_cipher_decrypt failed: %s\n",
            pass, algo, mode, gpg_strerror (err));
       gcry_cipher_close (hd);
-      return -1;
+      goto err_out_free;
+    }
+
+  if (taglen > 0)
+    {
+      clutter_vector_registers();
+      err = gcry_cipher_checktag (hd, tag_result, taglen);
+      if (err)
+       {
+         fail ("pass %d, algo %d, mode %d, gcry_cipher_checktag failed: %s\n",
+               pass, algo, mode, gpg_strerror (err));
+         gcry_cipher_close (hd);
+         goto err_out_free;
+       }
     }
 
   if (memcmp (plain, in, nplain))
@@ -6668,9 +11107,10 @@ check_one_cipher_core (int algo, int mode, int flags,
 
   /* Again, using in-place encryption.  */
   if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
-    return -1;
+    goto err_out_free;
 
   memcpy (out, plain, nplain);
+  clutter_vector_registers();
   err = gcry_cipher_encrypt (hd, out, nplain, NULL, 0);
   if (err)
     {
@@ -6678,7 +11118,24 @@ check_one_cipher_core (int algo, int mode, int flags,
             " %s\n",
            pass, algo, mode, gpg_strerror (err));
       gcry_cipher_close (hd);
-      return -1;
+      goto err_out_free;
+    }
+
+  if (taglen > 0)
+    {
+      err = gcry_cipher_gettag (hd, tag, taglen);
+      if (err)
+       {
+         fail ("pass %d, algo %d, mode %d, in-place, "
+               "gcry_cipher_gettag failed: %s\n",
+               pass, algo, mode, gpg_strerror (err));
+         gcry_cipher_close (hd);
+         goto err_out_free;
+       }
+
+      if (memcmp (tag_result, tag, taglen))
+       fail ("pass %d, algo %d, mode %d, in-place, tag mismatch\n",
+             pass, algo, mode);
     }
 
   if (memcmp (enc_result, out, nplain))
@@ -6686,8 +11143,9 @@ check_one_cipher_core (int algo, int mode, int flags,
           pass, algo, mode);
 
   if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
-    return -1;
+    goto err_out_free;
 
+  clutter_vector_registers();
   err = gcry_cipher_decrypt (hd, out, nplain, NULL, 0);
   if (err)
     {
@@ -6695,7 +11153,21 @@ check_one_cipher_core (int algo, int mode, int flags,
             " %s\n",
            pass, algo, mode, gpg_strerror (err));
       gcry_cipher_close (hd);
-      return -1;
+      goto err_out_free;
+    }
+
+  if (taglen > 0)
+    {
+      clutter_vector_registers();
+      err = gcry_cipher_checktag (hd, tag_result, taglen);
+      if (err)
+       {
+         fail ("pass %d, algo %d, mode %d, in-place, "
+               "gcry_cipher_checktag failed: %s\n",
+               pass, algo, mode, gpg_strerror (err));
+         gcry_cipher_close (hd);
+         goto err_out_free;
+       }
     }
 
   if (memcmp (plain, out, nplain))
@@ -6704,7 +11176,7 @@ check_one_cipher_core (int algo, int mode, int flags,
 
   /* Again, splitting encryption in multiple operations. */
   if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
-    return -1;
+    goto err_out_free;
 
   piecelen = blklen;
   pos = 0;
@@ -6713,6 +11185,7 @@ check_one_cipher_core (int algo, int mode, int flags,
       if (piecelen > nplain - pos)
         piecelen = nplain - pos;
 
+      clutter_vector_registers();
       err = gcry_cipher_encrypt (hd, out + pos, piecelen, plain + pos,
                                  piecelen);
       if (err)
@@ -6721,19 +11194,37 @@ check_one_cipher_core (int algo, int mode, int flags,
                 "piecelen: %d), gcry_cipher_encrypt failed: %s\n",
                 pass, algo, mode, pos, piecelen, gpg_strerror (err));
           gcry_cipher_close (hd);
-          return -1;
+          goto err_out_free;
         }
 
       pos += piecelen;
       piecelen = piecelen * 2 - ((piecelen != blklen) ? blklen : 0);
     }
 
+  if (taglen > 0)
+    {
+      clutter_vector_registers();
+      err = gcry_cipher_gettag (hd, tag, taglen);
+      if (err)
+       {
+         fail ("pass %d, algo %d, mode %d, split-buffer (pos: %d, "
+                "piecelen: %d), gcry_cipher_gettag failed: %s\n",
+               pass, algo, mode, pos, piecelen, gpg_strerror (err));
+         gcry_cipher_close (hd);
+         goto err_out_free;
+       }
+
+      if (memcmp (tag_result, tag, taglen))
+       fail ("pass %d, algo %d, mode %d, in-place, tag mismatch\n",
+             pass, algo, mode);
+    }
+
   if (memcmp (enc_result, out, nplain))
     fail ("pass %d, algo %d, mode %d, split-buffer, encrypt mismatch\n",
           pass, algo, mode);
 
   if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
-    return -1;
+    goto err_out_free;
 
   piecelen = blklen;
   pos = 0;
@@ -6742,6 +11233,7 @@ check_one_cipher_core (int algo, int mode, int flags,
       if (piecelen > nplain - pos)
         piecelen = nplain - pos;
 
+      clutter_vector_registers();
       err = gcry_cipher_decrypt (hd, in + pos, piecelen, out + pos, piecelen);
       if (err)
         {
@@ -6749,13 +11241,27 @@ check_one_cipher_core (int algo, int mode, int flags,
                 "piecelen: %d), gcry_cipher_decrypt failed: %s\n",
                 pass, algo, mode, pos, piecelen, gpg_strerror (err));
           gcry_cipher_close (hd);
-          return -1;
+          goto err_out_free;
         }
 
       pos += piecelen;
       piecelen = piecelen * 2 - ((piecelen != blklen) ? blklen : 0);
     }
 
+  if (taglen > 0)
+    {
+      clutter_vector_registers();
+      err = gcry_cipher_checktag (hd, tag_result, taglen);
+      if (err)
+       {
+         fail ("pass %d, algo %d, mode %d, split-buffer (pos: %d, "
+                "piecelen: %d), gcry_cipher_checktag failed: %s\n",
+               pass, algo, mode, pos, piecelen, gpg_strerror (err));
+         gcry_cipher_close (hd);
+         goto err_out_free;
+       }
+    }
+
   if (memcmp (plain, in, nplain))
     fail ("pass %d, algo %d, mode %d, split-buffer, encrypt-decrypt mismatch\n",
           pass, algo, mode);
@@ -6763,7 +11269,7 @@ check_one_cipher_core (int algo, int mode, int flags,
   /* Again, using in-place encryption and splitting encryption in multiple
    * operations. */
   if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
-    return -1;
+    goto err_out_free;
 
   piecelen = blklen;
   pos = 0;
@@ -6773,6 +11279,7 @@ check_one_cipher_core (int algo, int mode, int flags,
         piecelen = nplain - pos;
 
       memcpy (out + pos, plain + pos, piecelen);
+      clutter_vector_registers();
       err = gcry_cipher_encrypt (hd, out + pos, piecelen, NULL, 0);
       if (err)
         {
@@ -6780,7 +11287,7 @@ check_one_cipher_core (int algo, int mode, int flags,
                 "piecelen: %d), gcry_cipher_encrypt failed: %s\n",
                 pass, algo, mode, pos, piecelen, gpg_strerror (err));
           gcry_cipher_close (hd);
-          return -1;
+          goto err_out_free;
         }
 
       pos += piecelen;
@@ -6792,7 +11299,7 @@ check_one_cipher_core (int algo, int mode, int flags,
           pass, algo, mode);
 
   if (check_one_cipher_core_reset (hd, algo, mode, pass, nplain) < 0)
-    return -1;
+    goto err_out_free;
 
   piecelen = blklen;
   pos = 0;
@@ -6801,6 +11308,7 @@ check_one_cipher_core (int algo, int mode, int flags,
       if (piecelen > nplain - pos)
         piecelen = nplain - pos;
 
+      clutter_vector_registers();
       err = gcry_cipher_decrypt (hd, out + pos, piecelen, NULL, 0);
       if (err)
         {
@@ -6808,7 +11316,7 @@ check_one_cipher_core (int algo, int mode, int flags,
                 "piecelen: %d), gcry_cipher_decrypt failed: %s\n",
                 pass, algo, mode, pos, piecelen, gpg_strerror (err));
           gcry_cipher_close (hd);
-          return -1;
+          goto err_out_free;
         }
 
       pos += piecelen;
@@ -6822,25 +11330,247 @@ check_one_cipher_core (int algo, int mode, int flags,
 
   gcry_cipher_close (hd);
 
+  free (enc_result);
+  free (out_buffer);
+  free (in_buffer);
+  return 0;
+
+err_out_free:
+  free (enc_result);
+  free (out_buffer);
+  free (in_buffer);
+  return -1;
+}
+
+
+
+static int
+check_one_cipher_ctr_reset (gcry_cipher_hd_t hd, int algo, int mode,
+                           u32 ctr_high_bits, int be_ctr,
+                           int pass)
+{
+  unsigned char iv[16] = { 0 };
+  unsigned char swap;
+  unsigned int ivlen;
+  u32 ctr_low_bits;
+  int err;
+  int i;
+
+  /* This should be largest parallel block processing count in any
+   * implementation negated. Currently for CTR this is 32 and, for
+   * ChaCha20, count is 8. */
+  ctr_low_bits = (mode == GCRY_CIPHER_MODE_CTR) ? -32 : -8;
+
+  gcry_cipher_reset (hd);
+
+  if (mode == GCRY_CIPHER_MODE_CTR)
+    ivlen = get_algo_mode_blklen(algo, GCRY_CIPHER_MODE_ECB);
+  else
+    ivlen = 16;
+
+  /* Little-endian fill. */
+  for (i = 0; i < 4; i++)
+    iv[i + 0] = (ctr_low_bits >> (i * 8)) & 0xff;
+  for (i = 0; i < 4; i++)
+    iv[i + 4] = (ctr_high_bits >> (i * 8)) & 0xff;
+
+  if (be_ctr)
+    {
+      /* Swap to big-endian. */
+      for (i = 0; i < ivlen / 2; i++)
+       {
+         swap = iv[i];
+         iv[i] = iv[ivlen - (i + 1)];
+         iv[ivlen - (i + 1)] = swap;
+       }
+    }
+
+  clutter_vector_registers();
+  if (mode == GCRY_CIPHER_MODE_CTR)
+    err = gcry_cipher_setctr (hd, iv, ivlen);
+  else
+    err = gcry_cipher_setiv (hd, iv, ivlen);
+
+  if (err)
+    {
+      fail ("pass %d, algo %d, mode %d, gcry_cipher_setiv failed: %s\n",
+           pass, algo, mode, gpg_strerror (err));
+      gcry_cipher_close (hd);
+      return -1;
+    }
+
   return 0;
 }
 
+static int
+check_one_cipher_ctr_overflow (int algo, int mode, int flags,
+                              const char *key, size_t nkey,
+                              const unsigned char *plain, size_t nplain,
+                              unsigned long ctr_high_bits, int be_ctr,
+                              int pass)
+{
+  gcry_cipher_hd_t hd;
+  unsigned char *out;
+  unsigned char *enc_result;
+  int keylen;
+  gcry_error_t err = 0;
+  unsigned int firstlen;
+  unsigned int leftlen;
+  unsigned int blklen;
+  unsigned int pos;
+  unsigned int i;
+
+  out = malloc (nplain);
+  enc_result = malloc (nplain);
+  if (!out || !enc_result)
+    {
+      fail ("pass %d, algo %d, mode %d, malloc failed\n",
+           pass, algo, mode);
+      goto err_out_free;
+    }
+
+  assert (nkey == 64);
+  assert (nplain > 0);
+  assert ((nplain % 16) == 0);
+
+  keylen = gcry_cipher_get_algo_keylen (algo);
+  if (!keylen)
+    {
+      fail ("pass %d, algo %d, mode %d, gcry_cipher_get_algo_keylen failed\n",
+           pass, algo, mode);
+      goto err_out_free;
+    }
+
+  if (keylen < 40 / 8 || keylen > 32)
+    {
+      fail ("pass %d, algo %d, mode %d, keylength problem (%d)\n",
+           pass, algo, mode, keylen);
+      goto err_out_free;
+    }
+
+  err = gcry_cipher_open (&hd, algo, mode, flags);
+  if (err)
+    {
+      fail ("pass %d, algo %d, mode %d, gcry_cipher_open failed: %s\n",
+           pass, algo, mode, gpg_strerror (err));
+      goto err_out_free;
+    }
+
+  clutter_vector_registers();
+  err = gcry_cipher_setkey (hd, key, keylen);
+  if (err)
+    {
+      fail ("pass %d, algo %d, mode %d, gcry_cipher_setkey failed: %s\n",
+           pass, algo, mode, gpg_strerror (err));
+      gcry_cipher_close (hd);
+      goto err_out_free;
+    }
+
+  if (check_one_cipher_ctr_reset (hd, algo, mode, ctr_high_bits, be_ctr,
+                                 pass) < 0)
+    goto err_out_free;
+
+  /* Non-bulk processing. */
+  for (i = 0; i < nplain; i += 16)
+    {
+      clutter_vector_registers();
+      err = gcry_cipher_encrypt (hd, out + i, 16, plain + i, 16);
+      if (err)
+       {
+         fail ("pass %d, algo %d, mode %d, gcry_cipher_encrypt failed: %s\n",
+               pass, algo, mode, gpg_strerror (err));
+         gcry_cipher_close (hd);
+         goto err_out_free;
+       }
+    }
+
+  memcpy (enc_result, out, nplain);
+
+  /* Test with different bulk processing sizes. */
+  for (blklen = 2 * 16; blklen <= 32 * 16; blklen *= 2)
+    {
+      /* Move bulk processing start offset, test at different spots to
+       * test bulk counter calculation throughly. */
+      for (firstlen = 16; firstlen < 8 * 64; firstlen += 16)
+       {
+         if (check_one_cipher_ctr_reset (hd, algo, mode, ctr_high_bits, be_ctr,
+                                         pass) < 0)
+           goto err_out_free;
+
+         clutter_vector_registers();
+         err = gcry_cipher_encrypt (hd, out, firstlen, plain, firstlen);
+         if (err)
+           {
+             fail ("pass %d, algo %d, mode %d, gcry_cipher_encrypt "
+                   "failed: %s\n", pass, algo, mode, gpg_strerror (err));
+             gcry_cipher_close (hd);
+             goto err_out_free;
+           }
+
+         leftlen = nplain - firstlen;
+         pos = firstlen;
+         while (leftlen)
+           {
+             unsigned int currlen = leftlen > blklen ? blklen : leftlen;
+
+             clutter_vector_registers();
+             err = gcry_cipher_encrypt (hd, out + pos, currlen, plain + pos,
+                                        currlen);
+             if (err)
+               {
+                 fail ("pass %d, algo %d, mode %d, block len %d, first len %d,"
+                       "gcry_cipher_encrypt failed: %s\n", pass, algo, mode,
+                       blklen, firstlen, gpg_strerror (err));
+                 gcry_cipher_close (hd);
+                 goto err_out_free;
+               }
+
+             pos += currlen;
+             leftlen -= currlen;
+           }
+
+         if (memcmp (enc_result, out, nplain))
+           fail ("pass %d, algo %d, mode %d, block len %d, first len %d, "
+                 "encrypt mismatch\n", pass, algo, mode, blklen, firstlen);
+       }
+    }
+
+  gcry_cipher_close (hd);
+
+  free (enc_result);
+  free (out);
+  return 0;
+
+err_out_free:
+  free (enc_result);
+  free (out);
+  return -1;
+}
 
 
 static void
 check_one_cipher (int algo, int mode, int flags)
 {
+  size_t medium_buffer_size = 2048 - 16;
+  size_t large_buffer_size = 64 * 1024 + 1024 - 16;
   char key[64+1];
-  unsigned char plain[1040+1];
+  unsigned char *plain;
   int bufshift, i;
 
-  for (bufshift=0; bufshift < 4; bufshift++)
+  plain = malloc (large_buffer_size + 1);
+  if (!plain)
+    {
+      fail ("pass %d, algo %d, mode %d, malloc failed\n", -1, algo, mode);
+      return;
+    }
+
+  for (bufshift = 0; bufshift < 4; bufshift++)
     {
       /* Pass 0: Standard test.  */
       memcpy (key, "0123456789abcdef.,;/[]{}-=ABCDEF_"
                   "0123456789abcdef.,;/[]{}-=ABCDEF", 64);
       memcpy (plain, "foobar42FOOBAR17", 16);
-      for (i = 16; i < 1040; i += 16)
+      for (i = 16; i < medium_buffer_size; i += 16)
         {
           memcpy (&plain[i], &plain[i-16], 16);
           if (!++plain[i+7])
@@ -6849,30 +11579,81 @@ check_one_cipher (int algo, int mode, int flags)
             plain[i+14]++;
         }
 
-      if (check_one_cipher_core (algo, mode, flags, key, 64, plain, 1040,
-                                 bufshift, 0+10*bufshift))
-        return;
+      if (check_one_cipher_core (algo, mode, flags, key, 64, plain,
+                                medium_buffer_size, bufshift,
+                                0+10*bufshift))
+        goto out;
 
       /* Pass 1: Key not aligned.  */
       memmove (key+1, key, 64);
-      if (check_one_cipher_core (algo, mode, flags, key+1, 64, plain, 1040,
-                                 bufshift, 1+10*bufshift))
-        return;
+      if (check_one_cipher_core (algo, mode, flags, key+1, 64, plain,
+                                medium_buffer_size, bufshift,
+                                1+10*bufshift))
+        goto out;
 
       /* Pass 2: Key not aligned and data not aligned.  */
-      memmove (plain+1, plain, 1040);
-      if (check_one_cipher_core (algo, mode, flags, key+1, 64, plain+1, 1040,
-                                 bufshift, 2+10*bufshift))
-        return;
+      memmove (plain+1, plain, medium_buffer_size);
+      if (check_one_cipher_core (algo, mode, flags, key+1, 64, plain+1,
+                                medium_buffer_size, bufshift,
+                                2+10*bufshift))
+        goto out;
 
       /* Pass 3: Key aligned and data not aligned.  */
       memmove (key, key+1, 64);
-      if (check_one_cipher_core (algo, mode, flags, key, 64, plain+1, 1040,
-                                 bufshift, 3+10*bufshift))
-        return;
+      if (check_one_cipher_core (algo, mode, flags, key, 64, plain+1,
+                                medium_buffer_size, bufshift,
+                                3+10*bufshift))
+        goto out;
+    }
+
+  /* Pass 5: Large buffer test.  */
+  memcpy (key, "0123456789abcdef.,;/[]{}-=ABCDEF_"
+               "0123456789abcdef.,;/[]{}-=ABCDEF", 64);
+  memcpy (plain, "foobar42FOOBAR17", 16);
+  for (i = 16; i < large_buffer_size; i += 16)
+    {
+      memcpy (&plain[i], &plain[i-16], 16);
+      if (!++plain[i+7])
+       plain[i+6]++;
+      if (!++plain[i+15])
+       plain[i+14]++;
+    }
+
+  if (check_one_cipher_core (algo, mode, flags, key, 64, plain,
+                            large_buffer_size, bufshift,
+                            50))
+    goto out;
+
+  /* Pass 6: Counter overflow tests for ChaCha20 and CTR mode. */
+  if (mode == GCRY_CIPHER_MODE_STREAM && algo == GCRY_CIPHER_CHACHA20)
+    {
+      /* 32bit overflow test (little-endian counter) */
+      if (check_one_cipher_ctr_overflow (algo, mode, flags, key, 64, plain,
+                                         medium_buffer_size, 0UL,
+                                         0, 60))
+       goto out;
+      /* 64bit overflow test (little-endian counter) */
+      if (check_one_cipher_ctr_overflow (algo, mode, flags, key, 64, plain,
+                                         medium_buffer_size, 0xffffffffUL,
+                                         0, 61))
+       goto out;
+    }
+   else if (mode == GCRY_CIPHER_MODE_CTR)
+    {
+      /* 32bit overflow test (big-endian counter) */
+      if (check_one_cipher_ctr_overflow (algo, mode, flags, key, 64, plain,
+                                         medium_buffer_size, 0UL,
+                                         1, 62))
+       goto out;
+      /* 64bit overflow test (big-endian counter) */
+      if (check_one_cipher_ctr_overflow (algo, mode, flags, key, 64, plain,
+                                         medium_buffer_size, 0xffffffffUL,
+                                         1, 63))
+       goto out;
     }
 
-  return;
+out:
+  free (plain);
 }
 
 
@@ -6921,6 +11702,10 @@ check_ciphers (void)
 #endif
 #if USE_GOST28147
     GCRY_CIPHER_GOST28147,
+    GCRY_CIPHER_GOST28147_MESH,
+#endif
+#if USE_SM4
+    GCRY_CIPHER_SM4,
 #endif
     0
   };
@@ -6937,17 +11722,31 @@ check_ciphers (void)
 #endif
     0
   };
+  gcry_error_t err = 0;
   int i;
 
   if (verbose)
     fprintf (stderr, "Starting Cipher checks.\n");
   for (i = 0; algos[i]; i++)
     {
-      if (gcry_cipher_test_algo (algos[i]) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (algos[i])))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    algos[i]);
+          if (in_fips_mode && (algos[i] == GCRY_CIPHER_AES ||
+                               algos[i] == GCRY_CIPHER_AES192 ||
+                               algos[i] == GCRY_CIPHER_AES256))
+            fail ("algorithm %d failed: %s\n", algos[i], gpg_strerror (err));
+          else
+            {
+              if (verbose)
+                fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                         algos[i]);
+            }
+          continue;
+        }
+      else if (in_fips_mode && algos[i] != GCRY_CIPHER_AES &&
+               algos[i] != GCRY_CIPHER_AES192 && algos[i] != GCRY_CIPHER_AES256)
+        {
+          fail ("algorithm %d did not fail as expected in FIPS mode\n", algos[i]);
           continue;
         }
       if (verbose)
@@ -6962,6 +11761,7 @@ check_ciphers (void)
       check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, 0);
       check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS);
       check_one_cipher (algos[i], GCRY_CIPHER_MODE_CTR, 0);
+      check_one_cipher (algos[i], GCRY_CIPHER_MODE_EAX, 0);
       if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_CCM_BLOCK_LEN)
         check_one_cipher (algos[i], GCRY_CIPHER_MODE_CCM, 0);
       if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_GCM_BLOCK_LEN)
@@ -6974,11 +11774,21 @@ check_ciphers (void)
 
   for (i = 0; algos2[i]; i++)
     {
-      if (gcry_cipher_test_algo (algos2[i]) && in_fips_mode)
+      if ((err = gcry_cipher_test_algo (algos2[i])))
         {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    algos2[i]);
+          if (in_fips_mode)
+            {
+              if (verbose)
+                fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                         algos2[i]);
+            }
+          else
+            fail ("algorithm %d failed: %s\n", algos2[i], gpg_strerror (err));
+          continue;
+        }
+      else if (in_fips_mode)
+        {
+          fail ("algorithm %d did not fail as expected in FIPS mode\n", algos2[i]);
           continue;
         }
       if (verbose)
@@ -7004,16 +11814,25 @@ check_cipher_modes(void)
   if (verbose)
     fprintf (stderr, "Starting Cipher Mode checks.\n");
 
+  check_ecb_cipher ();
   check_aes128_cbc_cts_cipher ();
   check_cbc_mac_cipher ();
   check_ctr_cipher ();
   check_cfb_cipher ();
   check_ofb_cipher ();
   check_ccm_cipher ();
-  check_gcm_cipher ();
+  if (!in_fips_mode)
+    {
+      /* This will have to go through modifications as the GCM fails in fips
+       * as late as in gcry_cipher_gettag, but we want to allow it in the end */
+      check_gcm_cipher ();
+    }
   check_poly1305_cipher ();
   check_ocb_cipher ();
   check_xts_cipher ();
+  check_eax_cipher ();
+  check_siv_cipher ();
+  check_gcm_siv_cipher ();
   check_gost28147_cipher ();
   check_stream_cipher ();
   check_stream_cipher_large_block ();
@@ -7038,7 +11857,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
   gcry_md_hd_t hd, hd2;
   unsigned char *p;
   int mdlen;
-  int i;
+  int i, j;
   int xof = 0;
   gcry_error_t err = 0;
 
@@ -7066,6 +11885,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
 
   if (key && klen)
     {
+      clutter_vector_registers();
       err = gcry_md_setkey (hd, key, klen);
       if (err)
        {
@@ -7075,6 +11895,69 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
        }
     }
 
+  if (*data == '!' && !data[1] && !xof)
+   {
+      unsigned char *p1, *p2;
+      char buf[129];
+
+      /* Test hashing small input sizes first as full block, then byte-by-byte
+       * and check that resulting digests are the same. */
+
+      err = gcry_md_open (&hd2, algo, 0);
+      if (err)
+       {
+         gcry_md_close (hd);
+         fail ("algo %d, gcry_md_open failed: %s\n", algo, gpg_strerror (err));
+         return;
+       }
+
+      if (key && klen)
+       {
+         clutter_vector_registers();
+         err = gcry_md_setkey (hd2, key, klen);
+         if (err)
+           {
+             gcry_md_close (hd);
+             gcry_md_close (hd2);
+             fail ("algo %d, gcry_md_setkey failed: %s\n", algo, gpg_strerror (err));
+             return;
+           }
+       }
+
+      for (i = 0; i < sizeof(buf); i++)
+       buf[i] = i;
+
+      for (i = 1; i < sizeof(buf); i++)
+       {
+         gcry_md_reset (hd);
+         gcry_md_reset (hd2);
+
+         clutter_vector_registers();
+          gcry_md_write (hd, buf, i);
+         for (j = 0; j < i; j++)
+           gcry_md_write (hd2, &buf[j], 1);
+
+         clutter_vector_registers();
+         p1 = gcry_md_read (hd, algo);
+         p2 = gcry_md_read (hd2, algo);
+         if (memcmp (p1, p2, mdlen))
+           {
+             printf ("full block (input length %d): ", i);
+             for (i = 0; i < mdlen; i++)
+               printf ("%02x ", p1[i] & 0xFF);
+             printf ("\nbyte-by-byte: ");
+             for (i = 0; i < mdlen; i++)
+               printf ("%02x ", p2[i] & 0xFF);
+             printf ("\n");
+
+             fail ("algo %d, digest mismatch\n", algo);
+           }
+       }
+
+      gcry_md_close (hd2);
+      gcry_md_reset (hd);
+   }
+
   if ((*data == '!' && !data[1]) || /* hash one million times a "a" */
       (*data == '?' && !data[1]))   /* hash million byte data-set with byte pattern 0x00,0x01,0x02,... */
     {
@@ -7098,6 +11981,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
          if (*data == '?')
            fillbuf_count(aaa, piecelen, 1000 * 1000 - left);
 
+         clutter_vector_registers();
           gcry_md_write (hd, aaa, piecelen);
 
           left -= piecelen;
@@ -7114,6 +11998,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
          if (*data == '?')
            fillbuf_count(aaa, piecelen, 1000 * 1000 - left);
 
+         clutter_vector_registers();
           gcry_md_write (hd, aaa, piecelen);
 
           left -= piecelen;
@@ -7125,8 +12010,12 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
         }
     }
   else
-    gcry_md_write (hd, data, len);
+    {
+      clutter_vector_registers();
+      gcry_md_write (hd, data, len);
+    }
 
+  clutter_vector_registers();
   err = gcry_md_copy (&hd2, hd);
   if (err)
     {
@@ -7137,6 +12026,9 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
 
   if (!xof)
     {
+      static const char buf[128];
+
+      clutter_vector_registers();
       p = gcry_md_read (hd2, algo);
 
       if (memcmp (p, expect, mdlen))
@@ -7151,18 +12043,25 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
 
           fail ("algo %d, digest mismatch\n", algo);
         }
+
+      /* Write after final/read is allowed for timing attack mitigation
+       * purposes. Try writing and see if we catch fire. */
+      clutter_vector_registers();
+      gcry_md_write (hd2, buf, sizeof(buf));
     }
   else
     {
       char buf[1000];
       int outmax = sizeof(buf) > elen ? elen : sizeof(buf);
 
+      clutter_vector_registers();
       err = gcry_md_copy (&hd, hd2);
       if (err)
        {
          fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err));
        }
 
+      clutter_vector_registers();
       err = gcry_md_extract(hd2, algo, buf, outmax);
       if (err)
        {
@@ -7185,6 +12084,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
       memset(buf, 0, sizeof(buf));
 
       /* Extract one byte at time. */
+      clutter_vector_registers();
       for (i = 0; i < outmax && !err; i++)
        err = gcry_md_extract(hd, algo, &buf[i], 1);
       if (err)
@@ -7207,7 +12107,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
 
       if (*data == '!' && !data[1])
        {
-         int crcalgo = GCRY_MD_RMD160;
+         int crcalgo = GCRY_MD_SHA256;
          gcry_md_hd_t crc1, crc2;
          size_t startlen;
          size_t piecelen;
@@ -7236,6 +12136,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
          /* Extract large chucks, total 1000000 additional bytes. */
          for (i = 0; i < 1000; i++)
            {
+             clutter_vector_registers();
              err = gcry_md_extract(hd, algo, buf, 1000);
              if (!err)
                gcry_md_write(crc1, buf, 1000);
@@ -7258,6 +12159,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
              if (piecelen > left)
                piecelen = left;
 
+             clutter_vector_registers();
              err = gcry_md_extract (hd2, algo, buf, piecelen);
              if (!err)
                gcry_md_write(crc2, buf, piecelen);
@@ -7275,7 +12177,9 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen,
                piecelen = piecelen * 2 - ((piecelen != startlen) ? startlen : 0);
            }
 
+         clutter_vector_registers();
          p1 = gcry_md_read (crc1, crcalgo);
+         clutter_vector_registers();
          p2 = gcry_md_read (crc2, crcalgo);
 
          if (memcmp (p1, p2, crclen))
@@ -7351,6 +12255,7 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect)
   iovcnt++;
   assert (iovcnt <= DIM (iov));
 
+  clutter_vector_registers();
   err = gcry_md_hash_buffers (algo, 0, digest, iov, iovcnt);
   if (err)
     {
@@ -7374,6 +12279,67 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect)
 
 
 static void
+check_one_md_final(int algo, const char *expect, unsigned int expectlen)
+{
+  const unsigned int max_inbuf_len = 288 + 1;
+  char *inbuf;
+  char xorbuf[64];
+  char digest[64];
+  unsigned int mdlen;
+  int i, j;
+
+  mdlen = gcry_md_get_algo_dlen (algo);
+  if (mdlen < 1 || mdlen > 64)
+    {
+      return;
+    }
+
+  if (expectlen == 0)
+    expectlen = mdlen;
+
+  if (expectlen != mdlen)
+    {
+      fail ("check_one_md_final: algo %d, digest length mismatch\n", algo);
+      return;
+    }
+
+  clutter_vector_registers();
+  gcry_md_hash_buffer (algo, xorbuf, NULL, 0);
+  for (i = 1; i < max_inbuf_len; i++)
+    {
+      inbuf = xmalloc(i);
+      if (!inbuf)
+       {
+         fail ("out-of-memory\n");
+         return;
+       }
+
+      for (j = 0; j < i; j++)
+       inbuf[j] = j;
+
+      gcry_md_hash_buffer (algo, digest, inbuf, i);
+      for (j = 0; j < expectlen; j++)
+       xorbuf[j] ^= digest[j];
+
+      xfree (inbuf);
+    }
+
+  if (memcmp(expect, xorbuf, expectlen) != 0)
+    {
+      printf ("computed: ");
+      for (i = 0; i < expectlen; i++)
+       printf ("%02x ", xorbuf[i] & 0xFF);
+      printf ("\nexpected: ");
+      for (i = 0; i < expectlen; i++)
+       printf ("%02x ", expect[i] & 0xFF);
+      printf ("\n");
+
+      fail ("check_one_md_final: algo %d, digest mismatch\n", algo);
+    }
+}
+
+
+static void
 check_digests (void)
 {
   static const char blake2_data_vector[] =
@@ -7563,6 +12529,18 @@ check_digests (void)
         "\x74\xee\x78\xeb\x79\x1f\x94\x38\x5b\x73\xef\xf8\xfd\x5d\x74\xd8"
         "\x51\x36\xfe\x63\x52\xde\x07\x70\x95\xd6\x78\x2b\x7b\x46\x8a\x2c"
         "\x30\x0f\x48\x0c\x74\x43\x06\xdb\xa3\x8d\x64\x3d\xe9\xa1\xa7\x72" },
+      { GCRY_MD_SHA512_256, "abc",
+       "\x53\x04\x8E\x26\x81\x94\x1E\xF9\x9B\x2E\x29\xB7\x6B\x4C\x7D\xAB"
+       "\xE4\xC2\xD0\xC6\x34\xFC\x6D\x46\xE0\xE2\xF1\x31\x07\xE7\xAF\x23" },
+      { GCRY_MD_SHA512_256, "!",
+       "\x9a\x59\xa0\x52\x93\x01\x87\xa9\x70\x38\xca\xe6\x92\xf3\x07\x08"
+       "\xaa\x64\x91\x92\x3e\xf5\x19\x43\x94\xdc\x68\xd5\x6c\x74\xfb\x21" },
+      { GCRY_MD_SHA512_224, "abc",
+       "\x46\x34\x27\x0F\x70\x7B\x6A\x54\xDA\xAE\x75\x30\x46\x08\x42\xE2"
+       "\x0E\x37\xED\x26\x5C\xEE\xE9\xA4\x3E\x89\x24\xAA" },
+      { GCRY_MD_SHA512_224, "!",
+       "\x37\xab\x33\x1d\x76\xf0\xd3\x6d\xe4\x22\xbd\x0e\xde\xb2\x2a\x28"
+       "\xac\xcd\x48\x7b\x7a\x84\x53\xae\x96\x5d\xd2\x87" },
       { GCRY_MD_SHA3_224, "abc",
        "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f"
        "\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf" },
@@ -7937,6 +12915,33 @@ check_digests (void)
         "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb",
         "\x9d\xd2\xfe\x4e\x90\x40\x9e\x5d\xa8\x7f\x53\x97\x6d\x74\x05\xb0"
         "\xc0\xca\xc6\x28\xfc\x66\x9a\x74\x1d\x50\x06\x3c\x55\x7e\x8f\x50" },
+      /* Special tests for carry flag in addition */
+      { GCRY_MD_STRIBOG512,
+        "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
+       "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
+       "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
+       "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
+       "\x16\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11"
+       "\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11"
+       "\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11"
+       "\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x16",
+       "\x8b\x06\xf4\x1e\x59\x90\x7d\x96\x36\xe8\x92\xca\xf5\x94\x2f\xcd"
+       "\xfb\x71\xfa\x31\x16\x9a\x5e\x70\xf0\xed\xb8\x73\x66\x4d\xf4\x1c"
+       "\x2c\xce\x6e\x06\xdc\x67\x55\xd1\x5a\x61\xcd\xeb\x92\xbd\x60\x7c"
+       "\xc4\xaa\xca\x67\x32\xbf\x35\x68\xa2\x3a\x21\x0d\xd5\x20\xfd\x41" },
+      { GCRY_MD_STRIBOG512,
+        "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+       "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+       "\x90\xa1\x61\xd1\x2a\xd3\x09\x49\x8d\x3f\xe5\xd4\x82\x02\xd8\xa4"
+       "\xe9\xc4\x06\xd6\xa2\x64\xae\xab\x25\x8a\xc5\xec\xc3\x7a\x79\x62"
+       "\xaa\xf9\x58\x7a\x5a\xbb\x09\xb6\xbb\x81\xec\x4b\x37\x52\xa3\xff"
+       "\x5a\x83\x8e\xf1\x75\xbe\x57\x72\x05\x6b\xc5\xfe\x54\xfc\xfc\x7e" },
 #include "./sha3-224.h"
 #include "./sha3-256.h"
 #include "./sha3-384.h"
@@ -8451,6 +13456,171 @@ check_digests (void)
        "\x0e\xfc\x29\xde" },
       { GCRY_MD_BLAKE2S_128, "?",
        "\x70\x0b\x8a\x71\x1d\x34\x0a\xf0\x13\x93\x19\x93\x5e\xd7\x54\x9c" },
+
+#if USE_SM3
+      { GCRY_MD_SM3, "abc",
+       "\x66\xc7\xf0\xf4\x62\xee\xed\xd9\xd1\xf2\xd4\x6b\xdc\x10\xe4\xe2"
+       "\x41\x67\xc4\x87\x5c\xf2\xf7\xa2\x29\x7d\xa0\x2b\x8f\x4b\xa8\xe0" },
+      { GCRY_MD_SM3,
+       "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+       "\x63\x9b\x6c\xc5\xe6\x4d\x9e\x37\xa3\x90\xb1\x92\xdf\x4f\xa1\xea"
+       "\x07\x20\xab\x74\x7f\xf6\x92\xb9\xf3\x8c\x4e\x66\xad\x7b\x8c\x05" },
+      { GCRY_MD_SM3, "!",
+       "\xc8\xaa\xf8\x94\x29\x55\x40\x29\xe2\x31\x94\x1a\x2a\xcc\x0a\xd6"
+       "\x1f\xf2\xa5\xac\xd8\xfa\xdd\x25\x84\x7a\x3a\x73\x2b\x3b\x02\xc3" },
+      { GCRY_MD_SM3, "?",
+       "\x3a\x3f\x53\xfc\x96\xc2\xde\xb2\xd9\x12\x3a\x1b\xd8\x47\x71\x28"
+       "\xbc\x5d\x5e\x94\xea\x08\x86\x3d\xfb\xe4\x00\x5a\xd9\xed\x79\x26" },
+      { GCRY_MD_SM3,
+       "Libgcrypt is free software; you can redistribute it and/or modif"
+       "y it under the terms of the GNU Lesser general Public License as"
+       " published by the Free Software Foundation; either version 2.1 o"
+       "f the License, or (at your option) any later version.\nLibgcrypt"
+       " is distributed in the hope that it will be useful, but WITHOUT "
+       "ANY WARRANTY; without even the implied warranty of MERCHANTABILI"
+       "TY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser Gene"
+       "ral Public License for more details.",
+       "\x8b\x91\x3f\x0e\x85\xae\x43\x25\x6d\x28\x38\x6c\x09\x5c\xc7\x72"
+       "\xcc\x2e\x78\x89\x7e\x2e\x4e\x5a\x3d\xf6\x55\xfe\x87\xbe\xa6\xbc" },
+#endif /* USE_SM3 */
+
+      { GCRY_MD_GOSTR3411_CP,
+        "*",
+        "\x72\xd7\xe3\xbf\xa0\x08\xc9\x62\xae\xa9\xc5\xd8\x93\x5f\x17\xd7"
+        "\x3f\xf2\x52\xb4\xc1\x16\xcf\x63\xa4\xcc\x4a\x8c\x7f\xe5\x60\x2c" },
+      { GCRY_MD_MD4,
+        "*",
+        "\xe8\xb9\xe4\x59\x61\x08\xc0\xfe\x54\xef\xc5\x8e\x20\x7c\x9b\x37" },
+      { GCRY_MD_MD5,
+        "*",
+        "\x0b\x1e\xab\xa2\x5e\x48\x76\x92\xae\x16\x12\xde\x5f\xb3\x29\x41" },
+      { GCRY_MD_RMD160,
+        "*",
+        "\x28\xfd\xd6\xa8\x95\x29\x43\x6b\x5e\xd9\xa0\x06\x82\xbb\xe6\x10"
+        "\xd3\xcc\x79\x33" },
+      { GCRY_MD_SHA1,
+        "*",
+        "\xd8\x37\x46\x1a\x46\xfe\x42\x11\x7d\x50\xca\xf7\x3d\x7e\x0c\x36"
+        "\x42\x0c\x15\xb6" },
+      { GCRY_MD_SHA224,
+        "*",
+        "\x2e\xba\x51\x6c\x71\x5a\x1d\xb8\x6b\x57\xfb\xf1\x46\xa0\xa7\x1d"
+        "\x72\x66\xaf\x90\xb8\x01\x18\xc8\x58\x57\xa5\x63" },
+      { GCRY_MD_SHA256,
+        "*",
+        "\x30\xed\xe4\x69\xf3\x1c\x70\x8a\x6d\x92\x00\xac\xd8\x08\x89\xea"
+        "\x7e\x92\xff\x02\x0b\x72\x4a\xdf\xa9\x2b\x9f\x80\xba\xd0\x25\xd0" },
+      { GCRY_MD_SHA384,
+        "*",
+        "\x21\xd7\x40\xdf\x34\x13\xcf\x56\xf7\x61\x0a\x1b\x11\xb7\x1e\x01"
+        "\x87\xad\xbb\x3e\x9a\xe8\xaa\xaa\xbc\x3a\x89\x39\x0a\xa9\xcb\x4f"
+        "\x09\x75\x4c\x44\x59\x42\xf5\x13\x5f\xe5\xa6\x2b\x16\xbe\xfc\xdf" },
+      { GCRY_MD_SHA512,
+        "*",
+        "\x5c\xbe\x01\x03\xbd\x8d\xa1\x38\x5e\x87\x00\x94\x8d\x14\xd0\xb3"
+        "\x2c\x88\xeb\xb8\xf6\xcc\x06\x44\x54\xb1\x58\x88\xa9\x67\xa0\xe3"
+        "\x0d\x28\x8b\xf4\x2c\xc6\x7a\xdc\x1a\x35\xbf\x0c\xc8\x35\xf0\x24"
+        "\x69\xb5\xfe\x15\x6f\x71\xbd\x87\x07\x52\x27\xcc\xdc\x21\x84\x21" },
+      { GCRY_MD_SHA3_224,
+        "*",
+        "\x1a\xa6\x6f\x1a\x3c\x62\x14\x75\xea\x9d\x49\x4d\x39\x01\x2b\xbd"
+        "\x4d\xe1\x58\xbc\x32\xac\x48\xcf\x6a\x1a\x54\x34" },
+      { GCRY_MD_SHA3_256,
+        "*",
+        "\x87\xf8\x0e\x78\xc1\x7b\x0c\x36\x4c\xbb\x8d\xca\x5e\x77\xc3\xfd"
+        "\x95\xbd\xaf\x94\x85\xc6\x0c\xe6\x22\x52\xeb\x22\x50\x32\x48\x57" },
+      { GCRY_MD_SHA3_384,
+        "*",
+        "\x89\x5a\xd6\xc8\x60\x20\x66\xe7\x9e\xb3\x6d\x5c\x07\xd7\x5e\xd0"
+        "\x48\x84\x9d\x51\x75\x14\x77\xdb\xcd\xbf\x70\x18\xdc\x64\x53\x85"
+        "\x94\x95\xa5\xd3\x26\x9c\xf1\x63\x14\x8d\x11\xa0\xfc\xd8\x05\x9e" },
+      { GCRY_MD_SHA3_512,
+        "*",
+        "\x53\x0b\x1c\xb7\xff\x2c\xaa\x7e\x62\x15\xa7\x57\x9a\xd0\xcf\x4f"
+        "\xa5\xae\xe0\x05\x1c\x77\x0f\x29\x5b\x3f\xba\xab\x88\x0c\x0b\x8e"
+        "\x10\xcf\x3d\xa9\x0d\x1e\x97\x98\x96\xeb\x24\x2e\x70\x30\xd0\x78"
+        "\x2b\x9e\x30\xad\x5d\xcf\x56\xcf\xd0\xc1\x58\x95\x53\x09\x78\xd6" },
+#if USE_SM3
+      { GCRY_MD_SM3,
+        "*",
+        "\xb6\xfc\x1e\xc4\xad\x9b\x88\xbd\x08\xaa\xf3\xb3\xfa\x4f\x1b\x9c"
+        "\xd6\x9a\x32\x09\x28\x9e\xda\x3a\x99\xb6\x09\x8f\x35\x99\xa6\x11" },
+#endif /* USE_SM3 */
+      { GCRY_MD_STRIBOG256,
+        "*",
+        "\x35\x0b\xec\x46\x1f\x98\x19\xe7\x33\x12\xda\x9f\xaf\x3d\x32\xa6"
+        "\xe4\xa5\x80\x38\x1b\x56\x68\x13\x2d\x0d\xa6\xfd\xfa\xe5\x3d\xf2" },
+      { GCRY_MD_STRIBOG512,
+        "*",
+        "\x01\x4c\xbd\xd4\x3a\x1a\x51\x9e\xa8\x7c\x1f\xd2\xc3\x2e\x71\x78"
+        "\x03\x46\xd0\x1b\x30\xdd\x07\xf6\x82\x2b\xa4\x43\x8f\x95\x44\x9d"
+        "\x92\x3a\x17\x70\x1b\xdd\xfc\x8f\x71\x20\xc6\xa0\xd8\x6f\xb2\x06"
+        "\xb6\x61\x27\x48\x45\x94\x96\xe7\xdc\xf5\x7a\x2f\x83\x82\x03\x08" },
+      { GCRY_MD_TIGER1,
+        "*",
+        "\x95\xe1\x25\x8f\xc5\x4b\x82\x12\x69\x83\xfa\xfd\x79\x7d\x87\x38"
+        "\x01\x4f\xf9\x24\xa2\xf0\x8f\x85" },
+      { GCRY_MD_WHIRLPOOL,
+        "*",
+        "\x8e\x02\x8e\x8d\xeb\x03\xcc\x37\xf2\x67\x61\x4e\x16\x27\x06\x13"
+        "\x26\x8c\x35\x17\x0c\xab\x3c\x8b\x25\xc3\x3a\x2b\x7d\x54\xbf\xcf"
+        "\x7e\xa2\xe4\x4f\x8d\x67\xb7\x85\xfa\x54\x76\x7c\xb0\x24\x87\xd5"
+        "\x0e\x7d\x3b\x02\x8f\x30\x9e\x91\x78\xea\xc6\xdc\x0e\xee\x71\xca" },
+      { GCRY_MD_CRC24_RFC2440,
+        "*",
+        "\x44\x53\xd8" },
+      { GCRY_MD_CRC32,
+        "*",
+        "\x96\x11\x46\x4d" },
+      { GCRY_MD_TIGER,
+        "*",
+        "\x12\x82\x4b\xc5\x8f\x25\xe1\x95\x38\x87\x7d\x79\xfd\xfa\x83\x69"
+        "\x85\x8f\xf0\xa2\x24\xf9\x4f\x01" },
+      { GCRY_MD_TIGER2,
+        "*",
+        "\xc6\x8f\x98\x71\xee\xb3\x1a\xf6\x77\x50\x8e\x74\x98\x08\x6c\x42"
+        "\xc0\x37\x43\xc2\x17\x89\x5f\x98" },
+      { GCRY_MD_CRC32_RFC1510,
+        "*",
+        "\xf4\x45\xfd\x43" },
+      { GCRY_MD_BLAKE2B_512,
+        "*",
+        "\xe0\xf7\x38\x87\x07\xf9\xfd\xeb\x58\x8d\xb9\xb8\xa4\x85\x21\x8e"
+        "\x56\xa9\xe6\x8d\x64\x4d\xfb\xe8\x8a\x84\xa4\x45\xc7\x80\x4b\x1f"
+        "\x63\x0b\x27\x84\x96\xd4\xeb\x99\x19\xcb\xc6\x37\x01\x42\xb9\x03"
+        "\x50\x63\xdf\xb9\x5e\xc5\xb1\xda\x2d\x19\xeb\x65\x73\xd2\xfa\xfa" },
+      { GCRY_MD_BLAKE2B_384,
+        "*",
+        "\x44\xde\xb8\x2b\x46\x22\xe5\xc6\xa5\x66\x8a\x88\x2b\xc3\x2c\x27"
+        "\xc1\x4e\x4f\x6b\x70\x96\xcb\x1a\x99\x04\x67\x54\x8a\x0a\x55\xb4"
+        "\xdb\x8b\xf6\x36\xfc\x2e\xf6\x2a\x6b\xe2\x1d\x09\x0e\x2f\x65\x33" },
+      { GCRY_MD_BLAKE2B_256,
+        "*",
+        "\x75\xd1\x62\xad\x02\xf1\x3f\xa3\x95\x2f\x5f\x89\x13\x2c\xf4\x2f"
+        "\xc3\x84\xd2\x46\xbc\x35\x2b\x13\x01\xe0\x9e\x46\x55\x92\x40\x5a" },
+      { GCRY_MD_BLAKE2B_160,
+        "*",
+        "\x8c\x67\x38\x0e\xf8\xc7\xb6\x3e\x7f\x8e\x32\x73\x8a\xba\xa4\x71"
+        "\x87\x9a\xb0\x4c" },
+      { GCRY_MD_BLAKE2S_256,
+        "*",
+        "\x71\x4a\x6d\xe4\xbb\x6c\x9f\x22\xff\x50\x02\xba\x5f\x54\xa6\x39"
+        "\x9d\x07\x95\x82\x38\x98\xac\x62\xab\xc6\x13\x12\x65\x64\x9e\x69" },
+      { GCRY_MD_BLAKE2S_224,
+        "*",
+        "\x4c\x01\xe6\x67\xa2\x02\xd1\x62\x9b\xc3\x3b\xb5\x93\xc4\x3c\xa9"
+        "\x90\x7b\x96\x70\xfd\xdf\xd1\xc3\xad\x09\xa9\xe7" },
+      { GCRY_MD_BLAKE2S_160,
+        "*",
+        "\x21\xca\x18\x74\x76\x3c\x6b\xe4\x92\x01\xd6\xd5\x91\xd1\x53\xfb"
+        "\x37\x73\x99\xb9" },
+      { GCRY_MD_BLAKE2S_128,
+        "*",
+        "\x1d\x87\xfa\x69\xe0\x93\xd9\xcd\xb0\x3c\x52\x00\x35\xe1\xa3\xee" },
+      { GCRY_MD_GOSTR3411_94,
+        "*",
+        "\x6e\xa9\x9e\x23\xde\x5f\x7a\xb7\x7f\xa7\xdc\xe1\xc8\x05\x46\xae"
+        "\x1e\x7c\x76\xbb\x52\x0f\x52\x07\x78\x59\xd3\xc1\x64\xdb\x51\xac" },
       { 0 }
     };
   gcry_error_t err;
@@ -8463,16 +13633,29 @@ check_digests (void)
     {
       if (gcry_md_test_algo (algos[i].md))
         {
-          show_md_not_available (algos[i].md);
-          continue;
-        }
-      if (gcry_md_test_algo (algos[i].md) && in_fips_mode)
-        {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    algos[i].md);
+          if (in_fips_mode)
+            {
+              if (verbose)
+                fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                         algos[i].md);
+            }
+          else
+            show_md_not_available (algos[i].md);
           continue;
         }
+
+      if (!strcmp (algos[i].data, "*"))
+       {
+         if (verbose)
+           fprintf (stderr, "  checking %s [%i] for final handling\n",
+                   gcry_md_algo_name (algos[i].md),
+                   algos[i].md);
+
+         check_one_md_final (algos[i].md, algos[i].expect, algos[i].expectlen);
+
+         continue;
+       }
+
       if (verbose)
        fprintf (stderr, "  checking %s [%i] for length %d\n",
                 gcry_md_algo_name (algos[i].md),
@@ -8575,23 +13758,36 @@ check_one_hmac (int algo, const char *data, int datalen,
       return;
     }
 
-  gcry_md_setkey( hd, key, keylen );
+  err = gcry_md_setkey( hd, key, keylen );
+  if (err)
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr,
+                     "  shorter key (%d) rejected correctly in fips mode\n",
+                     keylen);
+        }
+      gcry_md_close (hd);
+      return;
+    }
 
   gcry_md_write (hd, data, datalen);
 
   err = gcry_md_copy (&hd2, hd);
+
+  gcry_md_close (hd);
+
   if (err)
     {
       fail ("algo %d, gcry_md_copy failed: %s\n", algo, gpg_strerror (err));
+      return;
     }
 
-  gcry_md_close (hd);
-
   p = gcry_md_read (hd2, algo);
   if (!p)
     fail("algo %d, hmac gcry_md_read failed\n", algo);
-
-  if (memcmp (p, expect, mdlen))
+  else if (memcmp (p, expect, mdlen))
     {
       printf ("computed: ");
       for (i = 0; i < mdlen; i++)
@@ -8900,14 +14096,14 @@ check_hmac (void)
     {
       if (gcry_md_test_algo (algos[i].md))
         {
-          show_old_hmac_not_available (algos[i].md);
-          continue;
-        }
-      if (gcry_md_test_algo (algos[i].md) && in_fips_mode)
-        {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    algos[i].md);
+          if (in_fips_mode)
+            {
+              if (verbose)
+                fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                         algos[i].md);
+            }
+          else
+            show_old_hmac_not_available (algos[i].md);
           continue;
         }
       if (verbose)
@@ -8975,14 +14171,25 @@ check_one_mac (int algo, const char *data, int datalen,
       return;
     }
 
+  clutter_vector_registers();
   err = gcry_mac_setkey (hd, key, keylen);
   if (err)
-    fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err));
-  if (err)
-    goto out;
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr,
+                     "  shorter key (%d) rejected correctly in fips mode\n",
+                     keylen);
+        }
+      else
+        fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err));
+      goto out;
+    }
 
   if (ivlen && iv)
     {
+      clutter_vector_registers();
       err = gcry_mac_setiv (hd, iv, ivlen);
       if (err)
         fail("algo %d, mac gcry_mac_ivkey failed: %s\n", algo,
@@ -8995,6 +14202,7 @@ check_one_mac (int algo, const char *data, int datalen,
     {
       for (i = 0; i < datalen; i++)
         {
+         clutter_vector_registers();
           err = gcry_mac_write (hd, &data[i], 1);
           if (err)
             fail("algo %d, mac gcry_mac_write [buf-offset: %d] failed: %s\n",
@@ -9028,6 +14236,7 @@ check_one_mac (int algo, const char *data, int datalen,
               if (*data == '?')
                 fillbuf_count(aaa, piecelen, 1000 * 1000 - left);
 
+             clutter_vector_registers();
               gcry_mac_write (hd, aaa, piecelen);
 
               left -= piecelen;
@@ -9044,6 +14253,7 @@ check_one_mac (int algo, const char *data, int datalen,
               if (*data == '?')
                 fillbuf_count(aaa, piecelen, 1000 * 1000 - left);
 
+             clutter_vector_registers();
               gcry_mac_write (hd, aaa, piecelen);
 
               left -= piecelen;
@@ -9056,6 +14266,7 @@ check_one_mac (int algo, const char *data, int datalen,
         }
       else
         {
+         clutter_vector_registers();
           err = gcry_mac_write (hd, data, datalen);
         }
 
@@ -9065,11 +14276,13 @@ check_one_mac (int algo, const char *data, int datalen,
         goto out;
     }
 
+  clutter_vector_registers();
   err = gcry_mac_verify (hd, expect, maclen);
   if (err)
     fail("algo %d, mac gcry_mac_verify failed: %s\n", algo, gpg_strerror (err));
 
   macoutlen = maclen;
+  clutter_vector_registers();
   err = gcry_mac_read (hd, p, &macoutlen);
   if (err)
     fail("algo %d, mac gcry_mac_read failed: %s\n", algo, gpg_strerror (err));
@@ -9668,6 +14881,7 @@ check_mac (void)
         "\xe1\x99\x21\x90\x54\x9f\x6e\xd5\x69\x6a\x2c\x05\x6c\x31\x54\x10" },
       { GCRY_MAC_CMAC_AES, "?", "????????????????????????????????",
         "\x9f\x72\x73\x68\xb0\x49\x2e\xb1\x35\xa0\x1d\xf9\xa8\x0a\xf6\xee" },
+#if USE_DES
       { GCRY_MAC_CMAC_3DES,
         "",
         "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58"
@@ -9714,6 +14928,8 @@ check_mac (void)
         "\x31\xb1\xe4\x31\xda\xbc\x4e\xb8" },
       { GCRY_MAC_CMAC_3DES, "?", "????????????????????????",
         "\xc1\x38\x13\xb2\x31\x8f\x3a\xdf" },
+#endif /* USE_DES */
+#if USE_CAMELLIA
       /* CMAC Camellia test vectors from
          http://tools.ietf.org/html/draft-kato-ipsec-camellia-cmac96and128-05 */
       { GCRY_MAC_CMAC_CAMELLIA,
@@ -9739,6 +14955,7 @@ check_mac (void)
         "\xc2\x69\x9a\x6e\xba\x55\xce\x9d\x93\x9a\x8a\x4e\x19\x46\x6e\xe9" },
       { GCRY_MAC_CMAC_CAMELLIA, "?", "????????????????????????????????",
         "\xba\x8a\x5a\x8d\xa7\x54\x26\x83\x3e\xb1\x20\xb5\x45\xd0\x9f\x4e" },
+#endif /* USE_CAMELLIA */
       /* http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip */
       { GCRY_MAC_GMAC_AES,
         "",
@@ -9985,6 +15202,15 @@ check_mac (void)
         "\x9d\xeb\xb0\xcd\x24\x90\xd3\x9b\x47\x78\x37\x0a\x81\xf2\x83\x2a",
         "\x61\xee\x09\x21\x8d\x29\xb0\xaa\xed\x7e\x15\x4a\x2c\x55\x09\xcc",
         0, 32 },
+#if USE_GOST28147
+      { GCRY_MAC_GOST28147_IMIT,
+        "\xb5\xa1\xf0\xe3\xce\x2f\x02\x1d\x67\x61\x94\x34\x5c\x41\xe3\x6e",
+       "\x9d\x05\xb7\x9e\x90\xca\xd0\x0a\x2c\xda\xd2\x2e\xf4\xe8\x6f\x5c"
+       "\xf5\xdc\x37\x68\x19\x85\xb3\xbf\xaa\x18\xc1\xc3\x05\x0a\x91\xa2",
+        "\xf8\x1f\x08\xa3",
+        NULL,
+        16, 32 },
+#endif /* USE_GOST28147 */
       { 0 },
     };
   int i;
@@ -9998,14 +15224,14 @@ check_mac (void)
 
       if (gcry_mac_test_algo (algos[i].algo))
         {
-          show_mac_not_available (algos[i].algo);
-          continue;
-        }
-      if (gcry_mac_test_algo (algos[i].algo) && in_fips_mode)
-        {
-          if (verbose)
-            fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                    algos[i].algo);
+          if (in_fips_mode)
+            {
+              if (verbose)
+                fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                         algos[i].algo);
+            }
+          else
+            show_mac_not_available (algos[i].algo);
           continue;
         }
       if (verbose)
@@ -10050,10 +15276,11 @@ verify_one_signature (gcry_sexp_t pkey, gcry_sexp_t hash,
 }
 
 
-/* Test the public key sign function using the private ket SKEY. PKEY
+/* Test the public key sign function using the private key SKEY. PKEY
    is used for verification. */
 static void
-check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
+check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo,
+                   int flags)
 {
   gcry_error_t rc;
   gcry_sexp_t sig, badhash, hash;
@@ -10125,6 +15352,17 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
         " (random-override #4253647587980912233445566778899019283747#))\n",
        GCRY_PK_RSA,
        0 },
+      { "(data\n (flags pss)\n"
+       " (hash-algo sha1)\n"
+       " (value #11223344556677889900AA#))\n",
+       GCRY_PK_RSA,
+       0 },
+      { "(data\n (flags pss)\n"
+       " (hash-algo sha1)\n"
+       " (value #11223344556677889900AA#)\n"
+        " (random-override #4253647587980912233445566778899019283747#))\n",
+       GCRY_PK_RSA,
+       0 },
       { NULL }
     };
 
@@ -10132,6 +15370,7 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
   if (rc)
     die ("converting data failed: %s\n", gpg_strerror (rc));
 
+  sig = NULL;
   for (dataidx = 0; datas[dataidx].data; dataidx++)
     {
       if (datas[dataidx].algo && datas[dataidx].algo != algo)
@@ -10147,12 +15386,19 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
        die ("converting data failed: %s\n", gpg_strerror (rc));
 
       rc = gcry_pk_sign (&sig, hash, skey);
+      if (in_fips_mode && (flags & FLAG_NOFIPS))
+        {
+          if (!rc)
+            fail ("gcry_pk_sign did not fail as expected in FIPS mode\n");
+          goto next;
+        }
       if (gcry_err_code (rc) != datas[dataidx].expected_rc)
        fail ("gcry_pk_sign failed: %s\n", gpg_strerror (rc));
 
       if (!rc)
        verify_one_signature (pkey, hash, badhash, sig);
 
+    next:
       gcry_sexp_release (sig);
       sig = NULL;
       gcry_sexp_release (hash);
@@ -10163,10 +15409,11 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
 }
 
 
-/* Test the public key sign function using the private ket SKEY. PKEY
+/* Test the public key sign function using the private key SKEY. PKEY
    is used for verification.  This variant is only used for ECDSA.  */
 static void
-check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey)
+check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey,
+                         int flags)
 {
   gcry_error_t rc;
   gcry_sexp_t sig, badhash, hash;
@@ -10233,11 +15480,22 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey)
         /* */    "000102030405060708090A0B0C0D0E0F#))",
         0
       },
+      { 256,
+        "(data (flags sm2)\n"
+        " (hash sm3 #112233445566778899AABBCCDDEEFF00"
+        /* */       "123456789ABCDEF0123456789ABCDEF0#))",
+        0,
+        "(data (flags sm2)\n"
+        " (hash sm3 #B524F552CD82B8B028476E005C377FB1"
+        /* */       "9A87E6FC682D48BB5D42E3D9B9EFFE76#))",
+        0
+      },
       { 0, NULL }
     };
 
   nbits = gcry_pk_get_nbits (skey);
 
+  sig = NULL;
   for (dataidx = 0; datas[dataidx].data; dataidx++)
     {
       if (datas[dataidx].nbits != nbits)
@@ -10257,6 +15515,12 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey)
         die ("converting data failed: %s\n", gpg_strerror (rc));
 
       rc = gcry_pk_sign (&sig, hash, skey);
+      if (in_fips_mode && (flags & FLAG_NOFIPS))
+        {
+          if (!rc)
+            fail ("gcry_pk_sign did not fail as expected in FIPS mode\n");
+          goto next;
+        }
       if (gcry_err_code (rc) != datas[dataidx].expected_rc)
        fail ("gcry_pk_sign failed: %s\n", gpg_strerror (rc));
 
@@ -10266,6 +15530,7 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey)
       if (!rc)
         verify_one_signature (pkey, hash, badhash, sig);
 
+    next:
       gcry_sexp_release (sig);
       sig = NULL;
       gcry_sexp_release (badhash);
@@ -10277,7 +15542,8 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey)
 
 
 static void
-check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
+check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo,
+                    int flags)
 {
   gcry_error_t rc;
   gcry_sexp_t plain = NULL;
@@ -10410,6 +15676,12 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
        die ("converting data failed: %s\n", gpg_strerror (rc));
 
       rc = gcry_pk_encrypt (&ciph, data, pkey);
+      if (in_fips_mode && (flags & FLAG_NOFIPS))
+        {
+          if (!rc)
+            fail ("gcry_pk_encrypt did not fail as expected in FIPS mode\n");
+          goto next;
+        }
       if (gcry_err_code (rc) != datas[dataidx].encrypt_expected_rc)
        fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (rc));
 
@@ -10425,8 +15697,8 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
              gcry_sexp_t list;
 
              /* Convert decoding hint into canonical sexp. */
-             hint_len = gcry_sexp_new (&list, datas[dataidx].hint,
-                                       strlen (datas[dataidx].hint), 1);
+             gcry_sexp_new (&list, datas[dataidx].hint,
+                             strlen (datas[dataidx].hint), 1);
              hint_len = gcry_sexp_sprint (list, GCRYSEXP_FMT_CANON, NULL, 0);
              hint = gcry_malloc (hint_len);
              if (!hint)
@@ -10508,6 +15780,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo)
            }
        }
 
+    next:
       gcry_sexp_release (plain);
       plain = NULL;
       gcry_sexp_release (ciph);
@@ -10539,23 +15812,23 @@ static void
 do_check_one_pubkey (int n, gcry_sexp_t skey, gcry_sexp_t pkey,
                     const unsigned char *grip, int algo, int flags)
 {
if (flags & FLAG_SIGN)
 if ((flags & FLAG_SIGN))
    {
      if (algo == GCRY_PK_ECDSA)
-       check_pubkey_sign_ecdsa (n, skey, pkey);
+       check_pubkey_sign_ecdsa (n, skey, pkey, flags);
      else
-       check_pubkey_sign (n, skey, pkey, algo);
+       check_pubkey_sign (n, skey, pkey, algo, flags);
    }
if (flags & FLAG_CRYPT)
-   check_pubkey_crypt (n, skey, pkey, algo);
- if (grip && (flags & FLAG_GRIP))
-   check_pubkey_grip (n, grip, skey, pkey, algo);
 if ((flags & FLAG_CRYPT))
+    check_pubkey_crypt (n, skey, pkey, algo, flags);
 if (grip && (flags & FLAG_GRIP))
+    check_pubkey_grip (n, grip, skey, pkey, algo);
 }
 
 static void
 check_one_pubkey (int n, test_spec_pubkey_t spec)
 {
-  gcry_error_t err = GPG_ERR_NO_ERROR;
+  gcry_error_t err = 0;
   gcry_sexp_t skey, pkey;
 
   err = gcry_sexp_sscan (&skey, NULL, spec.key.secret,
@@ -10623,7 +15896,7 @@ check_pubkey (void)
 {
   static const test_spec_pubkey_t pubkeys[] = {
   {
-    GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN,
+    GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN | FLAG_GRIP | FLAG_NOFIPS, /* 1k RSA */
     {
       "(private-key\n"
       " (rsa\n"
@@ -10661,7 +15934,63 @@ check_pubkey (void)
       "\xa2\x5d\x3d\x69\xf8\x6d\x37\xa4\xf9\x39"}
   },
   {
-    GCRY_PK_DSA, FLAG_SIGN,
+    GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN | FLAG_GRIP, /* 2k RSA */
+    {
+      "(private-key"
+      " (rsa"
+      "  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+      "      7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+      "      7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+      "      958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+      "      DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+      "      6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+      "      42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+      "      664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6"
+      "      CB#)\n"
+      "   (e #010001#)\n"
+      "   (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19"
+      "       8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93"
+      "       7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12"
+      "       771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F"
+      "       5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48"
+      "       EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD"
+      "       69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84"
+      "       3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401"
+      "       #)\n"
+      "   (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0"
+      "       79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B"
+      "       441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF"
+      "       54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17"
+      "       83#)\n"
+      "   (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46"
+      "       79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77"
+      "       88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E"
+      "       8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B9"
+      "       19#)\n"
+      "   (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04"
+      "       479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4"
+      "       A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9"
+      "       AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7"
+      "       #)))\n",
+
+      "(public-key\n"
+      " (rsa\n"
+      "  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+      "      7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+      "      7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+      "      958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+      "      DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+      "      6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+      "      42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+      "      664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6"
+      "      CB#)\n"
+      "   (e #010001#)))\n",
+
+      "\xe0\x08\x98\x9b\xb6\x44\xa2\x9a\x83\x37"
+      "\x47\xdd\x69\x55\xdb\x3a\xac\x89\x6e\x40"}
+  },
+  {
+    GCRY_PK_DSA, FLAG_SIGN | FLAG_GRIP | FLAG_NOFIPS, /* 1k DSA */
     {
       "(private-key\n"
       " (DSA\n"
@@ -10706,7 +16035,7 @@ check_pubkey (void)
       "\x4a\xa6\xf9\xeb\x23\xbf\xa9\x12\x2d\x5b" }
   },
   {
-    GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT,
+    GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT | FLAG_GRIP | FLAG_NOFIPS,
     {
       "(private-key\n"
       " (ELG\n"
@@ -10754,8 +16083,7 @@ check_pubkey (void)
       "(public-key\n"
       " (ecdsa\n"
       "  (curve nistp192)\n"
-      "  (q #048532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE"
-      "        C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966#)))\n",
+      "  (q #028532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE#)))\n",
 
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
@@ -10832,15 +16160,14 @@ check_pubkey (void)
       "(public-key\n"
       " (ecc\n"
       "  (curve nistp256)\n"
-      "  (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2B"
-      "      EB6644D3609FC781B71F9A8072F58CB66AE2F89BB1245187"
-      "      3ABF7D91F9E1FBF96BF2F70E73AAC9A283#)))\n",
+      "  (q #03D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2B"
+      "      EB6644D3609FC781B7#)))\n",
 
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
   },
   { /* GOST R 34.10-2001/2012 test 256 bit.  */
-    GCRY_PK_ECDSA, FLAG_SIGN,
+    GCRY_PK_ECDSA, FLAG_SIGN | FLAG_NOFIPS,
     {
       "(private-key\n"
       " (ecc\n"
@@ -10862,11 +16189,11 @@ check_pubkey (void)
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
   },
   { /* GOST R 34.10-2012 test 512 bit.  */
-    GCRY_PK_ECDSA, FLAG_SIGN,
+    GCRY_PK_ECDSA, FLAG_SIGN | FLAG_NOFIPS,
     {
       "(private-key\n"
       " (ecc\n"
-      "  (curve GOST2012-test)\n"
+      "  (curve GOST2012-512-test)\n"
       "  (q #04115DC5BC96760C7B48598D8AB9E740D4C4A85A65BE33C1"
       "        815B5C320C854621DD5A515856D13314AF69BC5B924C8B"
       "        4DDFF75C45415C1D9DD9DD33612CD530EFE137C7C90CD4"
@@ -10879,13 +16206,13 @@ check_pubkey (void)
 
       "(public-key\n"
       " (ecc\n"
-      "  (curve GOST2012-test)\n"
+      "  (curve GOST2012-512-test)\n"
       "  (q #04115DC5BC96760C7B48598D8AB9E740D4C4A85A65BE33C1"
       "        815B5C320C854621DD5A515856D13314AF69BC5B924C8B"
       "        4DDFF75C45415C1D9DD9DD33612CD530EFE137C7C90CD4"
       "        0B0F5621DC3AC1B751CFA0E2634FA0503B3D52639F5D7F"
       "        B72AFD61EA199441D943FFE7F0C70A2759A3CDB84C114E"
-      "        1F9339FDF27F35ECA93677BEEC#)))\n"
+      "        1F9339FDF27F35ECA93677BEEC#)))\n",
 
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
@@ -10907,12 +16234,36 @@ check_pubkey (void)
       "  (curve secp256k1)\n"
       "  (q #0439A36013301597DAEF41FBE593A02CC513D0B55527EC2D"
       "      F1050E2E8FF49C85C23CBE7DED0E7CE6A594896B8F62888F"
-      "      DBC5C8821305E2EA42BF01E37300116281#)))\n"
+      "      DBC5C8821305E2EA42BF01E37300116281#)))\n",
+
+      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+      "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
+  },
+  { /* sm2 test */
+    GCRY_PK_ECDSA, FLAG_SIGN | FLAG_NOFIPS,
+    {
+      "(private-key\n"
+      " (ecc\n"
+      "  (curve sm2p256v1)\n"
+      "  (q #04"
+      "      8759389A34AAAD07ECF4E0C8C2650A4459C8D926EE2378324E0261C52538CB47"
+      "      7528106B1E0B7C8DD5FF29A9C86A89065656EB33154BC0556091EF8AC9D17D78#)"
+      "  (d #41EBDBA9C98CBECCE7249CF18BFD427FF8EA0B2FAB7B9D305D9D9BF4DB6ADFC2#)"
+      "))",
+
+      "(public-key\n"
+      " (ecc\n"
+      "  (curve sm2p256v1)\n"
+      "  (q #04"
+      "      8759389A34AAAD07ECF4E0C8C2650A4459C8D926EE2378324E0261C52538CB47"
+      "      7528106B1E0B7C8DD5FF29A9C86A89065656EB33154BC0556091EF8AC9D17D78#)"
+      "))",
 
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }
     }
   };
+  gcry_error_t err = 0;
   int i;
 
   if (verbose)
@@ -10920,12 +16271,19 @@ check_pubkey (void)
   for (i = 0; i < sizeof (pubkeys) / sizeof (*pubkeys); i++)
     if (pubkeys[i].id)
       {
-        if (gcry_pk_test_algo (pubkeys[i].id) && in_fips_mode)
+        if ((err = gcry_pk_test_algo (pubkeys[i].id)))
           {
-            if (verbose)
-              fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                       pubkeys[i].id);
-            continue;
+            if (in_fips_mode && (pubkeys[i].flags & FLAG_NOFIPS))
+              {
+                if (verbose)
+                  fprintf (stderr, "  algorithm %d not available in fips mode\n",
+                           pubkeys[i].id);
+              }
+            else
+              {
+                fail ("gcry_pk_test_algo failed: %s\n", gpg_strerror (err));
+                continue;
+              }
           }
         check_one_pubkey (i, pubkeys[i]);
       }
@@ -10933,21 +16291,10 @@ check_pubkey (void)
     fprintf (stderr, "Completed public key checks.\n");
 
   if (verbose)
-    fprintf (stderr, "Starting additional public key checks.\n");
-  for (i = 0; i < sizeof (pubkeys) / sizeof (*pubkeys); i++)
-    if (pubkeys[i].id)
-      {
-        if (gcry_pk_test_algo (pubkeys[i].id) && in_fips_mode)
-          {
-            if (verbose)
-              fprintf (stderr, "  algorithm %d not available in fips mode\n",
-                       pubkeys[i].id);
-            continue;
-          }
-        check_one_pubkey_new (i);
-      }
+    fprintf (stderr, "Starting additional public key check.\n");
+  check_one_pubkey_new (i);
   if (verbose)
-    fprintf (stderr, "Completed additional public key checks.\n");
+    fprintf (stderr, "Completed additional public key check.\n");
 
 }
 
@@ -10960,6 +16307,7 @@ main (int argc, char **argv)
   int selftest_only = 0;
   int pubkey_only = 0;
   int cipher_modes_only = 0;
+  int hash_only = 0;
   int loop = 0;
   unsigned int loopcount = 0;
 
@@ -11005,6 +16353,11 @@ main (int argc, char **argv)
           cipher_modes_only = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--hash"))
+        {
+          hash_only = 1;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--die"))
         {
           die_on_error = 1;
@@ -11036,10 +16389,10 @@ main (int argc, char **argv)
         }
     }
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
 
   if (use_fips)
-    xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
+    xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0));
 
   /* Check that we test exactly our version - including the patchlevel.  */
   if (strcmp (GCRYPT_VERSION, gcry_check_version (NULL)))
@@ -11050,16 +16403,16 @@ main (int argc, char **argv)
     in_fips_mode = 1;
 
   if (!in_fips_mode)
-    xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+    xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
 
   if (verbose)
     gcry_set_progress_handler (progress_handler, NULL);
 
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
   /* No valuable keys are create, so we can speed up our RNG. */
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
 
   do
     {
@@ -11070,6 +16423,12 @@ main (int argc, char **argv)
           check_ciphers ();
           check_cipher_modes ();
         }
+      else if (hash_only)
+        {
+          check_digests ();
+          check_hmac ();
+          check_mac ();
+        }
       else if (!selftest_only)
         {
           check_ciphers ();
@@ -11096,7 +16455,7 @@ main (int argc, char **argv)
       gcry_md_hd_t md;
 
       /* First trigger a self-test.  */
-      xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
+      gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
       if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0))
         fail ("not in operational state after self-test\n");
 
@@ -11125,7 +16484,7 @@ main (int argc, char **argv)
                 {
                   /* Now run a self-test and to get back into
                      operational state.  */
-                  xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
+                  gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
                   if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0))
                     fail ("did not reach operational after error "
                           "and self-test\n");
index 8ec97bf..1387190 100755 (executable)
@@ -68,7 +68,7 @@ done | sort | (
   while read opts; do
     currn=$nbasic
     curr_jobs=($(jobs -p))
-    while [ "${#curr_jobs[@]}" -ge "8" ]; do
+    while [ "${#curr_jobs[@]}" -ge "$njobs" ]; do
       # Wait for one job to complete
       wait ${retcodes[$nwait]}
       retval=$?
index 75e6e43..1bd6ee1 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <string.h>
 #include <assert.h>
+#include <float.h>
 #include <time.h>
+#ifdef _WIN32
+#include <windows.h>
+#endif
 
 #ifdef _GCRYPT_IN_LIBGCRYPT
 # include "../src/gcrypt-int.h"
@@ -50,6 +55,9 @@ static int num_measurement_repetitions;
    results.  */
 static double cpu_ghz = -1;
 
+/* Attempt to autodetect CPU Ghz. */
+static int auto_ghz;
+
 /* Whether we are running as part of the regression test suite.  */
 static int in_regression_test;
 
@@ -61,6 +69,14 @@ static char *current_algo_name;
 static char *current_mode_name;
 
 
+/* Currently used CPU Ghz (either user input or auto-detected. */
+static double bench_ghz;
+
+/* Current accuracy of auto-detected CPU Ghz. */
+static double bench_ghz_diff;
+
+static int in_fips_mode;
+
 /*************************************** Default parameters for measurements. */
 
 /* Start at small buffer size, to get reasonable timer calibration for fast
@@ -79,6 +95,9 @@ static char *current_mode_name;
  * measurements is selected as data point further analysis. */
 #define NUM_MEASUREMENT_REPETITIONS    64
 
+/* Target accuracy for auto-detected CPU Ghz. */
+#define AUTO_GHZ_TARGET_DIFF           (5e-5)
+
 /**************************************************** High-resolution timers. */
 
 /* This benchmarking module needs needs high resolution timer.  */
@@ -220,6 +239,7 @@ struct bench_obj
   unsigned int step_size;
 
   void *priv;
+  void *hd;
 };
 
 typedef int (*const bench_initialize_t) (struct bench_obj * obj);
@@ -235,7 +255,28 @@ struct bench_ops
 };
 
 
-double
+static double
+safe_div (double x, double y)
+{
+  union
+  {
+    double d;
+    char buf[sizeof(double)];
+  } u_neg_zero, u_y;
+
+  if (y != 0)
+    return x / y;
+
+  u_neg_zero.d = -0.0;
+  u_y.d = y;
+  if (memcmp(u_neg_zero.buf, u_y.buf, sizeof(double)) == 0)
+    return -DBL_MAX;
+
+  return DBL_MAX;
+}
+
+
+static double
 get_slope (double (*const get_x) (unsigned int idx, void *priv),
           void *get_x_priv, double y_points[], unsigned int npoints,
           double *overhead)
@@ -246,12 +287,18 @@ get_slope (double (*const get_x) (unsigned int idx, void *priv),
 
   sumx = sumy = sumx2 = sumy2 = sumxy = 0;
 
+  if (npoints <= 1)
+    {
+      /* No slope with zero or one point. */
+      return 0;
+    }
+
   for (i = 0; i < npoints; i++)
     {
       double x, y;
 
       x = get_x (i, get_x_priv);       /* bytes */
-      y = y_points[i];         /* nsecs */
+      y = y_points[i];                 /* nsecs */
 
       sumx += x;
       sumy += y;
@@ -260,11 +307,13 @@ get_slope (double (*const get_x) (unsigned int idx, void *priv),
       sumxy += x * y;
     }
 
-  b = (npoints * sumxy - sumx * sumy) / (npoints * sumx2 - sumx * sumx);
-  a = (sumy - b * sumx) / npoints;
+  b = safe_div(npoints * sumxy - sumx * sumy, npoints * sumx2 - sumx * sumx);
 
   if (overhead)
-    *overhead = a;             /* nsecs */
+    {
+      a = safe_div(sumy - b * sumx, npoints);
+      *overhead = a;           /* nsecs */
+    }
 
   return b;                    /* nsecs per byte */
 }
@@ -383,7 +432,7 @@ adjust_loop_iterations_to_timer_accuracy (struct bench_obj *obj, void *buffer,
 
 /* Benchmark and return linear regression slope in nanoseconds per byte.  */
 double
-do_slope_benchmark (struct bench_obj *obj)
+slope_benchmark (struct bench_obj *obj)
 {
   unsigned int num_measurements;
   double *measurements = NULL;
@@ -464,6 +513,179 @@ err_free:
   return -1;
 }
 
+/********************************************* CPU frequency auto-detection. */
+
+static int
+auto_ghz_init (struct bench_obj *obj)
+{
+  obj->min_bufsize = 16;
+  obj->max_bufsize = 64 + obj->min_bufsize;
+  obj->step_size = 8;
+  obj->num_measure_repetitions = 16;
+
+  return 0;
+}
+
+static void
+auto_ghz_free (struct bench_obj *obj)
+{
+  (void)obj;
+}
+
+static void
+auto_ghz_bench (struct bench_obj *obj, void *buf, size_t buflen)
+{
+  (void)obj;
+  (void)buf;
+
+  buflen *= 1024;
+
+  /* Turbo frequency detection benchmark. Without CPU turbo-boost, this
+   * function will give cycles/iteration result 1024.0 on high-end CPUs.
+   * With turbo, result will be less and can be used detect turbo-clock. */
+
+#ifdef HAVE_GCC_ASM_VOLATILE_MEMORY
+  /* Auto-ghz operation takes two CPU cycles to perform. Memory barriers
+   * are used to prevent compiler from optimizing this loop away. */
+  #define AUTO_GHZ_OPERATION \
+       asm volatile ("":"+r"(buflen)::"memory"); \
+       buflen ^= 1; \
+       asm volatile ("":"+r"(buflen)::"memory"); \
+       buflen -= 2
+#else
+  /* TODO: Needs alternative way of preventing compiler optimizations.
+   *       Mix of XOR and subtraction appears to do the trick for now. */
+  #define AUTO_GHZ_OPERATION \
+       buflen ^= 1; \
+       buflen -= 2
+#endif
+
+#define AUTO_GHZ_OPERATION_2 \
+       AUTO_GHZ_OPERATION; \
+       AUTO_GHZ_OPERATION
+
+#define AUTO_GHZ_OPERATION_4 \
+       AUTO_GHZ_OPERATION_2; \
+       AUTO_GHZ_OPERATION_2
+
+#define AUTO_GHZ_OPERATION_8 \
+       AUTO_GHZ_OPERATION_4; \
+       AUTO_GHZ_OPERATION_4
+
+#define AUTO_GHZ_OPERATION_16 \
+       AUTO_GHZ_OPERATION_8; \
+       AUTO_GHZ_OPERATION_8
+
+#define AUTO_GHZ_OPERATION_32 \
+       AUTO_GHZ_OPERATION_16; \
+       AUTO_GHZ_OPERATION_16
+
+#define AUTO_GHZ_OPERATION_64 \
+       AUTO_GHZ_OPERATION_32; \
+       AUTO_GHZ_OPERATION_32
+
+#define AUTO_GHZ_OPERATION_128 \
+       AUTO_GHZ_OPERATION_64; \
+       AUTO_GHZ_OPERATION_64
+
+  do
+    {
+      /* 1024 auto-ghz operations per loop, total 2048 instructions. */
+      AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128;
+      AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128;
+      AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128;
+      AUTO_GHZ_OPERATION_128; AUTO_GHZ_OPERATION_128;
+    }
+  while (buflen);
+}
+
+static struct bench_ops auto_ghz_detect_ops = {
+  &auto_ghz_init,
+  &auto_ghz_free,
+  &auto_ghz_bench
+};
+
+
+double
+get_auto_ghz (void)
+{
+  struct bench_obj obj = { 0 };
+  double nsecs_per_iteration;
+  double cycles_per_iteration;
+
+  obj.ops = &auto_ghz_detect_ops;
+
+  nsecs_per_iteration = slope_benchmark (&obj);
+
+  cycles_per_iteration = nsecs_per_iteration * cpu_ghz;
+
+  /* Adjust CPU Ghz so that cycles per iteration would give '1024.0'. */
+
+  return safe_div(cpu_ghz * 1024, cycles_per_iteration);
+}
+
+
+double
+do_slope_benchmark (struct bench_obj *obj)
+{
+  unsigned int try_count = 0;
+  double ret;
+
+  if (!auto_ghz)
+    {
+      /* Perform measurement without autodetection of CPU frequency. */
+
+      do
+        {
+         ret = slope_benchmark (obj);
+        }
+      while (ret <= 0 && try_count++ <= 4);
+
+      bench_ghz = cpu_ghz;
+      bench_ghz_diff = 0;
+    }
+  else
+    {
+      double target_diff = AUTO_GHZ_TARGET_DIFF;
+      double cpu_auto_ghz_before;
+      double cpu_auto_ghz_after;
+      double nsecs_per_iteration;
+      double diff;
+
+      /* Perform measurement with CPU frequency autodetection. */
+
+      do
+        {
+          /* Repeat measurement until CPU turbo frequency has stabilized. */
+
+         if ((++try_count % 4) == 0)
+           {
+             /* Too much frequency instability on the system, relax target
+              * accuracy. */
+             target_diff *= 2;
+           }
+
+          cpu_auto_ghz_before = get_auto_ghz ();
+
+          nsecs_per_iteration = slope_benchmark (obj);
+
+          cpu_auto_ghz_after = get_auto_ghz ();
+
+          diff = 1.0 - safe_div(cpu_auto_ghz_before, cpu_auto_ghz_after);
+          diff = diff < 0 ? -diff : diff;
+        }
+      while ((nsecs_per_iteration <= 0 || diff > target_diff)
+            && try_count < 1000);
+
+      ret = nsecs_per_iteration;
+
+      bench_ghz = (cpu_auto_ghz_before + cpu_auto_ghz_after) / 2;
+      bench_ghz_diff = diff;
+    }
+
+  return ret;
+}
+
 
 /********************************************************** Printing results. */
 
@@ -476,8 +698,10 @@ double_to_str (char *out, size_t outlen, double value)
     fmt = "%.3f";
   else if (value < 100.0)
     fmt = "%.2f";
-  else
+  else if (value < 1000.0)
     fmt = "%.1f";
+  else
+    fmt = "%.0f";
 
   snprintf (out, outlen, fmt, value);
 }
@@ -489,31 +713,55 @@ bench_print_result_csv (double nsecs_per_byte)
   char nsecpbyte_buf[16];
   char mbpsec_buf[16];
   char cpbyte_buf[16];
+  char mhz_buf[16];
+  char mhz_diff_buf[32];
 
+  strcpy (mhz_diff_buf, "");
   *cpbyte_buf = 0;
+  *mhz_buf = 0;
 
   double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte);
 
   /* If user didn't provide CPU speed, we cannot show cycles/byte results.  */
-  if (cpu_ghz > 0.0)
+  if (bench_ghz > 0.0)
     {
-      cycles_per_byte = nsecs_per_byte * cpu_ghz;
+      cycles_per_byte = nsecs_per_byte * bench_ghz;
       double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte);
+      double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000);
+      if (auto_ghz && bench_ghz_diff * 1000 >= 1)
+       {
+         snprintf(mhz_diff_buf, sizeof(mhz_diff_buf), ",%.0f,Mhz-diff",
+                  bench_ghz_diff * 1000);
+       }
     }
 
   mbytes_per_sec =
-    (1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024);
+      safe_div(1000.0 * 1000.0 * 1000.0, nsecs_per_byte * 1024 * 1024);
   double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
 
   /* We print two empty fields to allow for future enhancements.  */
-  printf ("%s,%s,%s,,,%s,ns/B,%s,MiB/s,%s,c/B\n",
-          current_section_name,
-          current_algo_name? current_algo_name : "",
-          current_mode_name? current_mode_name : "",
-          nsecpbyte_buf,
-          mbpsec_buf,
-          cpbyte_buf);
-
+  if (auto_ghz)
+    {
+      printf ("%s,%s,%s,,,%s,ns/B,%s,MiB/s,%s,c/B,%s,Mhz%s\n",
+              current_section_name,
+              current_algo_name? current_algo_name : "",
+              current_mode_name? current_mode_name : "",
+              nsecpbyte_buf,
+              mbpsec_buf,
+              cpbyte_buf,
+              mhz_buf,
+              mhz_diff_buf);
+    }
+  else
+    {
+      printf ("%s,%s,%s,,,%s,ns/B,%s,MiB/s,%s,c/B\n",
+              current_section_name,
+              current_algo_name? current_algo_name : "",
+              current_mode_name? current_mode_name : "",
+              nsecpbyte_buf,
+              mbpsec_buf,
+              cpbyte_buf);
+    }
 }
 
 static void
@@ -523,24 +771,45 @@ bench_print_result_std (double nsecs_per_byte)
   char nsecpbyte_buf[16];
   char mbpsec_buf[16];
   char cpbyte_buf[16];
+  char mhz_buf[16];
+  char mhz_diff_buf[32];
+
+  strcpy (mhz_diff_buf, "");
 
   double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte);
 
   /* If user didn't provide CPU speed, we cannot show cycles/byte results.  */
-  if (cpu_ghz > 0.0)
+  if (bench_ghz > 0.0)
     {
-      cycles_per_byte = nsecs_per_byte * cpu_ghz;
+      cycles_per_byte = nsecs_per_byte * bench_ghz;
       double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte);
+      double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000);
+      if (auto_ghz && bench_ghz_diff * 1000 >= 0.5)
+       {
+         snprintf(mhz_diff_buf, sizeof(mhz_diff_buf), "±%.0f",
+                  bench_ghz_diff * 1000);
+       }
     }
   else
-    strcpy (cpbyte_buf, "-");
+    {
+      strcpy (cpbyte_buf, "-");
+      strcpy (mhz_buf, "-");
+    }
 
   mbytes_per_sec =
-    (1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024);
+      safe_div(1000.0 * 1000.0 * 1000.0, nsecs_per_byte * 1024 * 1024);
   double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
 
-  printf ("%9s ns/B %9s MiB/s %9s c/B\n",
-          nsecpbyte_buf, mbpsec_buf, cpbyte_buf);
+  if (auto_ghz)
+    {
+      printf ("%9s ns/B %9s MiB/s %9s c/B %9s%s\n",
+              nsecpbyte_buf, mbpsec_buf, cpbyte_buf, mhz_buf, mhz_diff_buf);
+    }
+  else
+    {
+      printf ("%9s ns/B %9s MiB/s %9s c/B\n",
+              nsecpbyte_buf, mbpsec_buf, cpbyte_buf);
+    }
 }
 
 static void
@@ -553,6 +822,54 @@ bench_print_result (double 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)
 {
   if (csv_mode)
@@ -578,8 +895,35 @@ bench_print_header (int algo_width, const char *algo_name)
         printf (" %-*s | ", -algo_width, algo_name);
       else
         printf (" %-*s | ", algo_width, algo_name);
-      printf ("%14s %15s %13s\n", "nanosecs/byte", "mebibytes/sec",
-              "cycles/byte");
+
+      if (auto_ghz)
+        printf ("%14s %15s %13s %9s\n", "nanosecs/byte", "mebibytes/sec",
+                "cycles/byte", "auto Mhz");
+      else
+        printf ("%14s %15s %13s\n", "nanosecs/byte", "mebibytes/sec",
+                "cycles/byte");
+    }
+}
+
+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");
     }
 }
 
@@ -659,6 +1003,11 @@ bench_encrypt_init (struct bench_obj *obj)
     }
 
   keylen = gcry_cipher_get_algo_keylen (mode->algo);
+  if (mode->mode == GCRY_CIPHER_MODE_SIV)
+    {
+      keylen *= 2;
+    }
+
   if (keylen)
     {
       char key[keylen];
@@ -684,7 +1033,7 @@ bench_encrypt_init (struct bench_obj *obj)
       exit (1);
     }
 
-  obj->priv = hd;
+  obj->hd = hd;
 
   return 0;
 }
@@ -692,7 +1041,7 @@ bench_encrypt_init (struct bench_obj *obj)
 static void
 bench_encrypt_free (struct bench_obj *obj)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
 
   gcry_cipher_close (hd);
 }
@@ -700,10 +1049,12 @@ bench_encrypt_free (struct bench_obj *obj)
 static void
 bench_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
   int err;
 
-  err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
+  err = gcry_cipher_reset (hd);
+  if (!err)
+    err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
   if (err)
     {
       fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
@@ -716,10 +1067,12 @@ bench_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
 static void
 bench_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
   int err;
 
-  err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
+  err = gcry_cipher_reset (hd);
+  if (!err)
+    err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
   if (err)
     {
       fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
@@ -749,10 +1102,9 @@ bench_xts_encrypt_init (struct bench_obj *obj)
   gcry_cipher_hd_t hd;
   int err, keylen;
 
-  /* For XTS, benchmark with typical data-unit size (512 byte sectors). */
-  obj->min_bufsize = 512;
-  obj->max_bufsize = 16 * obj->min_bufsize;
-  obj->step_size = obj->min_bufsize;
+  obj->min_bufsize = BUF_START_SIZE;
+  obj->max_bufsize = BUF_END_SIZE;
+  obj->step_size = BUF_STEP_SIZE;
   obj->num_measure_repetitions = num_measurement_repetitions;
 
   err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0);
@@ -790,82 +1142,28 @@ bench_xts_encrypt_init (struct bench_obj *obj)
       exit (1);
     }
 
-  obj->priv = hd;
+  obj->hd = hd;
 
   return 0;
 }
 
-static void
-bench_xts_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
-{
-  gcry_cipher_hd_t hd = obj->priv;
-  unsigned int pos;
-  static const char tweak[16] = { 0xff, 0xff, 0xfe, };
-  size_t sectorlen = obj->step_size;
-  char *cbuf = buf;
-  int err;
-
-  gcry_cipher_setiv (hd, tweak, sizeof (tweak));
-
-  /* Process each sector separately. */
-
-  for (pos = 0; pos < buflen; pos += sectorlen, cbuf += sectorlen)
-    {
-      err = gcry_cipher_encrypt (hd, cbuf, sectorlen, cbuf, sectorlen);
-      if (err)
-       {
-         fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
-                 gpg_strerror (err));
-         gcry_cipher_close (hd);
-         exit (1);
-       }
-    }
-}
-
-static void
-bench_xts_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
-{
-  gcry_cipher_hd_t hd = obj->priv;
-  unsigned int pos;
-  static const char tweak[16] = { 0xff, 0xff, 0xfe, };
-  size_t sectorlen = obj->step_size;
-  char *cbuf = buf;
-  int err;
-
-  gcry_cipher_setiv (hd, tweak, sizeof (tweak));
-
-  /* Process each sector separately. */
-
-  for (pos = 0; pos < buflen; pos += sectorlen, cbuf += sectorlen)
-    {
-      err = gcry_cipher_decrypt (hd, cbuf, sectorlen, cbuf, sectorlen);
-      if (err)
-       {
-         fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
-                 gpg_strerror (err));
-         gcry_cipher_close (hd);
-         exit (1);
-       }
-    }
-}
-
 static struct bench_ops xts_encrypt_ops = {
   &bench_xts_encrypt_init,
   &bench_encrypt_free,
-  &bench_xts_encrypt_do_bench
+  &bench_encrypt_do_bench
 };
 
 static struct bench_ops xts_decrypt_ops = {
   &bench_xts_encrypt_init,
   &bench_encrypt_free,
-  &bench_xts_decrypt_do_bench
+  &bench_decrypt_do_bench
 };
 
 
 static void
 bench_ccm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
   int err;
   char tag[8];
   char nonce[11] = { 0x80, 0x01, };
@@ -909,7 +1207,7 @@ bench_ccm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
 static void
 bench_ccm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
   int err;
   char tag[8] = { 0, };
   char nonce[11] = { 0x80, 0x01, };
@@ -956,7 +1254,7 @@ static void
 bench_ccm_authenticate_do_bench (struct bench_obj *obj, void *buf,
                                 size_t buflen)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
   int err;
   char tag[8] = { 0, };
   char nonce[11] = { 0x80, 0x01, };
@@ -1030,10 +1328,11 @@ static void
 bench_aead_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen,
                             const char *nonce, size_t noncelen)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
   int err;
   char tag[16];
 
+  gcry_cipher_reset (hd);
   gcry_cipher_setiv (hd, nonce, noncelen);
 
   gcry_cipher_final (hd);
@@ -1060,17 +1359,22 @@ static void
 bench_aead_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen,
                             const char *nonce, size_t noncelen)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
   int err;
   char tag[16] = { 0, };
 
+  gcry_cipher_reset (hd);
+  gcry_cipher_set_decryption_tag (hd, tag, 16);
+
   gcry_cipher_setiv (hd, nonce, noncelen);
 
   gcry_cipher_final (hd);
   err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
+  if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
+    err = gpg_error (GPG_ERR_NO_ERROR);
   if (err)
     {
-      fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
+      fprintf (stderr, PGM ": gcry_cipher_decrypt failed: %s\n",
            gpg_strerror (err));
       gcry_cipher_close (hd);
       exit (1);
@@ -1093,18 +1397,23 @@ bench_aead_authenticate_do_bench (struct bench_obj *obj, void *buf,
                                  size_t buflen, const char *nonce,
                                  size_t noncelen)
 {
-  gcry_cipher_hd_t hd = obj->priv;
+  gcry_cipher_hd_t hd = obj->hd;
   int err;
   char tag[16] = { 0, };
   char data = 0xff;
 
-  err = gcry_cipher_setiv (hd, nonce, noncelen);
-  if (err)
+  gcry_cipher_reset (hd);
+
+  if (noncelen > 0)
     {
-      fprintf (stderr, PGM ": gcry_cipher_setiv failed: %s\n",
-           gpg_strerror (err));
-      gcry_cipher_close (hd);
-      exit (1);
+      err = gcry_cipher_setiv (hd, nonce, noncelen);
+      if (err)
+       {
+         fprintf (stderr, PGM ": gcry_cipher_setiv failed: %s\n",
+              gpg_strerror (err));
+         gcry_cipher_close (hd);
+         exit (1);
+       }
     }
 
   err = gcry_cipher_authenticate (hd, buf, buflen);
@@ -1233,70 +1542,213 @@ static struct bench_ops ocb_authenticate_ops = {
 
 
 static void
-bench_poly1305_encrypt_do_bench (struct bench_obj *obj, void *buf,
-                                size_t buflen)
+bench_siv_encrypt_do_bench (struct bench_obj *obj, void *buf,
+                           size_t buflen)
 {
-  char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
-  bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+  bench_aead_encrypt_do_bench (obj, buf, buflen, NULL, 0);
 }
 
 static void
-bench_poly1305_decrypt_do_bench (struct bench_obj *obj, void *buf,
-                                size_t buflen)
+bench_siv_decrypt_do_bench (struct bench_obj *obj, void *buf,
+                           size_t buflen)
 {
-  char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
-  bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+  bench_aead_decrypt_do_bench (obj, buf, buflen, NULL, 0);
 }
 
 static void
-bench_poly1305_authenticate_do_bench (struct bench_obj *obj, void *buf,
-                                     size_t buflen)
+bench_siv_authenticate_do_bench (struct bench_obj *obj, void *buf,
+                                size_t buflen)
 {
-  char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
-  bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+  bench_aead_authenticate_do_bench (obj, buf, buflen, NULL, 0);
 }
 
-static struct bench_ops poly1305_encrypt_ops = {
+static struct bench_ops siv_encrypt_ops = {
   &bench_encrypt_init,
   &bench_encrypt_free,
-  &bench_poly1305_encrypt_do_bench
+  &bench_siv_encrypt_do_bench
 };
 
-static struct bench_ops poly1305_decrypt_ops = {
+static struct bench_ops siv_decrypt_ops = {
   &bench_encrypt_init,
   &bench_encrypt_free,
-  &bench_poly1305_decrypt_do_bench
+  &bench_siv_decrypt_do_bench
 };
 
-static struct bench_ops poly1305_authenticate_ops = {
+static struct bench_ops siv_authenticate_ops = {
   &bench_encrypt_init,
   &bench_encrypt_free,
-  &bench_poly1305_authenticate_do_bench
+  &bench_siv_authenticate_do_bench
 };
 
 
-static struct bench_cipher_mode cipher_modes[] = {
-  {GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops},
-  {GCRY_CIPHER_MODE_ECB, "ECB dec", &decrypt_ops},
-  {GCRY_CIPHER_MODE_CBC, "CBC enc", &encrypt_ops},
-  {GCRY_CIPHER_MODE_CBC, "CBC dec", &decrypt_ops},
-  {GCRY_CIPHER_MODE_CFB, "CFB enc", &encrypt_ops},
-  {GCRY_CIPHER_MODE_CFB, "CFB dec", &decrypt_ops},
-  {GCRY_CIPHER_MODE_OFB, "OFB enc", &encrypt_ops},
-  {GCRY_CIPHER_MODE_OFB, "OFB dec", &decrypt_ops},
-  {GCRY_CIPHER_MODE_CTR, "CTR enc", &encrypt_ops},
-  {GCRY_CIPHER_MODE_CTR, "CTR dec", &decrypt_ops},
-  {GCRY_CIPHER_MODE_XTS, "XTS enc", &xts_encrypt_ops},
-  {GCRY_CIPHER_MODE_XTS, "XTS dec", &xts_decrypt_ops},
+static void
+bench_gcm_siv_encrypt_do_bench (struct bench_obj *obj, void *buf,
+                               size_t buflen)
+{
+  char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
+                     0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 };
+  bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static void
+bench_gcm_siv_decrypt_do_bench (struct bench_obj *obj, void *buf,
+                               size_t buflen)
+{
+  char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
+                     0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 };
+  bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static void
+bench_gcm_siv_authenticate_do_bench (struct bench_obj *obj, void *buf,
+                                    size_t buflen)
+{
+  char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
+                     0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 };
+  bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static struct bench_ops gcm_siv_encrypt_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_gcm_siv_encrypt_do_bench
+};
+
+static struct bench_ops gcm_siv_decrypt_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_gcm_siv_decrypt_do_bench
+};
+
+static struct bench_ops gcm_siv_authenticate_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_gcm_siv_authenticate_do_bench
+};
+
+
+static void
+bench_eax_encrypt_do_bench (struct bench_obj *obj, void *buf,
+                           size_t buflen)
+{
+  char nonce[16] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
+                     0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
+                     0x00, 0x00, 0x01, 0x00 };
+  bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static void
+bench_eax_decrypt_do_bench (struct bench_obj *obj, void *buf,
+                           size_t buflen)
+{
+  char nonce[16] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
+                     0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
+                     0x00, 0x00, 0x01, 0x00 };
+  bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static void
+bench_eax_authenticate_do_bench (struct bench_obj *obj, void *buf,
+                                size_t buflen)
+{
+  char nonce[16] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
+                     0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
+                     0x00, 0x00, 0x01, 0x00 };
+  bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static struct bench_ops eax_encrypt_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_eax_encrypt_do_bench
+};
+
+static struct bench_ops eax_decrypt_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_eax_decrypt_do_bench
+};
+
+static struct bench_ops eax_authenticate_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_eax_authenticate_do_bench
+};
+
+static void
+bench_poly1305_encrypt_do_bench (struct bench_obj *obj, void *buf,
+                                size_t buflen)
+{
+  char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
+  bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static void
+bench_poly1305_decrypt_do_bench (struct bench_obj *obj, void *buf,
+                                size_t buflen)
+{
+  char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
+  bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static void
+bench_poly1305_authenticate_do_bench (struct bench_obj *obj, void *buf,
+                                     size_t buflen)
+{
+  char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
+  bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
+}
+
+static struct bench_ops poly1305_encrypt_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_poly1305_encrypt_do_bench
+};
+
+static struct bench_ops poly1305_decrypt_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_poly1305_decrypt_do_bench
+};
+
+static struct bench_ops poly1305_authenticate_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_poly1305_authenticate_do_bench
+};
+
+
+static struct bench_cipher_mode cipher_modes[] = {
+  {GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_ECB, "ECB dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_CBC, "CBC enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_CBC, "CBC dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_CFB, "CFB enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_CFB, "CFB dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_OFB, "OFB enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_OFB, "OFB dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_CTR, "CTR enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_CTR, "CTR dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_XTS, "XTS enc", &xts_encrypt_ops},
+  {GCRY_CIPHER_MODE_XTS, "XTS dec", &xts_decrypt_ops},
   {GCRY_CIPHER_MODE_CCM, "CCM enc", &ccm_encrypt_ops},
   {GCRY_CIPHER_MODE_CCM, "CCM dec", &ccm_decrypt_ops},
   {GCRY_CIPHER_MODE_CCM, "CCM auth", &ccm_authenticate_ops},
+  {GCRY_CIPHER_MODE_EAX, "EAX enc",  &eax_encrypt_ops},
+  {GCRY_CIPHER_MODE_EAX, "EAX dec",  &eax_decrypt_ops},
+  {GCRY_CIPHER_MODE_EAX, "EAX auth", &eax_authenticate_ops},
   {GCRY_CIPHER_MODE_GCM, "GCM enc", &gcm_encrypt_ops},
   {GCRY_CIPHER_MODE_GCM, "GCM dec", &gcm_decrypt_ops},
   {GCRY_CIPHER_MODE_GCM, "GCM auth", &gcm_authenticate_ops},
   {GCRY_CIPHER_MODE_OCB, "OCB enc",  &ocb_encrypt_ops},
   {GCRY_CIPHER_MODE_OCB, "OCB dec",  &ocb_decrypt_ops},
   {GCRY_CIPHER_MODE_OCB, "OCB auth", &ocb_authenticate_ops},
+  {GCRY_CIPHER_MODE_SIV, "SIV enc", &siv_encrypt_ops},
+  {GCRY_CIPHER_MODE_SIV, "SIV dec", &siv_decrypt_ops},
+  {GCRY_CIPHER_MODE_SIV, "SIV auth", &siv_authenticate_ops},
+  {GCRY_CIPHER_MODE_GCM_SIV, "GCM-SIV enc", &gcm_siv_encrypt_ops},
+  {GCRY_CIPHER_MODE_GCM_SIV, "GCM-SIV dec", &gcm_siv_decrypt_ops},
+  {GCRY_CIPHER_MODE_GCM_SIV, "GCM-SIV auth", &gcm_siv_authenticate_ops},
   {GCRY_CIPHER_MODE_POLY1305, "POLY1305 enc", &poly1305_encrypt_ops},
   {GCRY_CIPHER_MODE_POLY1305, "POLY1305 dec", &poly1305_decrypt_ops},
   {GCRY_CIPHER_MODE_POLY1305, "POLY1305 auth", &poly1305_authenticate_ops},
@@ -1311,6 +1763,7 @@ cipher_bench_one (int algo, struct bench_cipher_mode *pmode)
   struct bench_obj obj = { 0 };
   double result;
   unsigned int blklen;
+  unsigned int keylen;
 
   mode.algo = algo;
 
@@ -1319,6 +1772,10 @@ cipher_bench_one (int algo, struct bench_cipher_mode *pmode)
   if (!blklen)
     return;
 
+  keylen = gcry_cipher_get_algo_keylen (algo);
+  if (!keylen)
+    return;
+
   /* Stream cipher? Only test with "ECB" and POLY1305. */
   if (blklen == 1 && (mode.mode != GCRY_CIPHER_MODE_ECB &&
                      mode.mode != GCRY_CIPHER_MODE_POLY1305))
@@ -1337,14 +1794,26 @@ cipher_bench_one (int algo, struct bench_cipher_mode *pmode)
   if (mode.mode == GCRY_CIPHER_MODE_CCM && blklen != GCRY_CCM_BLOCK_LEN)
     return;
 
-  /* GCM has restrictions for block-size */
-  if (mode.mode == GCRY_CIPHER_MODE_GCM && blklen != GCRY_GCM_BLOCK_LEN)
+  /* GCM has restrictions for block-size; not allowed in FIPS mode */
+  if (mode.mode == GCRY_CIPHER_MODE_GCM && (in_fips_mode || blklen != GCRY_GCM_BLOCK_LEN))
     return;
 
   /* XTS has restrictions for block-size */
   if (mode.mode == GCRY_CIPHER_MODE_XTS && blklen != GCRY_XTS_BLOCK_LEN)
     return;
 
+  /* SIV has restrictions for block-size */
+  if (mode.mode == GCRY_CIPHER_MODE_SIV && blklen != GCRY_SIV_BLOCK_LEN)
+    return;
+
+  /* GCM-SIV has restrictions for block-size */
+  if (mode.mode == GCRY_CIPHER_MODE_GCM_SIV && blklen != GCRY_SIV_BLOCK_LEN)
+    return;
+
+  /* GCM-SIV has restrictions for key length */
+  if (mode.mode == GCRY_CIPHER_MODE_GCM_SIV && !(keylen == 16 || keylen == 32))
+    return;
+
   /* Our OCB implementation has restrictions for block-size.  */
   if (mode.mode == GCRY_CIPHER_MODE_OCB && blklen != GCRY_OCB_BLOCK_LEN)
     return;
@@ -1433,7 +1902,7 @@ bench_hash_init (struct bench_obj *obj)
       exit (1);
     }
 
-  obj->priv = hd;
+  obj->hd = hd;
 
   return 0;
 }
@@ -1441,7 +1910,7 @@ bench_hash_init (struct bench_obj *obj)
 static void
 bench_hash_free (struct bench_obj *obj)
 {
-  gcry_md_hd_t hd = obj->priv;
+  gcry_md_hd_t hd = obj->hd;
 
   gcry_md_close (hd);
 }
@@ -1449,7 +1918,7 @@ bench_hash_free (struct bench_obj *obj)
 static void
 bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
 {
-  gcry_md_hd_t hd = obj->priv;
+  gcry_md_hd_t hd = obj->hd;
 
   gcry_md_reset (hd);
   gcry_md_write (hd, buf, buflen);
@@ -1595,7 +2064,7 @@ bench_mac_init (struct bench_obj *obj)
       break;
     }
 
-  obj->priv = hd;
+  obj->hd = hd;
 
   free (key);
   return 0;
@@ -1604,7 +2073,7 @@ bench_mac_init (struct bench_obj *obj)
 static void
 bench_mac_free (struct bench_obj *obj)
 {
-  gcry_mac_hd_t hd = obj->priv;
+  gcry_mac_hd_t hd = obj->hd;
 
   gcry_mac_close (hd);
 }
@@ -1612,7 +2081,7 @@ bench_mac_free (struct bench_obj *obj)
 static void
 bench_mac_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
 {
-  gcry_mac_hd_t hd = obj->priv;
+  gcry_mac_hd_t hd = obj->hd;
   size_t bs;
   char b;
 
@@ -1756,10 +2225,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];
 
   mode.algo = algo;
   mode.subalgo = subalgo;
@@ -1794,31 +2260,7 @@ kdf_bench_one (int algo, int subalgo)
   obj.priv = &mode;
 
   nsecs_per_iteration = do_slope_benchmark (&obj);
-
-  strcpy(cpiter_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 (cpu_ghz > 0.0)
-    {
-      cycles_per_iteration = nsecs_per_iteration * cpu_ghz;
-      double_to_str (cpiter_buf, sizeof (cpiter_buf), cycles_per_iteration);
-    }
-
-  if (csv_mode)
-    {
-      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
-    {
-      printf ("%14s %13s\n", nsecpiter_buf, cpiter_buf);
-    }
+  bench_print_result_nsec_per_iteration (nsecs_per_iteration);
 }
 
 void
@@ -1829,11 +2271,7 @@ kdf_bench (char **argv, int argc)
 
   bench_print_section ("kdf", "KDF");
 
-  if (!csv_mode)
-    {
-      printf (" %-*s | ", 24, "");
-      printf ("%14s %13s\n", "nanosecs/iter", "cycles/iter");
-    }
+  bench_print_header_nsec_per_iteration (24, "");
 
   if (argv && argc)
     {
@@ -1863,17 +2301,643 @@ kdf_bench (char **argv, int argc)
 }
 
 
+/************************************************************ ECC benchmarks. */
+
+#if USE_ECC
+enum bench_ecc_algo
+{
+  ECC_ALGO_ED25519 = 0,
+  ECC_ALGO_ED448,
+  ECC_ALGO_X25519,
+  ECC_ALGO_X448,
+  ECC_ALGO_NIST_P192,
+  ECC_ALGO_NIST_P224,
+  ECC_ALGO_NIST_P256,
+  ECC_ALGO_NIST_P384,
+  ECC_ALGO_NIST_P521,
+  ECC_ALGO_SECP256K1,
+  ECC_ALGO_BRAINP256R1,
+  __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 int
+ecc_algo_fips_allowed (int algo)
+{
+  switch (algo)
+    {
+      case ECC_ALGO_NIST_P224:
+      case ECC_ALGO_NIST_P256:
+      case ECC_ALGO_NIST_P384:
+      case ECC_ALGO_NIST_P521:
+       return 1;
+      case ECC_ALGO_SECP256K1:
+      case ECC_ALGO_BRAINP256R1:
+      case ECC_ALGO_ED25519:
+      case ECC_ALGO_ED448:
+      case ECC_ALGO_X25519:
+      case ECC_ALGO_X448:
+      case ECC_ALGO_NIST_P192:
+      default:
+       return 0;
+    }
+}
+
+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_X25519:
+       return "X25519";
+      case ECC_ALGO_X448:
+       return "X448";
+      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";
+      case ECC_ALGO_BRAINP256R1:
+       return "brainpoolP256r1";
+      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_X25519:
+       return "Curve25519";
+      case ECC_ALGO_X448:
+       return "X448";
+      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";
+      case ECC_ALGO_BRAINP256R1:
+       return "brainpoolP256r1";
+      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_X25519:
+       return 255;
+      case ECC_ALGO_X448:
+       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;
+      case ECC_ALGO_BRAINP256R1:
+       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_oper *oper = obj->priv;
+  struct bench_ecc_mult_hd *hd = obj->hd;
+  gcry_mpi_t y;
+  size_t i;
+
+  (void)buf;
+
+  if (oper->algo == ECC_ALGO_X25519 || oper->algo == ECC_ALGO_X448)
+    {
+      y = NULL;
+    }
+  else
+    {
+      y = hd->y;
+    }
+
+  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, 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;
+      case ECC_ALGO_BRAINP256R1:
+        err = gcry_sexp_build (&hd->key_spec, NULL,
+                               "(genkey (ECDSA (curve brainpoolP256r1)))");
+       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_X25519 || algo == ECC_ALGO_X448 ||
+       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;
+
+  /* Skip not allowed mechanisms */
+  if (in_fips_mode && !ecc_algo_fips_allowed (algo))
+    return;
+
+  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 <mhz>           Set CPU speed for calculating cycles",
-    "                             per bytes results.",
+    "                             per bytes results.  Set as \"auto\"",
+    "                             for auto-detection of CPU speed.",
     "   --disable-hwf <features>  Disable hardware acceleration feature(s)",
     "                             for benchmarking.",
     "   --repetitions <n>         Use N repetitions (default "
@@ -1989,8 +3053,15 @@ main (int argc, char **argv)
          argv++;
          if (argc)
            {
-             cpu_ghz = atof (*argv);
-             cpu_ghz /= 1000;  /* Mhz => Ghz */
+              if (!strcmp (*argv, "auto"))
+                {
+                  auto_ghz = 1;
+                }
+              else
+                {
+                  cpu_ghz = atof (*argv);
+                  cpu_ghz /= 1000;     /* Mhz => Ghz */
+                }
 
              argc--;
              argv++;
@@ -2017,7 +3088,7 @@ main (int argc, char **argv)
        }
     }
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int) verbose);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int) verbose));
 
   if (!gcry_check_version (GCRYPT_VERSION))
     {
@@ -2027,11 +3098,14 @@ main (int argc, char **argv)
     }
 
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
+
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
 
   if (in_regression_test)
     fputs ("Note: " PGM " running in quick regression test mode.\n", stdout);
@@ -2043,6 +3117,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"))
     {
@@ -2076,6 +3151,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);
index 44a8711..a45fc5f 100644 (file)
 #define PGM "benchmark"
 #include "t-common.h"
 
-/* Do encryption tests with large buffers.  */
+/* Do encryption tests with large buffers (100 KiB).  */
 static int large_buffers;
 
+/* Do encryption tests with huge buffers (256 MiB). */
+static int huge_buffers;
+
 /* Number of cipher repetitions.  */
 static int cipher_repetitions;
 
@@ -458,7 +461,7 @@ random_bench (int very_strong)
 
   putchar ('\n');
   if (verbose)
-    xgcry_control (GCRYCTL_DUMP_RANDOM_STATS);
+    xgcry_control ((GCRYCTL_DUMP_RANDOM_STATS));
 }
 
 
@@ -610,7 +613,7 @@ mac_bench ( const char *algoname )
   algo = gcry_mac_map_name (algoname);
   if (!algo)
     {
-      fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname);
+      fprintf (stderr, PGM ": invalid MAC algorithm `%s'\n", algoname);
       exit (1);
     }
 
@@ -743,6 +746,60 @@ static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen)
 }
 
 
+static gcry_error_t
+cipher_encrypt (gcry_cipher_hd_t h, char *out, size_t outsize,
+               const char *in, size_t inlen, size_t max_inlen)
+{
+  gcry_error_t ret;
+
+  while (inlen)
+    {
+      size_t currlen = inlen;
+
+      if (currlen > max_inlen)
+       currlen = max_inlen;
+
+      ret = gcry_cipher_encrypt(h, out, outsize, in, currlen);
+      if (ret)
+       return ret;
+
+      out += currlen;
+      in += currlen;
+      outsize -= currlen;
+      inlen -= currlen;
+    }
+
+  return 0;
+}
+
+
+static gcry_error_t
+cipher_decrypt (gcry_cipher_hd_t h, char *out, size_t outsize,
+               const char *in, size_t inlen, size_t max_inlen)
+{
+  gcry_error_t ret;
+
+  while (inlen)
+    {
+      size_t currlen = inlen;
+
+      if (currlen > max_inlen)
+       currlen = max_inlen;
+
+      ret = gcry_cipher_decrypt(h, out, outsize, in, currlen);
+      if (ret)
+       return ret;
+
+      out += currlen;
+      in += currlen;
+      outsize -= currlen;
+      inlen -= currlen;
+    }
+
+  return 0;
+}
+
+
 static void
 cipher_bench ( const char *algoname )
 {
@@ -760,32 +817,36 @@ cipher_bench ( const char *algoname )
     int mode;
     const char *name;
     int blocked;
+    unsigned int max_inlen;
     void (* const aead_init)(gcry_cipher_hd_t hd, size_t buflen, int authlen);
     int req_blocksize;
     int authlen;
     int noncelen;
     int doublekey;
   } modes[] = {
-    { GCRY_CIPHER_MODE_ECB, "   ECB/Stream", 1 },
-    { GCRY_CIPHER_MODE_CBC, "      CBC", 1 },
-    { GCRY_CIPHER_MODE_CFB, "      CFB", 0 },
-    { GCRY_CIPHER_MODE_OFB, "      OFB", 0 },
-    { GCRY_CIPHER_MODE_CTR, "      CTR", 0 },
-    { GCRY_CIPHER_MODE_XTS, "      XTS", 0,
+    { GCRY_CIPHER_MODE_ECB, "   ECB/Stream", 1, 0xffffffffU },
+    { GCRY_CIPHER_MODE_CBC, " CBC/Poly1305", 1, 0xffffffffU },
+    { GCRY_CIPHER_MODE_CFB, "      CFB", 0, 0xffffffffU },
+    { GCRY_CIPHER_MODE_OFB, "      OFB", 0, 0xffffffffU },
+    { GCRY_CIPHER_MODE_CTR, "      CTR", 0, 0xffffffffU },
+    { GCRY_CIPHER_MODE_XTS, "      XTS", 0, 16 << 20,
       NULL, GCRY_XTS_BLOCK_LEN, 0, 0, 1 },
-    { GCRY_CIPHER_MODE_CCM, "      CCM", 0,
-      ccm_aead_init, GCRY_CCM_BLOCK_LEN, 8 },
-    { GCRY_CIPHER_MODE_GCM, "      GCM", 0,
+    { GCRY_CIPHER_MODE_CCM, "      CCM", 0, 0xffffffffU,
+      ccm_aead_init, GCRY_CCM_BLOCK_LEN, 8, },
+    { GCRY_CIPHER_MODE_GCM, "      GCM", 0, 0xffffffffU,
       NULL, GCRY_GCM_BLOCK_LEN, GCRY_GCM_BLOCK_LEN },
-    { GCRY_CIPHER_MODE_OCB, "      OCB", 1,
+    { GCRY_CIPHER_MODE_OCB, "      OCB", 1, 0xffffffffU,
       NULL, 16, 16, 15 },
-    { GCRY_CIPHER_MODE_STREAM, "", 0 },
+    { GCRY_CIPHER_MODE_EAX, "      EAX", 0, 0xffffffffU,
+      NULL, 0, 8, 8 },
+    { GCRY_CIPHER_MODE_STREAM, "", 0, 0xffffffffU },
+    { GCRY_CIPHER_MODE_POLY1305, "", 0, 0xffffffffU,
+      NULL, 1, 16, 12 },
     {0}
   };
   int modeidx;
   gcry_error_t err = GPG_ERR_NO_ERROR;
 
-
   if (!algoname)
     {
       for (i=1; i < 400; i++)
@@ -794,7 +855,12 @@ cipher_bench ( const char *algoname )
       return;
     }
 
-  if (large_buffers)
+  if (huge_buffers)
+    {
+      allocated_buflen = 256 * 1024 * 1024;
+      repetitions = 4;
+    }
+  else if (large_buffers)
     {
       allocated_buflen = 1024 * 100;
       repetitions = 10;
@@ -867,9 +933,18 @@ cipher_bench ( const char *algoname )
   for (modeidx=0; modes[modeidx].mode; modeidx++)
     {
       size_t modekeylen = keylen * (!!modes[modeidx].doublekey + 1);
+      int is_stream = modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM
+                      || modes[modeidx].mode == GCRY_CIPHER_MODE_POLY1305;
+
+      if ((blklen > 1 && is_stream) || (blklen == 1 && !is_stream))
+        continue;
 
-      if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM)
-          || (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
+      if (modes[modeidx].mode == GCRY_CIPHER_MODE_POLY1305
+          && algo != GCRY_CIPHER_CHACHA20)
+        continue;
+
+      /* GCM is not available in FIPS mode */
+      if (in_fips_mode && modes[modeidx].mode == GCRY_CIPHER_MODE_GCM)
         continue;
 
       if (modes[modeidx].req_blocksize > 0
@@ -943,14 +1018,16 @@ cipher_bench ( const char *algoname )
             {
               (*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen);
               gcry_cipher_final (hd);
-              err = gcry_cipher_encrypt (hd, outbuf, buflen, buf, buflen);
+              err = cipher_encrypt (hd, outbuf, buflen, buf, buflen,
+                                   modes[modeidx].max_inlen);
               if (err)
                 break;
               err = gcry_cipher_gettag (hd, outbuf, modes[modeidx].authlen);
             }
           else
             {
-              err = gcry_cipher_encrypt (hd, outbuf, buflen, buf, buflen);
+              err = cipher_encrypt (hd, outbuf, buflen, buf, buflen,
+                                   modes[modeidx].max_inlen);
             }
         }
       stop_timer ();
@@ -1022,7 +1099,8 @@ cipher_bench ( const char *algoname )
             {
               (*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen);
               gcry_cipher_final (hd);
-              err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen);
+              err = cipher_decrypt (hd, outbuf, buflen, buf, buflen,
+                                   modes[modeidx].max_inlen);
               if (err)
                 break;
               err = gcry_cipher_checktag (hd, outbuf, modes[modeidx].authlen);
@@ -1032,7 +1110,8 @@ cipher_bench ( const char *algoname )
           else
             {
               gcry_cipher_final (hd);
-              err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen);
+              err = cipher_decrypt (hd, outbuf, buflen, buf, buflen,
+                                   modes[modeidx].max_inlen);
             }
         }
       stop_timer ();
@@ -1077,7 +1156,7 @@ rsa_bench (int iterations, int print_header, int no_blinding)
       printf ("RSA %3d bit    ", nbits);
       fflush (stdout);
 
-      if (in_fips_mode && !(nbits == 2048 || nbits == 3072))
+      if (in_fips_mode && nbits < 2048)
         {
           puts ("[skipped in fips mode]");
           continue;
@@ -1240,6 +1319,12 @@ elg_bench (int iterations, int print_header)
       printf ("ELG %d bit             -", p_sizes[i]);
       fflush (stdout);
 
+      if (in_fips_mode)
+        {
+          puts ("[skipped in fips mode]");
+          goto next;
+        }
+
       start_timer ();
       for (j=0; j < iterations; j++)
         {
@@ -1275,6 +1360,7 @@ elg_bench (int iterations, int print_header)
       printf ("   %s  %s\n", elapsed_time (1), timerbuf1);
       fflush (stdout);
 
+    next:
       gcry_sexp_release (plain);
       plain = NULL;
       gcry_sexp_release (enc);
@@ -1348,6 +1434,12 @@ dsa_bench (int iterations, int print_header)
       printf ("DSA %d/%d             -", p_sizes[i], q_sizes[i]);
       fflush (stdout);
 
+      if (in_fips_mode)
+        {
+          puts ("[skipped in fips mode]");
+          goto next;
+        }
+
       start_timer ();
       for (j=0; j < iterations; j++)
         {
@@ -1381,6 +1473,7 @@ dsa_bench (int iterations, int print_header)
       printf ("     %s\n", elapsed_time (1));
       fflush (stdout);
 
+    next:
       gcry_sexp_release (sig);
       gcry_sexp_release (data);
       sig = NULL;
@@ -1400,7 +1493,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;
 
@@ -1417,14 +1510,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)
@@ -1433,6 +1529,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);
@@ -1450,10 +1552,14 @@ 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)))",
-                               p_size == 256 ? "GOST2001-test" : "GOST2012-test");
+                               p_size == 256 ? "GOST2001-test" : "GOST2012-512-test");
       else
         err = gcry_sexp_build (&key_spec, NULL,
                                "(genkey (ECDSA (nbits %d)))", p_size);
@@ -1487,6 +1593,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
@@ -1656,7 +1766,6 @@ main( int argc, char **argv )
 {
   int last_argc = -1;
   int no_blinding = 0;
-  int use_random_daemon = 0;
   int use_secmem = 0;
   int pk_count = 100;
 
@@ -1702,11 +1811,6 @@ main( int argc, char **argv )
           debug++;
           argc--; argv++;
         }
-      else if (!strcmp (*argv, "--use-random-daemon"))
-        {
-          use_random_daemon = 1;
-          argc--; argv++;
-        }
       else if (!strcmp (*argv, "--use-secmem"))
         {
           use_secmem = 1;
@@ -1716,17 +1820,17 @@ main( int argc, char **argv )
         {
           /* This is anyway the default, but we may want to use it for
              debugging. */
-          xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD);
+          xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD));
           argc--; argv++;
         }
       else if (!strcmp (*argv, "--prefer-fips-rng"))
         {
-          xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
+          xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS));
           argc--; argv++;
         }
       else if (!strcmp (*argv, "--prefer-system-rng"))
         {
-          xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
+          xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM));
           argc--; argv++;
         }
       else if (!strcmp (*argv, "--no-blinding"))
@@ -1739,6 +1843,11 @@ main( int argc, char **argv )
           large_buffers = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--huge-buffers"))
+        {
+          huge_buffers = 1;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--cipher-repetitions"))
         {
           argc--; argv++;
@@ -1804,7 +1913,7 @@ main( int argc, char **argv )
         {
           argc--; argv++;
           /* This command needs to be called before gcry_check_version.  */
-          xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
+          xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0));
         }
       else if (!strcmp (*argv, "--progress"))
         {
@@ -1816,7 +1925,7 @@ main( int argc, char **argv )
   if (buffer_alignment < 1 || buffer_alignment > 16)
     die ("value for --alignment must be in the range 1 to 16\n");
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
 
   if (!gcry_check_version (GCRYPT_VERSION))
     {
@@ -1826,20 +1935,17 @@ main( int argc, char **argv )
     }
 
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
 
   if (gcry_fips_mode_active ())
     in_fips_mode = 1;
   else if (!use_secmem)
-    xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-
-  if (use_random_daemon)
-    xgcry_control (GCRYCTL_USE_RANDOM_DAEMON, 1);
+    xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
 
   if (with_progress)
     gcry_set_progress_handler (progress_cb, NULL);
 
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
   if (cipher_repetitions < 1)
     cipher_repetitions = 1;
@@ -1853,7 +1959,7 @@ main( int argc, char **argv )
 
   if ( !argc )
     {
-      xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+      xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
       md_bench (NULL);
       putchar ('\n');
       mac_bench (NULL);
@@ -1875,9 +1981,9 @@ main( int argc, char **argv )
         random_bench ((**argv == 's'));
       else if (argc == 2)
         {
-          xgcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, argv[1]);
+          xgcry_control ((GCRYCTL_SET_RANDOM_SEED_FILE, argv[1]));
           random_bench ((**argv == 's'));
-          xgcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
+          xgcry_control ((GCRYCTL_UPDATE_RANDOM_SEED_FILE));
         }
       else
         fputs ("usage: benchmark [strong]random [seedfile]\n", stdout);
@@ -1912,7 +2018,7 @@ main( int argc, char **argv )
     }
   else if ( !strcmp (*argv, "pubkey"))
     {
-        xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
         rsa_bench (pk_count, 1, no_blinding);
         elg_bench (pk_count, 0);
         dsa_bench (pk_count, 0);
@@ -1920,27 +2026,27 @@ main( int argc, char **argv )
     }
   else if ( !strcmp (*argv, "rsa"))
     {
-        xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
         rsa_bench (pk_count, 1, no_blinding);
     }
   else if ( !strcmp (*argv, "elg"))
     {
-        xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
         elg_bench (pk_count, 1);
     }
   else if ( !strcmp (*argv, "dsa"))
     {
-        xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
         dsa_bench (pk_count, 1);
     }
   else if ( !strcmp (*argv, "ecc"))
     {
-        xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
         ecc_bench (pk_count, 1);
     }
   else if ( !strcmp (*argv, "prime"))
     {
-        xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+        xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
         prime_bench ();
     }
   else
diff --git a/tests/cavs_driver.pl b/tests/cavs_driver.pl
deleted file mode 100755 (executable)
index bc93feb..0000000
+++ /dev/null
@@ -1,2243 +0,0 @@
-#!/usr/bin/env perl
-#
-# $Id: cavs_driver.pl 1497 2009-01-22 14:01:29Z smueller $
-#
-# CAVS test driver (based on the OpenSSL driver)
-# Written by: Stephan Müller <sm@atsec.com>
-# Copyright (c) atsec information security corporation
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-#                            NO WARRANTY
-#
-#    BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-#    FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-#    OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-#    PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-#    OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-#    MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-#    TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-#    PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-#    REPAIR OR CORRECTION.
-#
-#    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-#    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-#    REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-#    INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-#    OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-#    TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-#    YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-#    PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-#    POSSIBILITY OF SUCH DAMAGES.
-#
-#
-# test execution instruction:
-# 1. get the request files from the lab
-# 2. call each request file from 1. with this program:
-#      $0 <FILE>.rep
-# 3. send the resulting file <FILE>.rsp to the lab
-#
-#
-# Test should be easily adoptable to other implementations
-# See the first functions for this task
-#
-# Following tests are covered (others may also be covered
-# but have not been tested)
-#
-# AES
-#      [CBC|CFB128|ECB|OFB]GFSbox[128|192|256]
-#      [CBC|CFB128|ECB|OFB]MCT[128|192|256]
-#      [CBC|CFB128|ECB|OFB]VarKey[128|192|256]
-#      [CBC|CFB128|ECB|OFB]KeySbox[128|192|256]
-#      [CBC|CFB128|ECB|OFB]MMT[128|192|256]
-#      [CBC|CFB128|ECB|OFB]VarTxt[128|192|256]
-#
-# RSA
-#      SigGen[15|RSA]
-#      SigVer15
-#      (SigVerRSA is not applicable for OpenSSL as X9.31 padding
-#              is not done through openssl dgst)
-#      KeyGen RSA X9.31
-#
-# SHA
-#      SHA[1|224|256|384|512]ShortMsg
-#      SHA[1|224|256|384|512]LongMsg
-#      SHA[1|224|256|384|512]Monte
-#
-# HMAC (SHA - caveat: we only support hash output equal to the block size of
-#      of the hash - we do not support truncation of the hash; to support
-#      that, we first need to decipher the HMAC.req file - see hmac_kat() )
-#      HMAC
-#
-# TDES
-#      T[CBC|CFB??|ECB|OFB]Monte[1|2|3]
-#      T[CBC|CFB??|ECB|OFB]permop
-#      T[CBC|CFB??|ECB|OFB]MMT[1|2|3]
-#      T[CBC|CFB??|ECB|OFB]subtab
-#      T[CBC|CFB??|ECB|OFB]varkey
-#      T[CBC|CFB??|ECB|OFB]invperm
-#      T[CBC|CFB??|ECB|OFB]vartext
-#
-# ANSI X9.31 RNG
-#      ANSI931_AES128MCT
-#      ANSI931_AES128VST
-#
-# DSA
-#      PQGGen
-#      SigGen
-#      SigVer
-#
-# RC4 (atsec developed tests)
-#      RC4KeyBD
-#      RC4MCT
-#      RC4PltBD
-#      RC4REGT
-#
-
-use strict;
-use warnings;
-use IPC::Open2;
-use Getopt::Std;
-use MIME::Base64;
-
-# Contains the command line options
-my %opt;
-
-#################################################################
-##### Central interface functions to the external ciphers #######
-#################################################################
-# Only these interface routines should be changed in case of
-# porting to a new cipher library
-#
-# For porting to a new library, create implementation of these functions
-# and then add pointers to the respective implementation of each
-# function to the given variables.
-
-# common encryption/decryption routine
-# $1 key in hex form (please note for 3DES: even when ede3 for three
-#    independent ciphers is given with the cipher specification, we hand in
-#    either one key for k1 = k2 = k3, two keys which are concatinated for
-#    k1 = k3, k2 independent, or three keys which are concatinated for
-#    k1, k2, k3 independent)
-# $2 iv in hex form
-# $3 cipher - the cipher string is defined as specified in the openssl
-#    enc(1ssl) specification for the option "-ciphername"
-#    (e.g. aes-128-cbc or des-ede3-cbc)
-# $4 encrypt=1/decrypt=0
-# $5 de/encrypted data in hex form
-# return en/decrypted data in hex form
-my $encdec;
-
-#
-# Derive an RSA key from the given X9.31 parameters.
-# $1: modulus size
-# $2: E   in hex form
-# $3: Xp1 in hex form
-# $4: Xp2 in hex form
-# $5: Xp  in hex form
-# $6: Xq1 in hex form
-# $7: Xq2 in hex form
-# $8: Xq  in hex form
-# return: string with the calculated values in hex format, where each value
-#        is separated from the previous with a \n in the following order:
-#         P\n
-#         Q\n
-#         N\n
-#         D\n
-my $rsa_derive;
-
-# Sign a message with RSA
-# $1: data to be signed in hex form
-# $2: Hash algo
-# $3: Key file in PEM format with the private key
-# return: digest in hex format
-my $rsa_sign;
-
-# Verify a message with RSA
-# $1: data to be verified in hex form
-# $2: hash algo
-# $3: file holding the public RSA key in PEM format
-# $4: file holding the signature in binary form
-# return: 1 == verified / 0 == not verified
-my $rsa_verify;
-
-# generate a new private RSA key with the following properties:
-#      exponent is 65537
-#      PEM format
-# $1 key size in bit
-# $2 keyfile name
-# return: nothing, but file created
-my $gen_rsakey;
-
-# Creating a hash
-# $1: Plaintext in hex form
-# $2: hash type in the form documented in openssl's dgst(1ssl) - e.g.
-#     sha1, sha224, sha256, sha384, sha512
-# return: hash in hex form
-my $hash;
-
-# supplying the call to the external cipher implementation
-# that is being used to keep STDIN and STDOUT open
-# to maintain the state of the block chaining
-# $1: cipher
-# $2: 1=encryption, 0=decryption
-# $3: buffersize needed for openssl
-# $4: encryption key in binary form
-# $5: IV in binary form
-# return: command line to execute the application
-my $state_cipher;
-# the only difference of the DES version is that it implements the inner loop
-# of the TDES tests
-my $state_cipher_des;
-
-# supplying the call to the external cipher implementation
-# that is being used to keep STDIN and STDOUT open
-# to maintain the state of the RNG with its seed
-#
-# input holds seed values
-# $1: cipher key in hex format
-# $2: DT value in hex format
-# $3: V value in hex format
-#
-# return: command line to execute the application
-#
-# the application is expected to deliver random values on STDOUT - the script
-# reads 128 bits repeatedly where the state of the RNG must be retained
-# between the reads. The output of the RNG on STDOUT is assumed to be binary.
-my $state_rng;
-
-# Generate an HMAC based on SHAx
-# $1: Key to be used for the HMAC in hex format
-# $2: length of the hash to be calculated in bits
-# $3: Message for which the HMAC shall be calculated in hex format
-# $4: hash type (1 - SHA1, 224 - SHA224, and so on)
-# return: calculated HMAC in hex format
-my $hmac;
-
-#
-# Generate the P, Q, G, Seed, counter, h (value used to generate g) values
-# for DSA
-# $1: modulus size
-# return: string with the calculated values in hex format, where each value
-#        is separated from the previous with a \n in the following order:
-#         P\n
-#         Q\n
-#         G\n
-#         Seed\n
-#         counter\n
-#         h
-my $dsa_pqggen;
-
-#
-# Generate an DSA public key from the provided parameters:
-# $1: Name of file to create
-# $2: P in hex form
-# $3: Q in hex form
-# $4: G in hex form
-# $5: Y in hex form
-my $dsa_genpubkey;
-
-# Verify a message with DSA
-# $1: data to be verified in hex form
-# $2: file holding the public DSA key in PEM format
-# $3: R value of the signature
-# $4: S value of the signature
-# return: 1 == verified / 0 == not verified
-my $dsa_verify;
-
-# generate a new DSA key with the following properties:
-#      PEM format
-# $1 keyfile name
-# return: file created, hash with keys of P, Q, G in hex format
-my $gen_dsakey;
-
-# Sign a message with DSA
-# $1: data to be signed in hex form
-# $2: Key file in PEM format with the private key
-# return: hash of digest information in hex format with Y, R, S as keys
-my $dsa_sign;
-
-################################################################
-##### OpenSSL interface functions
-################################################################
-sub openssl_encdec($$$$$) {
-       my $key=shift;
-       my $iv=shift;
-       my $cipher=shift;
-       my $enc = (shift) ? "-e" : "-d";
-       my $data=shift;
-
-       # We only invoke the driver with the IV parameter, if we have
-       # an IV, otherwise, we skip it
-       $iv = "-iv $iv" if ($iv);
-
-       $data=hex2bin($data);
-       my $program="openssl enc -$cipher -nopad -nosalt -K $key $enc $iv";
-       $program = "rc4 -k $key" if $opt{'R'}; #for ARCFOUR, no IV must be given
-       $data=pipe_through_program($data,$program);
-       return bin2hex($data);
-}
-
-sub openssl_rsa_sign($$$) {
-       my $data = shift;
-       my $cipher = shift;
-       my $keyfile = shift;
-
-       $data=hex2bin($data);
-       die "ARCFOUR not available for RSA" if $opt{'R'};
-       $data=pipe_through_program($data,
-               "openssl dgst -$cipher -binary -sign $keyfile");
-       return bin2hex($data);
-}
-
-sub openssl_rsa_verify($$$$) {
-       my $data = shift;
-       my $cipher = shift;
-       my $keyfile = shift;
-       my $sigfile = shift;
-
-       $data = hex2bin($data);
-       die "ARCFOUR not available for RSA" if $opt{'R'};
-       $data = pipe_through_program($data,
-               "openssl dgst -$cipher -binary -verify $keyfile -signature $sigfile");
-
-       # Parse through the OpenSSL output information
-       return ($data =~ /OK/);
-}
-
-sub openssl_gen_rsakey($$) {
-       my $keylen = shift;
-       my $file = shift;
-
-       die "ARCFOUR not available for RSA" if $opt{'R'};
-       # generating of a key with exponent 0x10001
-       my @args = ("openssl", "genrsa", "-F4", "-out", "$file", "$keylen");
-        system(@args) == 0
-               or die "system @args failed: $?";
-       die "system @args failed: file $file not created" if (! -f $file);
-}
-
-sub openssl_hash($$) {
-       my $pt = shift;
-       my $cipher = shift;
-
-       die "ARCFOUR not available for hashes" if $opt{'R'};
-       my $hash = hex2bin($pt);
-       #bin2hex not needed as the '-hex' already converts it
-       return pipe_through_program($hash, "openssl dgst -$cipher -hex");
-}
-
-sub openssl_state_cipher($$$$$) {
-       my $cipher = shift;
-       my $encdec = shift;
-       my $bufsize = shift;
-       my $key = shift;
-       my $iv = shift;
-
-       my $enc = $encdec ? "-e": "-d";
-
-       # We only invoke the driver with the IV parameter, if we have
-       # an IV, otherwise, we skip it
-       $iv = "-iv ".bin2hex($iv) if ($iv);
-
-       my $out = "openssl enc -'$cipher' $enc -nopad -nosalt -bufsize $bufsize -K ".bin2hex($key)." $iv";
-       #for ARCFOUR, no IV must be given
-       $out = "rc4 -k " . bin2hex($key) if $opt{'R'};
-       return $out;
-}
-
-###### End of OpenSSL interface implementation ############
-
-###########################################################
-###### libgcrypt implementation
-###########################################################
-sub libgcrypt_encdec($$$$$) {
-       my $key=shift;
-       my $iv=shift;
-       my $cipher=shift;
-       my $enc = (shift) ? "encrypt" : "decrypt";
-       my $data=shift;
-
-       # We only invoke the driver with the IV parameter, if we have
-       # an IV, otherwise, we skip it
-       $iv = "--iv $iv" if ($iv);
-
-       my $program="fipsdrv --key $key $iv --algo $cipher $enc";
-
-       return pipe_through_program($data,$program);
-
-}
-
-sub libgcrypt_rsa_derive($$$$$$$$) {
-       my $n   = shift;
-       my $e   = shift;
-       my $xp1 = shift;
-       my $xp2 = shift;
-       my $xp  = shift;
-       my $xq1 = shift;
-       my $xq2 = shift;
-       my $xq  = shift;
-       my $sexp;
-       my @tmp;
-
-       $n = sprintf ("%u", $n);
-       $e = sprintf ("%u", hex($e));
-       $sexp = "(genkey(rsa(nbits " . sprintf ("%u:%s", length($n), $n) . ")"
-               . "(rsa-use-e " . sprintf ("%u:%s", length($e), $e) . ")"
-               . "(derive-parms"
-               . "(Xp1 #$xp1#)"
-               . "(Xp2 #$xp2#)"
-               . "(Xp  #$xp#)"
-               . "(Xq1 #$xq1#)"
-               . "(Xq2 #$xq2#)"
-               . "(Xq  #$xq#))))\n";
-
-       return pipe_through_program($sexp, "fipsdrv rsa-derive");
-}
-
-
-sub libgcrypt_rsa_sign($$$) {
-       my $data = shift;
-       my $hashalgo = shift;
-       my $keyfile = shift;
-
-       die "ARCFOUR not available for RSA" if $opt{'R'};
-
-       return pipe_through_program($data,
-               "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile rsa-sign");
-}
-
-sub libgcrypt_rsa_verify($$$$) {
-       my $data = shift;
-       my $hashalgo = shift;
-       my $keyfile = shift;
-       my $sigfile = shift;
-
-       die "ARCFOUR not available for RSA" if $opt{'R'};
-       $data = pipe_through_program($data,
-               "fipsdrv --pkcs1 --algo $hashalgo --key $keyfile --signature $sigfile rsa-verify");
-
-       # Parse through the output information
-       return ($data =~ /GOOD signature/);
-}
-
-sub libgcrypt_gen_rsakey($$) {
-       my $keylen = shift;
-       my $file = shift;
-
-       die "ARCFOUR not available for RSA" if $opt{'R'};
-       my @args = ("fipsdrv --keysize $keylen rsa-gen > $file");
-       system(@args) == 0
-               or die "system @args failed: $?";
-       die "system @args failed: file $file not created" if (! -f $file);
-}
-
-sub libgcrypt_hash($$) {
-       my $pt = shift;
-       my $hashalgo = shift;
-
-       my $program = "fipsdrv --algo $hashalgo digest";
-       die "ARCFOUR not available for hashes" if $opt{'R'};
-
-       return pipe_through_program($pt, $program);
-}
-
-sub libgcrypt_state_cipher($$$$$) {
-       my $cipher = shift;
-       my $enc = (shift) ? "encrypt": "decrypt";
-       my $bufsize = shift;
-       my $key = shift;
-       my $iv = shift;
-
-       # We only invoke the driver with the IV parameter, if we have
-       # an IV, otherwise, we skip it
-       $iv = "--iv ".bin2hex($iv) if ($iv);
-
-       my $program="fipsdrv --binary --key ".bin2hex($key)." $iv --algo '$cipher' --chunk '$bufsize' $enc";
-
-       return $program;
-}
-
-sub libgcrypt_state_cipher_des($$$$$) {
-       my $cipher = shift;
-       my $enc = (shift) ? "encrypt": "decrypt";
-       my $bufsize = shift;
-       my $key = shift;
-       my $iv = shift;
-
-       # We only invoke the driver with the IV parameter, if we have
-       # an IV, otherwise, we skip it
-       $iv = "--iv ".bin2hex($iv) if ($iv);
-
-       my $program="fipsdrv --algo '$cipher' --mct-server $enc";
-
-       return $program;
-}
-
-sub libgcrypt_state_rng($$$) {
-       my $key = shift;
-       my $dt = shift;
-       my $v = shift;
-
-       return "fipsdrv --binary --loop --key $key --iv $v --dt $dt random";
-}
-
-sub libgcrypt_hmac($$$$) {
-       my $key = shift;
-       my $maclen = shift;
-       my $msg = shift;
-       my $hashtype = shift;
-
-       my $program = "fipsdrv --key $key --algo $hashtype hmac-sha";
-       return pipe_through_program($msg, $program);
-}
-
-sub libgcrypt_dsa_pqggen($) {
-       my $mod = shift;
-
-       my $program = "fipsdrv --keysize $mod dsa-pqg-gen";
-       return pipe_through_program("", $program);
-}
-
-sub libgcrypt_gen_dsakey($) {
-       my $file = shift;
-
-       my $program = "fipsdrv --keysize 1024 --key $file dsa-gen";
-       my $tmp;
-       my %ret;
-
-       die "ARCFOUR not available for DSA" if $opt{'R'};
-
-       $tmp = pipe_through_program("", $program);
-       die "dsa key gen failed: file $file not created" if (! -f $file);
-
-       @ret{'P', 'Q', 'G', 'Seed', 'c', 'H'} = split(/\n/, $tmp);
-       return %ret;
-}
-
-sub libgcrypt_dsa_genpubkey($$$$$) {
-       my $filename = shift;
-       my $p = shift;
-       my $q = shift;
-       my $g = shift;
-       my $y = shift;
-
-       my $sexp;
-
-       $sexp = "(public-key(dsa(p #$p#)(q #$q#)(g #$g#)(y #$y#)))";
-
-       open(FH, ">", $filename) or die;
-       print FH $sexp;
-       close FH;
-}
-
-sub libgcrypt_dsa_sign($$) {
-       my $data = shift;
-       my $keyfile = shift;
-       my $tmp;
-       my %ret;
-
-       die "ARCFOUR not available for DSA" if $opt{'R'};
-
-       $tmp = pipe_through_program($data, "fipsdrv --key $keyfile dsa-sign");
-       @ret{'Y', 'R', 'S'} = split(/\n/, $tmp);
-       return %ret;
-}
-
-sub libgcrypt_dsa_verify($$$$) {
-       my $data = shift;
-       my $keyfile = shift;
-       my $r = shift;
-       my $s = shift;
-
-       my $ret;
-
-       die "ARCFOUR not available for DSA" if $opt{'R'};
-
-       my $sigfile = "$keyfile.sig";
-       open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?";
-       print FH "(sig-val(dsa(r #$r#)(s #$s#)))";
-       close FH;
-
-       $ret = pipe_through_program($data,
-               "fipsdrv --key $keyfile --signature $sigfile dsa-verify");
-       unlink ($sigfile);
-       # Parse through the output information
-       return ($ret =~ /GOOD signature/);
-}
-
-######### End of libgcrypt implementation ################
-
-################################################################
-###### Vendor1 interface functions
-################################################################
-
-sub vendor1_encdec($$$$$) {
-       my $key=shift;
-       my $iv=shift;
-       my $cipher=shift;
-       my $enc = (shift) ? "encrypt" : "decrypt";
-       my $data=shift;
-
-       $data=hex2bin($data);
-       my $program = "./aes $enc $key";
-       $data=pipe_through_program($data,$program);
-       return bin2hex($data);
-}
-
-sub vendor1_state_cipher($$$$$) {
-       my $cipher = shift;
-       my $encdec = shift;
-       my $bufsize = shift;
-       my $key = shift;
-       my $iv = shift;
-
-       $key = bin2hex($key);
-       my $enc = $encdec ? "encrypt": "decrypt";
-       my $out = "./aes $enc $key $bufsize";
-       return $out;
-}
-
-##### No other interface functions below this point ######
-##########################################################
-
-##########################################################
-# General helper routines
-
-# Executing a program by feeding STDIN and retrieving
-# STDOUT
-# $1: data string to be piped to the app on STDIN
-# rest: program and args
-# returns: STDOUT of program as string
-sub pipe_through_program($@) {
-       my $in = shift;
-       my @args = @_;
-
-       my ($CO, $CI);
-       my $pid = open2($CO, $CI, @args);
-
-       my $out = "";
-       my $len = length($in);
-       my $first = 1;
-       while (1) {
-               my $rin = "";
-               my $win = "";
-               # Output of prog is FD that we read
-               vec($rin,fileno($CO),1) = 1;
-               # Input of prog is FD that we write
-               # check for $first is needed because we can have NULL input
-               # that is to be written to the app
-               if ( $len > 0 || $first) {
-                       (vec($win,fileno($CI),1) = 1);
-                       $first=0;
-               }
-               # Let us wait for 100ms
-               my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1);
-               if ( $wout ) {
-                       my $written = syswrite($CI, $in, $len);
-                       die "broken pipe" if !defined $written;
-                       $len -= $written;
-                       substr($in, 0, $written) = "";
-                       if ($len <= 0) {
-                               close $CI or die "broken pipe: $!";
-                       }
-               }
-               if ( $rout ) {
-                       my $tmp_out = "";
-                       my $bytes_read = sysread($CO, $tmp_out, 4096);
-                       $out .= $tmp_out;
-                       last if ($bytes_read == 0);
-               }
-       }
-       close $CO or die "broken pipe: $!";
-       waitpid $pid, 0;
-
-       return $out;
-}
-
-#
-# convert ASCII hex to binary input
-# $1 ASCII hex
-# return binary representation
-sub hex2bin($) {
-       my $in = shift;
-       my $len = length($in);
-       $len = 0 if ($in eq "00");
-       return pack("H$len", "$in");
-}
-
-#
-# convert binary input to ASCII hex
-# $1 binary value
-# return ASCII hex representation
-sub bin2hex($) {
-       my $in = shift;
-       my $len = length($in)*2;
-       return unpack("H$len", "$in");
-}
-
-# $1: binary byte (character)
-# returns: binary byte with odd parity using low bit as parity bit
-sub odd_par($) {
-       my $in = ord(shift);
-       my $odd_count=0;
-       for(my $i=1; $i<8; $i++) {
-               $odd_count++ if ($in & (1<<$i));
-       }
-
-       my $out = $in;
-       if ($odd_count & 1) { # check if parity is already odd
-               $out &= ~1; # clear the low bit
-       } else {
-               $out |= 1; # set the low bit
-       }
-
-       return chr($out);
-}
-
-# DES keys uses only the 7 high bits of a byte, the 8th low bit
-# is the parity bit
-# as the new key is calculated from oldkey XOR cipher in the MCT test,
-# the parity is not really checked and needs to be set to match
-# expectation (OpenSSL does not really care, but the FIPS
-# test result is expected that the key has the appropriate parity)
-# $1: arbitrary binary string
-# returns: string with odd parity set in low bit of each byte
-sub fix_key_parity($) {
-       my $in = shift;
-       my $out = "";
-       for (my $i = 0; $i < length($in); $i++) {
-               $out .= odd_par(substr($in, $i, 1));
-       }
-
-       return $out;
-}
-
-####################################################
-# DER/PEM utility functions
-# Cf. http://www.columbia.edu/~ariel/ssleay/layman.html
-
-# Convert unsigned integer to base256 bigint bytes
-# $1 integer
-# returns base256 octet string
-sub int_base256_unsigned($) {
-       my $n = shift;
-
-       my $out = chr($n & 255);
-       while ($n>>=8) {
-               $out = chr($n & 255) . $out;
-       }
-
-       return $out;
-}
-
-# Convert signed integer to base256 bigint bytes
-# $1 integer
-# returns base256 octet string
-sub int_base256_signed($) {
-       my $n = shift;
-       my $negative = ($n < 0);
-
-       if ($negative) {
-               $n = -$n-1;
-       }
-
-       my $out = int_base256_unsigned($n);
-
-       if (ord(substr($out, 0, 1)) & 128) {
-               # it's supposed to be positive but has sign bit set,
-               # add a leading zero
-               $out = chr(0) . $out;
-       }
-
-       if ($negative) {
-               my $neg = chr(255) x length($out);
-               $out ^= $neg;
-       }
-
-       return $out;
-}
-
-# Length header for specified DER object length
-# $1 length as integer
-# return octet encoding for length
-sub der_len($) {
-       my $len = shift;
-
-       if ($len <= 127) {
-               return chr($len);
-       } else {
-               my $blen = int_base256_unsigned($len);
-
-               return chr(128 | length($blen)) . $blen;
-       }
-}
-
-# Prepend length header to object
-# $1 object as octet sequence
-# return length header for object followed by object as octets
-sub der_len_obj($) {
-       my $x = shift;
-
-       return der_len(length($x)) . $x;
-}
-
-# DER sequence
-# $* objects
-# returns DER sequence consisting of the objects passed as arguments
-sub der_seq {
-       my $seq = join("", @_);
-       return chr(0x30) . der_len_obj($seq);
-}
-
-# DER bitstring
-# $1 input octets (must be full octets, fractional octets not supported)
-# returns input encapsulated as bitstring
-sub der_bitstring($) {
-       my $x = shift;
-
-       $x = chr(0) . $x;
-
-       return chr(0x03) . der_len_obj($x);
-}
-
-# base-128-encoded integer, used for object numbers.
-# $1 integer
-# returns octet sequence
-sub der_base128($) {
-       my $n = shift;
-
-       my $out = chr($n & 127);
-
-       while ($n>>=7) {
-               $out = chr(128 | ($n & 127)) . $out;
-       }
-
-       return $out;
-}
-
-# Generating the PEM certificate string
-# (base-64-encoded DER string)
-# $1 DER string
-# returns octet sequence
-sub pem_cert($) {
-       my $n = shift;
-
-       my $out = "-----BEGIN PUBLIC KEY-----\n";
-       $out .= encode_base64($n);
-       $out .= "-----END PUBLIC KEY-----\n";
-
-       return $out;
-}
-
-# DER object identifier
-# $* sequence of id numbers
-# returns octets
-sub der_objectid {
-       my $v1 = shift;
-       my $v2 = shift;
-
-       my $out = chr(40*$v1 + $v2) . join("", map { der_base128($_) } @_);
-
-       return chr(0x06) . der_len_obj($out);
-}
-
-# DER signed integer
-# $1 number as octet string (base 256 representation, high byte first)
-# returns number in DER integer encoding
-sub der_bigint($) {
-       my $x = shift;
-
-       return chr(0x02) . der_len_obj($x);
-}
-
-# DER positive integer with leading zeroes stripped
-# $1 number as octet string (base 256 representation, high byte first)
-# returns number in DER integer encoding
-sub der_pos_bigint($) {
-       my $x = shift;
-
-       # strip leading zero digits
-       $x =~ s/^[\0]+//;
-
-       # need to prepend a zero if high bit set, since it would otherwise be
-       # interpreted as a negative number. Also needed for number 0.
-       if (!length($x) || ord(substr($x, 0, 1)) >= 128) {
-               $x = chr(0) . $x;
-       }
-
-       return der_bigint($x);
-}
-
-# $1 number as signed integer
-# returns number as signed DER integer encoding
-sub der_int($) {
-       my $n = shift;
-
-       return der_bigint(int_base256_signed($n));
-}
-
-# the NULL object constant
-sub der_null() {
-       return chr(0x05) . chr(0x00);
-}
-
-# Unit test helper
-# $1 calculated result
-# $2 expected result
-# no return value, dies if results differ, showing caller's line number
-sub der_test($$) {
-       my $actual = bin2hex(shift);
-       my $expected = shift;
-
-       my @caller = caller;
-       $actual eq $expected or die "Error:line $caller[2]:assertion failed: "
-               ."$actual != $expected\n";
-}
-
-# Unit testing for the DER encoding functions
-# Examples from http://www.columbia.edu/~ariel/ssleay/layman.html
-# No input, no output. Dies if unit tests fail.
-sub der_unit_test {
-       ## uncomment these if you want to test the test framework
-       #print STDERR "Unit test running\n";
-       #der_test chr(0), "42";
-
-       der_test der_null, "0500";
-
-       # length bytes
-       der_test der_len(1), "01";
-       der_test der_len(127), "7f";
-       der_test der_len(128), "8180";
-       der_test der_len(256), "820100";
-       der_test der_len(65536), "83010000";
-
-       # bigint
-       der_test der_bigint(chr(0)), "020100";
-       der_test der_bigint(chr(128)), "020180"; # -128
-       der_test der_pos_bigint(chr(128)), "02020080"; # +128
-       der_test der_pos_bigint(chr(0).chr(0).chr(1)), "020101";
-       der_test der_pos_bigint(chr(0)), "020100";
-
-       # integers (tests base256 conversion)
-       der_test der_int(     0), "020100";
-       der_test der_int(   127), "02017f";
-       der_test der_int(   128), "02020080";
-       der_test der_int(   256), "02020100";
-       der_test der_int(    -1), "0201ff";
-       der_test der_int(  -128), "020180";
-       der_test der_int(  -129), "0202ff7f";
-       der_test der_int(-65536), "0203ff0000";
-       der_test der_int(-65537), "0203feffff";
-
-       # object encoding, "RSA Security"
-       der_test der_base128(840), "8648";
-       der_test der_objectid(1, 2, 840, 113549), "06062a864886f70d";
-
-       # Combinations
-       der_test der_bitstring("ABCD"), "03050041424344";
-       der_test der_bitstring(der_null), "0303000500";
-       der_test der_seq(der_int(0), der_null), "30050201000500";
-
-       # The big picture
-       der_test der_seq(der_seq(der_objectid(1, 2, 840, 113549), der_null),
-                        der_bitstring(der_seq(der_pos_bigint(chr(5)),
-                                              der_pos_bigint(chr(3))))),
-                "3017300a06062a864886f70d05000309003006020105020103";
-}
-
-####################################################
-# OpenSSL missing functionality workarounds
-
-## Format of an RSA public key:
-#    0:d=0  hl=3 l= 159 cons: SEQUENCE
-#    3:d=1  hl=2 l=  13 cons:  SEQUENCE
-#    5:d=2  hl=2 l=   9 prim:   OBJECT            :rsaEncryption
-#   16:d=2  hl=2 l=   0 prim:   NULL
-#   18:d=1  hl=3 l= 141 prim:  BIT STRING
-#                              [ sequence: INTEGER (n), INTEGER (e) ]
-
-# generate RSA pub key in PEM format
-# $1: filename where PEM key is to be stored
-# $2: n of the RSA key in hex
-# $3: e of the RSA key in hex
-# return: nothing, but file created
-sub gen_pubrsakey($$$) {
-       my $filename=shift;
-       my $n = shift;
-       my $e = shift;
-
-       # make sure the DER encoder works ;-)
-       der_unit_test();
-
-       # generate DER encoding of the public key
-
-       my $rsaEncryption = der_objectid(1, 2, 840, 113549, 1, 1, 1);
-
-       my $der = der_seq(der_seq($rsaEncryption, der_null),
-                         der_bitstring(der_seq(der_pos_bigint(hex2bin($n)),
-                                               der_pos_bigint(hex2bin($e)))));
-
-       open(FH, ">", $filename) or die;
-       print FH pem_cert($der);
-       close FH;
-
-}
-
-# generate RSA pub key in PEM format
-#
-# This implementation uses "openssl asn1parse -genconf" which was added
-# in openssl 0.9.8. It is not available in older openssl versions.
-#
-# $1: filename where PEM key is to be stored
-# $2: n of the RSA key in hex
-# $3: e of the RSA key in hex
-# return: nothing, but file created
-sub gen_pubrsakey_using_openssl($$$) {
-       my $filename=shift;
-       my $n = shift;
-       my $e = shift;
-
-       my $asn1 = "asn1=SEQUENCE:pubkeyinfo
-
-[pubkeyinfo]
-algorithm=SEQUENCE:rsa_alg
-pubkey=BITWRAP,SEQUENCE:rsapubkey
-
-[rsa_alg]
-algorithm=OID:rsaEncryption
-parameter=NULL
-
-[rsapubkey]
-n=INTEGER:0x$n
-
-e=INTEGER:0x$e";
-
-       open(FH, ">$filename.cnf") or die "Cannot create file $filename.cnf: $?";
-       print FH $asn1;
-       close FH;
-       my @args = ("openssl", "asn1parse", "-genconf", "$filename.cnf", "-noout", "-out", "$filename.der");
-       system(@args) == 0 or die "system @args failed: $?";
-       @args = ("openssl", "rsa", "-inform", "DER", "-in", "$filename.der",
-                "-outform", "PEM", "-pubin", "-pubout", "-out", "$filename");
-       system(@args) == 0 or die "system @args failed: $?";
-       die "RSA PEM formatted key file $filename was not created"
-               if (! -f $filename);
-
-       unlink("$filename.cnf");
-       unlink("$filename.der");
-}
-
-############################################
-# Test cases
-
-# This is the Known Answer Test
-# $1: the string that we have to put in front of the key
-#     when printing the key
-# $2: crypto key1 in hex form
-# $3: crypto key2 in hex form (TDES, undef otherwise)
-# $4: crypto key3 in hex form (TDES, undef otherwise)
-# $5: IV in hex form
-# $6: Plaintext (enc=1) or Ciphertext (enc=0) in hex form
-# $7: cipher
-# $8: encrypt=1/decrypt=0
-# return: string formatted as expected by CAVS
-sub kat($$$$$$$$) {
-       my $keytype = shift;
-       my $key1 = shift;
-       my $key2 = shift;
-       my $key3 = shift;
-       my $iv = shift;
-       my $pt = shift;
-       my $cipher = shift;
-       my $enc = shift;
-
-       my $out = "";
-
-       $out .= "$keytype = $key1\n";
-
-       # this is the concardination of the keys for 3DES
-       if (defined($key2)) {
-               $out .= "KEY2 = $key2\n";
-               $key1 = $key1 . $key2;
-       }
-       if (defined($key3)) {
-               $out .= "KEY3 = $key3\n";
-               $key1= $key1 . $key3;
-       }
-
-       $out .= "IV = $iv\n" if (defined($iv) && $iv ne "");
-       if ($enc) {
-               $out .= "PLAINTEXT = $pt\n";
-               $out .= "CIPHERTEXT = " . &$encdec($key1, $iv, $cipher, 1, $pt) . "\n";
-       } else {
-               $out .= "CIPHERTEXT = $pt\n";
-               $out .= "PLAINTEXT = " . &$encdec($key1, $iv, $cipher, 0, $pt) . "\n";
-       }
-
-       return $out;
-}
-
-# This is the Known Answer Test for Hashes
-# $1: Plaintext in hex form
-# $2: hash
-# $3: hash length (undef if not applicable)
-# return: string formatted as expected by CAVS
-sub hash_kat($$$) {
-       my $pt = shift;
-       my $cipher = shift;
-       my $len = shift;
-
-       my $out = "";
-       $out .= "Len = $len\n" if (defined($len));
-       $out .= "Msg = $pt\n";
-
-       $pt = "" if(!$len);
-       $out .= "MD = " . &$hash($pt, $cipher) . "\n";
-       return $out;
-}
-
-# Known Answer Test for HMAC hash
-# $1: key length in bytes
-# $2: MAC length in bytes
-# $3: key for HMAC in hex form
-# $4: message to be hashed
-# return: string formatted as expected by CAVS
-sub hmac_kat($$$$) {
-       my $klen = shift;
-       my $tlen = shift;
-       my $key  = shift;
-       my $msg  = shift;
-
-       # XXX this is a hack - we need to decipher the HMAC REQ files in a more
-       # sane way
-       #
-       # This is a conversion table from the expected hash output size
-       # to the assumed hash type - we only define here the block size of
-       # the underlying hashes and do not allow any truncation
-       my %hashtype = (
-               20 => 1,
-               28 => 224,
-               32 => 256,
-               48 => 384,
-               64 => 512
-       );
-
-       die "Hash output size $tlen is not supported!"
-               if(!defined($hashtype{$tlen}));
-
-       my $out = "";
-       $out .= "Klen = $klen\n";
-       $out .= "Tlen = $tlen\n";
-       $out .= "Key = $key\n";
-       $out .= "Msg = $msg\n";
-       $out .= "Mac = " . &$hmac($key, $tlen, $msg, $hashtype{$tlen}) . "\n";
-
-       return $out;
-}
-
-
-# Cipher Monte Carlo Testing
-# $1: the string that we have to put in front of the key
-#     when printing the key
-# $2: crypto key1 in hex form
-# $3: crypto key2 in hex form (TDES, undef otherwise)
-# $4: crypto key3 in hex form (TDES, undef otherwise)
-# $5: IV in hex form
-# $6: Plaintext (enc=1) or Ciphertext (enc=0) in hex form
-# $7: cipher
-# $8: encrypt=1/decrypt=0
-# return: string formatted as expected by CAVS
-sub crypto_mct($$$$$$$$) {
-       my $keytype = shift;
-        my $key1 = hex2bin(shift);
-        my $key2 = shift;
-        my $key3 = shift;
-        my $iv = hex2bin(shift);
-        my $source_data = hex2bin(shift);
-       my $cipher = shift;
-        my $enc = shift;
-
-       my $out = "";
-
-       $key2 = hex2bin($key2) if (defined($key2));
-       $key3 = hex2bin($key3) if (defined($key3));
-        my $bufsize = length($source_data);
-
-       # for AES: outer loop 0-99, inner 0-999 based on FIPS compliance tests
-       # for RC4: outer loop 0-99, inner 0-999 based on atsec compliance tests
-       # for DES: outer loop 0-399, inner 0-9999 based on FIPS compliance tests
-       my $ciph = substr($cipher,0,3);
-       my $oloop=100;
-       my $iloop=1000;
-       if ($ciph =~ /des/) {$oloop=400;$iloop=10000;}
-
-        for (my $i=0; $i<$oloop; ++$i) {
-               $out .= "COUNT = $i\n";
-               if (defined($key2)) {
-                       $out .= "$keytype = ". bin2hex($key1). "\n";
-                       $out .= "KEY2 = ". bin2hex($key2). "\n";
-                       $key1 = $key1 . $key2;
-               } else {
-                       $out .= "$keytype = ". bin2hex($key1). "\n";
-               }
-               if(defined($key3)) {
-                       $out .= "KEY3 = ". bin2hex($key3). "\n";
-                       $key1 = $key1 . $key3;
-               }
-               my $keylen = length($key1);
-
-                $out .= "IV = ". bin2hex($iv) . "\n"
-                       if (defined($iv) && $iv ne "");
-
-                if ($enc) {
-                        $out .= "PLAINTEXT = ". bin2hex($source_data). "\n";
-                } else {
-                        $out .= "CIPHERTEXT = ". bin2hex($source_data). "\n";
-                }
-                my ($CO, $CI);
-               my $cipher_imp = &$state_cipher($cipher, $enc, $bufsize, $key1, $iv);
-               $cipher_imp = &$state_cipher_des($cipher, $enc, $bufsize, $key1, $iv) if($cipher =~ /des/);
-                my $pid = open2($CO, $CI, $cipher_imp);
-
-                my $calc_data = $iv; # CT[j]
-                my $old_calc_data; # CT[j-1]
-                my $old_old_calc_data; # CT[j-2]
-               my $next_source;
-
-               # TDES inner loop implements logic within driver
-               if ($cipher =~ /des/) {
-                       # Need to provide a dummy IV in case of ECB mode.
-                       my $iv_arg = (defined($iv) && $iv ne "")
-                                       ? bin2hex($iv)
-                                       : "00"x(length($source_data));
-                       print $CI "1\n"
-                                 .$iloop."\n"
-                                 .bin2hex($key1)."\n"
-                                 .$iv_arg."\n"
-                                 .bin2hex($source_data)."\n\n" or die;
-                       chomp(my $line = <$CO>);
-                       $calc_data = hex2bin($line);
-                       chomp($line = <$CO>);
-                       $old_calc_data = hex2bin($line);
-                       chomp($line = <$CO>);
-                       $old_old_calc_data = hex2bin($line);
-                       chomp($line = <$CO>);
-                       $iv = hex2bin($line) if (defined($iv) && $iv ne "");
-                       chomp($line = <$CO>);
-                       $next_source = hex2bin($line);
-                       # Skip over empty line.
-                       $line = <$CO>;
-               } else {
-                       for (my $j = 0; $j < $iloop; ++$j) {
-                               $old_old_calc_data = $old_calc_data;
-                               $old_calc_data = $calc_data;
-
-                               #print STDERR "source_data=", bin2hex($source_data), "\n";
-                               syswrite $CI, $source_data or die $!;
-                               my $len = sysread $CO, $calc_data, $bufsize;
-
-                               #print STDERR "len=$len, bufsize=$bufsize\n";
-                               die if $len ne $bufsize;
-                               #print STDERR "calc_data=", bin2hex($calc_data), "\n";
-
-                               if ( (!$enc && $ciph =~ /des/) ||
-                                    $ciph =~ /rc4/ ||
-                                    $cipher =~ /ecb/ ) {
-                                       #TDES in decryption mode, RC4 and ECB mode
-                                       #have a special rule
-                                       $source_data = $calc_data;
-                               } else {
-                                       $source_data = $old_calc_data;
-                               }
-                       }
-               }
-                close $CO;
-                close $CI;
-                waitpid $pid, 0;
-
-                if ($enc) {
-                        $out .= "CIPHERTEXT = ". bin2hex($calc_data). "\n\n";
-                } else {
-                        $out .= "PLAINTEXT = ". bin2hex($calc_data). "\n\n";
-                }
-
-               if ( $ciph =~ /aes/ ) {
-                       $key1 ^= substr($old_calc_data . $calc_data, -$keylen);
-                       #print STDERR bin2hex($key1)."\n";
-               } elsif ( $ciph =~ /des/ ) {
-                       die "Wrong keylen $keylen" if ($keylen != 24);
-
-                       # $nkey needed as $key holds the concatenation of the
-                       # old key atm
-                       my $nkey = fix_key_parity(substr($key1,0,8) ^ $calc_data);
-                       #print STDERR "KEY1 = ". bin2hex($nkey)."\n";
-                       if (substr($key1,0,8) ne substr($key1,8,8)) {
-                               #print STDERR "KEY2 recalc: KEY1==KEY3, KEY2 indep. or all KEYs are indep.\n";
-                               $key2 = fix_key_parity((substr($key1,8,8) ^ $old_calc_data));
-                       } else {
-                               #print STDERR "KEY2 recalc: KEY1==KEY2==KEY3\n";
-                               $key2 = fix_key_parity((substr($key1,8,8) ^ $calc_data));
-                       }
-                       #print STDERR "KEY2 = ". bin2hex($key2)."\n";
-                       if ( substr($key1,0,8) eq substr($key1,16)) {
-                               #print STDERR "KEY3 recalc: KEY1==KEY2==KEY3 or KEY1==KEY3, KEY2 indep.\n";
-                               $key3 = fix_key_parity((substr($key1,16) ^ $calc_data));
-                       } else {
-                               #print STDERR "KEY3 recalc: all KEYs are independent\n";
-                               $key3 = fix_key_parity((substr($key1,16) ^ $old_old_calc_data));
-                       }
-                       #print STDERR "KEY3 = ". bin2hex($key3)."\n";
-
-                       # reset the first key - concardination happens at
-                       # beginning of loop
-                       $key1=$nkey;
-               } elsif ($ciph =~ /rc4/ ) {
-                       $key1 ^= substr($calc_data, 0, 16);
-                       #print STDERR bin2hex($key1)."\n";
-               } else {
-                       die "Test limitation: cipher '$cipher' not supported in Monte Carlo testing";
-               }
-
-               if ($cipher =~ /des-ede3-ofb/) {
-                        $source_data = $source_data ^ $next_source;
-               } elsif (!$enc && $cipher =~ /des-ede3-cfb/) {
-                       #TDES decryption CFB has a special rule
-                       $source_data = $next_source;
-               } elsif ( $ciph =~ /rc4/ || $cipher eq "des-ede3" || $cipher =~ /ecb/) {
-                       #No resetting of IV as the IV is all zero set initially (i.e. no IV)
-                       $source_data = $calc_data;
-               } elsif (! $enc && $ciph =~ /des/ ) {
-                       #TDES in decryption mode has a special rule
-                       $iv = $old_calc_data;
-                       $source_data = $calc_data;
-               } else {
-                       $iv = $calc_data;
-                       $source_data = $old_calc_data;
-               }
-        }
-
-       return $out;
-}
-
-# Hash Monte Carlo Testing
-# $1: Plaintext in hex form
-# $2: hash
-# return: string formatted as expected by CAVS
-sub hash_mct($$) {
-       my $pt = shift;
-       my $cipher = shift;
-
-       my $out = "";
-
-       $out .= "Seed = $pt\n\n";
-
-        for (my $j=0; $j<100; ++$j) {
-               $out .= "COUNT = $j\n";
-               my $md0=$pt;
-               my $md1=$pt;
-               my $md2=$pt;
-               for (my $i=0; $i<1000; ++$i) {
-                       #print STDERR "outer loop $j; inner loop $i\n";
-                       my $mi= $md0 . $md1 . $md2;
-                       $md0=$md1;
-                       $md1=$md2;
-                       $md2 = &$hash($mi, $cipher);
-                       $md2 =~ s/\n//;
-               }
-                $out .= "MD = $md2\n\n";
-               $pt=$md2;
-       }
-
-       return $out;
-}
-
-# RSA SigGen test
-# $1: Message to be signed in hex form
-# $2: Hash algorithm
-# $3: file name with RSA key in PEM form
-# return: string formatted as expected by CAVS
-sub rsa_siggen($$$) {
-       my $data = shift;
-       my $cipher = shift;
-       my $keyfile = shift;
-
-       my $out = "";
-
-       $out .= "SHAAlg = $cipher\n";
-       $out .= "Msg = $data\n";
-       $out .= "S = " . &$rsa_sign($data, lc($cipher), $keyfile) . "\n";
-
-       return $out;
-}
-
-# RSA SigVer test
-# $1: Message to be verified in hex form
-# $2: Hash algorithm
-# $3: Signature of message in hex form
-# $4: n of the RSA key in hex in hex form
-# $5: e of the RSA key in hex in hex form
-# return: string formatted as expected by CAVS
-sub rsa_sigver($$$$$) {
-       my $data = shift;
-       my $cipher = shift;
-       my $signature = shift;
-       my $n = shift;
-       my $e = shift;
-
-       my $out = "";
-
-       $out .= "SHAAlg = $cipher\n";
-       $out .= "e = $e\n";
-       $out .= "Msg = $data\n";
-       $out .= "S = $signature\n";
-
-       # XXX maybe a secure temp file name is better here
-       # but since it is not run on a security sensitive
-       # system, I hope that this is fine
-       my $keyfile = "rsa_sigver.tmp.$$";
-       gen_pubrsakey($keyfile, $n, $e);
-
-       my $sigfile = "$keyfile.sig";
-       open(FH, ">$sigfile") or die "Cannot create file $sigfile: $?";
-       print FH hex2bin($signature);
-       close FH;
-
-       $out .= "Result = " . (&$rsa_verify($data, lc($cipher), $keyfile, $sigfile) ? "P\n" : "F\n");
-
-       unlink($keyfile);
-       unlink($sigfile);
-
-       return $out;
-}
-
-# RSA X9.31 key generation test
-# $1 modulus size
-# $2 e
-# $3 xp1
-# $4 xp2
-# $5 Xp
-# $6 xq1
-# $7 xq2
-# $8 Xq
-# return: string formatted as expected by CAVS
-sub rsa_keygen($$$$$$$$) {
-       my $modulus = shift;
-       my $e = shift;
-       my $xp1 = shift;
-       my $xp2 = shift;
-       my $Xp = shift;
-       my $xq1 = shift;
-       my $xq2 = shift;
-       my $Xq = shift;
-
-       my $out = "";
-
-       my $ret = &$rsa_derive($modulus, $e, $xp1, $xp2, $Xp, $xq1, $xq2, $Xq);
-
-       my ($P, $Q, $N, $D) = split(/\n/, $ret);
-
-       $out .= "e = $e\n";
-       $out .= "xp1 = $xp1\n";
-       $out .= "xp2 = $xp2\n";
-       $out .= "Xp = $Xp\n";
-       $out .= "p = $P\n";
-       $out .= "xq1 = $xq1\n";
-       $out .= "xq2 = $xq2\n";
-       $out .= "Xq = $Xq\n";
-       $out .= "q = $Q\n";
-       $out .= "n = $N\n";
-       $out .= "d = $D\n\n";
-
-       return $out;
-
-}
-
-# X9.31 RNG test
-# $1 key for the AES cipher
-# $2 DT value
-# $3 V value
-# $4 type ("VST", "MCT")
-# return: string formatted as expected by CAVS
-sub rngx931($$$$) {
-       my $key=shift;
-       my $dt=shift;
-       my $v=shift;
-       my $type=shift;
-
-       my $out = "Key = $key\n";
-       $out   .= "DT = $dt\n";
-       $out   .= "V = $v\n";
-
-       my $count = 1;
-       $count = 10000 if ($type eq "MCT");
-
-       my $rnd_val = "";
-
-       # we read 16 bytes from RNG
-       my $bufsize = 16;
-
-       my ($CO, $CI);
-       my $rng_imp = &$state_rng($key, $dt, $v);
-       my $pid = open2($CO, $CI, $rng_imp);
-       for (my $i = 0; $i < $count; ++$i) {
-               my $len = sysread $CO, $rnd_val, $bufsize;
-               #print STDERR "len=$len, bufsize=$bufsize\n";
-               die "len=$len != bufsize=$bufsize" if $len ne $bufsize;
-               #print STDERR "calc_data=", bin2hex($rnd_val), "\n";
-       }
-       close $CO;
-       close $CI;
-       waitpid $pid, 0;
-
-       $out .= "R = " . bin2hex($rnd_val) . "\n\n";
-
-       return $out;
-}
-
-# DSA PQGGen test
-# $1 modulus size
-# $2 number of rounds to perform the test
-# return: string formatted as expected by CAVS
-sub dsa_pqggen_driver($$) {
-       my $mod = shift;
-       my $rounds = shift;
-
-       my $out = "";
-       for(my $i=0; $i<$rounds; $i++) {
-               my $ret = &$dsa_pqggen($mod);
-               my ($P, $Q, $G, $Seed, $c, $H) = split(/\n/, $ret);
-               die "Return value does not contain all expected values of P, Q, G, Seed, c, H for dsa_pqggen"
-                       if (!defined($P) || !defined($Q) || !defined($G) ||
-                           !defined($Seed) || !defined($c) || !defined($H));
-
-               # now change the counter to decimal as CAVS wants decimal
-               # counter value although all other is HEX
-               $c = hex($c);
-
-               $out .= "P = $P\n";
-               $out .= "Q = $Q\n";
-               $out .= "G = $G\n";
-               $out .= "Seed = $Seed\n";
-               $out .= "c = $c\n";
-               $out .= "H = $H\n\n";
-       }
-
-       return $out;
-}
-
-
-# DSA SigGen test
-# $1: Message to be signed in hex form
-# $2: file name with DSA key in PEM form
-# return: string formatted as expected by CAVS
-sub dsa_siggen($$) {
-       my $data = shift;
-       my $keyfile = shift;
-
-       my $out = "";
-
-       my %ret = &$dsa_sign($data, $keyfile);
-
-       $out .= "Msg = $data\n";
-       $out .= "Y = " . $ret{'Y'} . "\n";
-       $out .= "R = " . $ret{'R'} . "\n";
-       $out .= "S = " . $ret{'S'} . "\n";
-
-       return $out;
-}
-
-
-# DSA signature verification
-# $1 modulus
-# $2 P
-# $3 Q
-# $4 G
-# $5 Y - public key
-# $6 r
-# $7 s
-# $8 message to be verified
-# return: string formatted as expected by CAVS
-sub dsa_sigver($$$$$$$$) {
-       my $modulus = shift;
-       my $p = shift;
-       my $q = shift;
-       my $g = shift;
-       my $y = shift;
-       my $r = shift;
-       my $s = shift;
-       my $msg = shift;
-
-       my $out = "";
-
-       #PQG are already printed - do not print them here
-
-       $out .= "Msg = $msg\n";
-       $out .= "Y = $y\n";
-       $out .= "R = $r\n";
-       $out .= "S = $s\n";
-
-       # XXX maybe a secure temp file name is better here
-       # but since it is not run on a security sensitive
-       # system, I hope that this is fine
-       my $keyfile = "dsa_sigver.tmp.$$";
-       &$dsa_genpubkey($keyfile, $p, $q, $g, $y);
-
-       $out .= "Result = " . (&$dsa_verify($msg, $keyfile, $r, $s) ? "P\n" : "F\n");
-
-       unlink($keyfile);
-
-       return $out;
-}
-
-##############################################################
-# Parser of input file and generator of result file
-#
-
-sub usage() {
-
-       print STDERR "Usage:
-$0 [-R] [-D] [-I name] <CAVS-test vector file>
-
--R     execution of ARCFOUR instead of OpenSSL
--I NAME        Use interface style NAME:
-               openssl     OpenSSL (default)
-               libgcrypt   Libgcrypt
--D     SigGen and SigVer are executed with DSA
-       Please note that the DSA CAVS vectors do not allow distinguishing
-       them from the RSA vectors. As the RSA test is the default, you have
-       to supply this option to apply the DSA logic";
-}
-
-# Parser of CAVS test vector file
-# $1: Test vector file
-# $2: Output file for test results
-# return: nothing
-sub parse($$) {
-       my $infile = shift;
-       my $outfile = shift;
-
-       my $out = "";
-
-       # this is my cipher/hash type
-       my $cipher = "";
-
-       # Test type
-       # 1 - cipher known answer test
-       # 2 - cipher Monte Carlo test
-       # 3 - hash known answer test
-       # 4 - hash Monte Carlo test
-       # 5 - RSA signature generation
-       # 6 - RSA signature verification
-       my $tt = 0;
-
-       # Variables for tests
-       my $keytype = ""; # we can have "KEY", "KEYs", "KEY1"
-       my $key1 = "";
-       my $key2 = undef; #undef needed for allowing
-       my $key3 = undef; #the use of them as input variables
-       my $pt = "";
-       my $enc = 1;
-       my $iv = "";
-       my $len = undef; #see key2|3
-       my $n = "";
-       my $e = "";
-       my $signature = "";
-       my $rsa_keyfile = "";
-       my $dsa_keyfile = "";
-       my $dt = "";
-       my $v = "";
-       my $klen = "";
-       my $tlen = "";
-       my $modulus = "";
-       my $capital_n = 0;
-       my $capital_p = "";
-       my $capital_q = "";
-       my $capital_g = "";
-       my $capital_y = "";
-       my $capital_r = "";
-       my $xp1 = "";
-       my $xp2 = "";
-       my $Xp = "";
-       my $xq1 = "";
-       my $xq2 = "";
-       my $Xq = "";
-
-       my $mode = "";
-
-       open(IN, "<$infile");
-       while(<IN>) {
-
-               my $line = $_;
-               chomp($line);
-               $line =~ s/\r//;
-
-               my $keylen = "";
-
-               # Mode and type check
-               # consider the following parsed line
-               # '# AESVS MCT test data for CBC'
-               # '# TDES Multi block Message Test for CBC'
-               # '# INVERSE PERMUTATION - KAT for CBC'
-               # '# SUBSTITUTION TABLE - KAT for CBC'
-               # '# TDES Monte Carlo (Modes) Test for CBC'
-               # '#  "SHA-1 Monte" information for "IBMRHEL5"'
-               # '# "SigVer PKCS#1 Ver 1.5" information for "IBMRHEL5"'
-               # '# "SigGen PKCS#1 Ver 1.5" information for "IBMRHEL5"'
-               # '#RC4VS MCT test data'
-
-               # avoid false positives from user specified 'for "PRODUCT"' strings
-               my $tmpline = $line;
-               $tmpline =~ s/ for ".*"//;
-
-               ##### Extract cipher
-               # XXX there may be more - to be added
-               if ($tmpline =~ /^#.*(CBC|ECB|OFB|CFB|SHA-|SigGen|SigVer|RC4VS|ANSI X9\.31|Hash sizes tested|PQGGen|KeyGen RSA)/) {
-                       if ($tmpline    =~ /CBC/)   { $mode="cbc"; }
-                       elsif ($tmpline =~ /ECB/)   { $mode="ecb"; }
-                       elsif ($tmpline =~ /OFB/)   { $mode="ofb"; }
-                       elsif ($tmpline =~ /CFB/)   { $mode="cfb"; }
-                       #we do not need mode as the cipher is already clear
-                       elsif ($tmpline =~ /SHA-1/) { $cipher="sha1"; }
-                       elsif ($tmpline =~ /SHA-224/) { $cipher="sha224"; }
-                       elsif ($tmpline =~ /SHA-256/) { $cipher="sha256"; }
-                       elsif ($tmpline =~ /SHA-384/) { $cipher="sha384"; }
-                       elsif ($tmpline =~ /SHA-512/) { $cipher="sha512"; }
-                       #we do not need mode as the cipher is already clear
-                       elsif ($tmpline =~ /RC4VS/) { $cipher="rc4"; }
-                       elsif ($tmpline =~ /SigGen|SigVer/) {
-                               die "Error: X9.31 is not supported"
-                                       if ($tmpline =~ /X9/);
-                               $cipher="sha1"; #place holder - might be overwritten later
-                       }
-
-                       if ($tmpline =~ /^#.*AESVS/) {
-                               # AES cipher (part of it)
-                               $cipher="aes";
-                       }
-                       if ($tmpline =~ /^#.*(TDES|KAT)/) {
-                               # TDES cipher (full definition)
-                               # the FIPS-140 test generator tool does not produce
-                               # machine readable output!
-                               if ($mode eq "cbc") { $cipher="des-ede3-cbc"; }
-                               if ($mode eq "ecb") { $cipher="des-ede3"; }
-                               if ($mode eq "ofb") { $cipher="des-ede3-ofb"; }
-                               if ($mode eq "cfb") { $cipher="des-ede3-cfb"; }
-                       }
-
-                       # check for RNG
-                       if ($tmpline =~ /ANSI X9\.31/) {
-                               # change the tmpline to add the type of the
-                               # test which is ONLY visible from the file
-                               # name :-(
-                               if ($infile =~ /MCT\.req/) {
-                                       $tmpline .= " MCT";
-                               } elsif ($infile =~ /VST\.req/) {
-                                       $tmpline .= " VST";
-                               } else {
-                                       die "Unexpected cipher type with $infile";
-                               }
-                       }
-
-                       if ($tt == 0) {
-                       ##### Identify the test type
-                               if ($tmpline =~ /KeyGen RSA \(X9\.31\)/) {
-                                       $tt = 13;
-                                       die "Interface function rsa_derive for RSA key generation not defined for tested library"
-                                               if (!defined($rsa_derive));
-                               } elsif ($tmpline =~ /SigVer/ && $opt{'D'} ) {
-                                       $tt = 12;
-                                       die "Interface function dsa_verify or dsa_genpubkey for DSA verification not defined for tested library"
-                                               if (!defined($dsa_verify) || !defined($dsa_genpubkey));
-                               } elsif ($tmpline =~ /SigGen/ && $opt{'D'}) {
-                                       $tt = 11;
-                                       die "Interface function dsa_sign or gen_dsakey for DSA sign not defined for tested library"
-                                               if (!defined($dsa_sign) || !defined($gen_rsakey));
-                               } elsif ($tmpline =~ /PQGGen/) {
-                                       $tt = 10;
-                                       die "Interface function for DSA PQGGen testing not defined for tested library"
-                                               if (!defined($dsa_pqggen));
-                               } elsif ($tmpline =~ /Hash sizes tested/) {
-                                       $tt = 9;
-                                       die "Interface function hmac for HMAC testing not defined for tested library"
-                                               if (!defined($hmac));
-                               } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /MCT/) {
-                                       $tt = 8;
-                                       die "Interface function state_rng for RNG MCT not defined for tested library"
-                                               if (!defined($state_rng));
-                               } elsif ($tmpline =~ /ANSI X9\.31/ && $tmpline =~ /VST/) {
-                                       $tt = 7;
-                                       die "Interface function state_rng for RNG KAT not defined for tested library"
-                                               if (!defined($state_rng));
-                               } elsif ($tmpline =~ /SigVer/ ) {
-                                       $tt = 6;
-                                       die "Interface function rsa_verify or gen_rsakey for RSA verification not defined for tested library"
-                                               if (!defined($rsa_verify) || !defined($gen_rsakey));
-                               } elsif ($tmpline =~ /SigGen/ ) {
-                                       $tt = 5;
-                                       die "Interface function rsa_sign or gen_rsakey for RSA sign not defined for tested library"
-                                               if (!defined($rsa_sign) || !defined($gen_rsakey));
-                               } elsif ($tmpline =~ /Monte|MCT|Carlo/ && $cipher =~ /^sha/) {
-                                       $tt = 4;
-                                       die "Interface function hash for Hashing not defined for tested library"
-                                               if (!defined($hash));
-                               } elsif ($tmpline =~ /Monte|MCT|Carlo/) {
-                                       $tt = 2;
-                                       die "Interface function state_cipher for Stateful Cipher operation defined for tested library"
-                                               if (!defined($state_cipher) || !defined($state_cipher_des));
-                               } elsif ($cipher =~ /^sha/) {
-                                       $tt = 3;
-                                       die "Interface function hash for Hashing not defined for tested library"
-                                               if (!defined($hash));
-                               } else {
-                                       $tt = 1;
-                                       die "Interface function encdec for Encryption/Decryption not defined for tested library"
-                                               if (!defined($encdec));
-                               }
-                       }
-               }
-
-               # This is needed as ARCFOUR does not operate with an IV
-               $iv = "00000000000000000000000000000000" if ($cipher eq "rc4"
-                                                            && $iv eq "" );
-
-               # we are now looking for the string
-               # '# Key Length : 256'
-               # found in AES
-               if ($tmpline =~ /^# Key Length.*?(128|192|256)/) {
-                       if ($cipher eq "aes") {
-                               $cipher="$cipher-$1-$mode";
-                       } else {
-                               die "Error: Key length $1 given for cipher $cipher which is unexpected";
-                       }
-               }
-
-               # Get the test data
-               if ($line =~ /^(KEY|KEY1|Key)\s*=\s*(.*)/) { # found in ciphers and RNG
-                       die "KEY seen twice - input file crap" if ($key1 ne "");
-                       $keytype=$1;
-                       $key1=$2;
-                       $key1 =~ s/\s//g; #replace potential white spaces
-               }
-               elsif ($line =~ /^(KEYs)\s*=\s*(.*)/) { # found in ciphers and RNG
-                       die "KEY seen twice - input file crap" if ($key1 ne "");
-                       $keytype=$1;
-                       $key1=$2;
-                       $key1 =~ s/\s//g; #replace potential white spaces
-                       $key2 = $key1;
-                       $key3 = $key1;
-               }
-               elsif ($line =~ /^KEY2\s*=\s*(.*)/) { # found in TDES
-                       die "First key not set, but got already second key - input file crap" if ($key1 eq "");
-                       die "KEY2 seen twice - input file crap" if (defined($key2));
-                       $key2=$1;
-                       $key2 =~ s/\s//g; #replace potential white spaces
-               }
-               elsif ($line =~ /^KEY3\s*=\s*(.*)/) { # found in TDES
-                       die "Second key not set, but got already third key - input file crap" if ($key2 eq "");
-                       die "KEY3 seen twice - input file crap" if (defined($key3));
-                       $key3=$1;
-                       $key3 =~ s/\s//g; #replace potential white spaces
-               }
-               elsif ($line =~ /^IV\s*=\s*(.*)/) { # found in ciphers
-                       die "IV seen twice - input file crap" if ($iv ne "");
-                       $iv=$1;
-                       $iv =~ s/\s//g; #replace potential white spaces
-               }
-               elsif ($line =~ /^PLAINTEXT\s*=\s*(.*)/) { # found in ciphers
-                       if ( $1 !~ /\?/ ) { #only use it if there is valid hex data
-                               die "PLAINTEXT/CIPHERTEXT seen twice - input file crap" if ($pt ne "");
-                               $pt=$1;
-                               $pt =~ s/\s//g; #replace potential white spaces
-                               $enc=1;
-                       }
-               }
-               elsif ($line =~ /^CIPHERTEXT\s*=\s*(.*)/) { # found in ciphers
-                       if ( $1 !~ /\?/ ) { #only use it if there is valid hex data
-                               die "PLAINTEXT/CIPHERTEXT seen twice - input file crap" if ($pt ne "");
-                               $pt=$1;
-                               $pt =~ s/\s//g; #replace potential white spaces
-                               $enc=0;
-                       }
-               }
-               elsif ($line =~ /^Len\s*=\s*(.*)/) { # found in hashs
-                       $len=$1;
-               }
-               elsif ($line =~ /^(Msg|Seed)\s*=\s*(.*)/) { # found in hashs
-                       die "Msg/Seed seen twice - input file crap" if ($pt ne "");
-                       $pt=$2;
-               }
-               elsif ($line =~ /^\[mod\s*=\s*(.*)\]$/) { # found in RSA requests
-                       $modulus = $1;
-                       $out .= $line . "\n\n"; # print it
-                       # generate the private key with given bit length now
-                       # as we have the required key length in bit
-                       if ($tt == 11) {
-                               $dsa_keyfile = "dsa_siggen.tmp.$$";
-                               my %pqg = &$gen_dsakey($dsa_keyfile);
-                               $out .= "P = " . $pqg{'P'} . "\n";
-                               $out .= "Q = " . $pqg{'Q'} . "\n";
-                               $out .= "G = " . $pqg{'G'} . "\n";
-                       } elsif ( $tt == 5 ) {
-                               # XXX maybe a secure temp file name is better here
-                               # but since it is not run on a security sensitive
-                               # system, I hope that this is fine
-                               $rsa_keyfile = "rsa_siggen.tmp.$$";
-                               &$gen_rsakey($modulus, $rsa_keyfile);
-                               my $modulus = pipe_through_program("", "openssl rsa -pubout -modulus -in $rsa_keyfile");
-                               $modulus =~ s/Modulus=(.*?)\s(.|\s)*/$1/;
-                               $out .= "n = $modulus\n";
-                               $out .= "\ne = 10001\n"
-                       }
-               }
-               elsif ($line =~ /^SHAAlg\s*=\s*(.*)/) { #found in RSA requests
-                       $cipher=$1;
-               }
-               elsif($line =~ /^n\s*=\s*(.*)/) { # found in RSA requests
-                       $out .= $line . "\n";
-                       $n=$1;
-               }
-               elsif ($line =~ /^e\s*=\s*(.*)/) { # found in RSA requests
-                       $e=$1;
-               }
-               elsif ($line =~ /^S\s*=\s*(.*)/) { # found in RSA requests
-                       die "S seen twice - input file crap" if ($signature ne "");
-                       $signature=$1;
-               }
-               elsif ($line =~ /^DT\s*=\s*(.*)/) { # X9.31 RNG requests
-                       die "DT seen twice - check input file"
-                               if ($dt ne "");
-                       $dt=$1;
-               }
-               elsif ($line =~ /^V\s*=\s*(.*)/) { # X9.31 RNG requests
-                       die "V seen twice - check input file"
-                               if ($v ne "");
-                       $v=$1;
-               }
-               elsif ($line =~ /^Klen\s*=\s*(.*)/) { # HMAC requests
-                       die "Klen seen twice - check input file"
-                               if ($klen ne "");
-                       $klen=$1;
-               }
-               elsif ($line =~ /^Tlen\s*=\s*(.*)/) { # HMAC RNG requests
-                       die "Tlen seen twice - check input file"
-                               if ($tlen ne "");
-                       $tlen=$1;
-               }
-               elsif ($line =~ /^N\s*=\s*(.*)/) { #DSA PQGGen
-                       die "N seen twice - check input file"
-                               if ($capital_n);
-                       $capital_n = $1;
-               }
-               elsif ($line =~ /^P\s*=\s*(.*)/) { #DSA SigVer
-                       die "P seen twice - check input file"
-                               if ($capital_p);
-                       $capital_p = $1;
-                       $out .= $line . "\n"; # print it
-               }
-               elsif ($line =~ /^Q\s*=\s*(.*)/) { #DSA SigVer
-                       die "Q seen twice - check input file"
-                               if ($capital_q);
-                       $capital_q = $1;
-                       $out .= $line . "\n"; # print it
-               }
-               elsif ($line =~ /^G\s*=\s*(.*)/) { #DSA SigVer
-                       die "G seen twice - check input file"
-                               if ($capital_g);
-                       $capital_g = $1;
-                       $out .= $line . "\n"; # print it
-               }
-               elsif ($line =~ /^Y\s*=\s*(.*)/) { #DSA SigVer
-                       die "Y seen twice - check input file"
-                               if ($capital_y);
-                       $capital_y = $1;
-               }
-               elsif ($line =~ /^R\s*=\s*(.*)/) { #DSA SigVer
-                       die "R seen twice - check input file"
-                               if ($capital_r);
-                       $capital_r = $1;
-               }
-               elsif ($line =~ /^xp1\s*=\s*(.*)/) { #RSA key gen
-                       die "xp1 seen twice - check input file"
-                               if ($xp1);
-                       $xp1 = $1;
-               }
-               elsif ($line =~ /^xp2\s*=\s*(.*)/) { #RSA key gen
-                       die "xp2 seen twice - check input file"
-                               if ($xp2);
-                       $xp2 = $1;
-               }
-               elsif ($line =~ /^Xp\s*=\s*(.*)/) { #RSA key gen
-                       die "Xp seen twice - check input file"
-                               if ($Xp);
-                       $Xp = $1;
-               }
-               elsif ($line =~ /^xq1\s*=\s*(.*)/) { #RSA key gen
-                       die "xq1 seen twice - check input file"
-                               if ($xq1);
-                       $xq1 = $1;
-               }
-               elsif ($line =~ /^xq2\s*=\s*(.*)/) { #RSA key gen
-                       die "xq2 seen twice - check input file"
-                               if ($xq2);
-                       $xq2 = $1;
-               }
-               elsif ($line =~ /^Xq\s*=\s*(.*)/) { #RSA key gen
-                       die "Xq seen twice - check input file"
-                               if ($Xq);
-                       $Xq = $1;
-               }
-               else {
-                       $out .= $line . "\n";
-               }
-
-               # call tests if all input data is there
-               if ($tt == 1) {
-                       if ($key1 ne "" && $pt ne "" && $cipher ne "") {
-                               $out .= kat($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc);
-                               $keytype = "";
-                               $key1 = "";
-                               $key2 = undef;
-                               $key3 = undef;
-                               $iv = "";
-                               $pt = "";
-                       }
-               }
-               elsif ($tt == 2) {
-                       if ($key1 ne "" && $pt ne "" && $cipher ne "") {
-                               $out .= crypto_mct($keytype, $key1, $key2, $key3, $iv, $pt, $cipher, $enc);
-                               $keytype = "";
-                               $key1 = "";
-                               $key2 = undef;
-                               $key3 = undef;
-                               $iv = "";
-                               $pt = "";
-                       }
-               }
-               elsif ($tt == 3) {
-                       if ($pt ne "" && $cipher ne "") {
-                               $out .= hash_kat($pt, $cipher, $len);
-                               $pt = "";
-                               $len = undef;
-                       }
-               }
-               elsif ($tt == 4) {
-                       if ($pt ne "" && $cipher ne "") {
-                               $out .= hash_mct($pt, $cipher);
-                               $pt = "";
-                       }
-               }
-               elsif ($tt == 5) {
-                       if ($pt ne "" && $cipher ne "" && $rsa_keyfile ne "") {
-                               $out .= rsa_siggen($pt, $cipher, $rsa_keyfile);
-                               $pt = "";
-                       }
-               }
-               elsif ($tt == 6) {
-                       if ($pt ne "" && $cipher ne "" && $signature ne "" && $n ne "" && $e ne "") {
-                               $out .= rsa_sigver($pt, $cipher, $signature, $n, $e);
-                               $pt = "";
-                               $signature = "";
-                       }
-               }
-               elsif ($tt == 7 ) {
-                       if ($key1 ne "" && $dt ne "" && $v ne "") {
-                               $out .= rngx931($key1, $dt, $v, "VST");
-                               $key1 = "";
-                               $dt = "";
-                               $v = "";
-                       }
-               }
-               elsif ($tt == 8 ) {
-                       if ($key1 ne "" && $dt ne "" && $v ne "") {
-                               $out .= rngx931($key1, $dt, $v, "MCT");
-                               $key1 = "";
-                               $dt = "";
-                               $v = "";
-                       }
-               }
-               elsif ($tt == 9) {
-                       if ($klen ne "" && $tlen ne "" && $key1 ne "" && $pt ne "") {
-                               $out .= hmac_kat($klen, $tlen, $key1, $pt);
-                               $key1 = "";
-                               $tlen = "";
-                               $klen = "";
-                               $pt = "";
-                       }
-               }
-               elsif ($tt == 10) {
-                       if ($modulus ne "" && $capital_n > 0) {
-                               $out .= dsa_pqggen_driver($modulus, $capital_n);
-                               #$mod is not resetted
-                               $capital_n = 0;
-                       }
-               }
-               elsif ($tt == 11) {
-                       if ($pt ne "" && $dsa_keyfile ne "") {
-                               $out .= dsa_siggen($pt, $dsa_keyfile);
-                               $pt = "";
-                       }
-               }
-               elsif ($tt == 12) {
-                       if ($modulus ne "" &&
-                           $capital_p ne "" &&
-                           $capital_q ne "" &&
-                           $capital_g ne "" &&
-                           $capital_y ne "" &&
-                           $capital_r ne "" &&
-                           $signature ne "" &&
-                           $pt ne "") {
-                               $out .= dsa_sigver($modulus,
-                                                  $capital_p,
-                                                  $capital_q,
-                                                  $capital_g,
-                                                  $capital_y,
-                                                  $capital_r,
-                                                  $signature,
-                                                  $pt);
-
-                               # We do not clear the domain values PQG and
-                               # the modulus value as they
-                               # are specified only once in a file
-                               # and we do not need to print them as they
-                               # are already printed above
-                               $capital_y = "";
-                               $capital_r = "";
-                               $signature = "";
-                               $pt = "";
-                       }
-               }
-               elsif ($tt == 13) {
-                       if($modulus ne "" &&
-                          $e ne "" &&
-                          $xp1 ne "" &&
-                          $xp2 ne "" &&
-                          $Xp ne "" &&
-                          $xq1 ne "" &&
-                          $xq2 ne "" &&
-                          $Xq ne "") {
-                               $out .= rsa_keygen($modulus,
-                                                  $e,
-                                                  $xp1,
-                                                  $xp2,
-                                                  $Xp,
-                                                  $xq1,
-                                                  $xq2,
-                                                  $Xq);
-                               $e = "";
-                               $xp1 = "";
-                               $xp2 = "";
-                               $Xp = "";
-                               $xq1 = "";
-                               $xq2 = "";
-                               $Xq = "";
-                       }
-               }
-               elsif ($tt > 0) {
-                       die "Test case $tt not defined";
-               }
-       }
-
-       close IN;
-       $out =~ s/\n/\r\n/g; # make it a dos file
-       open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?";
-       print OUT $out;
-       close OUT;
-
-}
-
-# Signalhandler
-sub cleanup() {
-       unlink("rsa_siggen.tmp.$$");
-       unlink("rsa_sigver.tmp.$$");
-       unlink("rsa_sigver.tmp.$$.sig");
-       unlink("rsa_sigver.tmp.$$.der");
-       unlink("rsa_sigver.tmp.$$.cnf");
-       unlink("dsa_siggen.tmp.$$");
-       unlink("dsa_sigver.tmp.$$");
-       unlink("dsa_sigver.tmp.$$.sig");
-       exit;
-}
-
-############################################################
-#
-# let us pretend to be C :-)
-sub main() {
-
-       usage() unless @ARGV;
-
-       getopts("DRI:", \%opt) or die "bad option";
-
-       ##### Set library
-
-       if ( ! defined $opt{'I'} || $opt{'I'} eq 'openssl' ) {
-               print STDERR "Using OpenSSL interface functions\n";
-               $encdec =       \&openssl_encdec;
-               $rsa_sign =     \&openssl_rsa_sign;
-               $rsa_verify =   \&openssl_rsa_verify;
-               $gen_rsakey =   \&openssl_gen_rsakey;
-               $hash =         \&openssl_hash;
-               $state_cipher = \&openssl_state_cipher;
-       } elsif ( $opt{'I'} eq 'libgcrypt' ) {
-               print STDERR "Using libgcrypt interface functions\n";
-               $encdec =       \&libgcrypt_encdec;
-               $rsa_sign =     \&libgcrypt_rsa_sign;
-               $rsa_verify =   \&libgcrypt_rsa_verify;
-               $gen_rsakey =   \&libgcrypt_gen_rsakey;
-               $rsa_derive =   \&libgcrypt_rsa_derive;
-               $hash =         \&libgcrypt_hash;
-               $state_cipher = \&libgcrypt_state_cipher;
-               $state_cipher_des =     \&libgcrypt_state_cipher_des;
-               $state_rng =    \&libgcrypt_state_rng;
-               $hmac =         \&libgcrypt_hmac;
-               $dsa_pqggen =   \&libgcrypt_dsa_pqggen;
-               $gen_dsakey =   \&libgcrypt_gen_dsakey;
-               $dsa_sign =     \&libgcrypt_dsa_sign;
-               $dsa_verify =   \&libgcrypt_dsa_verify;
-               $dsa_genpubkey = \&libgcrypt_dsa_genpubkey;
-        } else {
-                die "Invalid interface option given";
-        }
-
-       my $infile=$ARGV[0];
-       die "Error: Test vector file $infile not found" if (! -f $infile);
-
-       my $outfile = $infile;
-       # let us add .rsp regardless whether we could strip .req
-       $outfile =~ s/\.req$//;
-       if ($opt{'R'}) {
-               $outfile .= ".rc4";
-       } else {
-               $outfile .= ".rsp";
-       }
-       if (-f $outfile) {
-               die "Output file $outfile could not be removed: $?"
-                       unless unlink($outfile);
-       }
-       print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n";
-
-       #Signal handler
-       $SIG{HUP} = \&cleanup;
-       $SIG{INT} = \&cleanup;
-       $SIG{QUIT} = \&cleanup;
-       $SIG{TERM} = \&cleanup;
-
-       # Do the job
-       parse($infile, $outfile);
-
-       cleanup();
-
-}
-
-###########################################
-# Call it
-main();
-1;
diff --git a/tests/cavs_tests.sh b/tests/cavs_tests.sh
deleted file mode 100755 (executable)
index 7d8499b..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/bin/sh
-# Run FIPS CAVS tests
-# Copyright 2008 Free Software Foundation, Inc.
-#
-# This file is free software; as a special exception the author gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-#
-# Instructions:
-#
-# 1. Cd to the libgcrypt/tests directory
-#
-# 2. Unpack the test vector tarball into subdirectory named "cavs".
-#    An example directory layout after unpacking might be:
-#      libgcrypt/tests/cavs/AES/req/CBCGFSbox128.req
-#      libgcrypt/tests/cavs/AES/req/CFB128MCT128.req
-#
-#    Note that below the "cavs" directory there should only be one
-#    directory part named "req".  Further avoid directory part
-#    names "resp".
-#
-# 3. Run this script from the libgcrypt/tests directory:
-#      ./cavs_tests.sh
-#
-# 4. Send the result file cavs/CAVS_results-*.zip to the testing lab.
-#
-
-# Stop script if something unexpected happens.
-set -e
-
-# A global flag to keep track of errors.
-errors_seen_file="$(pwd)/.#cavs_test.errors_seen.tmp"
-[ -f "$errors_seen_file" ] && rm "$errors_seen_file"
-continue_mode=no
-[ "$1" = "--continue" ] && continue_mode=yes
-
-
-# Function to run one test.
-# The argument is the request file name.
-function run_one_test () {
-    local reqfile="$1"
-    local rspfile
-    local tmprspfile
-    local respdir
-    local dflag=""
-
-    tmprspfile=$(echo "$reqfile" | sed 's,.req$,.rsp,')
-    rspfile=$(echo "$tmprspfile" | sed 's,/req/,/resp/,' )
-    respdir=$(dirname "$rspfile")
-    [ -f "$tmprspfile" ] && rm "$tmprspfile"
-    [ -d "$respdir" ] || mkdir "$respdir"
-    [ -f "$rspfile" ] &&  rm "$rspfile"
-
-    if echo "$reqfile" | grep '/DSA/req/' >/dev/null 2>/dev/null; then
-        dflag="-D"
-    fi
-
-    if ./cavs_driver.pl -I libgcrypt $dflag "$reqfile"; then
-      if [ -f "$tmprspfile" ]; then
-          mv "$tmprspfile" "$rspfile"
-      else
-          echo "failed test: $reqfile" >&2
-          : >"$errors_seen_file"
-      fi
-    else
-        echo "failed test: $reqfile rc=$?" >&2
-        : >"$errors_seen_file"
-    fi
-}
-
-
-
-# Save date and system architecure to construct the output archive name
-DATE=$(date +%Y%m%d)
-ARCH=$(arch || echo unknown)
-result_file="CAVS_results-$ARCH-$DATE.zip"
-
-for f in fipsdrv cavs_driver.pl; do
-    if [ ! -f "./$f" ]; then
-      echo "required program \"$f\" missing in current directory" >&2
-      exit 2
-    fi
-done
-if [ ! -d cavs ]; then
-    echo "required directory \"cavs\" missing below current directory" >&2
-    exit 2
-fi
-if [ ! zip -h >/dev/null 2>&1 ]; then
-    echo "required program \"zip\" is not installed on this system" >&2
-    exit 2
-fi
-
-# Set the PATH to this directory so that the perl script is able to
-# find the test drivers.
-PATH=.:$PATH
-
-# Check whether there are any stale response files
-find cavs -type f -name "*.rsp" | ( while read f ; do
-    echo "Stale response file: $f" >&2
-    any=yes
-done
-if [ "$any" = "yes" ]; then
-    echo "Stale response files found" >&2
-    if [ "$continue_mode" != "yes" ]; then
-       echo "use option --continue if that is not a problem" >&2
-       exit 1
-    fi
-fi
-) || exit 1
-
-
-# Find all test files and run the tests.
-find cavs -type f -name "*.req" | while read f ; do
-    echo "Running test file $f" >&2
-    run_one_test "$f"
-    if [ -f "$errors_seen_file" ]; then
-        break;
-    fi
-done
-
-if [ -f "$errors_seen_file" ]; then
-    rm "$errors_seen_file"
-    echo "Error encountered - not packing up response file" >&2
-    exit 1
-fi
-
-echo "Packing up all response files" >&2
-cd cavs
-find . -type f -name "*rsp" -print | zip -@ "$result_file"
-
-echo "Result file is: cavs/$result_file" >&2
index 9e75fd5..3c73817 100644 (file)
@@ -32,8 +32,8 @@
 #define PGM "curves"
 #include "t-common.h"
 
-/* Number of curves defined in ../cipger/ecc.c */
-#define N_CURVES 22
+/* Number of curves defined in ../cipher/ecc-curves.c */
+#define N_CURVES 27
 
 /* A real world sample public key.  */
 static char const sample_key_1[] =
@@ -69,6 +69,7 @@ static char const sample_key_2[] =
 static char const sample_key_2_curve[] = "brainpoolP160r1";
 static unsigned int sample_key_2_nbits = 160;
 
+static int in_fips_mode;
 
 static void
 list_curves (void)
@@ -112,26 +113,159 @@ check_matching (void)
 
   gcry_sexp_release (key);
 
-  err = gcry_sexp_new (&key, sample_key_2, 0, 1);
-  if (err)
-    die ("parsing s-expression string failed: %s\n", gpg_strerror (err));
-  name = gcry_pk_get_curve (key, 0, &nbits);
-  if (!name)
-    fail ("curve name not found for sample_key_2\n");
-  else if (strcmp (name, sample_key_2_curve))
-    fail ("expected curve name %s but got %s for sample_key_2\n",
-          sample_key_2_curve, name);
-  else if (nbits != sample_key_2_nbits)
-    fail ("expected curve size %u but got %u for sample_key_2\n",
-          sample_key_2_nbits, nbits);
+  if (!in_fips_mode)
+    {
+      err = gcry_sexp_new (&key, sample_key_2, 0, 1);
+      if (err)
+        die ("parsing s-expression string failed: %s\n", gpg_strerror (err));
+      name = gcry_pk_get_curve (key, 0, &nbits);
+      if (!name)
+        fail ("curve name not found for sample_key_2\n");
+      else if (strcmp (name, sample_key_2_curve))
+        fail ("expected curve name %s but got %s for sample_key_2\n",
+              sample_key_2_curve, name);
+      else if (nbits != sample_key_2_nbits)
+        fail ("expected curve size %u but got %u for sample_key_2\n",
+              sample_key_2_nbits, nbits);
 
-  gcry_sexp_release (key);
+      gcry_sexp_release (key);
+    }
 }
 
+#define TEST_ERROR_EXPECTED (1 << 0)
+#define TEST_NOFIPS         (1 << 1)
 
 static void
 check_get_params (void)
 {
+  static struct {
+    int algo;
+    const char *name;
+    int flags;
+  } tv[] =
+      {
+       { GCRY_PK_ECC, "Ed25519", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.6.1.4.1.11591.15.1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.101.112", TEST_NOFIPS },
+
+       { GCRY_PK_ECC, "Curve25519", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.6.1.4.1.3029.1.5.1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.101.110", TEST_NOFIPS },
+       { GCRY_PK_ECC, "X25519", TEST_NOFIPS },
+
+       { GCRY_PK_ECC, "Ed448", TEST_NOFIPS },
+       { GCRY_PK_ECC, "X448", TEST_NOFIPS  },
+       { GCRY_PK_ECC, "1.3.101.113", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.101.111", TEST_NOFIPS },
+
+       { GCRY_PK_ECC, "NIST P-192", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.840.10045.3.1.1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "prime192v1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "secp192r1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "nistp192", TEST_NOFIPS },
+
+       { GCRY_PK_ECC, "NIST P-224" },
+       { GCRY_PK_ECC, "secp224r1"  },
+       { GCRY_PK_ECC, "1.3.132.0.33" },
+       { GCRY_PK_ECC, "nistp224"   },
+
+       { GCRY_PK_ECC, "NIST P-256" },
+       { GCRY_PK_ECC, "1.2.840.10045.3.1.7" },
+       { GCRY_PK_ECC, "prime256v1" },
+       { GCRY_PK_ECC, "secp256r1" },
+       { GCRY_PK_ECC, "nistp256"  },
+
+       { GCRY_PK_ECC, "NIST P-384" },
+       { GCRY_PK_ECC, "secp384r1" },
+       { GCRY_PK_ECC, "1.3.132.0.34" },
+       { GCRY_PK_ECC, "nistp384"   },
+
+       { GCRY_PK_ECC, "NIST P-521" },
+       { GCRY_PK_ECC, "secp521r1" },
+       { GCRY_PK_ECC, "1.3.132.0.35" },
+       { GCRY_PK_ECC, "nistp521"   },
+
+       { GCRY_PK_ECC, "brainpoolP160r1",       TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.1",  TEST_NOFIPS },
+       { GCRY_PK_ECC, "brainpoolP192r1",       TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.3",  TEST_NOFIPS },
+       { GCRY_PK_ECC, "brainpoolP224r1",       TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.5",  TEST_NOFIPS },
+       { GCRY_PK_ECC, "brainpoolP256r1",       TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.7",  TEST_NOFIPS },
+       { GCRY_PK_ECC, "brainpoolP320r1",       TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.9",  TEST_NOFIPS },
+       { GCRY_PK_ECC, "brainpoolP384r1",       TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.11", TEST_NOFIPS },
+       { GCRY_PK_ECC, "brainpoolP512r1",       TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.36.3.3.2.8.1.1.13", TEST_NOFIPS },
+
+       { GCRY_PK_ECC, "GOST2001-test", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.2.2.35.0", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.2.2.35.1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-B", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.2.2.35.2", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.2.2.35.3", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-XchA", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-XchB", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.2.2.36.0", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.2.2.36.1", TEST_NOFIPS },
+
+       /* Noet that GOST2012-256-tc26-A" is only in the curve alias
+        * list but has no parameter entry.  */
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.7.1.2.1.1.2", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-A", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-256-tc26-B", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-B", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.7.1.2.1.1.3", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-B", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-256-tc26-C", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.7.1.2.1.1.4", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2001-CryptoPro-C", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-256-tc26-D", TEST_NOFIPS },
+
+       { GCRY_PK_ECC, "GOST2012-512-test", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-test", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-512-test", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.7.1.2.1.2.0", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-512-tc26-A", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-tc26-A", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-512-tc26-B", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-tc26-B", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-512-tc26-A", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.7.1.2.1.2.1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-512-tc26-B", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.7.1.2.1.2.2", TEST_NOFIPS },
+       { GCRY_PK_ECC, "GOST2012-512-tc26-C", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.643.7.1.2.1.2.3", TEST_NOFIPS },
+
+       { GCRY_PK_ECC, "secp256k1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.3.132.0.10", TEST_NOFIPS },
+
+       { GCRY_PK_ECC, "sm2p256v1", TEST_NOFIPS },
+       { GCRY_PK_ECC, "1.2.156.10197.1.301", TEST_NOFIPS },
+
+       /* Check also the ECC algo mapping.  */
+       { GCRY_PK_ECDSA, "Ed25519", TEST_NOFIPS },
+       { GCRY_PK_EDDSA, "Ed25519", TEST_NOFIPS },
+       { GCRY_PK_ECDH,  "Ed25519", TEST_NOFIPS },
+       { GCRY_PK_ECDSA, "Curve25519", TEST_NOFIPS },
+       { GCRY_PK_EDDSA, "Curve25519", TEST_NOFIPS },
+       { GCRY_PK_ECDH,  "Curve25519", TEST_NOFIPS },
+       { GCRY_PK_ECC,   "NoSuchCurve", TEST_ERROR_EXPECTED },
+       { GCRY_PK_RSA,   "rsa", TEST_ERROR_EXPECTED },
+       { GCRY_PK_ELG,   "elg", TEST_ERROR_EXPECTED },
+       { GCRY_PK_DSA,   "dsa", TEST_ERROR_EXPECTED }
+      };
+  int idx;
   gcry_sexp_t param;
   const char *name;
 
@@ -148,22 +282,47 @@ check_get_params (void)
 
   gcry_sexp_release (param);
 
-  /* Brainpool curves are not supported in fips mode */
-  if (gcry_fips_mode_active())
-    return;
+  if (!in_fips_mode)
+    {
+      param = gcry_pk_get_param (GCRY_PK_ECDSA, sample_key_2_curve);
+      if (!param)
+        fail ("error gerring parameters for `%s'\n", sample_key_2_curve);
 
-  param = gcry_pk_get_param (GCRY_PK_ECDSA, sample_key_2_curve);
-  if (!param)
-    fail ("error gerring parameters for `%s'\n", sample_key_2_curve);
+      name = gcry_pk_get_curve (param, 0, NULL);
+      if (!name)
+        fail ("get_param: curve name not found for sample_key_2\n");
+      else if (strcmp (name, sample_key_2_curve))
+        fail ("get_param: expected curve name %s but got %s for sample_key_2\n",
+              sample_key_2_curve, name);
 
-  name = gcry_pk_get_curve (param, 0, NULL);
-  if (!name)
-    fail ("get_param: curve name not found for sample_key_2\n");
-  else if (strcmp (name, sample_key_2_curve))
-    fail ("get_param: expected curve name %s but got %s for sample_key_2\n",
-          sample_key_2_curve, name);
+      gcry_sexp_release (param);
+    }
 
-  gcry_sexp_release (param);
+  /* Some simple tests */
+  for (idx=0; idx < DIM (tv); idx++)
+    {
+      param = gcry_pk_get_param (tv[idx].algo, tv[idx].name);
+      if (in_fips_mode && tv[idx].flags & TEST_NOFIPS)
+        {
+          if (param)
+            fail ("get_param: test %d (%s) should have failed in fips mode\n",
+                  idx, tv[idx].name);
+        }
+      else {
+        if (!param)
+          {
+            if (!(tv[idx].flags & TEST_ERROR_EXPECTED))
+              fail ("get_param: test %d (%s) failed\n", idx, tv[idx].name);
+          }
+        else
+          {
+            if (tv[idx].flags & TEST_ERROR_EXPECTED)
+              fail ("get_param: test %d (%s) failed (error expected)\n",
+                    idx, tv[idx].name);
+          }
+        }
+      gcry_sexp_release (param);
+    }
 }
 
 
@@ -178,10 +337,14 @@ main (int argc, char **argv)
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
   list_curves ();
   check_matching ();
   check_get_params ();
index 2cfa94a..79b25c3 100644 (file)
@@ -33,6 +33,7 @@
 #define PGM "dsa-rfc6979"
 #include "t-common.h"
 
+static int in_fips_mode;
 
 static void
 show_sexp (const char *prefix, gcry_sexp_t a)
@@ -111,6 +112,7 @@ check_dsa_rfc6979 (void)
   static struct {
     const char *name;
     const char *key;
+    int fips;
   } keys[] = {
     {
       "DSA, 1024 bits",
@@ -130,7 +132,7 @@ check_dsa_rfc6979 (void)
       "     92195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D"
       "     4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E6"
       "     82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B#)"
-      " ))"
+      " ))", 0
     },
     {
       "DSA, 2048 bits",
@@ -162,7 +164,7 @@ check_dsa_rfc6979 (void)
       "     687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D1"
       "     23AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA"
       "     74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)"
-      " ))"
+      " ))", 0
     },
     {
       "ECDSA, 192 bits (prime field)",
@@ -172,7 +174,7 @@ check_dsa_rfc6979 (void)
       " (q #04AC2C77F529F91689FEA0EA5EFEC7F210D8EEA0B9E047ED56"
       "       3BC723E57670BD4887EBC732C523063D0A7C957BC97C1C43#)"
       " (d #6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4#)"
-      " ))"
+      " ))", 0
     },
     {
       "ECDSA, 224 bits (prime field)",
@@ -183,7 +185,7 @@ check_dsa_rfc6979 (void)
       "     00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C"
       "     EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A#)"
       " (d #F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1#)"
-      " ))"
+      " ))", 1
     },
     {
       "ECDSA, 256 bits (prime field)",
@@ -194,7 +196,7 @@ check_dsa_rfc6979 (void)
       "     60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"
       "     7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)"
       " (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)"
-      " ))"
+      " ))", 1
     },
     {
       "ECDSA, 384 bits (prime field)",
@@ -208,7 +210,7 @@ check_dsa_rfc6979 (void)
       "     288B231C3AE0D4FE7344FD2533264720#)"
       " (d #6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8"
       "     96D5724E4C70A825F872C9EA60D2EDF5#)"
-      " ))"
+      " ))", 1
     },
     {
       "ECDSA, 521 bits (prime field)",
@@ -225,7 +227,7 @@ check_dsa_rfc6979 (void)
       " (d #FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75"
       "     CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B8"
       "     3538#)"
-      " ))"
+      " ))", 1
     },
     { NULL }
   };
@@ -937,6 +939,14 @@ check_dsa_rfc6979 (void)
         die ("building data sexp failed: %s\n", gpg_strerror (err));
 
       err = gcry_pk_sign (&sig, data, seckey);
+      if (in_fips_mode && !keys[i].fips)
+        {
+          if (!err)
+            fail ("signing should not work in FIPS mode: %s\n", gpg_strerror (err));
+          gcry_sexp_release (data);
+          gcry_sexp_release (seckey);
+          continue;
+        }
       if (err)
         fail ("signing failed: %s\n", gpg_strerror (err));
 
@@ -966,16 +976,18 @@ main (int argc, char **argv)
       debug = 1;
     }
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   /* Check that we test exactly our version - including the patchlevel.  */
   if (strcmp (GCRYPT_VERSION, gcry_check_version (NULL)))
     die ("version mismatch; pgm=%s, library=%s\n",
          GCRYPT_VERSION,gcry_check_version (NULL));
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
   /* No valuable keys are create, so we can speed up our RNG. */
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
 
   check_dsa_rfc6979 ();
 
index b5f0cf0..3f7c0d1 100644 (file)
@@ -34,6 +34,7 @@
 #define PGM "fips186-dsa"
 #include "t-common.h"
 
+static int in_fips_mode;
 
 static void
 show_sexp (const char *prefix, gcry_sexp_t a)
@@ -154,7 +155,7 @@ check_dsa_gen_186_2 (void)
     int counter;
     const char *h;
   } tbl[] = {
-    /* These tests are from FIPS 186-2, B.3.1.  */
+    /* These tests are from FIPS 186-2, DSAVS B.3.1 PQGGen.rsp.  CAVS 2.2.  */
     {
       1024,
       "d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921"
@@ -352,7 +353,13 @@ check_dsa_gen_186_2 (void)
       gcry_sexp_release (key_spec);
       if (err)
         {
-          fail ("error generating key %d: %s\n", tno, gpg_strerror (err));
+          if (in_fips_mode)
+            {
+              if (verbose > 1)
+                fprintf (stderr, "DSA keys are not available in FIPS mode");
+            }
+          else
+            fail ("error generating key %d: %s\n", tno, gpg_strerror (err));
           continue;
         }
 
@@ -394,9 +401,158 @@ check_dsa_gen_186_2 (void)
 static void
 check_dsa_gen_186_3 (void)
 {
-  /* FIXME: Needs to be implemented.  */
-  if (verbose)
-    info ("generating FIPS 186-3 test keys - skipped\n");
+  static struct {
+    int nbits, qbits;
+    const char *p, *q;
+    const char *seed;
+    int counter;
+  } tbl[] = {
+    /* These tests are from FIPS 186-3 Test Vectors, PQGGen.rsp.  CAVS 11.1.  */
+    {
+      2048,
+      256,
+      "8e2266d5cb5b1e9ad34ac6380e3d166fd4d60dadc6dfa1be8492a5642c91fdf7"
+      "e81b9634a4eeff59e7e93b1b0e8f49ded45a72788866dff71b1329feeb4b6cdb"
+      "f2c7166c7cbca20b04300ae127c9940233e891712ac905ed6b43495717a2998e"
+      "a8c4eef4ec6c32dc9e774e8e66476f17d9c39abac59e8b583b1107b679e0bed0"
+      "78476e933a90cfcf80c89b831c0e054f86eac7ca848e059662d938a4e12947e2"
+      "e73b1ffedd7125dd54ba463217abc9c5f3399132aec77b946c806429f6f812c1"
+      "0716d57dde7b5d45cb2e5eb6e4dbb81d5a465054fa17e613cbe01afb49ea593f"
+      "33f1a696a774941ca1ff6f208577fe529f5e7592f39698c63bf6ae9d56cd2d93",
+      "b19c6d094e1210c92910f49aa083957fbe68c0ca4602896f50123fd776786275",
+      "f770a4598ff756931fc529764513b103ce57d85f4ad8c5cf297c9b4d48241c5b",
+      105
+    },
+    {
+      2048,
+      256,
+      "b636e5970383cecab68840cca8a909a29325c3924e2c187dd034222f9e1a4334"
+      "1061ca620f82787bd349fb8f380fc3f0adb84be116c695529114aecee8a0a1b0"
+      "9e7ebb6888e6da71f48eefb3e9990e2d7bd36c1aa24fb10e011a193d6b5a1b22"
+      "6cf97fab302e237ecb1dc824264dba2e2285930005717c4e9a12cc1a1ac336c2"
+      "0619c4d06ec4e1e02e0d1d2d285661a7472d30c4282646506487cbe6a5c988ee"
+      "8402d474713a7d8213eeb19a0719996bbfd3835eb8832eead5a3a340e61c52f0"
+      "0dde1c98655a13839ad215d8f43c8e482317af8b086c3d555fc8dbb2f595f256"
+      "3520a0c6387661774e1e6ca5fe2626b26a2c4f99b7aff043a091434dfd3275b7",
+      "fe9f06fa1901182ab00bf063bff8fd4f736922ce830fd50fee47ebbd21e291e9",
+      "3a66a430f23374ce3d2e758881c411c23dad4a8cd6ad697056d24b8cfcc8c353",
+      720
+    },
+    {
+      2048,
+      256,
+      "8d636640981c2ce1935bd16ad3aa3ce2a6efa26f23f07ceda92766f80e82fa03"
+      "5c6cf44dc41e08fea242c5cd5846d839bdf0c11d3a29ebaca00aad844cd33a80"
+      "448f1f96cebe66b9963f7e3b5c976e29dc430bc5ddf5d2c198eb736339adc14d"
+      "5c8a3d22533d7c6a861b6a8b31c55e46804e4c2f95e2e9cc2bbb23bbc833995a"
+      "7afe619127d28fa53b0712b17da4786f9116cc39e2c6254845e85513c220e368"
+      "fe9c92bc71eabfa831062f01e66e8a970f043112ca0af175f64d13fcff2f087f"
+      "ff9198a9fe9732001ab49b2a48d0e39f99d036698703aa853ac02c65f3d55993"
+      "5a72c8bbc6ab2fa59ff9a2fcd837a4675229abed23d42badc12a60b34a3bf0f5",
+      "b5f3c535e7f48d3251d353b73b3a05c4bdb4591a8c2f2ba4a6a945a889f5aeff",
+      "77eb88f087bfbbc312bca7572bafd36f2a7aca2e4d7378dd923b0b277f3d730f",
+      137
+    },
+    {
+      2048,
+      256,
+      "8fa95228b848a9533375e4789c88bb7df505c4478ed3c79545c5d2b04f0e0efb"
+      "ac8d3f603603a48b203e1cc67ded22b840ac21bc41b7ab78c73a9cd0773148ca"
+      "7c87a5a51564164f683e8f8a77b97cf7d91f989aa3668819bca8f54e0ec8f10c"
+      "78ecd26982048cf0ab0446a6de154bbed8891be916627d470061811caf51bef1"
+      "b5be8ef2b560cf981c2a097b3769bed61d6ee9b66221e956fe2c49f1809a2d5f"
+      "6996be7b39f41afea5184a73c049f3abbd28fddbf37bcae6c4aa4a7255464c2e"
+      "ee915c44b8d90d76e5d9e3d8e6cf4ac7c5d9436d19ccc27c5bc1b65dbb56723b"
+      "5e77624489652313f9da2ce38554401fdbd61c78f2a4fa69bcc2f5aaffbfed2d",
+      "ed3f52bce81572d126b27fb1e9c02346ae523532af82b79943565593d6f46d45",
+      "e0ed96bf5e7d78754b5095ed766a1bbc4338eaa8f3d00e9906ef51a8798bc1c2",
+      40
+    },
+    {
+      2048,
+      256,
+      "a80f2481a814d07eb47a7c67e24bc3f8f1ccebc6cf684a0bc9fbb0054cc24cef"
+      "24872315b566630d5147184980b4bce3f0849660c84b22dfacb785446c0f6314"
+      "b7a53a92cf821bcceb325e03dc9e404832146d34ff8a9b112ed0e69efe69c619"
+      "5de03373e590eba88fc5b9d337d6566dc7e82e326a28343f644779f6784159eb"
+      "3d33f2ddf1157a02f2f91d0897a4e8ad53f614186a5fe043187510316904bd95"
+      "6966e10735d6ef01c195b7dd7fd245a83c18af7908fef0bced2f454e1954f2a3"
+      "2c35658f4e0f5811a3d06c81cca715537debabbbc65ba4dd0e7fb0c08397622f"
+      "039a51df69f5b10dda61f57bbb84c55f25eacd0f3d8b40ae016ed0ba856837e7",
+      "9e3b5a7939082c95069902d3833df8421871ca2dab8a34f7be6cd39151291d07",
+      "c7bb440d973189ca07464b037fd309f68ec38baba390988a2e986ecee281e2f5",
+      722
+    }
+  };
+  gpg_error_t err;
+  int tno;
+  gcry_sexp_t key_spec, key, pub_key, sec_key, seed_values;
+  gcry_sexp_t l1;
+
+  for (tno = 0; tno < DIM (tbl); tno++)
+    {
+      if (verbose)
+        info ("generating FIPS 186-3 test key %d\n", tno);
+
+      {
+        void *data;
+        size_t datalen;
+
+        data = data_from_hex (tbl[tno].seed, &datalen);
+        err = gcry_sexp_build (&key_spec, NULL,
+                               "(genkey (dsa (nbits %d)(qbits %d)(use-fips186)"
+                               "(derive-parms(seed %b))))",
+                               tbl[tno].nbits, tbl[tno].qbits,
+                               (int)datalen, data);
+        gcry_free (data);
+      }
+      if (err)
+        die ("error creating S-expression %d: %s\n", tno, gpg_strerror (err));
+
+      err = gcry_pk_genkey (&key, key_spec);
+      gcry_sexp_release (key_spec);
+      if (err)
+        {
+          if (in_fips_mode)
+            {
+              if (verbose > 1)
+                fprintf (stderr, "DSA keys are not available in FIPS mode");
+            }
+          else
+            fail ("error generating key %d: %s\n", tno, gpg_strerror (err));
+          continue;
+        }
+
+      if (verbose > 1)
+        show_sexp ("generated key:\n", key);
+
+      pub_key = gcry_sexp_find_token (key, "public-key", 0);
+      if (!pub_key)
+        fail ("public part missing in key %d\n", tno);
+
+      sec_key = gcry_sexp_find_token (key, "private-key", 0);
+      if (!sec_key)
+        fail ("private part missing in key %d\n", tno);
+
+      l1 = gcry_sexp_find_token (key, "misc-key-info", 0);
+      if (!l1)
+        fail ("misc_key_info part missing in key %d\n", tno);
+      seed_values = gcry_sexp_find_token (l1, "seed-values", 0);
+      if (!seed_values)
+        fail ("seed-values part missing in key %d\n", tno);
+      gcry_sexp_release (l1);
+
+      extract_cmp_mpi (sec_key, "p", tbl[tno].p);
+      extract_cmp_mpi (sec_key, "q", tbl[tno].q);
+
+      extract_cmp_data (seed_values, "seed", tbl[tno].seed);
+      extract_cmp_int (seed_values, "counter", tbl[tno].counter);
+
+      gcry_sexp_release (seed_values);
+      gcry_sexp_release (sec_key);
+      gcry_sexp_release (pub_key);
+      gcry_sexp_release (key);
+    }
 }
 
 
@@ -411,15 +567,18 @@ main (int argc, char **argv)
       debug = 1;
     }
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
   /* No valuable keys are create, so we can speed up our RNG. */
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+
 
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
 
   check_dsa_gen_186_2 ();
   check_dsa_gen_186_3 ();
index f9d9c45..f6268e2 100644 (file)
@@ -929,7 +929,7 @@ run_external_rng_test (void *context, void *buffer, size_t buflen)
 static void
 deinit_external_rng_test (void *context)
 {
-  xgcry_control (PRIV_CTL_DEINIT_EXTRNG_TEST, context);
+  xgcry_control ((PRIV_CTL_DEINIT_EXTRNG_TEST, context));
 }
 
 
@@ -1835,7 +1835,7 @@ print_dsa_domain_parameters (gcry_sexp_t key)
   /* Extract the parameters from the S-expression and print them to stdout.  */
   for (idx=0; "pqg"[idx]; idx++)
     {
-      l2 = gcry_sexp_find_token (l1, "pqg"+idx, 1);
+      l2 = gcry_sexp_find_token (l1, &"pqg"[idx], 1);
       if (!l2)
         die ("no %c parameter in returned public key\n", "pqg"[idx]);
       mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
@@ -1923,7 +1923,7 @@ print_ecdsa_dq (gcry_sexp_t key)
   /* Extract the parameters from the S-expression and print them to stdout.  */
   for (idx=0; "dq"[idx]; idx++)
     {
-      l2 = gcry_sexp_find_token (l1, "dq"+idx, 1);
+      l2 = gcry_sexp_find_token (l1, &"dq"[idx], 1);
       if (!l2)
         die ("no %c parameter in returned public key\n", "dq"[idx]);
       mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
@@ -2476,16 +2476,16 @@ main (int argc, char **argv)
   if (verbose)
     fprintf (stderr, PGM ": started (mode=%s)\n", mode_string);
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
   if (!no_fips)
-    xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
+    xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0));
   if (!gcry_check_version ("1.4.3"))
     die ("Libgcrypt is not sufficient enough\n");
   if (verbose)
     fprintf (stderr, PGM ": using Libgcrypt %s\n", gcry_check_version (NULL));
   if (no_fips)
-    xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+    xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
   /* Most operations need some input data.  */
   if (!chunksize
diff --git a/tests/fipsrngdrv.c b/tests/fipsrngdrv.c
new file mode 100644 (file)
index 0000000..17cc920
--- /dev/null
@@ -0,0 +1,271 @@
+/* fipsrngdrv.c  -  A driver to test the FIPS RNG.
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <ctype.h>
+#ifndef HAVE_W32_SYSTEM
+# include <signal.h>
+#endif
+
+#include <gcrypt.h>
+
+#define PGM "fipsrngdrv"
+
+#define my_isascii(c) (!((c) & 0x80))
+#define digitp(p)   (*(p) >= '0' && *(p) <= '9')
+#define hexdigitp(a) (digitp (a)                     \
+                      || (*(a) >= 'A' && *(a) <= 'F')  \
+                      || (*(a) >= 'a' && *(a) <= 'f'))
+#define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
+                     *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+
+static void
+die (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  va_start (arg_ptr, format);
+  fputs (PGM ": ", stderr);
+  vfprintf (stderr, format, arg_ptr);
+  va_end (arg_ptr);
+  exit (1);
+}
+
+
+/* Convert STRING consisting of hex characters into its binary
+   representation and store that at BUFFER.  BUFFER needs to be of
+   LENGTH bytes.  The function checks that the STRING will convert
+   exactly to LENGTH bytes. The string is delimited by either end of
+   string or a white space character.  The function returns -1 on
+   error or the length of the parsed string.  */
+static int
+hex2bin (const char *string, void *buffer, size_t length)
+{
+  int i;
+  const char *s = string;
+
+  for (i=0; i < length; )
+    {
+      if (!hexdigitp (s) || !hexdigitp (s+1))
+        return -1;           /* Invalid hex digits. */
+      ((unsigned char*)buffer)[i++] = xtoi_2 (s);
+      s += 2;
+    }
+  if (*s && (!my_isascii (*s) || !isspace (*s)) )
+    return -1;             /* Not followed by Nul or white space.  */
+  if (i != length)
+    return -1;             /* Not of expected length.  */
+  if (*s)
+    s++; /* Skip the delimiter. */
+  return s - string;
+}
+
+
+
+
+static gcry_error_t
+init_external_test (void **r_context,
+                    unsigned int flags,
+                    const void *key, size_t keylen,
+                    const void *seed, size_t seedlen,
+                    const void *dt, size_t dtlen)
+{
+  return gcry_control (58,
+                       r_context, flags,
+                       key, keylen,
+                       seed, seedlen,
+                       dt, dtlen);
+}
+
+static gcry_error_t
+run_external_test (void *context, void *buffer, size_t buflen)
+{
+  return gcry_control (59, context, buffer, buflen);
+}
+
+static void
+deinit_external_test (void *context)
+{
+  xgcry_control ((60, context));
+}
+
+
+static void
+print_buffer (const unsigned char *buffer, size_t length)
+{
+  while (length--)
+    printf ("%02X", *buffer++);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  int verbose = 0;
+  int binary = 0;
+  int loop = 0;
+  int progress = 0;
+  int no_fips = 0;
+  unsigned char key[16];
+  unsigned char seed[16];
+  unsigned char dt[16];
+  void *context;
+  gpg_error_t err;
+  unsigned char buffer[16];
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM
+                 " [--verbose] [--binary] [--loop] [--progress] KEY V DT\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--no-fips"))
+        {
+          no_fips++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--binary"))
+        {
+          binary = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--loop"))
+        {
+          loop = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--progress"))
+        {
+          progress = 1;
+          argc--; argv++;
+        }
+    }
+
+  if (!argc)
+    {
+      memcpy (key,  "1234567890123456", 16);
+      memcpy (seed, "abcdefghijklmnop", 16);
+      memcpy (dt,   "XXXXXXXXXXXXXXXX", 16);
+    }
+  else if (argc == 3)
+    {
+      if (    hex2bin (argv[0], key, 16) < 0
+           || hex2bin (argv[1], seed, 16) < 0
+           || hex2bin (argv[2], dt, 16) < 0 )
+        die ("args are not 32 hex digits each\n");
+    }
+  else
+    die ("invalid usage (try --help)\n");
+
+#ifndef HAVE_W32_SYSTEM
+  if (loop)
+    signal (SIGPIPE, SIG_IGN);
+#endif
+
+  if (verbose)
+    fputs (PGM ": started\n", stderr);
+
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
+  if (!no_fips)
+    xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0));
+  if (!gcry_check_version ("1.4.3"))
+    die ("version mismatch\n");
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  /* The flag value 1 disables the dup check, so that the RNG returns
+     all generated data.  */
+  err = init_external_test (&context, 1, key, 16, seed, 16, dt, 16);
+  if (err)
+    die ("init external test failed: %s\n", gpg_strerror (err));
+
+  do
+    {
+      int writerr = 0;
+
+      err = run_external_test (context, buffer, sizeof buffer);
+      if (err)
+        die ("run external test failed: %s\n", gpg_strerror (err));
+      if (binary)
+        {
+          if (fwrite (buffer, 16, 1, stdout) != 1)
+            writerr = 1;
+          else
+            fflush (stdout);
+        }
+      else
+        {
+          print_buffer (buffer, sizeof buffer);
+          if (putchar ('\n') == EOF)
+            writerr = 1;
+        }
+      if (writerr)
+        {
+#ifndef HAVE_W32_SYSTEM
+          if (loop && errno == EPIPE)
+            break;
+#endif
+          die ("writing output failed: %s\n", strerror (errno));
+        }
+
+      if (progress)
+        {
+          putc ('.', stderr);
+          fflush (stderr);
+        }
+    }
+  while (loop);
+
+  if (progress)
+    putc ('\n', stderr);
+
+  deinit_external_test (context);
+
+  if (verbose)
+    fputs (PGM ": ready\n", stderr);
+
+  return 0;
+}
index 83dc7b5..43ce53b 100644 (file)
@@ -43,15 +43,15 @@ init_gcrypt (void)
     exit (2);
   }
 
-  xgcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
+  xgcry_control ((GCRYCTL_SUSPEND_SECMEM_WARN));
 
   /* Allocate a pool of 16k secure memory.  This make the secure memory
    * available and also drops privileges where needed.  */
-  xgcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+  xgcry_control ((GCRYCTL_INIT_SECMEM, 16384, 0));
 
-  xgcry_control (GCRYCTL_RESUME_SECMEM_WARN);
+  xgcry_control ((GCRYCTL_RESUME_SECMEM_WARN));
 
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 }
 
 int
index 92b1c1b..a52b869 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-algos="SHA1 SHA256 SHA512"
+algos="SHA1 SHA256 SHA512 SM3"
 
 test "@RUN_LARGE_DATA_TESTS@" = yes || exit 77
 echo "      now running 256 GiB tests for $algos - this takes looong"
index 2ecbc1f..4c9704f 100644 (file)
@@ -102,6 +102,17 @@ static struct {
     "0c91b91665ceaf7af5102e0ed31aa4f050668ab3c57b1f4763946d567efe66b3"
     "ab9a2016cf238dee5b44eae9f0cdfbf7b7a6eb1e759986273243dc35894706b6" },
 
+  { GCRY_MD_SM3, 256, -64,
+    "4ceb893abeb43965d4cac7626da9a4be895585b5b2f16f302626801308b1c02a" },
+  { GCRY_MD_SM3, 256, -1,
+    "825f01e4f2b6084136abc356fa1b343a9411d844a4dc1474293aad817cd2a48f" },
+  { GCRY_MD_SM3, 256, +0,
+    "d948a4025ac3ea0aa8989f43203411bd22ad17eaa5fd92ebdf9cabf869f1ba1b" },
+  { GCRY_MD_SM3, 256, +1,
+    "4f6d0e260299c1f286ef1dbb4638a0770979f266b6c007c55410ee6849cba2a8" },
+  { GCRY_MD_SM3, 256, +64,
+    "ed34869dbadd62e3bec1f511004d7bbfc9cafa965477cc48843b248293bbe867" },
+
   { 0 }
 };
 
@@ -383,13 +394,13 @@ main (int argc, char **argv)
   if (gigs < 0 || gigs > 1024*1024)
     die ("value for --gigs must be in the range 0 to %d", 1024*1024);
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
   /* A quick check that all given algorithms are valid.  */
   for (idx=0; idx < argc; idx++)
index 5852ee4..2b4c0f9 100644 (file)
@@ -192,10 +192,10 @@ main (int argc, char **argv)
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
   check_hmac ();
   check_hmac_multi ();
 
index 6b6a60a..5b154c9 100644 (file)
@@ -269,8 +269,10 @@ check_elg_keys (void)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
   rc = gcry_pk_genkey (&key, keyparm);
   gcry_sexp_release (keyparm);
-  if (rc)
+  if (rc && !in_fips_mode)
     die ("error generating Elgamal key: %s\n", gpg_strerror (rc));
+  else if (!rc && in_fips_mode)
+    die ("generating Elgamal key must not work in FIPS mode.");
   if (verbose > 1)
     show_sexp ("1024 bit Elgamal key:\n", key);
   gcry_sexp_release (key);
@@ -302,7 +304,7 @@ check_dsa_keys (void)
       if (rc && !in_fips_mode)
         die ("error generating DSA key: %s\n", gpg_strerror (rc));
       else if (!rc && in_fips_mode)
-        die ("generating 1024 bit DSA key must not work!");
+        die ("generating 1024 bit DSA key must not work in FIPS mode!");
       if (!i && verbose > 1)
         show_sexp ("1024 bit DSA key:\n", key);
       gcry_sexp_release (key);
@@ -323,7 +325,7 @@ check_dsa_keys (void)
   if (rc && !in_fips_mode)
     die ("error generating DSA key: %s\n", gpg_strerror (rc));
   else if (!rc && in_fips_mode)
-    die ("generating 1536 bit DSA key must not work!");
+    die ("generating 1536 bit DSA key must not work in FIPS mode!");
   if (verbose > 1)
     show_sexp ("1536 bit DSA key:\n", key);
   gcry_sexp_release (key);
@@ -340,8 +342,10 @@ check_dsa_keys (void)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
   rc = gcry_pk_genkey (&key, keyparm);
   gcry_sexp_release (keyparm);
-  if (rc)
+  if (rc && !in_fips_mode)
     die ("error generating DSA key: %s\n", gpg_strerror (rc));
+  else if (!rc && in_fips_mode)
+    die ("generating DSA key must not work in FIPS mode!");
   if (verbose > 1)
     show_sexp ("3072 bit DSA key:\n", key);
   gcry_sexp_release (key);
@@ -358,8 +362,10 @@ check_dsa_keys (void)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
   rc = gcry_pk_genkey (&key, keyparm);
   gcry_sexp_release (keyparm);
-  if (rc)
+  if (rc && !in_fips_mode)
     die ("error generating DSA key: %s\n", gpg_strerror (rc));
+  else if (!rc && in_fips_mode)
+    die ("generating DSA key must not work in FIPS mode!");
   if (verbose > 1)
     show_sexp ("2048 bit DSA key:\n", key);
   gcry_sexp_release (key);
@@ -376,8 +382,10 @@ check_dsa_keys (void)
     die ("error creating S-expression: %s\n", gpg_strerror (rc));
   rc = gcry_pk_genkey (&key, keyparm);
   gcry_sexp_release (keyparm);
-  if (rc)
+  if (rc && !in_fips_mode)
     die ("error generating DSA key: %s\n", gpg_strerror (rc));
+  else if (!rc && in_fips_mode)
+    die ("generating DSA key must not work in FIPS mode!");
   if (verbose > 1)
     show_sexp ("2048 bit DSA key:\n", key);
   gcry_sexp_release (key);
@@ -733,22 +741,22 @@ main (int argc, char **argv)
         break;
     }
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
   if (opt_fips)
-    xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
+    xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0));
 
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
   if (!opt_fips)
-    xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+    xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
 
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
   /* No valuable keys are create, so we can speed up our RNG. */
   if (!no_quick)
-    xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+    xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
   if (with_progress)
     gcry_set_progress_handler (progress_cb, NULL);
 
index f775f7a..49bd71b 100644 (file)
@@ -33,6 +33,9 @@
 
 static int repetitions;
 
+/* Whether fips mode was active at startup.  */
+static int in_fips_mode;
+
 \f
 
 static void
@@ -54,6 +57,7 @@ static struct
   int algo;
   const char *key;
   const unsigned char grip[20];
+  int skip_when_fips;
 } key_grips[] =
   {
     {
@@ -145,6 +149,54 @@ static struct
       " (q #04C8A4CEC2E9A9BC8E173531A67B0840DF345C32E261ADD780E6D83D56EFADFD5DE872F8B854819B59543CE0B7F822330464FBC4E6324DADDCD9D059554F63B344#)))",
       "\xE6\xDF\x94\x2D\xBD\x8C\x77\x05\xA3\xDD\x41\x6E\xFC\x04\x01\xDB\x31\x0E\x99\xB6"
     },
+    {
+      GCRY_PK_ECC,
+      "(public-key"
+      " (ecc"
+      " (curve brainpoolP256r1)"
+      " (q #042ECD8679930BE2DB4AD42B8600BA3F80"
+      /*   */"2D4D539BFF2F69B83EC9B7BBAA7F3406"
+      /*   */"436DD11A1756AFE56CD93408410FCDA9"
+      /*   */"BA95024EB613BD481A14FCFEC27A448A#)))",
+      "\x52\xBA\xD4\xB4\xA3\x2D\x32\xA1\xDD\x06"
+      "\x5E\x99\x0B\xF1\xAB\xC1\x13\x3D\x84\xD4",
+      1
+    },
+    { /* Compressed form of above.  */
+      GCRY_PK_ECC,
+      "(public-key"
+      " (ecc"
+      " (curve brainpoolP256r1)"
+      " (q #022ECD8679930BE2DB4AD42B8600BA3F80"
+      /*   */"2D4D539BFF2F69B83EC9B7BBAA7F3406#)))",
+      "\x52\xBA\xD4\xB4\xA3\x2D\x32\xA1\xDD\x06"
+      "\x5E\x99\x0B\xF1\xAB\xC1\x13\x3D\x84\xD4",
+      1
+    },
+    {
+      GCRY_PK_ECC,
+      "(public-key"
+      " (ecc"
+      " (curve brainpoolP256r1)"
+      " (q #045B784CA008EE64AB3D85017EE0D2BE87"
+      /*   */"558762C7300E0C8E06B1F9AF7C031458"
+      /*   */"9EBBA41915313417BA54218EB0569C59"
+      /*   */"0B156C76DBCAB6E84575E6EF68CE7B87#)))",
+      "\x99\x38\x6A\x82\x41\x96\x29\x9C\x89\x74"
+      "\xD6\xE1\xBF\x43\xAC\x9B\x9A\x12\xE7\x3F",
+      1
+    },
+    { /* Compressed form of above.  */
+      GCRY_PK_ECC,
+      "(public-key"
+      " (ecc"
+      " (curve brainpoolP256r1)"
+      " (q #035B784CA008EE64AB3D85017EE0D2BE87"
+      /*   */"558762C7300E0C8E06B1F9AF7C031458#)))",
+      "\x99\x38\x6A\x82\x41\x96\x29\x9C\x89\x74"
+      "\xD6\xE1\xBF\x43\xAC\x9B\x9A\x12\xE7\x3F",
+      1
+    },
     { /* Ed25519 standard */
       GCRY_PK_ECC,
       "(public-key"
@@ -155,7 +207,8 @@ static struct
       "     47BD24842905C049257673B3F5249524E0A41FAA17B25B818D0F97E625F1A1D0#)"
       "     ))",
       "\x0C\xCA\xB2\xFD\x48\x9A\x33\x40\x2C\xE8"
-      "\xE0\x4A\x1F\xB2\x45\xEA\x80\x3D\x0A\xF1"
+      "\xE0\x4A\x1F\xB2\x45\xEA\x80\x3D\x0A\xF1",
+      1
     },
     { /* Ed25519+EdDSA */
       GCRY_PK_ECC,
@@ -165,7 +218,8 @@ static struct
       " (q #773E72848C1FD5F9652B29E2E7AF79571A04990E96F2016BF4E0EC1890C2B7DB#)"
       " ))",
       "\x9D\xB6\xC6\x4A\x38\x83\x0F\x49\x60\x70"
-      "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47"
+      "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47",
+      1
     },
     { /* Ed25519+EdDSA (with compression prefix) */
       GCRY_PK_ECC,
@@ -176,7 +230,8 @@ static struct
       "     773E72848C1FD5F9652B29E2E7AF79571A04990E96F2016BF4E0EC1890C2B7DB#)"
       " ))",
       "\x9D\xB6\xC6\x4A\x38\x83\x0F\x49\x60\x70"
-      "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47"
+      "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47",
+      1
     },
     { /* Ed25519+EdDSA  (same but uncompressed)*/
       GCRY_PK_ECC,
@@ -188,7 +243,40 @@ static struct
       "     5bb7c29018ece0f46b01f2960e99041a5779afe7e2292b65f9d51f8c84723e77#)"
       " ))",
       "\x9D\xB6\xC6\x4A\x38\x83\x0F\x49\x60\x70"
-      "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47"
+      "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47",
+      1
+    },
+    { /* Cv25519 */
+      GCRY_PK_ECC,
+      "(public-key"
+      " (ecc"
+      " (curve Curve25519)(flags djb-tweak)"
+      " (q #40"
+      "     918C1733127F6BF2646FAE3D081A18AE77111C903B906310B077505EFFF12740#)"
+      " ))",
+      "\x0F\x89\xA5\x65\xD3\xEA\x18\x7C\xE8\x39"
+      "\x33\x23\x98\xF5\xD4\x80\x67\x7D\xF4\x9C",
+      1
+    },
+    { /* Random key  */
+      GCRY_PK_RSA,
+      "(shadowed-private-key"
+      " (rsa"
+      " (n #00B493C79928398DA9D99AC0E949FE6EB62F683CB974FFFBFBC01066F5C9A89B"
+      "     D3DC48EAD7C65F36EA943C2B2C865C26C4884FF9EDFDA8C99C855B737D77EEF6"
+      "     B85DBC0CCEC0E900C1F89A6893A2A93E8B31028469B6927CEB2F08687E547C68"
+      "     6B0A2F7E50A194FF7AB7637E03DE0912EF7F6E5F1EC37625BD1620CCC2E7A564"
+      "     31E168CDAFBD1D9E61AE47A69A6FA03EF22F844528A710B2392F262B95A3078C"
+      "     F321DC8325F92A5691EF69F34FD0DE0B22C79D29DC87723FCADE463829E8E5F7"
+      "     D196D73D6C9C180F6A6A0DDBF7B9D8F7FA293C36163B12199EF6A1A95CAE4051"
+      "     E3069C522CC6C4A7110F663A5DAD20F66C13A1674D050088208FAE4F33B3AB51"
+      "     03#)"
+      " (e #00010001#)"
+      " (shadowed t1-v1"
+      " (#D2760001240102000005000123350000# OPENPGP.1)"
+      ")))",
+      "\xE5\x6E\xE6\xEE\x5A\x2F\xDC\x3E\x98\x9D"
+      "\xFE\x49\xDA\xF5\x67\x43\xE3\x27\x28\x33"
     }
   };
 
@@ -205,6 +293,9 @@ check (void)
 
   for (i = 0; i < (sizeof (key_grips) / sizeof (*key_grips)); i++)
     {
+      if (in_fips_mode && key_grips[i].skip_when_fips)
+        continue;
+
       if (gcry_pk_test_algo (key_grips[i].algo))
         {
           if (verbose)
@@ -217,6 +308,9 @@ check (void)
       if (err)
         die ("scanning data %d failed: %s\n", i, gpg_strerror (err));
 
+      if (debug)
+        info ("check(%d): s-exp='%s'\n", i, key_grips[i].key);
+
       for (repn=0; repn < repetitions; repn++)
         {
           ret = gcry_pk_get_keygrip (sexp, buf);
@@ -228,6 +322,8 @@ check (void)
               print_hex ("keygrip: ", buf, sizeof buf);
               die ("keygrip for %d does not match\n", i);
             }
+          else if (debug && !repn)
+            print_hex ("keygrip: ", buf, sizeof buf);
         }
 
       gcry_sexp_release (sexp);
@@ -294,10 +390,13 @@ main (int argc, char **argv)
 
   gcry_set_progress_handler (progress_handler, NULL);
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
 
   check ();
 
index 18156d1..48ea18b 100644 (file)
@@ -205,6 +205,7 @@ test_maxsize (void)
 {
   gpg_error_t err;
   gcry_mpi_t a;
+  unsigned int val;
   char buffer[2+2048]; /* For PGP: 2 length bytes and 16384 bits.  */
 
   memset (buffer, 0x55, sizeof buffer);
@@ -232,7 +233,36 @@ test_maxsize (void)
   err = gcry_mpi_scan (&a, GCRYMPI_FMT_PGP, buffer, sizeof buffer, NULL);
   if (err)
     die ("gcry_mpi_scan did not parse a large PGP: %s\n", gpg_strerror (err));
+
+  /* Let's also test get_ui.  */
+  gcry_mpi_set_ui (a, 0);
+  val = 4711;
+  err = gcry_mpi_get_ui (&val, a);
+  if (err || val != 0)
+    die ("gcry_mpi_get_ui failed at %d: %s\n", __LINE__, gpg_strerror (err));
+
+  gcry_mpi_sub_ui (a, a, 1);
+  val = 4711;
+  err = gcry_mpi_get_ui (&val, a);
+  if (gpg_err_code (err) != GPG_ERR_ERANGE || val != 4711)
+    die ("gcry_mpi_get_ui failed at %d: %s\n", __LINE__, gpg_strerror (err));
+
+  gcry_mpi_set_ui (a, 0xffffffff);
+  val = 4711;
+  err = gcry_mpi_get_ui (&val, a);
+  if (err || val != 0xffffffff)
+    die ("gcry_mpi_get_ui failed at %d: %s\n", __LINE__, gpg_strerror (err));
+
+  if (sizeof (val) == 4)
+    {
+      gcry_mpi_add_ui (a, a, 1);
+      err = gcry_mpi_get_ui (&val, a);
+      if (gpg_err_code (err) != GPG_ERR_ERANGE)
+        die ("gcry_mpi_get_ui failed at %d: %s\n", __LINE__,gpg_strerror (err));
+    }
+
   gcry_mpi_release (a);
+
 }
 
 
@@ -348,7 +378,8 @@ test_add (void)
   gcry_mpi_t two;
   gcry_mpi_t ff;
   gcry_mpi_t result;
-  unsigned char* pc;
+  gcry_mpi_t minusfive;
+  char *pc;
 
   gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL);
   gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL);
@@ -356,21 +387,47 @@ test_add (void)
   result = gcry_mpi_new(0);
 
   gcry_mpi_add(result, one, two);
-  gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result);
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
   if (debug)
     gcry_log_debug ("Result of one plus two:\n%s\n", pc);
+  if (strcmp (pc, "030303030303030303030303030303030303030303030303"
+                  "030303030303030303030303030303030303030303030303") != 0)
+    fail ("mpi_add failed at line %d", __LINE__);
   gcry_free(pc);
 
   gcry_mpi_add(result, ff, one);
-  gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result);
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
   if (debug)
     gcry_log_debug ("Result of ff plus one:\n%s\n", pc);
+  if (strcmp (pc, "010101010101010101010101010101010101010101010101"
+                  "01010101010101010101010101010101010101010101010100") != 0)
+    fail ("mpi_add failed at line %d", __LINE__);
+  gcry_free(pc);
+
+  gcry_mpi_scan(&minusfive, GCRYMPI_FMT_HEX, "-5", 0, NULL);
+  gcry_mpi_add_ui (result, minusfive, 2);
+
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
+  if (debug)
+    gcry_log_debug ("Result of minus five plus two:\n%s\n", pc);
+  if (strcmp (pc, "-03") != 0)
+    fail ("mpi_add_ui failed at line %d", __LINE__);
+  gcry_free(pc);
+
+  gcry_mpi_add_ui (result, result, 3);
+
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
+  if (debug)
+    gcry_log_debug ("Result of minus three plus three:\n%s\n", pc);
+  if (strcmp (pc, "00") != 0)
+    fail ("mpi_add_ui failed at line %d", __LINE__);
   gcry_free(pc);
 
   gcry_mpi_release(one);
   gcry_mpi_release(two);
   gcry_mpi_release(ff);
   gcry_mpi_release(result);
+  gcry_mpi_release(minusfive);
   return 1;
 }
 
@@ -378,24 +435,76 @@ test_add (void)
 static int
 test_sub (void)
 {
+  gcry_mpi_t zero;
   gcry_mpi_t one;
   gcry_mpi_t two;
+  gcry_mpi_t five;
   gcry_mpi_t result;
-  unsigned char* pc;
+  gcry_mpi_t minusfive;
+  char *pc;
 
   gcry_mpi_scan(&one, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL);
   gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL);
   result = gcry_mpi_new(0);
   gcry_mpi_sub(result, two, one);
 
-  gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result);
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
   if (debug)
     gcry_log_debug ("Result of two minus one:\n%s\n", pc);
+  if (strcmp (pc, "010101010101010101010101010101010101010101010101"
+                  "010101010101010101010101010101010101010101010101") != 0)
+    fail ("mpi_sub failed at line %d", __LINE__);
+  gcry_free(pc);
+
+  zero = gcry_mpi_new(0);
+  five = gcry_mpi_new(0);
+  minusfive = gcry_mpi_new(0);
+  gcry_mpi_set_ui (zero, 0);
+  gcry_mpi_set_ui (one, 1);
+  gcry_mpi_set_ui (two, 2);
+  gcry_mpi_set_ui (five, 5);
+  gcry_mpi_sub (minusfive, zero, five);
+
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, minusfive);
+  if (debug)
+    gcry_log_debug ("Result of zero minus five:\n%s\n", pc);
+  if (strcmp (pc, "-05") != 0)
+    fail ("mpi_sub failed at line %d", __LINE__);
+  gcry_free(pc);
+
+  gcry_mpi_sub_ui (result, five, 2);
+
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
+  if (debug)
+    gcry_log_debug ("Result of five minus two:\n%s\n", pc);
+  if (strcmp (pc, "03") != 0)
+    fail ("mpi_sub_ui failed at line %d", __LINE__);
+  gcry_free(pc);
+
+  gcry_mpi_sub_ui (result, one, 10);
+
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
+  if (debug)
+    gcry_log_debug ("Result of one minus ten:\n%s\n", pc);
+  if (strcmp (pc, "-09") != 0)
+    fail ("mpi_sub_ui failed at line %d", __LINE__);
+  gcry_free(pc);
+
+  gcry_mpi_sub_ui (result, minusfive, 2);
+
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
+  if (debug)
+    gcry_log_debug ("Result of minus five minus two:\n%s\n", pc);
+  if (strcmp (pc, "-07") != 0)
+    fail ("mpi_sub_ui failed at line %d", __LINE__);
   gcry_free(pc);
 
   gcry_mpi_release(one);
   gcry_mpi_release(two);
   gcry_mpi_release(result);
+  gcry_mpi_release(zero);
+  gcry_mpi_release(five);
+  gcry_mpi_release(minusfive);
   return 1;
 }
 
@@ -406,21 +515,47 @@ test_mul (void)
   gcry_mpi_t two;
   gcry_mpi_t three;
   gcry_mpi_t result;
-  unsigned char* pc;
+  gcry_mpi_t minusfive;
+  char *pc;
 
   gcry_mpi_scan(&two, GCRYMPI_FMT_USG, twos, sizeof(twos), NULL);
   gcry_mpi_scan(&three, GCRYMPI_FMT_USG, threes, sizeof(threes), NULL);
   result = gcry_mpi_new(0);
   gcry_mpi_mul(result, two, three);
 
-  gcry_mpi_aprint(GCRYMPI_FMT_HEX, &pc, NULL, result);
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
   if (debug)
     gcry_log_debug ("Result of two mul three:\n%s\n", pc);
+  if (strcmp (pc, "060C12181E242A30363C42484E545A60666C72787E848A90"
+                  "969CA2A8AEB4BAC0C6CCD2D8DEE4EAF0F6FD03090F151B21"
+                  "1B150F0902FCF6F0EAE4DED8D2CCC6C0BAB4AEA8A29C9690"
+                  "8A847E78726C66605A544E48423C36302A241E18120C06") != 0)
+    fail ("mpi_mul failed at line %d", __LINE__);
+  gcry_free(pc);
+
+  gcry_mpi_scan(&minusfive, GCRYMPI_FMT_HEX, "-5", 0, NULL);
+  gcry_mpi_mul_ui (result, minusfive, 3);
+
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
+  if (debug)
+    gcry_log_debug ("Result of minus five mul three:\n%s\n", pc);
+  if (strcmp (pc, "-0F") != 0)
+    fail ("mpi_mul_ui failed at line %d", __LINE__);
+  gcry_free(pc);
+
+  gcry_mpi_mul_ui (result, result, 0);
+
+  gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char **)&pc, NULL, result);
+  if (debug)
+    gcry_log_debug ("Result of minus fifteen mul zero:\n%s\n", pc);
+  if (strcmp (pc, "00") != 0)
+    fail ("mpi_mul_ui failed at line %d", __LINE__);
   gcry_free(pc);
 
   gcry_mpi_release(two);
   gcry_mpi_release(three);
   gcry_mpi_release(result);
+  gcry_mpi_release(minusfive);
   return 1;
 }
 
@@ -565,7 +700,7 @@ main (int argc, char* argv[])
       fputs ("version mismatch\n", stderr);
       exit (1);
     }
-  xgcry_control(GCRYCTL_DISABLE_SECMEM);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM));
 
   test_const_and_immutable ();
   test_opaque ();
index e458b42..a7665f4 100644 (file)
@@ -441,12 +441,12 @@ main (int argc, char **argv)
         }
     }
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
 
   if (fips_mode)
-    xgcry_control (GCRYCTL_FORCE_FIPS_MODE, 0);
+    xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0));
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM));
   if (!gcry_check_version (GCRYPT_VERSION))
     {
       fprintf (stderr, PGM ": version mismatch\n");
@@ -456,11 +456,11 @@ main (int argc, char **argv)
   if (genkey_mode)
     {
       /* No valuable keys are create, so we can speed up our RNG. */
-      xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+      xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
     }
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
 
   if (genkey_mode && argc == 2)
index b52bff8..f26e779 100644 (file)
@@ -36,6 +36,8 @@
 #include "t-common.h"
 
 
+static int in_fips_mode;
+
 static void
 show_sexp (const char *prefix, gcry_sexp_t a)
 {
@@ -147,6 +149,18 @@ check_oaep (void)
       gcry_free (rsa_e);
       gcry_free (rsa_d);
 
+      if (in_fips_mode)
+        {
+          unsigned int nbits = gcry_pk_get_nbits (pub_key);
+
+          if (nbits < 2048)
+            {
+              if (verbose > 1)
+                info ("... skipped\n");
+              goto next;
+            }
+        }
+
       for (mno = 0; mno < DIM (tbl[0].m); mno++)
         {
           void *mesg, *seed, *encr;
@@ -225,6 +239,7 @@ check_oaep (void)
           ciph = NULL;
         }
 
+    next:
       gcry_sexp_release (sec_key);
       gcry_sexp_release (pub_key);
     }
@@ -269,6 +284,18 @@ check_pss (void)
       gcry_free (rsa_e);
       gcry_free (rsa_d);
 
+      if (in_fips_mode)
+        {
+          unsigned int nbits = gcry_pk_get_nbits (pub_key);
+
+          if (nbits < 2048)
+            {
+              if (verbose > 1)
+                info ("... skipped\n");
+              goto next;
+            }
+        }
+
       for (mno = 0; mno < DIM (tbl[0].m); mno++)
         {
           void *mesg, *salt, *sign;
@@ -347,6 +374,7 @@ check_pss (void)
           sigtmpl = NULL;
         }
 
+    next:
       gcry_sexp_release (sec_key);
       gcry_sexp_release (pub_key);
     }
@@ -391,6 +419,18 @@ check_v15crypt (void)
       gcry_free (rsa_e);
       gcry_free (rsa_d);
 
+      if (in_fips_mode)
+        {
+          unsigned int nbits = gcry_pk_get_nbits (pub_key);
+
+          if (nbits < 2048)
+            {
+              if (verbose > 1)
+                info ("... skipped\n");
+              goto next;
+            }
+        }
+
       for (mno = 0; mno < DIM (tbl[0].m); mno++)
         {
           void *mesg, *seed, *encr;
@@ -469,6 +509,7 @@ check_v15crypt (void)
           ciph = NULL;
         }
 
+    next:
       gcry_sexp_release (sec_key);
       gcry_sexp_release (pub_key);
     }
@@ -513,6 +554,18 @@ check_v15sign (void)
       gcry_free (rsa_e);
       gcry_free (rsa_d);
 
+      if (in_fips_mode)
+        {
+          unsigned int nbits = gcry_pk_get_nbits (pub_key);
+
+          if (nbits < 2048)
+            {
+              if (verbose > 1)
+                info ("... skipped\n");
+              goto next;
+            }
+        }
+
       for (mno = 0; mno < DIM (tbl[0].m); mno++)
         {
           void *mesg, *sign;
@@ -583,6 +636,7 @@ check_v15sign (void)
           sigtmpl = NULL;
         }
 
+    next:
       gcry_sexp_release (sec_key);
       gcry_sexp_release (pub_key);
     }
@@ -597,6 +651,7 @@ main (int argc, char **argv)
   int run_pss = 0;
   int run_v15c = 0;
   int run_v15s = 0;
+  int use_fips = 0;
 
   if (argc)
     { argc--; argv++; }
@@ -625,6 +680,11 @@ main (int argc, char **argv)
           die_on_error = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--fips"))
+        {
+          use_fips = 1;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--oaep"))
         {
           run_oaep = 1;
@@ -650,15 +710,27 @@ main (int argc, char **argv)
   if (!run_oaep && !run_pss && !run_v15c && !run_v15s)
     run_oaep = run_pss = run_v15c = run_v15s = 1;
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  if (!gcry_check_version ("1.5.0"))
-    die ("version mismatch\n");
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
+
+  if (use_fips)
+    xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0));
+
+  /* Check that we test exactly our version - including the patchlevel.  */
+  if (strcmp (GCRYPT_VERSION, gcry_check_version (NULL)))
+    die ("version mismatch; pgm=%s, library=%s\n",
+         GCRYPT_VERSION,gcry_check_version (NULL));
+
+  if ( gcry_fips_mode_active () )
+    in_fips_mode = 1;
+
+  if (!in_fips_mode)
+    xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
   /* No valuable keys are create, so we can speed up our RNG. */
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
 
   if (run_oaep)
     check_oaep ();
diff --git a/tests/pkcstv2c.awk b/tests/pkcstv2c.awk
new file mode 100755 (executable)
index 0000000..747f47d
--- /dev/null
@@ -0,0 +1,112 @@
+#! /usr/bin/awk -f
+# pkcstv2c.awk - Convert pkcs1 test vectors into a C table.
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+
+BEGIN {
+    in_key = 0;
+    in_item = 0;
+    in_number = 0;
+    no_comma = 0;
+
+    printf "  static struct {\n";
+    printf "    const char *desc;\n";
+    printf "    const char *n, *e, *d;\n";
+    printf "    struct {\n";
+    printf "      const char *desc;\n";
+    printf "      const char *mesg;\n";
+    printf "      const char *seed;\n";
+    printf "      const char *encr;\n";
+    printf "    } m[20];\n";
+    printf "  } tbl[] =\n";
+    printf "  {\n";
+}
+
+{ sub (/\r/,""); }
+
+/^# Public key/  { skip_pub = 1; }
+/^# Private key/ { skip_pub = 0; }
+skip_pub { next }
+
+in_number && ! /^[0-9a-f]/ {
+    if (in_number == 2)
+        printf "\"";
+    if (no_comma)
+        no_comma = 0;
+    else
+        printf ","
+    printf "\n";
+    in_number = 0;
+}
+
+in_number == 3 {
+    printf "\n";
+    in_number = 1;
+}
+
+in_number == 1 {
+    gsub (/ /,"")
+    printf "%*s\"%s", indent, "", $0;
+    in_number = 2;
+    next;
+}
+
+in_number == 2 {
+    gsub (/ /,"")
+    printf "%s\"", $0;
+    in_number = 3;
+    next;
+}
+
+/^#.*Example.*key pair/ {
+    if (in_item) {
+        printf "        }\n      }\n    },\n";
+        in_item = 0;
+    }
+    in_key = 1;
+    indent = 6;
+    printf "    {\n      \"%s\",\n", gensub(/.*: (A .*)/, "\\1", "g");
+    next
+}
+
+/^# PKCS#1 .*Example/  {
+    if (in_key) {
+        printf "      {\n";
+        in_key = 0;
+    }
+    if (in_item)
+        printf "        },{\n";
+    else
+        printf "        {\n";
+    in_item = 1;
+    indent = 10;
+    printf "          \"%s\",\n",  gensub(/^# (.*)/, "\\1", "g");
+    next
+}
+
+(in_key || in_item) && /^# (Modulus|Public|Exponent|Message|Seed)/ {
+    # printf "/* %s */\n", $0;
+    in_number = 1;
+    next
+}
+(in_key || in_item) && /^# (Signature|Encryption)/ {
+    # printf "/* %s */\n", $0;
+    in_number = 1;
+    no_comma = 1;
+    next
+}
+
+END {
+    if (in_item) {
+        printf "        }\n      }\n    }\n  };\n";
+        in_item = 0;
+    }
+}
\ No newline at end of file
index 5e90ce0..4226498 100644 (file)
@@ -224,13 +224,13 @@ main (int argc, char **argv)
   else if ((argc > 1) && (! strcmp (argv[1], "--42")))
     verbose = debug = mode42 = 1;
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (! gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
 
   if (mode42)
     create_42prime ();
index fbb7bbb..b352490 100644 (file)
 #define PGM "pubkey"
 #include "t-common.h"
 
+static int in_fips_mode;
 
 /* Sample RSA keys, taken from basic.c.  */
 
 static const char sample_private_key_1[] =
 "(private-key\n"
 " (openpgp-rsa\n"
-"  (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
-      "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
-      "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
-      "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n"
+"  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+"      7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+"      7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+"      958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+"      DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+"      6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+"      42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+"      664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6"
+"      CB#)\n"
 "  (e #010001#)\n"
-"  (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11"
-      "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD"
-      "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21"
-      "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n"
-"  (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
-      "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n"
-"  (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9"
-      "35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)\n"
-"  (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
-      "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n"
+"  (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19"
+"      8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93"
+"      7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12"
+"      771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F"
+"      5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48"
+"      EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD"
+"      69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84"
+"      3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401"
+"      #)\n"
+"  (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0"
+"      79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B"
+"      441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF"
+"      54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17"
+"      83#)\n"
+"  (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46"
+"      79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77"
+"      88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E"
+"      8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B9"
+"      19#)\n"
+"  (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04"
+"      479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4"
+"      A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9"
+"      AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7"
+"      #)\n"
 " )\n"
 ")\n";
 
@@ -57,15 +77,25 @@ static const char sample_private_key_1[] =
 static const char sample_private_key_1_1[] =
 "(private-key\n"
 " (openpgp-rsa\n"
-"  (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
-      "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
-      "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
-      "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n"
+"  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+"      7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+"      7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+"      958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+"      DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+"      6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+"      42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+"      664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6"
+"      CB#)\n"
 "  (e #010001#)\n"
-"  (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11"
-      "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD"
-      "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21"
-      "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n"
+"  (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19"
+"      8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93"
+"      7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12"
+"      771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F"
+"      5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48"
+"      EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD"
+"      69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84"
+"      3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401"
+"      #)\n"
 " )\n"
 ")\n";
 
@@ -74,29 +104,50 @@ static const char sample_private_key_1_1[] =
 static const char sample_private_key_1_2[] =
 "(private-key\n"
 " (openpgp-rsa\n"
-"  (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
-      "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
-      "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
-      "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n"
+"  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+"     7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+"     7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+"     958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+"     DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+"     6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+"     42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+"     664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6"
+"     CB#)\n"
 "  (e #010001#)\n"
-"  (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11"
-      "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD"
-      "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21"
-      "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n"
-"  (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213"
-      "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n"
-"  (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e"
-      "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n"
+"  (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19"
+"      8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93"
+"      7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12"
+"      771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F"
+"      5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48"
+"      EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD"
+"      69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84"
+"      3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401"
+"      #)\n"
+"  (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0"
+"      79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B"
+"      441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF"
+"      54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17"
+"      83#)\n"
+"  (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04"
+"      479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4"
+"      A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9"
+"      AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7"
+"      #)\n"
 " )\n"
 ")\n";
 
 static const char sample_public_key_1[] =
 "(public-key\n"
 " (rsa\n"
-"  (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa"
-      "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291"
-      "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7"
-      "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n"
+"  (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC"
+"      7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8"
+"      7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C"
+"      958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917"
+"      DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613"
+"      6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C"
+"      42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918"
+"      664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6"
+"      CB#)\n"
 "  (e #010001#)\n"
 " )\n"
 ")\n";
@@ -409,7 +460,15 @@ get_elg_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int fixed_x)
   rc = gcry_pk_genkey (&key, key_spec);
   gcry_sexp_release (key_spec);
   if (rc)
-    die ("error generating Elgamal key: %s\n", gcry_strerror (rc));
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "The Elgamal keys are not available in FIPS modee.\n");
+          return;
+        }
+      die ("error generating Elgamal key: %s\n", gcry_strerror (rc));
+    }
 
   if (verbose > 1)
     show_sexp ("generated ELG key:\n", key);
@@ -444,7 +503,15 @@ get_dsa_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int transient_key)
   rc = gcry_pk_genkey (&key, key_spec);
   gcry_sexp_release (key_spec);
   if (rc)
-    die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "The DSA keys are not available in FIPS modee.\n");
+          return;
+        }
+      die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    }
 
   if (verbose > 1)
     show_sexp ("generated DSA key:\n", key);
@@ -476,7 +543,15 @@ get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   rc = gcry_pk_genkey (&key, key_spec);
   gcry_sexp_release (key_spec);
   if (rc)
-    die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "The DSA keys are not available in FIPS modee.\n");
+          return;
+        }
+      die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    }
 
   if (verbose > 1)
     show_sexp ("generated DSA key (fips 186):\n", key);
@@ -504,22 +579,38 @@ get_dsa_key_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
   rc = gcry_sexp_new
     (&key_spec,
      "(genkey (dsa (transient-key)(domain"
-     "(p #d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921"
-     "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7"
-     "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0"
-     "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69#)"
-     "(q #9c916d121de9a03f71fb21bc2e1c0d116f065a4f#)"
-     "(g #8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab"
-     "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad"
-     "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e"
-     "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44#)"
+     "(p #a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe13a059705e"
+     "663230a377bf7323a8fa117100200bfd5adf857393b0bbd67906c081e585410e"
+     "38480ead51684dac3a38f7b64c9eb109f19739a4517cd7d5d6291e8af20a3fbf"
+     "17336c7bf80ee718ee087e322ee41047dabefbcc34d10b66b644ddb3160a28c0"
+     "639563d71993a26543eadb7718f317bf5d9577a6156561b082a10029cd44012b"
+     "18de6844509fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d"
+     "125dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31b9f96d5f"
+     "34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff007e8be2f0be06cc15f#)"
+     "(q #e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e68604d6b9dfb#)"
+     "(g #5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa104abfb5d"
+     "84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff8071d63b9bb956e547"
+     "af3a8df99e5d3061979652ff96b765cb3ee493643544c75dbe5bb39834531952"
+     "a0fb4b0378b3fcbb4c8b5800a5330392a2a04e700bb6ed7e0b85795ea38b1b96"
+     "2741b3f33b9dde2f4ec1354f09e2eb78e95f037a5804b6171659f88715ce1a9b"
+     "0cc90c27f35ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de"
+     "8347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d2183f1ba"
+     "3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb64fd9a6c5b75c4561#)"
      ")))", 0, 1);
   if (rc)
     die ("error creating S-expression: %s\n", gcry_strerror (rc));
   rc = gcry_pk_genkey (&key, key_spec);
   gcry_sexp_release (key_spec);
   if (rc)
-    die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "The DSA keys are not available in FIPS modee.\n");
+          return;
+        }
+      die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    }
 
   if (verbose > 1)
     show_sexp ("generated DSA key:\n", key);
@@ -592,17 +683,26 @@ get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey)
      "(genkey"
      "  (dsa"
      "    (nbits 4:2048)"
+     "    (qbits 3:256)"
      "    (use-fips186)"
      "    (transient-key)"
      "    (derive-parms"
-     "      (seed #0cb1990c1fd3626055d7a0096f8fa99807399871#))))",
+     "      (seed #f770a4598ff756931fc529764513b103ce57d85f4ad8c5cf297c9b4d48241c5b#))))",
      0, 1);
   if (rc)
     die ("error creating S-expression: %s\n", gcry_strerror (rc));
   rc = gcry_pk_genkey (&key, key_spec);
   gcry_sexp_release (key_spec);
   if (rc)
-    die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            fprintf (stderr, "The DSA keys are not available in FIPS modee.\n");
+          return;
+        }
+      die ("error generating DSA key: %s\n", gcry_strerror (rc));
+    }
 
   if (verbose > 1)
     show_sexp ("generated DSA key (fips 186 with seed):\n", key);
@@ -628,6 +728,7 @@ check_run (void)
   gcry_sexp_t pkey, skey;
   int variant;
 
+  pkey = skey = NULL;
   for (variant=0; variant < 3; variant++)
     {
       if (verbose)
@@ -642,6 +743,7 @@ check_run (void)
       check_keys (pkey, skey, 800, variant == 2? GPG_ERR_NO_OBJ : 0);
       gcry_sexp_release (pkey);
       gcry_sexp_release (skey);
+      pkey = skey = NULL;
     }
 
   if (verbose)
@@ -650,6 +752,7 @@ check_run (void)
   check_keys (pkey, skey, 800, 0);
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+  pkey = skey = NULL;
 
   if (verbose)
     fprintf (stderr, "Checking generated RSA key (X9.31).\n");
@@ -657,51 +760,74 @@ check_run (void)
   check_keys (pkey, skey, 800, 0);
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+  pkey = skey = NULL;
 
   if (verbose)
     fprintf (stderr, "Checking generated Elgamal key.\n");
   get_elg_key_new (&pkey, &skey, 0);
-  check_keys (pkey, skey, 400, 0);
+  if (!in_fips_mode)
+    check_keys (pkey, skey, 400, 0);
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+  pkey = skey = NULL;
 
   if (verbose)
     fprintf (stderr, "Checking passphrase generated Elgamal key.\n");
   get_elg_key_new (&pkey, &skey, 1);
-  check_keys (pkey, skey, 800, 0);
+  if (!in_fips_mode)
+    check_keys (pkey, skey, 800, 0);
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+  pkey = skey = NULL;
 
   if (verbose)
     fprintf (stderr, "Generating DSA key.\n");
   get_dsa_key_new (&pkey, &skey, 0);
-  /* Fixme:  Add a check function for DSA keys.  */
+  if (!in_fips_mode)
+    {
+      /* Fixme:  Add a check function for DSA keys.  */
+      ;
+    }
+
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+  pkey = skey = NULL;
 
-  if (!gcry_fips_mode_active ())
+  if (verbose)
+    fprintf (stderr, "Generating transient DSA key.\n");
+  get_dsa_key_new (&pkey, &skey, 1);
+  if (!in_fips_mode)
     {
-      if (verbose)
-        fprintf (stderr, "Generating transient DSA key.\n");
-      get_dsa_key_new (&pkey, &skey, 1);
       /* Fixme:  Add a check function for DSA keys.  */
-      gcry_sexp_release (pkey);
-      gcry_sexp_release (skey);
+      ;
     }
+  gcry_sexp_release (pkey);
+  gcry_sexp_release (skey);
+  pkey = skey = NULL;
 
   if (verbose)
     fprintf (stderr, "Generating DSA key (FIPS 186).\n");
   get_dsa_key_fips186_new (&pkey, &skey);
-  /* Fixme:  Add a check function for DSA keys.  */
+  if (!in_fips_mode)
+    {
+      /* Fixme:  Add a check function for DSA keys.  */
+      ;
+    }
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+  pkey = skey = NULL;
 
   if (verbose)
     fprintf (stderr, "Generating DSA key with given domain.\n");
   get_dsa_key_with_domain_new (&pkey, &skey);
-  /* Fixme:  Add a check function for DSA keys.  */
+  if (!in_fips_mode)
+    {
+      /* Fixme:  Add a check function for DSA keys.  */
+      ;
+    }
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+  pkey = skey = NULL;
 
   /* We need new test vectors for get_dsa_key_fips186_with_domain_new.  */
   if (verbose)
@@ -715,9 +841,14 @@ check_run (void)
   if (verbose)
     fprintf (stderr, "Generating DSA key with given seed (FIPS 186).\n");
   get_dsa_key_fips186_with_seed_new (&pkey, &skey);
-  /* Fixme:  Add a check function for DSA keys.  */
+  if (!in_fips_mode)
+    {
+      /* Fixme:  Add a check function for DSA keys.  */
+      ;
+    }
   gcry_sexp_release (pkey);
   gcry_sexp_release (skey);
+  pkey = skey = NULL;
 }
 
 
@@ -901,9 +1032,10 @@ check_x931_derived_key (int what)
     err = _gcry_pk_util_get_nbits(key_spec, &nbits);
     if (err)
       die ("nbits not found\n");
-    if (gcry_fips_mode_active() && nbits < 2048)
+    if (in_fips_mode && nbits < 2048)
       {
         info("RSA key test with %d bits skipped in fips mode\n", nbits);
+        gcry_sexp_release (key_spec);
         goto leave;
       }
   }
@@ -1179,14 +1311,17 @@ main (int argc, char **argv)
       debug = 1;
     }
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
   /* No valuable keys are create, so we can speed up our RNG. */
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
 
   for (i=0; i < 2; i++)
     check_run ();
@@ -1195,7 +1330,7 @@ main (int argc, char **argv)
     check_x931_derived_key (i);
 
   check_ecc_sample_key ();
-  if (!gcry_fips_mode_active ())
+  if (!in_fips_mode)
     check_ed25519ecdsa_sample_key ();
 
   return !!error_count;
index 2f48323..2ffd528 100644 (file)
@@ -292,7 +292,7 @@ check_close_random_device (void)
     die ("fork failed: %s\n", strerror (errno));
   if (!pid)
     {
-      xgcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
+      xgcry_control ((GCRYCTL_CLOSE_RANDOM_DEVICE, 0));
 
       /* The next call will re-open the device.  */
       gcry_randomize (buf, sizeof buf, GCRY_STRONG_RANDOM);
@@ -345,7 +345,7 @@ check_rng_type_switching (void)
   if (rngtype != rng_type ())
     die ("RNG type unexpectedly changed\n");
 
-  xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
+  xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM));
 
   rngtype = rng_type ();
   if (debug)
@@ -358,7 +358,7 @@ check_rng_type_switching (void)
   if (rngtype != rng_type ())
     die ("RNG type unexpectedly changed\n");
 
-  xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
+  xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS));
 
   rngtype = rng_type ();
   if (debug)
@@ -371,7 +371,7 @@ check_rng_type_switching (void)
   if (rngtype != rng_type ())
     die ("RNG type unexpectedly changed\n");
 
-  xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD);
+  xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD));
 
   rngtype = rng_type ();
   if (debug)
@@ -399,7 +399,7 @@ check_early_rng_type_switching (void)
     info ("rng type: %d\n", rngtype);
   initial = rngtype;
 
-  xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
+  xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM));
 
   rngtype = rng_type ();
   if (debug)
@@ -407,7 +407,7 @@ check_early_rng_type_switching (void)
   if (initial >= GCRY_RNG_TYPE_SYSTEM && rngtype != GCRY_RNG_TYPE_SYSTEM)
     die ("switching to System RNG failed\n");
 
-  xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
+  xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS));
 
   rngtype = rng_type ();
   if (debug)
@@ -415,7 +415,7 @@ check_early_rng_type_switching (void)
   if (initial >= GCRY_RNG_TYPE_FIPS && rngtype != GCRY_RNG_TYPE_FIPS)
     die ("switching to FIPS RNG failed\n");
 
-  xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD);
+  xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD));
 
   rngtype = rng_type ();
   if (debug)
@@ -505,6 +505,65 @@ check_drbg_reinit (void)
 }
 
 
+#if defined(USE_POSIX_SPAWN_FOR_TESTS) && defined (HAVE_SPAWN_H)
+#include <spawn.h>
+extern char **environ;
+
+static void
+run_all_rng_tests (const char *program)
+{
+  static const char *options[][2] = {
+    { "--early-rng-check",     NULL },
+    { "--early-rng-check",     "--prefer-standard-rng" },
+    { "--early-rng-check",     "--prefer-fips-rng" },
+    { "--early-rng-check",     "--prefer-system-rng" },
+    { "--prefer-standard-rng", NULL },
+    { "--prefer-fips-rng",     NULL },
+    { "--prefer-system-rng",   NULL },
+    { NULL, NULL }
+  };
+  int idx;
+  char *argv[8];
+
+  for (idx=0; options[idx][0]; idx++)
+    {
+      int i;
+      pid_t pid;
+      int status;
+
+      if (verbose)
+        info ("now running with options '%s%s%s'\n",
+              options[idx][0],
+              options[idx][1] ? " " : "",
+              options[idx][1] ? options[idx][1] : "");
+
+      i = 0;
+      argv[i++] = xstrdup (program);
+      argv[i++] = xstrdup ("--in-recursion");
+      argv[i++] = xstrdup ("--verbose");
+      argv[i++] = xstrdup ("--debug");
+      argv[i++] = xstrdup ("--progress");
+      argv[i++] = xstrdup (options[idx][0]);
+      if (options[idx][1])
+        argv[i++] = xstrdup (options[idx][1]);
+      argv[i++] = NULL;
+
+      if (posix_spawn (&pid, program, NULL, NULL, argv, environ))
+        die ("spawning '%s' failed\n", program);
+
+      if (waitpid (pid, &status, 0) < 0)
+        die ("waitpid for '%s' failed\n", program);
+
+      if (WIFEXITED (status) && WEXITSTATUS (status))
+        die ("running '%s' failed with %d\n", program, WEXITSTATUS (status));
+      else if (!WIFEXITED (status))
+        die ("running '%s' failed\n", program);
+
+      while (i)
+        xfree (argv[--i]);
+    }
+}
+#else
 /* Because we want to check initialization behaviour, we need to
    fork/exec this program with several command line arguments.  We use
    system, so that these tests work also on Windows.  */
@@ -559,6 +618,7 @@ run_all_rng_tests (const char *program)
 
   free (cmdline);
 }
+#endif
 
 
 static void
@@ -659,18 +719,18 @@ main (int argc, char **argv)
         {
           /* This is anyway the default, but we may want to use it for
              debugging. */
-          xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE,
-                         GCRY_RNG_TYPE_STANDARD);
+          xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE,
+                          GCRY_RNG_TYPE_STANDARD));
           argc--; argv++;
         }
       else if (!strcmp (*argv, "--prefer-fips-rng"))
         {
-          xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
+          xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS));
           argc--; argv++;
         }
       else if (!strcmp (*argv, "--prefer-system-rng"))
         {
-          xgcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
+          xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM));
           argc--; argv++;
         }
       else if (!strcmp (*argv, "--disable-hwf"))
@@ -701,7 +761,7 @@ main (int argc, char **argv)
         check_early_rng_type_switching ();
     }
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
@@ -718,9 +778,9 @@ main (int argc, char **argv)
       xfree (fname);
     }
 
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
 
   if (benchmark)
     {
@@ -760,7 +820,7 @@ main (int argc, char **argv)
     }
 
   if (debug)
-    xgcry_control (GCRYCTL_DUMP_RANDOM_STATS);
+    xgcry_control ((GCRYCTL_DUMP_RANDOM_STATS));
 
   return 0;
 }
index 3d83264..3cc50d7 100644 (file)
@@ -361,11 +361,11 @@ main (int argc, char **argv)
   else
     input = stdin;
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
   if (!gcry_check_version ("1.4.0"))
     die ("Libgcrypt is not sufficient enough\n");
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
   do
     {
index 2040f09..e356c39 100644 (file)
@@ -151,9 +151,9 @@ info (const char *format, ...)
 
 
 /* Convenience macro for initializing gcrypt with error checking.  */
-#define xgcry_control(cmd...)                                   \
+#define xgcry_control(cmd)                                      \
   do {                                                          \
-    gcry_error_t err__ = gcry_control (cmd);                    \
+    gcry_error_t err__ = gcry_control cmd;                      \
     if (err__)                                                  \
       die ("line %d: gcry_control (%s) failed: %s",             \
            __LINE__, #cmd, gcry_strerror (err__));              \
index 121039c..d5d162b 100644 (file)
@@ -141,6 +141,7 @@ static void
 check_formats (void)
 {
   static struct {
+    int have_value;
     int value;
     struct {
       const char *hex;
@@ -154,136 +155,283 @@ check_formats (void)
       const char *pgp;
     } a;
   } data[] = {
-    {    0, { "00",
-              0, "",
-              4, "\x00\x00\x00\x00",
-              0, "",
-              2, "\x00\x00"}
-    },
-    {    1, { "01",
-              1, "\x01",
-              5, "\x00\x00\x00\x01\x01",
-              1, "\x01",
-              3, "\x00\x01\x01" }
-    },
-    {    2, { "02",
-              1, "\x02",
-              5, "\x00\x00\x00\x01\x02",
-              1, "\x02",
-              3, "\x00\x02\x02" }
-    },
-    {  127, { "7F",
-              1, "\x7f",
-              5, "\x00\x00\x00\x01\x7f",
-              1, "\x7f",
-              3, "\x00\x07\x7f" }
-    },
-    {  128, { "0080",
-              2, "\x00\x80",
-              6, "\x00\x00\x00\x02\x00\x80",
-              1, "\x80",
-              3, "\x00\x08\x80" }
-    },
-    {  129, { "0081",
-              2, "\x00\x81",
-              6, "\x00\x00\x00\x02\x00\x81",
-              1, "\x81",
-              3, "\x00\x08\x81" }
-    },
-    {  255, { "00FF",
-              2, "\x00\xff",
-              6, "\x00\x00\x00\x02\x00\xff",
-              1, "\xff",
-              3, "\x00\x08\xff" }
-    },
-    {  256, { "0100",
-              2, "\x01\x00",
-              6, "\x00\x00\x00\x02\x01\x00",
-              2, "\x01\x00",
-              4, "\x00\x09\x01\x00" }
-    },
-    {  257, { "0101",
-              2, "\x01\x01",
-              6, "\x00\x00\x00\x02\x01\x01",
-              2, "\x01\x01",
-              4, "\x00\x09\x01\x01" }
-    },
-    {   -1, { "-01",
-              1, "\xff",
-              5, "\x00\x00\x00\x01\xff",
-              1,"\x01" }
-    },
-    {   -2, { "-02",
-              1, "\xfe",
-              5, "\x00\x00\x00\x01\xfe",
-              1, "\x02" }
-    },
-    { -127, { "-7F",
-              1, "\x81",
-              5, "\x00\x00\x00\x01\x81",
-              1, "\x7f" }
-    },
-    { -128, { "-0080",
-              1, "\x80",
-              5, "\x00\x00\x00\x01\x80",
-              1, "\x80" }
-    },
-    { -129, { "-0081",
-              2, "\xff\x7f",
-              6, "\x00\x00\x00\x02\xff\x7f",
-              1, "\x81" }
-    },
-    { -255, { "-00FF",
-              2, "\xff\x01",
-              6, "\x00\x00\x00\x02\xff\x01",
-              1, "\xff" }
-    },
-    { -256, { "-0100",
-              2, "\xff\x00",
-              6, "\x00\x00\x00\x02\xff\x00",
-              2, "\x01\x00" }
-    },
-    { -257, { "-0101",
-              2, "\xfe\xff",
-              6, "\x00\x00\x00\x02\xfe\xff",
-              2, "\x01\x01" }
-    },
-    {  65535, { "00FFFF",
-                3, "\x00\xff\xff",
-                7, "\x00\x00\x00\x03\x00\xff\xff",
-                2, "\xff\xff",
-                4, "\x00\x10\xff\xff" }
-    },
-    {  65536, { "010000",
-                3, "\x01\00\x00",
-                7, "\x00\x00\x00\x03\x01\x00\x00",
-                3, "\x01\x00\x00",
-                5, "\x00\x11\x01\x00\x00 "}
-    },
-    {  65537, { "010001",
-                3, "\x01\00\x01",
-                7, "\x00\x00\x00\x03\x01\x00\x01",
-                3, "\x01\x00\x01",
-                5, "\x00\x11\x01\x00\x01" }
-    },
-    { -65537, { "-010001",
-                3, "\xfe\xff\xff",
-                7, "\x00\x00\x00\x03\xfe\xff\xff",
-                3, "\x01\x00\x01" }
-    },
-    { -65536, { "-010000",
-                3, "\xff\x00\x00",
-                7, "\x00\x00\x00\x03\xff\x00\x00",
-                3, "\x01\x00\x00" }
-    },
-    { -65535, { "-00FFFF",
-                3, "\xff\x00\x01",
-                7, "\x00\x00\x00\x03\xff\x00\x01",
-                2, "\xff\xff" }
+    {
+      1, 0,
+      { "00",
+       0, "",
+       4, "\x00\x00\x00\x00",
+       0, "",
+       2, "\x00\x00" }
+    },
+    {
+      1, 1,
+      { "01",
+       1, "\x01",
+       5, "\x00\x00\x00\x01\x01",
+       1, "\x01",
+       3, "\x00\x01\x01" }
+    },
+    {
+      1, 2,
+      { "02",
+       1, "\x02",
+       5, "\x00\x00\x00\x01\x02",
+       1, "\x02",
+       3, "\x00\x02\x02" }
+    },
+    {
+      1, 127,
+      { "7F",
+       1, "\x7f",
+       5, "\x00\x00\x00\x01\x7f",
+       1, "\x7f",
+       3, "\x00\x07\x7f" }
+    },
+    {
+      1, 128,
+      { "0080",
+       2, "\x00\x80",
+       6, "\x00\x00\x00\x02\x00\x80",
+       1, "\x80",
+       3, "\x00\x08\x80" }
+    },
+    {
+      1, 129,
+      { "0081",
+       2, "\x00\x81",
+       6, "\x00\x00\x00\x02\x00\x81",
+       1, "\x81",
+       3, "\x00\x08\x81" }
+    },
+    {
+      1, 255,
+      { "00FF",
+       2, "\x00\xff",
+       6, "\x00\x00\x00\x02\x00\xff",
+       1, "\xff",
+       3, "\x00\x08\xff" }
+    },
+    {
+      1, 256,
+      { "0100",
+       2, "\x01\x00",
+       6, "\x00\x00\x00\x02\x01\x00",
+       2, "\x01\x00",
+       4, "\x00\x09\x01\x00" }
+    },
+    {
+      1, 257,
+      { "0101",
+       2, "\x01\x01",
+       6, "\x00\x00\x00\x02\x01\x01",
+       2, "\x01\x01",
+       4, "\x00\x09\x01\x01" }
+    },
+    {
+      1, -1,
+      { "-01",
+       1, "\xff",
+       5, "\x00\x00\x00\x01\xff",
+       1,"\x01" }
+    },
+    {
+      1, -2,
+      { "-02",
+       1, "\xfe",
+       5, "\x00\x00\x00\x01\xfe",
+       1, "\x02" }
+    },
+    {
+      1, -127,
+      { "-7F",
+       1, "\x81",
+       5, "\x00\x00\x00\x01\x81",
+       1, "\x7f" }
+    },
+    {
+      1, -128,
+      { "-0080",
+       1, "\x80",
+       5, "\x00\x00\x00\x01\x80",
+       1, "\x80" }
+    },
+    {
+      1, -129,
+      { "-0081",
+       2, "\xff\x7f",
+       6, "\x00\x00\x00\x02\xff\x7f",
+       1, "\x81" }
+    },
+    {
+      1, -255,
+      { "-00FF",
+       2, "\xff\x01",
+       6, "\x00\x00\x00\x02\xff\x01",
+       1, "\xff" }
+    },
+    {
+      1, -256,
+      { "-0100",
+       2, "\xff\x00",
+       6, "\x00\x00\x00\x02\xff\x00",
+       2, "\x01\x00" }
+    },
+    {
+      1, -257,
+      { "-0101",
+       2, "\xfe\xff",
+       6, "\x00\x00\x00\x02\xfe\xff",
+       2, "\x01\x01" }
+    },
+    {
+      1, 65535,
+      { "00FFFF",
+       3, "\x00\xff\xff",
+       7, "\x00\x00\x00\x03\x00\xff\xff",
+       2, "\xff\xff",
+       4, "\x00\x10\xff\xff" }
+    },
+    {
+      1, 65536,
+      { "010000",
+       3, "\x01\00\x00",
+       7, "\x00\x00\x00\x03\x01\x00\x00",
+       3, "\x01\x00\x00",
+       5, "\x00\x11\x01\x00\x00 "}
+    },
+    {
+      1, 65537,
+      { "010001",
+       3, "\x01\00\x01",
+       7, "\x00\x00\x00\x03\x01\x00\x01",
+       3, "\x01\x00\x01",
+       5, "\x00\x11\x01\x00\x01" }
+    },
+    {
+      1, -65537,
+      { "-010001",
+       3, "\xfe\xff\xff",
+       7, "\x00\x00\x00\x03\xfe\xff\xff",
+       3, "\x01\x00\x01" }
+    },
+    {
+      1, -65536,
+      { "-010000",
+       3, "\xff\x00\x00",
+       7, "\x00\x00\x00\x03\xff\x00\x00",
+       3, "\x01\x00\x00" }
+    },
+    {
+      1, -65535,
+      { "-00FFFF",
+       3, "\xff\x00\x01",
+       7, "\x00\x00\x00\x03\xff\x00\x01",
+       2, "\xff\xff" }
+    },
+    {
+      1, 0x7fffffff,
+      { "7FFFFFFF",
+       4, "\x7f\xff\xff\xff",
+       8, "\x00\x00\x00\x04\x7f\xff\xff\xff",
+       4, "\x7f\xff\xff\xff",
+       6, "\x00\x1f\x7f\xff\xff\xff" }
+    },
+    { 1, -0x7fffffff,
+      { "-7FFFFFFF",
+       4, "\x80\x00\x00\x01",
+       8, "\x00\x00\x00\x04\x80\x00\x00\x01",
+       4, "\x7f\xff\xff\xff" }
+    },
+    {
+      1, (int)0x800000ffU,
+      { "-7FFFFF01",
+       4, "\x80\x00\x00\xff",
+       8, "\x00\x00\x00\x04\x80\x00\x00\xff",
+       4, "\x7f\xff\xff\x01" }
+    },
+    {
+      1, (int)0x800000feU,
+      { "-7FFFFF02",
+       4, "\x80\x00\x00\xfe",
+       8, "\x00\x00\x00\x04\x80\x00\x00\xfe",
+       4, "\x7f\xff\xff\x02" }
+    },
+    {
+      1, (int)0x800000fcU,
+      { "-7FFFFF04",
+       4, "\x80\x00\x00\xfc",
+       8, "\x00\x00\x00\x04\x80\x00\x00\xfc",
+       4, "\x7f\xff\xff\x04" }
+    },
+    {
+      1, (int)0x800000f8U,
+      { "-7FFFFF08",
+       4, "\x80\x00\x00\xf8",
+       8, "\x00\x00\x00\x04\x80\x00\x00\xf8",
+       4, "\x7f\xff\xff\x08" }
+    },
+    {
+      1, (int)0x800000f0U,
+      { "-7FFFFF10",
+       4, "\x80\x00\x00\xf0",
+       8, "\x00\x00\x00\x04\x80\x00\x00\xf0",
+       4, "\x7f\xff\xff\x10" }
+    },
+    {
+      1, (int)0x800000e0U,
+      { "-7FFFFF20",
+       4, "\x80\x00\x00\xe0",
+       8, "\x00\x00\x00\x04\x80\x00\x00\xe0",
+       4, "\x7f\xff\xff\x20" }
+    },
+    {
+      1, (int)0x800000c0U,
+      { "-7FFFFF40",
+       4, "\x80\x00\x00\xc0",
+       8, "\x00\x00\x00\x04\x80\x00\x00\xc0",
+       4, "\x7f\xff\xff\x40" }
+    },
+    {
+      1, (int)0x80000080U,
+      { "-7FFFFF80",
+       4, "\x80\x00\x00\x80",
+       8, "\x00\x00\x00\x04\x80\x00\x00\x80",
+       4, "\x7f\xff\xff\x80" }
+    },
+    {
+      1, (int)0x80000100U,
+      { "-7FFFFF00",
+       4, "\x80\x00\x01\x00",
+       8, "\x00\x00\x00\x04\x80\x00\x01\x00",
+       4, "\x7f\xff\xff\x00" }
+    },
+    {
+      0, 0,
+      { "076543210FEDCBA9876543210123456789ABCDEF00112233",
+       24, "\x07\x65\x43\x21\x0f\xed\xcb\xa9\x87\x65\x43\x21\x01\x23"
+           "\x45\x67\x89\xab\xcd\xef\x00\x11\x22\x33",
+       28, "\x00\x00\x00\x18\x07\x65\x43\x21\x0f\xed\xcb\xa9\x87\x65"
+           "\x43\x21\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x11\x22\x33"
+           "\x44",
+       24, "\x07\x65\x43\x21\x0f\xed\xcb\xa9\x87\x65\x43\x21\x01\x23"
+           "\x45\x67\x89\xab\xcd\xef\x00\x11\x22\x33",
+       26, "\x00\xbb\x07\x65\x43\x21\x0f\xed\xcb\xa9\x87\x65\x43\x21"
+           "\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x11\x22\x33" }
+    },
+    {
+      0, 0,
+      { "-07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01",
+       24, "\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff",
+       28, "\x00\x00\x00\x18\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+           "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff",
+       24, "\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+           "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01" }
     }
   };
   gpg_error_t err;
   gcry_mpi_t a, b;
+  char valuestr[128];
   char *buf;
   void *bufaddr = &buf;
   int idx;
@@ -295,24 +443,39 @@ check_formats (void)
       if (debug)
         info ("print test %d\n", data[idx].value);
 
-      if (data[idx].value < 0)
-        {
-          gcry_mpi_set_ui (a, -data[idx].value);
-          gcry_mpi_neg (a, a);
-        }
+      if (data[idx].have_value)
+       {
+         snprintf(valuestr, sizeof(valuestr), "%d", data[idx].value);
+         if (data[idx].value < 0)
+           {
+             gcry_mpi_set_ui (a, -data[idx].value);
+             gcry_mpi_neg (a, a);
+           }
+         else
+           gcry_mpi_set_ui (a, data[idx].value);
+       }
       else
-        gcry_mpi_set_ui (a, data[idx].value);
+       {
+         /* Use hex-format as source test vector. */
+         snprintf(valuestr, sizeof(valuestr), "%s", data[idx].a.hex);
+          gcry_mpi_release (a);
+         err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, data[idx].a.hex, 0,
+                              &buflen);
+         if (err)
+           fail ("error scanning value %s from %s: %s\n",
+                 valuestr, "HEX", gpg_strerror (err));
+       }
 
       err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
       if (err)
-        fail ("error printing value %d as %s: %s\n",
-              data[idx].value, "HEX", gpg_strerror (err));
+        fail ("error printing value %s as %s: %s\n",
+              valuestr, "HEX", gpg_strerror (err));
       else
         {
           if (strcmp (buf, data[idx].a.hex))
             {
-              fail ("error printing value %d as %s: %s\n",
-                    data[idx].value, "HEX", "wrong result");
+              fail ("error printing value %s as %s: %s\n",
+                    valuestr, "HEX", "wrong result");
               info ("expected: '%s'\n", data[idx].a.hex);
               info ("     got: '%s'\n", buf);
             }
@@ -321,15 +484,15 @@ check_formats (void)
 
       err = gcry_mpi_aprint (GCRYMPI_FMT_STD, bufaddr, &buflen, a);
       if (err)
-        fail ("error printing value %d as %s: %s\n",
-              data[idx].value, "STD", gpg_strerror (err));
+        fail ("error printing value %s as %s: %s\n",
+              valuestr, "STD", gpg_strerror (err));
       else
         {
           if (buflen != data[idx].a.stdlen
               || memcmp (buf, data[idx].a.std, data[idx].a.stdlen))
             {
-              fail ("error printing value %d as %s: %s\n",
-                    data[idx].value, "STD", "wrong result");
+              fail ("error printing value %s as %s: %s\n",
+                    valuestr, "STD", "wrong result");
               showhex ("expected:", data[idx].a.std, data[idx].a.stdlen);
               showhex ("     got:", buf, buflen);
             }
@@ -338,15 +501,15 @@ check_formats (void)
 
       err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a);
       if (err)
-        fail ("error printing value %d as %s: %s\n",
-              data[idx].value, "SSH", gpg_strerror (err));
+        fail ("error printing value %s as %s: %s\n",
+              valuestr, "SSH", gpg_strerror (err));
       else
         {
           if (buflen != data[idx].a.sshlen
               || memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen))
             {
-              fail ("error printing value %d as %s: %s\n",
-                    data[idx].value, "SSH", "wrong result");
+              fail ("error printing value %s as %s: %s\n",
+                    valuestr, "SSH", "wrong result");
               showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen);
               showhex ("     got:", buf, buflen);
             }
@@ -355,15 +518,15 @@ check_formats (void)
 
       err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a);
       if (err)
-        fail ("error printing value %d as %s: %s\n",
-              data[idx].value, "USG", gpg_strerror (err));
+        fail ("error printing value %s as %s: %s\n",
+              valuestr, "USG", gpg_strerror (err));
       else
         {
           if (buflen != data[idx].a.usglen
               || memcmp (buf, data[idx].a.usg, data[idx].a.usglen))
             {
-              fail ("error printing value %d as %s: %s\n",
-                    data[idx].value, "USG", "wrong result");
+              fail ("error printing value %s as %s: %s\n",
+                    valuestr, "USG", "wrong result");
               showhex ("expected:", data[idx].a.usg, data[idx].a.usglen);
               showhex ("     got:", buf, buflen);
             }
@@ -374,19 +537,19 @@ check_formats (void)
       if (gcry_mpi_is_neg (a))
         {
           if (gpg_err_code (err) != GPG_ERR_INV_ARG)
-            fail ("error printing value %d as %s: %s\n",
-                  data[idx].value, "PGP", "Expected error not returned");
+            fail ("error printing value %s as %s: %s\n",
+                  valuestr, "PGP", "Expected error not returned");
         }
       else if (err)
-        fail ("error printing value %d as %s: %s\n",
-              data[idx].value, "PGP", gpg_strerror (err));
+        fail ("error printing value %s as %s: %s\n",
+              valuestr, "PGP", gpg_strerror (err));
       else
         {
           if (buflen != data[idx].a.pgplen
               || memcmp (buf, data[idx].a.pgp, data[idx].a.pgplen))
             {
-              fail ("error printing value %d as %s: %s\n",
-                    data[idx].value, "PGP", "wrong result");
+              fail ("error printing value %s as %s: %s\n",
+                    valuestr, "PGP", "wrong result");
               showhex ("expected:", data[idx].a.pgp, data[idx].a.pgplen);
               showhex ("     got:", buf, buflen);
             }
@@ -401,24 +564,39 @@ check_formats (void)
       if (debug)
         info ("scan test %d\n", data[idx].value);
 
-      if (data[idx].value < 0)
-        {
-          gcry_mpi_set_ui (a, -data[idx].value);
-          gcry_mpi_neg (a, a);
-        }
+      if (data[idx].have_value)
+       {
+         snprintf(valuestr, sizeof(valuestr), "%d", data[idx].value);
+         if (data[idx].value < 0)
+           {
+             gcry_mpi_set_ui (a, -data[idx].value);
+             gcry_mpi_neg (a, a);
+           }
+         else
+           gcry_mpi_set_ui (a, data[idx].value);
+       }
       else
-        gcry_mpi_set_ui (a, data[idx].value);
+       {
+         /* Use hex-format as source test vector. */
+         snprintf(valuestr, sizeof(valuestr), "%s", data[idx].a.hex);
+          gcry_mpi_release (a);
+         err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, data[idx].a.hex, 0,
+                              &buflen);
+         if (err)
+           fail ("error scanning value %s from %s: %s\n",
+                 valuestr, "HEX", gpg_strerror (err));
+       }
 
       err = gcry_mpi_scan (&b, GCRYMPI_FMT_HEX, data[idx].a.hex, 0, &buflen);
       if (err)
-        fail ("error scanning value %d from %s: %s\n",
-              data[idx].value, "HEX", gpg_strerror (err));
+        fail ("error scanning value %s from %s: %s\n",
+              valuestr, "HEX", gpg_strerror (err));
       else
         {
           if (gcry_mpi_cmp (a, b))
             {
-              fail ("error scanning value %d from %s: %s\n",
-                    data[idx].value, "HEX", "wrong result");
+              fail ("error scanning value %s from %s: %s\n",
+                    valuestr, "HEX", "wrong result");
               showmpi ("expected:", a);
               showmpi ("     got:", b);
             }
@@ -428,14 +606,14 @@ check_formats (void)
       err = gcry_mpi_scan (&b, GCRYMPI_FMT_STD,
                            data[idx].a.std, data[idx].a.stdlen, &buflen);
       if (err)
-        fail ("error scanning value %d as %s: %s\n",
-              data[idx].value, "STD", gpg_strerror (err));
+        fail ("error scanning value %s as %s: %s\n",
+              valuestr, "STD", gpg_strerror (err));
       else
         {
           if (gcry_mpi_cmp (a, b) || data[idx].a.stdlen != buflen)
             {
-              fail ("error scanning value %d from %s: %s (%lu)\n",
-                    data[idx].value, "STD", "wrong result",
+              fail ("error scanning value %s from %s: %s (%lu)\n",
+                    valuestr, "STD", "wrong result",
                     (long unsigned int)buflen);
               showmpi ("expected:", a);
               showmpi ("     got:", b);
@@ -446,14 +624,14 @@ check_formats (void)
       err = gcry_mpi_scan (&b, GCRYMPI_FMT_SSH,
                            data[idx].a.ssh, data[idx].a.sshlen, &buflen);
       if (err)
-        fail ("error scanning value %d as %s: %s\n",
-              data[idx].value, "SSH", gpg_strerror (err));
+        fail ("error scanning value %s as %s: %s\n",
+              valuestr, "SSH", gpg_strerror (err));
       else
         {
           if (gcry_mpi_cmp (a, b) || data[idx].a.sshlen != buflen)
             {
-              fail ("error scanning value %d from %s: %s (%lu)\n",
-                    data[idx].value, "SSH", "wrong result",
+              fail ("error scanning value %s from %s: %s (%lu)\n",
+                    valuestr, "SSH", "wrong result",
                     (long unsigned int)buflen);
               showmpi ("expected:", a);
               showmpi ("     got:", b);
@@ -464,16 +642,16 @@ check_formats (void)
       err = gcry_mpi_scan (&b, GCRYMPI_FMT_USG,
                            data[idx].a.usg, data[idx].a.usglen, &buflen);
       if (err)
-        fail ("error scanning value %d as %s: %s\n",
-              data[idx].value, "USG", gpg_strerror (err));
+        fail ("error scanning value %s as %s: %s\n",
+              valuestr, "USG", gpg_strerror (err));
       else
         {
           if (gcry_mpi_is_neg (a))
             gcry_mpi_neg (b, b);
           if (gcry_mpi_cmp (a, b) || data[idx].a.usglen != buflen)
             {
-              fail ("error scanning value %d from %s: %s (%lu)\n",
-                    data[idx].value, "USG", "wrong result",
+              fail ("error scanning value %s from %s: %s (%lu)\n",
+                    valuestr, "USG", "wrong result",
                     (long unsigned int)buflen);
               showmpi ("expected:", a);
               showmpi ("     got:", b);
@@ -488,14 +666,14 @@ check_formats (void)
           err = gcry_mpi_scan (&b, GCRYMPI_FMT_PGP,
                                data[idx].a.pgp, data[idx].a.pgplen, &buflen);
           if (err)
-            fail ("error scanning value %d as %s: %s\n",
-                  data[idx].value, "PGP", gpg_strerror (err));
+            fail ("error scanning value %s as %s: %s\n",
+                  valuestr, "PGP", gpg_strerror (err));
           else
             {
               if (gcry_mpi_cmp (a, b) || data[idx].a.pgplen != buflen)
                 {
-                  fail ("error scanning value %d from %s: %s (%lu)\n",
-                        data[idx].value, "PGP", "wrong result",
+                  fail ("error scanning value %s from %s: %s (%lu)\n",
+                        valuestr, "PGP", "wrong result",
                         (long unsigned int)buflen);
                   showmpi ("expected:", a);
                   showmpi ("     got:", b);
@@ -520,11 +698,11 @@ main (int argc, char **argv)
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
   negative_zero ();
   check_formats ();
index 8c4a53e..ec1472a 100644 (file)
@@ -33,6 +33,7 @@
 #include "t-common.h"
 #define N_TESTS 18
 
+static int in_fips_mode;
 
 static void
 print_mpi (const char *text, gcry_mpi_t a)
@@ -115,12 +116,12 @@ reverse_buffer (unsigned char *buffer, unsigned int length)
  *
  * where R is expected result of X25519 (K, U).
  *
- * It calls gcry_pk_decrypt with Curve25519 private key and let
+ * It calls gcry_pk_encrypt with Curve25519 private key and let
  * it compute X25519.
  */
 static void
-test_cv (int testno, const char *k_str, const char *u_str,
-         const char *result_str)
+test_cv_hl (int testno, const char *k_str, const char *u_str,
+            const char *result_str)
 {
   gpg_error_t err;
   void *buffer = NULL;
@@ -188,7 +189,17 @@ test_cv (int testno, const char *k_str, const char *u_str,
   xfree (buffer);
   buffer = NULL;
 
-  if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk)))
+  err = gcry_pk_encrypt (&s_result, s_data, s_pk);
+  if (in_fips_mode)
+    {
+      if (!err)
+        fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d",
+              testno);
+      if (verbose > 1)
+        info ("not executed in FIPS mode\n");
+      goto leave;
+    }
+  if (err)
     fail ("gcry_pk_encrypt failed for test %d: %s", testno,
           gpg_strerror (err));
 
@@ -231,6 +242,95 @@ test_cv (int testno, const char *k_str, const char *u_str,
 }
 
 /*
+ * Test X25519 functionality through the API for X25519.
+ *
+ * Input: K (as hex string), U (as hex string), R (as hex string)
+ *
+ * where R is expected result of X25519 (K, U).
+ *
+ */
+static void
+test_cv_x25519 (int testno, const char *k_str, const char *u_str,
+                const char *result_str)
+{
+  gpg_error_t err;
+  void *scalar = NULL;
+  void *point = NULL;
+  size_t buflen;
+  unsigned char result[32];
+  char result_hex[65];
+  int i;
+  int algo = GCRY_ECC_CURVE25519;
+  unsigned int keylen;
+
+  if (verbose > 1)
+    info ("Running test %d\n", testno);
+
+  if (!(keylen = gcry_ecc_get_algo_keylen (algo)))
+    {
+      fail ("error getting keylen for test %d", testno);
+      goto leave;
+    }
+
+  if (keylen != 32)
+    {
+      fail ("error invalid keylen for test %d", testno);
+      goto leave;
+    }
+
+  if (!(scalar = hex2buffer (k_str, &buflen)) || buflen != keylen)
+    {
+      fail ("error of input for test %d, %s: %s",
+            testno, "k", "invalid hex string");
+      goto leave;
+    }
+
+  if (!(point = hex2buffer (u_str, &buflen)) || buflen != keylen)
+    {
+      fail ("error of input for test %d, %s: %s",
+            testno, "u", "invalid hex string");
+      goto leave;
+    }
+
+  err = gcry_ecc_mul_point (algo, result, scalar, point);
+  if (in_fips_mode)
+    {
+      if (!err)
+        fail ("gcry_ecc_mul_point is not expected to work in FIPS mode for test %d",
+              testno);
+      if (verbose > 1)
+        info ("not executed in FIPS mode\n");
+      goto leave;
+    }
+  if (err)
+    fail ("gcry_ecc_mul_point failed for test %d: %s", testno,
+          gpg_strerror (err));
+
+  for (i=0; i < keylen; i++)
+    snprintf (&result_hex[i*2], 3, "%02x", result[i]);
+
+  if (strcmp (result_str, result_hex))
+    {
+      fail ("gcry_ecc_mul_point failed for test %d: %s",
+            testno, "wrong value returned");
+      info ("  expected: '%s'", result_str);
+      info ("       got: '%s'", result_hex);
+    }
+
+ leave:
+  xfree (scalar);
+  xfree (point);
+}
+
+static void
+test_cv (int testno, const char *k_str, const char *u_str,
+         const char *result_str)
+{
+  test_cv_hl (testno, k_str, u_str, result_str);
+  test_cv_x25519 (testno, k_str, u_str, result_str);
+}
+
+/*
  * Test iterative X25519 computation through lower layer MPI routines.
  *
  * Input: K (as hex string), ITER, R (as hex string)
@@ -256,6 +356,15 @@ test_it (int testno, const char *k_str, int iter, const char *result_str)
     info ("Running test %d: iteration=%d\n", testno, iter);
 
   gcry_mpi_ec_new (&ctx, NULL, "Curve25519");
+  if (in_fips_mode)
+    {
+      if (ctx)
+        fail ("gcry_mpi_ec_new should fail in FIPS mode for test %d",
+              testno);
+      if (verbose > 1)
+        info ("not executed in FIPS mode\n");
+      return;
+    }
   Q = gcry_mpi_point_new (0);
 
   if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32)
@@ -553,13 +662,16 @@ main (int argc, char **argv)
         die ("unknown option '%s'", *argv);
     }
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
 
   start_timer ();
   check_cv25519 ();
diff --git a/tests/t-dsa.c b/tests/t-dsa.c
new file mode 100644 (file)
index 0000000..965b7cf
--- /dev/null
@@ -0,0 +1,627 @@
+/* t-dsa.c - Check the DSA crypto
+ * Copyright (C) 2021 g10 Code GmbH
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "stopwatch.h"
+
+#define PGM "t-dsa"
+#include "t-common.h"
+#define N_TESTS 300
+
+static int no_verify;
+static int custom_data_file;
+static int in_fips_mode;
+
+
+static void
+show_note (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!verbose && getenv ("srcdir"))
+    fputs ("      ", stderr);  /* To align above "PASS: ".  */
+  else
+    fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+  va_end (arg_ptr);
+}
+
+
+/* Prepend FNAME with the srcdir environment variable's value and
+ * return an allocated filename.  */
+char *
+prepend_srcdir (const char *fname)
+{
+  static const char *srcdir;
+  char *result;
+
+  if (!srcdir && !(srcdir = getenv ("srcdir")))
+    srcdir = ".";
+
+  result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
+  strcpy (result, srcdir);
+  strcat (result, "/");
+  strcat (result, fname);
+  return result;
+}
+
+
+/* Read next line but skip over empty and comment lines.  Caller must
+   xfree the result.  */
+static char *
+read_textline (FILE *fp, int *lineno)
+{
+  char line[4096];
+  char *p;
+
+  do
+    {
+      if (!fgets (line, sizeof line, fp))
+        {
+          if (feof (fp))
+            return NULL;
+          die ("error reading input line: %s\n", strerror (errno));
+        }
+      ++*lineno;
+      p = strchr (line, '\n');
+      if (!p)
+        die ("input line %d not terminated or too long\n", *lineno);
+      *p = 0;
+      for (p--;p > line && my_isascii (*p) && isspace (*p); p--)
+        *p = 0;
+    }
+  while (!*line || *line == '#');
+  /* if (debug) */
+  /*   info ("read line: '%s'\n", line); */
+  return xstrdup (line);
+}
+
+
+/*
+ * The input line is like:
+ *
+ *      [mod = L=2048, N=256, SHA-384]
+ *
+ */
+static void
+parse_annotation (char **buffer, const char *line, int lineno)
+{
+  const char *s;
+
+  xfree (*buffer);
+  *buffer = NULL;
+
+  s = strchr (line, '-');
+  if (!s)
+    {
+      fail ("syntax error at input line %d", lineno);
+      return;
+    }
+  *buffer = xstrdup (s-3);
+  (*buffer)[strlen (*buffer) - 1] = 0; /* Remove ']'.  */
+}
+
+/* Copy the data after the tag to BUFFER.  BUFFER will be allocated as
+   needed.  */
+static void
+copy_data (char **buffer, const char *line, int lineno)
+{
+  const char *s;
+
+  xfree (*buffer);
+  *buffer = NULL;
+
+  s = strchr (line, '=');
+  if (!s)
+    {
+      fail ("syntax error at input line %d", lineno);
+      return;
+    }
+  for (s++; my_isascii (*s) && isspace (*s); s++)
+    ;
+  *buffer = xstrdup (s);
+}
+
+
+/* Convert STRING consisting of hex characters into its binary
+   representation and return it as an allocated buffer. The valid
+   length of the buffer is returned at R_LENGTH.  The string is
+   delimited by end of string.  The function returns NULL on
+   error.  */
+static void *
+hex2buffer (const char *string, size_t *r_length)
+{
+  const char *s;
+  unsigned char *buffer;
+  size_t length;
+
+  buffer = xmalloc (strlen(string)/2+1);
+  length = 0;
+  for (s=string; *s; s +=2 )
+    {
+      if (!hexdigitp (s) || !hexdigitp (s+1))
+        return NULL;           /* Invalid hex digits. */
+      ((unsigned char*)buffer)[length++] = xtoi_2 (s);
+    }
+  *r_length = length;
+  return buffer;
+}
+
+
+static void
+one_test_sexp (const char *sha_alg,
+               const char *p, const char *q, const char *g,
+               const char *x, const char *y,
+               const char *msg, const char *k,
+               const char *r, const char *s)
+{
+  gpg_error_t err;
+  int i;
+  char *p0;
+  void *buffer = NULL;
+  void *buffer2 = NULL;
+  void *buffer3 = NULL;
+  void *buffer4 = NULL;
+  void *buffer5 = NULL;
+  size_t buflen, buflen2, buflen3, buflen4, buflen5;
+  gcry_ctx_t ctx = NULL;
+  int md_algo;
+  const char *data_tmpl;
+  gcry_md_hd_t hd = NULL;
+  gcry_sexp_t s_pk = NULL;
+  gcry_sexp_t s_sk = NULL;
+  gcry_sexp_t s_sig= NULL;
+  gcry_sexp_t s_tmp, s_tmp2;
+  unsigned char *out_r = NULL;
+  unsigned char *out_s = NULL;
+  size_t out_r_len, out_s_len;
+  char *sig_r_string = NULL;
+  char *sig_s_string = NULL;
+
+  if (verbose > 1)
+    info ("Running test %s\n", sha_alg);
+
+  if (!strcmp (sha_alg, "SHA-1"))
+    md_algo = GCRY_MD_SHA1;
+  else if (!strcmp (sha_alg, "SHA-224"))
+    md_algo = GCRY_MD_SHA224;
+  else if (!strcmp (sha_alg, "SHA-256"))
+    md_algo = GCRY_MD_SHA256;
+  else if (!strcmp (sha_alg, "SHA-384"))
+    md_algo = GCRY_MD_SHA384;
+  else if (!strcmp (sha_alg, "SHA-512"))
+    md_algo = GCRY_MD_SHA512;
+  else
+    {
+      fail ("error for test, %s: %s: %s",
+            "SHA algo", "invalid", sha_alg);
+      goto leave;
+    }
+
+  err = gcry_md_open (&hd, md_algo, 0);
+  if (err)
+    {
+      fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err));
+      return;
+    }
+
+  if (!(buffer = hex2buffer (p, &buflen)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "p", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer2 = hex2buffer (q, &buflen2)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "q", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer3 = hex2buffer (g, &buflen3)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "g", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer4 = hex2buffer (y, &buflen4)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "y", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer5 = hex2buffer (x, &buflen5)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "x", "invalid hex string");
+      goto leave;
+    }
+
+  err = gcry_sexp_build (&s_sk, NULL,
+                         "(private-key (dsa (p %b)(q %b)(g %b)(y %b)(x %b)))",
+                         (int)buflen, buffer,
+                         (int)buflen2, buffer2,
+                         (int)buflen3, buffer3,
+                         (int)buflen4, buffer4,
+                         (int)buflen5, buffer5);
+  if (err)
+    {
+      fail ("error building SEXP for test, %s: %s",
+            "sk", gpg_strerror (err));
+      goto leave;
+    }
+
+  err = gcry_sexp_build (&s_pk, NULL,
+                         "(public-key (dsa (p %b)(q %b)(g %b)(y %b)))",
+                         (int)buflen, buffer,
+                         (int)buflen2, buffer2,
+                         (int)buflen3, buffer3,
+                         (int)buflen4, buffer4);
+  if (err)
+    {
+      fail ("error building SEXP for test, %s: %s",
+            "pk", gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (buffer3);
+  xfree (buffer4);
+  xfree (buffer5);
+  buffer = buffer2 = buffer3 = buffer4 = buffer5 = NULL;
+
+  if (!(buffer = hex2buffer (msg, &buflen)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "msg", "invalid hex string");
+      goto leave;
+    }
+
+  gcry_md_write (hd, buffer, buflen);
+  xfree (buffer);
+  buffer = NULL;
+
+  if (!(buffer2 = hex2buffer (k, &buflen2)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "salt_val", "invalid hex string");
+      goto leave;
+    }
+
+  err = gcry_pk_random_override_new (&ctx, buffer2, buflen2);
+  if (err)
+    {
+      fail ("error setting salt for test: %s",
+           gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer2);
+  buffer2 = NULL;
+
+  data_tmpl = "(data(flags raw)(hash %s %b)(label %b))";
+
+  err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, ctx);
+  if (err)
+    {
+      if (in_fips_mode)
+        {
+          if (verbose)
+            show_note ("DSA is not allowed in FIPS mode\n");
+        }
+      else
+        fail ("gcry_pkey_hash_sign failed: %s", gpg_strerror (err));
+      goto leave;
+    }
+
+  out_r_len = out_s_len = 0;
+  out_s = out_r = NULL;
+  s_tmp2 = NULL;
+  s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
+  if (s_tmp)
+    {
+      s_tmp2 = s_tmp;
+      s_tmp = gcry_sexp_find_token (s_tmp2, "dsa", 0);
+      if (s_tmp)
+        {
+          gcry_sexp_release (s_tmp2);
+          s_tmp2 = s_tmp;
+          s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0);
+          if (s_tmp)
+            {
+              const char *p1;
+              size_t n;
+
+              out_r_len = buflen2;
+              out_r = xmalloc (out_r_len);
+              if (!out_r)
+                {
+                  err = gpg_error_from_syserror ();
+                  gcry_sexp_release (s_tmp);
+                  gcry_sexp_release (s_tmp2);
+                 goto leave;
+                }
+
+              p1 = gcry_sexp_nth_data (s_tmp, 1, &n);
+              if (n == out_r_len)
+                memcpy (out_r, p1, out_r_len);
+              else
+                {
+                  memset (out_r, 0, out_r_len - n);
+                  memcpy (out_r + out_r_len - n, p1, n);
+                }
+              gcry_sexp_release (s_tmp);
+            }
+          s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0);
+          if (s_tmp)
+            {
+              const char *p1;
+              size_t n;
+
+              out_s_len = out_r_len;
+              out_s = xmalloc (out_s_len);
+              if (!out_s)
+                {
+                  err = gpg_error_from_syserror ();
+                  gcry_sexp_release (s_tmp);
+                  gcry_sexp_release (s_tmp2);
+                 goto leave;
+                }
+
+              p1 = gcry_sexp_nth_data (s_tmp, 1, &n);
+              if (n == out_s_len)
+                memcpy (out_s, p1, out_s_len);
+              else
+                {
+                  memset (out_s, 0, out_s_len - n);
+                  memcpy (out_s + out_s_len - n, p1, n);
+                }
+              gcry_sexp_release (s_tmp);
+            }
+        }
+    }
+  gcry_sexp_release (s_tmp2);
+
+  sig_r_string = xmalloc (2*out_r_len+1);
+  p0 = sig_r_string;
+  *p0 = 0;
+  for (i=0; i < out_r_len; i++, p0 += 2)
+    snprintf (p0, 3, "%02x", out_r[i]);
+
+  sig_s_string = xmalloc (2*out_s_len+1);
+  p0 = sig_s_string;
+  *p0 = 0;
+  for (i=0; i < out_s_len; i++, p0 += 2)
+    snprintf (p0, 3, "%02x", out_s[i]);
+
+  if (strcmp (sig_r_string, r) || strcmp (sig_s_string, s))
+    {
+      fail ("gcry_pk_hash_sign failed: %s",
+            "wrong value returned");
+      info ("  expected: '%s'", r);
+      info ("       got: '%s'", sig_r_string);
+      info ("  expected: '%s'", s);
+      info ("       got: '%s'", sig_s_string);
+    }
+
+  if (!no_verify)
+    {
+      err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, ctx);
+      if (err)
+        fail ("gcry_pk_hash_verify failed for test: %s",
+              gpg_strerror (err));
+    }
+
+ leave:
+  gcry_ctx_release (ctx);
+  gcry_sexp_release (s_sig);
+  gcry_sexp_release (s_sk);
+  gcry_sexp_release (s_pk);
+  if (hd)
+    gcry_md_close (hd);
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (buffer3);
+  xfree (buffer4);
+  xfree (buffer5);
+  xfree (out_r);
+  xfree (out_s);
+  xfree (sig_r_string);
+  xfree (sig_s_string);
+}
+
+
+static void
+check_dsa (const char *fname)
+{
+  FILE *fp;
+  int lineno, ntests;
+  char *line;
+  char *sha_alg;
+  char *p, *q, *g;
+  char *msg, *x, *y, *k, *r, *s;
+
+  info ("Checking DSA.\n");
+
+  fp = fopen (fname, "r");
+  if (!fp)
+    die ("error opening '%s': %s\n", fname, strerror (errno));
+
+  sha_alg = NULL;
+  p = q = g = NULL;
+  msg = x = y = k = r = s = NULL;
+  lineno = ntests = 0;
+  while ((line = read_textline (fp, &lineno)))
+    {
+      if (!strncmp (line, "[mod", 4))
+        parse_annotation (&sha_alg, line, lineno);
+      else if (!strncmp (line, "P =", 3))
+        copy_data (&p, line, lineno);
+      else if (!strncmp (line, "Q =", 3))
+        copy_data (&q, line, lineno);
+      else if (!strncmp (line, "G =", 3))
+        copy_data (&g, line, lineno);
+      else if (!strncmp (line, "Msg =", 5))
+        copy_data (&msg, line, lineno);
+      else if (!strncmp (line, "X =", 3))
+        copy_data (&x, line, lineno);
+      else if (!strncmp (line, "Y =", 3))
+        copy_data (&y, line, lineno);
+      else if (!strncmp (line, "K =", 3))
+        copy_data (&k, line, lineno);
+      else if (!strncmp (line, "R =", 3))
+        copy_data (&r, line, lineno);
+      else if (!strncmp (line, "S =", 3))
+        copy_data (&s, line, lineno);
+      else
+        fail ("unknown tag at input line %d", lineno);
+
+      xfree (line);
+      if (sha_alg && p && q && g && msg && x && y && k && r && s)
+        {
+          one_test_sexp (sha_alg, p, q, g, x, y, msg, k, r, s);
+          ntests++;
+          if (!(ntests % 256))
+            show_note ("%d of %d tests done\n", ntests, N_TESTS);
+          xfree (msg); msg = NULL;
+          xfree (x); x = NULL;
+          xfree (y); y = NULL;
+          xfree (k); k = NULL;
+          xfree (r); r = NULL;
+          xfree (s); s = NULL;
+        }
+
+    }
+  xfree (p);
+  xfree (q);
+  xfree (g);
+  xfree (sha_alg);
+  xfree (msg);
+  xfree (x);
+  xfree (y);
+  xfree (k);
+  xfree (r);
+  xfree (s);
+
+  if (ntests != N_TESTS && !custom_data_file)
+    fail ("did %d tests but expected %d", ntests, N_TESTS);
+  else if ((ntests % 256))
+    show_note ("%d tests done\n", ntests);
+
+  fclose (fp);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  char *fname = NULL;
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options]\n"
+                 "Options:\n"
+                 "  --verbose       print timings etc.\n"
+                 "  --debug         flyswatter\n"
+                 "  --no-verify     skip the verify test\n"
+                 "  --data FNAME    take test data from file FNAME\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--no-verify"))
+        {
+          no_verify = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--data"))
+        {
+          argc--; argv++;
+          if (argc)
+            {
+              xfree (fname);
+              fname = xstrdup (*argv);
+              argc--; argv++;
+            }
+        }
+      else if (!strncmp (*argv, "--", 2))
+        die ("unknown option '%s'", *argv);
+
+    }
+
+  if (!fname)
+    fname = prepend_srcdir ("t-dsa.inp");
+  else
+    custom_data_file = 1;
+
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  if (!gcry_check_version (GCRYPT_VERSION))
+    die ("version mismatch\n");
+  if (debug)
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
+  start_timer ();
+  check_dsa (fname);
+  stop_timer ();
+
+  xfree (fname);
+
+  info ("All tests completed in %s.  Errors: %d\n",
+        elapsed_time (1), error_count);
+  return !!error_count;
+}
diff --git a/tests/t-dsa.inp b/tests/t-dsa.inp
new file mode 100644 (file)
index 0000000..38fae45
--- /dev/null
@@ -0,0 +1,2224 @@
+# CAVS 11.2
+# "SigGen" information for "dsa2_values"
+# Mod sizes selected: L=1024, N=160, SHA-1 L=1024, N=160, SHA-224 L=1024, N=160, SHA-256 L=1024, N=160, SHA-384 L=1024, N=160, SHA-512 L=2048, N=224, SHA-1 L=2048, N=224, SHA-224 L=2048, N=224, SHA-256 L=2048, N=224, SHA-384 L=2048, N=224, SHA-512 L=2048, N=256, SHA-1 L=2048, N=256, SHA-224 L=2048, N=256, SHA-256 L=2048, N=256, SHA-384 L=2048, N=256, SHA-512 L=3072, N=256, SHA-1 L=3072, N=256, SHA-224 L=3072, N=256, SHA-256 L=3072, N=256, SHA-384 L=3072, N=256, SHA-512
+# Generated on Tue Aug 16 11:21:08 2011
+
+[mod = L=1024, N=160, SHA-1]
+
+P = a8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed3256b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b02e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd5ebe2d1229681b5b06439ac9c7e9d8bde283
+Q = f85f0f83ac4df7ea0cdf8f469bfeeaea14156495
+G = 2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df131f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909a6a3a99bbe089216368171bd0ba81de4fe33
+
+Msg = 3b46736d559bd4e0c2c1b2553a33ad3c6cf23cac998d3d0c0e8fa4b19bca06f2f386db2dcff9dca4f40ad8f561ffc308b46c5f31a7735b5fa7e0f9e6cb512e63d7eea05538d66a75cd0d4234b5ccf6c1715ccaaf9cdc0a2228135f716ee9bdee7fc13ec27a03a6d11c5c5b3685f51900b1337153bc6c4e8f52920c33fa37f4e7
+X = c53eae6d45323164c7d07af5715703744a63fc3a
+Y = 313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761bbb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae19c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32786d96f5a31aedf75364008ad4fffebb970b
+K = 98cbcc4969d845e2461b5f66383dd503712bbcfa
+R = 50ed0e810e3f1c7cb6ac62332058448bd8b284c0
+S = c6aded17216b46b7e4b6f2a97c1ad7cc3da83fde
+
+Msg = d2bcb53b044b3e2e4b61ba2f91c0995fb83a6a97525e66441a3b489d9594238bc740bdeea0f718a769c977e2de003877b5d7dc25b182ae533db33e78f2c3ff0645f2137abc137d4e7d93ccf24f60b18a820bc07c7b4b5fe08b4f9e7d21b256c18f3b9d49acc4f93e2ce6f3754c7807757d2e1176042612cb32fc3f4f70700e25
+X = e65131d73470f6ad2e5878bdc9bef536faf78831
+Y = 29bdd759aaa62d4bf16b4861c81cf42eac2e1637b9ecba512bdbc13ac12a80ae8de2526b899ae5e4a231aef884197c944c732693a634d7659abc6975a773f8d3cd5a361fe2492386a3c09aaef12e4a7e73ad7dfc3637f7b093f2c40d6223a195c136adf2ea3fbf8704a675aa7817aa7ec7f9adfb2854d4e05c3ce7f76560313b
+K = 87256a64e98cf5be1034ecfa766f9d25d1ac7ceb
+R = a26c00b5750a2d27fe7435b93476b35438b4d8ab
+S = 61c9bfcb2938755afa7dad1d1e07c6288617bf70
+
+Msg = d5431e6b16fdae31481742bd394758beb8e24f31947e19b7ea7b458521882270c1f43192aa050f4485145af8f3f9c5142d68b85018d2ec9cb7a37ba12ed23e73b95fd680fba3c61265e9f5a0a027d70fad0c8aa08a3cbfbe99018d0045386173e5fae225faebe0cef5dd45910f400a86c2be4e15252a16de4120a267be2b594d
+X = 20bcabc6d9347a6e79b8e498c60c44a19c73258c
+Y = 23b4f404aa3c575e550bb320fdb1a085cd396a10e5ebc6771da62f037cab19eacd67d8222b6344038c4f7af45f5e62b55480cbe2111154ca9697ca76d87b56944138084e74c6f90a05cf43660dff8b8b3fabfcab3f0e4416775fdf40055864be102b4587392e77752ed2aeb182ee4f70be4a291dbe77b84a44ee34007957b1e0
+K = 7d9bcfc9225432de9860f605a38d389e291ca750
+R = 3f0a4ad32f0816821b8affb518e9b599f35d57c2
+S = ea06638f2b2fc9d1dfe99c2a492806b497e2b0ea
+
+Msg = 85662b697550e4915c29e338b624b912845d6d1a920d9e4c1604dd47d692bc7c0ffb95ae614e852bebaf1573758ad01c713cac0b476e2f121745a3cfeeffb2441ff6abfb9bbeb98aa634ca6ff541947dcc9927659d44f95c5ff9170fdc3c86473cb601ba31b487fe5936bac5d9c632cbcc3db06246ba01c55a038d797fe3f6c3
+X = 52d1fbe687aa0702a51a5bf9566bd51bd569424c
+Y = 6bc36cb3fa61cecc157be08639a7ca9e3de073b8a0ff23574ce5ab0a867dfd60669a56e60d1c989b3af8c8a43f5695d503e3098963990e12b63566784171058eace85c728cd4c08224c7a6efea75dca20df461013c75f40acbc23799ebee7f3361336dadc4a56f305708667bfe602b8ea75a491a5cf0c06ebd6fdc7161e10497
+K = 960c211891c090d05454646ebac1bfe1f381e82b
+R = 3bc29dee96957050ba438d1b3e17b02c1725d229
+S = 0af879cf846c434e08fb6c63782f4d03e0d88865
+
+Msg = 87b6e75b9f8e99c4dd62adb693dd5890edff1bd0028f4ef849df0f1d2ce6b181fc3a55aea6d0a1f0aecab8ed9e248a00e96be794a7cfba1246efb710ef4b37471cef0a1bcf55cebc8d5ad071612bd237efedd5102362db07a1e2c7a6f15e09fe64ba42b60a2628d869ae05ef611fe38d9ce15eeec9bb3decc8dc17809f3b6e95
+X = c86a54ec5c4ec63d7332cf43ddb082a34ed6d5f5
+Y = 014ac746d3605efcb8a2c7dae1f54682a262e27662b252c09478ce87d0aaa522d7c200043406016c0c42896d21750b15dbd57f9707ec37dcea5651781b67ad8d01f5099fe7584b353b641bb159cc717d8ceb18b66705e656f336f1214b34f0357e577ab83641969e311bf40bdcb3ffd5e0bb59419f229508d2f432cc2859ff75
+K = 6c445cee68042553fbe63be61be4ddb99d8134af
+R = 637e07a5770f3dc65e4506c68c770e5ef6b8ced3
+S = 7dfc6f83e24f09745e01d3f7ae0ed1474e811d47
+
+Msg = 2259eead2d6bbc76d49213ea0dc8b7350a97699f22341044c3940782364ac9ea683179a438a5ea45998df97c2972dae03851f5be23fa9f04182e79ddb2b56dc8652393ecb27f3f3b7c8a8d761a86b3b8f4d41a07b4be7d02fddefc42b928124a5a45b9f4609042209b3a7f585bd514cc39c00effcc42c7fe70fa83edf8a32bf4
+X = aee6f213b9903c8069387e64729a08999e5baf65
+Y = 0fe74045d7b0d472411202831d4932396f242a9765e92be387fd81bbe38d845054528b348c03984179b8e505674cb79d88cc0d8d3e8d7392f9aa773b29c29e54a9e326406075d755c291fcedbcc577934c824af988250f64ed5685fce726cff65e92d708ae11cbfaa958ab8d8b15340a29a137b5b4357f7ed1c7a5190cbf98a4
+K = e1704bae025942e2e63c6d76bab88da79640073a
+R = 83366ba3fed93dfb38d541203ecbf81c363998e2
+S = 1fe299c36a1332f23bf2e10a6c6a4e0d3cdd2bf4
+
+Msg = 219e8df5bf881590430ece608250f7670dc56537249302429e28ecfeb9ceaaa54910a69490f765f3df82e8b01cd7d76e561d0f6ce226ef3cf752cada6febdc5bf00d67947f92d420516b9e37c96c8f1f2da0b075097c3bda758a8d91bd2ebe9c75cf147f254c256963b33b67d02b6aa09e7d7465d038e50195ece4189b41e768
+X = 699f1c07aa458c6786e770b40197235fe49cf21a
+Y = 3a41b0678ff3c4dde20fa39772bac31a2f18bae4bedec9e12ee8e02e30e556b1a136013bef96b0d30b568233dcecc71e485ed75c922afb4d0654e709bee84993792130220e3005fdb06ebdfc0e2df163b5ec424e836465acd6d92e243c86f2b94b26b8d73bd9cf722c757e0b80b0af16f185de70e8ca850b1402d126ea60f309
+K = 5bbb795bfa5fa72191fed3434a08741410367491
+R = 579761039ae0ddb81106bf4968e320083bbcb947
+S = 503ea15dbac9dedeba917fa8e9f386b93aa30353
+
+Msg = 2da79d067885eb3ccf5e293ae3b1d8225322203abb5adfde3b0f53bbe24c4fe001541e1183d870a997f1f9460100b5d711923180154345287a0214cf1cac37b7a47dfbb2a0e8ce4916f94ebd6fa54e315b7a8eb5b63cd954c5ba05c1bf7e33a4e8a151f32d2877b01729c1ad0e7c01bb8ae723c995183803e45636520ea38ca1
+X = d6e08c20c82949ddba93ea81eb2fea8c595894dc
+Y = 56f7272210f316c51af8bfc45a421fd4e9b1043853271b7e79f40936f0adcf262a86097aa86e19e6cb5307685d863dba761342db6c973b3849b1e060aca926f41fe07323601062515ae85f3172b8f34899c621d59fa21f73d5ae97a3deb5e840b25a18fd580862fd7b1cf416c7ae9fc5842a0197fdb0c5173ff4a4f102a8cf89
+K = 6d72c30d4430959800740f2770651095d0c181c2
+R = 5dd90d69add67a5fae138eec1aaff0229aa4afc4
+S = 47f39c4db2387f10762f45b80dfd027906d7ef04
+
+Msg = ba30d85be357e7fb29f8a07e1f127baaa24b2ee027f64cb5efeec6aaeabcc7345c5d556ebf4bdc7a61c77c7b7ea43c73babc18f7b4807722da239e45ddf249849cbbfe3507112ebf87d7ef560c2e7d391ed8424f8710cea41685143e3006f81b68fbb4d5f9644c7cd10f7092ef2439b8d18c0df655e00289372a4166385d640c
+X = 50018482864c1864e9db1f04bde8dbfd3875c76d
+Y = 0942a5b7a72ab116ead29308cf658dfe3d55d5d61afed9e3836e64237f9d6884fdd827d2d5890c9a41ae88e7a69fc9f345ade9c480c6f08cff067c183214c227236cedb6dd1283ca2a602574e8327510221d4c27b162143b7002d8c726916826265937b87be9d5ec6d7bd28fb015f84e0ab730da7a4eaf4ef3174bf0a22a6392
+K = df3a9348f37b5d2d4c9176db266ae388f1fa7e0f
+R = 448434b214eee38bde080f8ec433e8d19b3ddf0d
+S = 0c02e881b777923fe0ea674f2621298e00199d5f
+
+Msg = 83499efb06bb7ff02ffb46c278a5e92630ac5bc3f9e53dd2e78ff15e368c7e31aad77cf771f35fa02d0b5f135208a4afdd867bb2ec26ea2e7dd64cdef237508a38b27f39d8b22d45cac5a68a90b6ea76058645f6356a9344d36f00ec6652eaa4e9bae7b694f9f1fc8c6c5e86fadc7b27a219b5c1b2ae80a725e5f61165fe2edc
+X = ae56f66b0a9405b9cca54c60ec4a3bb5f8be7c3f
+Y = a01542c3da410dd57930ca724f0f507c4df43d553c7f69459939685941ceb95c7dcc3f175a403b359621c0d4328e98f15f330a63865baf3e7eb1604a0715e16eed64fd14b35d3a534259a6a7ddf888c4dbb5f51bbc6ed339e5bb2a239d5cfe2100ac8e2f9c16e536f25119ab435843af27dc33414a9e4602f96d7c94d6021cec
+K = 8857ff301ad0169d164fa269977a116e070bac17
+R = 8c2fab489c34672140415d41a65cef1e70192e23
+S = 3df86a9e2efe944a1c7ea9c30cac331d00599a0e
+
+Msg = f23ee79eb4fce5cbf3b08d65a1803d2e3e191d3580a44d177d8ff069f90784d012ca5746e6dd6638dfe8413f1db3d8fe282c2160f5dd96607dd63d610f791dfc10abad18721587101cec8a2a12913cfbada3a5b7593958b9bfa6e9af3af5d71ff17ec72aaaeecaaffc5d174e629a090297e94cdfe988d9bf6c80827c23df5137
+X = a62079b4f45772bf17b85d7560e3be4e521439eb
+Y = 229a26dcaff29ed1a7264ed0f77d676239b9ba1ef4778e7dd640e8aa6fabdc1f1bd3f582e211bd01c26b3d9d3bffe7199f9ed45d764cd9d0e844b385cb34e6de22370ebc6ba41db409d63f50c1ac09bed00cdc2b7c55223c596b7e133ba25ba9e78f33502f8dd52f32a667a7683e504047817963238d9629a918a0ceebaad518
+K = c01acd36910f2f2bff608386b81c35a0a7c0b378
+R = 8d388ec7f2863dd5b7c99ac93505d1580bf2e0c7
+S = 76ae9317696d37f2d8bd61c47733e9455b61d347
+
+Msg = 6836255e6e659de4ffb535892d466a3bea09693e587eb5bd50f44f8a22f11697057d68660bc6562400d587baac1c19d330ff794a70df5300a5211c72541a56d0ff2af02a278ed2db1df94ccb2026d3138b2d924245021ee835d3c17b0b3b7677def85611227f6ce2913e7cb446a479b95acfd0105c25e4656fbc56c2a10a22b3
+X = 7861e82e66b6caea54b159c59c887ec27b2e915f
+Y = a7bbc35423510edfebf79c4e2e56986f2806d11116bcae90a716f05dcbfc46dcbfebe2ec946c40f9cc8c1a7439cdd04e270122ec1c3baca83811a9f1bdaed9b1172150af1c8ce1c5d502dfe5f4e8467e50605087a8f8c5f45ca672fd049eec0a06f5e01f782d51f3ba56404bf1388065552fc87ad21ac0fa4027a145d0b0d9e6
+K = 4e22cfa2e8ca2b33a9fd91ff4837fc205864e8b1
+R = c0ab43d309a5e94b6ef4db9943306e6d966fc9b5
+S = 07ec5aa1928f19fc3a420f29b935bac46124c0e2
+
+Msg = 4b0845c99db348294f1d83166b27f448ec29ab7965464477f45444f44672a409ddcafaf35e91faf401eca7498e3268caa2d96bf1aa840c0e1ed43a5ab60888fcf02b2f8a2c89daa598adf0b7d2dace9210efd41ab496a1e73a182da430c1d043e249a1289c91809c8c7298cfdbb0ae438b00936c283a0ec2d79cdc81c9ce3c2d
+X = 6f2d3b09fae6910dd975870db3a2c19d97169491
+Y = 541a9c45e165d3d91e71bb1370d7c032c360322aa15e99d8c1c16ea35c8c193224a06467ab77a65478c467b3f20cb0c5fdb8c84cefa69566a594a2aa54c3a948ebc1ea7e6c3d28d380cbd01740634c96b76d6a03cc6eba0afa7226f23fc10a18b0b6f97270dfa038160960b5b839ba66af50fda07245810e80d38b6693e8a9ce
+K = 8588557c12ec6fe176b0be7bbd8b482ad78f1fef
+R = 44286019c1d53103980616940c028bad3217f78d
+S = 4b372bf527c515f58025699a45f2021ef18e11b9
+
+Msg = 4597c1ca0b0764be31fa73ccc589116cc8d0a31605f2550eb37fa569b2496c4f34321d61bb8e49f858c8671b7437fc15f269dd2d4146470b817dfe3069225ddd3cd4a6c977fb6cfc0d43264a7bf6659283e140e4c89ab2e8a4d0ede6274961d655bd79c7e47880a741fb0180c325b5b7d2f7b8a57aed52d0206a83bb69a9d7a4
+X = 49f6c1ac8e639bcc99b2d9d1f1e325713f29b97c
+Y = 5315adf90e196946be6b04c5414da1fafd98b0d17c3a39000a00091b7b56574b1ecd026eabb25be9ecd0ad691df2b7bf7eecd6ad95bb4d7d17ac747060ee7e3eb5c6fb7557cf7e8003a620e43e587d0612854472c3ad851839f744159411a33876aec365eb0491dec80ba14cba2d11dec42af4a4bf9c99312a2ae7e5462a2adf
+K = 8ef1c5976ac8caf74df65d9ecdbe78a6490bc220
+R = 90d547712bc0cebbd3ebd18a63d9b92a03953050
+S = 34ea6176b4c63043295f129a4895e14ee5816563
+
+Msg = 18c62a40b52347a473f57aa668eebb4484beb5f10fdc51779e6770106c0d122eb6356ae53a3379e270edca39015da3005770c7b2a5afd11217993153ff43a0b26db01aa2a493de061492a0aa3f229b5abd1aff29395e31b063504eb35620219ba29997f92a52e1b2e6ff207480fd13d58ff0290eec5aabf23b84943eea20a43c
+X = 396cbe3e71d74f6db795c38d49c32d78eab03397
+Y = 3b738246f9e38cebf4542ced3fc0c0096aeb9e9a3ad928f4dd4745d875fe6e20fb65556d06696432ecffd55b334940c6e23c903f0aa4a1335f7394c55070586baac86c38cc198ebaf15401259528c55192e9298d2a0c8914daf2ad00259fe72555c3c0442e38c1e6e5020928c6e6571a0a98f6f485e43791ae8aaab180461fa4
+K = 04bfe51616f5c244d2e01648362f5bbe5fa73501
+R = 29b7c0f90d624f8d587efd3f49f97da70f6e63e7
+S = 222a3d9ffca0dcf57937e89c92538e32e7a8680f
+
+[mod = L=1024, N=160, SHA-224]
+
+P = 8b9b32f5ba38faad5e0d506eb555540d0d7963195558ca308b7466228d92a17b3b14b8e0ab77a9f3b2959a09848aa69f8df92cd9e9edef0adf792ce77bfceccadd9352700ca5faecf181fa0c326db1d6e5d352458011e51bd3248f4e3bd7c820d7e0a81932aca1eba390175e53eada197223674e3900263e90f72d94e7447bff
+Q = bc550e965647fb3a20f245ec8475624abbb26edd
+G = 11333a931fba503487777376859fdc12f7c687b0948ae889d287f1b7a712ad220ae4f1ce379d0dbb5c9abf419621f005fc123c327e5055d1850634c36d397e689e111d598c1c3636b940c84f42f436846e8e7fcad9012ceda398720f32fffd1a45ab6136ce417069207ac140675b8f86dd063915ae6f62b0cec729fbd509ac17
+
+Msg = fb2128052509488cad0745ed3e6312850dd96ddaf791f1e624e22a6b9beaa65319c325c78ef59cacba0ccfa722259f24f92c17b77a8f6d8e97c93d880d2d8dbbbedcf6acefa06b0e476ca2013d0394bd90d56c10626ef43cea79d1ef0bc7ac452bf9b9acaef70325e055ac006d34024b32204abea4be5faae0a6d46d365ed0d9
+X = 6e2e31bbfc670944d7a7120e39a981520614d8a8
+Y = 7e339f3757450390160e02291559f30bed0b2d758c5ccc2d8d456232bb435ae49de7e7957e3aad9bfdcf6fd5d9b6ee3b521bc2229a8421dc2aa59b9952345a8fc1de49b348003a9b18da642d7f6f56e3bc665131ae9762088a93786f7b4b72a4bcc308c67e2532a3a5bf09652055cc26bf3b18833598cffd7011f2285f794557
+K = 8cb35d255505a4c41421e562d10827266aa68663
+R = afee719e7f848b54349ccc3b4fb26065833a4d8e
+S = 734efe992256f31325e749bc32a24a1f957b3a1b
+
+Msg = 02971e0cdd48ae2331db9c6285e9880e96104fa7a9f378dfea718e63efe98352fe4d35a2bc94b3a888cfb88b8b7d9f6c8c54e48613f32c9946ffe6e9a4b7108ececdda41bc151b3d8724b61f5b83a4e27476914387b0488e41be54f63aa773175eb373a3641e6e7950eee8faf048a841f107d30cf9be268493231545d8984694
+X = 0b448f49a085a52a03d7f668a1d6fb87f2e221ac
+Y = 633bb757b3c0e3b7867bf845301ea4e39f75c9759c223f46ce266d406b9df5db501fb826b6e61cba6104c604458c90799f2a36ab51166d0e83b770840624fedc35ebfb9853419e7e09b32b4bd652da4f1ce973ac2620c966b61e35a3f216439a8de1a104f172e1b6e2878112a66c34d16a9aef3ac24a34af5edbf39818a3e2ef
+K = 4481a4be9db6821e3b0a08c9c82603631971a682
+R = 92c65e07462d668b06dd45b608784965897838bc
+S = 2e40adf41cafb8048c793c7092a7e823515b6cfa
+
+Msg = 062e82fb43236ee17ebfaa3d363b9b873d0fe41444c74cef7f7e3bd81f723fd90fd148a28e997585413695113757758aa4dd275f70b375f8903c7be46e3a3ad3190cd04971abd2f1db192ef0d2b98bbb80181a721a5809928b5bca5c118a2911132ad233cd27c7e41adfccfeb4e952874bfa819661182975e44d37c61734759c
+X = a4a25a8bb1c2ba69f9611939b591032b96333fa3
+Y = 3b0a091dfca05dce61e9f05b15b07487d2e3ea4f568dc9ac752d42c0aa771ae0ccc372ce9774fb9fd16a30cb3759bb1989488ce85db7cdfa506476acec644c21168f2db1f36efe0230c6fb8f1f2ae4eaf1799d5e29e212467b11bfbc1eebed142d7a017262cd8735e3e29d8e0c4a6e766c07d7aa9f8d176f536087bfecf4c414
+K = a7135820910f041b27321534a17bb1f33ac51aca
+R = ba554124874d06a6cef62740e15821ccddbfe6f3
+S = 5962be757d75b0f17d15482ebb595ca4e9fbfe22
+
+Msg = 4fca074844eae247d19c06e92032ae8e773043e2e1f45d400e9dcebbde5d65e7c1423b0390161991c026f38a0e2bfeef40dae18741737b1d535ab46b566a1b672fc22dec86747a7c7638fa65047f1ede36ad43f6aedf51b5bf2979adf4d9a94ed802a29de5603b704770b32c8b946a32e1b6054cd70c3add025cc9371d1e404d
+X = 1f15cafca282083e82d7e54258647b2914418986
+Y = 40b638c94b1e719a337d83358699c70cd867ff888c655a5f5a1de8732d058bf027d4747efe3b8dedca3276de5a58f136ed35cff03030f672da65c71f18e58278ddfc7b9b50a248eff9236874ee3cb0d0a35b7b2ee185b139ea84eed7bffc5094ab8743a75374bc36c7d69d5f3e6fe5f3ef1f9358f00a3c5892fff41ed6afee3b
+K = 128ab9677c7ade5e1c02a8427650ff054db6390e
+R = 651a389d8ca50d6e3273cabbe71cd84cccd02361
+S = 3401fe47b3812daa8c020c9bd42609cbebdfa728
+
+Msg = 4d9630fe058998ca5b80ae62f3f73dc85bee291509843ac00240d13d55251ae53b37794783b97d53e042cab26f8c84de0a70f5b43051fbefb3e43f08f5d2e8aad9e2de2717412dbb902acc8849adc04d06fed8c1421c4cfe8b81ee7f5ac5d4f0c0b68e80b6f88fd3c7d5b32022572b0a681bd2d4df2d047b0b23b6887145afe1
+X = 1485f719b8be77c78829baa0d2c322df60174476
+Y = 727b6528357d6705c20d31358f641934fdec63cc66df98837d2f378164e15fa0842207acf3220c8023a9f4f8d2057165b3c849eaeb5376e3fad11785f1d0261779aaedd53b1e52798007eb4c8e83b1ff321b620d883391a14fa47fec4901d96ec232eabb4a0bb4453368fef5176c67135649979d3214d3fb67a1319ac54feb01
+K = 8f4cc1254c787ec8cbf54405105f7ef83ffdeee0
+R = 9ca3e433504c557ba1aac66469781175cdfb4ad5
+S = 72145dfa5279dd82ae99604d16a2b8df71b95320
+
+Msg = 62b9d601e30b42a279c7e04df3ca8d8140a55cd5876c7e9181c73575e4c4f921a94e4e2d0bdd7ba98600d652e5df5be9464e7a9011ab486960f69d57ece1d2c4af9324457c1e3d83fba4265beb47407e4761dbc949d5bd67fee4a476a4d5a93d77acda96a221a0a31e0f024b3f0b8234c015238f3258daa085ae9f4e1aa7b1cc
+X = 43c76a9a00045cdfb2e7927b5c8730e006423c05
+Y = 5f6dfb064caddf644af399e33a672565766761d55ac0b84bead42c3980e7e396043744361778f04dcb698e4563853420fecacd594af828f57df541d9e4de899d61f04f6379c1c96246d152369395242a1c2e70eef8f35417a0ffdb039282516ce21b85687904c511087f113e5142f027f1179712edcbce27939ab15ec49c085f
+K = 5e4b5e4595e31397422c7a4487ae51051289be61
+R = 331920a7b79e3cfa7638e409d9702aafd08fbec6
+S = 071d06e6cd301515f37b60690afa219fe5083d96
+
+Msg = 0006e09c20376442e689bf2d34268fd69109c1301ea66cbe90394cc0f41f94822c28845819b9a98764d2f7262e98891487ff55b05bd69e18b7cad41bd98e137566b6041c739db11f78e567cac02f33f140d19a4805002545375daebfd7dcbea33242e73c8e269149d7eb9db9f9006e17acb736b5e977645ab651b81225c5e543
+X = 16f89d97dd3b31c191495173ae0e145c6ce185d6
+Y = 1b1f725664d75bdcb2a5a4c653061c460799dd48bf1e6b03e13c71d83e3fdb506fa94e6cafb5dbdead88a33d23d4e9287b4707e1fba871b97c9a48f930cdccba0dc06a4f0a8bfbb4e14d0b4d5a0871fa1341caec7bc08138713121d419769f31203508df71947265644fdc6137d8e466c8cb0ce985340cb2e279b4ce9315a772
+K = 475b5aa12ff77d49e4c8171f80d3d1f15147ed12
+R = b6aa833b825184729af308f81bf5e58e2d7e9284
+S = 5453b4b2e3fc802b2f977d0cf6eb7f5c16673fa3
+
+Msg = e04a71f2b5c176a0db17a983a17dec588c00f42c9aa3026b5eb440f07a2140c2ed84024e0531ea7788dfeaa91883fb6a9841c17dcfd312968adb00e556bc7eb3021f57b7a16894fa4fe12ec93dfd494a0a1c693d6ade154ef648c05552da41224d4922d1861d9f7671b8ce6ce448e895ea0eed25802e3350ec08ae79f2d61e0f
+X = 3eda44e3c38380df7a4f47d8e1024596238bcef1
+Y = 687e16309b06817b93236dd990faef9e232eb81cb9c7d6dae4fdd4f8e7ca933e185b1da622d7c7fa35e0a3906f915ded14ba96d6035b46bd6ca5fe172af94e081fb0b9a9583a458bd206c1e87f97a57d00d6eade19ec56ac2e9bbd8c15df356ee7b12c91311a38fc3315cfde9ff462ca6adff2808b3f8e805ee915ae885ca957
+K = aeaa655b6febfec50b05562c3f358865533e4736
+R = 14892b1ec7fc716c75a17f7ad2e41ec6faa78836
+S = 72cc56a9890e8bdf1a53d3acc6f89137264f9ff8
+
+Msg = 5e8eb96b5c6ad75d3dab1e28bb2ce751ecc31611a019e8d4b561c7e4533cc7ab73bd9de931e8c54c51c5711e6c276a8ed92f4bb457ddf28233da2ca3e3013c56e3cd2bc61d4d4e0e22cf6361304e56d68b315ca5d3fcc472a7eef8cca575204dd084a21a99ba67fddbf90df7c6c658761734bce13c3d22d80b6fb9bece551492
+X = 0b55f99ad958a766eaf5ac20a127a4df1b946bae
+Y = 50b0f7605911bce6ed5ecff1e3c1816fbbf03a1479a0820603ffa715aef9ffbccbd067579cbbc8c87c392e85bbe929a0b5e1059faae6f9121df49c66a049a98a90d84c70a21312bf837f4723993d0ec0ac4c2a7ffb9d400957b39fb83e951ef41362452cf458d784c43fe822ea7a7abbea0a6998321a93819d2d282c7884f5c2
+K = 9e9b9afb43a7157761f6c2011138d2f65ac1cba9
+R = 7399b120d4bfbd6dc4064d2f3f8f0ca5c362b2d8
+S = 2302d81d7ebb2417eef45d88941b070ecab11cab
+
+Msg = da91c692cdb0a59562e2b664dcfe7554ac589d57f82246c4a8a3f9573bf47b257eb8f93447c1ebab13dce53d6f4416fb2c6c36303ed97885cf7a6caef055f7e3145ef3838c31877fad7a8883ffc84ebd973f8c06d17cdd339bb3371f9d3d4f2d9f0b80ae2bcc878b4af78f845eac4f2aacee6a9451daf814a44e927bb5428820
+X = ac701252c773ba36711b9731afdc077c5d3f9271
+Y = 678b3958ed24fc84942054f49d9e6f27bbac7de3a4a52af9ffcb9ce6c1fb8bdd99db0e80c868ac547c4cfc782de7ebcf6943b2e46433c670178de0104bd6fc25dc3054db9c48c12706e1dea35e163be36a4ab721950c028b0546f1719ff2edd81b2b7974fb9b121224ccfaabc47e9e629a97bc6ba42691ca3f649ccac47d0f1e
+K = 6cabf2c0e2890b2b393da3ea6aac2782216efa73
+R = 6f1579edcf437584d3e939fa5b002eee83e3b614
+S = 71208a87a4cf2b3a9b65477773b0096d452dae60
+
+Msg = 0f2edc87f4d2942c4693b064a511b93f790c60dc149a1b0b7041af5183bc0f42234134b284270e4c7e53614f7ecfe711de0efb28336d0bb359c86e8be8839f583211e9174832b3d41ee6d21864ac6186fd1db920dda65b25966c5951ab8a2050dda87d1d72e3032852ad43da9fb430e850022b4bb6cc9cb90e428f3a5ca32a62
+X = 588f40e3eb813cd22a41c9cdeadb6895a348db3c
+Y = 3a978e9022a8f7a0caa91f275bf9cf7648e1b9a31a0702d8acdbf59affb5467fb07a8f7e5b4c86775ac4efb609b946f05a3f13034db94acc64057f906d1854910de538f84367181c618e96c3f922547d408ee6408b7a70acedc75de8ae445c5d4dd5def4a352d2528234070cc720700c14ce12d2f36990d36b29d7b00596e34b
+K = 8ac2fe7bcd690a7239d294b22725b818d262a446
+R = b6ea9cdb211c4560b3d592e93af6d5f133b64b9b
+S = 6242e45a472fa8147cb5253dbddebae31ef31e4e
+
+Msg = d12fc1983e0095e9e2b6b8743fb34386cc4821540e3efe1a29f84cf7e63e2a0668d551f912ad2221b5a3d6b9ebd12136def5e6690e1d32aae919f9f1cf5d24d62a46a9a9a604bae11b9c0866350367204a920b589a317ddfbb877f9fad6b0d3629af9635da46933151c0d9a20aaabddd3df5d049659b2860ddb8b20963261ea0
+X = 67cd81c7d6ac2d8bd44ef26297ac02ecba41f73f
+Y = 10b7b14ad29fb34d7a39f3e953051f456a0cd1233ef54d90a4adc82dfbd9fa7a85628f11039632b47ba9daeca6e463ec4644f5e2a2a4bf95d392e8c9c9f287a20ba45a198815ca0e9ba854d7f3c79d9037fa1417724fb7f02799b1c2b2bcc79d64367b90c06d1789dcc6de57ca19fcefafc04fcce29c8f495ed564f5d9a112ca
+K = 1341e376e8919e01991e5e48b8e0c7255929b3d2
+R = 360617965f65a68abcb83dbf2d886a1a10ca05de
+S = 71abb6acbf7e653d2ebc3cb7149b51cc0c92fba8
+
+Msg = 87a6dfb8487f16f6fef1d68bc31469ac210ea55387965bb4458ca0d00d6c46858be28a019ce914c39c2479f321f0252ca4a8bd681a5b358a093fc8341c31bc47c618403f93322b443084ce5818490b74e83c3866b8164bbcf79bf82539f428c9351c40b10d773cbe1cbaa8c9800a6dcf38d85515e2dff5d4f8a965ecaef37e38
+X = 22bbb8468f3e90768d347cb3492f64db2a23f721
+Y = 75ef5d5f67022426f531e9b8ca9115921d5a5c446bcdf1af701b605bae687dff8d1e7b3c4f8b289537eb09a7461d6688a3711974371a5b73a2082e991410118666ccd94f444977d0c89ba36162de023aa519037a6ba6305417dad3f2dc38756a40046491e8ee80c4f147825b8c021b5d09a2422d39d7c4abc395f6c2d7903c66
+K = 9c609e56c19f74ddc46eb2e2cfe26b1519ff0d1b
+R = 5409cd62f5539306ae8c936082eef932c6505c39
+S = 07c0ccb30ec90b1481409cbfa2f5de6cfaf1efc5
+
+Msg = a332b38e642bcad8bd271f776fff24a731724a43400c1614f5e21296db04f725eebad28d62e20ca3f7f18328a76b8092d97b632bb78718f0f2f9ecc7c12cc36b505959917b5c54312ad4717be84fa840b9f06de005c792af3e9ea72b7ae2e3423d07c781c9c2553f899554a0d8dec9a285c1ee25160fa278489474a0e4379516
+X = bbb1854e9b0942cb5d1eb71e8cc6fc7e0f4cfcb5
+Y = 41cc1d6d9e0cf5f158dab599114f3ee4738f197cf2c956b6bb0ddd6dfdcf5e4db399aacc16c538948c4b50de85bad6d916dbc415bad2f6737023fc7063c133bd0c4231d6b33ce813c0d6024d1315269571b2554bbb2edf2a99108a4359e8e23bf8a143bfc538ab9f8842cd4e925968f49ac56a02e3f067e26001e5207bcb56d4
+K = 336e458fc213c0b2775537ae61decc034ccb1d32
+R = a16a7308a6824d929b6a9a3bdb280d151a6eed81
+S = 7a42addab7ddb98000286044d9993d5cf818f2b1
+
+Msg = 79b144d50e0047596cf06bfcb3e9ce3959ec4b8cc9ba01434fc3f68f47c868cea048b990e62cd7a50eee288b35ae62aa797924c9dcab76409b869b33de28885e62f17db7a7758973482968b9f960eb2dba84ae85101aa6c6141b3f0839a4185a4c496eae876ecdc45627330d36f01a67cbb7faef834357330aac36c7c6f47ac9
+X = 754b24ea5c8cb8e88e370074e79cb62605530018
+Y = 74db7460c51919a9e87b430d105d86362ee4acd9682bf6c9fe87d9956c2f5ff17d95930ccc12f7e92d8bcb6af5f7ef1848da8d15c9152082477de99594781b998daafbf8ae4af23772125c19e166421f806bd0fbeac365076ecd9e15432ad4ac2523418f6e410cbfcbc5a71a0edf22e694a67d14b9cfc9722bc4bd8c43e22a91
+K = 1b50341e94f4498b92cce4d17ab9d4016fb2e074
+R = 021a3de98c3da698b477b4c3d50b2169e65f5e91
+S = afd764318dd0fee04fd6b07f550320789cd9bfa5
+
+[mod = L=1024, N=160, SHA-256]
+
+P = cba13e533637c37c0e80d9fcd052c1e41a88ac325c4ebe13b7170088d54eef4881f3d35eae47c210385a8485d2423a64da3ffda63a26f92cf5a304f39260384a9b7759d8ac1adc81d3f8bfc5e6cb10efb4e0f75867f4e848d1a338586dd0648feeb163647ffe7176174370540ee8a8f588da8cc143d939f70b114a7f981b8483
+Q = 95031b8aa71f29d525b773ef8b7c6701ad8a5d99
+G = 45bcaa443d4cd1602d27aaf84126edc73bd773de6ece15e97e7fef46f13072b7adcaf7b0053cf4706944df8c4568f26c997ee7753000fbe477a37766a4e970ff40008eb900b9de4b5f9ae06e06db6106e78711f3a67feca74dd5bddcdf675ae4014ee9489a42917fbee3bb9f2a24df67512c1c35c97bfbf2308eaacd28368c5c
+
+Msg = 812172f09cbae62517804885754125fc6066e9a902f9db2041eeddd7e8da67e4a2e65d0029c45ecacea6002f9540eb1004c883a8f900fd84a98b5c449ac49c56f3a91d8bed3f08f427935fbe437ce46f75cd666a0707265c61a096698dc2f36b28c65ec7b6e475c8b67ddfb444b2ee6a984e9d6d15233e25e44bd8d7924d129d
+X = 2eac4f4196fedb3e651b3b00040184cfd6da2ab4
+Y = 4cd6178637d0f0de1488515c3b12e203a3c0ca652f2fe30d088dc7278a87affa634a727a721932d671994a958a0f89223c286c3a9b10a96560542e2626b72e0cd28e5133fb57dc238b7fab2de2a49863ecf998751861ae668bf7cad136e6933f57dfdba544e3147ce0e7370fa6e8ff1de690c51b4aeedf0485183889205591e8
+K = 85976c5610a74959531040a5512b347eac587e48
+R = 76683a085d6742eadf95a61af75f881276cfd26a
+S = 3b9da7f9926eaaad0bebd4845c67fcdb64d12453
+
+Msg = c1b1f1472f08df38a52a55ba55827ba3b7cdd6beded904fcd52610c899eda3c61682656873bbfaab0d907495dacf458ea3450afd93be967a37434d412b6325669ad84b4eaa278a24870ecc2df0da13ad526a9e6669958d4e52dbfba2803ae9ae135d0c0acca86a04c42ba9cafb09b7af96347188880b086169ebdf9f1f5f3173
+X = 1a220585a989ef2c12bbfa9fc0d258713556fe38
+Y = 99187498534f313dc7cd7f3a48d62b2335bcdc36f0dc98dbf845dc6085c267474c36fdfca38854219830e614bbcab2bb9decb81e86124bd78f86d471bd84be06ac1f0f41fe5b4b3740b2107e0c9c48f81e31e9bf550d96564dd380ca47a11d72f0d0a3275f075f95bbd59869c14dc912a1cbcf01db9fb7f71015cc149986825e
+K = 8fef50b7121a04a24755b6f3e1cdc93848a9081c
+R = 54ed4efaecdfc78d026471b65cfefc6529945bbf
+S = 6d6dac296ebde3f873b751c6b14843f0b7befdff
+
+Msg = b80a47071d1376fe617e59fdc005a890369a4ca5e678ff46eb9b205d6ec09cbd49373bb341fe7813ee442a6ece17e720bf71a74557ac9a375c059e5535e773a45e79e1bff3465a3886c86e2a2bc882f0beceefffb2ae1a522f13c82def4cfd0cfca6fceeb4cece71869e90cd10d0aff27a84b5601daae061cbeb3aa62b37fd3a
+X = 4247e7e4dc4270fc7680bc05746807c183e0dd98
+Y = 91f50270a754055e5da611c720a4262f3cb8bd4161f77d07401604d3d1165e45518f7e1901adef6628f23dc48271d35ff492af8d62aa538c0e77e042f23a522f2214e62114bfeea46ae8888bdadacdaa0a9a5b503d79c23e4c20c98bd4ebb36f95bf4451ccb0b5bb44dfd011341cfa29a9e156a3cd828e126e68cb911e8f9dc0
+K = 3aeb3383a3c0f53217c0d7077c3cd66d2ef74a2e
+R = 1fc2d1cb80bf6e0e78b25fac293b752cbff2b5ac
+S = 75bcc772f773d5fd98dde1f907e7ec2cba201dfb
+
+Msg = a9603054465887df15db07c0709a8c878d2f1abdcfc6195eabf3e9b3ad07e8558b99cc4a7aa076daf67e9b7d8480f11e8afb18e2ac56a9547b48453fedca32da9eb0c29271eb60f0a1d95c18f42d992394b3264ff3e21e606e0beac08a7ba71b8e5795a8da985118e432cf5b30b6cd3a603d8b0d580f06c626ee937c6cd05f40
+X = 4d2a5462ebccc5d19bc6c1cabb609c08ad088e08
+Y = a2c4569a301473ae4f164d68b9a3c6eb705ae81f75d6e5cc3070a559cccb8b1a2d8c21090ed70e61670c7e9dbf5f755a37d58d3abb34c2dfd40db9f26f6868d0dd91be98f395ac0ebdc37e1b5423802bea7a6cb196d7e0f93db92f663b6c9c726e80feb2e9227154ce1c15f8e8df93ec0d37fa47e5fa112bb0a48f4a239d6052
+K = 36a3cd0101358a4d30c5b7117bc239fb4f6ce2e7
+R = 48539523815bd8d73ce702367c7712b9b13867f2
+S = 20ff4cfef8a668829feae73b520e8aa4d02c8168
+
+Msg = 19eb088c3229a44f9586f00421cfe7423a486d5f7e28ad2c9119dd2e1395df1acc06cb28e9069cee62f09f48e4ca29269dd89df9fec1ffdf64b1fe2717fe52b1421fcf6c705c0cf39930f90ecb339b51ef95b2ef38a6d96a575f7b36f5edf4f2cbd6d261e1fdd77d4459288c02e68c82a3910ff8ca1747c86bb187d5205f51a8
+X = 0842ddd5a04161e4579797b5d8eda0002dd847ad
+Y = 49e606aad5d2e54e1bae2517915c660ba30ec4fd28d718613a7c84464b0f44bc6d546e5a9bc1dc60423b45dd01ec295564ec08f29d6887e69f689d6b3488f9da5d5a60f39cdd5a158d51a3d073b2225fea559e58bb222e29a87b5f0f5ab31dd7c0ceaad887070dac955d28973607a99e46ddd7737beab65199f250d7f03b6583
+K = 712eed73c8d2567809b4d9ec2f59e77d39290b2b
+R = 6bf4f5d3251201059ee85edb99a67a706f37197d
+S = 3125c5af397759996b876cb5857be2632aaaf3b6
+
+Msg = addb5a045c9f4f4fb9eb5e5db44d6515980c9e088015b68593d8bcbffc6ff57f18865ab824d3d1586425cb5081197e9e01cb7297b06b64103cea437eeeec9c50798679fb869ec306a72575057fd368aeb0f674a29c3ac248b6a08f91331d8456d062025347c12a0a61c61f76e5206fe6ca437735af430dea7cc8f39f1a5b7505
+X = 1f1cfc682048375915fb483b77037c81c05ed728
+Y = 221ced57a91325b10f8dcd1220b1af68f8daf397f419a43bbd8fbe644311755b111aae5257c642fafd83b047a1f56f2a829fcdf4df3e5dccb23645b28c0a34c6e8a650efcdfadd48fea467cc943ca4e7378829300713838b6c710962ba72e790c10ab879a01fe1457ea3dd4b7c3c3a542e3522a75d0db261e576cd3f22c998e4
+K = 703154f6c6e12f163ecad0494897dfcf5657fbe2
+R = 7cc662e352e0eede85140107a7773ad8663e70bd
+S = 15c17b9d245872844eaac3d46bb08c3e08597423
+
+Msg = 02709d2be0d9dc1dc0ebc55f630d91fa23609f61b513c2275766034d8f40e819aaf9326c8db37c35c5a17e96bc956df6d11b558d16d91871afc010b3119c5798c2e29411ff4f0d7196e7e476bf0ad03bf72e897fed873c10613dd255d15243870b81cd87d0abc16e140d032fe5bd1c8eeb2f66e04d13d49269fc7da6b65a7c1c
+X = 1d9cf98dc0c1d7bf8dec98962ac6ef6e9406ce76
+Y = 9e93bc03e6e815308734e3b8f1d106961bebdff10a525303257a053dea4da6dcf504c7839b54d57522f2acb3aac959ff4ae8610022ca5a1e688232336ca1ee8fd7028bf7b6e9eedf8a4b0d098969f5e5fd3d9300c340e7f19fd471a451afb92ed4829fa4d90249144aa363dc18807b3e29d27e6ec3da736c33b185511bb3aaa0
+K = 68ae16534c5f6225fc7ef980f0063de483a76903
+R = 72b0bcc6defa66fa8bab029676a1c7703f9608f2
+S = 69d911e05acd7be52f2834c0aa005128e7fa85b8
+
+Msg = cc061edb31c34d3981517f4d89afbe980f74185260cf48b3043bc13a144944ad43e0e576d2a58bf589cc021dc1c1d332c4d76896ea77dda197f683e51eed71b4d6df46666a1b142e679b0283cf339e5bca90e2ff9c34dd5fd7cc4917d66704fee4364f7693101dc766707104efb2b933c4848b93e13f94855f75e4fd756cb6e3
+X = 78ffb40fd89416388804e56444c9a642cb5e98e8
+Y = 5d7d2e342154983ebc2015bc6750f9876f5689ca0ada8529908ed4fdbc596b972c5cc6d53e80a8ad8a8cedf3ce64b62a75db441c96207fc7477e3f7b9f10df28e0cc2fb77383e7ca4c5150f712dd823c2309f0161be0bd5eedd60cf6ba230861a08b9d9a7468438b4d6ec673d28a54d83c7010d50631e55f0a02832abc5a0a46
+K = 07c6857486160ef4003470411573399fc4e5f7af
+R = 21f512425670943477534e9075ceb5b7d63f20df
+S = 73c6f6f8de3aaea520a083b2264299e81cfc91c5
+
+Msg = 79d529e40c2ba4e5b9c7d77d72076f1fd9490928ff4419c824e64db8fb9a051e01e8e173c6f214e0e9e645ed250b6daaa6f8c1a5cc900d52cf3e1efbfea25748e89a1a548c73e2d110b25f5308bcf757b2135216c91dca2783332c0d7903eb21c226dbd33a69eef575aa8a41cbbdcd1b3d94928aa8f8ba58c5ce0d317786e87b
+X = 784b9db2d19ef0ca8e696884c7711dc2f8ce150a
+Y = 282decc0e37994c2856e61f36b831b61bdc02b7ca675dbc3c2032800b7efd3b711acf14c8869968831e145361bf2182b060e4838f07dc61f76584cf102a913bb28a52c7317af5f9d2322927c9666e5e87c2f2bfd2f181dd32612d7b2b2a645bf1a47c0ebfd79a940f627a668a8f2eb729fd051aa2c659abc918e5571994e6593
+K = 1bfcf3290fa84652a476655506b145743213e1b4
+R = 929a4851be0ae4ba91da0e6c7376d71df7592dbb
+S = 7e6b6504b748ef0024d9d2a2e6f3bcd7cf135ac7
+
+Msg = f5516410706323549b20c52dafa2f2f90799786c0ddb85048892ccc18720dce5c129a10eb4388788a3d97a03b0001799cb65a79c880836bc9f3204ea75a577204dc1e2894c572a258f9e517ca37c5b791e48b27c8dc1c821b34ebb1f29858c4a72a0d5172c565e9dbe1bdddf6e024891cd6291faa81ed565746c61c2eda2011f
+X = 673a384687ef29ebfa66e331866bd206ca2f7664
+Y = 74ccc6eb83adbcbad0fc37144d9bfb85fdcc85ab92c9f8877c9cda66251d1aff2fb224888dddb7d772a8b738c53e03ecad9903796fa3c9c6024d06367e0870ad797694f598708d08912c0fe09881763a0a722dda95d94eee8824927cbfa6761a79a038aa6d331da34d9bd5c5833c94c526a86af1cdfb2d4079d2db6d0b9a1238
+K = 52ee4510675f0da529684fa60f6848ce63c4689f
+R = 27b3f235e4afc18c6613b4fa7f27d7a8262ba4c0
+S = 8b22634e4d45b71a84eabaa1e5a4bf1e37337a59
+
+Msg = 55bd1526e08f6443b255acd32c286807542d34c0f3d79892713f9d6d6d6b3be707e4af6e71f7dab4a2c5f6bd25f5ae1f514b2644a4cdafcece1e58f7576f82e2ab0af2326c71279e9bcef1e1c54a76fa77ec2b2d056717645764e7991b520b0e5a1b049109519b22aa5204e3ed53b1e0957dab5ec32479d06ac3e11a5d1cbd03
+X = 495009f3a92548be4c9a562ff703187b0ec2cc86
+Y = 5d6edf6db6e6c27e80a7f02597237919170b4936489d6f15f598b820cd917e172509b7e287b88b0cc14e1a0186793886809ab4170209987095092234b4fdc44b3d1fc16eeb2efaf852ed3916698cf9eca4612b4961bb6e20c32e188469883f97f49e29a8197c30d0723babb06dea704f7704b2788e57d76d6d9a3cfa68f6c783
+K = 423308bb414ef959025bf1a4b27db278f904241d
+R = 621a290930ac436737a72fb4c62bf5c4b67481af
+S = 62db20f82a5754f109f7a2ce581d4c8d71c68d29
+
+Msg = 62789a89f0d708e21a121fc34009af884133681b9d4a66cc36c0365c34be72a4982eb0961ce257f35e6e7183f0204a96a545193001023d3309a8997e7c4b762ab4f4c40e03e13f4edb328b23cf00c09119deb40addf6567b3b74acef5ceff045304d618421e873c41a72d31e451d213b060829b286f64013d4d9342ae7ab8064
+X = 2b8dd3965992fcffd158a0816a5987f80908b84c
+Y = ad590590a82e8929ca86f405516c32913bf5282f70309c6d4a88ccf165ce15fcf11e140c366bb273839a711cb6ae52bb717859570fdbf9fc26726728596e6fc71923deadb35a9d57cdb213c0f29c1375f8b1d3c6b52690c428f7481c14aad82fba7f24eea8cd8da7f0ef7ae781c1a926671a61d4e5ffc8ddf1bc10d688a904c6
+K = 58ccff88958d5fc48d671ba22ed71f5f82370ac6
+R = 89dcbca7c8cd6b90aa906a4c547153762fcfffd6
+S = 23e8926b18cfd4b67c53fac4a2d5321e5c3d880c
+
+Msg = 4eafcc6874ae2a6d525738967afb3054357a39670d1e5555d7dc55be24dd5a32a0c7ca3f1b5c6d948c9ce391013abeb47f7e24cd2c54e1fc7c0e92c4ab77f5973a7054bd1c6c845b802b7937d6520508ae018ae14b27ff4b1e340a4b9f6f6b4814d07e90cb8f19b15e915d6ad1834c0f7a3c3e1e45206772a0eec2d3f9160897
+X = 6b3acee42276bba155156f23dfb7cdf64e4b1ae8
+Y = b93d79472f049893779a3a0e83b3853f78b3cf69b75961a60e950f0c00f498f3eaa2384325f74ddd38292fbdbdb199212e90b14ec9e554727df81e06eb7783adda38691c63a7cb00cd76d8e18e3d29c793e9f1fe8337f1598b89651f634cb703f218e1906319f82ac6d58e6786da7aecfbca5939f03a13e7b4d5a8ac812d7829
+K = 1c48f62bd097d7686879d33ee5771558e453bb3d
+R = 633e9812a0657cec3326aa5415340c46362fcd4b
+S = 6b201f0c3fd44247f6c28c01d1217eb99146c040
+
+Msg = 86d9892b48f5954101482742c0dafb68dc97122483b9e459f97495cc970e056d2162c7c71db167229fb7f45209e0c01eb06ff924b823eda51a7e990f3c986eb9af2a7a073f754cb84db453a9e8c0ae7fa5c05a2655d261ad7ec5612876fa7df09522e0b69ae92477f63def1992c96ce95ee7bd630ec1614621da6a512ab53dd7
+X = 836d90fd90d21b84bb012da7b2168ea8f05202cf
+Y = ae264ea96bf093ef2de27381738219e3bfdb08616967cd13e9415f475c4a794c19f12a607b898db1e3e6bc5402327585d32841ae15e3462880850e9e4136a4751b64a729ea27b72ce36128a44fa53752a08d73584faa44fb14120f47a04c47e989eadabc7e5cdb15d27c2b0ea4257cec229a2c7bf7c93c571e8d22aeaa2e38be
+K = 7956ea15111ff392d6a9359067bfd8c21f0bfc0b
+R = 77b480885c70c1fee2056237d1b79cfd9fb54a1f
+S = 2283f4c0640ff6daacbdfbbef7224afa59ca3959
+
+Msg = 8b60b9b6ba375448de4f00de51d18706ef8c4f97ba34c9cce2b0abb0698436009d1d2bafcbef73a8b5dff6a3cd5db5258ac84ef724b28d8a62d715da6e111939735366a7c66470364557f546377d5c0e7ea9064731cb7149e1051d66a7bed14aa205bdc5d4b9ca029a1e68a6fa2c1db22d27fb79d83877cfaa6742119229a493
+X = 5a4ae9f8fc82c9198d9400c51f282493b194a07b
+Y = 87032f263de2bf2f268a093f33c366d6bcda772ca959fa17cfe948f1dca3e75ec94276de91d9bc60fc6ab9224861c55dc9ccc5f715c251dd508bd438681cab205059050f8e11e8a5468da42d20aefac53d7a9fb71f6424d7bdc65db873ee4f9dcd918091aa724b261b6056f320ca7724518e14cb8dba0b713f54a0fe44ff1597
+K = 662351e9b8c3a607afdf3ee599b46681e27b83c0
+R = 5d159f894d250db90d7fccd49329e44d1112db47
+S = 37231bc15195ecb6badb7c3fe80380ff912baeda
+
+[mod = L=1024, N=160, SHA-384]
+
+P = f24a4afc72c7e373a3c30962332fe5405c45930963909418c30792aaf135ddea561e94f24726716b75a18828982e4ce44c1fddcb746487b6b77a9a5a17f868ab50cd621b5bc9da470880b287d7398190a42a5ee22ed8d1ff147e2019810c8298ed68e1ca69d41d555f249e649fb1725ddb075c17b37beff467fdd1609243373f
+Q = da065a078ddb56ee5d2ad06cafab20820d2c4755
+G = 47b5591b79043e4e03ca78a0e277c9a21e2a6b543bf4f044104cd9ac93eff8e101bb6031efc8c596d5d2f92e3a3d0f1f74702dd54f77d3cd46c04dee7a5de9f00ad317691fddcefe4a220a2651acae7fcedda92bfcca855db6705e8d864f8192bf6bf860c00f08ad6493ecc1872e0028d5c86d44505db57422515c3825a6f78a
+
+Msg = b0dbbf4a421ba5c5b0e52f09629801c113258c252f29898c3354706e39ec5824be523d0e2f8cfe022cd61165301274d5d621a59755f50404d8b802371ce616defa962e3636ae934ec34e4bcf77a16c7eff8cf4cc08a0f4849d6ad4307e9f8df83f24ad16ab46d1a61d2d7d4e21681eb2ae281a1a5f9bca8573a3f5281d308a5a
+X = 649820168eb594f59cd9b28b9aefe8cc106a6c4f
+Y = 43a27b740f422cb2dc3eaa232315883a2f6a22927f997d024f5a638b507b17d3b1cbd3ec691cc674470960a0146efdecb95bb5fe249749e3c806cd5cc3e7f7bab845dadbe1f50b3366fb827a942ce6246dda7bd2c13e1b4a926c0c82c884639552d9d46036f9a4bc2a9e51c2d76e3074d1f53a63224c4279e0fa460474d4ffde
+K = 33c7ba88ff69707971b25ac344ae4a566e195f99
+R = 77c4d99f62b3ad7dd1fe6498db45a5da73ce7bde
+S = 23871a002ae503fdabaa6a84dcc8f38769737f01
+
+Msg = ec84bed09ecb4a6feeec3a7071b65a4c1267a03cac8b5a0500c237b20dc058514da798335a21b23d7e8cbb15efcf92e6060a13fb77f4998147dec1d0fa0edd418b0aae8eb0056fc7d4008b198bd40b969dc10d79e15b2300820323bd5e1b7d894ce8e7bc8f7ceca129b5e511ee1c8caec25514f537353a912a971b8070e3f141
+X = 952b61ea90df3f788eab61d95be16ca28001800c
+Y = d7a0950d0e6362b0c942ad8af67161df07debca59a4cfa728f93d49b6e296a23969a65a92b2e05398a114d73d5a52b73b71ebb28571cf6b6002f853a8f594b5c93b9a84233f3c552823619e0aa847d60203db15d2a916ad02228325e15783988f4159e05c8ca088360e6ea7ace51b055102153c00adf335ff6affd1754f2a8aa
+K = 7982f6b8956c2bc0a2c2d02ecdb9e47d23a7ba81
+R = b2570e0e19935438d32686c478473a0e45dad023
+S = 39a02e9803624f7e90feab8714cddc41e01f8fce
+
+Msg = 80f757fc06409b70d733efdb68b520f3f9078ab936c4479fb98d0beb1631d8303324470824862224b439bc85decfccb8de8fbf36a2bc4ce3a092688249ab4eb9febfad268245fbd7e72e0f240500af71292ea23c8ad4b71e032106f587f4611663137690cb25241912763c5e1879b3ab67e2187f92d821fc81f552e2c355bd73
+X = 2a5f637f4b886a3d37c4369cab04d78c79f1a3a8
+Y = 1f03013e66fd1e633ff743894c37f6964839a52cfbb6e849cfb4eac9a3c9cdb55c28e14788865c212be62047cb39c6365780bb2e627957d34e99232f69170a8efb894d8029d1b8bea8b911cebcd43b86bd536693f18bfe50c84b99911181ace14c3fab9fb6acd98786f9d2ad129c5efeb8cd0941a3d89098d5721d435343cb76
+K = b7c75c380bce0fffd59dfc3993e1d0724da877b6
+R = c7db4a9f54d882ec5f561705396c94834dd53c5a
+S = 6752cb6be9b87265d76d69b382299678f96a5faf
+
+Msg = 36a25659a7f1de66b4721b48855cdebe98fe6113241b7beddc2691493ed0add0b6a9fbbf9fb870a1bc68a901b932f47ded532f93493b1c081408165807b38efce7acc7dbc216bef74ed59e20973326553cc83779f742e3f469a7278eeb1537dd71cd8f15114d84693c2e6bbf62814a08e82ba71539f4cb4bf08c869d7db9dea9
+X = bb318987a043158b97fdbbc2707471a38316ce58
+Y = c9003995b014afad66de25fc0a2210b1f1b22d275da51a27faacda042fd7645686ec8b1b62d58d8af2e1063ab8e146d11e3a07710bc4521228f35f5173443bbfd089f642cd16641c57199c9ab6e0d9b0c01931c2d162f5e20dbe7365c93adc62fd5a461bea5956d7c11ac67647bedcead5bb311224a496aa155992aee74e45ad
+K = 2ff654b680e722ce65a560e785e8ce0b4773c86d
+R = 17cc53b5b9558cc41df946055b8d7e1971be86d7
+S = 003c21503971c03b5ef4edc804d2f7d33f9ea9cc
+
+Msg = 65a3c92453f961de7f576d5a1e3106c38b7f20813994b5dd201546dc455065dde59edcd84d0fa17a85c0f9f99171d67a34475cef4f311951f2eef7f6b64a5bbc6da6d1b622480cde56a07a77aa6040ebc1fcb265b3b624881fd27203dcfe8a12492198474a990cb9f34a1943356fde5bce3fd83516da8bf780f8cb1851b3b954
+X = 59d92aba23f50ad08b1d7c2ad560ded36b94ebc8
+Y = 0fc514ca160f34f2f6ede1ba5914d5844c9de514208c72569a0b36ec92c8b2c8fdfb7d68127486e58a04a32d0d150e51bb05e66624cb622edae19a6b4b1d8317689baafa30168ef3759ee82e614e4761900182df90e9cd2d931153771b8be30d89c2fbb95be7e05a4b29da968ffebbda5c0c9839354bb59dc697a269063f2f50
+K = 3d0ea569b4dc69342955f5b240af66d228791e50
+R = 77ffaf4290c41eb089c1d7be5c8d3833027702ef
+S = cb753a2d4ce0e59851f814779f343beb615f2770
+
+Msg = 1526b64ce41cc8e2cef26f3706be530a36ac9cd16ff69f05773e9447ed9452064b7751f3a64919bfa3a7e1020dfc175a10acfdf096fd41c03372e4d2abd7ba887e0076716ce9552f2c7c8eddb1b3fca1bdcd23300ce2b1677d4a2debeaa7053466e59b098771bfb9218e0fb4ab6b7418abebcc34d681e14c4a8975000d83bb44
+X = 716290d0ff2ad2329be2cccf825f2075be659743
+Y = d30eed739f46479364d4c2bec18cf4c75c324f8db8184d9c3c175556a00acfb0a6813887b68706e70c167f4063bc0046396ba1bb3226c29221bd64ec4cebc990a7b404e26e2cf042304a7c57ab7de418ba671e17f7f502b9e1bb5984469b304ebc0c3c3a5a69cff7abff4110130316651e0f93ebd2834dd044eae1fd6f045102
+K = 919d698fe37c027e3e40cdf6e77f81e96d8bfffb
+R = 31abe8e7458ce363a5f3985111b239bc8df8dcb9
+S = 1d967be0116128699d167fc16e5e920a41311669
+
+Msg = d7852ee90b3f1120bb11249808c7e7be14fe577bff1886be3c42589a6eeb06a1834110862b65d26cc5a2e5d903ed24328d684c96e3babb37ae31f96d32f57657a3bd7798aafae86f44ad8981e7cd47d7f31bb4564a757c925c64da9820963c1c5148f589d6393004a6a58aa2c8a578f4db7595f886170e79e9d57bf7ff8fd0a7
+X = 0531cb42f45bb813f401bd239044df2d3d1968b2
+Y = 0dd37985163f93618fdea8e3975419fcf7446ff980851e18932d7494f809c0ae9c03cc39779ff0422cb2248ae1986f9aad2a43d6fa6878d244b429aac5ea80157980577e5ba0d11b1fa340a283fa0a2d651e024331e6bbe7d01ac034db37b008b91f9f88d135fad23af8c22765d833a9c9eff7accf668e17f9a8bdf59317c202
+K = 739dbd1f84b6be2efdb921a0dfb76dbc6136915c
+R = 44c2d6509874ace71acd1dcc32335b394c4e41e0
+S = 37e78f13aec052eb7b07a8b9f6d54dbc77829006
+
+Msg = 9ab91448a0dc9694be173ce6d9b522ce0e2f75fcb57720fc5eb8f92d8fb0e195030063968925a568636f4aea1edf6c5fcb86dcedd204539d8c291757fb8a51620abda59aa8f8502e6904bce0667d92c8cb3fcf1a61b1fb0bb4e9383b37eb469bd5c2f5a77680da62f907c2e263cb48402b4b12985eaab90451885e819b3e8c3a
+X = 6d764cf62a268b0070bf80308622bb31941d4763
+Y = 49d7f08fde0a83cfb8116c9b7cdcab29751fca5ffe310760fea713c30e95e7755e65ce60928893c65020ee9b61f6c9c89c07e0fc503b7b031368f069578a9e6b451fef369ef90c26dd660ee1a6b8b714d1cc28245e9f13f187122de26ac2fbf5bccb7caff59f1de910551104d3a0e8fa9fe6b7eacc9a5fd556b7bf7139d6edf9
+K = c66ea7177cd6edf6b9079fbcf6737d3890469b19
+R = 95da25d06ff9c02bc893fb032508304c17ebcf08
+S = 617adb8de10da1a87413d64466b482409d27bce7
+
+Msg = c9c0e69f840cb6deb984c2575d7f6816fa35af03b4429c703a5aec90e7cb26e52413587f3bc5a0772be7b5e589c9a76071c1739833f4611fa951d375820b48d740626c665534d60487bf3e0a84eb6389e099fe621f269491c3b8942e03bbad2a5220caf51e7b4a2650e4b300024a0a96f0861b3206fffca83d0850f2a3e2a06c
+X = 38a62d234e1aea0e847621e79dd17ee9d08bd9c6
+Y = 26f73219d0e7dd3a80e7fbc079d9baad4512891aadfd2416b1859f41adac31171ec624d8a4d6a10d5de1b93959bc49953f23492f18ab765f963a98584807d66629e5a1e057d77d42e3363458641a0469166a0d853b27798bd848aa0d3ccdbb40fa21b9fe62824cb2c7cc62425978e672aff0bbd8c8cd08e46385b0d6219dc56e
+K = 5f5755dce464174adfe00affb55a71222d83da85
+R = b6b25a9da110b5d57675889eae75ab58a4d8e281
+S = 5a60c2b0adbea4c5be065bbd0fd0e3ce4bf29200
+
+Msg = 4002de825bb87ac346bd8487cf6be053cb30ee67c66434217107a8b0b52e5726900615edd2fd0acdf88a7e65e7dd3ba6abbbb371a1c840250d9ce809e7b1111f16daf5194211715ff5fe631e378408749848a0c81a289b4338bccd8d1053f863197ad02920fcbca514e2dfd94a8b00f90cf034adfd776f4dcaef2c8dce3b0539
+X = c8f0d697bbcbcc0e31864f8319984125f52ff5aa
+Y = 149bcbb4f5983db56fbe998fcd02d736e6d2f18fcf96468cd7e99bc647436fbd74fd7a2cc2f0d8866952b97b44ff644b5665cd1065b07a2c33d9151deb335e3522c1b77da1443a1373c93bfa040da5a1353b88a78e3a5a084e6c442db03f7fbb4bdbd30b1af3963f8c5d3e83453294e3a07ddacfd43dc8f9e83032fef78420c4
+K = b4281920a775fbeefb89615b236217fd1046f2cf
+R = d3cde170d82154ec1bbd9077c486971120600376
+S = b008fcd01b5e49a85a921bee1ddd706212799086
+
+Msg = f7018ff0af6776ed4234c1fb9cca1f8cff31295cb9f76d8b73898430097c49a40028441771ea1de08ffd5cec7eaa59e32b3a170329139227ba86e0c5efcaee382bfff962249da853dee418413f201a28fe45b8293c262089d2ceeb9af67529ab011f04f5eeaf82ba32dce9a9821762c3351b00206591a3f87c5260a4263659f0
+X = 9dbd262da7a529f80aa667b27a29d6a52671fb89
+Y = 6c206e71fed8b363fcf571786ce1b4e52a404de7eda7031e5d93a47ea668de43dc7073e31d3b6b125ae3e8ee45aed273bc878c73423b225a1526bbb149a0ce5e9a2d2962bd6d332375860f84ce0e787a0af93f44e64edaa2dce6ca22bcc6d48b84b0affba342753b1842941067d5b8414c356138e625bb506566a27b335094b0
+K = 0f0e02596ce6674684e7ec448d2938de12842fe2
+R = 079b08bc016c543d09d6b276c023347a3aace9ae
+S = 164c3c380f209feaf8ffcf53691ee3031c3b3fff
+
+Msg = 4a18bdcccd46bb89567ceb9c1e2e500a3baed24ff2c5fc7f83cb3cf6a6f38859a1a927fab5e2fd7ea1e1a4154739301cb1957709103af886c929cf88d25ced5cd6f8cf3ffee7b088edc2f6abd1114398a3ab00fc21bec02e8e539ba12df70a587fbfba63195c6449b2b849547c42277834e1ec086b5e53d949846769e89715bf
+X = 5b3e9cc0e0be3d714d1bb2d95e5146d27a58f2ee
+Y = 8e668dd1527b5d1e56aae4a6ca225e677368412324a79d98bfdad9a84d9f87c1357518c9a5056ea6a0882e94d4ffadd97d89bcf2f32ff442b25dd2af2a78ddade46b75aa8a5b1a1471764ab699d700cb2a28b959a3848edbbd6c9514ee849f833c43008531365a01541f9c0b65d5e7d3c21dc8bef1369a41c0405f3723f67910
+K = 3d9b8166860e18a9306026ba669a3620c2954ad4
+R = b22c00fe0bc2fae7a4ab74edcd496c64a999c7d3
+S = 85ba8dbbc93ab94a76133d479e3f79576944e6ca
+
+Msg = 75474711821766b065e2448601e82b88153a41bfb5c6b6a9ddcf73170ee374a6625de19c560bcbd2020bfeab5cbfad8fc60ccfc95a1b94fbefdf815d9bfc43fa59315e7093d5685274b8afc3139b925ebf697fe2699b0feb1e42bca65e5d4eb0b4514af92dfab85e7f2666c87e9789395f354ce33938e9623061113465a4e2b9
+X = 9b4a2536a108892240fc40c8c69a4b9b903ac760
+Y = 74a93c73d75500ca4305ca3184475b53d96c6fdd417ef23d9dc61b80bbc1108228d2543c1c3a9f2e7783ca69b019c0cd9a6d2b62b0ed93d4229da87bfc21f9e4bd0dea2c4e6d4d2f88201ab0504b31f4ef1558adf493e470adfc572ca68debc46123589ae913b967983dbcac6bf3bd8611137e39d5870057ae18cb84a76aae30
+K = a993b059a49855e359014151700d02e8292ae708
+R = 1ed131c96a2c310e1f7976d3082a69a5af45bdd0
+S = 70663e9ad7113ae57d4af6907712e0aaf88bc07a
+
+Msg = 340df708d457df9413ef2bda225c5f558b90966cdd531a0b5aa745d5c3ea790debea224861ef12fb1638bff0121ff26dbdcffc299bf9f3a9c1fe6027400ff14c34fb06f67db9c30a1dcbfd996903523d85046382ff280418d974a3ece6b5fafe305e2e79b1d07a7c1eeb7a1277a82282be62831df7fee38841462602986a8e9b
+X = 067e6e55be4744723b6f056b76629e93c297a585
+Y = 6150a68d64adda3d3fb5a973c62b992ad3fe538af7161bae41ea2f1799304fe5b8c864e061d133d94c16a4c6b0ed8dffdf2cefa7394015e75c57b181419dcfefe3409d3b53d86911c749f9f28f7c1de99f7e4b2ea22a48817ace4fd9974fa53b8d4f05f5731488813803d7f3aaf1cfa138bc73c4d27ca1621e9226661883e9dd
+K = 77857e6de8f37eeb6925a87c027a3cd88b9d3584
+R = 4f182ad42cb5671d3162bb9d04a06cd20edbc558
+S = a6c5417947447718ed1cb89a6efce2d3116e50d1
+
+Msg = 9f23c82563ab7c0ba86bbb989335000a493b291e5dc17ce729494958903623ed99df344230ffb626b1dbefcce059ae16c2ee7ee6fd2a7807336cb71b8853e2ed3b74b2faac82a831d53e03d7bbb96d38df98fd19bd4c1a6248cd507c89f7995f59579afe5319731b443d6871e558f5b77f2f9a4dd99efb305e27916594524e02
+X = b457e1756ee9056fda7207616cf7c04a33afa66a
+Y = 96d7451181fb253fbc3f441409be5e5e0144972610e37fa82bc2af246637a4c918023097875255a217ea895daddf46bfbb174749b04c59fefa6289684f2f9aeadf5ce7ca47f0032e384b7d50597901181501cb5915fb4686a6ad7bcd5b46862411a4df22b1ed2a56905e07c0a936c9944213194ebefd4ec68597cca036338b3c
+K = b29f28659dffea28449435b5a044487e29d82d6a
+R = b6599fbddb4856276df448cf09d62fd7657de6c3
+S = 4b49589099be5578322d829b87b43ac07f62e35d
+
+[mod = L=1024, N=160, SHA-512]
+
+P = 88d968e9602ecbda6d86f7c970a3ffbeb1da962f28c0afb9270ef05bc330ca98c3adf83c072feb05fb2e293b5065bbb0cbcc930c24d8d07869deaecd92a2604c0f5dd35c5b431fda6a222c52c3562bf7571c710209be8b3b858818788725fe8112b7d6bc82e0ff1cbbf5d6fe94690af2b510e41ad8207dc2c02fb9fa5cefaab5
+Q = a665689b9e5b9ce82fd1676006cf4cf67ecc56b7
+G = 267e282857417752113fba3fca7155b5ce89e7c8a33c1a29122e2b720965fc04245267ff87fc67a5730fe5b308013aa3266990fbb398185a87e055b443a868ce0ce13ae6aee330b9d25d3bbb362665c5881daf0c5aa75e9d4a82e8f04c91a9ad294822e33978ab0c13fadc45831f9d37da4efa0fc2c5eb01371fa85b7ddb1f82
+
+Msg = 3a84a5314e90fd33bb7cd6ca68720c69058da1da1b359046ae8922cac8afc5e025771635fb4735491521a728441b5cb087d60776ee0ecc2174a41985a82cf46d8f8d8b274a0cc439b00971077c745f8cf701cf56bf9914cc57209b555dc87ca8c13da063270c60fc2c988e692b75a7f2a669903b93d2e14e8efb6fb9f8694a78
+X = 07ce8862e64b7f6c7482046dbfc93907123e5214
+Y = 60f5341e48ca7a3bc5decee61211dd2727cd8e2fc7635f3aabea262366e458f5c51c311afda916cb0dcdc5d5a5729f573a532b594743199bcfa7454903e74b33ddfe65896306cec20ebd8427682fa501ee06bc4c5d1425cbe31828ba008b19c9da68136cf71840b205919e783a628a5a57cf91cf569b2854ffef7a096eda96c9
+K = 2f170907ac69726b14f22056dcb37b4df85f7424
+R = a53f1f8f20b8d3d4720f14a8bab5226b079d9953
+S = 11f53f6a4e56b51f60e20d4957ae89e162aea616
+
+Msg = 6f39973fd225167a7673cd71ab3534d2686687c332f93fd66db5f1ca99678efd2825a84cd7a7107adf96501dd1d05e7bbc8d113e087bba77b2346b4364132125245e9aace3a146b576f654c86e07fc1914cafa209dd6d04845575dbb279cd1b23296d01ef505b5e1ce7f2194f18988f355c9b34f920ab35152e03bcf792ac529
+X = 8d75294b56262e42a82db41a4039615396574dbf
+Y = 110e398e36c9d2726e77deb465dd23303f9e387778b549700a52b9a5468512ee377ce3d7dcbfc6b64ee353eac6a43898b26484058ba1b24b229cd69c994d976d43344c181ea6c47df0062c09a16b23ab6075c04a0899bac3e4f034a983bf90438f6ac26855d8a5fded90172e7e8c196a2ce7e1fc0dac94278aff1653c3ae09f5
+K = 66a1322607ab98aaa57c12a5cc3f59dce8d7d0cc
+R = 1b9ed39bcc4b46ed0007679ce9c3f6dc7c4157b9
+S = 258d4136ad95b704a7959d04096dcd781eb54bde
+
+Msg = 7f59744c790c0f985a9ae101d9fa00da3b95d2473d792805ec1d6d1e95222a6f30ee6ab8fc5a632057153f237ad3aa2fae8f1e51eae75906d07e576dd0021ac1711b1c8853e62d27fe6b098766b8ce3e76d347c8e49be0ab05d0d12fd777a85cffc7ad1207a9aa75643d7b415ba4b1b97dc0ee19d05a607ba063a0341f176104
+X = 25b7fedcba71eda85fe189bf0d0c43214ab6388a
+Y = 3ead9cf211f3859d5baa5155fb62331bca3fff9ecbe182ebf8b04db0ebb19eda548c86db4cbb5eca98ce449cfd51f1c460d7848326eee22fcac7247fb889ee415c4933a909c78ce9bc50ee190116da9ae2547ae6242a340ddbb9a15ac818c4677f2919c64509d03c49d1307bb2cd78e01ce5b25a9f47d828fc7584ebce366c2f
+K = 8fd754defb1274bb7ddea0fc13fdc76722442d86
+R = 38f52df78b0e454d3583208a0fce03b904eec816
+S = 5cdc57a943ab1f269ca11c63bcb1059ee76f9c2e
+
+Msg = 16250c74ccb40443625a37c4b7e2b3615255768241f254a506fa819efbb8698ade38fc75946b3af09055578f28a181827dda311bd4038fd47f6d86cceb1bbbef2df20bf595a0ad77afd39c84877434ade3812f05ec541e0403abadc778d116fd077c95c6ec0f47241f4db813f31986b7504c1cd9ddb496ac6ed22b45e7df72cc
+X = 3fee04cc08624f3a7f34c538d87692209dd74797
+Y = 6e8c85150c5c9ca6dcb04806671db1b672fc1087c995311d7087ad12ab18f2c14b612cea13bf79518d2b570b8b696b3e4efcd0fda522a253bbcb7dbb711d984c598fa201c21a8a9e2774bc15020920cd8c27c2875c779b08ef95093caac2c9cea37ec498c23dd24b684abcb467ec952a202cbd2df7960c1ef929cc2b611ca6c8
+K = 934552738360670c98b9c5384b639c46cdecfa83
+R = 00018f0fdc16d914971c8f310f1af7796c6f662a
+S = 62b7aecc75cbc6db00dd0c24339f7bdb5ae966a5
+
+Msg = a2ce90b51a480c0668b55936bbeebe3679f8d406a0b694b90345749e3b9c67776cae9a62c25cc011cdb3180263ddd73aa2090ec7a749092f6c7816c26744c5393acb08c6b7b359bb3a3c7543684f8050ecc6422234ff24978ae06b91d6a24c086d71eb1761caf14176d8bacdcad53b7895bdb0e053c616b147ff73d2d86ba3bc
+X = 2d667bebf445cd3ee45d5815e07ca5735b858ada
+Y = 0e6b419da8b4db802d938873e3b105ab3eff432d8a1376602059cf2e510f696a2a4e42025670db0011e9be31e8b1403615b9a339ce654a89a2d462ee20c080c4479648c5c00e172ecd537c934e7534af7002bd6fdafab56506680c019ced38779d954091645fedf5d0057a23ff634919fc56a96771ce21fa99ecd9aa7f7985f1
+K = 4aeb4911d38f1f634ddf5fe6c970d943ea51b266
+R = 5b13f1337ac72e419867c92f9387f9df62883aa5
+S = 90ab5b68fd8253b6bb64c61759164a97834c39e1
+
+Msg = 3b6eeaedc5fb38ce8691686c89993caf17c9e24fa565a9e8d48436b87db62fab839c42d81fb1f8b8968c826e78d333b1d99d5c36e08a9a0ec7554c2bde07fd8ec422af128246ba3beae18ef2be755db22a869202951cd95796fc2ff7ba2a6967d19e5ca2304655bfdf879b7747f80a59b1dac0461cf6e490378e56ab378584f2
+X = 71dbbac59768e1e3093f0c60404731a2ead482c3
+Y = 4a7ff667f7ab2891a8a69ab5d15d93d1fd833906c9b629fcb9b49e84d8ecb35b397d93839d7985590326cffb55a70e4a51a2829e387290f6fafb7d226151c282470224fd717f3d526589c6eed9611c5bdf4bde63fcc9204c8007b0b143c49d1981835658bcf800a2157c5c143d76369fd6e78d0a3f800b8a3a8f0e11c9059dcd
+K = 8f78910d1e8a9daad9523626ee7ab1d0a5b4d977
+R = 61380ca86798fc5fb61c35675af08d5cc13c25aa
+S = 54ddf68f476884af3e0e6536f3a80925ee63a402
+
+Msg = 01197ae960de90a93d9736896fe136bc561f0550c6b1cc3631b31df683017c2ab8c6f41d2745f1a797e0e89dc3d5878866c3694a080366757e6fd892d26668fd2d860ea2a2b67fdaca96e32297758787ecc0a7e1d304cc719803272e72e339b3f34c347e47b91a1ed69ca8062cd350dccc9c2264732b9fdd8462d9f6fc76850c
+X = 45963a0771456d6ae897edf7579091f5f8c76747
+Y = 373081770a9f4dae8df5dfa70503e149d759ca37408549aa34d1b49b3176a39d7c4661e421a1f5d61e3f77b3c4b39bb2e63cd24919a2910a8b155e1758f5a375da60f19d2bf4020e828f4237eb3e2a36124a6a3914469d6833695b83b9377fb285b27bd2689933c189c7fde42e1e0e20308331fd56ed0db2efbc77ea3ac7121f
+K = 1f68d020331b81fc1aea51907e94f7d62ace9135
+R = 41ed170c8bf6f20fd1ce18faac97565fdb4fe6f4
+S = 7c8c6feace68c97ca43780741fae58f2f61bf765
+
+Msg = 0d5ab27b2b7e18cfce4ccda13aa1a5a8c18baaf39b14e642b8f81b30cd5418a1dd05df22599fbbb3bae4fee1e4b2c150a23e216c133fe2d8235485e34f80685c66bc0c190af67a0a49930b476b2803e12274cd43090921bf668fdfef155072a3cdf17901427afa51318afdda937e283e2c60d85e3bfe07f3da5f992c1fca4b98
+X = 95bc588bb848751ba57d7a9ab340cb00e79e06d8
+Y = 1ca36e3505ee70a56afd5dc40a48e97979e984dd2d896abc7a491d3461c6931668a0cef11e45bb66c611137999907ad7e1f7cfea7f7ed49aae935bfc41443293e71dd2fec29f37a9544672ab9250caa28188f390b5d4af13bb05e9692c1c6a4d6aafebddaf7eef1834fffe0f5391bce243789a2d55d29e2b90ce120429f2a075
+K = 07a4f8000f0ecddb72302cf4d7975c7efc41c143
+R = 66015e5fb3abe9d78523770f7ba0990031065ad7
+S = 4b8b153d5b01ddfa91f2dec6f0faff02e6e87218
+
+Msg = 906a933bc823a307e2ab29a4a8f7f1510d5d303504fde38169ded168913e3bf81d53a4389a3e73a3efebd5e42cf402bf9fdc5da5ef46878165ada6d2e07299035a3987ed6c2c6c8becc44ea131a9493e72aee28242cf7cfac38ee870e54eb95a6efa9fad74354b281cb63ea71652eba1ad73f841dba7778f3a03d3e00190ed68
+X = 8295ed7e125a65ea1762aaaada34602a7bc76845
+Y = 4f3ade3ea4f7066107321e8bfb12eeaf9b3c7bdcc6147908754231156b46e0639c9db9d5447abd2d0a9223c85d63d8b1dfa69742ebf7e0419e608c4b18c3ad9f55f5d2848edbec4e7180e34bfbb1f6b6ebbb68649714b5fbfa6cfab4a01f655008a95a7eedcdc2f7171094563a3c1831e81f5ca075c6e853beeae87a67ff9022
+K = 8148e40362a255d240a3e6af746a8880162d78ad
+R = 99c91e0794723bcde34594dd2268418dfb353443
+S = 42e9c49d60ad8f9b41f290ae6b772f44be62cea9
+
+Msg = 1d6ba43a0ff677cf8cf68d6a1d3304d99490a7cae56fe35318f38ed0f5879fe254703fa77458c45e8a698469b899a215c25e869fd28741101d27dc111ffad6980f8ebd748f6977d5d60438e6edec37a49d3011f8f0f08525156ae60bc91abe661638f4b9c6c365c3af1713bf7f7225d4afad7a1b531a331133d8b8fd238598a4
+X = 8d3c302da7b77ece9ce6e280e603bd260d2dc144
+Y = 08ad77f233334c04ca2282f6dac0b0d8a00d596e02e836a767a146ef80624b33fdba8b35204b20bee8ff2be9a82bd80131c0aa898b17eeab5af24c20551d5d636a11548fdd2e6c616b09df86b057e5702146ecc4fa2d44d85bb1427e7e3576f698b4f21645a1e00479d08982b0573dd1981bbd405c2a45d7de9242afae8f95c9
+K = 79989e8eb43520091706039415794d2306329861
+R = a2b42cca55bc1ba33f8252d1a89c8d89b00b3950
+S = 2ec5166e35e63f0fa116b3db1bd18681a4399c04
+
+Msg = 3bd0c5b759cb710c52b81fba48b6771cab17bf1b67eafd08f4ee1777dd473064dd0bec98d3582ee1e991ab9a91a6fe558a41db9ae6b21a057932811440d64c786b22d150e3d38c71900ad5b61e0530744e765b5c2ef30bcb96e726e3079e440086ef300bae9000df3403c33a79849f8f83d6c03f77eae98052578d82d628e65c
+X = 4d3e42ef42a60630edcc842f25a1b33c8851c742
+Y = 3a1ed976b7934bee3e80d69fbcdd35f82051ccc214bde6fa756be67017ff60ac6847cf8d1f823f890d26af8cd351716ad2d4eefd7f06c1951ea4a7db5caf250f407b78f21fff425d0cba1b5fb35a5b5dcf062a1cdf2507af74789326710e334faf3c501bd8c8347225f94f8973adb7a8b5def9896109d1efe550325dd89f31d6
+K = 6c59f3cec7e34db174dcbd6bfe224d52226c56cd
+R = 77d62ec2a95beba6c672d8422ee663d1d18049d0
+S = 2a339cc8f567c12149a8917375ec6ca4b47254a1
+
+Msg = 8dc582a2b5af65e66ebdf5b533d8e22b38b5c1977e578d3213a110e9d4837a74d4b7bf7d71875690b5b71c8e8afab89434c46a8641cced1a130e21cd0c805ee45c134c7c0df75d5cd30c41818f7ae475dd6022877c743d09d54f0c94581ae7bd4b423f02e19397be7bd4a904b88cbd2f814b1dff1e796d9f2d1c8470b796c69a
+X = 6a6a9874f0f89f04cbeaebde3833ae179ade3f5a
+Y = 5d6dc1749f28cb8f7c014d5c5516cf5bc222c6d9337ac0089b19b90b321956cf6192f3255d0eec45840810c21fe91cf5308948852a57cd0189f15bd96af8380d19cb821b1c56afdc38a94b2c32feb18213939693b69f2bcbae7e70ab09ead3b6a8b7dad3c4f521ad0455dd4e872b3627d4fed20d5efc78f6ae467fb9267ab1d4
+K = 27b2661922214411aec66e58cb36142ab3e5a256
+R = 05363bcca193d726cd20e03489e1b13b7df3bc98
+S = 31bdaccb29e4a60023929f182199c070b71ac575
+
+Msg = 477af8c025181b557732b9568634b1324e6669b4c28a0bcd4c653d4c81ed68b2a2043a800a314ba95e50deeacc5ee9c2ba6f6f62fdba0e86aca227d727377552a3abdbab601c2601846ec27a192a3f33e7ffdbe4a4aa7beb2b3ff6c91bd5cd5c890bcb6f4c908ff5b9b555e2a0a7df8c3ef6770136bbf009755bf6c3e6307310
+X = 17949e838d7c93e1d837be65b3c4482433a1b208
+Y = 2cceddc9e2cebbc1e99b83b03053bb14a9cfaf072b45e4746d18cb3901f6a2c3cf72da66b0b9b3e105bd4cd0e5427d7e9b657ed71884cd49f51fe8fa18a366018a3eafac3381e07a5b19f6d3862ed2916094906e75286eaf1d13c485744b270404ff9adc8e177833043bdc34c307e6fc9c55c53d8ff84a6e251038dbeb5ef774
+K = 620f07d7e7ced030e669685ab8c39174d88c79eb
+R = 3591c521b2a56cf46051c0cb3d444b9a22fff63f
+S = 7ac78ee252440cf9e8510494d1fad8b518f1e128
+
+Msg = bb6593ff219c9f20aa47e1e157e88ed59ae29c8940a527c82e0e0f2e855fa98e94e07be1f6bce3832b7ea1e60a5c9ef583f2ec7b179227e4afdcf829d673e1377f832ae38e7cadede415964f12baf775d38ce38e945563e72861519197c2d08f28d8b6466562e059ec41741de349ed5de2c7d6cc7518a87720a248b301733a47
+X = 301c11a34edce1f7ab040754e0b2d4fd88572187
+Y = 15d9e20c3f39cc9e3b8fb65feb64fb1568f6efdef6457d231c491ed51731d58f06e45ea5d665d04969823da4e6750a2c3d16c5ff6080ecd09aa39c006eedceb4dbc16ebd64bc5b1e44b831a6bb25afbcb3000fa6b6c2000860014011189c22542c145e407e7b59f6d3fb1e136295ec850b14ff2f4994ea37481e80199910be8e
+K = 117e12f88d6e44fc7f4d51d5384fc31b2e3419a2
+R = 61e727716cc96914509740a7cba6e74a9dec6406
+S = 2e77c14f01f22180bcda5725cf0eaac9ad13a7d1
+
+Msg = 565f19244468515e8463d07b425b4d5f81ff2efab5156ba19a63734219c226ccca5903bf9c35dbca0961db7c2e3f6944d057edfa6c2394c39a00f1c42596e7ee72ed644c6a182115bdc44b9010c86e7b0ec2e3bdf7016c5e04f455b4cb693e32490b8f494bb4103b3b5ea6808222452841b733faf735f10a95fb283dd86ce593
+X = 07dfca41446b2f4e1af2a67bc8468db9a9c2dfe0
+Y = 664245aaebcf5c055c32109b2159a17473043087915f14e959dddc0c9b20c726f0124f1ecbaf202fe2676afdabd346a7b5bef769a25c6f733612d7378df1b2d4c518a2da5b3a4cd0252bb8180838a46389a84693be8cc24fbdc639b62cb21d8abe1272b5aa06222fe2133fc5556d24e75496a53e1934d3b5848e510b69da04a4
+K = 4522d27cd17a6ee739873d69f107d872ed7e2db5
+R = 5ca07bc7cd9f7a60cf79391d873b6fddf5a48cca
+S = 9799c74a806fc196e0223fb1a613fd178cafbd99
+
+[mod = L=2048, N=224, SHA-1]
+
+P = f2d39ed3062b13c916273600a0f2a029e86d7a4b9217b4f1815bf2b24d9710a57ab33f997294b014585b8d0198dfdccbcd75314da5ff85aa344b45adaeaa979b51a312a7bfa94472fb633f1a6f156bb4458867dfd38403f06b851f00fe2d3484077bded71ab7513d04a140220575fb693395480e4c8402b7a46cec2d37a778c305accd1f13e9f62e865315f4b22cc467c8986ec8e4961ddf810566b0c4ee369ac6aa15e43f4744005826f5bde8071a19e30b6909aac4b3d174237270dad02799d09b8a2cc5f22e66894b5422228b2c234f11f5a771c5b89cf465a2acecbbeeaa1725fe8f9b59422be8991052cb556ddf2c8ce8fa9206dbf39feadc194e00f8e5
+Q = 8000000000000000c118f49835e4ef733c4d15800fcf059e884d31b1
+G = e3a93c09da6f560e4d483a382a4c546f2335c36a4c35ac1463c08a3e6dd415df56fdc537f25fd5372be63e4f5300780b782f1acd01c8b4eb33414615fd0ea82573acba7ef83f5a943854151afc2d7dfe121fb8cd03335b065b549c5dcc606be9052483bc284e12ac3c8dba09b426e08402030e70bc1cc2bf8957c4ba0630f3f32ad689389ac47443176063f247d9e2296b3ea5b5bc2335828ea1a080ed35918dee212fd031279d1b894f01afec523833669eac031a420e540ba1320a59c424a3e5849a460a56bcb001647885b1433c4f992971746bfe2977ce7259c550b551a6c35761e4a41af764e8d92132fcc0a59d1684eab90d863f29f41cf7578faa908c
+
+Msg = edc6fd9b6c6e8a59f283016f7f29ee16deeaa609b5737927162aef34fed985d0bcb550275637ba67831a2d4efccb35296dfe730f4a0b4f4728d1d7d1bb8f4a36238a5c94311fa1134a93a6b4de39c085e9f60ae4e237c0416d58042bb36baa38cba8c896295b745d5376fd8ce42eb6ee5a1b38f87716b265b76e58cfb24a9170
+X = 6132e551cdac88409183bd37ee1452cd247d4834b08814b275be3ff5
+Y = 289ff18c32a56bb0b8839370647683a38a5a7e291410b93207212adc8088d30f93e9e4abc523f3d46936e7d5c90d88742b36afd37563408f15c8c1a4f7ac24bf05f01008ffee70c8825d57c3a9308bad8a095af2b53b2dda3cbed846d95e301eb9b84766415d11f6c33209a0d28571096ab04a79aa0dc465997529686b68e887cd8a205c2dc8195aef0422eba9979f549ac85548e419413643b7244361153ada1480d238cd00dc16527938955548dd5d027ded1029eeeb8ed6c61b4cd59341d8b15466e9da890a989996f4d7691e6072de136af28b5874bf08bd1f8a60cfb1c00888132909f515e04bce81b02951aa41baac68ffdb8c5dc77a1d32d8f2c10dd7
+K = 7197392d32d0af6a7183cc3398556f8f687d86a8ff742be6ad38562f
+R = 45df2f423e94bf155dd4e1d9e63f315ea606dd38527d4cf6328738c8
+S = 59b3e8efa5bc0ccbf4a3cbb6515c4b9bf784cfacdcc101dc9f81d31f
+
+Msg = 3bd2ab08217878e6774ec7797deb75d5c94c40e24ddf1fac8dde3a29c86b26f57157d329aac31a6622e1d6dac97e22695d7d1f8e20aa26b06795c2f878ba5d2b9cc4b16d5fa60a5fa5c24c09031de2f970a9b57ea24af17192ece21a4d120fdb52e62b8238f778ff8552fa453c0a8891243fc8757188e9c4e0e749f7e9cdf1c1
+X = 32d53ad2620c156e4617a8680c543839c9be93103e80cc0fefa44ce5
+Y = b9b0e1cd37bafbedeed173fd709983f53c2c427f9f61c895fac9eb549bd6201d05efd551aecb98b2df80142dea7a35491d474a3adc83f0da8dc4eacd7f6d7201c6fc0ab798abe89dcd7d0310d5f00fa10d211f18ea853579e2fe31ee55371d1c9fc4cfb050786586659bdc0f1aac4c109b9e4f9416d22c42b39a471311e28a8ed62f1f41bcfe06e074bb2f1acd29597953c3b69d3a78831fb2f83665d04a1395775ea3a2a6ea142ec00507badd4de0d9c102eac7bb894f7453e6a8e0dd3f14978377d1ddb1fdf1c55835b9924f42ad45c847c79b3f83fbf924f80b78f50329731016763e01ba8ef69e81523e181584f45c21e3c8edfed4e2ec56fb7b02aa4ee9
+K = 2e8e4625de74e31bea9e480a5de92890095b6ce36897a2337ff97d53
+R = 6d19fe3c415d6b07d6a1039a1fe34b106daa2eea4cbca971cb669eac
+S = 14d7decc2cc05a1700fa256e4d2994bc4bd957bed0baf9a18bda7090
+
+Msg = c67fa77cd7351d100c7624e25418481f8fa499d75f5949a5cae60f96a0f7bfcdda7dba373f9f7512a5f1460a95213077cebd912e2662c43ac6bbe38c4479b04151a5e2d2880902d031aa0dff3f41126dd09fba5c0507634ed16c3938fbd3a96473a8b1ebdc37d32c767fd5932efa235555f3825a1595369238675453604d278e
+X = 062bd01487e413074126d9d47258b5c7c77790a9db0af952ce799eb0
+Y = 31939ccdd393f747541a5c69f8e509761dd67eddb42e0bdfc412d4cc30d368d878d26d856c5290ec746b59c5e5af65ef3fd62c9a2dccfc1558dfbfb62cfecd7838e6d59495b20db5ad9d78e82f046f9f1598113aae0a79601d6b94a32e05f6ecfdf2b9c4cfa720debfc212221b14b0dd6f7078205a4f218cd4b8f10bea8fa481eca5254f365d01f3c86520bf254323d5634b96920a13b8f29d734e07fde8064eb0c9f8ebb6ae0b40b4aa7d26bb8d80868231d4558a278045cb5f2951cbfe0dc97bbdcee7af8c9b1e3b63cb49dc29f300775cdbe4d2d27894e27e0e7c9eada13a359f0b92b449e9d069b95bdc2aa7c85e56811c07207a150e598735996a6e5349
+K = 7439c7aa4446ed540ba50b9c817792b08fc0278fa0af2daded03756b
+R = 7924b76ee76ad7ff2ab327dabbbd31336750fc7663df4b5b94eeb62d
+S = 5914cf965490b0bf8192fc6e169754bdfd31c48d716361dd15f45bf7
+
+Msg = fde7434c41666022d6d7dabc7a67315b1ff49a2a85a6168f2b6063e3036a4f35e66d2872af3d97e5beba239698d88e13bd036ef08cf0e83a41664c3d0d21863c24129a6a9b27b8e96c8029ec673e07af7246ab77a56c21ca208df4b1818deda906b553b2b23a37b5a05e29825ebeb47f53986c2bf26d731a5b731fffc353258c
+X = 6e6bae97e3b37a402eca050d666b6483cf7d700419c5ab1eed1bed05
+Y = 59a14e36c9ededdce8000f04c6f7401ad987f1c7a5a070b80e0aaed7751d1d50d99a580cf205dbcc3797a0a0406b04776d80f2f2df418cee249b98672de7e61cda85cfbe903690e54642dc2a12a90ecf88c59256a4d77c4c0cb54e13fa3647b11431e1734f3ceeea04fbf3459665e999fc0f7a754683e48cefeb4a95fe473911ffe0de0f738960753dac33666c53ed2893bc63dd4162d7a6328739a252cdaea7a948c97d024153b55d14fd5304e3575048418808a952675fafb95fad84b1156b24e98e048aa777a745324ec13ba378e83b2384bc2e96c6095aa786bd28fc3be6bfa4db0c3c44fed4c351bd88a19e179a6a7bc12fc014f17de46fd12ef1287f72
+K = 08544a6237ac967e5d11f2eccc6618399818b891df7a04d08cbc5e74
+R = 49ea82713aaad799e263809e161b0655f1e74323a06041836f676980
+S = 76b3f6c1647f8d17718ffb92d6e1424606ba9724e5290daa4ee95efb
+
+Msg = 6676a3a131cef7e5647ea7590da3c704a0f5dc3f37f26913a70d430609cc2497c45e68b7bd6f5893dba26287ff0d240bab8a0761936aa709a2162ebf1c20a6136a748352dc39ba4403cbe4b0a5a54a729286dd193eac1a2e6bdc150fb06369be4443a60e75e5330083ff009eabb05232c52368a26fd237c7c3185c1c7e7d5955
+X = 18faf583215bc4fa71791f6f34e682ab3529aa9a1a71c1fc7bd456a8
+Y = ddcdf4c616fd6e4016099fb34ebc4ec507290762c5ee6876f10c6a2dedec97ba86a6063aa8ff069f3f3db40c9464afb1ba7ed691773afd6083586b14e35694a9ddc376ddc39dac57132a05bf88a0a6085c72a80a21c13e590c68c4e98eedb67f1e16c8cc7e9e25ff37c87ee3be9adf1ad0b838651b0fddf8d026969d4a16bbb828fcaf00efa306fcedd5ae19ca1a1abf44a2bdf6f994123ce941fd3523bc1335f51fa8dc5d525358bddf0c55fe2ce07ce974408d9090488837976f16845eb7a82d04c43a704be2dee1be2c8683b2d9e5c44f1833f5c46c65b6e62c2a720421bb35843fead7b9e0b3fc04c646be39e890e370b982bde91f2fc18442b650ae602f
+K = 11b25b09408bb5dd784ad70264e585c978dc02cc1df8bb95a28aedfe
+R = 1658a7ef2f444b014a1885b1eda8dad3605b96c3948e544e4c8825eb
+S = 602150f67b19a5e3e39fc53abea02dd8f3b30d25c0b4ea0bcddcbdb0
+
+Msg = 071f06a11588584da5576013029b5a14712581a48408bbfdbe34e17568c0a0e4d12c1e9c3fb227101440dd8dcdc415e3b49f68a26a0ec7612a10bbc64ddb8f7ec9e9750d1efc9c0574700875fcf52d00d37b9dd744ca841ecf7566977c1b5799dc4105d0b7a92551c5b33a50133fa300a5908b18f4c01936347c6049447abf29
+X = 58882f1a41e08bf6c8dad091a299af0fbbd14515c1550906ff77f6ae
+Y = b1f4dfc9c83455f279a3e7522734d6b120ab8ed36ccba7854e26504c707983d2a9c075045723f441abfc7b36fbb5d4bf0447678f5b709ca5129b74888a0723e905769836b9dac1303f1b9ace26554342b6e6d032ac4b477e011a4ddd3e2978fc0c449c64a66efe7d4e22e5a5fa2b01bb17fcdbec7185dd4115a19d972fb01a06b33bb18b9349ff95fb10dbbf2dcf899b1817d30ad48a99a614d57770ba764a11a84a8db3af3041ec362614f807196ea3b90d05b014054ff4e18524c795e6722c0fa1f6d1205d532d94347633eb132e6cbb596d8b341e65f2b2f955872ebd4d3006c45ac33da11167fa46869c7ee70e9cf147b23368b3aacd9c1880b09ac86a8d
+K = 5ff04e754fe3246f35b3400b87a450192a7bfd9b3c03f3ece93449f4
+R = 07bd3f6718e39839304ef54ac48bda8d9ac8ee051a49bb9131dcc918
+S = 6496b2469bfb5845485004702b0c79941bc3c3007007ba169d8307ce
+
+Msg = 71279b848c00208fb4e4d87979cf973b321b20d098dea912a3b4b5789cdd3b7ccd8f3993a9c92c34b70e9b0bd57520db56f2ded3a612a6169d2a1cc6350905ed0202a25c113b7bf8faec4edd2ea3b8f447ca75d15a712b4b4394c22de0c2554b9aa07ec8466727e7ef6f1f04ac4568d7726d9d77f50a2fd551ac29e42f8dda23
+X = 292b1666d0b1fb361da268de725b11310000705964705ee975d4ebae
+Y = 7c8d63b9d55f59290b02a0fcea6d98c6c545e2c0d4b109a069694d80cb034dbdbd9edb6b4d9b152849cabd655fc77071644bbf4a0c7ea4edfe864a43c44fded163dd899c21cc2f9c33cbf56e8caf84394b24f8c14e84f22c3b0f747129d9aef41b6f1b1fa8ff5a8f680b496595dbc7b7b63a7790e3628747011b3277b06e80de0b67942f602eada60b518f282cde69cd717a5f6a19c8e169449e0d32a9d8ce8f09a5ada23c12a02dccfcdc0290a8bd46e8b7eb397494f32a0ecb49fa5a8edd41845eb417fbb8cdb89a9f18b9ad1b41dd4122ab349bb3c44951e4f9604360fcb1b795311545a61cfd67c287a7c9d4d3530214988e7616979e2ce907d5c7f3e9ad
+K = 6b1b752bb180d8787c71505be758c0ce41fef428ac10591502c9a04b
+R = 4cf5c26c4c2cd48c05508e52d743ef48685f6324141adef23d79a396
+S = 59f64755a04c90a14b187ae142ec483c4600b6fbbe19f04a49e9ff88
+
+Msg = 3ea03e9b005ec1954fee0c73326d8aca1a4f63648eb4cc59265528ee8e969ecefecf2797a0144c8336500e26a1c7cb1a642b1ec65201416e5deb355201de2bda695d1beba8dee62772f4d5914a245be9ffecf39408ae7bf1bff7c2451029c4ba0c522516e89955ad3bd699cce94c744081a9f2d60f5c5127ec722fa57316cede
+X = 087e432b1c29c00508d768fda7c4b279fc088c48439f09980bfa159c
+Y = 1239c347be4ce6f1daa721fbbb141ee6e2f7c73098effe8e71beb9f1ab72d1b5bd3e78df770f7fbd4b3a9505702dacf102eeb8a16f11b4f809ca002ae3774ac0407e2572ae3ee1716458e5f45c493f4b921144e858d87d63773d023745512b0cc02b31ebfe5c24ad37efe539cd393cfc2b951fe1b6ffad2a2824c0f54bd776aa0afcf9c1ef427afc6cf4c4b17f66355d68574132e1d88ade3722513e395fc62d65e9485157c82064c90803a1a91f9e6b10af2f80699d917daa6b81415e508193152b4ccded593dde35f645e54b7cba445775eb16c5e19073f0a9eb5369bf2513b92158165b94dea511e938fb6a8798e040a05da94fdb5a4d44bee943b95b39d9
+K = 0a8a45ce2412cb84e4e0174d7ecd2eb5b37ad0a53b474fa9bcf56d9a
+R = 5ca2e971f21b70127a70c655eb87e20b2517976228a2c4e648d549b2
+S = 44036b34667136a5140dd1948ddc2fb2bf679efee21f29b7ad87af7c
+
+Msg = a3f7033958c5b779072b0548baedf4f88d14f11a6dd6eec0181b399943d7246a45d50c4f7b5295dae4cd3ba7c4c181fa201581ad5c4b38793bcf454f176868e9cbe0997aa41987b1aa3d5ddc046be7b022fb5130594c8a9df03cfaa7acef817e3ba5e192c69a120299492baa52a9be83b8e871abe318b4a1f588f9edcddafc17
+X = 5831abf9843eee928944e3dbb759dc7224910e1adab827a04f596e3c
+Y = 62de2465edbc1ef8458beaa205f45f9dc0fc3db77bae0f2b13bef6d803db689b8f5c747e3a041c08d326cd7e1891675b022a9da3bbaef8007784c56c86c4176c0ac876351d1062d9c270d548c8f4ec39a4556c66e76e507fc5f2540abfa77c178a9bae153435a7caaa008f36b9cab213ecf5e19a0f7b1e62fb9a9c8223bb689e8547b5ec915b04a85b2f53ccc792dc0a7a41d172e6f59f5b5e7c440350ac6a72ca9c06562d4cf8c60e70870a978312e19bf54c2481c582296b64554bd871accc8b251a7617ca5e5d2aadc19d484d76bc3826841f88fad1491d80679243e1527197d02a406348b247ae786108e5400975a38f3961758adc07ce740d8d442f152f
+K = 36b3d1d36d1a8c41442b6fffd46bcd7977a306b53dcf7fa590538194
+R = 1823f0a807fb9e71ad69b8e9fc674cf76f67c42cadbea6d34cf1f1cc
+S = 667fc57a44b289fc34a198556117afd696dcbd96bf1baacb40d3f8b2
+
+Msg = 680d878ca6eeb87e4ae158dddc3732784013ebb1da89401acdd6109089e5601d695f9e4e6ebf16026aa746dee80a01235033f242079af1b7fa6965c87eae8b3291a009e4f19d5b8f1394d866e7c9b72073a95652c0eed98e9484a15c9244764d8cbaabd49d24c207c705703cc35ebfc7683f4a0e6abf23fa07678350a6a00cde
+X = 738a8bfc478e462c4bef8d5633e0793475206551bbddd08507f005f5
+Y = 511a3608c4bda7c82d7d68a5d30bd4c71e457b0f323027d601d6324a94893ab3d62878b12d98c44dcf30adab4352b70f4daa772df6aed3c07587e96c68f8a847a335051481d53903d1d1ae0cf99a54387b00169a1c9704bb62f1d98047dba8a0fdda734cd41611584d50554ad77890720c8ac29932097cf2bb1a8d0daf8663241e23640cc396f9e6877348f014073f4fdc5bebd115a0d74c2ce857e100ae3dc0707b95effa4a2cd8629fdd9bce72091c0e2612d2b30320420f42ecb0986ac3289251b4ae54e51ed83d0195deda9d4e5b398b037213d2f8f0ffdbf727214085534a324d4fefc1653642035ebdbe8167b150bd92b7cdf276fcf5e0bffce956a47e
+K = 58d8b64bc8c2da02a294e9db46bfefb273e74870651e19d6cd017c55
+R = 7ceb71480b5a7133401b5227fa2253332e04f78ea5d0fe237c8525d1
+S = 484800e81f7b5692b79eb21ac2fff83c49c9f0d409c756c73fbdd2f0
+
+Msg = 697f9efc8653fedb898c77f90f124bea5c3b893c49d7f1b116479e83d35cb6c3940797501e7f52887d18ae9f4055e1bdd124b572f7a6fad101f58b52b30ca30d9743a9016af891896d25356e44f982d406ea26a9b25fc4f903092d7e8e8713774a8be7aaac93a6942c1f2c48e9dea64984ae54f7ef99961bfd9b8d93226af776
+X = 550c8755237857a0c8fc8a63525d4025713b89bdb127d1c330c3324a
+Y = 64b588499c9db3e5864192464d32fa3547f648fe676c150a8f9e153c5af57925c76dda4b419d60b22fa5cdea0fb6f0b8479c988a324d275bd42ef10d8998c36039eb4021fc0d2788b59a75cf25ed6ee4d44882b0c5c5cb8dcc1002c0baa4798107e0b57cd26debbcd0ba41d1b1b860b8eb90f6f30500b2e4be7a00b67d93c87d3ff7a6ce53b977a930999807fcbef57d8dc67a8f366124991389328ce7e70f9e5c22ffdedb28498282b4a9a9c68534a238322e0db6088ed0afa8bc77ce998c814471ab56767b35d07b94290ea106ff0c998b51f02222738ef9301f290c6b485dbc4f12b472a1192fd93f2d23527a02d95af0b422be7640a9702ecaac26c9e004
+K = 0b4329f9e5ac4a117689883db2ca8e968d30a3aced61e27ba27c6242
+R = 62054d11529b993a6f19a0d5481b99b4b4461a49866c29534a361a8b
+S = 7a7fd0982e4e2118d1a069787a80b902493465f6620a355c86a94867
+
+Msg = d080a7dff1ef20e33832b99cf83c6c919c07620bf608e080aa301831ca6178e44ef7a4c115e93ab6d877e96652171610a51d927d2034f42f280fe87d7c1747c480ebccbf565a150f3240f6d4ce5d6eb0b2e964416791376ed22b3559cf93a019676e9e0be3c8d34f0e0d1152ec6c326d3dbf1d3303beadd188c3aa0d77e8a117
+X = 2171d5e7cdda9a691dd27f0524f24ca41d5d801eb2ab0dcdbe6014ad
+Y = 41767ce26c780e3f2019f5a49a701570148e9ff3382203833d1b18e9d8d6a00c0b2258f2e567db31ad4e8cfb2621794bac87d9b3b53b79199a775058febc190d00adedae0fd3021291bc2d1ff0508bf019eca0c573fd863722f367d5d02bd9fa0d07f75406ac204fd3a5ca16325c661fe854fd00fb26654752febbe439096dd2284d5ab13de9eb004847d1d8599fee687cb2ecd0e5b761d91a7e9c58e6921f103024215e74f3de3cc12f5ed7703def041dd3267f1cde0d4fda8dd5ccc9c07b65de59482c4784b4f6fa85667186e2df6c5dc8b495be8ec61379f20923576f17680c4dab99312d0b6441306ae717c95d3f352ba4c096f01d14a7dc05b28ba9a3ca
+K = 0f6626008e50c19def9bd694c00522cc861eb7069d55892e08ddff58
+R = 44e70d2ead3c51dd0c5461dd4186825e23b4e751d8ab17d0b7edfaac
+S = 48ffade27531db478f22fa0ec92bcfd2ffeb6db67715dcdc79bcb028
+
+Msg = f6a9afe241dd984e3bc265787dcc49491b3bca67feef32fc1e07fdaf0af6c5d06dccb47cdb6907511cb30c109f62e66718c5c4bb43d4b00b51235df43223d60ce1f9be3493a4dcb02e25ed3ddae10d131b481a61aef334b690c7a1ec74865954b39ccfa7a51a9a1e62e654bb89270c774f082adf09b579c8358dacb9db7ca1c2
+X = 77207cf0963f1e961c3539d7d0f678fce517f67b728bf15e0cab3ae6
+Y = b4138fa4e1dc6772b47e5a3ed130a13b822394c3ce8a0193d1dde4c90e7da1178e1126dd296252fa7d2f139a148ac44dc06a058b84ecb03ad827e66892e85529c362ceac2e7104b797b2e9826054de350596ab581765e9a5c9ff5143332c2f3bfd249a87fe1e30efd6fc057e234a1cd4c19e072bd71b32d55ef122ea930911081e26d998490376e3b721cc32fed92b82d545a7e6ba6e4eb434063c87db848df4ef02eda3fdf4f9d2905b78f7b16b5ea0b5998f1fbb0aaf62a1735591600f9801977b1b947f61a91ff2afb8727c55268972c87216aae900617a56f535ed18c4c5ddf8d7a54463256d09144d889c149e5b09bdd9d8509314b103b846f3e6fa1bb2
+K = 57585204d88d73c21f66a150991531973978dfeaedd8024e268f18d5
+R = 555a454880084f6cb2522daf3399fb4a501a943a9b6aacd58e2c7d37
+S = 730fedb3a5911844146098ac5603e2baaae76962b33a327b50420a50
+
+Msg = 2d1c573bf324028dc2fe00928f55f7fac79037d4d99eb185f3b997e042cdf808b5382d50a6aa8085c5d1958e67283df66986b93471c12e3045ba146ed5965c8ac5b44668f61984d21736cf1c276754b848e9fa636b6315b2272c19e65626bf8b1214d70989a623b5fff7803d28a663bbbbebb84c839b42720fd0e62246b3b034
+X = 789375055f94b9ade40b0af8f70640336f5de213571ca1c645ca468f
+Y = 5ccdca35551cf355ec85db8d68010ded63583255b1d5fd2a522e29513ad3ce6157be30ea1c305d87de6c27fbe3a3fa5007128275d6e6183a65cec5b694bc6c027335066e01273fd6981cc5f60c3e33751386ce792ccb6e6a6db5d7f073800329f9cc46d19f422923b9748dcca4971e43a9d1f59d1c749788a8527ad524df74150b39eafa7f4d5608d1c97255654456eadd4d382ac54fdd12538b2f2ef75a50980171a04d4054b4cd79c71e1c4deb3bc6af4c874f5cf0273896d4fdc5847fefdcc97f5402c7e76484d3d2d70ac16bda41996cadcd83ad92cb37c0c1e9d64fa1abd9a2cf005c2c29a1737cdd6d63aa2fdaa560799b9f07d448760678477629f22f
+K = 325b1562d5c9c61f95e6944fb12a4bb08d227c4dc0c8e9a79e391b08
+R = 7bf3c0c547e21846212bf4cf3e38362dd4d359b7af6420f90da57907
+S = 5ebd5d2d88cae40b37a9a5a84e6218d2453afa146c79a5d5f5df44f4
+
+Msg = bab4db55bf6d3abefd1bb4e0f7bcec65ee6c6d8eb04b7c480df4e9e39150f10c38f1abb63dfe1bb9755c41b38955ba38ba938b6ceedfec02001fa870070c59df1fd2d72a814104c5143376a3136b8118f7b47bd1ffab53359e53f95c66ee12705e31a462a8caae481556ceff607ccc8bf1450772cd68081d3f15a710e656ae56
+X = 6f4a94c9254a557787de9afa08215414db5a0dbc67c66cde1c1e6f04
+Y = 53c0b0b0269fcf2948667e28b11ccda9cbb9275463f21ee30da33c4575be5e111a182a6f38b890f20b8f2d224f5981895310db7c4703c1cec2b257f452d964be50c014b752360ee24f2fe1bcc023477a2d7085f58214df866b13a8d8af913146dc0bee078aea1ce645999b579498eae9277ed7e8b2c75f494efaa73a973f32232f08ce7f0afcba316623b94158de39bd4c0d513234ee1a481d5b72f4eea37749b40fff12ab620f11aaa01e3558e7a4c550707b71c16cb8cda98f46bf71769a476c3385a8caf7c886ae47d228b1771a8bd4b7f19e6f53047f62f029c339fe7575be93080ac748289149a57a0ddced54d72f6d4d344fb874ccc85ea7f3dd2164df
+K = 14fe2a5a75756885240ff29abd19d346b2e7e5dfa76d2430f0d069d6
+R = 118d2227be4bd91e98a2efde15609b2b9124b2e83c274b632300432b
+S = 3a447461944b2a59278a8e1118b406bd3ff416775d65530e54f9e623
+
+[mod = L=2048, N=224, SHA-224]
+
+P = aa815c9db1c4d3d2773c7d0d4d1da75ecfc4a39e97d5fa191ffec8b1490a290ce335e5ce87ea620a8a17de0bb64714e2ec840bf00e6ebdb4ffb4e324ca07c3c8717309af1410362a772c9add838b2b0cae1e90ab448adabdacd2e5df59c4187a32a23719d6c57e9400885383bf8f066f23b941920d54c35b4f7cc5044f3b40f17046956307b748e840732844d00a9ce6ec5714293b6265147f15c67f4be38b082b55fdeadb6124689fb76f9d25cc28b8eaa98b562d5c1011e0dcf9b39923240d332d89dc9603b7bddd0c70b83caa2905631b1c83cabbae6c0c0c2efe8f58131ed8351bf93e875f6a73a93cbad470141a2687fbacf2d71c8ddee971ad660729ad
+Q = ea347e90be7c2875d1fe1db622b4763837c5e27a6037310348c1aa11
+G = 2042094ccbc8b8723fc928c12fda671b83295e99c743576f44504be1186323319b5002d24f173df909ea241d6ea5289904ee4636204b2fbe94b068fe093f7962579549551d3af219ad8ed19939eff86bcec834de2f2f78596e89e7cb52c524e177098a56c232eb1f563aa84bc6b026deee6ff51cb441e080f2dafaea1ced86427d1c346be55c66803d4b76d133cd445b4c3482fa415023463c9bf30f2f784223e26057d3aa0d7fbb660630c52e49d4a0325c7389e072aa349f13c966e159752fbb71e9336890f93243fa6e72d299365ee5b3fe266ebf1110568fee4425c847b50210bd484b97431a42856adca3e7d1a9c9c675c7e266918320dd5a78a48c48a9
+
+Msg = e920fc1610718f2b0213d301c0092a51f3c6b0107bbbd8243a9689c044e2d142f202d9d195a5faef4be5acadc9ff6f7d2261e58b517139bcb9489b110423c2e59eb181294ffdae8aad0e624fab974c97f9f5e7dc19d678a9cb3429cf05ec509072856f5adfec6e29bafe8e5ba95593e612843e343111d88a1eaff7dc0a2e277f
+X = 7b489021578e79e7bd3ee7ab456f659f3dc07c88f5c9a39e4f8cee81
+Y = 1ae10c786ad0902c5c685dae5c7121418a377b888b5f2f2bc76623570fd62bcb190b471ad5359c5f062f8819289e956d8aa6f90d1f8cf1ee72d3a1bdfd56c478dc29a19c4569b5a60e3a8f34f60656eac5b25dde5514a5c67b675423204f6ccaf0990617cc7355b9d3ed868978a252020a769ed59a6edaa6efe3377eef45f3f6f3e64179cc7db8b143fb835c5d71bfcfa1e2a9049bccf7fe9ab57546220fe3f4b7521c861739d138507e81a46a6993605441dcb90d6ee4afbc42cabe90a254444968109d7edd9694a023239f1d56175dd1fac115915e24fab563f4fc3f269bed2f300832d112596485a711417aa73bb4ac72a651a1fa5baed3636c720d397008
+K = 37fadd419fcbd2b073a06ae96b9eceb63e29aee9ac5fa2bdb31ab85d
+R = 65102e8f64ecb11f06017b1a0c0def3c29897c277c4a948b1f4da6b9
+S = 21ad0abb27bd3c21166cb96aef70c0dbd5f3079cab0dd543d4125bd1
+
+Msg = da5e7b051c1859d22f2a3163335d277951973c172e06697c0490ff15b592c1ebd0fa5efa2463119804a3fea224b96b463e30083e002949a24e922031764bb3daff8101fa088af5457af36654c668f234a00cd828cc740a898c0cd3df09315da9b346b325b2fbec475210b75482affa61a3eff50c83c3a039fae5cfa8d971fddd
+X = 9d8bba124417c126c1c011115906a7bdb7a493661d8a945e32cb283c
+Y = 5e276987b847b852cc372e986e8aba0633dd46c461bab58acae056d4d1a9df03a19df114f648b28e038506fd09ad0d95449d9d8058aa1b241b2acd3badbf9882697331de45b452345c051c2cd830f7cdd7486b1166b93891a72a8b7dc6228bad708720ef33235801c4d4c3c4f28036df6029a195d0019124d16fe8f76c525b7e8f04bf4b8d8ba6ef608e623224fa8d988420f40526c25ae3e4c79d5ae7fee69793e02bad9651ea0fefd3eadc5ff1ca2d142930355b1f3aea102221fa17b735a18af3b83327c8f33efb9a49b70211014eba43fa65eeaf25ebf452bc4b7dc1f407d0cf1b834619b5f73c6cab7051c92070aa06f7f9406c507d1a15d12c11bc839a
+K = 1abaec5b4efaa83403fa970ff6027fdb596359df930a02baa12ed854
+R = 313615836f0d338d81b670f116a5414d2ce90ea5ca5308ba4f0c8a7d
+S = dc1d4c3c06203fd598a476c891dfe5934162d0d35f37f1c09dd6395d
+
+Msg = f49895b3290d9aaeb4af611c5e30afc0047dd42c07216211d54977d1497fa4ee6abe11000d6ac04d24b4c50f31e06ee8a74774d3d304137cc6b114d145250ee7e94a12a1ab592ae307ef5d930cf39170e9756adc5e7ba62a54abb6f047b4500b6121e1f4a95d3c6a96f7f8333cbb1ebeed8b4db1a7fe75f4071cebfbbdfdab90
+X = b9174a6cb4d3b2e7e4d168078e920ecb651343223575dd37c0677371
+Y = 6d622525ecf54dbecaa811939ee07ef2975d9da9f7a3c58bbb893ce3880677404f2c6e5963b8c0b4492601f15bc6fdfd747a00ab8334e9053201e1c9fba55fbfde36ec54237501b87416992771cb5ab8781d0a967b7f14f3d5de6b1665f662885878e50ad37827b95c8f0e21d6bbebc9dfd47b2957d2fcdd1a2b25a616e698129b45998b6b6aa2a99c1ebf4275493e28eef1ae34e9ca63cd8886da58572907aa9b714e89bd3644a7ea029fa3a4ae9c26e665c85296204fdf86b7b1dd7866bc8e9385e9518a270248292594c54a4a03dc1492664ddae53277c6fbb9dd0cdd99bf11eaf6ae31923e4f979a7f581799dc432b1940f613a7a7ea6855237f776e91d4
+K = 1c52eec9523245bd82707f2ebdb05fee6d34749f23023ba72a5a60ef
+R = 79d544cdecfd1ec1b7d1ba6322a5e0eb858aeb4b76d5b3202cea233a
+S = 0ea53dea4ccb25978a0af5529598911b47c25e0ba3b2a0505fd1d7fc
+
+Msg = 31d739566914549eb25726bf6d4b6c674f479ba7a406acd108a106f36c7f5214976dcf3adf2c83fd26b37d52c0b5ff51e6b3811a8dcb026a1fbb52f95027ea6034d91149b30ab4928ede26ddd692ddb8ddd929fbff83fc673788faa0ba5d967fd1339299e55be51cea80609d2b3c3433cf713a9686e229336cfa7e720fd5303d
+X = 4cb56c8acb9c107087837ef5e021f77cb015023c8ac1ec73575e5289
+Y = 386cbb8f7e728751d4f6a75f890502989b51228d3039dd1af7f2dd0186bf97a9ff763b40323b30ab0dc81bf09ef48db72c0cfbe772b3d314927ed19badee7b88b49ee294923714adae30c955d37b99c1dadc4a29f0f8c2b9d1038d17059c586a212a9748720fdec95b428971df1923f08a01d35893d12ed17e0b142ed8e9ef77d440a01d77905b92c51dace1b345cd19f91623a6964288ddee6e9908197f91da9a26f806bb14e2371742f849cdc6ce7a045a704a792e5760d6644eadb7cffaba806b0545fae3b9fadae4e36bdf3b69c6dbbf0d8b053da38b904e9c4b949325b2a005b249276ac36927b31793f80115b5e2f2107f987710380708e2c322894fa8
+K = d223b9e9c662ba6651cdbad84f2616fa223fa8742f783c87c2fb9e8e
+R = c8b8a92e8c101505a1991bcb02fb6e382a3ecbaec8f4374501b657be
+S = 20d161cefd584979224379f28d827aa219c572f9600147f4048ba7cf
+
+Msg = d0a8a1ca0ff2b44b37ff860007334b23be4934ff89051d787ce69d3d7fa734b9779e2f0b38c235391a897fb8514b857b991d10e34a00dc25b0c4382dfb6d53aa87ec1784f1cae2599259406d4756539867679d3088913a138871e2a434747222fcfab079d9e655ba254463cb0c5786b9858dc429ffdadf4c3b6a253f90eeba24
+X = 2286424f368e5e64bac0c977ff0d92a560b78e4f21b49f3aee7cdec6
+Y = 7247d4e1253f0b52a1388b794815db61c1a354cb0f73fd19fede615c1c3025840fff204b0c6e610ebef1113df56f67406badeb99445891dcafe18d28f597126064ddf7aaf203b2fb0d35d2f458bb74341ad937211edc394ec1a3f7909a3f972db27aa135d31bbd7e36c2bbc360585e7bb6e83276406b9525f688ee5995e7aa8ef7a72c27e990d64016b99a0ae4d04b2f1b7d238af88ac4c2e4e0f3294cfee9be2457e48955948cf4bb3a445a1d778cedfa4b86f59f156118034b2b834a9aa121e9d482d6922292823be2991b3b5b42c23925da294d5ea37406eaf78b7dc72519d8f261482d6afff0e567bf6e673dd89960ce734f092d98956352429a91845694
+K = c2795f65f0f077e32c022a703f7eb8e5dc068fa67cb087ef366b243a
+R = 9dabff22a43012dbf47d56b9ae5a09f4d739dd69fe907725afcd84f4
+S = b60c44728e4b1390f30238fba1dc1003fdd39507ff5d6ba7e609f2ae
+
+Msg = e4ffe72c77c3a43af8a61f58f9240e1a07b5c2894d5bdb654b2b994dc0c987bad9b704075d3d0a969cecfc98b1dc20e76cd8e012285819462226a84dcdd67895f6ea278266f1575ea785a2c359f8f4593bef31a58091b64afb84cdfd23e4aaff29d9626f0c823d934283a4faafc9c6cc18622328cad96f77d79b9ba35a43d825
+X = 86b0e564ef08e089c4c85675b6e5281daa4e82bc2fc0e27668052e4e
+Y = 7146009d12b03b2f32305f495fafcc4d452efb85cc80d671ff4249492c6699fb26a89ca4b224d56f6b8e745df9fbc7352ca583222f4deab118f9fec0b34e334060bdc28db872e0090649149499e7a1c197878d3c7262439303b90201d0b7f5be94d0a7c4eb15182935296c3e3fa2d77d74d78f41cadaa40eafd40d017888caa02a474868e40f496b7bc1ce367f503435e0d9a6375aab03c231d9cdaa15de23c48ac0878ef649eb144ce6be4d2de11da202fae82090673c83b32840a32df6176e1d55027d7a1c1c56e642f51aaeccb3c990898061bfa16b3dc1461073c333337fd76a3103f3fde821bc994ebedd6ffd7974d0ca1b54961d7df5b9eebbfa26c3d6
+K = 5aba2fdf6b24bf24151943a4f32d2794e44d1f62e8c968ceb5b073c7
+R = 4a2abc689d2a63e8b23214a3212a5d20a7386882d5e11c5d5daa66bc
+S = 08e0c6547087b58bc94fae247e962da1a2897888d1bc9c8cbf3ad6af
+
+Msg = f8fec19288f3a8bd1d0d573bbbc180106065697481bed912f8752750d331e3a097775a12276bc4293a78a80748b2b2c37d20b800335c1d1b430a71bbdfd8f7afeeec82ceff2fd33f2624e49d37457f262cf5dedef9025ce96e0b7d499fcc7a7ff06c02590ea821dd8ed060cabcf4feec9592aceddfd32b4c09e4d44938435b82
+X = e5ada29e91ccae11fd060112540eac31d9651b34b2754ee51620624c
+Y = 7e50011d422986eae01ae68943dca0c87af44f7b879bd1256d4caffa0eb1925029c0633a7ac67487a7b6f98ad77ee7e1442d129d06db475a4f7804fd8c6a038151911f81397e963594b9c91e3bfe94328f056e9bdbb9b11f54939d7e237aafb0c950e0581cabfe94bc26f0e0d5560997bfb0f6357bbf2cadb0108ec0095646e4caa22f71e1f17a9f34e8a8c4b71cf0b1265e001554fa91f18a17562bc0948c431f25945962ba7faf7dcb64ff0b8bdde701e1df620a11aad07196d67a956ebe498ae6f82324f75cafbe80edaabef0037b79c3ed658d9ba1b5422c4ac053ba69bbaf7fa9db990e8b5e7f9af57a79f3e31c07611f502b3015962b02b6b425706e0a
+K = cf0544a08823ea2ad5f13716b43b154aa4bf80d6bbcafe6040ad91c3
+R = 2f38c5cf86aa0e53d1fea0e65dd03813640404b8d9a8cd6d264d9285
+S = 47603880f3d67ba1a6eabc20137dc4882e417304cb95d622177df511
+
+Msg = 7559465af5ca04c1e74deb9f8e46b0ef17de4d7a2ae0faf4e903a2998bcaa09b7f1730393320ebc57d052d2e98f5486e8e92bd1ee6bb0ffd02d69e5d4591e2fa12e4ebff8b6b9d3270fc75274f8f82e1c60edb2a21f8d5531a2380cbebb24f6457176e54769a136601a9b81da68ff196ff8cc78cf059c04ae22459cec7da89b6
+X = 6ba814fb6c1d9fe5d282008dcc9af2761d1b03eb1fd02e2499c1b509
+Y = 5bcd42e586ca180f743395fc39e2bd393820f5b4c49c7cb76921ec38bb53e864fbe809a033775f16c7f5c64872fedde6abc560488e572955edd3f9569092071e56df211564f33185dbff180e7ab2297700c64db6e220701cb8a21ead2ea809f06a16554319b2739de2aca8057a62d4caa7957a2b9f039b3c7d4fb0761a73302a6fbb583100b239d727158b4cdc9765fe0485afb6a1b0ac0db504a947f3d87faa5542c6eef7a681c5fcd28f4636360f5593bff7e433b6a338d77e3d63f6ceff69536e2a3ff77ace745b65a5160d7fbf9105a90f46ce1c54fa353c8aeebe16fb238c8ed998617b63287511208d9db3f66d503374bbda48a552d04b2c304a15bac0
+K = 70af9c79fad2b3a0677fccadd95e6f72eb8a51464e443d1e5c007f98
+R = c5d33f5a4fe2280a9b96d7a9b5530dc17cd1054bf1e8cf6f4aa3e2ac
+S = c9bf1c062bd1e86f3bd3c1ff582c33270537fa7769b9592aef12e104
+
+Msg = 1674823896c5a764c61fd19b125a7d6cd58c883d86794391477349f03616d75b6925e9dcc553dea37047f0cd153168eb26e5ad4b8fe7cc65e4fa275514c842af63507f901fd110b98249133d3d1266d2f967c85b7f88dd76c7f76b786b5572dcae68cc646e458b8278db346b2e970c7870cffd8457fbec06bbb5141575f40fde
+X = b5a607136e5dfa76645f4fee9db17bbcd260b1f6023f28474921714b
+Y = 5c34135c90f97ebc9bf1ed986eba563e32ce8c25ae7141dfefca8600ad2f3cbe8e45b4a010ae4997820a38b4888187bf207bde438a1ec7befff81a64265a4ce9900b37a38e4fc23613887b638a113ef41665ad2b1f15764cb53607d0eec303ac48c055f5aadabcfbe2c5faa85e029c43e1607a3a29f65802959b686b468e8107c466a7317b5063e038021975b2f017f1f3bad07cd0ebb487964151e4f82bb5277c35a218ec570cb568ad0404a3713ab7fcc1297b1ea9743f85ac5d5a7ec818e5f90a4a58f2c2192bba6dffecbcd39f245cc932953190ee353a0ca99dc61eac4b4f834618140c9a32eca31d718c95ee03b2992c63a683b0628883a5c222fddef0
+K = 02e860266b3b7919a3d74f37f4fa9054f62f37959ee1ce66baea3b15
+R = b1a946fa42a36d836daab56fe015c9f29c4544a4a47d482ea2d9cc5b
+S = e2905ee70a5dc099b7e0baec5566b229e9ca8e7e00840966cf56c4d5
+
+Msg = 281fd14ae2e702dbd25f77d8ba8af09fdd77b1839648ab9c880bd119d4475378fcd0d12415abb9f26bfb8e26f108b1298859235ed12e7f9e915628e3ca36c5986d18811a5905aef7878c6300a95ea87182016ec595d32e4dfc274adb47c3ed0f6c38ec893b331f7092f19b724b9fe43f0ef8dec14fb7bf8b9041b5390beb4408
+X = 272b54a77c97fdfaaadf12ee05e1279f65e8748ef873c407372aaf80
+Y = 48ed8fa89d07deb5f8ee6d38748a4e66002020f79ff22d66fa53ad913d596860d4dbcb7c3a6633cd4224a80e5e95908f87b18acc2e364c14b51de6bdda7ad8961dfda454ef4798d0f7a30ef10eae87de40867764b84bc55d7c0283f9c7cd2be08e1852487512ff43a8d1e68a951197c771f9e6c2ffdf2c00ed2163f86dff5241f9e2ff1cdb05a0b3e647e6fd23ccada83b9c5961e6e2fef3297493ddb0e990295d38405a24448e249627c0a7998cc4072dd29139c5336d9856016642992cd245c758a3031ec2807b171abaeef14c82a3dab201752351de2bffa5085c137656e469581f63f86379d62868ac3e3aa24df9826a833314bd41e0d9a0ae5680e6a4d2
+K = bc06f559baf16de28e915dd27485338abf2bd0e62cdda5b3f1ad05f5
+R = 5a77639663664e3f0b19fd583bab6e680688cd89d5e012ddcb1e06bc
+S = d41c784b583cbc525bce87c6caa44062eac847bca8b005c12ab5e554
+
+Msg = 503f2042358f7e414296ab2d41f3a1f3f11182eca6c82b2ae6ee833dd737bcb34691793e30110036ae54d403a5ea45cbf3e5515bbf80b1af139853f506792df7ff5235995e080f82b562326adaf321159adeef20388024509f225e8c5235368a7b045d69e472e6b2ad7d470a11f6aa8d4ca6c6cdb0f3ed4e06fb9a95e2cf200c
+X = c3ff27ecdb6a7de642fb2d2f9d93ccb51dd09b543a77fb2e7a22a29f
+Y = 7e514a04bb575ab93e71b3555cdbac634d475c58c1d9b4802e153a858d027804ea748c2907eb9987f78e41c6757ed5cbf102544a714699a02a9ef14768f96dbbdf48f3b2b3792efb973a7f91f260e0dea28034c915d9d5a87a8f986a15f5d6f98d7d6d35bee7e059aedb59fe595ba7da17ce0db895f3411b832a1e221a831f706587841d9323e0c7f4435703127084b20eda9c6a2497280190a2b5273b231b44482c9253501c66ef1122253be4ea3477ff6186af871869af1ba10f6a15d1c432940317d119dd761ca0342ab606d532c471783a4dcd6fac9b8a67a6bae187c7dc64c7611ded7273dc348cd7613a52d02670e877e18d0b60c8bbdd1adb04eff213
+K = ac8009b8bc2503f5a68d667696c7fbf66ebba6f88ed3db3504c0c9b6
+R = 8486ab31c8278fad0691fdd6cac2f5fd790b2f3fed52b09986766042
+S = b6967b9eacde5f4883710eba387b3c6fedfc91944ea51f6ffab72531
+
+Msg = 650c3c409a885fa6d1ac1ff41e15f9001f6cd6a152c376fd22e2851c9cbaa5350d8a92b7401030809395cf0b1a0cb03a24dc3b4347050e8553da0e61d81dee4402b1cec97d898dc6886601024f6bfbc48d2f2c40bf96de9bc0e078e440c771f74e7115ad22ba994ae2f857c7fb865ea750b18c79e7b048563becef8898ced3dd
+X = d39e52c39ea46d6ce274670d3e8a22875cb9873daf4c2ed83bd3be37
+Y = 55186de39e6a0131adb7d84170a8d36ac4bf313616e750220de356fbb1899dbaaa650d8de9a7afabf3c4dd6a3c8bac241922acbcc4bb7fa4ce5fcdb5f231cb17a8c0978c8e69fb82d44683ebb9fb17898e0ba4939196ed9980ebecabbaad7b5b34cd9ec0ea6df96243823b1d170efccb4d59bcba24ce5faad32d591ad6ece0440d2b62a212059e000fb5005abfec127c1e9fa7d3469c72b89a96976eb4702f09f9c0a0971b30dfc339072b5e3a6ce40bfea2d52f2c930a11dd655dd36ac9fad86fc3986b4871e7c90459a2eaa3b3d22dd04cb824173ccc087d429bb2a188e05d8af0ac2911c907fd957b2bb330a6f3987a595930b312053c4bdf856de7293858
+K = 78683cfccca3e13d49999e7bacccb43fa33e11547014baf66b987b83
+R = a0c49d3c47240d30d26f0c20e4508b360a841285de3fc1986f1ef9f6
+S = 97caa2b76d15b1f9f177e209004a2b1fdd23a3945034584c2c15bfa2
+
+Msg = 64129153eb9ccc74cc3aae1d5999c6e90d986be6fa40c6c4bc00b1c3f8072d10a9d8e6c314d82a7641f8a3ae29d3e7dd1942dbf0dc52b4b4b35bb67a994942aff029ca6fa18709915ff720ab8f65f231155cb1d0dbcba04fc5193afc71a5eddb4a03867e5c4bb92d37b7ef771da954ec6754d5fbe2e372b92df6a3ea8c3a4aff
+X = a7d5664e781c28f4859f5c126cbe8d87f9b2aa0027149f8b0a921d46
+Y = 23f538d4ec345faa906eff12f6c5942ac166914baf8e737dafc71e47285512ebc57ebf3ec666342abc059b0ebddb021ceaff6ef75828c7be3766257f7247a67e1408239fa4dd1caac2b7229e8c1bcfd57aeea4c04e1586764e28669c3612d8a006582cf8f82910482691c10e4113216fc24feb299f84ba58700a3bb6fdefa17a7fac9aa9bb410fe411fb294d6294396f7f627dca0452ef595dc24170c147d3863fc16e23645019aca63fcc1152b0f766f5f651c9bb699e2f5047fa1e9603972d2c7551b18f3b16c106ddd6cc2e24d2d05e79687efe655102e6bc15bc3a57f60c1a6ad20bf1cbe62052ad0947437b92b2c932af5d72775d43183bbc6f359a4df6
+K = 85adc235c0060b510825ed2b436bdf003f4d63e299e973b5ddc81fc8
+R = 3d728962aec35822fff99e1b5217d8a6264a7c608d8066f4fcc9008a
+S = ca5c8e178a14ba006e93cf4ad119f045bbf82b828767d3e583d0bd15
+
+Msg = 9fd2791c41a2ffa6df26109804eaf070122e20bbb62ecd9811551136aa956dc1c321327893a0dde6dd1d5b3a0d2a5aa97ed754e5bc066753338dddfc68eba217d2483505b0d7c0a437732f8046cf3bf5930a11efd3f6599c0f8d465fca7676ce1f39102cc0cdf13281b2c7b9cf7a7afcde681005e5a2e4e38cf82e421357a41f
+X = ddffa0c5aafa1acf98290ce6aa7a48db2ddfec48d6ea881745f2373a
+Y = 147aa8d9e4ccac906d6a5a0b65bfeb59d4d66037ad40d288d7534fc9ae33c5aa701ca18e60f0b68908280562110af7d1d1bfb538c59d9100980384ae93b77be0332a03cc567d4d634f7648a1b9fd25daf250b2869683e9426d75561a5e1787c2bab71132757dffc4b7665143e7d87d50f12d01075bef5f4b0f14cb3f109d1599e5bf94de0111a01af57e8c13f583be4dc90089619c72d22a495c45256ec787a5832d2e4c4a42f0001837a975ac8fbb8c565f77b253303b1a873306fa5cf6a5dab62d7b1ba3d70dc11b4e4f875e3edae50ee8e5178dd09a334cf9260c3e0a10911d381d7f5601c0b3f26946682018629922946dd73f81240816ae9606911cbfd6
+K = 3ee8b1f03687b9726de846f54618ac45f8e2d6e8957ce6996bf50c2d
+R = a7cc7486f47fe62fe3254ed655e1c994902d797f0d7ca93fb97df9c1
+S = 914bf7d15ce2c9ecc5ae150d6308fc557d94e1ef18c0860aa68ad48e
+
+Msg = 6b78b4de5f7526dbed08ee0ff4e43335b60cd3bc371b70cd4fd9ce45bf06508391085d142cc3891b179167c76a1350ca8ef8ce754ab1d624572e437195660f004cb7bed2ff3b0f7c7e53f853305a3821dfbaec33e220df3c3ef7a79f34e82cc8fff8415f108c000f21c3bb21a4c33267a213cb4a558e3b370d17c639247bffeb
+X = 9da093f73c714e0b9994078b6cc748a675cf4f3bbc502a23895097b3
+Y = 9147670f64aedfa246938ba77fb9c1ac271ca1091d863f32f00d5ccdebe7022d268ba9051d80fe55dfc5f64b0716c4bb8da4b11e9e283448ed8be4278e93b52d675649abb45956522f92634c92a09ac5a5d603aae2a6d04a435239538de303fc05b9ed5fcb843f0536a8ab942d9c3bdc90feed97449ce309be8ab119676a96c2a60a06692e8cd59e55e6ff8d91fa462966555526c987fc44ba420bbff768f7a7fd363638d5ce4d9ea1edd7fd399d6c65627bbc337f131c7345b3d79b4db7412562547ca2a7c8ea55ebdddd05a4b4200c72ab2b83311152b71c99306c1d3b3d446657be65e58d7cf8a062b225ce937802590546853f192a6a8c8b3ff7a62fcf80
+K = bdd792b1ece3d0ce428cc1294b9d7497208de86929a2aad2ef481557
+R = 2f85ee5c32d546c68f0aa2698beae53e2848c375517a570e0f1b5546
+S = 547667e8b13f21635a0b106d324d06c85b74a64ce9225cc5e0843581
+
+[mod = L=2048, N=224, SHA-256]
+
+P = a4c7eaab42c4c73b757770916489f17cd50725cd0a4bc4e1cf67f763b8c1de2d6dab9856baafb008f365b18a42e14dc51f350b88eca0209c5aa4fd71a7a96c765f5901c21e720570d7837bec7c76d2e49344731ca39405d0a879b9e0dcd1a8125fd130ec1e783e654b94e3002e6b629e904ab3877867720cbd54b4270a9e15cd028c7cc796f06c272a660951928fdbeb2dca061b41e932257305742ff16e2f429191d5e5f1a6ddf6e78c5d7722cff80a9c0bd5c8d7aeba8c04438992b075e307c1534c49ad380f477f5f7987dc172c161dca38dcaf3fb3846c72c9119a5299adc748951b3dce0d00d4a9013800b2008203b72465bc6a84ae059a30c4522dea57
+Q = ce89fe332b8e4eb3d1e8ddcea5d163a5bc13b63f16993755427aef43
+G = 8c465edf5a180730291e080dfc5385397a5006450dba2efe0129264fbd897bb5579ca0eab19aa278220424724b4f2a6f6ee6328432abf661380646097233505339c5519d357d7112b6eec938b85d5aa75cc2e38092f0a530acb54e50fe82c4d562fb0f3036b80b30334023ebbe6637a0010b00c7db86371168563671e1e0f028aedbd45d2d572621a609982a073e51aae27707afbeef29e2ecee84d7a6d5da382be3a35f42b6c66849202ab19d025b869d08776476d1ab981475ad2ad2f3e6fd07e30696d90a626816df60d6ca7afd7b482f942f83b45cc82933731f87faee320900f2aa3e70b1867e1430e40be67c07f9290299ef067b8b24a7515b3f992c07
+
+Msg = cec8d2843dee7cb5f9119b75562585e05c5ce2f4e6457e9bcc3c1c781ccd2c0442b6282aea610f7161dcede176e774861f7d2691be6c894ac3ebf80c0fab21e52a3e63ae0b35025762ccd6c9e1fecc7f9fe00aa55c0c3ae33ae88f66187f9598eba9f863171f3f56484625bf39d883427349b8671d9bb7d396180694e5b546ae
+X = 551595eccbb003b0bf8ddda184a59da51e459a0d28205e5592ca4cb1
+Y = 748a40237211a2d9852596e7a891f43d4eb0ee48826c9cfb336bbb68dbe5a5e16b2e1271d4d13de03644bb85ef6be523a4d4d88415bcd596ba8e0a3c4f6439e981ed013d7d9c70336febf7d420cfed02c267457bb3f3e7c82145d2af54830b942ec74a5d503e4226cd25dd75decd3f50f0a858155d7be799410836ddc559ce99e1ae513808fdaeac34843dd7258f16f67f19205f6f139251a4186da8496d5e90d3fecf8ed10be6c25ff5eb33d960c9a8f4c581c8c724ca43b761e9fdb5af66bffb9d2ebb11a6b504a1fbe4f834ecb6ac254cab513e943b9a953a7084b3305c661bfad434f6a835503c9ade7f4a57f5c965ec301ecde938ee31b4deb038af97b3
+K = 6f326546aa174b3d319ef7331ec8dfd363dd78ae583a920165ff7e54
+R = 9c5fa46879ddaf5c14f07dfb5320715f67a6fec179e3ad53342fb6d1
+S = c3e17e7b3c4d0ac8d49f4dd0f04c16a094f42da0afcc6c90f5f1bbc8
+
+Msg = f3bb27bf9d412f13229a56d2d1533eae63f40004c143c6b92f6e606d263dd2da7581e5eb20b6cd021e3ab63b498abafce01b4ad7ac8628f7a1849c4e454f1168ae97adfab1fadbd313fca7381726f5045752dabaad6ea3250d303a5496bba2fa4895ae49f06a9aa6451ae70cf33b5f06fa17cac0144f28bd19fb2ac041a578ed
+X = 027d0171598e7ecf23f2922d0257e604291cefa77b5cfaf1b3e31ac4
+Y = 00c7aabe30fa4c3d1ba85e7ae0aae79360e5eab3041bcaaa5d321c92f3471e4194c10484cff152bade6b7d619cf286773475298f883efdf64c08b692583de31be0a4e2b8e8d508ec145c65a369ce6195446c52d02372eba562f9a9d7cb24d2ec3b0a1ab833e4d7623b0455a41eec759d07a3c8a20d88a926408c20f1675601be53cffd65617b66fd4eb353a1f2db31f66343b07faf60de0b6a680809c6166adbf5e504c5c61babb84be72c02d3ebeee066d9eab0d0ecdfe01b8ccd6728ee9123b9d21154b2bc9a134363566402291ac8a484ee32eb884046d40fde7cabbf51d1d1206df1c5ecf290ab7ea72abb5bd3be8d91c02bb63f809718ba1d380af88331
+K = 7494772f199ab7a7e9a248f6c2df918c9da62dc2d4176b7db9419b37
+R = 79a6aed73ce177ed3581f5d181a77f000d6358514ea95cb0388a6add
+S = 2b8597a694564e267b6f250a4c76361f8cdf49863a7902afa48fd6d8
+
+Msg = e714c01631704e9447390f5c315c9615a7a52863b143706583f661595c505aec477eeb5ad6d640ca812ce11750b67bc8bede2e4f9618dbe7376cab6231b21248ec914ae182df8753362d2118a65e66f64018810804ad97fcc1a87b8c9f349d1001e4b09b046991e6abe6338fbef7be48f1c80c350d2962eb6b8fce25b69f8dc9
+X = 6911c21a3da88d54ff9ab58ae2075a2affa3f3eb656978ea26bfa702
+Y = 04d301f001821b03c91394c520839ab6aaa95325c108a02dad9db48b3c8033d6443bcbf05045230ca88aaf98a8c4cb6b095b352d91b4c416f632fab49d45ac90699a5a419630a81d473bc89122eb5bacb91c40caa4e4bcc476f3ca77bf6a21037a06be24f11c645b0c21b857fdc5c04fbbf0a26efc569cdbb0ea989ba0e037c23f22b0c5f1643d77d98f2de248ccc36672d397d30c1c5e1319fc7e5842ae1a9fcd9e96fe890a74ddee91a39ce732e4c0eaf7094b53b7b409303860b0b4944cc81b4a42d40538cfe512b9680e0a281b1fbbf639139e8066ad638cf846c9ea51fb4c4ef84921f16a6ca3f2bd158157c551739c9d023e270b3de7c2f1d7683cf809
+K = bfb79665f7d6df843d2c39357173e415724c83e1a10932efb9e22676
+R = 790b4dcae31fe45cd3a7bb6fa10dcf9ede1f067123f93baad7edb489
+S = 71e3e46dfe040496ce4c5e490f6944a23cd5e66ce9b4d9acbe4130ce
+
+Msg = 3f6e482fd484ed3d07f1d0761f2d60fc96d46eb0ecd10a59dd4f392e3d3b2cbe184010e132685578b1f6303239798a5303a81169d4f52fba0d20a42834de293e3a7b32848b65dd308eef5350d633297465425b7b1595ffc8ea7b125896f89e2844561635f52ec62fab2ecfea288d23f0a771cd6311806103135172cf9fef1455
+X = 20328083aa86511140324fd0357067a1d6abfc316e77fe3d260f0ef2
+Y = 9fc1b292ebe15531579f35dda8d706bee0da857cd696a10af770dc356232736cf893f7411a9d2718b39f388118d177cd8d0fd7ca3b3c220f3aa743d8b167219d3c2c783e1f09d8b8df8ec7e17578c5329488c87a89678d2818a99366b785d53f6ca6995e193ba5ca26c00b849f9027ca5df5bb7ec87fe78735ae880f1a97dabc3ca7985d8cbc81be824c1ffb953f1096bf926226fb5e9d4ad43e9363da5e6b738c9a2f951ab3294e2b2822cf5282bb4134158aa90ab9c8f0f64d05a0d625a75bc2d6a4ae3dd11fc05ede7b6647ae7c0750ddb273fe5f8828318a91db3172ad59166aacf2da4f3704d169ebc860d9e1c6464abc2b653013774d29375b77bac1ec
+K = 8f4398bb9fe1b393c1d90a62e178899261fa0501c98bd9a8178b364c
+R = 3b5d8034c4b8ad9701bf29b10006db69d017fde8638079dd7bbface7
+S = cde01df54a66cef3c0538648525b250cb1f08707f5ff114bdebff8f7
+
+Msg = 31a278f881fdd375565c0f28ff7575f216110486d6fe08dae8fd072950978bdff601ded1ef226b5d904c47f7142a8f4665e03efe5870da2dd1ab80e449f5c757b3b6996a9dc0b5b2750b97bbad2f553fbaff2aedecfc9ff6a970d156e4fe3852979dc913bdb296a321f766367239de45e47cbef4d79bfa3d576887c65f7f8a60
+X = b75ee80c896b42148eeb7d185d45f5872a3758e983b4fdd8c2e71ca0
+Y = 7ec0a5418828159e3ec829f793b96ea3460328dea21ba157d71ac306f9bcde617db67368d592bf46d46918b130fc7e3d1189eeb7996d5f660ace30be509a26b218d865d9e56ba7f61942e567d8cdab96a78ca303c6b01d989b1e78ae956423e35b5a466c16074e0bc9e8372340d2c12516c22d5e1ff65abd5d448215b6baf565de18201c1fd5ba3de87e5d5b437d2f48deee72a12e655f8c7fa313d24bd0c8c20e59c90edfbf5dfc057c6b679850ae41826178f2f304ca3b92a9bac31ab3cf74dfb8ee5b643b4a341ebbdb5dbd24d0b782c5b450596abfc3df9ee05f45d0ea2e8ff4357cd3605f3506ce58a5394f1f2444c26359299af153532bc90daaf954ae
+K = ba98b478a9e12a1d03b6aca65c0acb265764357cca67d04d782fded9
+R = 2b47e257bf72adf34d618d3a6c46142881bdd0689a46f1cb3199ee6c
+S = cc1ff2fa3755a0e81edfc753bcf14e637413eaee0f22d7886b058dcc
+
+Msg = a6d76047bd18deefe70dc0a4bd082a10fa521dffda782a9364b9e2b11e147e1a36a11c4300672144d9b974132b4975f27ea6e8e46b55aedd6723e53e7bc9b40dce2449285a690885c3223b636cb5c4873c5ddaebb0b6dc5b69438d881a525905a51bdb97b051dbfec6dd4a7b580297b08f2ba60f2ead3a07531cf299977413af
+X = 1c0e4c78a4ad4f5046f929e7cd3db3f48b86e5eab4a5e2be61a08dfe
+Y = 8b2662775bb7f19252204594a84b469f3dc8d66eb7993bed122d8a065f59ea81d4c484cee5bd766a5c137dd57e43e941339852150509acbde6f7957a1b04ece718565ce8b637ea031bfa3410a580744b3d4959a5e75e315dd33c02b52c7c56218b7cdfdc24f51ddb4e7849faf289cf806c4d3c6b877c63dbfab569920a2b219c39215c5e3e638a3ebeebfb52c8b38e8285a85d625fc1b42fbf0e518c58eb8f45fa54676ed8b009415d2696ee9b5153dddc5eebef49cc7659810a98d4b5e8b9695fb2d9e4bf192093747c878a9565b47cba053c48ba7c0b9b1ce77f8a3e1043e87fcc6132cbe8fad7c738e9bf79bccb414ef24907675ba7cb059a8389eee7ebbe
+K = 5135933094326e3953250a29d5f5c4c9a1033ccb844ab35a14c19d31
+R = b8674d1ba6f13398f5e8944b82150d9e9bc9b210a81495b335947e64
+S = 75fcfe96926186efa12c007c0985205147cf65abd108363d8b891190
+
+Msg = f0d5b33327695536e351b37cd3feea693f10377a5f8bdd913402c2ed67a0fc1e7bcaab002fa779935950c76e42a491a68fa6fe445cd35575cfce5f376c29c4e8c0fed5a5487ef418b96fa5752a033ad07959653d1b8af6702dcce40efef21b2d64cf06bd8b03dadb2fdaaa73fb2d3d75b0985e9aefa1f94442a5491ae46d7c51
+X = 269055de62d0742324803624522e678234c3600ae7bc3996c8d17bc9
+Y = a448b0d448249a0e54a94586882985a08e19972281d10d9e7fb57f95dfeebf971f6d9dfe88dbd0a4950f528200be7b605865eefd8ec274ac53e4ed5b288c6a00721e028881b9725fb0a9ce4153dcc1fe7b5ce7259f16ea8b32456cb03bae81be77f3f6e8b39f52587bc9dd47a264278d5d8ecbe1ba574269696a7bb1e167a3ae7110ec057f4291a1bae8257d69c10ae095f3271621c6d6b5607925c3498189d751b7c9bf30e65683cb39fb51bd592f1f98279f2e7b2b53ad546816a8508c93f03496de7c47165f5cf297687ad7d60f010ab9faad0153432ec1ccdf26d4f441df625394e2104208bb675e7f972b6c66ed7028a1e3f45a671ab2716c60feabcc22
+K = 0d9d0b3e1f24cbb18320f9ce896cfca2a5a6bb28ceec83e1ff3218d3
+R = 01a4f4bc633ebf842a28d045184d250529920df280545cba00501cad
+S = 09fceb2df200b7c0a56ae7969f5473b7a1f6b703f743f954a4fbdbe3
+
+Msg = f58e039d666ef064cccc7ed015017c68393d1455300d0c4fd4f0d302c43a0022363a7cb01bf0673d325293bd50b27f8187d88ee2b553b159a97d15ac543421446c2aec39566315211b9b4108cacf9085dacdb4de94bce84097c0892b1cc65f2e10d74e5293a04a837b616d4181f3fe4caa4cc2e744916e770ff0ab1368c86cfc
+X = 3752b20033843d1ea4f48018bede79f39c15de33df64140259aebb82
+Y = 4052534a7726cbe17e34555648e5f297b963f22d3aca249785ad932f6ea1fb5df31d379b68522f8eebedfc9b5c5277e91574fa79ecf03780cc44351f3e3bfa1a0587c88d0e04e0a02cd1ee9ae210b3c9aacc65c71cf1b86463367e2be25ccadd9d5a4d1fcbd58772f7a117f3673c76ee2a8d93446ffd7cda7f8430490502c16b1a5022e12a3a95a7a9f20e98d3b285abe30e8de42a11c517c14ef3b6e5b6c47114a961d858c6875561c7d5d21b7c93f373cb330800728ea188b2578a6df34772a7acddb829c09b3acf9bc5b06140b9b035267a40e86c1af5577b3d02a89b20a46573c87500a2ebed4b00b1fb13a86f143e356702d791379a90dfcc26b80719ad
+K = 1220ac99b9124f1dc2212ade5691fd330d6d868f3e90694236d44b70
+R = 31fde5f22ebb426f256b175057a76125c40136974ad58e681ec2c4a9
+S = 77b0614dd99acbbf4c43aa926b3f0be1cd52d52775f22a408c4e0304
+
+Msg = 1477aa0b9f1b199b6aa0931d4d3f766d80a3af10c9ff7315391f15edc4e92632f9d4d21a8033215d5e99cff170d9888f020b0db0e5b97e123a2889898c5b0ef7c832d028afd5e385004531ff9989797c3bd954b1ac729066577667567884cd4bc5d055a3f645583d29cf4758507c883c5bbfa74444b9c5b9b495072c3261b6ec
+X = 83770784916227ab2a73edaac5a95f7538fd94f89650841d79a37d7a
+Y = 4675f19b0095faf8ec96888e483f3a0aa675f5b425910765069ab57c97a12b7c506437c8757fef54ecc6d310921d7159ff39f2f1cd9535b64f27f136913715775a238fbe01237e181adebe551ffe5d21e3c35774e7ade8c79df741c52dabd8be4782ee5a3b607a39d1b455dc848301847312980566f55eba080621e3c123142a1a2074e2e39f6c0630b36831f074869d46a68429f62573cd2c671726131fbfd566a6d07193db4f367802d7de8f4e830aa878ee2cdfb86d8537746b71c70fbcb6a1fad66213d6fbea68241eb9f617478adcc9faaab26cf81b912089da0c4b187b496a17d886cef571e393d6f1f857ebf517c801f9231e95db661e8cb2095456a3
+K = 6406035023c5e150e8758baeb00a9b858ebd0e4090334c69e2fd2377
+R = a2380b5ece76672669e26187a17da45ad89de1726c826e57378af707
+S = 9cc26c3456c0a409f4cc98c83ea5176eb293ec7157e51370726429ce
+
+Msg = fc82372566ef2c626b2145549a5db973118dff4c6d1d7c4a2e16ecc31b43c14ad3683173535b0b82331f15a183e6a50200fd1e88ff903ecfc50bdd4f5875e264a4499eadbdaf807f974f8d8104477a0e4d30463dfc61cdac5bf44eab96c770a7db912eee2db248cdd2b9b36211f93870beae6bdf8e0aed0097519ecde3470cdd
+X = 8d2855e4ea3e5085a5c145e324e5d5a5f8f23756284669279728ec9c
+Y = 3884ab23ab93d9d1b716712c8daa080b26af01657f0dab715ebe6bd766deca7612bea6a4cf1ff7d08abb2d4442ac0eaab01e68570bdcc222f84bc3dd6d8c5490132d1c36e23913f00d11c803b703a69a51a1b475f56db00fca47d234aac307b9e798e9fd891dff9c1257bee556314b021fbf93f75ed8c43433afa715b82d5ec6af8ef9471e9b02f9554ed7957c1f46d8db35a5921f4a83727f754e82b6ffa6d1b82595220876d22e18fbafa5333b26c2cfd47d894aaa7164a2630294d0a385fc8a8cf57d10ed0fc53f21f1fd6b4c27e9c69e65a288444619a3c248bcc44ec25605028325243274d72100edf560cd382babee1ca532b7f06a4388f181dbbb5db5
+K = 5cc12f090fd965c719efa2ee907a43b3643ca8f9ef7c537adcb09189
+R = 5461b20704453b6c51837f7b9ef5836131b501f2539145ca3481e6af
+S = b65f69d291ffae2d16e3108d69aeb01b4f9202afa01382e53dea4d54
+
+Msg = e66aad54048bececa5682644d5274c18068363e968e37e6c11c1f8a0d7e320578514e1874e9d4eaf1bd02da6b722ed22acfca48c3acb670a6f9ee62e3aa71deb18097508f431b05214c199c166fa42cd6a0797bc7b4d1a2f330cb62c2c95182fef0d06862542845e430d778c82076387adad4355c258e6c543cd656fe3cd2332
+X = 2c984e8464cf5716053520b6a72c69798b9eec1e115b0a1e30e2e44e
+Y = 06245bc509b4955440b0e401710ddb2c4ea2e559598361a3666c4ab12e766b439f21b953962f6ef5a11dbee5677ab7f8906d8b325180ef4e45d05c1294fce5dcaf6360f71b10b70556f306993d295b695ffe5729c5c5bbb6cb4834ad037bd8364a12c992c2598e8ee6beb1606ebc0ac0ff00c0ea2eb8aed75dca01a890085a400ebf993e5879382ff91abf1be2ceedd1fc4a874342b77b6c55ffe7f676a1c95ee4ecc32358a080c92361cfcd2e3426f78c217ae29556709ed029b287e71feae0608cf3938857040d7f06b0f91b3b4da8929df4b5698e734a37316879c308a81c096b723bf2089910d5ab30b8eff38858aff6ecf764e268ed698b70e8fb7f3c66
+K = b20370d79e097e7c65e956d76aea1e288b668dacb8e7944aba5fbadd
+R = 86d5bac3aeee9b501f91f2fa71b1066760df2e0ee147383f145bb0d3
+S = 8d6a207802d6fd6e534e1b8a1edb997b7cc9a25a97a9e4b6eebd0e23
+
+Msg = c85747cdd2ac9da0999b7e5d7f64d11dce7673df5bc605051316b4b94bc7fc776fb1d3da5a4395a674aa8a0798a341b31b11e63cdfac5f854346f6a4b74b49f2d089cbb86fae54ebfd95eb9f05a1b5e84306e930461ad7f827cfb910014a3af4dae0d46ece912bc26870a433f70f0a38bf23b15d98cc658848f4bad9c84e89f0
+X = 4076f4abf4d3c9a55b3f063535f6a69c221199581e72c5a8c31f1a71
+Y = 2972787dcbd67e5bddaaf1bd3f05ebd66949601dda44237ec9361591ce9b809f8722fb399e6b9b8109a79ea7b83fe98359a07a27e232cdea8f6533e34e37db3ae53309f62f108b2ee7b489a933e4ef58dd4db8c0108a3670c675b98b75798ac0884cf5a461af281f6dd8e7ea3d41396f049601a9af2e39088ae0a1ec0d2d10fae1dc1de962d84d8cf04215fc6d6262ac432541af2c48c09cd4e15bd9460e9a7bae17e0035af0b13d8de707870c54bc851112f4ae1d69074712c212bc7e13f199ffc8f37723cd6dcf539f8df8cf0cf1ed4c10eeaf0f444804f1eb9d9c329d6f19973eec273222fa04b5f1f0e17971ce399869582027b1c454dc1addd484902cb0
+K = 7149f49e3d07c45c97db09632740560e5b0e843240255da43ae97ec1
+R = 28e3dd71098ff04d1ca885c2774f78ecb3ecea708fab2e16bd5cece1
+S = ac8b6ee498ee383e28404ba4b53e64aca0fcd26790713264fe3cf6a1
+
+Msg = a7a59da62a9391cfe628697548b05f8af39ea9821d76c314478e210fbcd27fbf6b0bf460a65dbcbadcddfc0178ece135264a7d7c5b7053208bfbde54e3338d901927e95e1dc8eeb73d299e6fa6584555cfeafd1925e95e0b3558ddec641175fc7293c0310266ace18bbb16f9084fd4ac22ad2dc8528c3f3f332684039e74b390
+X = 22fdd44afd372e15842413c0829c9a894ce61a3f0b135c1546f57fb0
+Y = 0aa040bbb23c337d58874d95efe9277080862ea0888d9209ecc2f5d7e0d56b3e8444ca933800450f10b8124ff8812f87e1becf1a317ace0c3a1376d624938cab617bb546d0aad4f1d0aa23c6670cfae0da28660393a90911b3dbe3847eab4ebb7dd0504aeb0269126655d135d2e9149cd8ac5221151640914d480569b383e98364cc41cec56ea157ce8d7e73a949b348e5ffd3ceefea7f7625f599aa9afe2db4cf3b0d59f2700f6cecc54f8bf7853892f07337dbe76be781994ef4e14df2f0cf7cb342ee1c8b188a7dcc317a097c9f9e33ff89462c26465bb53eec05d1085fc6156cad0f7c9b80d2a68953501a97acb746ac3a2b9bdcf18dfceaa196716ec773
+K = b93120b594e8994f533c1811d61495f2ebf32fde9e7ecec856033f20
+R = 84934f3f56d64815fc66b0dbf3b1fa56d1387be7611a1e571c405100
+S = 431f11346950e77c9e9ed0127c50bf620f6f69a699cd017c7d87368a
+
+Msg = d4c5b439a1ccf5d98cf0b931f253f733037921d4efb02cf87b2509e732a56ccb49e0c83b1409cc009f1d2d1cb4c0c7ab00c402ee018ec5098031ac9e7197d4395d491721708a41ff5cda5a03be6a1169bf459470b1aaf53c8a9668acae1385b921f5a26c73365444515c3c126c6940b4bf57591a0bfd6c2c74c724426cb2ad3f
+X = c9ed82462158cc9c99231fd48a81e4f8318a88735c35b9f2c08ad280
+Y = 37c5f029816322da5161c4e20dc4f5abde9f04f5f9dff5d581b253109191b38424dde75febac32d6ce31b116063494a70c5c1d9d8b7351252ed377ea38fbe85b9f614eca1346bff65345d57e646bfb032e9befa9e6e5a89c16d715420e24129b6f70e4f681bc1d38ad1737db79655d244b4d67ad3d2bd80fd9d80c2e15240214859fdc0b6c43dd1e805dcdd2a5b9781397bd4a4e8bc4d6f9a1664036e90cac550e83d6641367613707d0de4f2dee55e9a5be6d3de893d61561f4ba90d387b7ab48801086016c842f3e0ce60e6b46aa980191cba147407aa4ccbe19b00b0ac71648d5296d13e48c75d52848bbd39f1ded988c3616faaf64f91a30742506316893
+K = 9f1fc151bcf8fe18bde1ac505737dc6868c34be605bf2ead6ae3294b
+R = 1b51b8d2d3eeb3d6218da3494714d0e88cd7366f387e6ede00f653e0
+S = 844203a81fb38f57505bf83bc8c1da002a39e81abbdd2f99ab6a4d65
+
+Msg = 40d4d9736b54993c1bcee7071c682390d34d47c35f177939ca5b70f457b3458fd5eca4cb03f0efe1aec10bf794b841216056a155dab58a3dbfc19ddf05d45861bae6eea2bd7ffb87a6fd0fd2394e847dc36c94c81561dee120779bbecbc32206327febaa17c96505ecb97d560c934c386f6f766a2f5154f545f22181c19fc698
+X = 5a050bfae63d347d64379ad01441b0ef9ab06ec5842c952f7a1c29ce
+Y = 24aa1c7c6a041f6d2c533006cebcc2ad048b3dc08fa86282f5879a237231d230cd854aa10158cebb45f387923fada8c5f4b91a7bc2dc3e2c39463797e6eb1958abc9b9e748bbfe80e360233e96952279959a6b80619100f6f1876fadeb790491462f5917da36cea3793c44db90908cb9da18f696ced90f2acb826355104c4c8f06c737d48acf985d6b8c2abf31807282b6e651d2967a16907be3d8e4b7f32ed34eba8c262d6c0ecb131946d2546362c217ae195d05656a4fcfac73717ae85a571d811cbc99e0b3124bba767fead605266d99021cdd8cb4c081bef102431007ee12523b48bb838698a5971e517252d6d93e1c7fe9fbe07bf434164baaa1026da4
+K = 5de3d5e6b78c888ba4185c1547272fe562b44e507c871a0524765aea
+R = 325aa7b173cac96d5865aa50ea54e5df45a10e72fd5dd1fb265aae09
+S = 0a7203f6b8fbf668b8f6435e929fd52f52e23ad4b8a156ae5f3c9c47
+
+[mod = L=2048, N=224, SHA-384]
+
+P = a6bb5333ce343c31c9b2c878ab91eef2fdea35c6db0e716762bfc0d436d87506e865a4d2c8cfbbd626ce8bfe64563ca5686cd8cf081490f02445b289087982495fb69976b10242d6d50fc23b4dbdb0bef78305d9a4d05d9eae65d87a893eaf397e04e39baa85a26c8ffbdef1233287b5f5b6ef6a90f27a69481a932ee47b18d5d27eb107ffb05025e646e8876b5cb567fec1dd35835d42082198531fafbe5ae280c575a1fb0e62e9b3ca37e197ad96d9dde1f33f2cec7d27deae261c83ee8e2002af7eb6e82f6a14796af037577a1032bbc709129caabd8addf870ae2d0595c8fdb37155748f0dea34b44d4f82ed58c2f5b1b8481662ac53473c693410082fbd
+Q = 8c3ee5bd9a2aaf068bd5845bd55ecf27417055307577bbc3770ec68b
+G = 43b5a6b6d0bb962ec9766a377c32cc4124f1311188c2ecf95c0cd4a4fa097225b7618cb1276c474578d3bf564c145199c092a1b14baa929c2f3f0f36e0c2dae91eba08be30992a889f2952e0442c37af484a4ecdc3243ccfcb9e3413cf5cdd6630b09fe17efbfde14d8725493019b7b73d1f782b48ef30bec36e00e02ba336d2254fc202a69612cd9446f91d76b739ffa6d8b86052f8dc5f1145801c56241af5ba9037241bd89e6338b58e01310671c268eb5e33acb57d1f99f16440a675827d4017754d601a17ada2fbedf904554a90b01530da8c93cd14ce293cb2bd3e7937e934b79e310fe4d80c13f92f63381355bd80a1abee1a73fdfb6da24ef28002a3
+
+Msg = df5d564db83592c1128be5d29b7036880d55e834a291a745ed8dcd438c4da6b1b9f39412b2c5110730db83c1ccdfe9059dd96ec7ea2bbcb34e3eba72ef0a1d4721c7c0221e29279f014d63facc5bc8f18c539b92ff2af89e568225d6b4cf599cb3dff5e3c6ddfac0a27f10f636ec220abb72630bae9a39c18fd3663e4651ccac
+X = 4efa5136eb6aa74e92bbfc913b0bfebb613db7a47221fb7b64f42e6f
+Y = 647979b7960ce7b971ff0e5f6435f42a41b18c9de09a301114a013a7cd01183f176f88838379dcb4efb67daea79def3f042cbcf9cc503b4c2151a2364f7c9437b19643e67e24a36bac4a4cfa293deedf8ec6b154a32aa72985f7d8de235334b546c29def458c55d0c5c0ac5d74e2024ec7d4abc2fda516a2a0b1a4d886ad92c204707828a4fc7794f60ee8a4be1101c9e5518f7e19eebd475f2de6f6ba89c28bd129f13993befe5818440319a79549833196342a31dbaf7d79497dec65ee7dbef70e58f99d0595f6a711409ade3151d45563d53c1cd0a8ab1a18beff6502cbb0c069b114ea7be77898d0f4e549991ba0b368971b1072ece4afc380e9ae329a50
+K = 7e0f1ce21d185ae65c0a00395567ea9cf217462b58b9c89c4e5ff9cf
+R = 5ab43ede66a15688146d1f4cd7164702c0c4457bd4fddebac0482953
+S = 6c58e8ab27d28512c46063c96bf5bceb8fbad232d8f5b39c4755d0b1
+
+Msg = ebeb9e2b692ec6c9afad2a0c2b908939943fdf4bb7438e3bd9288e7681984087ffdcf86502079c291236d7f1adb504e67e0f88bee61b61717014cf06b5fad5cb36f1b223b63912cdcd2b9416524d37f5d7b05c37d1789669e141aff6670db2e0de31673b2055f6799ac887937e5664a659ea0254a8d4ba6f204df2a38c2a77e4
+X = 1c84c5c065ff165a0e1d276c2ea9fdbf8423c12aa1c73844d6c64942
+Y = 31d31a5bb82874bdc76cabae3ec85690aa5103cacbe5234e0d5ef645eef380d3ae2f6239144b82b101a7ef4744aadb8fc98e82b41372e99d6c905ca974b81c9fa521f920a1dffab4e2ee15f61e03b742f42470dc2fa9ab257f1136f9fe4b5aa2ece5207230c4906d67a156a3ffef470cbf3a65e3189b389ddc66c6040a7995c68ae1df2085941b5b1df7d957fbcf366824e0291df88eae55d8d3040d8d09f4f6ffee34ccbd1961852a5a62b26c8daaaa56a8ff7fa863b63c6d604fd3378262e815f55171dca35d04761fe3d9eddc6d32657a96d643d4608ef2143b19f1c9d8c00ed265471b245b60f31f8c7ed48dd6b18b5bec1a6ede145dea40283230724ec8
+K = 6f399d636570476f7a2013efdc74a1bb75f5b35ce835079c4e19cc4d
+R = 82c3747a0658df006a7a205a6ae2aedd5d2948488559fc3cfd643a64
+S = 8636796df622d13f070fbed4184c8138358c21db30c606b8f9be521a
+
+Msg = dbd2516b03fdc58b32c0233080ffeea41c0d9c156b30332ec42be5e10584be3e3db85ffd5b5bae16fc876a0c9217627d84011223fab57d176def61e40d912e7eeb2bf868734ae8f276a96ab13de558ec42614167c5aa4c60357f71fac58980e579440f69968d2280bc970d0066b5bd6a6f5002481510256b3eb21bbb92ef2cdd
+X = 383585098edd867a8522dfad08997095aa23539b9c816a5e28359b51
+Y = 6e6ee0319af8fafd7ae02013f4227e266244ae5d87fe156cefd4518bcd71aa73f9364bff35d4d23d45b0f47dfe93a607d9f8b399b424ba75072fdced6c3ed2110606fa48ed633faef2064fb336069eec7ebd8ae475978389e6e433d5a435d6529a66c489ce153940d2b1b8c886c8110d8b0aeb641a40e285d6751ce71027c30ec62f4b1fc14f4da20b1d505742cada201cea81930c381f8a6f13dd0a42aac1e0bd7fcd19c6bdd170fac6a423767b831c1e289e0a29ef85d817ad238d91ac3ace2f40a163b0a9bbddc6f05d0bdcd8cc274a74d0743c9fb56556ec1cb8e9cba982c15a9a66fa6b6999b8485db1a86ee18be16e068e12a8a165e3599df96669a1b7
+K = 0183d11f1597ec9db32db21c1e910fa2be2f276f35d0583ce8b8f6ab
+R = 040405136a1220adbb64ab751db3307fafad5447ab2d9bcc52f79be3
+S = 1d35f3269c77c577243f1db8dfdbc4cc4531574276f0da1f7a44acd4
+
+Msg = 34c45435d0cc29269272a93d43320698e454a7c287db9d062092acacd7ca086455e583baee1276caba068fdeeb52183396d5444c5a14ad52a5c2bc082cd87452aa8f9b23056b5f8af2638d965ef4fe6e4e68e88b0f50e01248fe6a6a1d9d6d93b03cd55d16fd83cd4e06763d926f7c50f20f0ed6730613f0f4db571e22d288e4
+X = 0f115fc7073262e2f93a9d46b407b0f1bc29292aa09cd1a98a34a219
+Y = 5ebd8152935ff2a3f9a61b275e9808a041aad5650f593f612af33bc462b8c994169372e8f80f51b15f5ce966ea3e76a912c653978337e962219e323b6e922dea4bcc23c646a22eecde02433126fbace0e3a01fa6d0b9fdea9245d67899a7b745b8847c8087fa7f6c0f3edafab4c3b47220821fe46f1bcb00a323dff3dee47ee1de2ece44e1fdf3e64aa20c9e6b58e534482e7313dace1c617d8ea9a65dd51fd33024f735c3844c5c6b4a3f447e714ab0c17dc88e33f08b142b72e811e6da00299c82898aaf2bed5ae5170c1dd005678d2b576b9ce3e6bc6b2aeb04c9f04e444e2a9808405ff5926548b59304dddca8972631f7fb136808e213ecd93af98e2e54
+K = 835a744aa418a297b7e11febe7f3bba590752e58fa1ae12ffa3bfacc
+R = 66481f241f6b443148f0b1f2459be5ca16413d947d0981628717c108
+S = 2cdaa73500d0ad291252d07ceff9cfeab87a739752291eb5dcefea87
+
+Msg = d7ac5cc8a4c3f38cfe5c0e1068ea28f0f95d3250d1aeae5f66bdc4d22e23e246ff30429cbcbad3b02a62a0a179d4d107130fa3a780c0092c329c2b026e12e6735a75c495b097aa69ebe98a96ff891234ff379511149e07c6e2411e58976ee93fba7d3d570c911f6f208375783ff5d947a3af0c839d210a8e4a8c8fa41efbc57e
+X = 5339ec1f86a0dfd81324fca6a0d3e102b12fba8fe8c1bca45d8ddf10
+Y = 7b5fb022b55fb61f8ef8cdbfee46c0fc61e59fc62dee5c14d0c3134b4f2659112e3f4e7017f9574a2724188ba6a1ce777a8915bc1171d738754b5ac1df923103ad7b198511ed36272668ae0c2e3142ba011cb45f893ddbf7b38625818cba9a9b78aef8d06007ed505e6dd6e20c92d2500234f104c1283f7c00cf2a3a32458d97f7bd17090f76235c6c4f8ae194d52d67c74a854973fd124751f7f5804b67879b023bb6eeac76e96fe676daebbcb1bc94d5d851d7bc56bfb3d2a0a6d992313786d9fb38ad29b762349451d149d0e5fde6ad497183e352828e251bcc7c3a918be4d03b17af60f3f3ef6d9fb2455df7e8b6b169475e5f89db9908541b567d0f299b
+K = 7c62eb8fd725a453fdb2d1e75bbe22f0c5d27a5835135c788061ddfb
+R = 5b6be6bad725afa442f29ab7d343d2f8b4b4941cbd23d69164b3c5fd
+S = 3a1b94634e313fc4df8292e038c6e876336cef88d691b894c0eccd3f
+
+Msg = 7a96873f0777e8ada9867532ae5f51938bae2d56fb471e0fefa693b71a2aea2571c0108ba59e634401bbaf20a848ad8c305848420cee654a3040007f055d4e975807894b5618b9392363bc7f8c88d526bc491adbd892a93751a21d137ceede8a04423a4d0ca1557bcf334e4f855b04474544212929a81dc71fb3fc41f70d6b18
+X = 494b68624728aaae9898c3ca22c1bce810a052e25c881a185af43cd1
+Y = 0531518177087dff8d04a0666c1301a9b38427c2ea1b162e6fca520181ef22a2d205ceffffb1549c9707805560c6c4b31943d52556bf301c5e0e75924fbe6b5c362fc9801753e630433a9a348f53e62c0746b26e348dfb85853d1ef6eca02cf3f343e77c1769ffc1c109b88ecea16ab6cf476e54312500983622df41e695ec27a41ca7a63121ba97bee7b0e9d547bf420f647d0f8671bf4107a712a7dbc1af3aa8d15b98548d3909f72b9a27f81c46e3defa95eaff7590c626b9ba10974ae8b9f58535d09ca30f9f523539cf584f9bc6c74185c2ff12504f5598ffde6f86021ae514562fed3881197fca22db5590fcf9522ef760ed0e3631a6bd79f29000b42b
+K = 065a3ebed489d78ad676afb5373c7028f843816fa97c30169149897f
+R = 76bd6ff4cdc4fe37f6705e77efdcac6fbb9d54fc0b220643c662acbf
+S = 8a124a3640ad73280f305afc2bc3e57f7a2e074081be7bc90b5b1faa
+
+Msg = d69694bf9a93ac0cc3915973d40e351247c3bcaca98069cd9c1e7a3c5850636a592ea75fae7bfd38b1290e3f4d0aae8ee689ce4137ea868aaebb17dafb255c4a20e0fac1f4666612f90c46320a62002ede3167a34dff74a306a0842427cb9d2c61599b05c67b673144f6c08232d771f2e0af38253f36e122870e04ebc54a512f
+X = 044b1bcb76db64ab7500741f43989d3d878991788947b679bf22c088
+Y = 9c588b76269b2f087f7e7af4ec4c0ef263e9636f45e73e604502d62fae90a25101bc2bad2a002127d4b60f5c4a1388880cade9463ab5f7997d54a02c24e7d51a4b8a7d91cdf6afca2b433768094533a0de08dec1f19eccb46df1800f53d3dfeefbfb769a80e1686e8d53c60e8c1511a6dd4f42a155bd85f75740bcbb7b1127591822926d1682982375ea5ec29fd1ef4f283b94e02423a830b35e973caf12377ee18d2c6ee7771184d7a94e7a0c4a01044afc4efb2ffecb695e233aeb80c516c77d1c730d30d1aa4f39da51bcc48f44d07abfbe75f228abec2e7273593c98f323a9b003562a168752e837a1232f462a23d3b185ea8a05361570455aadd1037063
+K = 4707e611f7d2dbb66f5ff083bab786a525884b49390213300b088fde
+R = 108a082d2bf6358a737465624320c4fa9d3719744c2db69d18963d75
+S = 420f3537fa6858657db7a21e72e11ec0ec8cc85a09a0d1a445944980
+
+Msg = 17455bfbb128df0f96544bbf83ca0ff374bc086b2de18f74f59049f73eff3c8ef32a48429a4038256304636f3032192795ba2807407ef52b8d59b40bfd517583f998810279c0211771d9e54f2b84e898f9892ef77beba33ff31a2868693f1f0978b89895e350d5ded259fb1397e9c6989986452a0d77df99048fff84b6eb150e
+X = 2bca3c613be53a6aab121de91db4fa06b468fc6550c82eeec4bce9b1
+Y = 850c0fcac073c56318a92104654e6a8ae7678fc4014728304649bf1070277706fbd32ea4d41f77f80a80c88f2701e3665be73f59f914a915d66b411bb05ae5c18b00bc216251399732fdc2a68be6a21b3b088797416ae05ce876b6802e4f941a21b1c661e3f06d501ef2a17659f088d2195dd161f06404487a27b79df1ec574ac3abc30ece2a1428c5e0c1d4c49803398d0714cacd9853854b08746fa453561545e6f0d96cd2c7ce1b89bcace1c697ec4d616bf14d1889a79a806a3699f84f19efe690fa13a3b4383ebf77261400fcbe309c2e5eab0b24b197cb856aa27d7d71d92d32aab656faec5ff792ece53874c4069f540d948f8b2e5599082e21f02d72
+K = 4b528d2b2bdfa4f2fce09dc9806ed5302e41cc52f35962653d7f222c
+R = 423de9e112ec38e3a034f5d9675c76f9dc8536b30d05678a2963ec16
+S = 74051e79699fa44de18e36ab116873593a310e4e09dce18b833fc2f5
+
+Msg = de1f9606261ff82218c8c145aa4d5847673b459eb55fe7e6454c0443266bbf800c1d09051f5e3141c4370d1b990cf5fea9d2683986c3bdd2823107829ace6ed7034caeb2f657a07b25b7d60240a0205026c2e3018141d479c07787a14e702622f8e6df709b636c6d3d0b5fd54f5516dbad97038e5c0eb31f54db1264d600efc6
+X = 366a49173a1783b99550d84c7fa02b6cccab12ee9a306bed7bb81ba7
+Y = 4d6e89b022c278f3bf8932e706e418ecb20c1bbab13ea8c90b6bd84384f38b311e8fb2c4c0a94ba7d3afca1ba94252a4c1ac1187622cd9c16aa73bb1b4a5cf55b5aa34bd93526f187beeb11700e4afb88c816eda50a50e81860c87fa66a1b63f5ffec3c3ae39bdc009d38fa13da863ca5ec134a7ffcf5dc3ca85cc34d61c5df8f9d9bdbe6a541045b45cb512ef64d1ad3db7b37dba33c6e3c96180cfb26f48c63373a0f0003ae6582679da4850ad2a0b899e0e8a1847df07fef3a4330a72f8a802c06e8e95707e0c7dc1915f6e1731fe650f1ae352e782d2dd77f54e5dac52539a10a22bbc2eea31efb94438a030c4b2451bbff6901b5fb3016cd162af6bf0fb
+K = 13894dda6721bf3af8a40603a3d97af240976a8ecb3ead998eee0ff0
+R = 5f3839eb663f026f792912d1cb0b448f5e2e593139001e839f71c942
+S = 6b07edb6a034d084a61bf3c0a36e7ee6911948ad8f6e50ac6844b1f3
+
+Msg = c1edd86151af66c6223e413f17e734b2bc024ff066578c55308f1388a91ab87270cd25ca2efbc2867eb715ebed6d10012b6f4808f2de1986ff7f4c369daf46c80a618707888ae3f86e38e7f25d6caa509104d4851cbeefbb75692aad499a33aa35b11409300e495fe007524b4af2c20d33f1c8c04516b6973ac1e07df3f160dd
+X = 841ba91e273f1c57847ad336cea47c643335e68f611482a30d6c0bb7
+Y = 90dbbe4741a76a5ff222ddc833c0e2dd445ad01726bbea25cac247f9ef9da643932736db07cd9aeffeb45119351e00332d9dfc89f5903a541e74e2e9709d0f852ad65240d06159fe54436dd8201f8c56926e8d23c2ecadeb8cbc9aebf12d52be6489e0acb0e7526fba3754b7ec163dc7e2fa9193319124f0cbb61c2ab7ab1a28c14e7d581dfb8de23f53364d204190a58fcb9ea5b6f61a7979b86bb7a7a4263a1066f0516e5870de423a7e3b906d90313d1ff9322450f72ddda4733ac74fca5d4ad2be22c2667b92212069446b42a391233d85216a88c25b76c947d8d56591003df2532fcd7b18f923ed482d464fb76f2c85617840d370ab99e320e88cf9ef8d
+K = 5ed84fb90761dc03a5e60f3b396d6cc7f8c16c77f065a6ec0049fa51
+R = 836d84d86271e1648466d1955c2b60b2a04cc021405083626347aef9
+S = 63c7eeb5e06e81d8923356f799810a26af67c0faa18b392258e4a9a0
+
+Msg = 2b5fb613598c02916bf6b4b0fd7a6b5426ac5b56954392fba32de00bdf4b70953be196ad51ff2c097a81e6ce1d17cf837d2444752be92bd4a9d1a8b41327527ff6bdc0e5c3e0cf46f7e37966aae18a29ce1981f212d714dd6c0cbb410d3a5f3d006ba9b593da150ce422b5cc420f3b561bfdf11dcb9910005709eeb129e20665
+X = 220947396c2de85d480bae730298df67283d0d0694950f5efa4ea5d6
+Y = 95947fbc50d5a80299c90dd27cf3910091420d8af849240ebb541a21b49e528b0f3317acc10493d50e6bce676c433c31147f81286789e6a41f4b2603bac0f6e5ee7affdb44cceb42864358607d45f4655a709d7d67f716d7367bb5eab334f61cef3720c080cab17512329e6d99925b47e4960c85031bfddb13f0c61af80ea46b7b8702f8ad348d57d481efe821054fc83b5266782756a42dd431881ea6cfeb7f7900d8f747aac9976be8945952afb8a274dad03428088310a2456ec254d1ccfb63eedea5d374ed8cc637a7baabf8f422e1a12d5ff316dff8a082068931490a4706503d19f93554f25243751dfe62cd87cb856f644fbb6fc46fb9cf89af5aea1a
+K = 2697349761cc4ccbdb4550bb9ca73654280ade31f577ef86100ff4cf
+R = 7b455fae1002fa87f36cf6f345716225d4aa1407802af4082bfbb14a
+S = 235d8be4ceb0176f5d0c47c1199afc7e3041c7d7508b9feddcaa0d74
+
+Msg = bd7d69bcc2e4f8a42e627fa21c7fa9fdd3e574b6dc5ad20217e80bcc9997b4c5efb31c7b65dbe8a0a394f0af580387b9917888152dc4f63ce52d3ec4b723bfea8114825f9f1e259f67b5d13bcaa66c97de725fae4ad247bb922497ebed0f092bbac12f2cbd9b71b229087378e8be0626b8d5e8950b0a6e69e05129f0d3842d27
+X = 42777374114519bf323bd03b6e0ec238660dc863b1a3b85e0cf8f8a5
+Y = 6fa6dedc84a1479be43906f2f68df0e93234ca2230c832db079d9cbd9342b2df13de4bff10bdd831313453b33b725cd616acf1fe2f7927ea32d46ff10ef1154e503f71165adeaffdd500a83bf1001ed36ca65bb6974d0372cb0f2118278466fe1286adff3c7ef719c2a02cff9ed9374fbbe6051814d26848b7d970fbecfbbffedf40a03083fe33d3067838ace22854a8e88bfcb02ecd76c378bb5c8babd22dfbe090753abf9e97cb6ba708ce00ffea5c550b09f24930698df115c020b1301d571a470e5a8a6ccfc74ad18949a57f614fcb0f7e8bf7530a731bb6091a7301af42899d9ee9e45aa62ca4903e66733e47d01e26b299746da75c7a57dc00bceb4d6c
+K = 3ad0d788fbfaf4caef4beec9c1566a8c7a1de26bf75dba82a8243270
+R = 16a2a48578a0b5b57553cd20005b7e8400e1061c4fef20d033f72f8a
+S = 6c34d176e95dd49271ee48a3802edf4238401084bc3930201405693a
+
+Msg = 7766e1ab7638bcda3e6fdbd4c85b3661acb2763d411376b2eedb4b2c6bff5d8fa20c0ae5b3cbed20796a6d8b81a1096dc36a39826a18ffb897d36bfb16363cca7632ecb71d2f996cf7cac66669bf4c83114bd53be3be3305efc99d22769188f84289cb1d11501f040b85d15890d29af2c8eae614f74beeeeb5fc915afa4322c2
+X = 364bdce93df0eaad45ee0ef5c18828bfe2e381db607e5b6a77ffc6e9
+Y = 4c2b559024f1b3ff5c7167270cd1f33bbf0f40b9efa25e137441ab4698154e74da3cad34236da4bd1c57d7638e4277278b508e85e3a98d30388ab8638f553e2a700011923e5d154f8c1407452dc4f80770c9c31c368a21e499d5dfb6f05fd67791e761a494200710af8c2188892c2d1c3195be4a0a1d67551ad466fee80d7edc435379a72c3bffad271de31ad2ed107d784f40e24c5a6e8d5aae8f2405964fe3c28cc3652dc3c9523b39d4b083ee65e9a07ce897a17b02b354766f1b19c2b1229ab468b0148ca8fe89484b7b360024218086af56403707bec65c52281cb8aa5346cb6f6481430e8e057146f390607c572b5bd8426b90ef3a827cb0d58bd438d1
+K = 576f8454ff45df954d123bd1384cbe004413c8f85493ed7d6425bfaa
+R = 09c61878a9917177058e9dff27106bdca7d06c500e09099306668cbf
+S = 7b8b6c4c5615976d7a735ac3e184cde96154ffc87b458924d4602895
+
+Msg = 84095278f7f1d578e798399af0bc9f4695f9302ea5972479adf90c95fc25d59e576d97b89b73dec629cef05d6173b55d015a3fb1d8191ae540d552409b03a7a8db511bad0951896db949fcc28870f9d17314734ca6a3472683d02fdc8defa7b9d3762ae9357ca2a6ab623b046350fa211d5213787127d2711cbd91405abbe50d
+X = 161fff26a7b9d7ddc15237edbab3c1f99b7294c70feb96f962df8973
+Y = 4b52c56fc64922ac04ee7a80fc5c224013e2ffdaa167381257e00c597b433641ceadbc9b16568bbc9c6d31d02c8e36db2e3987520ce8590856bd4a841b725ec95a4659a61a0086f66a6bfdbf1e4bf92b441928cf319f929a6428f5e3ba7c89123dbb0cacc16bb0e2b80854b0f60dfaa99f9c4caa412c443a073b7a51259125f012d98f0f6699d70ade66df9c5e18185672e0e2830e0585413da2956c89d2320faac03aaa83fe718a0d6cf7feb38a194e4362d7c89e4a13967e3a2d4493f4ec09ac2fc89d56a595472e60332448548d91cd6aac84a2f9b4d7a80462dc154779be5f9e1f709b9d9a156273033fe6e4842ec47521964d2e2fe262280fddec6403e8
+K = 7cbe0c1c29b955fa1fdafcab79c02177c15ec5789a4dd53a6ad29ce8
+R = 0c4d4527815a94bc2d77063ea69049be6a2b3b3a3a0badd5e62a8f9a
+S = 5787ced7081fad3fe19ab5b9028e9e8df18639e4991ab6e1e243416e
+
+Msg = 30eedc9d630b632082c196b969d24f6eb9cf1b1e2c53d244e8d8b50a40982ab53c4d57ff995fa8458908a743890382da6513cfe9c1991824873615a8a16374a5e5dc2fab3f5cd25652ec8aa3939f4884f74ac737989b6ac2e43f45b885206a31e797fd8576357e4b4baa566291815dac2f546f4abf8ba1de1120fd804284e959
+X = 0209c00edad10594f7cd7878472169d512a7e8dc3fc1cd69285e69d5
+Y = 8920f6ab95b1dc6b93e08ead6b08141cc2a8f1ffbb71d5ec5964f6b2c3d72ff3adade52254370f130990b43487775c2fe017a8200d8119818a15ed7e5636bfbf3164042f27bb1ea418698b6756f75a8fdaebf0f6e5423e460287f4fdd2a0ef305e658741373d3baecce79063962f883398c314e36230ba8c570e667c30cac8fbaa4e70202a9157d22708ca605403066d0fc84845bce9b8c3b41ec32f40c845a532fdff4dd10cf62a714121ea8a6188500645afa9316fb3e11628b163d35d8cfcc55272b650e8072c237645600150bbb66d393c1c97345d5820f178dd405b5d46fc4ac8a5f3929e6b1627944093178a8d65101059fbbbb7081174f2308b2653ce
+K = 36454e085b6b3dcc7c755b65ff46697b099485abd6ceb00cbf5dceed
+R = 45212d1c8c128002fcb3ce35583ff8d08363711c1598307d9ec6a108
+S = 4858105649db5992764dd32b102d9b9d2bc6af64c6a81595611e3e20
+
+[mod = L=2048, N=224, SHA-512]
+
+P = bfebd000b2d6cd4ab38efba35df334df721d6c2f2b3d956679cbad009f3dfbd002952cc899cc2356ec8769bd3d1ba5a73023729888da92ca48a5ee94c97f4f04a2e3acb4f33a2f0fb3783c31f2c70fa7c70f38214a27dadec8b12e67996a9e85ee3bb148803130147392dc5253c04d7063535e6cd646bfb186984e08b58b74a7be5b333bf32b0abfd5665360e9a923a0c528ff1c62c7253458f5678528719d436e50148741f45dc7dd2c6cac71c55231f12a83fefd2ed0a33ede1b8a51f566fcf7890682cdc1931dc207c92bf2ef4e28ab31661eeb77f1601eea941c9591f038d3f00d912857db05e64b2ad569320061c6f863ff3354d842e7e7ea715afef8d1
+Q = aa986df8a064278e9363316a9830bcfa490656faa6d5daa817d87949
+G = 8195ad9a478fd985216ee58368366d2edd13c12b3d62239169fa042d91156408b483122f44ed6236b8308a6cdb52f9af3de88ec89e039afad7da3aa66c1976049a8e0a7d18d567baf99fcefe315cada01548386b10b25e52f52ed78eb4d28082e5e1ffee9480c4fe2cc4aafd1efc9d4fd2cc6d155968931271ef15b3240e7fb043a80c8f628befe09d645077c1029d21e0ac8bf0ba9c27714d1b580ede594aa01b3b76f6e745fc1ec07db37e2fd7e98c6c8c6915228e422c309de9f5db168f50249d1be1ed3298090808e2ebb896bb79b8c4cbf94d4c2064e37e612ba4449d7ac210edde211416d64b051dd8046ab041732665411a7f154d31b3e11a51da7fc0
+
+Msg = e9f59c6a5cbe8f5b0cf75008d06a076a6739bdddb39b82143cd03939aa4738a287c2a6f31829bbe15f02cc2ee7d7122dbd132825970daddd8a4d851da86e7edc8940cb1188319218b8e0248a103eae34bc68d85f5a32830d7e5dc7718f74db5e4224c0debe1e841e1eea1a88fee0f85d9fb087cbcee55f86037a646e38346d2b
+X = 6a5b4ffc44238d1852fb9b74e4c1661be85984043cfeee023f57cac6
+Y = af6721bf75dec6a1b76ad35ca3750def31117c5b441c15a306835a1db74c003b86ae9099ebfb745b0aa9cb000cf43fb021513b8f197bc865b22bf949b491809ad752ffc1ca8e54bea16dc7f539e4c55fb70a7743dd28f262f60ef0f2fcaac29e8021a7938c18ffe03075d0b7e0a2b4dcabe46ed1953d33e37f113af519ab0bf0b6186c12b5f6488437f5193096e2fd6a6a1835604794c66b42ae5265c1cf1cb53ae84997975e0318a93ce41e3902e4ef54de3c56555bd19491acd53f3e57464e1f460389dbc5fa80648fa5a5a0f2956e9ec3b8dc441b535c641c362eed770da828649bfd146472b0f46a4c064e459f88bff90dede7ec56177a9a71d167948712
+K = 9ced89ea5050982222830efef26e7394f5ab7d837d4549962d285fae
+R = 9da9966500de9d3b6b7f441ca550233fc450944bc507e01cd4acb030
+S = 2d72f1f6681e867f7d8beaebeba4bc5b23287604a64cfee1c164595a
+
+Msg = 971d16d111c96de0f7098b256af213f4475aef31007e12e2974c5f64b2f335e0183c196c33d50f6445c5f614649549770b1874dd0756a9a8e39971dfecc3f267ebcc1f5301703f88743b0f376482cfc06d5948bd7926d96ec4d731a44b0c0eee5e85da26687265de5a66cb1a73a7e4f3236f60647bee5c163340e19505577cf6
+X = 9053ec8ab1f9700c2ab59259bf2e07892904f03c844cd58a7ff59c79
+Y = 290517297e4249fc3212bad67269e032818d760b0ee0525dc5a17c97116ee29eb3b450b41d15cea405d5e983a8558184067f424acc498676415e17506a351c124b5404f1d17153272619df713ce34d03f1f9ee28592f22f829a31993b106c785fa6dbe57d0049c815db5ee2dfe948ddedd1a5e2cd2346cf2f66f04fbad619cd983a1b069b471ef9adb4df6ceaea23d09f0a548c3c7209634c8a05e5897445906dea08a52e4074be22d8485f20eaaeadbaab397199b067aa860056991ee088480b4921267a698a8f7a03777f56bac84e50903e88d07261f24d0a4f317128e01fe8a9224f12293949cb6c3f095afd19aecb16b209a99487dcc2a1b83c49d75e351
+K = 901632e0b8ffea7efebe2fc9ea0d1a52442817fe1e1b5455bd39a687
+R = 1f44f6eac218236a1d99cf7625abcf5c964b0a0c5d88b8d05d74a3c0
+S = 71015cbe8622d2a34fbb5e7cca8c59e828adee71f50524482d9e7904
+
+Msg = 08ea09fa5efde215bd8b3c4d6a9c90ee9387ffb7bd65becdb88b40132c6384106aa619b7c66ca92034d284608593864ce6b92877112aa139240cb44b388fe68a8fe0501ca584f6a2de27c0fb658e72bb13fddb8d039a6bf85d63a6c073b2668013ce8fe589a0150e46d5b1d9b0cbb5a14c100ae4b20d6ce81a987a50a949f434
+X = a2cdf2515cb098559fa13cb70b6a897e89df120a971064bb377988ee
+Y = b3e2b7e0641721d69616679596cc75091fade2da0558e310b8d14db0f4686f1fed48d0fb7f0b3b27bf6e1981eafa7737a3e651828d1fcbf88387d06f78404a7afaeaaf8fae1893bea3a09a118893937ae2a8fdef3320942a158463de4fddc11987f23fee9633e06ac239c06610bc45319abafe517ce4aeae6247ea789d7da60d3eeddfdc4b232b4d7a069bcc0eac7b99fc088fb7ec1946034a98d7e69cab0cb2b06b3d9deacd1b433ebe94f547a322895cca9b0ed319b1d458c3bfb260beb641a5345dbe3d01ce800ec2c6bd430ce3e3f5f78fcabf91a29658661c573b9f6fd3812e560d888b6cdf3d57673c1630e00ca841ee994958b250dafbc3e83bcb8be5
+K = 077b3adce42ba0622772eaaa8cabd16107c92f7a134c715a4dda5ebd
+R = 6c03637d253a8dcd0907d6de93926bdb3e1ea3135a709da2309a8da6
+S = 236e5163f2c2ebe0eccdbd3351e4285531a4f53e45284e41db37e266
+
+Msg = 957cef163b16d8073d5d3fe158fa0c7338bd107c6a653cb0f11ebe41402607b822abe30e36ca9ee4c9de00cf72db97f57d78f3db49a8e1093285563c68b0f4e124830b9febfa3e75ce2ea59cba2cc6d71e908b5e6d8f463954922b82bb55a69fb2ff143ffcae6b5656143c8b6cc24f57b17cfb020f6e15bdc5f25436d07b7f8a
+X = 15ea86b973ef146f03cc701b17b589b0ffdd318b64827d49ee3c0044
+Y = 3fcb8e44d6880f9eebaedfb75994605c9ec001f0595aeb5f2bcaf6b3987bc28a7ca905e1fed7e3c715401b5c608d12076938a18013473d8a433277fd9ce5a5cae038281e768ff909aebe4d257dcb5d93488022d07d4c2862afb2bf8a2b1e974a8e7b6e176b1b0b7ad6f63bda1b7142e46f504dcccca7d1e2e7662758f760e624e59528c5a0c9563ed517c691fba2abf66899241178223ba20013ed0ab21f91f3e6bef755c8100c51ee947b7a9ba38570f880b5e42f24b72d5321132e031b985a0db825bf3bb00a7771a03007387e03ce020fc358e65ed3de8d847f5be60720917c0616a450aa341ae00abe0a809c38e97314f303fe9b0c6cde446d0217cc4eab
+K = 9af96c995f0b7b8283e2ea288e3c3a6f751a56b38041297e2bc34cd7
+R = 150362da792701694e23f0b0a9b7035437cc8f4faa45c6df8f7982fb
+S = 6df4321c61738743a9fe78ec76b4952692aaa372d1c8530fba0fcdec
+
+Msg = 204d9cde24a2f0de02aff020f6363fd68f70420dc1a9b5138216201363f832da0aa801865a75a243427d9d6c78dc5e6041b27d033660e1e405abe1be27c909994bd6fb57180c3d6b498ce8793bee8ecf51e06b96411d00996209f44a380926c7b195e84e78f01fe02e0bc7032ca462a5182683475222f9dd8f3ade1ab8fea318
+X = 524a63cc5acada8557609a5f0d88fd3e9c6e63719704cd8bab8fe301
+Y = 99b8fc6e64cce262ed741c30cd586986aa2e8f6371b848a2617c619897de23726bb54536ece4b460cc7f1f39e0c184eb19291e930dc9140e4b7735541eeef8ca8ebc81790fed37a5f08e9da9abc66a3a2e909902a4212106927d08abec01f27c6056b6e0381150bd742d409f6810fa5818ffcb3f182adf894ba7f80678ce883c1089a6ae71db3a115c386dd9153f4191fc365461ac86838ecf2f3f81ccf283297a6fbc644f52aae664901ae30c96fe4df930cf1a41757241cc4d9adfccdd9a6bd5004b05757443598856400dd771dc089095c7dcde82f721f986af636638eea2c71770856c2ba80315e8696142a11e51ebd7559e9da6a00be3f9f38c614ef207
+K = 028091483753f5643b61e4093a7e0a5135d71c5fa318d6e8bb0efc66
+R = 9c023331751c79d5da355bb58e2bbe2e973e3e4b4f52743ce1f1eec2
+S = 96ad0e8ca90627fb7ac4540c9b58a016ee6c4e0a6f0aa1e7def81a51
+
+Msg = 1e4e58afb34c5d6f645a82645be358a2e228cc7b9c23dd7f3aa79595814d054b923b9cbc6c9e6c6f94848c1a4d215679023a96976a44e9b59136241fdf26f8f71fe5a9bf366e4912b5931e1c8f63c37fae2bf1d55ba3943a650bb463cded9a7b062ae55aa57d9c5ceed323fd9a7555e48b834d3ad4441c35d9e07c7c6e4d5d0f
+X = 33b25c6bbbf816addad05e48b72ca560c5191214d903a978b6708a30
+Y = b4dea0d5b671cc815382d0ec6dce661c30ff93719dc7f56e7e61df6eb6a3207a05617938c874bc3ab093bcdbbc983a4b0b587d60fdeb7b87f7b0be4a656883f5443ca7864541ccbfe0d0835636ef08a936b2321a51503be1eec5f7bccd0c73c9cd52397cc214318b30e8be1eab57200a4d4df78af991bde183e0164e694d8308b7d20d067bfcabdcb50f7a2c190c66ce3dd0e18960939cb57fc3a2e5a604f3d9bd6fa440d54e9cc0383958a0d6aa2ab670970f9b2caf866ee507067343f7513e0a981f3a344f2f753af44fda26d661796032bda0f6cc30a9a789db8d3d546f02f898116805180c6f0d2f5388ab5110a521077d88d214fbb32eed2664406cde9b
+K = 989d87703853c4133b6d273686bf672492e90ce2a91b3c72a4188a1c
+R = 0434ef1c127207d0c884701e75d801725c451ce67d2e71534638b231
+S = 0c625e4a334db07825a46b55da9c2e8a5f600a36b71606834097e777
+
+Msg = 5a470a38b2ebbead08e010efef7461f6f859257d91a61e2f0ba809e28c0ea3d410e4f41477a398d593df58039c4336260ea7d8e98c9d7daad0c31ecd1567c7db730179e2a9a62007bd56f9d9da48deaa657ac92293e5bfafbdebad1afe25c41e1aa09db61fcc191971c37549155b3e67956913aae3a5f6245cfcb9aad5dc1e15
+X = 13411c1a6fe0063e7f9b2467ccebf2be5cf30e742f9a35d715558ba7
+Y = 06a20d5571296eeb87e79eb274036d819e8623b15de44c2697dadecab2996f51a75aa088490e683f34d5e0e71d9fb8734bcfb71e9d19cbda3caca5cec417fa37a06142bfc0682de56f0dce6e826ee9f30d01279859d3ffbd4433bf4a1057ba0ad75060d41f968f6da822c33cbda9f772c2b77bc1b29305cb697182c0d39b132868932c64016bc9071b30920eb385c5ae41c5d4f631bf5f54b1eb4b373bb3e0bf6e448ad8c988fea16e643790307b8b85f009fb67317217d9148c6cd7a46136eece1950a119e5a416a197e00d0e929b04a5bbf6c988d8595a0b2a5ca71926ba351a5f7674af4183b5a68979bedd6491295b0f172e7373eca7e62d78d744fdccec
+K = 7406254d3cfe3d55267236ff63b0f42b2e3b55d1cee7ed1ca3f06ce0
+R = 74dddfa35b25d0c0b285a5d21719ee39d6e3f443445ceb90556b0186
+S = 474865d3ef07f5df49e0a6ebfb5ab5c2ede47c4c6314be4ccf455e21
+
+Msg = 0849d67ead3e8c44ad3b2f949be1cd9f9a4bf8b5785bd00ca66038e9a8b93727a652a415c1d8a1ecfcad77782d87d912623c2fef45b2083ec0f79a264ef7c5bfb76fde5b22b9845392e759a1ec05fa6387ccd2943ef1277c2e060337f82aa562cee5bd7c158258f2e779d51e47e000a7b0706077490976a07763e2efb275b5bf
+X = 5631c7dfd3f5adc0b7b542a8d121a07bb8251b6a1bf3a8cba771c724
+Y = b1c61442d8aedae0a04daef7b6f8a49c6d07bd958e8ec561906ddf31f3b4ffd481da5443fe8788056c4ea7b5dfa2cee6474e3fdc83fc043a2bba333d503a2a938865ec3f118640e8457c7d974e2a65659cef5b7ae4f49a054d94ae5e2eb6345f5bdaf92148beecc109c55031fccd90cef88213b69ddb754b40ca8d8f0a4bfc81a287637a38c21807f727a67025ff67b7fcc54418adad408a5c7d1ce05a1de7e30988d560e779fdea1b78753314b0b80fdacb6246faa4b4c4ee8acc5ae24b82312040134cd8cc2fd4fcb191fe43f64d140624a8c6c2ac5fa4bfdba5d625d7d21e3c3f6acd8a153a04fb22f8d3b244ae8c6a1dd0e6e3b2f73c064ffabfad6cc461
+K = 9c353ace0ae52501bbb98a2d1c9e28f3a833c2b0eaca49cd12c57ec7
+R = 2aeb7fce1b7764d32cfb7d85254ceed9f3a6337ee8dab42c8ab7a415
+S = 17cce13bcb917cdbefe0c566318fc974204b700c5cddc5b2b499a78e
+
+Msg = e74639f2bad42fd6393f9b350d6e19cd4c1ce0f41e8c902684ef6f86790ffc8311acd9b57d6521e80339b3243f6ec6b01a06ea899fd75da91e1080fdf06129dd851a895d74b1efb9837289c11d68e1308c47bb8c59d5eb895db53bba29102a5b48b1e75c73387ff22e6c0461196a7d48615ffdb9c8ff4ec6587b4f68d260ad86
+X = 7319bdf79a4c8dbc115e3780c818f6e2a3243ab47263e84ba259bd3d
+Y = 9e1b77243aba0886f9baeca6c11bd2c5c55547cc502e731d9c4725da8777ab6050e3399e25577704cfc66163f6df8d749142a7e974e49b7315ab7c8b85ad5d5cb271cf207eb72e1c3476b0d863721c967be15ecbfbf06eadc27de338eaa3cac1dde642d52aa5359198d8909d23d87d827090a8ada7b7a5553642d586603ea2464dabd2ef5e18db3a623be65be7b5a469890f9dde54a27ca723b4e05d56b7181b28d5c1f65415688ee41d5337a9952d92ede4d192b9091639caaa6033e4749418dde15abe4bad62c37fab05e3bef4cd7398a4977e07e121fef2aac56be7e0546e40fca885696a3850c9a28709e699d52611c9b7926e7ad18149040582c997db71
+K = 6defbce0e72f014526c8ab02c6fc320a4bbd85365d99fc5d3423fa4c
+R = 515b9ce53eb10c3e47890556e0f0fd19adb207b9c01f12ef5c6caaad
+S = 0900e3acc4c378bdfe9cda4db8f8ab54436931c73d8d3171c6dc8bb8
+
+Msg = 4a145dd5cc4a12ea43617ec9790f1038190ed3d8af24bbec14da3ecf5f387ca9764a8b9cbc5f6292a53a9da9533c751140f8da5fb6f3d48eba1e7b98662734d9a8b120dd515408ba756f75a5755212764ad92c3f2263835211add5b4cc0eca8d4fc7a843f49c38ce80868faf8b498fb414d3080ed41e3674e285d3e40d62f305
+X = 7944fa1a2a938ffabb234ca385916e01a89220cd16f06a474b9d4ac4
+Y = b3f6d44da86a515d7185b70c5adaa3f6059c0bb7995a53910761fea362d9843f92f2271ddb0bca0d4519e33fdb13af49d855cd0b9ab0b970267243e468d3c41677ac588fdfcb1cb9aa4d233f7ae017e67094f4f4d904e1575e76bdc6bd8299b42a2f39adef63ce047862aaa0bb8ba32ec2733493648406f54f5d8e2eb19eea837f4d5963ad3192917f5fe3b6d027b22bc1bf0dce8401d622ca72b1d73a89e888de1e62bead2e4e1da6b5d04b2a3694c76fe07ad3c66426343d67be12b2a72c3f76225573fc054f3b7d735915238d7bdbcb03ba6dde3edc00f8c983b0b50129fab426004a27a038139f2d3295b5b032701face34a7523559485fa631c219237f6
+K = 8ab9322319a138489eb773f3220d712d05cd14eed9aae402a8aa767b
+R = 5cfd4b9f92ca727d513ac14143b125148655f1642c53b73cc25131c9
+S = 2adef94aae372d579c99629ca0786362cb0247aa6d99957074cd7d43
+
+Msg = 428a20790cad1c7ba82118ae5841bd5380ee50be5b64b8040935ef3d6da37a26e6f02035fb1937c7a6bcd88c894fad7d8aa48abb89e0c64287cdc637454db89eaf0a7e692734c8a243856dd75690bdcefe554e39a0df84e6e0c96b2c5774a3e4e2afed028fb43d7998d3cdc9a6409322cf3bfa4d1e36f5e707203b59c49a753e
+X = 43dea1b4e5c2f22548074d7dddbdcb94a235a3dbbfdb7b3bfc5923d3
+Y = 47a9340ac513585c83bb20a2fba946971811184fd20065fb95cbb20625b47b216f75e1f3d89797f540a0485cfbf07b1716a3ece7027d86f4940ab90bbfdd8ebf15137bcf8805f93cea259c4bea5a2d3bb3dddf83aa290d3573e91aa300bbf1afb9b525542d67a8d86051aed8ff8a2cfc225a9e51eb374c31fe103ae8f4a0c8911421d225c019e1b5c07dc149babc26b708fc0fc0c13c3b35390317c409faae81aac9ab5d01ce85add24917d94cd1b2141b638de3a253bfca6b7f1a8104518d1572211ba52dd175632c8f3f6748265a4bf6c2b8363d9810ba1f1e584794f62319f0451da831d457b5269bbe67784c474ffff692bbe2baaca32d3f85f4fe39e03f
+K = 5615520867828ae7dbc8e9b116e7661e18f09e5cdae17518ead1484f
+R = 8a96c419e0f391daa29fb162a1b9570f48a00810aa480cde0f27cfb0
+S = 028ed9165522fc59aeeb79c491a95ed8427fd1b695f3dedf4228a328
+
+Msg = 2a07e28fc102dfe17c79b9368e0ba92414d2fcb407d34e903a0a53370f7d2d33aa13c02e527587718c3b39666125eca2e8fd4c94b9867fb6ef16d555549d8dd0f6e10417ebecf48f992ad84b5d9774540785ddcd264c55796bc2162898ecef4027c34187f8c0b1c20d4daa108b70d76c40ddbebc1e0f50f4dc904dbfbe6beb9d
+X = 5f4f3c4f95efb91c6b49f43afbde6d0f9b5a1324b4926f3276bc913e
+Y = 05f27ec035627860c31aa597c96837084605f270d15a3fbbdda1c3853db2ea6f6c9de4e11a6fbd773c300ebad0f9dbc33608f9c4c5cedede0c26791cbea35af0322a607739e97c3242f0ae7d36afe269aae64b5fb2db265cd756ced45d888eaab0465e509ab7f83d623f69e73cdc0c7670675ce0c29f49a19d7038623bde36e29fb854e6fe6ffdb916abb7d61fab4b620dc739a5cbd9608a45e86c2bbfb41b8699166822e832bb6cac66e004e93d190b951424edaf34bf6bd343bf60154f739c43562b03aeb4d23de1f76c18f74b5f7a73c805b22af8cc6bdc9b55779ccf6d441cfd3154616cda18807a9f5e2d7659e9e21329755157dabc622bd1ae2d5097c6
+K = 97861b777e2a8cffc4c2d24e2df9eedf0b65ea2c9373c1085ba44efb
+R = 91a4576931ed621a0342f14ee2ba8fa8e1bbdf894c1251afdf72146f
+S = 56755ca163f7dc89458a7a75d4dd3ce3adec42b4aa7d04b2858c47f6
+
+Msg = 7e96385816c97bd9de81de30e67db72436fb42faa9b6ccfeab1fa528c69e6351b2012a1097fb86d8c5cc60256ef11be18f16137617f8cdd29e3bab9468c12ae34336ba0e0eb6c828177d1d55b06698ddf753756af830a10ce9c99f1d13682668e3eb336a80618e666280096417c1e2b005b9351f5ea306b8c63fd184a59132b5
+X = 914e5d6d95ec12443f73c127b797229544971177f645b8dac5f6911d
+Y = 2b69bf21bf689a1f5ed7096b27e447c1d52fc2473e9e4353dbf185632022fc605cefe5489102f7cbe984f00c1ab32f2def1a84f1bedddbc15f87aed0a2b1e912e9edd74edbe2c15a4c37533014b9d32b05f5a44d323def1cebae0e216bc35a1ca8a4265c3db5574eb23e17f1838e225e467a9426e8798c5a2e896536c48c4e24cd2ee9da1b61aed2e25b98e4c1f4ee55e0b4705feb2bb1694cb18a6414bcdc1a7489b4bf8967985489316b3e57ea281204ced3ed88ad1b207be7d294127bca86a9b861ccca192c15c815e2328cbdaa5899c9dd271fcd6eea0d2ab009a8ba001e6725139be26c5151875cdca7f91434443b9e5e47a45cdc8b7399bc5e8bed9300
+K = 7d00160fa1ebb10b0465321748eba9ca6e1b3b5216c0c51dc34b98f7
+R = 1bcaa2caf483abc80b75f670252faa2a8e18c32301ba6fc06f37c08e
+S = 909a7852b8d5c8813e17c040779ad0dc5e9e0556612056835e68d2b8
+
+Msg = 24ed7a16782b5c34beb58bab6a7d2028719f9738e5d1ba6978efac4b53b37c88e7ea02e0cf0fd82a3e50046052a9049541d12993254a46fe401f402d38943e94918bf7a6fecb08ed1309b7b0f2185967ef289a2efa6c2e37a74d6592a2eb7401ca5e98bb8645a94e57499d362e0f3133ef336e119561cee1b558c15508781868
+X = 3a42f9927b4eb39ee3a910e4418987d1af1ffc1f3d5df0c4920e05d0
+Y = 9dccc137197bb29824b1c10e9e8dedd714efc936cff83f42634d64391f9b7f4fc3a231954a8c3bfe4ae0f82225fd52b5dde6dcd14c0ce5085971c515da38183427c7e2a8d76e40efb671af797e0c576e3881d434ca809dd553ccb0f7cd9f73c7aea2268f36c84170ab0ae03b2b46a219547564fd21c540b1603ad7306d22a9eb8ef37ca08c2b28d16c5b9c54a328ebb3c0f9505095c612270d52637cb5584ed08bad7138d3388c634b6502fa6473a2f594040b9acc1480b343d2287fdc70d16ba14b1c2117612dcc5860dbef8387af9aa5e1621d37a38f6cbe5935673ea3cbcde4f32a249eb6a5eed41cfdcaa4c87e8bcabaa6bd1fe5a879d17e9ae35837ce0f
+K = 23dda49474ec6cd13e1b0249ab24f50e9d69e40c6b5c07430780c44f
+R = 5f4f5449b8d0dda3ac590ba1640df9772ff08cec08528bc2d70d7ac9
+S = 5bea04bfd33248f26aee98ca8596774e95ce685465174d1caed7d920
+
+Msg = 4906dbdd9da6ddffa152fa2e250eead3c6ef708387a3ad64d34a0e057459471f48752fde0786db28a4bbf58114d8dc91b69e56be3c49ec1b9880d9917c73abc895754a60779b18bc951550b957a77c8cefa159908126cc801c665d1b01109ba604bb9e797c7a37660bfc0593bab0924df5806ca803381b24b03de3d03b484d49
+X = 0c53e5311c104f11f6eba646e4840d1960a92118204a49e3ec8ddec4
+Y = 072cb5612596aa716142f5f756c9542013f3f1628cfc5497eb1ba0aa51bd5adb8eb8adfe059c0e0882e3c09a17d1f51accb687b243fd3052bbcb81b063c1e7d5be066587ebca078006f6d6ee71a69ef59b6365cbcf64d4cf1b9299e7403009272026fc1665ed403ab8dee40eea4ee7d562af001951926dc8bf0c783984664ffef629cb59d709b3d9aa06805d62afd794541a2b4ce0c59043acf73e18e74453e86a082f17914ba6b2b0fa80da8353c7ed9162609575ed41f8eb78dbafaa7b518de0c85b1720e7f493b914d5a3d2d0748273d169d55c45556bcae670575c96a444fc1d789f5bacfc8b24132bfbd75b3061fbacf2935a219b0f2ac5dcad718516a9
+K = 3523465a8417b3a05ba1032bf6c42511591f2830b55144f9662bf6c9
+R = 77475900fc7f3e0b80f3884af8604eef60ffe484bc6cd3de123f7959
+S = 26ca927da0d10b43dc1521bfeb58ff347ee143fc38db451c11a03510
+
+[mod = L=2048, N=256, SHA-1]
+
+P = c1a59d215573949e0b20a974c2edf2e3137ff2463062f75f1d13df12aba1076bb2d013402b60af6c187fb0fa362167c976c2617c726f9077f09e18c11b60f65008825bd6c02a1f57d3eb0ad41cd547de43d87f2525f971d42b306506e7ca03be63b35f4ada172d0a06924440a14250d7822ac2d5aeafed4619e79d4158a7d5eb2d9f023db181a8f094b2c6cb87cb8535416ac19813f07144660c557745f44a01c6b1029092c129b0d27183e82c5a21a80177ee7476eb95c466fb472bd3d2dc286ce25847e93cbfa9ad39cc57035d0c7b64b926a9c7f5a7b2bc5abcbfbdc0b0e3fede3c1e02c44afc8aefc7957da07a0e5fd12339db8667616f62286df80d58ab
+Q = 8000000000000000000000001bd62c65e8b87c89797f8f0cbfa55e4a6810e2c7
+G = aea5878740f1424d3c6ea9c6b4799615d2749298a17e26207f76cef340ddd390e1b1ad6b6c0010ad015a103342ddd452cac024b36e42d9b8ed52fafae7a1d3ce9e4b21f910d1356eb163a3e5a8184c781bf14492afa2e4b0a56d8884fd01a628b9662739c42e5c5795ade2f5f27e6de1d963917ce8806fc40d021cd87aa3aa3a9e4f0c2c4c45d2959b2578b2fb1a2229c37e181059b9d5e7b7862fa82e2377a49ed0f9dca820a5814079dd6610714efaf8b0cc683d8e72e4c884e6f9d4946b3e8d4cbb92adbbe7d4c47cc30be7f8c37ca81883a1aac6860059ff4640a29ccae73de20b12e63b00a88b2ee9ba94b75eb40a656e15d9ec83731c85d0effcb9ef9f
+
+Msg = de3605dbefde353cbe05e0d6098647b6d041460dfd4c000312be1afe7551fd3b93fed76a9763c34e004564b8f7dcacbd99e85030632c94e9b0a032046523b7aacdf934a2dbbdcfceefe66b4e3d1cb29e994ff3a4648a8edd9d58ed71f12399d90624789c4e0eebb0fbd5080f7d730f875a1f290749334cb405e9fd2ae1b4ed65
+X = 5a42e77248358f06ae980a2c64f6a22bea2bf7b4fc0015745053c432b7132a67
+Y = 880e17c4ae8141750609d8251c0bbd7acf6d0b460ed3688e9a5f990e6c4b5b00875da750e0228a04102a35f57e74b8d2f9b6950f0d1db8d302c5c90a5b8786a82c68ff5b17a57a758496c5f8053e4484a253d9942204d9a1109f4bd2a3ec311a60cf69c685b586d986f565d33dbf5aab7091e31aa4102c4f4b53fbf872d700156465b6c075e7f778471a23502dc0fee41b271c837a1c26691699f3550d060a331099f64837cddec69caebf51bf4ec9f36f2a220fe773cb4d3c02d0446ddd46133532ef1c3c69d432e303502bd05a75279a7809a742ac4a7872b07f1908654049419350e37a95f2ef33361d8d8736d4083dc14c0bb972e14d4c7b97f3ddfccaef
+K = 2cb9c1d617e127a4770d0a946fb947c5100ed0ca59454ea80479f6885ec10534
+R = 363e01c564f380a27d7d23b207af3f961d48fc0995487f60052775d724ab3d10
+S = 4916d91b2927294e429d537c06dd2463d1845018cca2873e90a6c837b445fdde
+
+Msg = 49707b655b6d168c70baede03866b0fba60239ad4cf82f53b46e11b26fa8f6276ff6687d09e8ed1e5d963c11e4763b2e59a0927f01e8fffd1894a6262327c84bbb4298d7d7fbca660673128bb7dea46178146485539f9a8f88dac761d0d5d45cb557cdac960be23dd9199acd99cb64d1fee2ca68e423461a02abb34c1dc45011
+X = 62177a5b2f0b44352f643a9e69c1adb4a0b292a5ea52fa8065e94ad043d46218
+Y = 385349ecf99ce783d4e7a80a7dd2c533a3623c38260243ac392d4eab6deda5b79b8f9167922e8b60468623e4603fa7681f535e20de673531255e108f542a26d5c87f19e063372d142869c5eef1325281fee7f1c74d2a96255d420f2713864d55d36f8139194f643a6e98b5bf9732c8597445af5a71e23e2ac5cae3604323f7bf09449786974ed53a5717f9aec14dd01bd1cf276bf3c63dec43c3ec8ea6557de469916412f0456c90f01291bb7125e9f855f455b360c03d4a7b4a8d4090e47aaf1111f382dd2605734fb54f4b8ffe23c9ded2900b3121b497bd46d0458a09a5df4aa9cf1be906f5542313384f93d377ba9e0a762b4793403b914e52865afabb67
+K = 2bae4225836dcbbcad976ed47ecb5f3fc05439358791be244e74d2cf0617fc26
+R = 0fdc5a5a4a2c2f3df50c868383ba800396ae25265be1a14762d3110cbeb34819
+S = 4b41841cad45fedea5aad0a16b053e88353b6f0102df74c9fce09e38f5e6c277
+
+Msg = 763c1f15c5dd8a93aac4e048651c4ea84af18aee255b56959eaeb1876699be75271af0da6c3ca936e99be4ff4436410f69ae7018b6c843dce9d8b71a91efa53c39be55f285fb8ad8543952fd3ca89271ec23d342cfd557bfb72db43b434d0ed5b30763037754bb0f782ab08235a64abb7f0a828f892cde7e05e301da7c21c096
+X = 5d169761a3887a9eca0f7e59d77b75671ae02210006e754bf2f12091fc3275b0
+Y = 0becd917eed0be9cb58ff9d259a8fa415b816da4a25d3f569d7b9f317b3f47e4244cdef35796fb455c05c156452f1c8660f5346fba169276221446f82bbb2027b056b537cfd59c57299166a6f20871c74e6c1d3f5a37b75e8dad6cadcf12c909586a32f150c68e332306abef8be1abd56c42d3c36936cf8f2acaceb707994a3d4c0555a015de892037aac68e33813bf3050f0f3a8df5e81465852f6a195ea688ac5d258eee2076a6b236362e3d792e7f358c6ba994da7a64b18263969655473aaa37cb3cfb00a27f8fb24a4b73b025c96335438484e958ad0848277df950847d46a9874f1039fbea7e08bc79675ef1df6ef21230a79a3b161308a0a4600b5347
+K = 66011bdefe8cc4a04fbd5d69252bb72da8f9a8d6e00bb7ca75719133ecd86f1d
+R = 76e9b6ef7e8d48fbfc43bf465281592223fa7e0d9978392d355868c8a20209bb
+S = 7f9c8deab51c60bb6f866c76450138e0d2946aca6c5f88dfe35a0c1ba493ee47
+
+Msg = 67851de982fc70f969d82f65d85b0332d667114f27b58bb9e565d2e40ad011983d936049cc97a216260fa2e410ad6d6c98a548759aa8e2d022c1fbc1b16b10d83fbbbd126ec43d5fedc407c831461c7f33ed94740031ecd0f701c7b1df88a249265b3f60c38f4285bbc9bae164bc38e162c235c9a9dfc1b150eaeb1482ebed48
+X = 4f3e2c5901b656118d88a47fe2bd52f85cbf828dbf9b67365e2013a937f0f2d9
+Y = ab9a99ff87899bd6657b3a9e9b7206996bbc7799dde57dcfff8098875dc4650d791e90bc4cee10989bf49eb5e6230857f96841ae8362e4ee5cc8602f6a1a2c6f8f2f680ad3a72b0e07511ead301f575278a074138aa4eaa53919e34f001cbe2dcbc345c77f5687d071981a4dca29d026bb53ec9cf03a88d63c52206d351f8fca10239e84f4915ce347f48d650aaaa6b02d3164973f82fc0e0f83a2d458af65736d7e0dbb264fd779ffd5a3f066584494598526cd67e12d6c67965a70ec3f09e2cc447f177ec87604b531486683025e3b520a26e69c958cf8435f7c6ce564f0a72d1fc47205a50b39d516b14a476f6c2dcace50339cae20cd3421a75f6d377b8b
+K = 72bd0808076af461353d98cb0191ec76a7c04fbe3a7f793e390cc773434c1d4f
+R = 763e89fc8b2a090b75812aefa55de7b7cd61ec3fdf8730ce16b05a7b9456fd2d
+S = 4a97086b6717a73a6be6d4a95b8343bd20b0d7b51c3da1d86c5852350871379b
+
+Msg = 616de9dd23ebede428e032db7838108a224f7aca57b1df87f031fe1d86083d688c5c3ef078e64d8d5a9e612d3983460ca1f816f787c03ca43a1fd8ce138655df677056364c0eab8e0493c07bd4b2b05022190932de794f195dbef297093e7da1c4304db40b63ca53e1b8bcdad913d7a902af025c367c48de387f1a9bcd7ca42e
+X = 4d0240a34dd45aacaab9e24e4838223ccb759f1d93fa8791f28fc7c2e8318820
+Y = 584eaeed2dc785d8e2b8c85fd0e5ec251f134958bd9eeae4f79f862b62cf602ab10d22eca499042f2c875f2708ba0d697af39f23f5e0b7de4ff7964bab1279efa2aa797a2d21e788d249f42693cdbfd71fdcb1aa93b79bac0dbcb587bbff4ef15a3799a5fca8b1589838e30096069ca7931f7408815b585d140a747de43bd92cac3f9a9b1862fd704673e1e58710c16ddbe7e52d31a7df15974958b1288116ed98ff247f5028cec86d9eb97b126a48adc952e90dc52f2bd7810355aa9075051f26129c2d2fb0ba8066e414989d92e29e689960e33ee56ca62d714a42cb7487f70c0c0ba643fa9dd5f85259fdecd49fa970c8322682b114f2647837637abc0ed2
+K = 325e19d8b7ee8c8d9cb7e70bb5417035a8183bdf73149a45f0e83f3af68decc0
+R = 748f466b7fdcdfa77017c865a33b1dad4db99dbd63efa1c87345c4833b0632ac
+S = 0bf9938e7972ebb00fb0a3c0c2476d2509db23afcaecb17dc571905317eb8ca7
+
+Msg = 115f0a8be34e84d09bdcca69d19ce17dd67df739aa4fc6e8077076535f39af8302881471a5fb0e1839a3aa76dfda4bde2f9fa25fa582b756a4966d75320ac1995472271666156ea86c19a239895e5578a3c39b0ba3258827a01df1f30db22ddbc267c9e290d5d457d0a94d8aa73f8e79f3acd31bdeee7aa32c792c22acb807ba
+X = 0800394a2ccdd1f55800565374d46be9bbc1190b55eee26502bf5f2459ac5cc0
+Y = 2e06073f59196d3e29ba718e84489b6f447fd6f67a9ee6357c5e8a58fa3c4fb6ac8314ebdc3b4d6127f2b4d2112c27799f0c1ac5f7946b5607212d796741cc3be127212a125edc3a7a91a525cd62152199b18b4f1dc332215d65d64ad06098ff2180ab47bb5728720c937e1207649ed19c883331ea415faa51c556d12649665f1ece880d055a2a793adc74b38f15f50aa9b46786d907017b1d6235c43b37c2036a1640f6bfe3bec2b95b4300a3bd78f471f6aa56e5e6347571996f778670ad94efaf20991c555924fd55cd518df0bd558faac3f9826a865a3ced0f59cbea45c65412bddf8f2a8aab3dfca1dff50374163fa899cc7f7f108b194fc955cabe9ca4
+K = 617d00444047d8e943e429947d28b4718a8b7603475e5453cacb80fa704f90f1
+R = 5c8d76440735055c1b36698da73903b332d64ca5603046144fb7668b1acac337
+S = 11c54efbd492a7147a1c50b287377b52d2193907d5bb636159c15318a480ca6a
+
+Msg = 3c1f2b92db1b4315837baa863043a9b4496a78143ca74f6e67181facf50a6e08d27945d00e7b06f9c57c0e2f1527c94bcecea6993175d0f09bab4f15af55ab7aa9b16b48c94a6a99c2d7e477b744cd27cdb9b0bbf810756bc6376fa15bfbea3c9376ca6979752fdb3a655affd6c0186d1a34355daea8cc75acf96b8847dbdb8d
+X = 59edd0348ca6a85c408816549e9c58338ef92f56edd8fa753226acc0e181751c
+Y = a4742d3c7e7681b01cd6aae17423cc780491d08df73b4a71edf7bd2ee29c698cd66dba0491688fc7eefb4d709147bfd4c8c4b797ab9197573b5d36599c4a592c466955e80ae5d2122bcaa5d0e1d94b4ed2a99b1af5d08eec86c37753a3c3656c0fef0d2c471e4ffa0fb163174a4df1707879fe083655291127a3bbb0597e23802e424efe4016360364506c8ab4081f0a95692c2629537f05306181db669bcfaf01c15395614238a2309429199555142639b3443ef85af74b5e88b7c70a8167334f27294a8ba1266695a369372badcba7623aa58cbcf25b4bbe663d4eced1a18e7753391d6c53854c4a8d0ee1a790a1a21071f1386c235ac26182d01a1e81ecf8
+K = 0a96189b8740005f215ae5c5a8aa8686dbb4c353d2c55deb3904bccc4f9a9b9b
+R = 31c1c6aee7ed541a281f37632b27ba88536f36bcd92fcc360da041f4197f7f95
+S = 45e1019b2a1702b5df1eef4fb7df6a53aaa66ecb8be5cd2e28b353c870e01f41
+
+Msg = ad389f53235deb068f7097780330746493607fdb7e1170bd1fe0da012714b8f1b128c69a53d7dd2646b09720883e2387dd15d46564adff6642372c838287bafa5f4343a27ec8069770e5c367548833fddcc5f8617aaf41289d96dd40f1098ded9fbb110aeb14d69272dfb2dd7d75e7a88dc4147f27c64eb1bf0aa0569bbda320
+X = 19ff4eec2e47301d0b70a826dad822b609c997bc1b3a9d7cbd3d1d2252e8acda
+Y = bf4aa2d867b433f934d1d567010dbe067905f4e35d7ce568b55aba694d12dfba95c235078461aaab81f1e4df32319e5759c5263ebfbebf7960c57aed79bf2de38948f8ff79ef26d66a7f98384117dce1f386aecc4369afb2e0de77ccd2e7dec328614243effac607c8d5fc5c7c0b1143963573d9f106fcecf2e15c67a3bff6908b286d0e4131fb81622fff9e10f5771afede2276e8344d9ae2f493fb4856d1ba5760ddae38af7ddca409e7907268691baa33dfcbfd69e9aa9faa79cf303ac8b1fa07c1d40d1cea01e8ba0d65265f4c6aabb16ebe2f6ef5aaac25c0c2730cbeedc177667ee02bf4523418a986d5b87a9b75ec201af0f1961cd51b85879147e607
+K = 7ff51bb8946842c7e2f7245e73461e2b0820528548f7ecb53bcadc7a20e826b7
+R = 2f9484aaeda9dcb88d2d3644db2c58eefe2e7695a6c8be9abe97173efc9c0bc3
+S = 0166a7bf4e8bda6b86396943a74a8ebfc603a85ed287bf3f5a30dd0bbe49cd8b
+
+Msg = 12f9582e3a1a76f299d72d9b1502b99060802660226bc47b71e54ec9388eac325902acbe2bd7109e19f377c9d2b4d280cdfaa48888b9cf4ed06ccf5ad866d6932d402592f6be6e6876db5a62beeaf373b60238ab96829243759bdb586f45ec4ae2cb22248ab0b6aa7a7583a61dd3b8f119cd840479a4a9af8a439db904ac14ec
+X = 7142b195eb2417bc234cf32c6fd7cae470cb48c74dbdb469a264c1988eb3e52d
+Y = 72d8100692e1a30a32e37c909eb6c7baea7258b0b78668e75915070037479b884fa9f18066df89b490f9a2696a8505036977604dad268e90552835fdca3339b32360c94358ffcd0b1ea11066122efd017cd6fe1ecd0dd6678081b84cb6e144471dae7636b4a0929ca71aa47b4086665d66d4034c188d64d38b69f0ca171c85925cad2840277d2887a7f7b81e6b12870cc3c69e18ca9c22c3d3a39ee286ca65d23f3e8111aa7c6ea9a0d14c84ddf76abd44db3b9833d69cb99b524c98fdb9d0ff20c9d268e8e7175f13c11c5795d0fe0b3899b74c0dca91476febcb509f7fd507023988145242dfc809ce95c6f1b31f67e01650dd45878efc7ea89cf6e3171e43
+K = 1043805a13045a36e1b6498db97d163571c61cc4a719e506173b5e6df33fc81d
+R = 38cf6b8cbae82e6295f83316a9c49d2dc7c92cb90b19a2c2d45649949354d930
+S = 356a5850d07aec6e9d4a4d7f79d9b0352b087d7ef48394128c5ae4993e8259b8
+
+Msg = b6ac84c49f6bd601d5868ba06d49b8cba87a9d6e7905247541fd332c2b0374cf57d4a0dc0b5a6c3f8f7e24be3a1eedc4a8c575847c02e4edd4745040685670058996250f73e298a43b391a4ad567f0c9bc4b6abf6d1e5c56b22f4eab36aa1a812a1dae8d2873cb2c2a521d320019c7cab1efb11fa4595c534ce527d43ba605f7
+X = 1332c3c6e2d1b7b16f501b6d48c7b866628f0c82bf33354535df99a843dd68ce
+Y = 06dab48a076e8cec27d4c4fb98e7c00f36bed73f11e491d913864cae0fdf883468d735deee5251dd38a1f8b1d2bc19d37f3187a4ef69c33dc9528801a23a98d96fd3f129b8ca2941421ba1828e0c4f8d88c53193930292a0df1147b07c20aa726c7177ef660ddd4ecdd73315d4b9356013e115f067e843c896c1a54c81ffab1bfe7c785edec32fba652babfdaaa039b0568c6beb7d13fb4e4588140ed626b18749b0f79f669f6e7045738cf50a6d0028ba11fe1845a2dcbd9c1b02336fb30eaaa397418fe17e149829cab13d2c2e6b90e5cc81834e32fca8a173634e01f9a973e029644f0165b3033dfb054dd21d65e0c0e137b48c34d42134c47b972433ccde
+K = 167b97578e52869f49730df464f7e8d786594bb830d72db9af2cc88324ded288
+R = 1d600a745a1dec933868dc535a19ee9f1af8bf09b5abee15dc4f7cbcb95ac8c5
+S = 23b81097d583342ebe4aed364a7af9882f74e64518aaedce346c91d6d7ac470b
+
+Msg = a92e2ddbfd18cd307373fcb39dffc33e0b91a48c62071f2f7a8e50dbf2c290889307975b6acd642c8e3d3444acac98c22ed06551fec5dc7c9f2243b681cc9fa4fcc12c318237e9a5df0a77ac22402039cef31b1e623af58212a22e7e60419bb36b777cf6ce65dd1f56963eb28b7706f137c0f7363a002d827e45badc20233c16
+X = 119ab8a63a22a89baf4eb8f016dcce9423d5f40a677b258fab072a8cb622ebe5
+Y = 5141223f4697de272269f3d99437c48dba5ab7f1373fc6bad8161018c5d6fce2bccc40ca78e4d73b6eeb096f175c4cd0c8e9f3e9311951d51ea244fd33d9e47de75f1000248fdc003bc07b501ce58f6ec1aed1754c36826cd91976b408eb7aa9bc42448058ffd3b4e513c6589f8e1bc145a47b2470e7241e2325e54302255c3d6d97abc5c6056266a9523d461fc744146da35c04a4fc0b095881cb94fc4c03bb8623953928490dbe7f84ef68667f23d4cb3ed887449f77aeb158a26d1b39b4e6297f23d49f5b41f170e72f7213ee40364c1c9a63985f69e44eacdfdcb58c35dace8b935d0789a8c0669a23d673929b2a582d6d3b2f9e67be891890da1236c6f0
+K = 77cefd7a6b0fcd0237ff8f51c458e5e8a79116eba6f11ea1af7f29aa608393e5
+R = 34a65e99bf01698b5a68f215b9c292115d17b3c202ea1fda17fcd8a0cd74b636
+S = 7e67d442b8f9ac2974e84ba65aeff0df5f83c271ece792a8dab9c4aee87bfea8
+
+Msg = b5aa1cfe2348d57f0e5333fc70276d2418ddda49122f4a88e8010f6f78dc829ba5c7cc68db664080945c43eeb705c2ef13de6e4b8f4de1d04fb33d5bcd7893d8ca8bfde38c9feca6c4ec03b2ce7b35ed60a6a43f7fc9ed08061a099b3eeeae7f0f1516149d175a953f52c8c518f3ad247c9fba23f1f829d5cae62673ee201ada
+X = 4b75db034ed0b84dfcc60b493a00940e805feb78575fd256b24d146b05a9500c
+Y = 0b66ef2c7a34205d70fc36404957043cf46b28ac4f083ebac3787f55e8dd1f75d9193a842759376f0508c94cc7528d6611b50a73261a4a5cff730d9985bb341dfd739a4e963d1c40f114d7a7ace89e81dd70861efef2ba9d1c6425d5f85809059e8ef31f453c97743fcc94d3b1bd62084e975790b37193eb4058454ab283fe2bafaae803de892879554a340b9a3e2532931eb95d3ac5eb3f290a3f56936951288e1c05bda1fa74dc78d631c2e7a56367ec5781019dfee71453ea6bbd90778e92fea8c26bd6a823fbca71577b6335f3bdf40a30836e948db032db5a4603dd31b851ecbbdf76b4a6c9951d2192b97ff01daa5cb030e15ad1d4cff367f700e79ffb
+K = 654aa8be3b7bfc32f9b560b57a88a8aec1cfda276661283b7f44dd3b0944c20f
+R = 517f7df4831fbd01908b9218b17ae1c40e00c53404b3bd72b64f67cee75215f2
+S = 1903434a727c8ef0e80a43dce2834b807839ef43c22afb502b35a381782bb639
+
+Msg = 27aa81d2bc49601c3f6bceb0870bb55dd10e7ba6d1f8acada70b5f902a0f4062eb93ae72cdfd3f943099cc2a10a3da7bdc9f24b00bf36a29d75136af10bb71ec9c1932058e22ec9c0600d173d37970d58ae1f66cefd27e2905afdde4223979b4041fd7d7166ea326befd5dd896ef47abc6d045c1ca23c1953a6e12cc3c54b4f6
+X = 7e6b77d4bc9220c3352e91abea67e33a335ace34ec4516646e8a4ff098166ff4
+Y = 932b9c0f2d310b6bfee800c074a0969efa246244fb062a745a9a3cfe6f5336a313192e92a2027e1d2c3cfa93aac53dfe05cb8f8321ac882a63bd375af0f3d9ecc73aeebe1267f473a9f90b94f5b6de4357b74eb30cd41aeafc259e85cac7d365ee33382a584eec63719ea325a2414e116f84d2af9654268ec44d6ea2e981581d45d805b383d85c130d2dcd1c71fa68d9c76d79aa8196152c1d9440c33d99de451a359e0d2c51d6aaecb26795406e528f5de3e00947d3dacc695c08a960889a2e94ecf0a461c02afc58b51e00369c73c8140e8b92388caabd1f37a62d1b210e0f314127f46b576a4b8edeb34713aa4136b8a1875bba8a5937066544e34c206aa4
+K = 73c28bca3c8067da792f6312153b298a8f714cad70bb2349803b6dad024f6bc1
+R = 05057a982ab4a2e32238ef2e3edba07fd193d90c5f053c83a9f176e21a9d5208
+S = 03c2b26cf46b7f72691a72d7cbf33653df347f02b0683ebc6cb7ea7e72dc8a0a
+
+Msg = 7527533f2d10c18078f5a8dec350cdfad06d3157871e4ff7d7c2b7ab11dff232d34f07699278f075442e1d4ee00cd6e87c1931333841c399576f4e587a251684e731f7c8369f712656bc1e6c2d209f511179da09368d93290e058e0ce9b6530ac6c5e4cf0a1b22d588d98f32b34e85206e09aac04a0e1f2ae2a5cfdac4e6e2b3
+X = 40792e5ab46518c6ffcf5357f0c5de5d9e2de99c92aebea82a307ab0f5ad252b
+Y = 72c46505e4b071f46ed6b6d530801664a4fd518e4c6be8468a38c22bf74ed966fdc7bfd7c572218998fc4c144b59462af7e294bdf5797ecea5cb2edf8c8d2dabba88d0b84cf28524369c5040b58f090772dac0fe453c32907e9b6c740fb24ed4dacb8fdd25e0661bc0d79d41f103fbc8f96b3e3a4708a5a7f5dbffc98f344bb7ccf0d5ed07af2c2f0d5f407bcfefb54d9b947604e7a78356874c01b8c1fdd749f6a3d619d1090c83725e725706846c16bf9dfdf39f2180623f4f585402cc7d6e2c10b57c8300543686a386056a931be6336bb6173d9fda8b102cf32989cf0978f956d9ae0d8f30752f156f9f92d2954ef13100a75d9f7ff96fe15df07e7993e3
+K = 0c9fe826a7618108684ba2d74f10ca39168feb85f74d2737fd12d18cf27a2f16
+R = 6aa6c4d7afda30ff2d7178b52a3e437ed5b0745a247c9c9e120bd3e833a1dfac
+S = 26e0887911bb5edb6a566a2a1276353391b1e4ab8ae0b259c1bbb3af3d85b439
+
+Msg = 994a49e5e8a5698fdac9a7faac01fb09b2c6113a186677676d11e6049dc98c93c51eb5144af181e1efbf44439a13d295653854813671f032aa62258c14195c4864afae0b5d154f97565cef075bbb6d97e34181410309ffe98b45c1f874326343c36c14f55fa058489dff3b49dc7888f45a099c3c919b25edac1706bb90f164ca
+X = 266cfbe6060134ece2c8b9e6aa25bd6cc935e49c23fdd4fb6adb2ecde63a4960
+Y = 05e233ac49c1fda2a0c3c78b0bc72fa39674055d188a124a58ab3850d9a888861c2fe4d046c3e7c75ee254de70cdb1c3150201c2e04733ebcc25b88770fc2aa82f60526bc664047a026c2290fad8e9f81cedddde7fe3ba406535bf2710d79da01bd2d42bb5f4099c3f8bc2ac864be7892aeb6a1f3402c81474da23e0795cd6c21367509a541591ee1e6364f7e755b1419e90af869930152f34de51f0f06ca3076e68c3e3ea7f4f1bf1d3cde3a0dff0cffa1b5842752347082dda3475992f15a74d298524e636220bc9faed08af7aa5e481ba78d2d2fd8e51942cfd084efe0ebddd7500efc95a6cad37fc4923f9bf65297805840876c689ee079b7fa6169768fa
+K = 60f8416735fa49ab567c0bf1b6da434e1df41579699c1a92a3e70e1d90705379
+R = 3cc269bc7b895864a03231318cf39379ae33c7180a18c08b5aef7414fdac058f
+S = 6a6eb83c5fab10e34f0416628c821a6de0ad0c202443c6df032cc9d8e4948ac6
+
+[mod = L=2048, N=256, SHA-224]
+
+P = d02276ebf3c22ffd666983183a47ae94c9bccbcbf95ddcb491d1f7ce643549199992d37c79e7b032d26ed031b6ba4489f3125826fafb2726a98333ebd9abdde592d8693d9859536d9cc3841a1d24e044d35aced6136256fc6d6b615cf4f4163aa381eb2b4c480825a8eccc56d8ddcf5fe637e38ad9b2974bd2cf68bf271e0d067d2465a8b6b660524f0082598945ada58ea649b9804eb4753408c2c59768c46abb82e3295f3d9ca469f84cc187f572dc4b5a3b39346ec839dfad6f07d6d1f0e215209bb0ecc05c767cf2e7943ac9cfb02eee1e9ef5946e8ce88316b5e15fdcf95a132ef2e4bb0817136528cfa5dd96532f9c3abe5c421620edb6bcbd52234ca9
+Q = 8000000012997e8285e4089708f528070c6d7af8a0bd01409e7a079cdb6fc5bb
+G = 778453049ef262147fed7b59b0ee6764607c51e7b5b5fc6fea7a7a7b1dd6bb283f4a9ae98efd3964b1556758cb15b2a53af8619e74d85898bec77d3b3f382494ae5961a13ffc745da386182291519800f99dd710e00aeb15adee088e2798ee2e46f598526cf0f4667055d1ba009750041dc5cdd2725ff1d97dd340c8518af7671b87d39d67aeced84b66f84e0701efc82a5c9ef954ee576d24c385b14d63037f0d866fd424b4975bdd5485ed740cb932e843f906683f7c7b2c74775d901c361b847b519c0da699638da40bd736b783d2710b2c2cc26ef91271bf4e2c1929f876e902e2057164223bc78d6a2b9f6c0c7a7cb85922f7d6c4287ae23861f8128848
+
+Msg = 39f2d8d503aae8cd17854456ecfad49a18900d4375412bc689181ed9c2ccafea98dca689a72dc75e5367d3d3abfc2169700d5891cff70f69d9aca093b061b9f5057f94636bc2783115254344fb12e33b167272e198838a8728e7744ea9a2e8248e34d5906e298302472637b879de91c1a6f9f331a5cf98a5af29132990d27416
+X = 6ba81e6cd4367798aaab8b7af1135183a37c42a766dbd68cd2dce78f2670ef0f
+Y = 7bb31e98c7a0437f978a73d5dcfbdfbb09cc2499dfaf1eb5256bccd6358cabb5f67d04a42823463b7e957f2b9213f1fa8e5a98d614484701abb8c7d67641fe6ed06fa4527b493ddab2e74640fde3de70da693f1db2b8e26417040af0eea6cab451a795a52e187d2ee241b93f65c86c6d66f45834cce165ac5eb670d4f0095c23ce9757e3bdc636f991ee0073d90a09202edb35cc3ea1cf9adca1617fa0bffd9c126229a604a1d3bf4931ddf0b9942dfc8a2f8c09fcc97032564a79ae1ebe1e2ce49ff57839e7c43fa60b1603d15a450898aa4e4a1ee8065794126d64f013367096a83686b9f158c33b10f5f3b36cf1f6358b3f34f84b101dc26d3db68bcc95c8
+K = 45030b79a395b1632700cbaffead97998d02bed8e0656876fc0174e4bdb96f79
+R = 059bee9e708b7f20c3f791a640edee964e0aa672893c484799715817b3a8f6d4
+S = 4bd41c84a724cc86e4f0194ec0fbf379e654d0d7f6a1f08bd468139422a5c353
+
+Msg = 0577ee4a9b8dbe3c6fb9725174e89940b27e8a989217b64417e66f396a35e5824f21e58236b27910a3be6b57d311aa778bef63dd025d9435301aefc92223c1aabb03d3d5d385b1a3d1f937f0f1f7f8baba91a011207480b5c23a78ebaea69ae8ad4373b2b052d60c5461111479591f8330123bf74370fba66bc7e2b400192c47
+X = 7bd811cf6056c1a821a85a3169113639d775247bc6578c9eeb28d4b09503ac0b
+Y = c54a57b08f255db1c776bb2126ea3c1e60229f1e1981e43f1d6b9110f950edd8245eeca7d55ba06468040855b736db502f01d6b3cb2d9d621c4db44cf8cb390ab2ae332bca219e09bbbbc225541d4a0ec0b4f11a591c077f2382f04bd93b364c94fb1c6147ff7784e82558e5fb68427459fa9a69d78a9f6051bd9431887ace46fa4970f0e22d75d2befa5a228e489e009af97ce9211408b4e5bfe37d3e0700b258b54174a5125eb6bbeca38805da53b1f5829dfdec8c4c9376bf235b7b0eb7119d3d69768b80ee02234589b8d95faf8062a8e1e9c3a686b6350e30fa535eaae71d753b7c3b048f8e9722254dedbc220ac9c9af0784532032ab65e48ccfcfd623
+K = 7ce602ece3f821390641dec7ae01b44df0fc822de1c013496bade2e3e44fff0b
+R = 33c198ea68bec4a7fedaf0309c317d336b97d1eb1f1dc44ebaf5c85c5a3afa98
+S = 5c9b23c13bb607be5473b32ae2b5e8f2a1e18f59df8ca7fd9303f76ed8e680e3
+
+Msg = c643695d29b28210017aa5a7d16ebed81ba00a869d6681d1c0fe90a5e8be9d597329ea15d24ba12d77e4c3f2160bcbe808840c6e77b0528bf9ae588738e22f41910a80a7c6e3340c127b9de17945e7f9229953e2850217b6d486f7cc804e720de214cef02df4a892f7e42898f15caad26bb30bfaf4b0551aeea14035cb756b11
+X = 3ff2653cbc1f27253400a9b6b1f064247053c9816cfdcb704b14bdece2a8558b
+Y = 17ff2a5eff3926ee1520d5a63a13b4f701dceed25a653966f525450b3a63b03229d615ec54cf4f6ddb868b54df363feecc95eb8a3ab2587fc4de9c93dc8f8d7f38f99082d2867b23d073584c831baa0961651e071b43f9d5da97b60e7b5b7a935f6c1dc88279608e2bec5cac6162488085d092a97c6b6f24536589b801b6b48d478796b52c05564e904bc58ac1505074db3734fcf3575f79952ba0a2a0697e55e579d508a400ebfb2d4694b720804a9d00f8845ef0a8e690e675b4c1ce07996d64e666b0d6a1d6fc6bbc3cd9b5cc3864e5e888e3c335e05e83c67c0033ba5efc3dcdec0446d3b40793236ca074c54d2a74dad296d7c639dec938e3bf1ca085dc
+K = 356b49268eb799dc4db7781a06be0f8b96d28f6a13b7523c0ecbe70cb3eea1aa
+R = 4ddd2a1f411b570fef6d9184409b4fd55d12c5e4bddc2ac7211235873322155d
+S = 4043952c108ef84a25a168ea5b64a4386f7a483366054c5dfbfc5fa98579432a
+
+Msg = 2f64d11e290275987b7d7430242289afd54f1be028cf36f8f55db54be70b8dd5ad74ae26e079d0ed31a361c116951bde94d686abf15ac5ed1470c3e902461cea8e5d58f407d2e0c072ee61567da7b353f6c47e694cd607f3ae894a9705e8ea2bf9ceec3acfa6d20b238bf0a7a7eac76c4462b7e4e4e868174a88a6a6c9476cdf
+X = 4800e9ecd9bef5a4d46aca60aca96955d8565e1b85d84dd8141d4f597e178bff
+Y = 41cdb2c1bdfa3652ee49695d5e5eeec00f64b54b5676ee27f043b43f24133f61425b0cebaa1f88da072cc68865c12790c43285b7e19c3844fc7d81d064423ff1e19266f69f7dcb3d0203739f84d73bf00c52d60b2875171216678d59fb557553edc9eba6b84127169fe5dd2f81fc902c970d1d8d9c4779dfa1b14309f81006ee641776a6fa36339e963117447aceb823c9ca3367172eddaf6e361829dae43c4038cdb90ebb68b53c0a22d410b6f1bfa7c47496ea3aeddc36bf24f219b85917a24d30847c77d87d22a7f7486c6684755e045ddf72d41650e97b64a64becadfc47d53555127f8b7ab78d480529571996eede4618882d838bd695efc87e74d68ca5
+K = 460410eaeb111a18cf894468e10a88b8de8ef9dfd9a2ea1882a9fb696fd7823d
+R = 4fe6e2a75d9c72e81ac60dd33d31180df829b31a0dbd5fd20b7e28c4fee27d5b
+S = 3ce4a06bfaf70cb6cc93f33f95a43ad77ed7ad7c77a1674bf849e9ebbc5eda29
+
+Msg = 173c4a23621c32c3e4b157ef96b02fc1bb466a2537d3f6e51a58e510c4aef3aae4bce4c0b4d59bb1c00e7a35f98945ca9d7fdf1f0bac732d425043062bc6d32015233dfb295ae08a324ac7c1e02a117ce436d77d4e46d0b794af04b1db82a2709da1c4449c29ccba93db8ec48eb17921cb389f6e0ae32995d7fee1fa07177a7a
+X = 3e696f226f21916455f8ccc861b1845303867b75303ed92f9ac79088f56ea708
+Y = 673e349cf6d05caa16751d97ba6e344e40e158e6a7fc53ea2db87891341e6499825b5b9edbce9190bd87c3eadf7c6d5bf0a793af2c3a1c8ded790bc319449394c64384305864723a8a7bfef26c082030ab360bf9abb11117e61b00549726d772221f6f67c4a6a110cd9a9658781ea8f7ef2f176c6e8816a865af396db95d8415b541cf0f83e45a417374cf3acf5c6b4a98390522e7140cc8aa3f9d2dd26341d4eb79e4d931a178e3d57dc52bfdf90115e01b76094ad0294979d35d92b574ce7b0c627f08be66f99effadc33aed0f634f6a89507455d7341ee64183aa610d8bb3237147bd90dcd9c1a03d89b26ee31dbef5ae7e764ba9f77b6a7434ad2a8f966c
+K = 2837f7fa85efafb433093231983ccef5d82080e6063f67c68ff93465b59d581e
+R = 393d681c3edba28f7cb0f30593b94fc15cca659a80cfbcb3b236453722d5b402
+S = 44f7421bce1e5273a30ec016bb9969b757197987548e434e395ab3de1b0e7ba2
+
+Msg = 7d6f2a97e1eb085cb9e83aa24047af9ba30a05d7bab564a149b9cd2366518e8f199134fc2ca403947f2a614c0363ed4bc1349dc496a8ec74d880578475e47427628bb023f0272208876a3a7333307a596c158eba64ce42a3c790e7167ba4a327ac71aabad2f36341edea12ce5b2b735807b34b714a49a0aa476893578f0645db
+X = 660898413f7a71804432ecfa11cc68f85a34fdf75012c965259ea6ca0bbcd976
+Y = 777c251067c8ab16cce2c4a4d784c7e806fd296cbbbab0132e2ab91623acecd830e7cc7cde03e544b51fb1d8f0b2eec09f559539aa9d63ebc0c1e32579f095473d12717ce88f6671ec7e3d2581f61bfde66cf9be216d6a208086cd7bea770150a9bb0a5a7a0dace82b464180241202a30b26ad5fb933c8235ac2918e29bc53a5c01ebc1e30b1b46e37124aec596f8d1a73baeae588ce7d4aef1ae84e9a9766c24367321c047c3caba629f5d9185f0ffb3af7e50eebd1ba0eb77eb121b98073794cbc6622b678262ed3e229c6ceeb607274ce3496f370b482bf8f68c27366818486b72adfc810b2f579779adc9c25002e277641dd9ffbc5db5239f677ba1a9c1d
+K = 4abaf5c6f8e28356fd0dc6f096e9354baac1c2049170b2db05c81bacf02092f2
+R = 463b1fd6ef2986f75f9620779bb6f47e0beafa9340e3e5ee589d92428acd4f2c
+S = 27edd33917e49bf771f3fa1355cd3928d0bd401aa7bf0541f3af1643efd7b677
+
+Msg = 7f8785e1c4f82bc0bb75f78d8c4113e0887e761a86b48dfa43a3683b2bb886ba53f5603c8d94a052af3671c5c1e7c232908e10faa6cd54efc79ccfd64811131acd7d60a9309729455aa70443ae8f32a34580f9a1aa7d89e5fa8cd4e95809a573ec6dfe9fe35b1130571982a0dd46eeebb6a16f85ee6314931839e3a4c29dc700
+X = 4be0926fe24da1667d71d2abc2bc0bf87172c05d7c363a324ec61b4642777e57
+Y = 28c06e5ab3c860be8c13f74f28b5792b39487b79547f4afaf6f77a5c3a43e88132edf944ee00150a78b58a78cf92ed941578ec679e106767014e5b279c0eae9c408e6ed60687ee1464988ea545f55be3673ecda10c63fb0b1908e796d6715abd5451843da6e63bf8802ccada32c7c5342374ab26ee701f9db3d34fc96de9d23021b98a93df6877f84fad6741164055696f3b72050343ea3e5cca01a3d57e29727ebcf8583118146c27f42adaf62365b9697cf03bddc69d0bd151f715b23bfaaa27a368114b3dfb54c084e06d4343ffde1cd22058e9623a70e9942e090edc73db06dd3180bb960f0d7fed005b149b69d6d45f40368fc25ae04321eda46d52a592
+K = 057cca710c8e4998e9fe154cc57847bf35a512e6caf3cd338372b5becc66e8e1
+R = 3165b1cf3ca9bb89154ad684e089364f91b6e5d594526072f7b9db3b2358e711
+S = 49e1c8c34724ac5532fff1c7d243b486a2cdc0872ab84fda6cf2ba96f958f46a
+
+Msg = 3e17ea8b9feb2f4e55c103e58c4ead96b5cb892d0982ab2b0cb1eeb9e1ddde9990233a22588473421aadf52767a8df524bc6e6ed857a9fd5942ef976b1fd8bcad31e403b1febb865d2872a7b34ecdbab8b245ada45243a49c7be67aa09788029779d619de30dead9f7d8c9c42153b865b1a9e81180380e27a305a6392f4b2a0b
+X = 75c9b6c63c80755f7a7bf38eabc58e1bc2e0cc5cb4f2274f2d63058157656608
+Y = b71d0ab2d405a5012d694e0a4a82769256cbdb49c18112efee8153c8e816310486a17bce19748b11f3d5d18cb44998eb329b951c23a57cac47ec9973839b130f3a980e62705c0702e4d68425845d54e152e2e83646b56a6757cde06f85ba3779eea585dfe8302f12ae77fa58cbc6dcca70b461024b7d176510a393ec027c769cfe49b698e575fcf99c60293af2ade3dc4df23ff3386f13777306c52de97ed1a886b824788863ff7263bbbb5b5fa0d4681c16942272f5e441bdf49eec7556c1fd409c78e3aaffeb95c1267dee12c24c045ef67aa70e9a3d9244f2cf1ac68cd918df5f62a3dd3de7bcdeaa3f61de51cc01af636bd665c0099d13938eb4fc289b42
+K = 568b8f5049c2c411f05d74e1781be5718ff921026728d285f2a77025208dbd41
+R = 11b7ecfeb339d6014948de5ad4c96f4ba517a2cddca611c8887fc44f14ac9a63
+S = 13287a22cffd825302b0fdc0955458d918727092c7bfb3ec4c3d7a838ea6c491
+
+Msg = c3e1903ceccb2af5b0dc6b1fbaaf1b2e96477e001c43eee3046eed06128c4c81eb2bc917aa8ac30d07e66c9a9469518e3cabc264d6936e5d724a613bf9a44d60797b890cc5ce0d04629e5faa1dd53e7a125a14a26df3cdd9878d9c67e7e18a4655a188885363ddabd73a17659d191e51fafb6d4171ff6c4b651168ce167ada01
+X = 5feba370a58c16f34e931b65c042e6bfe794309cf30105d2fdac4d9fb3e14303
+Y = 429e6ba20b02cd69a29b4a97a6ea564e5b8874ada195a49c3a5293c9bc8d19e0a3a3c4ac8547bfdc7a209bf3a6037e5b0bb7aa291d5940d235c787a2af79a9cd7f83084ba7df85c036ad8ea23c4fdbf91d285c7caa6497af388017bd581ff308d9b56799029e21400c0c99d103a2caec195e40c90d244dac897bd418ae016d25f71e989af516d5e2491e1e4bc25914ec3ad0a9f85968a6777fbebdc73b1ac6814496d9421d2b7cdf17d53f00624010ed6618f1258da194f77c28286225d1b16da3fab76c9b70db1f7dbcbacf4e60b6b91a1f475007ee4d2c5e37fc31e89a0fa808f89e8a4e546bc90e696f454721be71c0731f99ee368afc6998761af9dd9d6d
+K = 7ba86d55b8b5a465f661944832862baf5f565ff0d9195986c809956db2872da9
+R = 77470f0d3923ff407e71a86f0336811bdd63e179891fd30e3452dac1e5175081
+S = 4b969f77c70b5e6ff9350ca25e7d951acaaee907fa7b830a32dce4f91a89afa4
+
+Msg = 4b7c0828b715ec2da1e092204f55ddd65d13f1cdd64c109478d3847487bc48a8cb0299222a7495efffa63ea158253faedcb5314881ab41b5e773337662cc2f50dbccc736974e31b3d080467589951d511032e4cba6647f94c679aa269fca6db92715a4da28ff9803a1dc61675fa5ac114e376fa4dadb37c1b09ed5c31bc5aee8
+X = 1ba85c9c8f4f4ae97013bc9f7fab372e733f3445fd9a68f8e015c375df3b5515
+Y = 09a16e0a6003f45aaaa3c6311aa9866217d4a7c8cb5093514976f6a341260e5aba7cb00ab2adb7462a47a8cfee4fdcae5accda6d42a3144792a14631bbe85534c111d2ffcdbc15b6db9dbfc4bc71d300324fd310c465443cb2a6f2ae33701f39668b118c38ef562e8554fea661a3ef80455699c23430d28ba6dcf042fc920a677c2971b2df8c6729c5b3b1be6c5a047ac1bcc8cd8dc519ada221bd92ca6893c1cc1dc158f9d472f89a8e02649440dded0f723485558effe8cf9df121c969a2d1b76a37dcbffb17edf3121d4338d4ab68b154226c0072d8bd51f23e5659a2afe520dd5e91005a6fc1157f07973610c5577824bf1666ccf851d69efde347f0b996
+K = 11d09ab8f3140f98dd4076d398a9aafb9c98656dd7185567a562cd108932eb77
+R = 1b8b8d67b640afda26fbe67cfd4bea521375526ad58a22d4d97d7af134384f4a
+S = 66d6c240992256eebe078265c3029a88c34095142134dfc31ff0a2d8bbd609b5
+
+Msg = baea89dcc102cd649135d63a5f52df437af7840d699a9daf131eaac381348d45b4e60477fea88803fca31b54829c5806c703eb8fdf412306ff7a79b55aab9064bc37cb26bffaa671debb74c228ba2d2a06da362f613b78e5b1f0a0b5c5febf6bc326b021bd7fc70471b25e153ea51de1010b87110e01497a7f1ac39cf4d424c3
+X = 2c0a2b700ea43f5fd589e665817339b60f837ca0b7dbab50d2ca7e4c362a14e6
+Y = cbd465ce9c3d0a137ee3d582a5172183b8a63cfe414070b247da367456203f986e6786ffb83ad764aba309c2ef7442ce38735f492c0ce6d92eaf9ae6b1cc873ab6ff58317cd166a510c3ffd8d4e6008825b58cae217fa35c94c9bbd12a4d638c20116398b21b5929dca1d49a7b748970e45de0d432fc912f76199137f1bb0c0d2c95bdcba0d303ecdbf489849be8e630ffff0603948c87a7e58131655c9f407708e8a9d675e28e9b57729f0346c0287f43ed67f9c0c0ce1542984851cc3b521afa5b9b8fa53680bdb2d73c2b6b090ef085a7e7c6f76a2e501064c852591df60439a96dd8d663b564c9e5c253ee8d8ee58ab27d8332113bdd51d8b41ac73c143a
+K = 05c7a20e6e4ddb833c4e30a564436fd66716f349af551e9943bac61572e04107
+R = 7689b5249f1943e685095106d3f68359cdb76be5d9a50ebfdf36e731575f8bda
+S = 049da42de51e617cdcdef17cdf6059345b8e181bac64c47123d47b5efe105ebb
+
+Msg = b1303768be174d83578407dde1ab91cf021124a34c4a35eafa4512707a3660d1f884fa6c3d7df299598018dca22f273f602bab371592b11f4574885741ab3fe2af5b71237d0057ae59f37b61dfd1ad5ea27cf8f05f5b69f2936ec79d104f4a46c902fb6790dfdc75b9768cc7dfbae011c795e646f9a234728707fb112c461007
+X = 247fccb44c2c0cb1f1e58d1033eabd203d8d874d0bf18ba70f04b75bd6495bad
+Y = 5602dd579fbe37f187d49d76fd5936fcdef2369f7af29da43c6456a6ac8317b39e4cd679143a4d97751b80ce1cb45186da7bee991e25eb9a1aed1490fd74f6ab507940821a1adfbc30e19a933cc4d21769ccdfc57c96f0d21944f8a0f131626ed013b3e5c01313a1756b67b7d2a21edac486cbc3cd1d2b6fcf20c82dd70b4f72929c1499ad796de894db8af103d9b91c25737073d9df62e6b624b90fb352db781c7f2ff8d3a20a7063fb51272395cc7d35ef79c27b7634e39f74eb152975fdf3b903c23990eede8aa58df9a29954333a3f525d5baafd379dd57fe396a51876f25d9e8265cf6971edc6278ce996bdee206883448af184fae23af2a69572b20090
+K = 0b94ed40c05a4ef445309afb5583cba8d411ff4092452c0a064dbbe6e3ccd1a5
+R = 1800b6bd5c94a031d977b9d017541790a9fe7e414c90fa4d3803d56ef16a6479
+S = 07ece1b64711c9b3eca489e75f2e63438e097498e2890dd0273729a55df0d2df
+
+Msg = 25ca3dc8e6ea4ebb936fa01b1ccc08bb1de923be6292421ff9f773af9cc7393510df2fcb6ec188b27c2688c72fdc2ff6c90f0ab0ed59c9c3a6503f53e32778b954eae582c95803c511ff3918adda02e68e2c3e73f8a6ad607a89d8eba0059eb87f4d9b0081f296961ec6ea78853aa53d24a470a74acf16a2f86748a8da34fb90
+X = 32b6f7ce3ce99770b888c1ef23a86377f3e00adf5dab2e380ef8c4298d20a1ee
+Y = bf2e140f8b8d99d2df1052e981fa0ac533c0d4ea9f266f9267cde7ba03cf10015da1cc13612dcfc92030b7c7d1c057e28a6fb45748eeb9c4bd2e6e79b217f4b68ef03f9659c8e84a20ee920d29711381ce39fe0afc9a7fe2fbdfce63249651230f3e72eed579f0d3659c2bffc70fb5d8be889a34bb67f1a904c318568394b946fd40383782cb5e4809d0c6019d20afad09f29fbbc994d28f4e41daf4666298f351898d8def404712c409745a88962e4a618c234976645559c90c54fe764eea46fa03543e4c4f25c8d2c3c1979f952458177dc6963e3f346a7fddbe0cdf23ddc7d2fa8a3455cd5b546e47169912ce7f333ac6f01e64aec596080b5d3e0f25adb9
+K = 73418db52c6594dd0956d9e3616a205de8204220648addd4bfd3a9fee412462a
+R = 7b1dfcf39b624d64db08a3974c8e14173105010f2bd5135e926f2884e30b46fa
+S = 697eeab669677469f62cca46d3e68c849f447881e2c9f74294f4e8ada4426c7d
+
+Msg = d58a8f5ab44f9df9ed936a1318657c324fb1399c251054986d19214c15ce951f87ccb3510aed9085411d9c5a6740df5160f3e57ea8c942d33547317c7a387c60c7ac2f0e14171f0b7719aba76ac418d157a4e3bec6b799b5da10bd3ecddae0857a29670c99d37810349b82b7bb37c0937b0dd2734da08b8b1cb7beecd43cb615
+X = 23a1290f8acbadc352a282015713d6cf5a88e8901cb9588a57151772619f5ae6
+Y = baa13652642d950d8bcec16c624a07999fb557fb40a266297c15659755fd615cc7e2125d4e8c8af8c43335539005e9e2f2d40428e7c8cc055ff3f6fe3b3df604ac128d995cfb9c867e2a9607aa3b77cf0f691738b784d4be2fea4739fda1f0674260f21f666acef5bd56a7800bbe950792ba05eee42e80a2578d2c50ec28d44afb6b687652bb9452408fcaf257c4b5cd564ddc4e63ce9ca13d4c7473f51b01ac8e4c3f799afc908eaeaccad062b0f97d958a3008cae22062bb166c7300df0b4386baecd599fa8b083fba6e7e4e5ba119860268517d79ebdcbe02437bf4eb5d91a843725db0eda66eedd46d66b781aced0dcc23154e4b8a8f0453b2f466033bd9
+K = 25f8923843d757ee4b7571b42de58925b0c2678ec89df07248b4cf34d83db926
+R = 1876b20926d8ede78d28174eeb4cb0c1af8ee206fc8db4a8cdebb5dbfb0c15cf
+S = 231af07aeba99ffd00659394ab6ed19a5e9f9e60e2197f65fc88c815beae7fe0
+
+Msg = aa134e9db73982e7a37a1034aab82b50d5e58e034a5637081dc880a6e265ebc7b353df210304ba00771c5bab445dc6c24999fe8eafdefabcdd46f7a91f30721a6896333c3f301e197f961944f545e4fe0730cd967790504c49b0ab5b890809be5c7c1c3f8a2e52d92a2c199b981b648fdd528e768e6ab392579b54c72c41617d
+X = 02ef078e61df318237c9a217b5ddbda12ab9ffde68a201971782b61b73214cae
+Y = 691dfea144e51b9e0ff7536557b58ace8716263a70554e2f4676d172332aedaa67736d72667d328170aca070e1bb89868bf4cc98962d87eb0599f10828c6ea24cffede8ed7b39abba666bd6d0d35024ade6aaa06fe6ae45dc4b3a91c219d472db0efed469d69cb5f11d40158ea81672b1ae116ff2c3016f245254e984a59945e4e3b3d37ad12058d84082955c768643e7d80c055c1703a883f2abb075a24c2e93056697340931c25894d1d2ffac4b1022012c15cb707fb359683ad0408b668779e9d9ba21989baa6a6b0b256a34efb4751bcaf4285b15635d409fda993c0438acddc9da006c390360304ab12da76b444d64e11ccf05d963ffb7f389bee831dc7
+K = 013e35ddd416e092335f3bb24a5e826e3e06cb90daad599a42cb5ae8da830b24
+R = 041d229349cec75fb2bd8c35c249f9196a18962ca75ebdb42dca61d21cb0e910
+S = 77bb7975a544c51bf249dee2359523072863934497d1a479d6e4b245d456eb2a
+
+[mod = L=2048, N=256, SHA-256]
+
+P = a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe13a059705e663230a377bf7323a8fa117100200bfd5adf857393b0bbd67906c081e585410e38480ead51684dac3a38f7b64c9eb109f19739a4517cd7d5d6291e8af20a3fbf17336c7bf80ee718ee087e322ee41047dabefbcc34d10b66b644ddb3160a28c0639563d71993a26543eadb7718f317bf5d9577a6156561b082a10029cd44012b18de6844509fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d125dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31b9f96d5f34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff007e8be2f0be06cc15f
+Q = e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e68604d6b9dfb
+G = 5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa104abfb5d84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff8071d63b9bb956e547af3a8df99e5d3061979652ff96b765cb3ee493643544c75dbe5bb39834531952a0fb4b0378b3fcbb4c8b5800a5330392a2a04e700bb6ed7e0b85795ea38b1b962741b3f33b9dde2f4ec1354f09e2eb78e95f037a5804b6171659f88715ce1a9b0cc90c27f35ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de8347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d2183f1ba3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb64fd9a6c5b75c4561
+
+Msg = 4e3a28bcf90d1d2e75f075d9fbe55b36c5529b17bc3a9ccaba6935c9e20548255b3dfae0f91db030c12f2c344b3a29c4151c5b209f5e319fdf1c23b190f64f1fe5b330cb7c8fa952f9d90f13aff1cb11d63181da9efc6f7e15bfed4862d1a62c7dcf3ba8bf1ff304b102b1ec3f1497dddf09712cf323f5610a9d10c3d9132659
+X = 446969025446247f84fdea74d02d7dd13672b2deb7c085be11111441955a377b
+Y = 5a55dceddd1134ee5f11ed85deb4d634a3643f5f36dc3a70689256469a0b651ad22880f14ab85719434f9c0e407e60ea420e2a0cd29422c4899c416359dbb1e592456f2b3cce233259c117542fd05f31ea25b015d9121c890b90e0bad033be1368d229985aac7226d1c8c2eab325ef3b2cd59d3b9f7de7dbc94af1a9339eb430ca36c26c46ecfa6c5481711496f624e188ad7540ef5df26f8efacb820bd17a1f618acb50c9bc197d4cb7ccac45d824a3bf795c234b556b06aeb929173453252084003f69fe98045fe74002ba658f93475622f76791d9b2623d1b5fff2cc16844746efd2d30a6a8134bfc4c8cc80a46107901fb973c28fc553130f3286c1489da
+K = 117a529e3fdfc79843a5a4c07539036b865214e014b4928c2a31f47bf62a4fdb
+R = 633055e055f237c38999d81c397848c38cce80a55b649d9e7905c298e2a51447
+S = 2bbf68317660ec1e4b154915027b0bc00ee19cfc0bf75d01930504f2ce10a8b0
+
+Msg = a733b3f588d5ac9b9d4fe2f804df8c256403a9f8eef6f191fc48e1267fb5b4d546ba11e77b667844e489bf0d5f72990aeb061d01ccd7949a23def74a803b7d92d51abfadeb4885ffd8ffd58ab87548a15c087a39b8993b2fa64c9d31a594eeb7512da16955834336a234435c5a9d0dd9b15a94e116154dea63fdc8dd7a512181
+X = 853f75ac81b3a842c999448562c584d1cd0277896ec2f93c05c337eed414367a
+Y = 356ed47537fbf02cb30a8cee0537f300dff1d0c467399ce70b87a8758d5ec9dd256246fccaeb9dfe109f2a984f2ddaa87aad54ce0d31f907e504521baf4207d7073b0a4a9fc67d8ddda99f87aed6e0367cec27f9c608af743bf1ee6e11d55a182d43b024ace534029b866f6422828bb81a39aae9601ee81c7f81dd358e69f4e2edfa4654d8a65bc64311dc86aac4abc1fc7a3f65159661a0d8e288eb8d665cb0adf5ac3d6ba8e9453facf7542393ae24fd50451d3828086558f7ec528e284935a53f67a1aa8e25d8ad5c4ad55d83aef883a4d9eeb6297e6a53f65049ba9e2c6b7953a760bc1dc46f78ceaaa2c02f5375dd82e708744aa40b15799eb81d7e5b1a
+K = d41b335753e1ff3f828f57b797ff5b2db5cd79f6a1abeaa137a2a830e24ed4b5
+R = bcd490568c0a89ba311bef88ea4f4b03d273e793722722327095a378dd6f3522
+S = 74498fc43091fcdd2d1ef0775f8286945a01cd72b805256b0451f9cbd943cf82
+
+Msg = ac30fb155104954b9d7139de9346d54ca05178954053fd361c9719cea530d2d2e1737fc46b0ee27357cecbd47e0fd47ada0d5236a9d77dd61a1b0db52e628b14588fdba8774882866b04b49cf5205db49445a8a202a5fc3fcc36efe0bd0c1e51eb08616c4a7afe120077ea08caf167e90446862298011ad9a1f11cefb5f74335
+X = d692d2c653bfcab2e7492ec56e512724c912227d793a59882800d37ad260bfd9
+Y = 84741bef3d9f9dab0e3fae7839d39c1a1966ab82798d71aa46b7def465e39ea5e7adaeed2dfc92c9bea72d65268b8df955f9b7e7b6923d2bf00e7e43f83a0e54ca944275dc39c0fb0c8a00ccd0b29b790d9d8f3496054390410b4ae5c6eaf2e21bdb52421179970fa13e0948280a06a576cdffae6fdb239ebd486bf4699270e2bc0879be25a6a0c2f7280ea33eeb32c5d2ea6093381fc4c83c8f9a591b0b0e72fcc149c685b01381a74af4ccb902c0050e05baf732bacd1606533e2acc6308c777201eecdcdcbe935149c4e572a15a205d2b80e75ef2473160f85e642d28370c0f19464125c687c969665b13b095aa87ba476802d72c354ebcbcd89f28ef001c
+K = 39335e9193222c7ae3caf8e5ad77b751e9847c37b9016d355ac7520407c91e87
+R = 28c6bfcadb5f52324e39903bf7a04faefb89383f473daa432cab9178f2470d3c
+S = 4e88f65ff776940bafbbfb35643bcdaeb43b25b45de2de3c011ff1449c8b8b32
+
+Msg = 2225031fd26a6bb4fd9990347bc2c8ea4ba45bd75df68476f983dffb5531899f1317d95f7cbb493de45cd2f11904cd5c5d5a748b4aa127ca730f89a928ddcd250a6551c2f7cce109e64d3ab74afb2d4f4f7e3494eb7d557060a1f29ecb5b75f64848370902bd6ae2fbf6802b2f9c37f34836ad71dd2e2abf6a0a47df4fd5573d
+X = 87bd74c5d70a292914d96b47dc5e9e97a6799c3b788014e7f106ce7ce7e17a95
+Y = 04964c093fdb852c97b165e179f7ef3b39350c2588e60a0177bc2e890ab08ffd73d8a5a6692cfebd0c912de2d50bf02139bf017ec715c2dd7be1aad9d0b96c47d6465d4eb0ea0247ff655959d94a3409e9f9262d877075f6f0c7783a8df3cc115c5287c69bdbf0ffe0ed3719e418ff99b5dcd5f0cfc1065e404a216e095086a6e2197a69c47774377203d99a234e7be61cc4a95a809f9b9dd0a550b712bce5d1cfdafda232d7c831ec52884701155a3df2b086be870af8e875557518b035c84957c1742b8c02b0d46b64a773012809bfa4c5407c3fbfed3b960816604cf42b2defb4feeabc172afbfcbc82836b44b927e0cd4ca63a1daeb3eeb30d1de608127b
+K = 64f504110193cc4a3f400b6fcfd71d64a1e166c048829d23206da12a7dc1423a
+R = 5568d810ba664a08b301266d08c69eacccec5aae870a6d579eda51a31b184655
+S = 9e818868e06787fb9519b50546ee21d0546e16bb1b5920311ba44769dc69c7a6
+
+Msg = 4b1f9335fdfe88c0866bb648c05857b79c2fda92a987b359282bbf0822db747a3940fee05aeb3cc081231e29b9d460ef30a55f0f88702a4ecdcb842beeb36a976136c9241f2eb5c2d93fe38a1580cd58fb93ed137a7d05ea22d5e87345633a0e393feea616eaf83684c3baca4fc5bf80a87dbec3a9787daccec479661af0b968
+X = afa080287898b0787f5d06d5826cc285ae5bee41768098750419a5c8863ae729
+Y = 57767c348ab0c61eab4f2e0894bb6223645a331c5be2490d764839fa4dac814e05e70925d720d0e0ab5faa3db6dc58ba573b4e0b7bc13e4c044b96259385fcd1eade0d7c5174498c70ba8fb8661ed524fa8171570fd52faac9915d947b51f6cf5b74e3edfa064a5161c7623ec6e80d29960b573fb98de9e710c56ee45aabc4022357f6c3712962ad19e43a4148957cc6b9c8f691877a59f43162d8f98f2472699ea510109305f8f98aa3f3f31e4302eb05e5f1a462d0f3bfdcd0c84e76bfdd14b7c90b982b8c0ec7c78cf3e6c216ed1d20b52a132f53c9747c7fbe39092d5ccfcc01a119c92faa3f13d4643e5db22ca1681d6536bc7b704bb09bf6c621c2ff06
+K = d23656910f6e8ea72cdb979cfd8c8f6676c47c6161c3aa14f2338392891d1afe
+R = 7ac95d3e0936cde441e4a290711cc044e6e98e8a8de68298bf7fb90eef589eb2
+S = 140e9de37ec5aeb3fb795b016f51ea3e92d6f198c5a0e5a5d236671c91042c94
+
+Msg = 3b87109bf21571fcfae92b859649bf37dd23d59f76d50cf26f4b2ebf7c5f4ae0b377bf3bf2c7e015a74efc808433047a71bf1ed4ba9025f4561dcb94bef2c2a2c94b3f55ed611c432f98a683abadc2c31d002eaca9b070f2b21319d072df75c62385d7d02897a00f863c2882b2897a331332bb9568b2fdfaccf50b3de4b42e8a
+X = 668606f4a82b50876abd7f3dc0ed580a10344c1dd092c5bc1b26c427028cc5f3
+Y = 7c16a9644c18257911b826da10b5b10115ff77675bdc3c9f77097162fc059e86b04c1faeed3c66306c7e5fe2d5c63e8fa5fa2b82565ac6065445de5819a2e4a56925bdcce138654dfb490ac624a38ad65849be4ba74d14c829ef102248a18193933335eaf0c73b7bfe77d669f857ef3addb1f4ca424dbfdedb9e2de1fc0cc2d9777ee834a0ac7d0cac1b2a613890071490efe5cb2097ac830fbc27881f9fa51d3b0247c5e1b7f6be13c30dd31c2c59b7683ce60a0ebd6663de97870af2dd17d91431323a4686bf32e1e39732dae1300c57bd600be790593b2efa045bbfca956768157b4724ca0a1472fe6c8dcd82a38024766341d1f548ad8f36dc676676fbe3
+K = a3d781e5385d66989b38034171da11594b20f15733fd4701a63cf24bb58ec341
+R = 1e219eefd616caac549a859d45186b5c528627573958fe55cf57fbbd1661f7b8
+S = b09545843dc0f6299b48f14311503605502868859e8c43867f80df3c2391c762
+
+Msg = 042365b1256931a111facc6c40f618c428801b03e4f222a1e1b7763c3b02a6214e4c517beb587a4ea69fdbd4ea2d5d5f45afded96ddac87dc89955613aeff7644fc6a58bb859a85221318fbc5e175c6985b19a1d16ab6ad3ca8fa1903acca42bc6d9efbe88fd6f2a8650425be97bab9cb670b2e39f36d526278e0bcfcbffc3c6
+X = 1c08570d1e1ac0857f649e4ba20de0e9aca97374acba6bae350104f1fce20be0
+Y = 815411ac6aa1b495c4bac802806a1a3592924fd9c0a3cca41e076db293d815c2f2b0a53e97cf657c8951b856cca1166ad433be5829b0b636ca9de49111ce5ceccededf36d795edefefee1d553250fbcd5bd05b4d99de55f147773ab3a0f754d090ca7b6ff75c160eefd1709a5df3cd8a0cae3e341f2275faaee3e3e31737e7e9c7e74845651f4f839c9d08da6bfd00f2c2b9c6ed9acb78d11175fa6ded7ab95dbb2bfef18feb149bc94f6de05a205221ba0406c96f63972aefec1beef030137011e6796af2e4ebaa100150d58caf408217acb1183a1a46e06368cff6fd744da7019e7ca109acf1244a763cc2b2186f49272ba3ae0425f2ebcd30e77e9f7c957a
+K = 0bc8f6e0b01bcb55a4d134c967f3a9411737103d400a33a968f9036292d6e3bd
+R = e7145c70e0038ae7e7d901b48828b0b8bc960cc4fa29a52e11ffc9ab08eee726
+S = b9c54ef6cb3e1b0498952299d1465ed2c5d4e670cdfd2506462466c3b0fcc538
+
+Msg = 98ffb2899f17c80a83e82ca6265e6f361733a6bbc63cdf8880dc756bc768b35b90db7390cfff745ec1b56f1655d8d9a29a6e8a63be0b1b2f9aa7436209a1fa061a7aec28622c472b3d0285a701655a496546e891a8ab29d9f40d2e748d0aa2babc06cfca641b300b7a219caa9e5bae3bf689f60567f922e7796fe47bb72ffb64
+X = 79885ff112bdb326577abf52db67784768742b36e575f06b8d1e4f0d2d49a3a3
+Y = 14111dca30c0138761fd2f55972b9846041e5ca8b9bc6b2dc820f2a2f5100abaab337c7e0d1bc59de5ae586bbdcf4d4b14aa23be40095293123badbb11919b78cd6412548d9f9d15f614b6928713344148fd7d30985fd2c509b44d396c5672a082de4183fee03e45a90eef6a08b0d9d47132c82a2ccfef05e2ad0f340dcc06d9e2e979ecc43844c6054e4fa5fb8a73a1e3873f2145b0fd40f3ec7946f1f43de8b8057c1be5bf04630a12453d623c9b8d9f0e30c88c30434215d48f77348e6b047f16934ea09743dd3b009cebc49dbc3a3d3567c3321555ec96b2160caf7870970ac3cd8294477a0643ad52c23d9d987dbfff64aed1a883c30a49f14ff0620095
+K = 13ab2945ab2a40067a93ed8c1a4b305182cb070022b79a56740238e55b07e8a2
+R = 4551b096446db6761b708f35209edb91cc51ee4ef96a7495407ab4167a05c791
+S = cfe4c58bdbf61caf09a42adb1aa5d98b4c459c0112c57823bc15b5b990d92ff1
+
+Msg = 5898cc0b422bb89f066dabbd30f59e9a35a392bdd7ad315ec8ad32b8f0f3d02864e70ea36e9076c395f0ba9de1ab6080df3cf4a1470e2b9990b8e7614bb8312b075c0b2a132d7e47ded9e4c0a1368455b9d1a67bc44af2f37428f48f7e089ab41d046378b6d48d9cb135eee4574072abea93bda7eb4f15a206cdaf3bbbebd318
+X = 416634f9b7722188c2a5266cfd9baf1bdd508c0c068010fb228c099fca7cec11
+Y = 766d7e4f8bc3254d92cf6a64abd504d01cdcf6c239178b0aeb3f69c9bf202bff7566eca09f29cf5d6fa4736d57c08205500d648336409df06e7f2cf99178b20a7ec2b5124bcffc61adb66f6fafc51e32521dea2124e5781c383b116d06a6a6e89dec46b5e4ad69f5a1e8dd7ac5e160da336c11860b601e7e6d58895e6797db5aa92deb7b942f2edf58d43d3dac9209557a6aa07b228e73a80ff0e92e4ec4603d362e1cca7e928d9459c21405aa0f6548732c0fc501ce50f0896f0763f633c8c1a8531321e1a0f47134a0d2d8676f45f13ea576e64c7870028033a4261bdfcec948ebb1aa25b02134d0259d73024a01da0cad1ce67571e36963dc130496160ebf
+K = b057bf5a5ae4204f941ff5a01560cbc29033dc6a2e06ad168403cbc6512646df
+R = a237d2c3d23706caf004a2e94de29f04c748936b62ab5431fe73c72485814265
+S = b48b9ef9cbd8bdf799b70605f00550b81b309c157332153be9707a399fbdd67f
+
+Msg = 0418e01236caed0f80241ce8c6307d026f5e25f4a922bbdb4aafb8d9db95a18175f9dcea9acb4d376f36ff7b7cb598e073de95ad2012eb9d11e15cb3941c6dd0dd69422e78512ebffb19cc8a403a9a7d1f1720ab0f2d25627580366093e21ac1537f93de90a94508f1d7a7a1db5a7b13c9fd00b82be044c3a35ec0451c309b82
+X = 6ad92911dd4fce033d7a50875e4660be08c44957b874339c2a70d915cc03e27f
+Y = 4cf4cee4d5abc2c92db522928b6d7e436ea00884009497ed588e93281cf05b3747ca0048b917708279cd0277ce8560c22775d2aa0e7eed1bba77be45417fa7afd776b8e560679c493a520a0e626acdc83df021351669bdf9da19b12bef2926b525fa4c8e3d1f2083ea6bbb489880f594e67934d1f35581ad18e0db462a1ac944066c65dd743f35741c6cf588918d8336702329c62113e9486bfa49ca5425914526a965e3c1975824f4b39fa5fef89cf6f9ea512f7ffc9138e72dbd0f71b01a70975312eacab11118471115ee3fc810522936c9df35977509b196d867fa11f607b7ef9ab78cb748213a6763439ce5e7641b05359670612203a47d4de9c5388405
+K = 5aed2d19239189cd0bc8cfa3c329748c0555d8eafd5e80ff931966680e3ea454
+R = 83ee960e6f9026fe2454d859462ac334a13896e75179858ef40e2e9a065c536a
+S = 7ce8699c6ccb184d4240b8709da11451328cf1a7e0cafe6e1c8ab53d7de67d9e
+
+Msg = 92c949fe2342f91a387b67c1b12b1d04d0721203caed593c9c464e5fda09fdcc91d3321d2985eec08ab2026d1ec3fcfa838cb6af45290c08dc30b9c14c4445d783b6f48409a00490f4e308dbc87fd1b2f878385212e1f4c3e1cf81c56d71e73fd7a095b56b4abec15c57107420fbdfa44477078ccf4519f9f6044f0744052035
+X = b0d23aab4d95446f8c6c5d496d477dd9486f50b2827f7cd19728bc96f82840c7
+Y = 256d231ac2bae650d25999b2706d4cb63a89b1468e0df36d677535fa7a0ea890590d3290d4b50bdb399f33dc415e4469c97c6c0cee8205eec962d7153c4c85ab88f7cf80979d4a1ffd8c74e681c1d28da07732116c3210ee4b693309333686246d667074c7172035fd6091b2840b113970b45983d474f54b95d26394b7a43e81b449a2ee9423aa1c27f4592b516c12d5433e2ba724f5463b4169a2b0940e1bccd60ccab9b5a38248acb60582ab8bbc01c5e75f9ef7474273fb51aa6316e649f4f22452dc70bfd4c3da072c03ea82ee009d4272a84961c98e517ab947741d812116011dec0373ca8fbac5576c2069b067f8b005d60a36eca44f56019a64835d76
+K = 17a199bd383a84e22029fb90d5abc9a8a7ccd3f0a33720ca80e3161971793526
+R = 84cace71a80ed47494570fc84839f2e350191b74f0eefff2d7ab2c689db77bae
+S = 9cac33594e1934b68f62aca05ca040f3c82110c10b7379878b7894b0919a0f2f
+
+Msg = df6a4eb7cad4ff9bdd8356d3568fcf0285c1a4e3c3109faa091b58a9bd907c629d54aa7a23a74870545a0942a2d23914f2f167d96573f06f35ea05ef704cac8014dd21b961d3dacf7b930bbd7e35550f721094c86333e03ed4dab7bc1b6416add9578d279edaee37504fd25ec0c5e8a37ac9ec19bfb1e3778ed6d9c6b6e35ec7
+X = 679ef48b643be394677d17e837a0be6d4d8027a900b686aed7c4b12634fea76a
+Y = 2f4b0c01e4b15eb5ee7afa9824093330738be2f3f06c42b2b7c6968fa54b987c184e7fa89eff16da02b93ff61b9ce48eebe7eab0f7e203ad11c71e7b297d23f2d5a5998272c30c2e1724b5e963bfd6f83239f874d88ea089435b896dd2109b6a14b2d848f9ed7e92143c0649f97f4f2eb05b8c5a07e99e497dbc752d443eba93d7f3dcdc3240a2714ea0e3e7627f216e4701148dd21192f274f1ed5df05c60b1576d3a0b7f69a776b5010404acd5afafd3d70f57763f2b778d0c361e5f7f0bbe17aafaa5cd393329171d06ec032039a9ffb37c3ab8cd858ea788a7b9f501996baf959ca85c7dafe0cd3e30957640eff105894c43f866bcc422698d128dca0887
+K = 3cf9da6f182bade870946d3ed3b078208ea8153c45515d64f589bca72b703ebf
+R = 1dd2daeaf3e89fd644c6cc942311ea5056413d8a24087787675ceffd3d6c15e4
+S = 3e12781396558560455c4e70f610522ab2b10fc25343296818ef7ffb0378fa47
+
+Msg = 4f16681eaa5d97673a7cca02ee8a7374b75411e0b5704a947f04d1a5b14be0b506f31c2fa329e3ca516fa4f1626a9b5e080bda7f353f850365eac7c3d2596f502a5d70b1542276c12d4ea4a22b5325b9eb3e942e556769b796c4f524595f1cc6ce17f99f9dbf51331453228ead327b614f4438d35d61428429f78c8c9377aaaa
+X = e0e576432913bc75a2e0de3b33bf3094148298612a9dc56fedd47aa569af8ac8
+Y = 2e33604ed9e6c0f1ba403a8c3c3fe8e8f488591813aa3d2fcccdf88fe808f70adf173f0f143abdaad43b80769e30ffc5749e8ad35999953deff4f61f4ca07313609e23acae7b35f77934fdbbe1c380b2727b1c3899250af5b4399b658b7908676d64d11763785373b2169836611d72a957319936c84efd72b72f92bdd2dbe0000d8841ab6d8d0d666e79361abb23b6007348dbbe7a94936dc6b026f3b7100081f547b994e0e0778cb761ebd43a29d8764c7f962a747ecc92e4a2a628f52d8abf43f6e3278a0d32ea67c2d79d04c83387ddc709365c0a0bacc83d75c946e283e0739233581441aeddb0d7d76503d621405d27ef66fa8b5379d178617d4bb5ad59
+K = 53cb2d046b391193efb14a4dfafa296c2ec92293c7b3c7d19a20e68c4a1141d9
+R = e2ff3fc441db4540194a7f5da1ead849c2c3c48dccf8b2c1b3b359a7b16e16ab
+S = 52fbdcd5c62a999aab46147fef9e18cbfc7daf680a7ddb892edfa44d285e2158
+
+Msg = 09e48a36523b5289ec41859faa141e2a29b3e88ab2d6351e20de001e6424b85337675f0ce26be224fa4f8df0ef9710ea285635b27b297d688e338b5461820b57be4bee21645b04957ca2f6cd7af9a6a52b3c97c5b9db1c2f7ea817cd6d3c8522d4e6a9de869aef26ec0dbdd269c79b38806927bd3a5100735e6f9f655ca94dae
+X = 7891b05e24823f283126d7d175a4e8c8124b3776f4f296d0ffc4b5e21bb64d70
+Y = 7e38cb668d647ee15f71ac5d2b55c11fd4731e1a6c031dd7594d614f2f1ed25623fffdc5956f5256e635c914205a2937a6074cfe1f3e443bbeb323a23b0f0fbccf8c1770ad18ba97d0acbea1e846e12cf12c370625b1555d710905eee943539f2241b8fb490c9d6b44f36139226b4c1f00e95ffe595014f61bf579836a14212c07231a5e9e87de4a9aaf0f46f34c9229f2eabb71d40de26a1cbe10db0645cec37d48575a1154bb5acc947becb2a74b07e2a0e45b903be37502f91b07fb4ecd7f21fb130c6d639ef0fd8444fa12de859abe95548801f6a3c40e7a65fd1518221a274d7b65ed4175f66c04d919c86d2ae8c374b14709e9c8a39e1d0c4e9935540b
+K = dc24b379ee2d26d5db792839795ad0d4b9622c0e3fd518df541a5f6e9cefba0f
+R = e550dc65af275e47be480fd647366e2b055c79ea33ded4f5a9557121e082af26
+S = e26b1a5f27cc6c87863e31ef7f1e61bea476fc5d7c25fdf22fe740f23aa9a752
+
+Msg = 8837bbceef577511f2d0c08f790d5d2e8562d93df3d82dd4c2827cd9a9115308114a18c452db2785561081eb523685ae2b3c8b090e0d44dd40d2fc0cdfc88d6f9063a7707df609edf0a8c55034815ea9f1d8b0bcbc92fba513ba81ee646bf98ad4eb22be26a4582b1be2899c91eebcbc9fba5825e021e99be0c9d28642d13fa4
+X = 116d1836a131310644aaaee6ac39b3643cd50026a6b486167cb4daac242a4e7a
+Y = 77d7a40a7bab3f5778f85d4fc48b3e28ce28b2df9eb87cc9cf394ef28e8064f39a9690103980a66da219cb5022c101f22011a8157a7568c5ff2e978ba2201367d17c22a867865d00c2a437385627bd088bfcf7219251bf6ae158269f4ef35da7095a53c24f37d61bcfb7c043feb6e93832343f9e90ee7104c80486ecd087be1b67f18cdaaa375e039cb7ad603cb0cd855623e9fb48e4eede14ea3c76a0364aac006650d3b5cd9b474b56f8584be58a721bf34dd0808d334cd8632e808536791fcbea961f7163dad28353c115eb3e856737dbbee03436721637a47754a8a1fe0fedf547b358a73d05b769a95bde3440007c0773a3c7c8dc9714e11c3a10ee01d7
+K = 4a6febb624c8ebd411cfb30c6db055dec3d0d17456dc0c54bd1b43531d4f2649
+R = 7b6b3eaef6cd5fe6daede86d63943478c771582483be0b926ee3022d22ef912e
+S = 39d928b59a690450d13359a29efe20cb98bfd3fc9726f80e5148f059663ffd08
+
+[mod = L=2048, N=256, SHA-384]
+
+P = a6167c16fff74e29342b8586aed3cd896f7b1635a2286ff16fdff41a06317ca6b05ca2ba7c060ad6db1561621ccb0c40b86a03619bfff32e204cbd90b79dcb5f86ebb493e3bd1988d8097fa23fa4d78fb3cddcb00c466423d8fa719873c37645fe4eecc57171bbedfe56fa9474c96385b8ba378c79972d7aaae69a2ba64cde8e5654f0f7b74550cd3447e7a472a33b4037db468dde31c348aa25e82b7fc41b837f7fc226a6103966ecd8f9d14c2d3149556d43829f137451b8d20f8520b0ce8e3d705f74d0a57ea872c2bdee9714e0b63906cddfdc28b6777d19325000f8ed5278ec5d912d102109319cba3b6469d4672909b4f0dbeec0bbb634b551ba0cf213
+Q = 8427529044d214c07574f7b359c2e01c23fd97701b328ac8c1385b81c5373895
+G = 6fc232415c31200cf523af3483f8e26ace808d2f1c6a8b863ab042cc7f6b7144b2d39472c3cb4c7681d0732843503d8f858cbe476e6740324aaa295950105978c335069b919ff9a6ff4b410581b80712fe5d3e04ddb4dfd26d5e7fbca2b0c52d8d404343d57b2f9b2a26daa7ece30ceab9e1789f9751aaa9387049965af32650c6ca5b374a5ae70b3f98e053f51857d6bbb17a670e6eaaf89844d641e1e13d5a1b24d053dc6b8fd101c624786951927e426310aba9498a0042b3dc7bbc59d705f80d9b807de415f7e94c5cf9d789992d3bb8336d1d808cb86b56dde09d934bb527033922de14bf307376ab7d22fbcd616f9eda479ab214a17850bdd0802a871c
+
+Msg = 8c78cffdcf25d8230b835b30512684c9b252115870b603d1b4ba2eb5d35b33f26d96b684126ec34fff67dfe5c8c856acfe3a9ff45ae11d415f30449bcdc3bf9a9fb5a7e48afeaba6d0b0fc9bce0197eb2bf7a840249d4e550c5a25dc1c71370e67933edad2362fae6fad1efba5c08dc1931ca2841b44b78c0c63a1665ffac860
+X = 459eb1588e9f7dd4f286677a7415cb25a1b46e7a7cfadc8a45100383e20da69d
+Y = 5ca7151bca0e457bbc46f59f71d81ab16688dc0eb7e4d17b166c3326c5b12c5bdebb3613224d1a754023c50b83cb5ecc139096cef28933b3b12ca31038e4089383597c59cc27b902be5da62cae7da5f4af90e9410ed1604082e2e38e25eb0b78dfac0aeb2ad3b19dc23539d2bcd755db1cc6c9805a7dd109e1c98667a5b9d52b21c2772121b8d0d2b246e5fd3da80728e85bbf0d7067d1c6baa64394a29e7fcbf80842bd4ab02b35d83f59805a104e0bd69d0079a065f59e3e6f21573a00da990b72ea537fa98caaa0a58800a7e7a0623e263d4fca65ebb8eded46efdfe7db92c9ebd38062d8f12534f015b186186ee2361d62c24e4f22b3e95da0f9062ce04d
+K = 2368037a1c7647c683d7e301ac79b7feebc736effe3ab1644b68308b4b28620d
+R = 4fd8f25c059030027381d4167c3174b6be0088c15f0a573d7ebd05960f5a1eb2
+S = 5f56869cee7bf64fec5d5d6ea15bb1fa1169003a87eccc1621b90a1b892226f2
+
+Msg = 02bb64d2d5032f54f1ac9e9ee164db83af0cb036d88d41e9b2118cfc39d1b4b4dc2c497549c7982ccacf665d1b0011268246c7c17f562ecba25e265489873e0dd9268e9b06880ba74e74b56f50c7324d29373853e3a0f3ff787eba4e5e7f9437f8ec8a5e868324e9c17fb3d0e12de2d31d438c5bf38b27167d43ae4311b11062
+X = 521f08c10774077ac15bc85f2f6a03d84207b4ed7bffecc35d730cdd1126877f
+Y = 11f3a716fbda7af35bdb62d128af6f21ec2ed4896aa81e8769c6eea9c21c81aef23ae0f525269dc405accef098377f652730968a33b50f0a4c7784345280651caa034df87342ca8973ad86ff7f0f8773a94f95dd2bfa802d268dbf3a2103b1276e06db2d734399f2ab7bdcca097616fc46ed2478e52cef049d19444586e7b75d6a56741da2270f54d2c739ec8db996c71f06a39af2383c611499be0fb34809b171254ef273516c33e17e14048ef2d21d600aa153bcf7377fba9405c6b2e5f2aaf0f2f3467d7461f62e814a2c461e8ac9db0df370e18ec6eed8212acaecf1e7241bcbcbca671060e50c29f966f1ea1e92af6903f81c7ab9ee09f60577bf30c186
+K = 08b161571ed031152677136b54e87119133f7de56268aec07cba07667b98bcd8
+R = 7a5d2016afe87883491bd6cd166edddf138c1c89961e4af6876be08b0e06ad74
+S = 34efbda1849dedd0d1aa775dab2aa2b14c9ba0206592fbc34eb47b844646adc2
+
+Msg = 4f1c0053984ab55a491f3618db1be2379174a4385974825fcbe584e2b6d0702abb8298dd9184eef1740b90a5eae850e9452b4e4ab219e187860f0fb4ad2be390ef2ba7d76cdedcaf10aeaf4f25e497b4da951375b687a8d67012d3f99c7b5ca82e9bd0630dffcd635ecd8209cddb872da5bf4736309783345a35376b4fce4b91
+X = 6ba8f6638316dd804a24b7390f31023cd8b26e9325be90941b90d5fd3155115a
+Y = 10e6f50fd6dbb1ca16f2df5132a4a4eabc51da4a58fe619b2225d7adab0cea3afc2db90b158b6231c8b0774e0f0d9074517f336ca053ae115671aee3c1de0f85728cff99deebc07ffc9a63631989a9277e64c54d9c25a7e739ae92f706ee237b98b8700a9df0de12d2124e2cfd81d9ec7b0469ee3a718ab15305de099d9a2f8cecb79527d016447c8f6fe4905c3718ce5234d13bf4edd7169b9d0db9a6b0fc77b7d53bdd32b07dc15bc829620db085114581608ac9e0937752095951d289855d0bcc9d421b945cc4f37f80b0cb25f1ffee9c61e567f49d21f889ecbc3f4ed337bca666ba3ba684874c883fe228ac44952a8513e12d9f0c4ed43c9b60f35225b2
+K = 2a4a4e014c94d8546c62f0db2fd488f5fac03073a11c3760376114ab3201930d
+R = 006b759fb718c34f1a6e518f834053b9f1825dd3eb8d719465c7bcc830322f4b
+S = 47fa59852c9ae5e181381e3457a33b25420011d6f911efa90f3eaced1dee1329
+
+Msg = 42199186434d6c55bcef269bee685c4e1580e243027ed128ca99492033a52954bd1ca8ecc5043820725a3c0d71a181a05aabcb4ecda7180d86855e7b4dfa9a44c7af4c98fbf1f0624058804fd8eaae4990d4d7bb75f01741ce36cfc9c137254cab065a4617d0d0cd5f58ea56868a40f3e0baf7db5d2557f4b9775c1820dc1d41
+X = 46d690ca6b9cc01e9a8c7bfdedc59a97eba52f097b8fdc19bc1f8c0ab5d4bfdb
+Y = 6364a35ae994f27703319c36d90793c8f26511846ba06038995b6556e4443aa61eb0f8efcc3d47f7c5f85276ea921da0784a67998253c992975f9e13847ccad099d9c1e5c94cfb195488e1293e23b74db00603e8bd6814c94690bf0cccc1c0e47f0c6609a48e144587ece178f72c8514a43590bc4c219da95cbe8966f4404fe9c288f23cd0f973e77ec84b4b0f163b50a3c556cd1d3951faebd982af44447e60d7834b93b6d9c3ff0961fccb908312a24376eedc508f806668d6617b77491a01d5d069d6ccd5f21b5eb3c3a3d4a0479593845c72f720157b188d2dfae4401c57a600b142b6bde2a69f1a0afba2f507a63cd6df056bb5b34fdfcee012d341b3f1
+K = 638e5fd0885f4c9f7e5f4e6a103b2d2d9d1368c493f9822ef431f54e65a7a3be
+R = 2551d4f855174f7b28a782b89697d48fbc314cfeb17ec4c9902a8e557cc6f6b9
+S = 278b786f9e28eeccd00586b445e75f48cf2649f3f1b7bff72b0e767f3443dc58
+
+Msg = 4fdd888756ac68f4c29cd5b1de42756794570ca8f18ff795f6f0fc856772b6a2189b5ed4a9b7547328075b56c28ddf50b84c27205cee57b29d0b387970e89a6a2236293bbc9e399013d1dd3bd5a10ab0d259f7fda704f71cbe3b8b8752806a0c84668d85e4d739cec628dff63371d24a4b14137382759ba400df0e2c25947d18
+X = 49da89d1673704d1f24ac7dc799bf006aa7d606c590e5e37e38032ec51a70376
+Y = 5b619845ba969f1ca5963fcf04c03aa40e989222774e957a54191acf9ddc407a54a161e22a5ac50ca5d61e6601cc7995bf0db38ff0fa1f77b244fe98148c81f208dca29ffa30f1131c76dbbe4303425e9180b4a48f22c757ed8e388b61bdc6d55519523d00c31a5f8376640d4688e60dcc172deece73de28437e900cb19a5311a0c9ca9af6cc6eeb6844e9b8359e3ef1cbe03784107d2d0aebec7c1d70d9385a4d2b8033851f5d5b7aa18ef570aa037fcbd3e30f2fc2013ffbfa0787be6d59ffa1616eed5e121ee4dbee04a9ede004956075465a7688701e04ec9b2153f52cafbff7ff9226e69397c7083c3aa536d7109ee430a65448b10c1818c70510a339c1
+K = 14dca45937cfdbca5c799f2ca50de2a44d8051e6d80af242c9f4d614419e6e07
+R = 4b90993d707f3371d0a0cc87255e99a8fba18c3b58ddddc1067cd394172366cc
+S = 4b2612d506fb85e5aff9fcd56c09bd12bf60f78ab7dfd021a742ff85dc507ae2
+
+Msg = 8507db5f1df9d22f447c20e4320f90d9b30722197196d1a2418d06dca41b3305f6fbe52ab58cc0b60ef1a1d257fc2fb2062fe6c5f2a25f0293ca39d0c083cfd5e4bdadf2169ad4ed178c88ecb5554ffa2b53aa4398115cde627d30144ace9325b2d79d7dce951509d734afb0ff6d9265b902672eb5884e9d8acff0ea22c76938
+X = 82ab2908e3d2335e07c1002764b07b1ca46d039a95b59b450b16d37ed4838872
+Y = 438831cb0eb09aab24275454354ce42b9a2eedb31f421219def74687e6f9c92f0b1982355cadb26e095b7ca25de530aaba63e64fc23acc3d1d1f1b70cb726156ca0a799b59094bcc3b8998a4ae7744d215d63b887082f4c84128e74b9b9999c60cad3bc6bb6f727284b4311a929bbd964c9a7074e86062224dcedb58b9b598546ac95b3b434ea114ab0d678541d6caec0c56009bc347a425f167cd32a34eecb7192424d57b0e54b4a9e82f425138703ce89b189039e92a770b51497f8f10eae9c3459ed87e5101f5ab1b6271485fdb2dd3dbc4217fcf67c7e92d0096dc7da9727f5a434b7545284cd8a283070b5a49d711dffa85904311e0345a99147a168ea0
+K = 1ea475584982b639ada8c84e51ef72738390ed6fa44395f11428dc5fd794a81e
+R = 1d2781f5f9d08ab2feb1683942c2c29a66318839a7dfef9aee9cd7a89efe2ab0
+S = 3adc7be968502ead10feec191e212ea0e07d449006e7f22ddf869a9fae711834
+
+Msg = c7844960966584c8e3a59dc37df37b7eb3ad333148a32b86c1ec18072f3b316c59cdef98ba4dc46f532a4280200c225fac6cd1adf0a45382c2d88054e447740454976e5272330c7487eb42a095f7314139938c7419193b1c128054c1bbf10d0634e22c6e02d8e12279cac0bfa01d3058e0f8d5547ba0f71529c27e0084d4bde7
+X = 0c76bd647c6fafe7da1029b9bf36a9f042195691a26f36bbe0eca3d4b1e6cbb4
+Y = 2de9d27f1a030199ffbba770e08aeb1ff3708edf8ebb3a8e664e3bd1511db126ed87bc44c2d2af40b9d512c50a4d6c10b23e3ca61819f5841cbf5d0bd6c88d46f1ac6474ec20b9100b328cc155879166f46b6d71140b0cfb2b0725b64a38d70a91ca8f0e3baeec6125262c52a95d5ca5d5ff6f4482b1825006cd469f9e7f31769a73eddb5f7017f18bc747ae4fce450c4274f4abb960577d13b6a77dd99e67d11edb413e428e50726f7052e53565fa1d6fde91859573c9289289ffef0598802808ecc5501cb300e06405ed0febc3df23f40a1f6532410f7d9049b920216f7d5c7a728c8dd63a8d0060fb53b3543d62a636661750fd43775e80b509004351475f
+K = 71e12996d8aaa7cb1e730713fa441098347ca95eb39362c5a78ee6e847469c7c
+R = 09e654b17ab775959628e7cad0e27053ee495bcc29cc2a5e3b029660a77b1330
+S = 261ad41d6bce6d04d891a43c16ec2a8114e51f0e47b48b1dd1f3d626150338fb
+
+Msg = 6f3f74388cc90b29c109ecbda08c79349dffdeb90722974d79d640620949448f66ae673eaf4d4af8c43da673a45ed152ea66fc97166baa7ce8beb666bd57ca43da6801c0ee5a5a9b50c5047935d7a8552c381d93eaf03cbbbb88ed0d3b5a2521b67612a4405120ef0205e89aeb48d577bcda3ad20e0a7cd07f8c9b215c845dd8
+X = 34c0d0de98c85be291b68a5b8c7fb3536b6f7447e8565ead9b002417f56f4616
+Y = 080ca412bd197c5aafa2c6df5933a6210fa54089826828d5496b453609a56b7d55d232fbe650dd9f62c05c050c026a8717a78b5db01614a19301c610d2b9964a7e3357c722a4c553273bf27f871b4b9241678c334e20827a5f511fe9319a075d12753ac0960df60870a08a12f09b9d3593781781a0cd75e9d81cc6b9b0d506d100fe972165b68297e6070db2d8b6ea32176d1562084f6a06e08e2929155b255d33853de6549e79f8b56049a1d02f29166d5f91cfbde5aaf6bcae56f5d2d90a9b4e8f6f450080cae8256c6619e9155523c2b2052255a8f6d9f53d8a897be5b0476002410bf798256f62bb1a81827c2c3fc4ecf9abfd77e74174787370864f05f9
+K = 8086cc691e7e793a5c2a81bd3d5a1ff5ae261d9336b33f103d983a817f7eaf7b
+R = 43993b68e847f6ba61d5ad4dc8f5ad70dabc317a7b6811c23e7f215f95415ed5
+S = 1ea727afdb907d1d5b2337c1ecea46c71eb0fc8363af23865a345202a762a7c5
+
+Msg = 74a433c2d313f66232324df875b82563805d7ed682b266eaf962375e422b3abbfe3dce7f3c1960a1e4100f333e168d021968b48397e8cce9005e951fdcb096a9abea342cb5b08bab79ef0c431dd3a43de7d5bd6b86bea8872ba038b43a236a7356b03f89b09004ba2def663e6d299763b6cafcb6b150a57f82b890ff6d56f832
+X = 5c1a80e926de194995195c4cee9a2e874c7f6af0fa8a4b2df5432f9cfc86b643
+Y = 444fafab58db4d6f5283c3443d6478b5b78daa631bd4c3d9a28ed17281da4c1c2ef4d5ed576d66bfe5314e11fe68abffe4df406f6033edb84f36a38a3ce614601bc25841f9419afb2867d991e87b44c4b744e39b64079d9aad4b585d79c8e21c8f90990540fec8ae981f7483dc5523d216088a55cf2380ea8eb5246781290559ea1b208ad4d0f5871cb4d13cdca6ef34fdf2de63e209aa320cdf14185b8f5f60ccf93f398c1a6cf8b3ce3d98daf05e4cf90c39801ce35f01ec76a9f6035ce1b5ba107a5f66cf253b71fba3833e9969c314eb6d500005749231f799b0c79a555a10cdd69f8eec4c117d7c8b4ec6f60a1ee557b70c0dea380af53b92fdde8823ca
+K = 13dcb7c12aeb75a417a93a22ce94618716996c3350909cfbff6d38b603d377f6
+R = 3bda5b0c9e3da22f0b3e29356a2f7ddace6e9b24a063eb3f5a7d755f2eeaffb5
+S = 4cbb815320314a06538d2a6740e6bf9d022eac9aa25c7508f659f0f7c1f59c45
+
+Msg = f4eadfea117fd3d670cea28aa9d2602c951ed843e2e8cb2864074c8c9bccb0606ced83ae2980598cc3e1b047fca8659127406d8f59f5b7bbfe8ece6d3e42f87f4e42ebe92adaa1e6e92ced3dcacc2e0b2c98eade7c9c99da887e74db5a59132c1d7df7cde866cb2f3ca750852ba53e265e62bf7a93fd693e4a13751e186e9d6b
+X = 6abf7cc887544bf8d3256fb210848eb46281526b1e8cdf6c9204c4c46a747435
+Y = 104f44fd7669607644ec55e6ca4096c9a279472752a1753dbb9f2a6941b8122274c87d16f63d75dda9ebcfd6584b0cb374fd17581353d2a246ec0b378de60e9613131683c0568bb54d74457ad73de859a4f02445344d13ee928f3cda5134202a9388e64cf05f8190049df4e777709838d0c9d3bcb37eecdc38c1a5d2b471c4b910cfaa9a9ba81f69b4b45c40344029958fa40000e56881bc6a14864330d5b351c161208676cb852bf47970268d37d4bfe97b3b26ef5b785f50ebc8c47949dc9bd0b2e673fb040e26789f3f5cdbce8e4b78389992bb83eeb2b063e9e1db06a9ede933faef7e635effe5e1b1e21153dc6934197efa1fd68f18a40ed569746c8374
+K = 0711c4621a8bcd40ff3e8b95728ce67a000e1fa33741246d420b046bdec48657
+R = 36c086070368265f736e7bbad54aaf2482d26161f8057a97a4b8cd2b4ddd7855
+S = 31d99d736ea67014fe59cb2212c47eb920f2af44e32b65db15af83cbe8e6aa70
+
+Msg = cbc37afc75177a8386dce2c40c33b8f5dedc23113b4512cb96790f2dd74066103e0c45a9c6176ff96b7d719162003cee10fad6ccc198550a389275d21e708b6961523272ecd5efab5680ed741c2de025b02bbdc56315a442e437c43e3b378e6d62ea8878fd9789858a8c68a504bff49516e762a22ae513a2dceba9253b36f553
+X = 7c6ee86f45ddf8b87f8884f59aad9e320b73b246a80b26a645188a40a9bca62d
+Y = 356cc7370c840fa26b0d106c47a626e028a0c967c093810b520639bdda0d339b7fc29adc0d9036b9710358ef9f8c6c05252b278281b2afe7953886429e85d228fb5474acfd65213151e9da0aef86a66f9f9c59fa88fd48cc3addc83d7adf4afb1665049ed094020219c01958b697f22e652152e53bf4e8f68f476a58181ddd3f64344e9b87a08c5d0de49e7b3c2995840c200084e90a76d2c05f8b5c68e77192d0676b4219d4579cb2de0f2a93a916b4f9cfe0d8113dc4bbd97ed12d8ce0447fcf9df12e922c6383ca69c9de9ad320f9c5331adb6eb1d223079196a2939cc0a7259c512c478c943fe05736710e273e4b5867174de72e703b5e7bf7afdbc06427
+K = 685a19da2ee3dd94fe9726a32e712fac05eeffe11e3dd9f60e6f90af7c13e23a
+R = 5645ef65e8e9236d874d459e7a5809923c05d64b22757bfc5b5621079e84819c
+S = 65f4c8febaf3e9d46581b17685c4f2ec9b956421d034a2c1aaabee94b787a4f1
+
+Msg = 8eb3685c3f406c5615e88accf4c0c7d2071b6c7bde5244994f73dc04f3cc0ab7e2b6664a1994e6eec52b62790a04328e436a2b4af3cbe3ba6e4c8f363a39b2529ef554c0c627f9f6b255928a39a465e60ac50ccf01f32c7ba483640344b6a8f583c90876b84d19554b0a4baabc2c240e296b12c819410cacffe7a7464419bee0
+X = 7e5e3d7255a629c39f88b6046fe0039159e44c2d2309b112ab05c61561d9e44a
+Y = 94ba486977f5982f2ae75e986b7e194461cc3d65cdbf26f936805d12d7f850aad7580206d7dc544cd12ca1891c9dc406c949e52b9febfa88836f1566d521a110bb545e07ba28caf07e1bbfa3b176cc917cc4bb45dae7f873b72dfa9000e9ab6083e705c0167d853dda114c429fd812a05961fc2e78ba9e68ccdb9dc67b116f10532034d9f0f7d39901dc643127c4309058f8ebf43b28a5ce534e29d6227c4ec27ccf777b0008df5ce8b8a19b5771725cb0f9f2a62bb41f0106c390803a307c60acbed6c2e1e0db5036e0e79ddcc3f718b29ca5aa022f2f0bbe815f9c0eb504fc9ff8d18a2da999023af8105cddfc6794dfdcc41333bccd446ad7b82a0a7bfe38
+K = 3966daabf7854949475ff47f3932393a73f21e275b3baad861a92a3ab322e376
+R = 27b4e3c3a45efa6131c3d005ca924dff11fdccf409c2a6993fcb505477b6e400
+S = 68a085bd130c4ec08aa9673c495ba5afd46c9ddad2052ba7ab396329d900d86c
+
+Msg = f2b02ac627b3f66baf4ebaa52b899adfd7071af53e78923182d8b4d5f3a9474251308b4dbd15fb6b657be65028a189353912d7c16d6d4989985c15cedc4343f0ceb680617bc7278511f9068abd613718a862513ee514fdf80cd25b6f84c48851e6a7850feaea57ea20deb1123ca4206bde8a93ff999ef789583e2c850d9e0635
+X = 7e52070b03aba0af4cad1cba0a733618e3adb7de873efba013878fa76331b5e1
+Y = 4e160d6970683f4d84eb88c55ba2da58d77f6374fc5127273d65e8ef96ccfff51df69b0e2fdf3e98f6d35e6a3dd9f7edd90bbae4c6581cd02ad01336c0086d4248eb1373480789f7d8333b831db3bae0bdb49789aab93cde1faf1ce88dcdc7a1a4f86143ce44f851ace459a5528c96195f4438ee7c1856ac61fd5035d839d62e48a1ab6bd23ad52f1f6ffed19826b6d7f6491cfb05003176f29079455443f0ab482150fac8e32a3902a4096775f342edee2daf4c4f338d455b4ea35d3975f72be85e98e87158486b4c3d6ec37a3703f63a3e19272ba5255089aacd30fa3979b458df616f57b7502b4291384562041f6188db503f3df7f5981da5705eb0f1d242
+K = 57c141f543386db3bd6a97121f93b47e38891796f02565058ec6a5ce65f7a212
+R = 6433bd33db0ac8261c691af3a27f52cdd4a65d799939faf279ac41788e7528a6
+S = 04cfdcb993382e8fd2db8d90dca80e94b17b432009852cd3f86625159e837c19
+
+Msg = 2b4365a4ac6854c972da7347af1cecc6edcbae9d533b74fbe6db5712163a6ce984f9d7a4c54b44dd7555e5c2d2f3d098f31d517f8ebd330199a54b15297e5adee1bdf391581f1019b1ad72dcccd5484b51d275a368c69a7662e79f9b29c9a3084c94ae76da04f958c7d36cecc5d41d77f2302ff28f2ed9c66a0662cabf51c842
+X = 35b701b7d59aad55eb4299e0f9e0348baec875eaf62d2174bce92dd23302a81a
+Y = 58e635eec80bde1eb7bf2da20600617af29f0a191705676bc10f7553f7611126e4c4d44bcf14f7a9f48da6e1b1e54d0a715724af5bca93867090f9bfc92741dfe1dd4f06075ec2a9262da81e0dcabfcab9e694ddca86d0e1cfaa321e2b5818182eb620bd5d16bc27a2da035d4bc17807cfe8ae3038c5bbb8a023fb232814b91b99749f519de39aa0f434313323b1b58202c59119b0be217617047c9e2ea453d608562cb96c4f0851a7965b164f9bbe151f9c508ca209f1af659e363804c8d8fa1ad700e20866ec9a1e505b74bbab70cb472308431a3e87272febf7cce2c20ec37f5d68b4e47bf3741013723936db7c9b0f3ded964acb7f8ac9c5a6b4f28de198
+K = 1c6ceff82adebf8c81bb4842b90dbe2a12c9d07c3a9d4990d44106a1768bb082
+R = 00a7c664c544cd7b61749410dda33bb3a47c3eb5a9a7be5fba201a390cecfaef
+S = 6fbbda967b584bd9ec6a0ae76e0c552b3d42bf0e9cf2939caf6123f6e86046f6
+
+Msg = cab1d17666b0c9658cc78cfcba17a08e2989d3c202c8b5085531404d928c618b6e230b25c46a5b58437e4335fc040020ba00c863182325940f00aad330145e666d07e9e9d876137010932ae520d9188ca3d7993c905395219c55846d19b8fcdb1d0c1586b9b51097afd6972ae1472b0e20453f8fbd5d6aa9e4a9a9b3dc37dd8f
+X = 1ca2b291707ce4f70e366ee97b5da158a1c985ba4f252c572f0fb329e43f9cb9
+Y = 5022c8a6fa79b7aa11a3d7af5acebb2ef8c50b28d8f0e3a556196562d34131fb44f22c3be3f9895e35eee70aa53b6c67920c540ba6c1085b0ea818b12aea811f2dfaeb6daed976e362430798fdcca3912a0891e7d1c83b748af1e7689e038b490eb73f7fe6e0612e8f238580e78833b20727a602768ab2d59dda36e75146fa4d3664f7b0cef7be877afdcdba23004ee313a69fd61c326759e7e779ad750f7a5cad9fb2dd80a8eea6dcbda0195dcc17b38ad6f0e2ab68cfc69b15c572f85f20c3679c15a83099cf08a379055f8fbdd8f590d43bd12f75baf0eccd6c077ac7589aab8171e8875db0122e6c78617c13586143a7ebe904a7822bacf48a7527f7fa4e
+K = 4f1e2aae323c5309b3ee5d3b73e5d4090c75da17765559e118bfd1460c312859
+R = 7b8b75ac8514c68de0caa98e9de0b9607253d8088d3feadf92b83ffc26e088ce
+S = 4b10e17ff64a0eb72f70a863d00a9bf331bbb515ba3a9fef72753ad7f0df0be5
+
+[mod = L=2048, N=256, SHA-512]
+
+P = f63da3be9a9616196c6556f3ce6fd8b98bdda9137473da46fed970e2b8d147387a81922065d528a7d6433ebc5e35b15c67ea35a5a5bff5b9cef1cd1e6fe31dda52838da3aa89b9b4e8d9d3c0732ccc4f238ce1b416c4ca93f2c6800e5f4ed41c4f7615cec5531b98680b20dc63f73e70d803aacfaece33d45fa0e39d77c8508209528b9046b5917010791234397e412d22bc0b8d67cbd1cd28a32c2460a0bd86aaba0eea80e16e3245643171e34221760c203a56b8207a1009e6c1a2f6cda85f85c4f9e410b9499233c0ee072e465af4fb4fb9282c5c10e8234fd630ea92f0aae6b97a520db34475707b79a4c175265c0356ccbca827e3837df3d6d0576d9079
+Q = 9b7463f8269f0b909abed10991684f36a64ac864e0d6d717c0ef21577a4c3907
+G = 972a75f606e8aa3a91ff08fd131a20f5963251304e3d1431b712fa0803d527fd710fb7eb27e52904971cd43ca977199a24dbeeb4b7bc2ba075d3b72eb6b2c5ad8f0e8b8f48c50b554c7e0711f4c7416330806672498f430292724bf98a8ea48c7f53d7b31d8b7528b1a6f087d2c27c335202835b1e314225b37aef8bfcec7d80920c4a460a3d68344ded75ed9ee867fa2a6945063894f563b68633b8b39f83a1aaaf5a96c7f422687e7c84cf8fb8cc5f4504dff087bcb26a95bbf8583f03b3a0e43a356b2bd7e25cdddf7a015300faecc6793c5ee99b6327cb8456e32d9115339d5a6b712b7f9d0301acb05133e3115e454d3a6dd24a1693c94aab5406504bf7
+
+Msg = 8ab01510cfa33cfa5bcff003bba39996fa727693abf6ac010bb959b0b59a15306c0c3a1921af2a76717aa55b39fa3723f4c3229ca9acf6b741614bb551cde8a7220ab97d4b453bec1e05a0eaa42e382bbc7b9b84f8237dc8964ee5b66e9b2a4ca61cf675140efef54fb327a665def8d57ab097e8c53c643fcb58209c4215b608
+X = 5f6e545daef6cd1b8d9848dd98758807236ac0b7ff053b32c703eaa3b1147557
+Y = 41197ce2233d7e48c803cd64c78f657923b9e36b871401f8661c21d8ba38c6b9b3239db767b11d1d401e5faecbf7a45860cc5f1a54d60286b7d6e1c99fd5b8c84ed851c5357d41ad60163f224d78c996143fff89dd3a8fe123dae1f621427fd8cce76ed138d68fa248f374ae233249625b93f3dd5937d15e541b7effa4df4fea7d52faced615bfe0348418ff93e69a20a52e55c76cc30f307f84e71e4aabc0825eca3a95b4bd58ebfb0029d23a169e9d80ba7d1c5fd35395e6602e089aa9918f08bae35ae1cac7af33694129e98f0dadadd90eaeb6eed25024390b1a60af794734c397b0f509865b134b2867c115d6f489b6dd7e3c82994b45dce2a23c6bc902
+K = 5fe61afddbdf04449b24295a52a1a037d3f31441a3cec138b7f0102db86ef132
+R = 6a47ea57ceaecc116d7190ff6c6dd9831ab75b4bf6cb291083e4268b486ed245
+S = 017355f698a32abe9a4d4a7dda7c85950cddc348ab8a6751e72fddc01aa5d1f0
+
+Msg = b2f56948a336982a5bcb4bb5d79e3fe5c36081bd286e6e021ab29b522f0be5ff5e81e638f23d0781c268a89b09332575cb31c0804bbd34c80589fb11570fc65b3f67612605a9411cdab3ac00ff3fce33ab22c46d26bf9c3fc5ad2d9018deb9b669b50fbfbaf8bed6230c7bd621d564fb1af953f0e82c5b5520ab97baccf58d6e
+X = 91e01626208863a954eb8987f8e987c8e6213536bb18f5afe3bd66a525bbadfc
+Y = 72b84eb6a60c686f74f376e26b2e47e44a6d5dd92c06fde49faad0af9b11e43147ce9308ef3501a752e7bf18e9e6df3c0a49c44cd2515a05508f8060a61e6e6f1b2ecf14b338cf0fd8b7ccbe678d52dbdf20352c155a2bd517d827d6cefbf48c5679c998298e2186ef1098160dfb65914506a177943a4a058282382d327ad36f88301be693c02000c72463e682421a0237804dbb27335c78e8495fac7842d2aafebf90f3c3605f758615df989fdbd06e23e4ad6974b62384f0aa01027db89ac3dcb01cb5258cdbd9c19372a6c4aadf27298062ac9a16de2eb076e167ad7c65d0505c8fcecf359bb5d05cd22e7d48629af539fe7f60e23e957c84c7a61ac92bf8
+K = 6aff566d97cc48ef6bac507d64973c95da14fd704d3a5332aaaca2bdf21e894e
+R = 43704e96cc8d63e6f5b7e118cb7c030d0bd563b8f7a1a304b368a6c66d7e7fa8
+S = 490da43fd0f19fec4ee081cce25df6b2720b1a76b023c15704dd03ef1c3e48a7
+
+Msg = 9ae8479327b8b8a57f570f6ec76a1ac6f02b198c6048a1f096e6ce5630b6caf363176413d88033b1cd07f4d3960a12dbae8a659174bb87c37aca6ec56ed5a6619b8ba676b650d97c6a21af023985dc361fa234b2b3c17e77703ba99ae3211260da10a60f240eeef478f2641184a281716ae57888117dba992853f494ac3caa45
+X = 8a5624694a25209a5fb3983ecac3fedf508e0b23e878f60a18ec0e897c379f7b
+Y = ce348b5cb3d36808422a5016dd5873df79f3cbb5e1b458e8c1110226047543d965769a112adb4fced0d146230962a8d413225cc70d810d40e6a72e6dc80db509400c09d263d66206966ed51ab65930a2aac99fcce3a398b64d59097683d2baa57682705abc32eb8c32d6f1e7d94ca17ed7067822cd20fba3795ed1843c01b0d7551c7c4c759d53a4191483bdc6e3121c2bc12607701f43e3ba382c6766819db07ef9c59586937514772c2eccde4c54d92575734c45a8e832c4417b43a92c9abd152259cc0a969bac64b237bb3a0826ae72919d7c2dd2efdf03e83701980c2a8f50ce6e44d7cc8848645bf40aefdf24fa7a6dce5a3b9aca6f017618a64d91ce4b
+K = 86c3ce567e7995a61bc00e088ff2f2a425433a453252b1a729d8d85ed506bdec
+R = 0091d750ad9a4f29573fd457a5891b68d4b6c15703a2bc192c7c620c4e4c4529
+S = 92c409c8977975a417d9f5e0e2dc70683a53a95662ad270ae35d496567a9a2fc
+
+Msg = e5a1a344c25ba0cbbcffe6800135f2ede81049180fb2759fd9e1af3b816ad5436a24faf29cf3ad91cf413332f454f74a9d4f5efe76cf02512c273cd525f04afdb5c24b0588d611d72153680d1e3995e0aa750e9077b0752bd4442bf7bfa8dba38e1c5e7ddd687f55aa54c138c7e6d5f064f3ec55942dc192dd996e553633afd6
+X = 976fb067157b214a80658e7ed2f566911b35b1671e5c0bdd55ff5811e822bf82
+Y = 3859d4735c14baeec14b79cc2693ffcac900a2c26ec634a8e977d206ad6ec7b13f2d450ef04782ec0abb0da48f000628cec1f6e9a727bb59d7c0f0d743f513ac0925beb61bf3ad75824fffae1eb783eb1b68fc40d28770e280fde23844a144d4b1a95409b755c7ff2e5c67811f3b1c2eb96cb159a642d84dd7b5dccc2c0aef06d1cd54eac94a11273f9498f1e7a7cd79c108e496dcf573ef3a6610b7731ab14c162ce8377cb9b90788e356f51f4b51a1ec8bd86bd88fd4c38e62cad619ab8941bcb98a2f35ee512f4f8ffdd5ee70caed8467156b893b3532a0a2aa5199ceaecc5b194bc057964cf450668c44f27ec80de21ea1a415ee6a6569832394f6b405d1
+K = 1ef4f08defdb5c59a3df3358e083ce804c969d046ab67f2f938eb1a8f06a5d0a
+R = 443644e127e381b17bb66c53509718a58a30f927425806a62840119e78c293b7
+S = 3f01e5d1e9fdb1cfda25eff3caccf4edf599fea277201cf2b01ffd7cb1a9a727
+
+Msg = b88c212070be398a1f81e85dfd71dc2424a38ae38a9d61085186504f4c2cbfa492b76dbcc051cefde0616a7e3310b4bf17244de7d10f847ce2a9f665948e76724d8f1f4bb3a61919b2ec7dc47ad8a72cb5998b79fe3a156395e4ae88e682b1dd16c52d64cb4b31c39d4a42a21e6242dc0cdbb0acf3d47182638c5f216dc6e8b1
+X = 02163cda612e84eb5ea9e4e068b14c10dad073409154d86fea6aaede59538d2e
+Y = 541c690f4ca0c42e5267646f78ef42fd68c363375b2e983be444e4819e63cdc129018bd3b8c6da8b707c196c35c93eabee10e875c41fd925bb3ce80696935d16313fd3a26858eccf2d507fc2a10950525c670dadc883dc6779ac1ce866d8820395f3541c863018337a6be944ddc644aaa6c007197d7a5f9aa53a5e1180ad51c98be9d561a85fe9734160ca35e4fadb02527ba0fa58041b4d96385f7f8ff6ae756add4968c0c2799c0d680f66c8ce96f498228738e3e87b7c866344db7d5a4ec3282431aee5951d9b4c83ec2a0cda36cb2e2c437363ceba4e8e9f6128439d12c51868d0cb1f61e53a68d4e71c5a9e7de43c6dfca26f1741aca916e4282653bfc1
+K = 42cc30e9591b42486ce9998ab7594ddabc5328ca2e931e08c75b76bbe1f8b978
+R = 078a7146a2c509b97a6a8c963baf1fbfbd1a2a5aa214a15ea45763f0e7930beb
+S = 2979cbf59adb70f28ac4fcb69297498f8163764c62b31963da9c8f9c0c43e075
+
+Msg = 4adf1ed4fbb5b82d7a2b1a2938430753a6207da1cc049574f0a19314272f9a80c6a53498b78e5c0b7401ce485fd4baebc966da6c1fcb025816cfae32b58aa87f5e8885054735f93df19ed32c819786d4109dbda047d68c0589330715e10522643bbe27e32c0dc9c58336be305b4c0c981b40e0eeda0de461d8441c02c18ceac5
+X = 5b44bfbb69277fbe497ec729838886e7a787f336c246551526b660a7603d167e
+Y = 8b6927fe293ac9111ba406125d6ebfbc30f96cbfd696fcac7dded42305c6105453accb1b0ca6f0f31601f8c34f96bb8ee4ccf149923a12821dfaa2a3859a39cf82567609b2060ff609232e90261d66cf31fb9264671f3f1bff6c8a958e5cd015dcc02dfd2f02fb6a443c2bf45abf13862059df98066e00311bb6438b7fe2d91e287553d25411f0fba47417c2902f978c57257ae4eaa3f99317d5adee0f9adf4d41e41072552b3f51eb9936a7f63cc28b466fab6429d06868d18ca09aba634093767192049b02bcb752eb674c98a86869d6726f742e57ef8c3d4531171c64f03e10a4e44039a44d407ebfc6b56a7cdf6b17394b53b5604347c51cf375551b7306
+K = 5f02472e007874056abe7194e80845b81baeaf4f6f564d3640373757f4252f57
+R = 5b201116d8bbc87db99001707b567e7c3451d802fa6c679bf3db3456711a1913
+S = 5be7e4c493fd5d19b771373141294daad97656a3dbe3fd2abbd3b6c62c166126
+
+Msg = bd491cf68b34f7ba9afe0c6ef5f2b7956ef964465f28b2797bc1d6e670a6d81730ee2993d0b4aa96905157025d775ba104e7c19b3b372e852026b1286cbc6a48a10cb9378e97ad966f9cf03917ee8db75b6264e9b0a48a0ae10c2f46444710d4234126ce456b9fd11ab7a3504948d046d5f438d893d9b1052b8fac9547415472
+X = 609a372d3844ca8224dfe780b425e1a7c00d09957a862de6f640af57c086dd6d
+Y = a92e446510764ee1cf81c6b59b5160a7608ff8952d045dd69f034fdfef93f633607ec209b106c6ac8f0cc6ffa64bb9a4484560b838d6f24c993a954efc9d5ee16656aaba2a0d5a94e7a346c7e501af83f131db9e0cab8789fab19bd591ec227f39b349be7f8d0df58ca0396efb1e76549335904b88ec21cd3265c543c4e80e9dde7cb5c9ea8cdda23d96ef1c3839ade8ed4a5cd5fd98b79bceeed9c641c5a7758d0529aceaf27b5014f13dfcaa267a14a0841b36897b6e1e8917b7f7cbf7cff1d1953ac43cc04ab06cf111e006497eb42f28cbc905d6f1cd5d8394857983e1c9e552015a451d0c13a6848a8fc56b79dec1723a8067ff18931c852ceb81affec1
+K = 8c70ac971b83f159d2e6ec26bca1463aadbc8e9987593f49a9258f7f0de9cb38
+R = 0cf526d8a0f9c912d143f3f8afded4598b2a5aaf200e0749ea27defeb7f28f3a
+S = 877a9066f6c5ae78251d9d140bcf39ae912d18bf131bdc7e9d61012daaa4292c
+
+Msg = c00a8a2fffd10bc2eab63b8e375d0c10f9dfae2848ba42afe6085aeec26e21af3eaa493ce4b3d95a31fa502a60ab88e805f4fdf889ed91c15421718084cd0d644795749b1a6b183d74782d52c7babf7400393cee698af5dc010c0ff7f5acdf0208f93ee7e4ef58da123dfde7f0a34e209bbaec61007293fd11afa60b6522c45d
+X = 683e924893dbbd751e0a3f910867471a6410fef562cca9f464943abd88e0430f
+Y = 7560105b8586c4532bf1b51e0d2cf9a713a5ea5d40e262ce01ebdaf1ee53d857129e1529a0f8dff63e86202c111c6eb289439cb15cd59fc218abe619c9516250f127fafe9a53076274f306f0b7871cffbd156b1a8819795f0a9955864756650274b83e67caa4e215f833afd5a77d0594b21b4b54356a98a56a0bf6177faffb9fdfd888d6538a1ce76059854bd1f0a20761281d7b751757c6ecc9b1e8131196d0669597213ae73edb9965da9ff372420851155011f691a03a7f1e2040291575b86f595998a06ef79f4eadbae2bd9e2e477dd72684d8efdc1e835f7f0f5c93635c181b96cc7c0eaa27ee62c9227ed9485a8c822b3224e9e2b7acc10956f3d49a6f
+K = 3bf5f524e3a3903c149958d10ae68f0a87a03821445a98b0b9d08a3689738853
+R = 98fee10c85ab46d334758734819e68b5046439cd0b66be26d43760613ac77b8c
+S = 665fab98dd437e06a4f877ee218986e37c2cb2d237e598d98f1b7d4e829a846b
+
+Msg = 27f01b47d15f7d196f2667b75ed15b89d7443fb4fab068f4adb67175ca70071d52e270f68964f9fb0e0e14ed5d2954a33d93807acf3c82500e8b9f5fc5510cc3bd6aaa1daac8309128ef4c0b4cac026425aefdd7e69c22c32e5f8d2a6e8f2ea291ac33da6c71a1953e443c0ea206568aadef2b96466cbf76bf149d89d86f529f
+X = 285dcba140162fc203651c5ff7f1155341436c5c5c98e1e9df192b3c948a16ca
+Y = 38fa994a1f61ab79ee7a7e6f689c38f6c2826f06647b1663cd812adb36d7fd7ccc50e9a90d02bf7c3f12a228c692c056fb3bd608f51aa401022c839791e6a678185cd31d88cc661af29e5d238142181dd3f6e7c8b05785221e62fdb36c71e07f51d732e7e0cab520a7f2fc5b1831b0a6ba280e00321cb9a025db6538abd672463dbff5ca81993676bcbaf0f6e9c754f24d654ee7879bc03d7d4bc8e8ca58fb9b3929a3c38365cd2e205729e9def0a00108dffe9407271e17d355ec4b29003e0caf0c5b2acb9bd8e52d4410baa9b97a49874c14beebf03abf28a9ec59bc1738b8dd4223d47aa336acbca7662fc69a6fefeecffd47f6737ecda331d1ba5cdf023d
+K = 4029e06b437cbcf8e0788a393ba3aad0d182564ab6a53565eec1755c4f4b6e2f
+R = 8dad02c02ad34fe4e758ff5c81d5384c40d2c49d0ac777bad1cdebc58ec01cfd
+S = 0fe4e1f6875c113f1c17a0f0ed228d44213f8d7e2f15567e57ceb2e8b1098f7d
+
+Msg = 73cc5e4a188d2814466941389014ea45a1a06525d2069cf4883ebcb5f22ab128c00f041cf69fd94b33fdade78548f6523c838b87ccd868f3d3d0a9a000f278ba54048b9cadac7a99d98def51713191ad83e5232e3e86497245c80bc710fdd7faaad88ce92c894f8cad3de0075caba337a222cb7a3d7c2d937bcfe4b6e69d388d
+X = 742242f1cde89559dadae5e2cea28cf402c60ea9af2a5282202281f55a0d4d04
+Y = 5266427ad4c1cf3ea229377ad397c7d5613512fc27f2ce37407d2cea8e1999aebb8f3767ee96cb927ebdd43b8dbc10ba2c47843d3f43368d9e442bf51ebcf20b48b543a4c388bb3ae3e4027acb657d1bf74abeb8b998421308770f70b3f7b1d910219a1210260340123b95dba187e00cb067f7e37792341202554bfc8a235fc01ecb099ec3615a67a3610d4d8c2dad16087024f5973eb18400c29c05d6984d1c15c159422827c0dbb2bf4509d710c4972ee93be7283aadd991ae8ef0e97312118f195d304fbe96d5aebfb21203eae6117831f9be9099d3d476b83f65ab225f8be493a8ad21620f259d8a44200810c8e562aea8e7a6bc238c129b19f2531a6af0
+K = 57d9723e0d17ed96a3a77ad47be6eafc06a5aa01b59b89be70a756d37dd0df2b
+R = 77236b33b04285425775ee3f658b3761295cbff8e4bc05abdd22e3d78b1b6da2
+S = 43fdbd936ab40459f6843056ca77e125b6ec5ad945041c1f6a2770be9dfcc682
+
+Msg = c0746befd2afc6ca15cdb145c18462c515bd42794c4c7ee513cd9aeb0fc6fc3048b6c7231634984a1be824c775f9c9b028255f5b3c3d8fa08d47aba07755b5f1b5b008933eff35838f15a02ba9366c1036d3ff19e88199ef86a88227272cf4e4e00ffad9c36bebac30578b00214fb29bae43cf555ed431a2f24922430b1496fb
+X = 47c0c6f4e6b56cdf1e1d9b63ff3739edec9c3d5a7c990492a1c72aa1494fcf9c
+Y = 431eee49090ad58f4a874c2eb5897969fafe3274bd7486b65e3519e4309d636ace6864d5ca4d8448a357cafac15ac3cb3bd7b2755b3cb6db0af1a4e91b2d1fcb28561b170faf2e0690071bc0f6e42b2d82abe5646ddb8f9b99ee1daf5906036f395d824d080bfaea103048b3f44d0636bc7a6a88e9b004a363b99d24a89b6e97379b20bacf48c7ae2e9bf7e281fe3b4d7eb947a102396d523a1e85ce17fd25f271f3c221a5681e9fb77d64d6241039ac8a85da32741bacf00660e421fe850a0fe73a08ee3a9b069c6d9114c1975272127468f9008552ea4cdf9d96561ea69a646695242500f2318bda82da633ef1ae0497014a637b15a572ddddec070d19d884
+K = 3598a6006fa3f8b8f9b7ff96ba06bf3837a1a1a92892e4a268c75285bfa6d660
+R = 796d7dba322d92a083da7a588fb6238dc86b1fc5104ed600c9b4c688edf805e9
+S = 012c1ff4de8ee386b951275e250581d661d030a4d8fe115432288ab0a4bd46cb
+
+Msg = b8b915cf4ea3b0c4cdcd8b2a06479e71bb4797294b6c41ca870d3cb2ec2cb5a49f6bfe5bcd10be609ed3e1882a312395fc991345aba5b566e67960b42913db669041ea30c29947edde7bdcfc0896b97660740d6c79f0088665f51dadcfa07f7be44821d60a8ffde4e5cb1f98139ff91c9c6f3126596344c5f7eff40049d3f9ae
+X = 0eb74b5186697af279ce72da74f1ebf59921ed425da0f3eea17517eadddb7c90
+Y = 1b3722764264e17994f3343bf260c73575d106f6307f2eaa3f7dcd5af804463ddb6bbe38a38f5ab5a8ae6701317cf6c267049fc9b84078241f82d3c6b7e5beba5c1427030297f1df258148e5f9eb41eb20a86877fcc06e5373cd50562613d307649539d28cb52418d42fd59758b61185e792992b5a581229b43403d793b04d878eb9b9d12ea10d2e64d153d3fa41881fe79a67ac408a5348d79239567dca96e1ead3c6ac22dbcdbcb5185bf8ace57660a4252104e5047cac87851d2815b12ae8ae96ab2f33345ea1cf5f2e58a4ddcba26265c06df65afcc6e852b3f910c8778de28a9f098158ed0eca652dda2f9f4ac8a17a9b252410ec5973a6063b642568f1
+K = 37128d19b2108a8e8fdf2cac984d45851078a194bb9946a4db260f27b4650439
+R = 6b4b0e1e7cbdefedb1df1f529ece47891f7b9e959a3f8556ba4bef7bb9856560
+S = 7e933b44ede6b2e941b60c37dcd1568284def229c0a2bb9093f4829000c4409a
+
+Msg = dffd458a808f1889d7f3d6197f0e41920ad731124cee308cb90d2361b23fee969c0e105835549e5d0a3f7690d5862d4cd6ccb33ad18094c85c9650d75b248496390a0b89e7dc7dc0d3a6130dd97789ebf105f8e55d8f0a1162fb3c6b529e2a80dd51e9045ef8ec42ca4bc46abb6539588b531c9799560cf4ea806c3d93d043e5
+X = 36ff71ed608f351c736042f3b638a89666007cefe8ab487e512d76fedce1ff35
+Y = ea437ad0ee9264de8792b677207e547090b32d6ab460b4d589d842ed0a0b4fb4c635e4443bf60e46cba8d226f659c76d2ca01c69707ba6d977255c4584b74740a7cdec4c973e3d16ab6af60cd3123ca12ed5971e69eaffa3da0770d8e1228889cd6825e1b85846f4f7ecdb33f1e5c7acd6b2add1308c5cec439728d0cc625eb89df34fb9c0dd4568f979deead286c50145903a0dccca7239874b4683d367ed31696eecada90dced8a9b1e01364b8794660c60f40590794c95a614c04563c92d444b5ecf01286b1bffe9ed9ef915b4db820ea5c9a5b3dedcf89a3e2c37871d21b763990c7bbf44418f91cdbce4361eeb227516cb344409d2c651f0dc29ec82623
+K = 91797ee940a167a57de7619334638f1b3ba63f9065b69f56dc04e4020a1682eb
+R = 3152fc286fed44f28b1af2d537592c5691d6798caed90591b5888b0d6fe6bb07
+S = 7bff61a8676f0df189654f25c5812b341dd17f4f44667789cc887c191bf47202
+
+Msg = a6516019727d95639db038f90306a8d94fac5243dc7b67c3568d63d85dead1cfddbb2b330b619589bd582af15f0811177504fd5b7aad7b298647a3f64797e3da5fe5bf87b65c2ddec576a8f40660686b808ba42e54bfd0e9e48082d6904f8e19050e54ea4797a2f401ff7c9f3d217b526c03be9201c0dc1b0e8e054bbb32c382
+X = 396102ad116ca2e419b9229667a31737344d0d7854cac8930af18e12a9e2d63e
+Y = 9779eb5338dcae7377b1847018ce72c1ed4c55292a963f81608ef332050f0a484519aa96b18bcce8e1b49c11a200c1ab4a75726bcc842485df6314e5c39fec622d819434294dbe1eb647885ce841527c03481b7f22ee586d8c2b1a8471a2757bffbdd9c26f125065685509ff0e4c8b826d73c6e12f6d4b9319cdfa72c069e07b2d2c254b330c06f488d6598c7476ce0f3330c97ec36b7c10871388472451a34afb7b4d4e251f9f72a4a38a6851aab86507b283e890c31ba96d0a1e5572637b2d8467060c0736d11d0744e332a19f59ae2920894e9cffacfeda64ae1ff4869882df3b690c7ce8fe0eb88171e4f2ab8624e6ac77dc8907613235163e0a2c7d9fd6
+K = 79753fbd43773b6757c01663b8f5ef642801aa5ccbf32082c780f71a22c4cb0d
+R = 7222d5eb392460defe8fe3df18fa534f3060235f1e8dce5370762ec6fc11e690
+S = 4351c428031cd9af567b1163037a4e376962620c4ec23c43b7105879f95bf614
+
+Msg = 1ffa7cf55f92f234a24bd3296744d543a433c907c1f77d8b706f4b6262d096e2dfe713fa9ca80e68579396fc11a12c0331cfb7745d96b005204e483fbf8f9fdc458e2ca8613406069df5f44918eff8c5f54b8b4d972e07a4b8e06d8426a70874cefe6e93404c1eb381c2d0701c37f85afb1601a09fff8ecfdaf6cb64ad9bd8b7
+X = 24039963cc5ac26a977728b852414f60a287174186ea812e00a5c8a8a5355daf
+Y = 18e298e6301389d48644674f8339487a8651b0768dee425905e803ab357c7f9fa05dd5e2ee84bfe105a092716274557e063d086e78b781a43c56a4e0ea115c5cfeac57a4c9b7e1effb89413689928f1546feb30738586d36ffe338083ee2bf5c5bd344bc3db2a7977de2b1ab5ba006d9ee93ef8688a7d10cafe27af3e671013a816984196bfacf002335fe7414423ed8bdc80327372b0d460866480bdf073c9def7977131b06e28d14ae1a816d3222ebaadcc8d7c300aa820e0328af66f742061aff5d4b7176a994ad69b390bbdd619fce047dc7d15a48ea71afa72040bb14eeaf4a2b23d99b4d977beb6d806101021eb0c3a0e31e54579e58c953b55b6e3245
+K = 2ae1af11ff810141c37b1c23796e54f027b4eb7c2f0c412b6c83076de3d4aba1
+R = 21d70ed955b09ea302fb792978d12501071a2e8e2cc8f659decd3df24e37c466
+S = 2cdaaee2a5a3dd74a67795f93ac1d8416223836c76f7fe31c72ec6170925fd73
+
+[mod = L=3072, N=256, SHA-1]
+
+P = fd5a6c56dd290f7dd84a29de17126eb4e4487b3eff0a44abe5c59792d2e1200b9c3db44d528b9f7d2248032e4ba0f7bfc4fafc706be511db2276c0b7ecffd38da2e1c2f237a75390c1e4d3239cba8e20e55840ecb05df5f01a1b6977ad1906f2cb544ccfb93b901ad0966b1832ad2dab526244a3156c905c01ac51cb73b9dcd9860d56175a425d846485d9b1f44a8a0c2578e6cf61947bc1a1392fdd320b16a9d70455fe436f2d47ded8e8e605f7486eb578ea7fc4ffd13c07f9996af159fd411e9451403278dd1141a8c926b35c96384bbd6bee09c46f44c36b1ffc7197f5e925dbe0544a68e6ab8c18e426a466b392f9c27dd79fefa9ca163cc5a375539a8559f277f657a535d1964c6a5e91683ef5698ebaa01ef818dbf72cb04c3ff092d188866f25cd405108f566b087f73d2d5beb51fac6de84ae5161a66af9602c7e4bfc146f4820bdfc092faeac69133e4a08a5b202a12498a22e57bad54674ed4b510109d52b5f74e70e1f6f82161718cd4cf00cc9f1958acc8bddcdfbd1fbe46cd1
+Q = 800000000000000000000000334a26dd8f49c6811ce81bb1342b06e980f64b75
+G = 99ab030a21a5c9818174872167641c81c1e03c9b274cfbc27bc472542927766de5fa0539b3b73f3f16ac866a9aec8b445ded97fbff08834ed98c77e7fc89e5dc657bef766ff7fbf8e76873e17bee412762d56fe1141760ab4d25bafd4b6ef25b49a3506632d1f8e10770930760ec1325932c5a4baf9e90154264ddf442ec5c41fed95d11525151dbcfb3758149bad81c62b9cff7816b8f953b8b7c022590d1584e921dc955f5328ac72983ed5cf0d04056fe0d531e62f8f6c9ab3c0fcd44e14860b7311d2561c77c1d32f6c69dc8f77968c9d881ad9db5e0c114fda8628bca0335eb7fb9e15e625aabab58fc01194c81bf6fb2ce54077b82250e57c6a7b25deb6ee39d4b686a5c307a7612b2d85ee92512413dea297e44f317be7ceb70a3328af0b401001a418562b8ffe4e9771b4b4a8e0b40c791349d5d4e459fe620a1a2fc72e2f6ca28567d4c2632bbde1b49864c06bb12619f132c1da8f571ef613eac739f66ab3914cb3fa1ab86e05e5082ebaa24ebeea4cf51beefc27df512fe3fee7d
+
+Msg = ca84af5c9adbc0044db00d7acfb1b493aab0388ffbad47b38cd3e9e3111cfe2cda2a45f751c46862f05bdcec4b698adfd2e1606e484c3be4ac0c379d4fbc7c2cda43e922811d7f6c33040e8e65d5f317684b90e26387cf931fe7c2f515058d753b08137ff2c6b79c910de8283149e6872cb66f7e02e66f2371785129569362f1
+X = 433cfd0532ccfd8cdd1b25920d2bb7396987b766240379035b0e86527ce9c52d
+Y = e7c2ee18c3aa362c0182c6a56c2584628083c73e045beda8d653690c9c2f6544edf9702c57c455273905336a5f5171107a313cd7d0b0f50f8d3342c60219f22a9023394059d05f464c4496d55dab6eb0898527ff4cf5678e7b5bfb5e18d92c4a9d73288cce14530fc4702f6d0397ec39a880c4a72d358730c56633386ede028023c1791f3164d1574e7823c79b8a3ca1343ea166ba6f02b7ff7e9ef2198db107f7cc159f3b6a1c00a78c355c566deb0ac6fde3f633cb9177a1fbc6c1766ca021d5fec470101abb440d2f06982181a8c92b7cdd765336b9a1e1ab70283d6db0a963fb648c37c4e29a74c37577291049ab47cdbc104c04db966681ea8ebb9f00cf4c4a5462117379575fbda4b801979451fa94b19b4e93656705c0f734f3e0914bb96c1e2b8a0fb68faf14296efdf3300ad95bcde8b67cc4b26e6488eef925cfaeac6f0d6567e8b41355f89d1c2b8fe687bfa2df5e287e1305b89b8c388c26196090ac0351abc561aadc797da8ccea4146c3e96095ebce353e0da4c55019052caa
+K = 40f503abd70fd49a76c67a83e08b062b3fd465ad92be433c080e5f295bb9f559
+R = 21ca148cdf44be4ae93b2f353b8e512d03ad96dafa80623fde4922a95f032732
+S = 73e48b77a3aa44307483c2dd895cb51db2112177c185c59cb1dcff32fda02a4f
+
+Msg = 3ccad0018519a898f87d8ce5f28c0d93ab16c51addf4173322cbc49d48ca9ea37ebe8bc9d8c1b3f783f8cf59cf3fcba10a393eb2ddd989ce258e73788ce74b0ce8223d24e993cfeafa49cc8ec1b8ecee017d83a11bb7034c779206c364ac463cfed3047e1a2bf5c591773b1d882b310bfba2db87893c89a5442c0845bf644e21
+X = 306c1304b380b7c3e09e7a4b489c64a295582bb3e03ce526f13d7482ef8263f0
+Y = 3750d36353bfd2e9973e26a555bcf0d834d3d6620cb66579199e040ce8eccfaee660046e78df66e8ff641523046adcf425b8319db2447680194c3a386b5201dd1ac6bf3e66394e939eaaaca4fd3f386fcfe1d5ef4524b06c5ed9a15746f24baef1eec41e683bf35371084495d4da8e727aeba307fba000a769a234e3c4609704b3ba4dfd6a8644fba56083dac848751b52a8c2cdc47946cd21ea24383cc6244f000918e9a23276b606c5688565c44ddf7788181b789565a6becd257123bb81a2cbf9db7fa384e0ca41804ed7cd3c9ca0e1f8bb390bff50213b0629682409933770f6e03a5c4e7e89ade90255609786f6b2fc5a7aa7566bcf7f725aead4cf456c5f5ed7dc3e91e20d94d1aa2f6568c97abdf21e0ba8cbfb6561305cb45175b1abd7f39b9a11c797926b944f5d13c3d70e0b2a8ca18e1f5cda8ce6ac43ecbc1fef881f5eef5a842fd5984ad1e321a317005ad478cb47c9cff61267f1d496fded0a48328d629b7b200c441634ee908879011745bcab6660e15583748014d6de2fe2
+K = 223e52fc516c0a79f55a5474321264fcce78c050cf79b3d9961b37e24d7f32d3
+R = 1ef7723345b2013b71104ceedbe7a9cad430018968bb295b672c2b57b9a108b9
+S = 72852da485c0836a8ebdbc4c996f7f6cb65e99391ce06b19a7187618e9a95584
+
+Msg = 1fc98288857fb3a83ab507465a53c079ed66679cafdfb8653bfdebb03020fe86a943182d4f1377d58eca3c7710d32e210d8d03728bc69e1b8003944ffedaa1b69ae6cc506302bd6917019f588cc29501cc8263572ebc0feb153877174bcfdbad4a58659175d2de71d5f5019c46d112b6631cf0c3f912aac83140cd56cdf903ee
+X = 047a5e52039da40523feffe63312887e4d1ecdf64f32abb31dfe680bd1513077
+Y = 335372770c0e8e591a367de99833bde6f01240bc6e236a5b4e36233e120b8ee6d1c19c77f4cdbc294d3278c3d4cf73ed9e8ea5032b0524a391cf293b35ee7e023430222216d9f18b45022f4d5f9385f6384d9faf1a0ffa4a800da23b937651a09e82c22285b9de6a408e23386ffa67abb9d1c71cda7bc0c93525fcd79e83153e746070782467858b697ad14914673033fedb2d7a105ad2d438daaa35b503b518314ac370fc5b1112d4fe514e5835d9a86de25e6b35691392d1cd04836d4126b295b8a89f217d581258af95277b8b91c31e6b0d23a7c52b0ce2641cf1a252838b6e28e226cfc4fa9dc914c5f675fc900ed680dc1aa9e1d17193c432af4032ebab954191327083c59a5f64c1ea18107ce4d7211d1c22f04805ed548fc22df4b162f30b6ff3a7f7c38a5a95fe824d2961180e98b30208dc7ea7071f792261d45c7bb7b911f3b19c3ee0171a326c033cf5fc2bf79de7d5115ac568e04789cb44e08f3a8627a1b1f3762342b49b7679bd7edbe47bc3ee9c3f02db15d53256a5ea2847
+K = 69a22d61b152af35c1b43deda88d5ad456d38df75b318b82712b2690a5f2f647
+R = 5dd0c7e8a3993b9de0676a579c897ea39943a43dbec5996e58c1985b541d7c1a
+S = 67971001822a08a2148a6b1adb50274a57dafe896fb04a12a6f99707555306ac
+
+Msg = fda9765cc91a9db922aec7b13fc32ac4ec4e3b8534f9e95af96e8ebeab89d847dcd150444868cfaf4213f8d8baa6b1d0886224e2afd0aeb93d59b886572088d05bf721c7adfb54da47c6c4851204a7a92a11deb39ba17cf6c07fb7ce8ba350a99d018d4ea64bd56d1d9f8f7d88157f190fcb372acf6f8d31cf7b795b36c10f5e
+X = 7f6ce353841963c8a6ff3405713e361ef9f1e0765e665195e7c147dd98120c4f
+Y = 0539cc992ca70f913537b1211dd326d85f7531baa6be0583ba45b9571baa81cd5828050dcd9ab7a203bc4fe1d874f76ec1f34d935579ed2132255789d7e6010cf504b4c7f586d44a716600acf8a04ad30cb7ca055d7223f9761cdaebfdf7ef72bdea3dfcd020069a969c560160f0534676beff5ea611fcbc0fd47c867f3163e1371e1de67a1a3c3e37168bf0be79c09f45f2bc43517aeea0100a2a25d148ff1990c06143fa253d8306f48d77362224bc3efe93389e922def0fd11d1992f550ed8294b6136547ffd612b0bc8e4ee90b3100bb89922177147be0083281bf663f8370417fa790d4105eb98cc126f5005b7c08bc211dea2898aa653c3d2b51fc67732bff5644e804aae69200c416035aa0ba5a14cc439b569f462117b7dfcf3f2cc13e723a93ff9533208f20241daf36cd16066be3dba20117cb145d756f5a6f79ce2356a051647aedd645bfa6faf8f80a6fdf3eec42ddd42bb2e7b7738296e23978c8bd63b8045953e06cef1263bfe03be2f61b16007df1eb198567a7bc6bff274e
+K = 01cd3cdd3feb4d1a995103b1520fef17f60cd9370ad59b3efe9383a2c0126f00
+R = 55c2b27e769fac99b47bc0a54ff1821c7a46be6001ab664fb68fb1bafc04446f
+S = 3059db42a399c428f3cfbb102d6c0409b06f20068d1ca8cbea4858ac6e5de1d3
+
+Msg = e49a12b8d761ef7afbcb1c377eedf629d08cc509a8753a5b92e26a2397365156e7c081bcb4686695575c6a64f5d77dfd550b04df390aa55e0d051c759f197a751a6041e2dd0959f902f2e359a167d880c49cfa81e7196fa1604ad32a8017071f098d4cb346b39266fbe75659dfc6607bf0d829640782cf3e12e38376c5a99282
+X = 28d9bc1d9aaba882427ee26c262bd4003aaeba422bf053b0dde14bb6d6d74bdc
+Y = ee7fff18822ff454a207f9db542d24298bb5edb11d80ddc6ddb9bfae0c952d4fe8d9db0f1a86e8a0f2193af7caaee7264d74106de5af0a6c14f710bb863eb7dc167a1e4378b6cdb7ab6841c664e9824529119773578ef55b7c35ed221ef070dd4690b4c12f27673e5d1fe964ffe29da57e2d1acd21ef13e0669fa97668bb199b56a3a53e10469133022081cdf62648100dca267c4f6a3ca3a75b573bb1b39c8a4e1fcf81269e9e1b10c63f5ba4fe75cf7139d038d02f5f534aa081fce732cd5051609bc06f18874dd01121d3c179f0c3f0399c185eebdc34635b3139f1ca50fbffb3b0ad12e481c1a64682143793f072c7db8b5b9eef41ccdd66b904139d644442a92f6255edb9bc1234e27d07a6ba32b1f14cdf98a22c6a12300dff50ac1b65568b6e915541bb386ec725da444467ca25e81448cb78375146ad2078a830e7d905de9ad7d89559c9d430cf5f419ce945704a426ab264016ed87c90d97f51a7d6e1ee2f51bbb3a8de81391697b0e422df9e5d3551e93374e5f38016b296d53bc2
+K = 0650ebc3e21bf1d90ffb3ef5a707013dfce78fbd2c21a0da9c8106d1fa98a46f
+R = 21d34df605237975db31b864f98c9ab6e465dbf0b3fc5868d67cd6cb3a13963b
+S = 70c48807d62d1fe74d58959347ab12c97b500d20607ed2a95d8a388fee265812
+
+Msg = 28f7a067a0ea7f0a4d797cea3939f66b281ed19cc98b8563ef375798b40614f4dd85ac2fcfccbc5ebf0ac93228c0b72937a481ca4f9df7a7e5d2e5da9af04874dcec35035f6a7db493793aa2361fb66ef2eedb7574d04e2147c357298a2adf99aca1eebe00cefa44b39157eb1e94aa8aa98d545151fbb4de67070b3904cce930
+X = 0c5088f5d337802770e6f98349d53461f13161020ab9a241efed4faed2e569ee
+Y = cdb9922d69e99c7f34a9210e2afc5be0115da4aaf682d9ea37788e0b6caa6fde13c88e51f558820668b59d14c06d2cbe6549d3f06d10dbeee46f59154cd467ae19e16be25e6f6cd238ccd1947fc581562d30ca329bb327258ca4aeb901f814414058b6f169a45ff55e40232d7870499ae78c0513777140752d55f0a470761bdcff5a6609cca2d1809f184b298718071d216a14ad01f56cccced23969607b62d4d140c9ef28507674f59fecc7e7ce8ad2636a5c53f070ad317c8cd0231f500a790ef69ac786000faf68e7b7854d6eb26499a9d524cbf8f373ca41dd6a2fa5198eba2a8e228f5ab29be9f6d450f7f5a149aeb20d8a277971fa6e64a0de36c8750afc381961756975621f287a3950f88402c5081fe0c54f44f9fa7c50df906b264098853646b3d05a4f04c6f1bbc6c440f7e7358d3a72b29f7643f4406b7db173690d40aa2938eaf01874d2ba8094cc5be1145b2b2ee9e7cf15bf398e50832d95017430b1869938732cdd1df593f5db2b2bd71308d8c253d254ef39b475e249d890
+K = 2be962ca1f82b879255e20d6971e633ba68582a5137bc55058fa42b48ddf0566
+R = 12de252da2593c5969a6496ae808d851cad1ded2959ea89057a92e5ec91c5f95
+S = 165338075e6a4fea0b238f9fac904b7b33dbee5a552646dfbed827f6d28d6492
+
+Msg = 0e156b0bd84595155ef4fc213dfc7e46bf27a89c275723e0984076b027c49cb2eee6ac866d75333581cca6f897e11418fb37ba5cab1391cd237e2c6ab3f11a055d3bd03f425baaabe5a6a34eba4b118af73edd610787cb8eaf476bd217048208ea4c1d0591372947a1c0ef94696568983424fd1d802fc911e7bf71224afdbdd9
+X = 2c4d972bb3539876b8f32cc645cff0d4be877175f31a028b9bfe973f0651789a
+Y = d0973641d56d8baaa2c2d430501dff44eaf9a3657478799134b0f335ae94ff2791dfd494401332486ba637683e704bd985f526919e661a2280d99bd48262b6c9305e0c8fd879cd0a836128d88eddae51fcfb51f744b23d2d2d27a2cc1ea5a9d5e0a7faf4227a2adbfb7ed45d6aa9c33798abf07bc69efc5fdde5dc5c780196257093eca75468b161cba44bcd142b21fae9edc6ab327830c28e1b3d2d7c812d8aec3a1952627a040110872e148e15de5c7b4ca24f086336daecbbf9816cdb9dc730db8a66a1929abecd4b09a039a19bffa45ffc85ddf0be3277bf075bbb46f07bf0daea24897e07044b5ee37f9f44fee757188170da22924fa15ed9c07f113cdf37a8c48648e586fb55a0c35f3b63a69667244193c70d94bbe36d043b25a041fba92a2042e2eef767e7cd18dd1c1b5ca4878fe774c833cb5c5aff9f67bfd6cfbf2dfc63b8842ad2d49cebcaff4c3927f3199c106d0c149a9b1b49bef1d6f8143d93d25df9db1b5b37d522e723ff64d9ee52e476206712a38246dd926271f5590e
+K = 5e12de89504bc84836c14fc47628a517e898fa46769eba2b36e7c69e580a6473
+R = 5ef5d78c421ae5a63978bcbf7d2037b5022bc47be7b293806580ad5b4de27a4e
+S = 67ccb2833c1d32c68e91ae3890b4c9a6e5229b22a5799168c0046ead92573c85
+
+Msg = 849c5337d88b3b247df573eb0d665548b6423763d5571f8acb5e61e316d7cdc208cda5b39a1944a717587e58e21b86ed222b8ee265105a32baff3692dcf7b8713d0b539262a5bd9a954cb7143ee66f8764db6236136cb1cb3b34a87cbd3fee3b11288bc94ac99179c681a469d62d9bcd91d40332a650a5bce33b6026884ef94a
+X = 680878e382b713d4dc9bed8b7eae880f1054f58e70cda2717577fed3c63393dc
+Y = 1e8d4d6fef9905d639e2564d87dcbe0d8f99bde38082ff091a977f2affcab86505aeffe6ef1ddbacf15d9165b006ac0517434aaa65db210452fb2ff4c990b87f25fee7ad5b26ad87749575190089a56cdbceee6782ceaaf569814bb9e658ff50aebf6f3c9791893e5d6ada5fdf8c4720fafa184cc84a84f5fca79d899636e007bd0e1a89da094a378edb6d72240cc2d1d7098b53ba4837a5d0d7d02019b952712e4f1420e58af23d1377cd6d5f3989b3d60b5fc572043b96c4f7beb7137c0894fa99d727a5a88a5d5dcbf2da7b0b2d83db88747fb0ccaa8991d24fccdef42111ff402ed0d9bdb8a4ad13f8fcff6a1df56c82a5f88f575f49a06275a9e66067f15daec402ed877048499909b9e76e5fde52feac944e1de7894cf13c515299acc6442d90f027317b0713805a9512256bcaa7963b9429a510c5869792c1e29082921d0e7d0cefffc34d30762fb83e2abb7821fab4ca89d08b497f75e3149a5cd3d23b29bc52137d8be9c4a95c6376f62ed64fdc159b1bb6c842bd07f8cf03f7f2eb
+K = 48ea48cad85abe488665eb75359217b63387427093318bdfb5d7d8092d342caa
+R = 11b16351f8f72031ba2a772000ac8726a479e1be4523a9eefabe23947a1df0d9
+S = 2660fbb44e29e7687c10e29de96fa1ab03c087ccce086cddab48ec63774141c1
+
+Msg = 4c37a4c8b41109240c4f53d87277d3c790b2f071105d15aa10bd0f7709da274ccea1961e0b99635b31acd2c80530d2b403d7110ad7cd0e3572518909c136e73e57d38c1c7443e58a257f0736b9f6f51da8fd1ae9213e8193003d69583381f020cce7fc59ba1b1ed5541dbef6b59925750d50b6515a977aa4325d5fade42f8287
+X = 6bc051fba93b92859a8a06eb361f348f5e50d091c55b998476ecaa1777f26fb8
+Y = 88a4dd593b64a4ebcb27ffea3de9a7ed7801f9672b5c8dc27b383d6cba58b4f00181634d05eb490282ce4e57f0940373d3a7bd7e9ccaa9bb2965322ab5fb21b4327b47ef4e2b42424c1383bbd8558b506a7bf5537b049fff35c558bcc739b760443728c090c34d6d4eba81e24e42394f8fb826f7c92ca71a9dab16e999274726b0c5d8f72fb9141870dac0bb9ec0429802b629ad71ae0560e5862ecf3eaba9c2a584885b32c684f6d55fd1b090d93d036a4e9858a4d89b9b5750849d926c519120131d456fce9d247341eb17336ca9729a9080ac5b1272fbf707526afc8ae6a8c661ef3c151845f6ee0902de9abb4322afe585e59d6d418e87d7cdce4897ccac81d013fd72dae1a5557762527312587ca676f0e0676000fc0c76b8265842f2db7e18e621c0e3c2ca9295e9e36ec8ce1c85097ca5fffa62e7b896bb16836d063386b1e663ef29ec1702965a7e0562d2d282f80952d7476b322ffa7929a453a638ea3bede802ff5f8f566085a6e2a2414ef7a6f117ac8628486b23603b1408faae
+K = 40c6be904308e25af6616fe77c23e6e6570ac32ba5bf54aa81f6773a5071a904
+R = 23e13a35777c189ae56509c7afb411b31307737e2ffc8db3f208940c5e76edb3
+S = 0544758362cbb61d66b66826958aca63af1b8ad615a49ba557923959b68f8228
+
+Msg = 443473d615bedcba2c8d9a9a45a28c428d7f1a26ab14705627d9ad13f53b767cbb60be523fc21a99c373bd7761817b314290f2f6a80e06e12cce238954c648ace50f3b0dfdf71dc308e1a8ee1159fc1f19b73ab6015d186d9b6bad965a9ad62e440a9ced13550a444b5f0400b96e2d238e9e3dc6e6de12f44205d4fd57f60e9d
+X = 0bdf6ed048358dcc9a2dc555c3d45ac394571135ab36168d9fc4ffe4a3529a80
+Y = 0f4ec6e2baaea9c81e90700519f2f05f545ddc0ae9bd3a091e8b6ba5255c15fce5ef3c046771c5f31bb01de4377e142831ac1749903f9317c7b01a990714985f9251198c829073205924c568050acd6dcca757618cd2809bb7aab64db1e86ca92eeb854120c9d89fb9363596be9cbbaf8eacae2f18f3ed483589eb466a5144824feb1f88c30cfcbb7628f7cb4159ce32e7c2ed04d0ff0481c958e5ff744522944cf32020389b32959b5e12f80f08064908a270f8695a3f99e75e7e85ba3b3c773f04ef9e09e76b6c47302e41d50ead04541e0fca4a42502722265f82ff60ef46aa7547f9de249135dd077f24a4e7e03be2e3094772767a9760883c520816fae637c030956ea25f0a869e4a00a4a8017bcb72b2f2fd83643bdc01d8ff2868d3caf100ae8b818b926c96a850bd69d8931dbfdcff31c67c537c4f5959d04b744a346647066dcc61f63be6251b590d688ae3c9b53f392007d8584e4624ffd2941650a31dcd5abfae7ca120b11c8d0194be96e8dd09b643d5685d1065d98f39b6ed7c
+K = 63066e05d16e79fd013a6ae456aa3f036e9d58675b3c9e08a412420a64c1f977
+R = 76bb0ecb9faec7c971137ea6feacf1792073ae80be1ca8ed9cec2a5ca6cd510f
+S = 34920246730e0974fb0faa57e77fc50ab78726c8e51579a0ef5ebe3fce3ba7cb
+
+Msg = cee06f792332080d6e73b3f02f5ec16996b66995beab4a2ba092f40d85c8ac1accf54fba068128c8cdbada209360776a7706455015e73e92c624ada1dfa62ec794cf2a1a9294f3fb55994bc5211add1c685d9a54acd5bcd830d9a4fcff29aec5001c3b2b2a9706046f38bfe48e8522768f1c6f08a8e240e123ed30e20fc46c19
+X = 530e54bf51b3ea012e76206b5ff53c1d5ae6f3433f2a50b66b6947e84dd52171
+Y = 5c9205fb649d3b4ba2d44c80a925e30d27b05bd339f1ce35e0d0419a91ed31fd108c51a2a62cf9d0adfd877d27cf5575e43ac7bfcfceec5673736cae089516df8eb1ea6b563198b24a6e2522f320b123bfb250d43b600df9298e121b6c5d2e637a989215e095e603ee6d4e8a2dcd17b908918aa514c86a33d8c717578d861261da43f73250ff2be746c6916fc72871fb42a279d22595051b8ac04afbf2013063e31661b117c5d094b4c232b22f21d2c65d6361290c08f12befd1f5a2b9b5259af0435b97b4328297c252d813499f5209dfa35e9198de68501af4ca8658942d059bb62b8e55a3ce6120a78ee098132e8d2dc3757f7e60f8c08c4e43feac67abcddd1ea2f016839fb1a0f797b8b137ab43b64508ef69f6ae0f3abc4ed682aa7e38fa5146fec62e01e0951a6e81152de43171ca8869fa1a42a4fb2d8ae512c005fd97d12bb13f299ab9f5321ee2fc39b28e61c9ebcb91ecd2b610fd8291f538a00d06d057c3e79422a931279fed9d93b0b6533fae441e98413025fb4fa73cdefa80
+K = 4e500b513c2e24ad17fcb8cc0d6a8c54e654e00a892545a33cb5af8877589520
+R = 6d02536db546f2bb1f65ff0b91b964802b38d171e678054ee41f2b8563809cfa
+S = 6bc51120e35c955ab8f717f8930d8cc8def8505415cf159d2516f96578842f31
+
+Msg = 58aba24e9481d1151b574b146ac21b17110ed0b9bfaa55a4e2e06dcdc18bd10cdfafac047189f5ba9f10377affb40a514d528a3483fe8e64b831ea0cd076ce583942b938a4b257d0b5a92412e01dfda8217d5f8054596a61d5737d8ad8112ae228220e3bff60e2e891d03d53fb14f14dd91975dc15d6b7bd62e99d74ef3839fd
+X = 7bc2316b6301b772b6742d0c50f2c1c39bbede01448026b6a201793bfe7dc3e3
+Y = 2adbc07d8aee284ec982c4b95e1ec3ec3f5fd5172368ddf83f9a3c69655291dee6b99ed713e5a1fec338239b8199c5a3bb2b5e2e7f23fc795058a9ac70ebdff2b3daaffa389e97fee35f174961f12d634e8b8250b8b770b8d7113d0fbc020b7b108f8d6b2d7cb6c59e2e151015145a8e374f9b7396e970d91e3c1f85ce23dcae12b2f53741cfc2350b582ca87f0ff9ab50ad0ca2879e216e61a5c358970a3c3528dcd9ece6b83d525b31fe687696a2a2c65e34f2854fea6ff92244d27500f7da946c37169756f4a4664b2909611549ad2b93ebacebfc270ecf4204e6641dbce05da2c000a4ca5ac885406ba155807494706180d54cc012ce06e734024f4ccd882bddd2257afb5c287bc3a8570edf21a20afeda0c762ad696fba177a5f2f9d609355cb91d72ccac8bb9e7c3cff1834d86b0772aec741d7b4b3c3e43bb26ec9f5e86b8685ea5c625b6aea450a46e85e380b158de6aaa2701ffad0c7d1ed0df355d09d06fe1758b2f27a5d02aa283aec9fd12d3b62d504dca0b6632e89fc55fb083
+K = 0c2a0d2b326ad63e869384e3e2e32fcff8db83285fa0a5b9a7b13589a7dd7fc1
+R = 2c462d49344f3ad03b6798f96452f7d66351cead919e8201b7665c877f8255bb
+S = 50e8908a1c6684a2caa8aafb432cda4b7699008c72d8d622c3da4171e51cfdbf
+
+Msg = e10604ca00728e533621dbb6618b0c877c4902a2ed79aaf40a4daa34d6cc216ad4648daab6cc1e18451bb94e6a1c0c6f9d0d883962eebd507da099788008da23205e3b4e90fad9ae857074ffeac63430c0facbae489c54c957db09d53e12b656cc278615a3a5612af4c2f168bdeb118a42a2a67103fac321adf5688b05848f7c
+X = 6dd500e2aece9ae331df269c26a4e5d58fc6be3963f5002e36bd9cd04c1adbbd
+Y = b0448d43c520377b7df214969f59ffd4e0010c12d7e5fa8f241e9ce1c634439c94700ed5742a8322d405dd05de9953447831c7674e5ae1b89041fb8f2ec1054b928c64ab862f021a55ebce838d2a3d2c7645ec7c0a1a4603617e4f508929144c1ef2b039bc78b59362d5ba9537906e66c8e9c9a3c68e71b35d88b8bac86cacbebd962c66e18129637fad2d98d21e45a32672649492f131bae88c9989bd6372e17492bedff4d9b091b3dd00ebca6bcc49148480589f9593e32795299f3de7e09d88bc0ed27b7ef22ef7d202207fb5ce8c91712c3bd5e758d2822809ea5d2cb288332aa0760368259281a34447ff5a98c9c97c1d58383cd14f6d59bb5e5763217b2337ec2321268197f02cecd0d9fd93db39f8059a38bbb35792ba0d4ed1bad95a05b481c39f6adc9017dec1d662b0803f2ecf0845935765f9356db536c8c11887d9e44b73b6996ae7ac24fcad9c23017e5c2aca88b5a136b6307298b85ff010f964b7477a4f980800e69d3cc0f438aff7f2df8ac61d64435ffaf5e46633609e87
+K = 65243ccac0a014b9e52638171b4a88b02a8c6e617ab9467da523487122e6650c
+R = 56ab9947ac94fe3df7e35801660f68753b0b620a26594cb8fd375be3ea4dbf05
+S = 608ed1835139af29a2e3d874df465edd8d6428f40357d9ae4904efe8bccbd035
+
+Msg = 8af31f66772fb0c31a8c5b28e568e6368cb66b591edfb0db867fd99e83feb3638bc80f0b14483d069e8f2e167c8b0f10cd6b45d039b7d6f833bd58d99b00597aeef82fa3aae2e55ded62ab660810de0fe1c92d53adf98c838c18fd76a273ea12119d675af727011869943d765b96ef266270b4f89ac72edadcf707a4a21b7533
+X = 145abce3eaa8fa6b670afd658ba0c14fa98d2d20e1422367d4455967f9844858
+Y = 22f3db9ea369938ed750d5ed3781368d594e62635c6b6e103d6db489a9972f398203abb973d5ad9c0dc110586978d2061483c0202738ceb01a665dd22fc568cbdff2148ae664dffbf888e4dda5a04fd3e89398b4f1ffc3a3813ae94da1f8965efbe7f300948749e9757cc7c05f6e53fdbff994c223aba2c137151b6a320f5b7f8cdd6003baa66020162990624099f3cf56d68b74e96ee09240f2cf11e3954e75b261ef9e8e3551c6c00f41e9eb17421203a4565388c321c1325f72eb10c28a9deeddcb4806f625382b37f0becf77936b7f83d26bf1ee1fe05e8a0005a4058c678eb569e339423e7c844305f4a18b1160a0c430513fad715896b62b9d6e2468232ae375f5f3c0056245eb4616ba11a6029410a955af09f07595fefa03e5516c95a4cfcd66046be2a4f7b3ab274b21c0a4f126c482c934c79dcbbd6916f3b887b2600472495c8335de121c7720f29ae56f5ccf9b99c9ce5655c5e1d15d67895af0dee586bc491a97241f7eff434bb79aad831db0695781e6b512e8702407a7d748
+K = 06f085f77088ec97cebe5397a588369e3dc15b70f2a5316a6dd5f94967fe3dbc
+R = 0fda7a8a3e5d324fc0a1c2841cd22f98757a0c6a2a465b0d9d65bda9b23b3c1a
+S = 40860265229085453fe58487a933edf3c28433694c7b85f6370d9a4783168237
+
+Msg = e2456ef5d465731b976f2ad1fc94634c0569a0ff7566a49d47d69e60b3b6d7eb2ab25cd49c931299796bff7e9774075ea20a972e3949a29dfb50b2b5613b45c596ca5dab282ff183f564a06311a49601a1e8560d43c6a481ce713f46c6ea85bf4c16489fbd72cf552b26516298bc66942a05d5a8e6d0f6a88f3e678d310e297b
+X = 286d3cec1d2ad2a85f0f163245267438f7d7d62149ba9e59a18dfffaefe44358
+Y = dc9d68b53f35c29f7ca003a2583ec8f8ef5d78a0e45db3c884d35df4fb531a080ee3831bffd3c756ea5042c7614570fba2f6ca4870db4a453d0f793fb4d0225d94f27412dbdf43432f52cb8f867fe5f492a8876d7bd850d899ba2f0a53820c440841fe0cb76fe0444bd6c3235785a3da3081fef99f53a195314aefe955f2964c56506fcc969b67b323766d299c0b02981c72a2ce3d7524ae6f08458795fd32e31b47aa1f974e356081163cb23efd73a9e655deefe5e734ceb58e88a9dbb524eff7e11c3e30680702d8560dd8b6ad9f61e7246c6dde164e914951d6a0573152ec8bdea679dca1985bcf267304d5f1bce2f32bb9946a056857359afbaffa59bee61ad960c567efe3f1145a8a87c2491fa6b33f7e71fcdd8f1ffbcd2b89920907d1144a8cf0573f5b89217bc0598c6e1754f1ae7d9d42a608a051621419da91d11bda9bb9dfa7118e4b663e7bffe6e9946c77ce9f8086dfc822a7ef728888b31654a19b6debd2ca62f5e3b4e289810435b363ecab511f47e9e157f0f4198862ca13
+K = 183ca3afd082bf3de19e89faffc5cfa7dd713a873c02c723279b3091f9bc627c
+R = 778640ce75da584a6a83f9794c4ffdbe30411be43027758c74f89f7ccc7f3983
+S = 6125481e103f7803b2f16d9a4d00f881e0b367024df5822f7cbeb5711e0e4401
+
+[mod = L=3072, N=256, SHA-224]
+
+P = f63b3cdd646d8e7ddb57216aa6eec2134d707488a1f29cfa9970645f1227ea5db2e318eea5da1687c7ed90509669345ed6134cff32203ab72aecbfa693d216aeb55d8d28a981f4abff07d1319a799be5dd746f84842817929c305b408598af12045daa2f1ccc8be4d81b513c630f017fec1658aca108a1af6120ec05e3018c4253c9dd35bce062b73d0f2a93d41c481a5c43bb97909682d39a9a60dc3c35e36375dec6ced0d2db3ba0d111bedea701a0e4753624977a9e75b70a74e2b81e38a52ab22da131b35416d3cec9663079746a763476e57598142e39861545daaf8d38a176f26c71f5afebd9c5620da80cf3452b55c37c661b4a1ec0351710b9de4a3cbe0b98b4d9ec89128d97aa7efb19db8ba43cc0be25c200f90e1506cb78ec0c336d7a95613d4204e8ed68d0f0a6c78420105a8d2d438fbd2551a64a1a0b03ffb878742f8c9979cfa87394150281998d51701d5fcfa9696a4989fd25f400955e626b1abe926c0afa69aa6981900effcdd030592f82b2042a47a9a5a8cb0283dc4d
+Q = 80000000ba4634b5fa4da054bd0ca48ae490e57711f381193842429159ba7ca1
+G = 8ad4553c4e49aa24728ab5024417b132d2ca53a55d959458f2f759adb0435beeefa3a2cfcd0038e2420643fc4a4deeb5d9feaa1edf21193b40e14b42982a94f35c58b81147d7189d263c9b12fe63ab9fa5f6f03a2860c186432e3ab04f2ab0f2fb6147bd9bf7ed5d20713b9da21383e2c3a168e7d09d3d8a5a058fd23095b5acfeb864a3306be2425fa1ad32ad6d9382e603b03c68af4af0246397102c4155cba811abf99da7839e77b2eac9970588ca1d0a2361723a164ac9229c2e80dcfa8db4f9e29803effb3168c7fed7a3a6de40dda19a0536af9b5b7afaefb9c70d6ae8df12da658f6236043aea873db29ceb6f07d108f5225687bd0c30e3084e2090b45ae2f92a97b8ecb7a9705c4956b8b31c4a3d61107c84e47adda6c80d5d22dab3d859220f9d5aab13677ae3df168f0c176d176b54506c639853f04ddef2722f39c18e5ce426e14562ad8ff26247af88870efb72c0cce836de8fee67a662378245b502bf1f83099988a093ce7cdc81364c78b1f4a51b800df6137c71d65e6b089a
+
+Msg = 957973fc3f3fe3f559065be5d4a0c281cf17959018b9a670d2b3706d41d5812e37301005f8b70ebd2fba3c40a3f377a751b6cb9693e3cb00d92888247d07921d3c1e9257ce08733b8926e0df7bdb6e855f1f851075d4e628d110d42b643b54876e5faa3611477ee68371562555269ed62a9271bad50cc4d46038de2dd41920c2
+X = 524a7ea5977f8102b3552930477f5f042401165d4637dcd8b9d13df4f3aae5d0
+Y = 42243539e49db9ea19d98d97f6f2a94b23529812df889eaabcfeda01ce4c759487fb89bc82da75fe1c9134361f86de47d16d8eee80e56ac502178e8ed8129477af8bfbd8262c5edd937e1a86c0f0e7b2afe7bcbddfcb5814ced0b756a76ca178423bb4d578c5da183712d968582640aa0ec7e9fb56bfd960d7a57549747d8fb7ade47cfe816c1e57da6633dacc537de060813964bb5b2757a312f9da3d84e60aff98170051d3d90e380b8bcc1986c58ff9dc91e8827d4f9f5fc4b2b2e743cf9389ff02dec01f5d434b430d162e891c3355f91855339f8df58300e4c993ae4df8c4318b5c4bd05283ca4b46b7d2fb0f6476bf15907f50dd4141aa7acac9daa62eccd3a67357122060b6cece0446a93eb230ad93bc9a4d1b1efeeca1e3fc83c119785035b439509ffb7968b1a448b7bd8315753fdf04a256eca1562a11b096c90a36b353659cbde4420e17e90b94c43c7519c60641ceec056f897b97d6bb1861268e0dc79b7c3b6b7639c255bf06865737459126cb465bc1da4a043a1963da7d63
+K = 29e4d7790e181b4767903fe0eb37757f33f13337c33588c1fdbfba0e655ab621
+R = 2e59d5f30f73781d38255b70dedeeb38ae78df4f002c1f747c08deadc6530155
+S = 615c55b2df0ca28c60a6b385c58fa036df8c4b2f4f1935730bf8f4f0bed13610
+
+Msg = 54071aca28969749ce2e2dc855052019bec27d0dd6a310219311b4b6d822467b22b3f02fb8313993fc77c4af1d76ab9db99b0b2b78204aa45f4032a7d945f93d55bcb8a6bbd47f98299a0929710461419edbe1132dc22575f5afbe7078cf5f05b231000f4a0f9f367d9025ed3ae1786e0183eac93ea96b55304a8c2dbf690821
+X = 4b2d62d0e7b88436737d03d6f64dd6a6dd0757021817169ba373e3a31bc12cb7
+Y = ef78152efd88130a4fecfe235037de2309b1e2f322d4f4154756caa8f0b3e41be45c80d895de56389257c391307286be8e8709b80186e2724172b0f2974be591584916fc0e750c0caf83d839b5c248f5de658668665f004bab8ad310118835957c02da6ae9a2a79da039adc884f9eb8b62e379e27f549e7f8aff8ad2fc276ece15f0423528a09e31b26421df93573bec7a4d6c2cbfbe5ce0fce0702088fb384ad1dc35bb2c1c742d43d79ad136e71057cb9f22ca042e61d2c5cc4ccf5b75a7379922bc4fd88372d2a8f6a2750865f91c143412a3fc61e4ad4abd03dc1ca0fc4297ab107a1963533a3d80a24ae2ec4146e8265acfd4446fc28103c5047c17796c4148b8e658e44e9b1c259d63c97f0e766fba8d9a7394cdb734508bfa09ae42d2da3068e2c85af2065f618ec3f3c73d73a750c13644c96e3dbbb7474325af48d1d145c28d69f22cbb4a9073059a9c40891804c73a229f01cef0678cf4855d18f900f0253acd6b3ee53dd96c4c92afff1f3087eeb4fba86d2e9495c5f734a46ca2
+K = 5af719a9e5d8567dc26576782e8f247517fad5ac5de0f7115c5158748fc73b40
+R = 0debcf6c88504a882a0191e6fa4c774c10858362629428aff24c22e3364baa15
+S = 53d8c1dbb3a2c1023521b705005ce6350bcf66c093588c35d768fca295a4a9ce
+
+Msg = 49d5f20acf1e9d59a656bd163fe46fc868476ccd926377a40ed3d7476e9eb7a8a70c4b88b16e799148d25fa23bd0c91611b76c9665f5722f404fd90efdb8ad14b759c349ff6c830642d51076ccbdc57f152fba41c6a7f3cd3905fa7c857265ffc7596a64dc69490a932b95adbc79a3b4f21b2c6fb5d5835d8bcae5d44d912a0a
+X = 4abef24f715cfb3ba6e39c26b07ca46b700aac69fb8df3c0e09be08df90e44e2
+Y = 8ff13022080316bea49b89a06dd5a971d86e0c9a3af414258a8f485088b66cc38cdea02cdd62096c00eb0d1c2ee662cff16f6d2d30440b2ad9e897b9eb939b1299ff879557f163f17c8ac60d0c6e998b3a044b43fbfac7b0cc30a579a6bda1b4ff598a531f9e37cc1901a7b08e794a7401d0f8ca4be55bff7b176321828575a477686a98b4b17266e101601f436e554b9e4288057970fa3463343e7e52a58ca145ec9befd7be31ea766ed74ac178bccdfee9d29565e7935e8d70c3eb091e3e3b3e6e77716931ed729c49b96443606098bd0810989e0e6f253cf3ec38294231b711b09a941609acc8976819076543926ec4e06f3e4d7f123c2b8771e54589e04524e3b4f950da560a25d12172d4ebdadc1719400d91cf0264708714479200c50ef00ec0e604909a546c95eb2fa53c65ee72ad53f149c938dc2193496db07af3b30a1f439708aa115c8dd47c81c1bc68ea3abd9026113c01eb05558b8a2be9093476f01247bfbeb3f2858b13e6228b98205fa710b6af1c5f71480dee401d7472d7
+K = 5472e89286e6ccbed316fe7564e3eae899ed7bfc55ca7fb6fbc392d191304bfa
+R = 19a73b049b164dbf7fb2826f4253617cf1c5bb46ffc5204efa00002a79e23c0b
+S = 7be137c109e68f337b5a21cb591a87af1cb8681419f875ff8f041e829991fe28
+
+Msg = 1190853efb7e04cd4947c1ea5b1b5d9e0ac5e6df1dd050877308f1b2c7e0a4917e588103d28c0f6e8b72d967aa06aca68a986d807740f2dddde7281e550af4f637eadf61f880c7351b486615096f6ba50d8754bbf9ba1c49a3485815ef06b3cd761b5586c3fc2b464c6fe12c160ab0f6f446fabf74212430cec15e75a57b102e
+X = 7b2510c73ea6447bc319de79afebcf45482917042a3ca3c1cb1c97d1a1216b2b
+Y = 9bb81c80d2b8a601a09e22475d70d1dc5513409fb4668b176c76b3aa1af8630ac7790a4444ab823787f6f569bdf02b9eef5e7bb21a88e3d3296857e91919f3c473add16bcd763f31a2f9844d7cbd8d480672a036c4b104be66acd66e6ef0e8a744b3d878090d1de9f105560247c62153e117efa55ec61c177cd82f8d72c51d253f4dc7336f79826025619fb2103f91144f90f6a689abcc51c68affd28462578b183eec942058f48abf546f738940a6c26d301c4b90ca40ea49c117d61147e8683989baed7a221c4f22092f72b1ed604b6aa94ff6a574b4215bd6f8e9d7b638afa435a3346589a61b1d1db2989d7b45f3234545e8a22d605ad6cb036ef791f625d2c6a995eda3e0cafce704a2bf15ab5dfad0162104592d23f52aa0fea1f432f0a308d16a45e1f41f823262074e9173754ceba70cd8a370dbab1a14f84159116da73d3a9cf82594cb3af95797cf444272850589acc6bca471d076335d67c461db602395bfb17c39bfa24df140c0ac4388db0534a50dfd261374f81b310f751d16
+K = 0fd7617bfdc671127a1d7465f683b98d8951a741f85d43cf5a5bef9232a16ae8
+R = 587d7f4454d59418a7527570f28f1b07451f3baf28f5cabe0310c4d79e4253a5
+S = 18839404aaad59ff24d6accec3b7cc6ac7003dd4adf96b77bab068ae72f25f61
+
+Msg = b1cb430c5a1d72788c795ab567a84c7f5977965933a5bf238058f2fc818880d25b4ddef9635481fd9fdd4598aecec3764fa73093a225d4e4ebcf01e4b75bdc1841dc01652c4d9916afa24b89c2d6854b72eaa7b1f3089d1a919210831ac80f99835790ce64abc34270cd4551d31b8f5348ce8a70df60b88e085a984acac665a7
+X = 403b2137ade39c1e5b817ffbd0bc3448024089fc1925550b5b860403e7ba65bc
+Y = a81a54be0685f33505aed9591f333a74a842995da5135fa48f5053fac29fff08afd9b901c3df1347204a3f133a7dff6b1adbab077526b638a63837d7844339d48fe107af08ed62e87de547ced84df9a2ccc45876b29bc5361ce8a9a21b81d4f85d3b671c9b44b5483f2610efa01751d3a07fd694e46653ac47ac64a910b7fc421f07e5de54e898789989091e9ed58b7c04e9e1dced60475dc693a0eb4015ed658110b82f8e720dc7afff69cea7b8e56b8a9755bf1e2933d083608377504cab52d38cce1ba82f84c26265e693f18cf52e930dc0d8bc9d41f4d28b32b7405cb1fce88a55be40dca1b1a351aa7d77fa6ef84c776fa301dba2e236933d89c8b944f53403414df0d434db72caa749fbcd566d76f4f6f0bc40e42a29aebe6210e89fa0ca8b6ac08a4cac65c590503533c3e4f1b3c5bde868e79d9da918b72d1b098a7278769546b78450e00e46dd400efe97c884db9612baaaeee2486f64cd8302a4c32d8fdb873fe0afffd7bb74811220b01339dfc5e567c766af2805ec1c30126399
+K = 2c1ca8b5ce7247dca6173fbaf854d00020ded6300311f53ebec8eccef9570d07
+R = 60d2763f0138076e9e0e20f83e4aa2e9aa352c19ca79e3726303fe89b12e27f2
+S = 07e08d916c8a10ba269dc460ee9d83f86a7b3d98621bb7324a6a7e607238baa3
+
+Msg = 3bb9430eea6979129be745d5ae6babd4966e3abf7d9ee5856f2caae6014cb340eebd28bd9f391eb46b3a2b8a4cdc224e5508532ca08cb104aff677133cf4393a20fe4499967dfa64515455930c659d43bbee2340b14a3b3342d4b9a466b889e850dff4b2a51d389ca32fb6a5f433ed93032be4e563695797b8c1e1e019184172
+X = 0d3fc8fc4c59971a963e8e41d26a86499c962615c64abe011e88e590bddd3b0b
+Y = 75b765eca4ebde0b6564c3137f16cdae00eeadd2d0b2cb83cd1500cd05ed0dd16730c9501c8a353a64634d065f6137ffcf9563d96127906fb17d5a79ad291024a4a6fb7e7d080219a6231ca158b65f5202912ddcb8dd1f018c9b0e76b3a476336c5041bc502f8acb748f136c3d78cb2c429c8f1ac17b63dd7e9e57b607f9debe571459df3688cf4c11fa1e84533aecda2dfece05f4bdb268cc7b0c8fe7af5a633a83515ada95f31824d6a3c7122fdcd12f54992cbe64d1d6bdbd0ab5ae4d19aa52609750a1de186afab5a16398da473d128882b065e873809fae0bbdc01a9c73b5c6ee65857fa794a15058ddfb24a9a17a0408646f2009dda610c8291ae148a18c173f836b197c78ede5654895b45a3419e9c3177f2503a93ce526be14ad919939ebe3f2d07f006a0b022d6a623c6017f0c76619f0780531d5390d4239b2f900efb44c9530c7d9b3e84a70c904b179ad0c4f909250f7ccf83c5f42d6437cbc9f03fbae8131a12d33e01721e650aee91e1c893f5e7e039e0d585cd7cd7495c40d
+K = 32d9aa04b104b5d7b59a122b368fe0cf476e28098b898662a78efee764545ea5
+R = 7416729a1f60208b7f837480fba81840e45b338ab9846e9bbb9168229f64bcea
+S = 58eb904076a3ac6907d750ff6cdfaa465435e9982ecbdf72197b09bb6df1373a
+
+Msg = 55a69fc16f6b753d0bf65e844d067859f51dd329279980196063fb59f89bd778a9244f932c2adb6811183612105d1c527e8302dfee5042cfce5dbeab165a396f5a4c21339be1021b7ecec66f2177f94243ef6261608c56919679d44863cf9d2afc6010fc2bf821b931ca3970d69b1e622a908389db5049d718e357071063aef8
+X = 3dd224f00ee1d4648c600b10ba05ff36ad2c06ddc5a9f0112e0331ae958f36af
+Y = 6146a51deb79957a83b2c7a3204b5c34ae4f8e0db60f0c07e70803f22bf99a39647263db9e285d72f6270ee10f18584c39081d2544d40502c50df1e35a457600b5569d61e8126c055f7b964572e9f3282e4d9745006955c24261c68d7c0cb3f08b0b0d8eaa971e1a631c68a3a914d35efe89f76b9c2116afb7bd1989e202e092b5b570eaefcc933542e650d92c033b5973821d6d77cfc243f744da80b56eaea7650bf50802516228ad6d5b0d4e889c575e3678ffdb1c289e59d9ff7f84a3d63d39d6888dbe213e2c3b3114085e006ad74505739fce826f963284dc4e2b01ec2f9233d3470e82d872ed944e62961f64134e8080daf2df494a76240ac0cd22f9afae7e80d3cf3efbe055147f62ff8c6192e388b49e47d9feaf19eccd65dca9991638ebd7b048077707adab1cb2a4358eefc4aab8251fb0f9d5f0b09f299c720d3a8c00a5a4d84feec040057040b709cc0ed185a832537bc4b2df0ec1f77169ac96e91282de21f342d5429ec3d66ad9d336c440949a1211217bf54aad93bb4b0a43
+K = 7969d08c0cafe4019b64ad3e6614be0aaabc2c2be61b3b3dcdd10d5f75fa24bb
+R = 136f93dcc7d33e559b8db0af13e00c7190928bff5086eedfd11706e6f2349ad0
+S = 32b95b9b147c7d1ac2a2f0057fc0538a4b7c9cd4652e6783e5d7e3534655631a
+
+Msg = 1567890c69e578a27d6208913dfbc20eddc61f5feed457400693dd170f8067bf290b11150780684c20d5cfd2bf1d536dd3b70025883fb41703436fd09c0a141125784f9091151303ef80cd345e5a7d2854335c2984538c5cd739b007248cd99f1dbcd3148cb0ff0db633f8cafc7a0b99c61e784d0303a5120307d3fb3c4c219e
+X = 3ac374b2a4940d92ab35ebb8e59677fbf95980fe632ffbb1db4f385ee4e13a15
+Y = 5c53d13a1bee17a28720b7089646d07a3fd58b9b2b23ec94af3144830746177b0d2073707b6b84901ffaa7a4165ceff2425640fcfe5d17650a44a168ebd769c833445f1b2d26434c228c1e2edf1704d711a86257be25235a7cea1e5cbac412235b7596d1dfa0398081a4f18151cbb51dc62c226a2abcaf3335e86ab54608040ee814e443b64398213ba60d7b5a3c8ea78ec6b98934c89aca05b97df5f65bc574a30acddd09f73cec14528be49a2fbeca70291b1b29f7042c594994da128fda22b3ed3a935a1a00575ff1ffd193c4cac53a2a2d4b0c510228a76a74333607d15b568614427144b4174da358e383f658c60b45710036f54f93f17bc808b302674e838c1dfd7f816f7ea44b0d97386e4e1634c9539568dd6ae1c28f25b27aa94499ae389a0926c8fa62956c6e24dced0afb0491dd9fac0516d27fd4d2dd0150ee6b4cff7bfd575043d701daad0f1b942a0e4c61956b32a68c9078f6077fa9945198d447a5bf3c47b7288427edc6f99655aeadf8de18515714c6b9c0d4ce5ab092c2
+K = 7ca690c92c8d4a3ac1d5255a2e5a12922093b8b2ee95906eab29b67f84fd21cc
+R = 4947d36e7426f1441be5a75dc9cd845450c61104f19ed40ce33e252fa2c26268
+S = 356879deb1daef01da04750d58e598db47aaaff50b1cf42d87334a615780ff8c
+
+Msg = 4f7d894dfb7d82040a9fed6c26a7d27a9a1511388c113c64715a06dc46fcf4f904070a6ed95bdd8dc1730a27645d37eb3b02847cb1c631ec0c67b2ee07b8805b34dd9b84e6ab3f9afb9246994ea579567a8f4af7feb86898cc9cb534c387993c6ec16584ac85bed36bbc2c305770f21163686167dd53fe562362ff549d903539
+X = 2c14cd975bc163f9740dcb4a5ba9d8529c5a075016e02400dbfede8dd4f0d245
+Y = 00967478358d7c1696ceb92be850f5538ad8543e151aadd84caba1b72f3636a2092a86b6462873903d5bf17f612b45b5133eac1630bf07c0371423d2e5d7147ceacc9baa8cb3b04cbc3cbda429ab40d7e592730dc477b0a95f1fb5ed5d91e14b9d5a1ac8d403a55a658d1c383bb598053be238cd82386968aedb811586fa2a14119324896f2111b9bc7cff666d37affe76041d98f362daa09ff65e82e865eb29c5d4710ca7800886887d383da0cb599b225fdd210a3d70929d35fb9ca807e56c91c0851252b95c07b6b120b3b650418e0f54f45736f82018d09294462dde6eeafcb15a2a728577faf3ef3eb13db044965ea3892f7eb0884e47766089d2a43abc62a3c375831c20848dfde8f83c249a8e27f2897cafcf5a06b7c3591e09b42f82849d498664f485de26c788e559ad5b15f999db927f81f54b96e997b9096b2a7e3e756f5a9aab54c160cfc2e64492179487c98d0aa38308d67428f3a113228bc6dcdf7ab93cbb1da225c72c636f49d27442cf3cf2f9c49b90ac8bafe740dbbfd5
+K = 141936264e075533a96952808935238d715e7cbd840c016ee7a9f508608e4808
+R = 0940724855a0671d60147dc61fd283190134a68c178114d59ab58da73a1c8182
+S = 43f194b97078dc9b84c8e8e867a74bafdc2211706ae110b5aec0b99ede1ffed8
+
+Msg = 9b62a74bc49ef4ff5c62165e7d25521f135c836bc4ef023fb4bb1d6b42c6291071eae0b465c59231cb297cac6d145875fd84f5729f79f92218522b9e55cb70d471030d36291a24925ab731a2d4458cff677079d207ce865b3d5526009238861d64506a92b76baff59b37b863087558d5965d76685f0fbd1fab1b1f9561f8f69c
+X = 70e12e51a254831bdec081a8882e5a24d78b48b6dd163727b93f803734e06a3e
+Y = 75d7d9a5dbdd47cecd12f69ab212dfe08a9656e2bca92c81db2d268a293a325e511cd5aa1ba59deef2ab6311665dda58230d48f1416371de1a8364b38f5ad599c472d363a18a2c13d572cf849be2fef9a166e838aa58b721ecfc4b361fdab1d0876b78e2e8f23ef1c82cc0e1700fa015a4007b1d7b535c82d23c129d1d1c9c4afe875a06c05f71f078cb8d9060f4d936671faee217d4045525d570b0c8ca0c4e8b55dfe9b780ba69c9d8cda10c50fd61c4e7214b943c1c29797b099f57a4c648597cedd9d909bc584a9b754b209515dbfa0fecce2ad05c848e99dca21a6d0d5f2dac2361e4c0eaf96df199ad2888d671974ef05d65c92788434ab42f1f1f79edc49ec1fa921395bd0feb6a9e6a0622e8255b0ef6937b89d0cccd5852872d2b0ab5d79c2f198bff6b8aa38acee21d6c3add5562d84d968758d93e8c1d611f7d6182b62e44f57df342899bb564a794d13915882143d9df45f8f21cc030af3397e9e949683ddd8d8da9909cc1139619e4b7b252aadd02c66a5e20105adf26f2f021
+K = 5de7fe70b5c60ec0ba66ade4fb6b0c925d1d56d26d6f57c5d12d07b5f6f800ed
+R = 01e3de398b018a694780ddc6ca12b78dc55e7ad9fdddb5a3f5b2cad0103253dd
+S = 03c98280abe3050a67f88ef29fb214a80124f47321c62e41e3905b8532f4936c
+
+Msg = 6c66051e04c2e6aaa43de9aa42cd9f61e8329c124ed3031b67452db4c435db291d756ba6ef90ab06307cb8d70f3496792e633bf5ac985c37c43bdb4e455c7f761a5ee450567f85cc977e968e7fa42a428c1a7e915c82874865631d8078899377255947c344618297b83c96114d11d74d8cd579b553667cac1d97aea4d1684987
+X = 11d2f10293c3884b1e28a600dd71b2ed37bea133255a0f97e641f9530bb4693c
+Y = ed2e10a44316d677467d79947bec9e405d30f32d860a1ce46b366845df9ad222b0f992f5844571b196a310d587fffa74bd510215f3bdafa1c93d1b1315246fd2f794c4da07bd722a98dda9a02ad4255b6d5267738256cb8639a145c28404562add2bc7691dac12600ba9f8ebe00614ee3fc6e6b2484d9c5c7090b3f3b134ba19909864563040fe8752d6c6ab95111fe1014bf7bbe4e674c9d03bb8d229e4b5f6a6e471c678b0265e88ccad7960fffae700f3a75e61a24ea882b970535eb7017e16c48ce9e2bc8357f7f0889c871d0b4ce29d279afd1d114998d1eb6fe4a5661e429b1327f0a39e9ef00a41a74fe479b90fdda21d9315555afe227274c11a71c0d10c9e5dfc89750eda53c6a8b52a5272c75526375e5fb91ff75d028df7aa2bceb5fdf6f8e3bc1ec3f1e226d04df1d842e4c8f458988cb7415f0d2ca4498b0cd67e8b085b008fc4ca064393a0df517f0b4833ea4051ac3f1de5686dccb7bba8bd939092d6d78fa08f5bf9bf6f13d7aef72f047fcc47a88223df6e1a62d218169f
+K = 2621703fb8f5094bc68eea72d5b5caf26f8ea3a173158b8d3e7f9565296767f0
+R = 31f2c86287e572ff4d07421a58dc7b3d727de113769952b6d8d736088b36a825
+S = 30acbd1c4cd6aa666ee52b0bdc41fc3b239b60d57e279b3f5483c4d54bdd97a6
+
+Msg = 5f8d7f283af00384a519769029d208b61eee0e1cb21ce9fb80e9d8596b894580da7ab3457429e72dfa64e7cb839414de344da21cff55b1b3a83189d208ad2089b35abd78e2416bceb66466762fd7ab9c234c4aec3872cbc8443c92b8ce4ee4595425e746e4b6f7972ebd5d065fb3fdc5e329e8a87ed3cddbe279d57227ae4b13
+X = 1de925bf532a50dc7a10984bd1dbd90500ec9ad22df0f2d6f185fd1ba8060d37
+Y = aa4d065270c38bdf996b1f5f1ee4b67a76ef1e7b134ea21fd0a6137521245052e74954b96544c700d40f36248ff29a712a098d80ca12e28fdd7901a622dd0988e1c4d67de4c497a957882ce992fcb08c5b85c6858447ed6fcbad26d8c40485f0a89d9d020fe233e89319038455644c828d608df9707c63170dd0618c0baef3eca8d1455460a2eb25faff444f803bca297bb680e5f0fd06e887ed50c8060f55d0160ec64517086f4e1d624ab7d12df1b5947017e622ebbcd6f4eddb0a41dcba82743efdc5804288d2863f54003eea12753246e6e0357df05501b195fdf3a7761c4c3acf26537bf98b32f2e72ff1e0159d046bbc053171e3d518344f0537f2e7200bcdd957ec96365caf55fcd246afe771709ecec28348a356a1d4eb136a176adb5fa102f5fa5c969f90896462e0677afc606a948b25587c10316d22e1269fc64f915a796c965b8be97e5beab047ca5198bf2ff856df740afbbc1aefafefb1ed47278b150e6a7222417d3a86494bdb51edd0616899526c27acc2a818e83baf579b
+K = 5f0d6676776f40cfd5ca255fd8e32b10bf3472b193818914876d4c3be68a83b9
+R = 7187cae836823618f9a6e847055ca2bc38c86e726d02d38f4950eb6b71b36bcb
+S = 21f6ff4175765430e2dbed342a85d30056b28905744ece5dad79755ee3d7bbbd
+
+Msg = b216a035b0ff29feaf7d4c34eeb1604155c90338006753ee2b36062d72f62b524504659f70b976c68952a62c2b9a2a00cf0066a5e5098a632df2ee56dd1a140a98f7b3ac12db3576b610d76563e4621637da1098aa20f3c83247b7278860417cecf7e137194cf1bae12bbc63a7bae02c906d503f694dea3bd534718e37704962
+X = 3bae9330b47aab85cec948f944ac13221ad35d859de56db56c31aae88345cbea
+Y = 7d6b3b71b1415807d15901427e6ab002ee985ce7c8d844969c6e7294a2167b4c26171bcd646f0d1bce14df05e4ce58a3ae50b2aba5fb74455233fa6d179a0794cb26e92ca910cd1c16e5464e8fa7ba936341d3ac211ac1f8a2f2a19c148a1c3d6b00ac44c35ea345a3ff73ae9d5abcc6ab65162a53daabdf6da25f96958eaf89f559895cbec52351394f9132c9564d61aac792640f11e09aa6f6cde9ee9ca5e05fd902911163817177bf054cf2eabf7ce8f34bb1c4aded8dad93411fb276d2d0a296799661307de579641e607fdad058d9a3f194574ea76f4bec46bef8adc5d62c7390da1c45f6fc5d9a784f696f24ae7e6b27a809029418dd18a420455c2cc9695e7c0fe00219a1711468e2866b71f3f9c538789ed2843f44f2a821773c52d211dd1333b5f164ecdf6c3ffd71de6678b0c272f92355d5974eb21c3c8fbd0bca7538bbd9894750b1dd0142bea85104356f9a515ef1ab69daed98d94803ac912c770e26efa2fa0b04e11051ced2f70f06f2f05eac8029d68e12261657cf4dbcc1
+K = 248048e6fc52c48398f5cd2ccd8a659c4b7b76dedf54f3fb90c5bb173c5d24f7
+R = 67df1d510d063c9067e9759180be470c71fe09c4f133aca181bdb47bb87b2097
+S = 7328b887bf0d520abe6f24aff2153f40de009e2706ae043dd3aa55521d9572d6
+
+Msg = 6c67116fbd21a0e3ed16b3c4ca58ac49661918bfc6a7c3a6acdbcd53dd4087034fca164df8d38f7ef7db03363701409246382ee053c69c84fafa3c77ad2ce08dc7f41c34a31da496d070a99435799f269dc8effd06d31f85879c299cf7241b37b9a4cfd545086393156737cd9da2d282e7d569fcfa5cbde4bba51bd89fdcc913
+X = 7fa66120c5acd5bac132d07083d07968b210cd9c26c2c56d9b16d98066f5df6e
+Y = 6a50d1125f9f3fc2f7e023c093b3608e6972acefe29c0c6ba07a2f61ed747153ada4a9b680622a842b9a820119675620c11688700b855d4b8d13bf726c36acf923256fef1b53093622d1bcbcf023848b8b8f4abf43bb6e87b84d061deb75236224ceda914b18f7ceb72708789dfb94070413b0e65c1231ad02db42decbe0e558aea06c310aa1a8d113be1f071482fc61913225f007b569b6e867cfb392725776ad71f50dc97b834a71375bac18fabf781126d06df62124064e6a723b48635e6754fc767a5094d0645974041591d0ad4828f63783356696af7ff77cd00107949fbff4709dff8a660a413f5b6c0df37ade84fcbc1d3253ba617265a10cc087606130290909a4f813341efdb611696feb5bea3d7d00a53a81f3a2043b887a776075d250c1a010ec47660087f3ef05782dd21d298d6d37559cd473008f474d8deca6817c1390180276097a81f462c0527928f93a461f4ac2d6ed8c9d6d101a2a9a29201a83d0589f57be28a727484518c7425cf5744df396a0e14a4d260a5c8d29bf
+K = 5771223a25f539c80481baebe7b2862156fcf26220d6e953c37f2a22bce77c0e
+R = 7d489ab0d44bc73271ef42e28a60e1b7ef7dd27af4045546047085da408bccc7
+S = 310151d943f088bb7dfdcd52d82884a7f1ee64d46f9d600d23f52f4cea4d2862
+
+Msg = c8d416c1efe686637078122f798d8804f64a6e85e05f7e8e07634a309a98e92abd54061cccc319f1acd4a087b1d7dbf0b6bf2a09c5dc508ed14dcd5442056eade7691b7fb65b678ec2e137b5fbe875208a427c2a7ad90665426fbcbc7655e48a8965d23fdef11ca8092f511207a607359f94e91b197fcc993ee6ce3c37ad3b71
+X = 1f4a3cf1fb60360db3790a03fe55194985977c6884a5fc05a6fb5eafd53587f5
+Y = cc9b9d0292915d631aa0d9eb6161f924705c566ee09e74e418d88e6b67b7f57aff5170f6c42a839ba839402bfe517c287781dc97df2e0550b3862484d253152f6cff895f092358b5c4459048581309eff2f689230b4c4951db8413573b6eae85c2dc50fd6134461328e5b6439f41442b91e3a34204428d1e2c22412b012242b14f92e2d1bad626af95051bf06c74da4081b0d619e136a99c8da3a91adb3b8cf8bc5964ff655d45c75ada253aba91c64095394c701c53ddc11f388d61984c32d4326a8c627df845b4100f171bbdb252d3e28494ac173432dd5531e03040302aac8c07c9ea92a9ab67faf0c78b3ad8d454dcd428f942d8ce6e29873049fdbfa1df0e6ec224c9dd066b981a400b1f5194fee13cc5ca7ffbeca98ed0a0221377a1ae612740fce774eeed68382b32b686a25ffc016682186448207c4d9783e83da20a5e8b228a134dc3f44ecc565ab9ae162b855ecd37e6407e714045f4e83b971a5f4e304cd778f3d34137745fc6ea15b4b74d60176ef807410b1b26f68ea14f8f91
+K = 589da8a8ac79ad6b62b353422691f35e6474e9c605d877670dd95738b4935f06
+R = 7fa51231bc845fa8b668393b78a7b0408113fb77c1e36f3c78c67d65715a8b58
+S = 730c9e3483811c52cf295bad042acb5dd6ee90083857bee95b6392b080b5041d
+
+[mod = L=3072, N=256, SHA-256]
+
+P = c7b86d7044218e367453d210e76433e4e27a983db1c560bb9755a8fb7d819912c56cfe002ab1ff3f72165b943c0b28ed46039a07de507d7a29f738603decd1270380a41f971f2592661a64ba2f351d9a69e51a888a05156b7fe1563c4b77ee93a44949138438a2ab8bdcfc49b4e78d1cde766e54984760057d76cd740c94a4dd25a46aa77b18e9d707d6738497d4eac364f4792d9766a16a0e234807e96b8c64d404bbdb876e39b5799ef53fe6cb9bab62ef19fdcc2bdd905beda13b9ef7ac35f1f557cb0dc458c019e2bc19a9f5dfc1e4eca9e6d466564124304a31f038605a3e342da01be1c2b545610edd2c1397a3c8396588c6329efeb4e165af5b368a39a88e4888e39f40bb3de4eb1416672f999fead37aef1ca9643ff32cdbc0fcebe628d7e46d281a989d43dd21432151af68be3f6d56acfbdb6c97d87fcb5e6291bf8b4ee1275ae0eb4383cc753903c8d29f4adb6a547e405decdff288c5f6c7aa30dcb12f84d392493a70933317c0f5e6552601fae18f17e6e5bb6bf396d32d8ab9
+Q = 876fa09e1dc62b236ce1c3155ba48b0ccfda29f3ac5a97f7ffa1bd87b68d2a4b
+G = 110afebb12c7f862b6de03d47fdbc3326e0d4d31b12a8ca95b2dee2123bcc667d4f72c1e7209767d2721f95fbd9a4d03236d54174fbfaff2c4ff7deae4738b20d9f37bf0a1134c288b420af0b5792e47a92513c0413f346a4edbab2c45bdca13f5341c2b55b8ba54932b9217b5a859e553f14bb8c120fbb9d99909dff5ea68e14b379964fd3f3861e5ba5cc970c4a180eef54428703961021e7bd68cb637927b8cbee6805fa27285bfee4d1ef70e02c1a18a7cd78bef1dd9cdad45dde9cd690755050fc4662937ee1d6f4db12807ccc95bc435f11b71e7086048b1dab5913c6055012de82e43a4e50cf93feff5dcab814abc224c5e0025bd868c3fc592041bba04747c10af513fc36e4d91c63ee5253422cf4063398d77c52fcb011427cbfcfa67b1b2c2d1aa4a3da72645cb1c767036054e2f31f88665a54461c885fb3219d5ad8748a01158f6c7c0df5a8c908ba8c3e536822428886c7b500bbc15b49df746b9de5a78fe3b4f6991d0110c3cbff458039dc36261cf46af4bc2515368f4abb7
+
+Msg = cb06e02234263c22b80e832d6dc5a1bee5ea8af3bc2da752441c04027f176158bfe68372bd67f84d489c0d49b07d4025962976be60437be1a2d01d3be0992afa5abe0980e26a9da4ae72f827b423665195cc4eed6fe85c335b32d9c03c945a86e7fa99373f0a30c6eca938b3afb6dff67adb8bece6f8cfec4b6a12ea281e2323
+X = 3470832055dade94e14cd8777171d18e5d06f66aeff4c61471e4eba74ee56164
+Y = 456a105c713566234838bc070b8a751a0b57767cb75e99114a1a46641e11da1fa9f22914d808ad7148612c1ea55d25301781e9ae0c9ae36a69d87ba039ec7cd864c3ad094873e6e56709fd10d966853d611b1cff15d37fdee424506c184d62c7033358be78c2250943b6f6d043d63b317de56e5ad8d1fd97dd355abe96452f8e435485fb3b907b51900aa3f24418df50b4fcdafbf6137548c39373b8bc4ba3dabb4746ebd17b87fcd6a2f197c107b18ec5b465e6e4cb430d9c0ce78da5988441054a370792b730da9aba41a3169af26176f74e6f7c0c9c9b55b62bbe7ce38d4695d48157e660c2acb63f482f55418150e5fee43ace84c540c3ba7662ae80835c1a2d51890ea96ba206427c41ef8c38aa07d2a365e7e58380d8f4782e22ac2101af732ee22758337b253637838e16f50f56d313d07981880d685557f7d79a6db823c61f1bb3dbc5d50421a4843a6f29690e78aa0f0cff304231818b81fc4a243fc00f09a54c466d6a8c73d32a55e1abd5ec8b4e1afa32a79b01df85a81f3f5cfe
+K = 3d7c068a3978b2d8fe9034bcad65ad7c300c4440e4085de280e577eea72c1207
+R = 53bae6c6f336e2eb311c1e92d95fc449a929444ef81ec4279660b200d59433de
+S = 49f3a74e953e77a7941af3aefeef4ed499be209976a0edb3fa5e7cb961b0c112
+
+Msg = 0661c1bf79eed78ad4879e240a46b95a0db2b29bf81263b9b1676daa2554aad7222c9eb7a893048e46fbd2826ab6e8cf42ab0cd631c4c4a1a819560f73cc861a5b6465cf2880a730635ed7f49e28f7b565768f029db2a443ba0a1bd10773f26f752c83da40fcd33f32f78d24ac9820d0bf70dae568a12538affa867160c81e39
+X = 807675fbaaf0b6d6ba3d82063cc07327cca3f3522d396fe5d2c6599045d668c5
+Y = 54b6818054cc000c3af61b62ef4189ba35e04845dee0015be6273392c67332e2e04510cd5b2bbf4723cd8196e025511f6623f03607e566484c330751d03c713068a77e08bde907fc57b3c021e37303373d9d811e38f14b547d2bd87d981269c677dac6ade6acbbae3014ebd381b4008637031c9b6d49ca908765472b05962f55aa361f7dd5a4260705ff5ecf7b317db1fe5d33fdbf48e6a33b3c78b14e620d93806b52e86e082fe4f54d5265e8df623b0c9a259f61b7fa2c0455fadf39693ef3977440f302067c3affbc4574224d5a22044e9bfe11d0d6ede2739c7ffe9277c8644d46beecb946f81775c116388fd6c24af02ec59f621233efe8792d6d0cd2c84333b11f07657333da4e274b8cd3914d977706e786f325e18a339b805c51b45eacb3ce241845970acb9fd1a482a564b2aeecdaeb0a0db39f33ad2991f25cf622bf22f0c4430cf94df1db59aa2d7c2004b5177b9ea69ff556dd4c07edec6259ee139b421573a11cf85d11e245e251190ba869c9cb4daf9f49451a85f38b9b903e
+K = 6215e72ef2d6f6e040b7b6ef4cf566a21fcc4f37783a68db445c1ddf3042a150
+R = 519fe4c5f9b7707ae4b36217ea1707a1871d8fce98eee9e643c45cd3eb50c5d3
+S = 1df224af0b51519e11d8422999b1d3ab0972064180ffc3f1114c9f876a1de3b1
+
+Msg = 1597353f24aaf515fd7c0b0a7453444d5f329d6c3f099113bb3a13309b053e6c123a56227a81e8b1a0c8ab4b46160cc5380df591b19d8a386d29a8e43ccab5d8c0e547fba21bffcf5ef42efb9fb2e9be6297c03d57da0b5889b3b9742ddc2c54b8373fed1f2195f5bb2329a8f1f3f8afcec25eb152e7fa819e5d36cfd3625239
+X = 169b11d03cba7e817da27d889cdb147ae9cb0459359bbf85a367c64c2ab556ad
+Y = 5062aa1fdc67294cd57623cedd2808303ceb43537e3abfa1bdbc492b1aeecee61b1fd96cc055d1459ab52ddc3f2344389e5f21448a90cb36e448e60787b1ff5ab6e5549a3921496e8354646bc1fd6cd5f2359ae299c0a047fac3920512a1f411c438bafd03e95e538c6e21d1dd1f15a89d38d48f26305c2534fa8e31d054dcb00774138fb8fc61c6a8d4ae1ca46430d0e31b4b92dfb15bd6b8739fd537101e77334e6f3ce5469e82a8dbc58b3be5ca370359f4a6132fe03360b8f6be248c34220a8003772648664059f1f6a322e0c122f427efdb7d640eb5bb7f3db2d967a2159092d8f8df333ff5ba135602b9ee7e9db6ae0b95886df38d4b4a26a4b2d790c24fa214cd68d0a7ede63e7dfacaeae14d9785be693ad78d88242dfad988b7122adf5afa9efdd0c2047470c607d47b30089ff8bfc4cf5d7a8ba69a7d0ab6c54c05280d66aa4019f6362ea24a1d3f8fcd80c3eb20831b6e0db010faf826488f015f63f0b9ac6df72883efd286f0532b5beff1b9e810ff6a2b2d328af675eafc2f56
+K = 467e04dcd564f36cfe47c8fb9fa09cb142a99417a61797e047fcfd51e16e3e00
+R = 0502a6e1d8c8dfdf56eb67f9a6f6605735e4d1b0076c8b08b61daf8e7c2bf2d6
+S = 7c67abdcf4e580812b13d0a4edbae8a2786d6612bc866e3c13bc09f3e96616e0
+
+Msg = 715f296930312368a2a98d3f42810da57115f00ffc4a12029c276b10629e6bddd60bca2c535b79a5f4a006817791f7f3ad2e01a00216672ee5adec579deb07e9d2b0db222c4e01e1f819c1a52d101b1ef678cfca85655dd6b2426f1ac379a92a9c69b0f8987432d109cd9a7bc04ef287c2afb663444688601ce3c55fd90d0fa3
+X = 4ee80e4cf46b4e072e976893a2d1e34c03d20f3aa1785a74564d6b4654b11a54
+Y = b63340d6a1955731283064f6f22ad7f0e28199f6a58c57ddcb44a026c61e441318c4f8755dfd71b295e9e7babe000849c972f68d4be00954a3c29cd4b4e83ad51830080e29e7619e45d3abbf9d82fd87e97581fe909d3da1e3e96cb3f0c893af9d07f418df902e76b0bbc1c97139cbd51226ac442b3d0b0525c784ba138131421c60543e6e296069f611b9c37cf6030636eecaf41c3b4838f506c02cc84cde6b99cabd2ca578449cc1718aa418ca12a2b76f78259c1691e0b49f09dbdaf585f626cf74d73212b3427845c66f2283b60703adf1a262bb8b10ac7ac5d1ec73614fdd37ee51b71cd1fb4e6db8938382643c721fbc4cfc987bc5efbc81299b375a560cde5adae62831ca4138c399d82f1f8bc680f9c6b47eb464a1e0aac448fe3b5c25bd8c0b7afb701b0680db87ab51738f19f5b965375dd48daca07bff3885632175700c678619f194e4ee5f55aa448aeca7f7b3322f64a547315c5cee045122549fb38b8acc95da5e833022b3b894f03ccb7f73b91c1fe82ce414e1219411780e
+K = 3d7728ce25def9a31dfbe442fef8b162b30544065d9cb7bcc4914662a282bc10
+R = 4c5e990a6e24feddab48d0af4a08b45ae8092594bfb3c012fa1c325c977a3cc0
+S = 820b6cafa89b41c4ccbec842d7c408c65d4998ab1ac6b6bce8d4d569cdf04726
+
+Msg = 1fe5ad49e11c207d3d5e1923060832afbfc0aa0cb29fc0b22b3be59a598f8c703b9bf2c7347f8abde25677ea9cc60af9307d21d301fdd23c28277fce11400310033962c04ecd377fd446358a3449efd6bc05721b784ddf0e238f28608e86bd4c3d7ac631fff8be0678d37bfbac16b75bc15a50ce1397dd4ba3bffcf94d341274
+X = 0d690f2c87fe2cebc9f15546f05afaf6dc843b80abd2046f33de30c2e806358f
+Y = 53fcd07399e4d31b09abeff2f096a7b2cc5cf417dee1207d8a5aabf9e8f9fb0f66be48826a3dc11e39beba2ff47b76544bcf55485acf1e3d49e19057015e49ed012a4877be741607749b6f4bf95c44ec3c9e8b893aae8d80e369978a3580371cc13de8e714092bb892e4a956ad3654032f7758fb9454a1cb56406e1bf45855108ee960107a65d45453cb482dc19049b6c83bac111756caf65bdbe5e6b270d5875b997a1722ee9d58384941aa40e810b60b83412eafd0a7428a0abb55df45680cf22656711db6bfce8bdcbb4c083a401cdb68284e0c7ec00f7de74e57146adae221e54cc4a566b05a113ddb22cbc19d881a41cd75de8cf6c7b89a5fae650df585aa70c045b84b2cbbccd0e7ab720c5896abfd356a66f3dcbbb5386be6d02ea9b3191ca275d22248aedc360ecd4057ae06ab2c2aafb50657a91c62e038eac9f5c4d88106db4c6926fb5dd2de1ec7e4e005ce184570e7e97d76422fa037621a6f6d46cb83ab6f4d434b6a8f073900cb03a7810455d19e77d4df624d08e782090ffa
+K = 796cef38518aed8644ec5a1b3389da5ee9b063b88e7fb4602af0709999f9a938
+R = 41a2c955f41413a7ab067b4f50c61e396f9febff61c1500b1a4bc69e50a51935
+S = 79edd751a9dc2372b40580fa4d538fbe2cda4149f6b11939ddad92c574740883
+
+Msg = a326973093ce502c16473d89ba196507d92281504759cb34c6cc353d45197f915b5e736b8ff857a8b2ec99649a3224f857401898c9ea607e6a2c1d320f27564ccff5dbdacfd87a145f1a029425d76502c081ac0f6a14de5b2cad1c23a61d4e9ec6a04e1a455fd710c3c78c096753c0b7f1511e8ba5f5f1af4f0741fee88b77eb
+X = 37d0fa99e5eed0fb51c6e690f0ac556ae74cab9a84d887a07363599b198475dd
+Y = 92915db21c2c3e57fcccb7dfdce28a12aaf6dd10581193b98b7d51a728c38516e39ef5cfb1ff9fa1659c9bee56d4ebc1cd69646c3cc3f7caae0c42d9cca9219148e4998c2ddc89eb9a3edcfa6f457129007a9344013dd123aff197bfcd3db1d9e2199bcea16165a4c34ed2ac32167abd167704ead31d5fc2860b834d44f86cb530dad9e887013ca4d6e883008c286d206b6c7cb252d1328b503ae0679b502ec1646f69f2602d5e3d631d4a5a63fc7a5d06f27926a4d6b1ef2f77ddff3d850d3d9f58a958c3f4f12cf029f148386c5b8a71bae9094dec85279b1e387799d26b2a6a0e0dbf06497366e4903e559e70975dedc7d4934d4e2d3d2cd305ab826402ea8f2778e26625119e7b0c24c45dd9c05a3890dd1d9d930bd0bb409366b07a47ce572ed5bcd5f63c467d49c56811fc3e401341b9a4531f776debdea540a34c7cca3c3fb2ea99c5fa9f9fdfde918a94f74e080d1986b68fc1e3fb978054872ced97bafd96731e6d4f1c4a91278c383d4761c974100974522f7b6e8a2884d5b3bbf6
+K = 0b5c9b613708ea26bea151a0dd4222bb573d950588483483cd2b8ab537469e53
+R = 73f1922e26d9b8068b68f83c2bd5dbbb5960403b49223c02a42ce6cf3810db66
+S = 3ad30be9a60f6d4227039456c9827d5424858a02a8e6d3891772cf80a5e4ee21
+
+Msg = 7504382fb7fba1dab3c93bd31b16e73d9ae1d027dd23166b3b94c7124183faf3963c420be5205a1f44a9a9026c6ef77e7c4ef1ec4845fef6e5ea2487ce012ff53f9450fceb0d3ac62f2102d717e3287db3714717a28cd8b7fc64556a86173e6e7f479f8a8dcd895429cd7f0f5304ef6aaf275d94a7f4b30acc1071787ca5f062
+X = 1c21aa2ef3b11d31f3c94a278859cb74bc40daf5993dbd774b32ea3ca24bf162
+Y = 2055bbe89da0a0c488c3dbf29531f1f7cd3fb55a26efc540c2eddcccea1615dd923fea4c8d0c95a5af7e1e7816048f2ae85323a96411e7d1ad62c4ca675b63df9dba31c1c76803fb1c8292465ad0a7e49ba3756a8ad4c6ce86fd30b8b28e08c4b4777e079faff10ff852f7d891a984198dd04977972108c52ce8bdb115646224a79337746e3647213198f1127430f5608733d88204a62be6eaee84629fc7282acef4c4f5d3adbe72410b1edfb74be16b2d675cca891bd8cef205178902b99271b48041abe33ac119ad6b756a477a63063aae8a17ccfbe2acae3c0a3c630c13ade197cf3d05a9fa9d6899c0a3f9487e6148732dc63e907ef79488df3373b8a213705d69dcce6ed9a2209f59ebc58bbbeb08054510b5a65169d0fc1d4d10bda68aa7eceae2e72f0339a2eaaea08303064dd6588414ee7705df3ab974debef588f4e31fd6a8f25979c9f521d2343120e40794f41a4601be579183b877e6a8f6c0ab7ce8480e7fbff467a581df570af89929bc4b56397b787df4d729e65f9b98ee7e
+K = 44efaf7a15a1eb2a7ba04fd4717e938fe738666040b3d81560497ce166f31e86
+R = 56e21a7ab61f9eabbff47c75e5f68c31873a9e1f2e1db662731182f9a029b8f6
+S = 2f24c52f7baae29c0b4633a3855233180eba80611dbc7e88e23548a520b60f66
+
+Msg = 0c0f7b0f9955bb54f16e4e39ad9bfd1deb04b8e8b38e674da455696bdf7cf28e24114ad00513d8dd4e5c895d351ea913fee516b646820087721d9a0b5ecd769b3825739123544e7058b66d2342b04462d5d173cdb00ef6aca604aaa438b8868d15dd6624abb8d19384db48bdaa66471413a894d3610bc97d848a59e2c69c0c0a
+X = 34651f5844cbf85960e987190eda4ca1fcf32d8cbe1ad08dd5aa36fbd0d42000
+Y = 45ef384ed817386668e1b90b42f1d423ad9b17ea870119c0932ac2f515f546a3b6b80a612ee66dfc00cc4d9e3b5dd15303d5ebc0aa40cbcd7746f54a3ffea23aea0704ae9cf5ad6145629c61d158db6ee39ac899bbda59794b1769a92982082b77a1d48856427b78bb6e077e27335f115bb842e53251f699f04488beaf83a6c4aa6a4b76370cefc9099c0a45bcf973242df2a01ef68e66c87effd7f98f441e94a09a2830076c2895f997afd0a909b45b3c059177000236c501bfaa56da800ecf08701d212016b525f30d63ccf3afea09df39e1cfab7bf45de1a39ac7f28de0037ec552e2ea10c6b56a5db8c13fcbf73d2e50d58b4f3cf278506f1eaf0873e9ee9465cbaff4ae626f3aa109fce49e55d57fe881c50f7279262621282adcf379141c9b2c39813faf823a7ec077c6e6bf953f130aca58f36e7a87ab1aaeea5eeb4402fa9e26ef8938c8f38a6c040809f4d04c81e2948387d7be813a973a9c95176700117de2f33e61940387f851a73dfa4ac5c984ec97918c967bfedd886d1bb705
+K = 52c16c3e7b17f3e73d7965f584bfd7ca036423b0d42cc00e58d1ccbc419d33b2
+R = 77563b3b48fc9ee0dbea79fc74dd6c69b72c4270918e6a1be2c998177023b40f
+S = 099cdd62dc044a57ea25d1b5c1f6ed84d11bacbb0975976d5821c414b5416bde
+
+Msg = c67735698ae7bbaeb6f321a1088617382a5c92092151ec364582962c9c0ed9ed8fc790cde0d9744d4e38970a8482401c0f61e91805f4984b8cfdf9dc8093a5c6681dac13809bc41d167d3e11bc99698a4bc07fd248a67491e8641081ff1e97871745157cf930195a35a14d0883a26db442e4edb962aa6187b8d1c7791d61bd25
+X = 2ad20d2e78a9ec234f99a4b2ff52faf492c3e3242ae6c04ea8a37d5f10fce6db
+Y = 0d3b3c3df072b5f5129118132bb7bca3c52f51df36767f1152387ec00df65c728f0cffc1cb6f224258cb6d3e90f79dd976b5a180b83903d210f0c4dab82eb72a1f8997bf09301d0f7c89075d552c81fd9585b0b1b1291744d21bd1edcb511217c2962e1a6de9bb01c2b9698ff55ea75dcfe456be481cb6f064fed4bff874eb1c9b7451979f7de7011baf5a47c976a179aee909d25ca87fd5e3c75df778e21272937c5ba7806aefa70647221e5f7cc32ab8015921a5a95ecbb3ca4b667249d0f34dd2d8ba86dc158f9e8425176e988048efd9f7b7cc53e9fcdb29ad2412ab4ca6ebbde6f4efca5945b53b2753bfc4eabe6280235620c4464f6940acca1a94659a527aa14cc7c5467382a54fe479656dfbc11923094fe8019a08c3ce7e99a28f086bdaaf0faac6ee16190dca8e94bf87657058495ad07931c89008ca1e565076256a93cb2468aa7122758b8e174f6a80f41a90fc92f05bf1f1f47da185b2f25a1abf5e0ccc6613e3aef87193400d751b4c87b44d9bdf5c0e207f0f6a7dc2113799
+K = 654dff8f0500b52adbb70fb7bb7aec4b4820963706964c19c8320e161c3ba365
+R = 42c902c5826874774550464c4bb736f2af7fd2a347f27c65bae11820eeb752aa
+S = 6411b45947a43c5b01c2f6cefcd41cab73fcb6ea0f2a35a21475563055316e3e
+
+Msg = eb6a0359c6e46e09a42c554705bcfc5c0c022670b2f6c1a5bfe14ea805759ca2256153fdf815057ca9bd5f4cf837e14fdba3ad17612ccd19fde00764ba2e8ecd8f5a185cb26512f7457259c2f0670852741e7393b40c8bab673be2fa519b48a95dee6552365fdb7ddb632b1b33f1a5290b828da5965e82d874f79cdb928814fb
+X = 0d06d405d228c0ed860b9e21bae570a6fd940cc702dd6e9a0846e7b2a4be47a5
+Y = 6db83b06c698ed80122ec4a2183370ed7dbd6ea44dbb4542149568570c53521d3399ab44fe2babd49068e11953c5d38f7ffe3bcbe4cbceb91c155ac8741dcf226a59ede10b050b9f3743f29689266ce6ee020ca17f9fa0e75b3f7158a65cef9fac76c88786b5e377afeacb9b3dda55be922da0ef958aa556abfb43067a414e915e31af5f5370881ed97b25b4bfecbe082a145d02717af800e77e28963cc0a6a1c11b02835e14bdba1a8c9ce4bfeb06aaebd760d7c43cf56ba212d0c75da026176535f982e8d749f20c2a8d5f53875d893374d859b7cee58b0eb319d3313cb8d17602f47e120d1a24a0f8a63cfe45a5028cc0937bbe89f6b3b7cdcaa7dcd5ec5f3ed2aa9f3aa8e91a496a8bad7874dd34bd8f2a9591997d54f92d5864216c953646840b378c7a05215ecd97b6ba944ca18597b7a54832ec98c1cac0003d50d5a05312cbc852d507cc973ecb56f424e8a1c198bcdbafaa6f928fd27a7c91f84bc234f2532639a8aa2196f8fc2b7111b3d0b1153165a0e0525d4ea595f89aec33b6
+K = 521906f186797e7f5ce85112ab2457ddc030d6f34be361929f4d373dda576e08
+R = 0493db0c18a3882709b3cc9f8dbe05454506c04c3a12a41d599d201d7615b6d8
+S = 7494b4d1b2f3ae22797255a1d0662746352a3d0532290402068594cfe48c23a3
+
+Msg = 5c59b209bbc0a1e010cb108db4101b8e2d04ced91299a8742322102e0d578c3698422b43d19d331608188bed4c7edc03a442f89aae60f4e7ee9b6325de3a8bb702918c21343bc9b266f2ebcf5a620336a7bc99ae3685f19080db46f24a501228c5bbfd9c0b4b0abecbfbd676c359607ce292cffd52d26af80b22e3c4d516ba0f
+X = 4214d55b0a058c3dee2751407d9296168fed9f255e5c68273e1e5aeb3e504e67
+Y = be31fd5d62db690bcdbc09e453d4417f82e8621ad717cab94648201a74f6ffdfab965311e8ff35c4a0b5dda339b435f17317175ac642f785129e151694ea8b244627e300ceb0f3be08f91c0f527f2e0df7c9f55492d1329b7d9689634c8a4f5210157e2419e615d9431736f804b1641103371e7ffe7200e74296127d59a8f97d41af11d70c3fd02531f7b811daa7516aa2f2a9ba70dcb704f3fee47f2cbed65c1e3d06c8814e1b28abe29f3d056792efdf9ac9307ed0106c5a328721af0e202b6df737ec4d82143dd2505e103ad845863c45869e69abd9e02c7b6eaaff9e2e12bc188138688c0be3e6941c37c7ddc9b6d289f7cc8fde42bc3c14e3ee521635f32f54280d119ccedfc51090a0ad006b2427604014ea4d0e0cd1efbce09c7f8e9981f969aed6d481cafb329f995343541d36686de6cb8e4b1e7e3727abd5c1e3ffa6936ad44b926063561512c0e9ac787f8eb791f963f790ba1b21dfe1b8d31d4c16b152a6de65bf54ab0f0d1e3d450317b1cf0c4e331d18587accb6960ccd04dd
+K = 574cca3bd87ec1994449da2f2324a3945fa3047791274367bac0f12d4c064343
+R = 7fc9bab3505adcd1b1c8127e2d1fbcd0e15eaac314250dc1c684fcc47fda2993
+S = 70f2007edd68fb9dfe19a63eee4d5a977291abd235ed26e4291476ca5d0c8171
+
+Msg = c805d18c0bb53d32b57cb652f5b0e5293be492a1c88dfbec5baf47ee093e2df06918994e5cacbc3dfff229abd31fab7a95ade2fb53adaa7dff51f6c8581c69eb5b090baec38607ee9435447ad8137455b6ba179fc53ac094f97e3e29d0724cd10811f142d67d1cfcd5c3d1e9b411dac38f6e1c0c14dc9a50d84bcf00ece8a603
+X = 3cc7e58577382500cb461c0ab8ff01ece8fa766b66f8be746e347ed2ebc18ebb
+Y = 2b6e1a8d4482b41697bbbe50b55b3dcdecea8d2e2eb5cf27b892bcbcabfb253c19486fa77c98c15add4149925b5501e5a5ef45b32ad09a872462a0f41d048af4e530660a3864937ba6a9eb0734e90fda3c9b6fcd30c9078771295a93802d9e1992a4eee9af7a0413880f33bc0b62036203286844bc384187ec51a33d390eaac0cc3328098a847509129bda735909fc7a11893ad0ec61276b7a5dcd4e626d9ba67610eaf0af876afc0419fa4f009aa5f913a1c73798c2707eeb8fa77f4ee058229a0ad37e845739668d95de226760898c02d06f155f82dc16360c3abca3780bcdb79446c8343583dc0f6925434b0dae7b59cb26b10008f86570ca0350de340b275524f00551310f1d095db8480b4acc489cf5e2947eb92904ebfd0d978bbfb5d0c6a1a9db50cc6917949c71854632b4408bade5195d40dcaf61fe950eff0c8997c374f1d465c80bc65adda636433e94f22c5fbcf09e99666a535919ee6f88154934f11377a9a9e021f2d7ecaba32510e92bf5ad67fa8b3d70dd2092b1389e3193
+K = 179c02ec8f18fd88146120fcc51628f23e250ad694aa47bd691c0f442a63a92d
+R = 38208c0985624bb9d62713bc7150942cbc92b8e8a36ef6d1ec4d08d1d9a5715f
+S = 65d2ba787ed4c08beabf24343d06ed61872d6d684a3bc70307fcb7e20df931da
+
+Msg = 9e0c66a4f120e85aea064e7a8ba132cf30a45de2889f3547384e4e84f45b3572bb0423b834de9f2c9636faffdb6331924f0d2f5b6876145d9cae110ab0cf6fc90c2eeff98c61fa186cc3952b57299a73678f4585bb18fbb84ef4166779ff10eed14d47ae528e03298dbb97cf4f88b7e6d0959b5894550a3e2e356947d25ffe73
+X = 5c5791dd648703f29099736146f5b1b5e35dc71a74d6eed312d37aeb6d389ef0
+Y = a62adbdaa5a55a2d1e439b5489cd6c8fcb23e9c64fbfae7c83e9d5599319bf3f06c3c290b989a638940b1d0b7e8bf6741319ab4c38d46e77ebd4945e25cb89cbb64e44b9474bc7c9d9f61a36e57eb6afab6c7a149afe02c1cd685483208c55feecb0d0bd96697b437991059267d76a488465faab4a7e17592329567005faa421e011d67f4da75accb627537e933e9ef0be3c70f21ed3f8c3b3d7d769bb611f82f2baa10fbc7313ad0819048d353d679736c4d14bca9985ecd37041afffb291a7d909c7458181d01592e6c90c0e34b49461ede66c5ac002671a4985546a6075df95b523f166d2e0d1f5da77baff5a24df775cc9d367f2a0728c4802d797041788c56cb871290332c1361f8da8897b5b8e25d4a93594ac648bc53c9d85b4fcdd7ab0f5a3ee9c25cc14ba6543b078859524ec7f0b61cdb209cc51c40aa9af082ea9c1d4b91b2c1f6dc11cd879fb3865d879fe000f0e0b4b233dbd01c9c98d01a664746577a64bf28d88256b76de2babf14961113733b1bb555325c09d8ec9189fca
+K = 8327daa2fbd001858dea53d2dc0cb005e0ae5fb15bebc0c5efd33371637ef318
+R = 4e35f586fad4f512863c485ec61ed01629aa1399b16fef4d80cb332752b1da92
+S = 262dfe6ac72a2f6044f62698e42dd2f92b1f9a91be42b5fdd293b1bf9a145f00
+
+Msg = ed88d7076c5f6a5e0f947543d5fe746afca9b2c4d06655da4607685c799c210be4aaee0e6ed19713814182c7f7d584ddbed488c8e3239ddd810555ad6316d1db37fd9553ad74e3ceef9eeefaf54563602f5547aad4161e9384edab655a898416db53f71237ac5a1485711182bc5bfff72460252784ab1bba23634a36be77533f
+X = 22b44bd6d23ee65ebc2e88030f837ef65593eeef0966239a92d5126cde867a13
+Y = 3e1ce8780f39444c2130dbf9d80ca4b25817dc16d08e2cdaca0b56cd2abdb9ef5adb741ccc1abecf62806ad7e87636f52831c6dea48e0729b904e5a0615d7ab4450104208a5ddfdb2f2569146ee83ac9aa27b4d066355fc53dc1a3683211ad3efad1ae69b8a7737bbd89f5ff48482e2c56edaa776e43b2a0ba62e513862da290288f07f84ca5a06837d19e9b186dc8d36952966e08f7213340186d31fd41a2d1455a083aee62127a28dfe4da6c876a5a6f36c45245dee6f6566b8318d3d01943b2adf8ce94ea01a01ba41a6e286820a96707cbd4002875b79d9fe2db6cc3f808ef0f71380ea9a73fc7e36850d022ffac131636367886a6e9965759d73f03ace69704b52144f67b678e2fa201c19bb37b00377daabc9377adcbddea2816cbb50b26ad2e429ea0576e7721b3b75c4fedb31fdf1f0c6c2eaa135f52c9a97f0df5fb25ef28848bdd7390cd054003722582d94e90a3bbe85beb34701271b4bb48bdf9b3d0e1bb5623445c7828c937a423be512c1177c9c0b5b0b6b0e1f639d330e051
+K = 0c37eecd48682f897accf43b3e4a538cccdfd784625a6cc046dc54b093d16162
+R = 2e7cb404a6daaa8e00760dafc95b4eb5545683224a61a1bcd6128bc4e7ac535e
+S = 3a70b3a97e06e63b89d56ed5232346461c1a3b6b145d89043a48d666de0256d5
+
+Msg = 9e440052ed927321948388776d3719be068739dc2d6c64c5937176b2005c2d70a9389e6a655663366c0970a8e2e3117ecef257e951ac81c0731dfcd4fbdb1241bc249adde9cb398c7d15e381368ad3d24edee23397c15a5a356e787d8f2fe9be76260bd363e17006281c199fe5b710f9dfcac52895e392f7384d71bb83053ffc
+X = 680883caf23665e813572c1e4230218edf53b3a5167f56a7d80e53e7d3ad1df9
+Y = 89e859fc63a263bcc051bc2ef58cc919ee537385cb3636d83a624a4230d4b0024ec5e28bcb884667cd2bf8c28451b64de097f2194cbb8c6e1cecbd6f9fbd576481555d0f0e8f13752f2472f7619d052318424310f69d50de78ad6c457b98c611f8481d4543031a73f83d1e852c1f2038a6435e571f776bbb5cf978a9b2c88f05d134fd5ff4656a69d6fe6b667da6da54be48386250394c75b495689fd4628f666424eb080094448d41b706292e51e75386543e5fcce6a6f3aac03a7d6d5c2551ca6b5b85fadc86bff14c79a1602fb0c1d43d88d5679021e826062ecf186aaaaefc312eab9f9e2da120a8d7d08ba09aa9abf4e34f6d88c4c314c59c36ba57f928d88d5d70fe48ac6700f5cf607a55e3646dd03d47e96ad869f7ba2bcc7d65a99c3221d4909d1f22e4ccba815fa5b720570e42f8626c31d99f60cd6a015391fab3537446f747c0111293c5bd6b5dab2bc3d5137d2124029eed12db71bdf794de1a2ec5070d83f87195264ff09cb48cddb5e852b233570f1b70cd457cf864e2ef3b
+K = 69e6cb5bcf8cae88c96e464a9b26c6e1bbac1e229909e27542278a50c66959f1
+R = 37c34f9cce916df3deff26be08a4e6bbae0661fbbb5d81d6039f00b1e5632b67
+S = 3f4a2932917e6bb088599a269d7b590769acf9807dc5a9420a95e12c7364c5fa
+
+[mod = L=3072, N=256, SHA-384]
+
+P = a410d23ed9ad9964d3e401cb9317a25213f75712acbc5c12191abf3f1c0e723e2333b49eb1f95b0f9748d952f04a5ae358859d384403ce364aa3f58dd9769909b45048548c55872a6afbb3b15c54882f96c20df1b2df164f0bac849ca17ad2df63abd75c881922e79a5009f00b7d631622e90e7fa4e980618575e1d6bd1a72d5b6a50f4f6a68b793937c4af95fc11541759a1736577d9448b87792dff07232415512e933755e12250d466e9cc8df150727d747e51fea7964158326b1365d580cb190f4518291598221fdf36c6305c8b8a8ed05663dd7b006e945f592abbecae460f77c71b6ec649d3fd5394202ed7bbbd040f7b8fd57cb06a99be254fa25d71a3760734046c2a0db383e02397913ae67ce65870d9f6c6f67a9d00497be1d763b21937cf9cbf9a24ef97bbcaa07916f8894e5b7fb03258821ac46140965b23c5409ca49026efb2bf95bce025c4183a5f659bf6aaeef56d7933bb29697d7d541348c871fa01f869678b2e34506f6dc0a4c132b689a0ed27dc3c8d53702aa584877
+Q = abc67417725cf28fc7640d5de43825f416ebfa80e191c42ee886303338f56045
+G = 867d5fb72f5936d1a14ed3b60499662f3124686ef108c5b3da6663a0e86197ec2cc4c9460193a74ff16028ac9441b0c7d27c2272d483ac7cd794d598416c4ff9099a61679d417d478ce5dd974bf349a14575afe74a88b12dd5f6d1cbd3f91ddd597ed68e79eba402613130c224b94ac28714a1f1c552475a5d29cfcdd8e08a6b1d65661e28ef313514d1408f5abd3e06ebe3a7d814d1ede316bf495273ca1d574f42b482eea30db53466f454b51a175a0b89b3c05dda006e719a2e6371669080d768cc038cdfb8098e9aad9b8d83d4b759f43ac9d22b353ed88a33723550150de0361b7a376f37b45d437f71cb711f2847de671ad1059516a1d45755224a15d37b4aeada3f58c69a136daef0636fe38e3752064afe598433e80089fda24b144a462734bef8f77638845b00e59ce7fa4f1daf487a2cada11eaba72bb23e1df6b66a183edd226c440272dd9b06bec0e57f1a0822d2e00212064b6dba64562085f5a75929afa5fe509e0b78e630aaf12f91e4980c9b0d6f7e059a2ea3e23479d930
+
+Msg = ed9a64d3109ef8a9292956b946873ca4bd887ce624b81be81b82c69c67aaddf5655f70fe4768114db2834c71787f858e5165da1a7fa961d855ad7e5bc4b7be31b97dbe770798ef7966152b14b86ae35625a28aee5663b9ef3067cbdfbabd87197e5c842d3092eb88dca57c6c8ad4c00a19ddf2e1967b59bd06ccaef933bc28e7
+X = 6d4c934391b7f6fb6e19e3141f8c0018ef5726118a11064358c7d35b37737377
+Y = 1f0a5c75e7985d6e70e4fbfda51a10b925f6accb600d7c6510db90ec367b93bb069bd286e8f979b22ef0702f717a8755c18309c87dae3fe82cc3dc8f4b7aa3d5f3876f4d4b3eb68bfe910c43076d6cd0d39fc88dde78f09480db55234e6c8ca59fe2700efec04feee6b4e8ee2413721858be7190dbe905f456edcab55b2dc2916dc1e8731988d9ef8b619abcf8955aa960ef02b3f02a8dc649369222af50f1338ed28d667f3f10cae2a3c28a3c1d08df639c81ada13c8fd198c6dae3d62a3fe9f04c985c65f610c06cb8faea68edb80de6cf07a8e89c00218185a952b23572e34df07ce5b4261e5de427eb503ee1baf5992db6d438b47434c40c22657bc163e7953fa33eff39dc2734607039aadd6ac27e4367131041f845ffa1a13f556bfba2307a5c78f2ccf11298c762e08871968e48dc3d1569d09965cd09da43cf0309a16af1e20fee7da3dc21b364c4615cd5123fa5f9b23cfc4ffd9cfdcea670623840b062d4648d2eba786ad3f7ae337a4284324ace236f9f7174fbf442b99043002f
+K = 40b5cc685c3d1f59072228af9551683b5b8c8ff65240114ad2dacfccf3928057
+R = 7695698a14755db4206e850b4f5f19c540b07d07e08aac591e20081646e6eedc
+S = 3dae01154ecff7b19007a953f185f0663ef7f2537f0b15e04fb343c961f36de2
+
+Msg = 4bfd28a0a79c94dbd667c275ef77a235d8ead7c698d42fb7f7c1fd3c8c2dc48d0dda2408dea56325d69283692a523d281ffea856ffd9f8417eafbea606d862dc5897bdf241f3e8e49aded5eadc7295e5afbf96b3975d0e25daa2433612e120f659036b807c1853c03c90fade2c19dcd923492ecc906cafc57a95da6f20dd59d6
+X = 95fded7e5e949602c1123d80f89503cc5fb7454be3173af495a18709c1c2506e
+Y = 6c778bcb146582277633931bfd029e69c9e8c0ae9e24913fa734554f24f64aa64fd9bc608ef677a1d4829aa8a8564c2ff0ffa2fa6a0c1a2ccb606dda018bf095f8c897d7a43349beb9807b7b118f8de8856b164b8d8babdc17b48f3a2b972ce537ab4e7a7d9ba5d7e6fa3698aca91973cd1787ef7b6b4d0410de59cd3143e0f3acfdaabe56b371b4354d0d32dbd1b5ca6a872054f3e6566319d5d50b2cf54c123ffc929007ad1857ba13b7c403f551c2fa4109c44e19ef97afb62a6103356fcc2ef451e736261010b0ef58ae07a0c801ff75ebaf6cdd763f8df2f83f0ebbda40845b2f42d3feeac071fc626ee5b51f9bc1a130514f2204971b4b7261b4bd783ff75775aa73a63d7ebe990b939b0f44a909ec390036f297c3563f64d142c14ea43c5d3c6def4a3a9ccf6274182b939b886501aeb4efb23d0073434cec6a915a67e24cbb2354c9bb1089af487eab5d8e499a632e6c61492ea15d2c444c269de33271a90042468de2767f0dcf7a66424a3a40a63eebd19cb89c8d74c58504c4e103
+K = 6bd1eede564ecb1b3fbbf2d96e334ab4cc002e6624e2cb8448d8608fe0e8c43b
+R = 37c3f7556d6e5acf7989f0baa770c2450deebd4d5f58b61e17b4b2b926b58031
+S = a61d86365f10ca5e1ee2c4bf276f2374e88b5a2d1acd8ecc11e97785b4fd9931
+
+Msg = e3fc751b6978fcf40f09606ee4263e1660ff20e9c63a7138f078ae3e3e603dfcad172f3c7cb3f3545fc23bc30c37c8439c7b238341f29148276ea2122ea8ed0feacb149de17cfd33b8c9408aee8ab0ea8ba4a2b2ea237418bc3165369c8cd420242f8d32bcabe0c352e21f65de80d587ba2713cea6e53ca524aec365bdf21adc
+X = 3a09006faedec91446995a393b034b0c7ff3fcd05cda2e9e3b2f98e3a4bbb9f5
+Y = 1349bbf16d375c392a9acd5bdce655f14d616274388a45cd372925c507ac129fe61b998e25127f210926ad1191583eee8c4190026ba0a95894be3f0ad5d05886c59a3c7a0044f7e2bd9bbe28bf9366d034db424f34960e30a8e7888f927d0bf984b0ff99ea271871124aa12e0c0e19624e533cb4149cedb3e11d321600dc07b32e531a615c8f7fd7f33a071caaa76433d1aab0b710fa7ba3ddb0175ced4e558d5117afc7542b9b07a8fe8e4b08a1de456443553fe87a4c2455ded72f98544d6c41d6ef66b7142a4aa9aa1d3d20f700010389e417840782fad682153d569f944d3d3ad1d88db5bfba3499e4c3660b76b44da4b0e6727ebc3f22b2a0aaf62dc2a29db8babcacc2169c2b8674054c89fd770db98b12af2d933becbeca9f22444b527aa894b3765292dcffaf3408e699495df79b98d957fdba7e4c8e7ace3f987a95dcb2e777fa2d1304479a6d137efcb0c404e6d8ed39d6afba2549f3ee2b9a45f324567c0227319dc59bcadfcfdf1566f356f7c2ba6db21cca2a8fb2fbeaf31cb7
+K = 4212971feb32e25fbb22845ab8c9333cb2a265f003542838a128a25108a88365
+R = 2d3f3c605eca8fec37a76d606d20fde89cb6f971a44796095a01dcf8e900f5b2
+S = 6a43168334e5b0ea07cfa5978609e86f969d1005528ebb3ee9073d5655d54b44
+
+Msg = 45f656a1ef0e61de46df2ca2d8ea26640a994c30380c0cfd66be3998d89849161bbcf3bee77ad30e769f10e23aad5b4df4edc19a86fbb5abdeec8779b76be279532d7692bc586c62692fa1e3dbcce33ffddc9f97589172f64a48535693ded6bc73b2ca32469d0eaf6706d2a5f58f8d28a745dc328bcc75b3415ca93e29eabb1e
+X = 9f35b1038686bde07a5f517d68f562739cb7150fa47ebaf7ffd29306afd4688a
+Y = 31a989601f32b205943a841887df3c6814cfb2258e5204d04d3928ddfaba0dffad43151e27d666d2928bedc67275440fb502ed3eafc3adc11009ee703f01eaa034aa724fcc63c59a8a5963f3352f7293ea2425ea89bbf1e41724b69f383bf10a973146ed02f55208b04833d1bb5399a67f04081590acfcfbb12105423e26091d09078c45007d436eb19f952f8798b001a3c64a3baa5496c9dbe6580781d4020bb7e4e7ae2380ce79658c10a2e57bbb8cac12087728ce43ba2b9f380e3abc2dd12a682488c6b4fb2f8dd7f3846b6a26f913ac156879ee6a1ae0ada9568521a4428ed9f741e0e79a842880019c01b34e988a7cf7e63524e8cd025453223a2660273e491968af7f4b1dc2123961de3753ab16eca5b1859a4f71172538f05a2a82a34f98ba07c1e531d82ef592e5493533416bd6c6a4c7ca3b0d2a2fff88a8f073a76c691802aaaece4e852d6650871a17cca0f5251ef22dfc8e3b261bfcbd5a22b2732aa17d7df1f7b82f6b222e5f6065bf80d04c2e5774094084e4d5ce0d3e8917
+K = 55d1ffc73b52b6364d660fa4658a6351142ac538fd3cfb4eec40ba07bef5418b
+R = 3ced0ea5f7fd588668a41efe0e90954c0930afb6be18d90752831f683cd92a9c
+S = 9e46ca12941745ea1a12c5a2d609884cb5792f46afaacff07237137400366868
+
+Msg = c737d5ae248a96062d6afa8dcacc0384c5fbfb9d8b6052b52493c60d3edfc524b567b1f896e7447d0e24019403ed83e4889c0c4de57c70fada6c8b5a09904350a44dfaf77d60af62de3edfd8760d077473f26df2837cfc2015f227dd7d351a5350f1428f2699fd3f518326fea8aef98fc4ea673130c8079fac3895fe856c77f8
+X = 40dbd496fc4644be7ccb24d9dc55895c1b923a05f4da5610589d564ee8aac33f
+Y = 6112d3cd3191d17dee7788f568815a0aab50006002c9de2bd1a9bba245ba02894b02e9247517ace698ae0a05176b62b3a025a563dda8deb7f2fc3e177ae3477448d39ae4ebe7ae8ec65a4421f754667fd6d7c2eb93f1a18d3d1a6235736bcdb74746f46d88e65dc07c2591e1f95dda5e5e20e105ee8b4ddcaaf36021290d6b6493671d8aafae145d9b90bec3cc60179bb8fc30f143c575d5d861623721b6547d3aaaade455f05fef9318abcd29bd19b12c35ca756de5108c185ece4aa1bf1a8e38809797067bd1f52b6cf2c415e73f9246bd5bfadd7b9a9d2b5369701e72147e22da7e092d9b578fb0c044a36effcbd709258500a00cff230962c44225712fc43f9e802baead7f9cb46ab4931f663c6e3ed4082d59610f01741b5f24566b01b3e3933b29e028c54bd2fc75b549fd05e64c58c9ae0ba417a9e98581db77be75233a42f771c99f0a49b494f0955202b19d6c740e866066104e463e65e4bad9a081636d05367426153f04bcb2712186dca6834388e82520d34efd8a89313b2c7e60
+K = aa63e91cb3fa545c447a8b8309a569d48104e14d5d05b8951033ac8a7d711c3f
+R = 0041b1c756dd2e42714f9ee7edce21ea33ef49dbf452ccd9357d5f45ffab08f9
+S = 102c6eaad38d39c0d036335ae19dd0d75e8dcabae59b120f69cbd2b5cf48abdb
+
+Msg = a6fc89a223022ee9e508725278582f56db9cd24c0d75d072a528d0c60f27171ea376e2dc28a9dc0b12e668af77dcbb381737e1ba7d9e80b9bec80bf9061b8fa10e43a7403a291624a600dd4f5c2b50c52d5c6155d52be5a325f6ad813fb3ecaf6d1f92e98cc87c26c68cbd15d548a3782bffdd1116c7c11fcabde4025fec5154
+X = 1b41c29364947768876ad4e7abcae59c8e61373d25274ba42ceb3d876d6ce672
+Y = 6c1d4d6b52aa4bff35f4302330052777f51f6a0849161f906ef217b04b18545ce52ae4ae423ad1b4f8b1735ae00ab0c044a56f945da84d1cdc26e082d7acd772dfabcd18b5e13c05c2791a8dc16146e151323e4ef2ce5d64389f69d9347aa2a5bd0114de0eecdf990a440d1bf9890dd95fd640d2fb1789ca6a6dbee1836ad7cb47370b7456e49f3bac03310f8cbe61dd1cc06d78c76fec6397e608a4cac4e2c38983ce5aa9dcba074a206fa608db35f2ad3d63d95b2cb7a01c33d498767e8e68578e4e99538bf3d703e63863a25091452e73b96a3716e9cc109b66008fa5cafdbf96b7fc10c3bb89d79d45ffefc01908d247ef1d4fcb903bf5e7917af88618a52a12004798890540a5a75c65fbc057d860f4b65d8b08b8d215f056d8e5e38bf0b319e294db242a4fc79b2e106feca2556d146f5203fd72adc73a48e3a5aadbb293a2ef5862654c31539ad856a16e5716c437b474f3339cd84f0ac92bc2ca6fac10c751d099a90408def6106ca83893d87e32818d7634537a4ef667ce7f26a5cb
+K = 4c9ace2c908648032151f638e3c909d1f0646fe018a1c9c22a170eff64447fbe
+R = 48bd010c1af77b3c40db50349706d64d16cbb72db51943d345151deacd4a4133
+S = 0f1c4bdb4758ab3b5518d4605b9864805723d33a36116ea650546feef11c4a5e
+
+Msg = 2ae4ac7ce29ae7d32490d3a54b715db3f47306f84b59b33b21622a18aa2c060a4434adfa01ff1686b5d1dd3035308e92f7acc76dea969deefb98c2972b42a596e1055a5aa2c661f0b734ba4f0b341c77827d88915a5e89f95a98d63d7729874fce4ff75d7add74f4313dff784e417b2ee1fcd270c038dbbbb96a7768484b8854
+X = 87980da0684558f87e5864ae585864625aed61b1309c1d5f30f6477f947c44fb
+Y = 0a84298f4768e9d7bf796d06585e8b75fbde658398a224a8ac3a49fb91235eaaa183aa8827cc2af79ea334dc8be4cc729029ab5f8161f718f7bfbe90ad2a159888523982b6d4932d8159495ba84d0ab35d7e395d14dba906a1679ae3cbb72c10ed6fa14da4d60077b0bfb591a3dec643996c396338a51d446bde6224aea16aef41f354e09a9dce9f3a00cb445a5c9cae4a6c3c1919c9e0c53082173d0ec00ae5e15aa7260750b6a03ef05a518a48615340ac20984073cea5fc990d489858949aaf6e9e347b4802afbe25a0669472bd9316ba2c23a61cc3aadf1b70d9fd9761bb035f0ca51edb2b12fcfd651cb92363ef48005a2683fd2ed8665d70588fd9a1be3aa51c958b81f13e4acfaf0d2a90aaaef21b2cc9ef2ed37bce3c47c8bcbfc1fb9f94e49bd2f1a30a88df22735a0fdf0ac6028a008b062c9560c42a476997dd21100692ef6396d5f3fb2c155328257e7b7d2bc05fabd54a81a2272993d342bec8577c64d51b4cdbe3654dae568c4da018618c3047aee06bf2621e056b335d044b
+K = 25b9d8fbe7e3ab7017f2b1e53da579df460dfb72ba5fe4ae4c85b8c23472bc8c
+R = 6b7ed3a4c2a4f78500c7e947e6175c5ca857c9d613e7790b9be0d14ec8403e5f
+S = a116f3de166260d110e20e84eb8c97c3f018178608a2ea3e3e2f5ed91d43de11
+
+Msg = 3eade9a10fb59af36a540170737fbc536e4c5230b8f6c4b216eddd3ea92342123a3374d0c751b24b627f9ead4de26e9a7897d9bc5d58a6a3ac74cd4575b3286ec15f8453224f37179e51d9c4ad8a60bf37d71c62ad7fc53e5c7b12f4aaa2d428e5c889fd7f062c913d9b574f4b5db516c976bad588302f219fd83e18bee8e68e
+X = 6cf453178db0dd7f2f94f9a1f518c622c1ddee46d4b090462812e9f7b862265b
+Y = 08a15b2384dff4f3033c87168673c567059870c8e78d2fddc7540afda8058df384d3182a42615432ff93777d3fce49c117c7bbe821e6789b5137ddf084656098aa7b0516fd30a42c8c86d94e6b268b6e13011d25eba018ca40cf8a35e1963135d5cd65a57aca8b007988a5ea75adb4d01cc0f0838ab42d3df643a7d2561cfd1fdebe3ad86ad03de317027533d523351be532bc731aaf43b8642a7da80873b80dc61b7a249e5860fd1a3eae0f8f0cf21e205d6f403cb0a103290c9e69d38cbed9e092b69f71f9172b3676f29a97133fc3e18746fedc653fbfb62c5e0afe89a8e1b8724b1a3314c4cacc4bb8f390439701a614ae9bcdafd472b0ab131667dbbf1c790f73ab9046a58932691a930b3c42e908b4d1f47ed6e2ff18d6b70bb16d1af7993bdb2ca3cb359a0b43f8dc844dea6aebaa34b8d2b6fc288419780ff980908926c46c3b0e595fa308f4e894ecb683c804c93140d91769132d37e93791b9f89d595e698f049b3a9502abc488bdd9472f1131a757f3d54b149067507d1b04a976
+K = a3fb61e544d59206d334049e8554d97b6699db616871fd2b421229c28e84f73c
+R = 9e833ec3ded9d81ea7422bdac78422274fa35348e3fce3bbc93b3c10d70b4f1e
+S = 653756594eac681d48a2358a0f82a10faa7929b00fd9cd4394c32679060f96e3
+
+Msg = 33decfc1e06b92ed81cd30ee3771470b59e22c1564647f1aae8510729715a8ce94624a11554ac909c924aec853df64327546db85d3df597916a39353388a8b3363765281a4352701ff1af43fba6d03664127c15da7b84c04d5409c364094dc62e37983a8eb066880de8136701406e67250679300d2b97d228327c1514c0bc1ea
+X = 3bf2be01d154c23ccae92ae93f78ea36f70efcf7fb7eb43cdcaeb9ffb8471b10
+Y = 16ea2e795c636c9d312159a579b8df329ffc28fecc4a4c13b16a290bd1525a53a97d72315be251d11d23ca78bbec45c0e243279b1eb6e206a9273c1e766e213648bdf90c40479df48acfd9c209a523c8b4a99a481ca8df4774b3bb29f82526520c2dc28ab314fe14140f2be1792e1ac3c759ad44f7845a2012f64ecab0b1fec0ed166bd175955704f62d9401111ffc04f804e48fe774dfd346bb41f4beca2b34a83134a3884a01729cce1abc5b8d0de3fe2654c374deb246d96ffaffc7aa2055b74e819bbeec137eb3caed1fc71f129c8ea8b763f2f57e88de0845f76ceb1841559019872a5b5a969c9cf385d6578b4f27b5b76be3ef0a8fd3ee47eed695e16f14e2a3b791f2a016d6b86ff8ec2343c6a5c80ab6224b6502eb374c8fa6510bce990d70efdfa9a0b702585595184514c78f7e905b6fd6c237333d560fcc06303637ac0b2c7f7c4da559e31f531df2e5d6c651591771d7ea4575888afc4011fa1124fbd1a282a41d933989eff91a51cd39bce7fb0d569fedcc42de48bf18ee755f
+K = a0c97f80ca449fd8f69733e046664408da590dbbab6865c3275c389a478aa248
+R = 6f77a52169a2e880a3b55aa278f6463032dc5f81c38468224d5532f6a601f2d9
+S = 96b753efb4abbc8c179d03cc2a1a0c1256e23d1fa2e97cfbf55d2bb69812d100
+
+Msg = 6ae5a6da794f923f6d8032549b81d04ae7aa35c2099dffbdd83bb94db574faf8f95c7126db2db60fed50f740e87c359544dc2ebfbcafb094ddca69c914d27e5f3d10fa0ce32d2a1355bcf61a2574c755d7c324a2e0ed6f7719ba2f2c9f113df8d04025f4abd2e1c4b7bc18d8acec9f6d8d797cd7b042f50348eeb3f7a2922da7
+X = 3b4a52c8b5c386f26ac6ffabcef2df3bf8b25e6108ab540d314dd3d9245c075d
+Y = 93106fb000c67f1111c6fd3da0f44b4ae4cb3695de2e35b241dfe88d3269b8fda25bf348008725fd613cd61aa826bd8f1aaaee22b4dc0a02842290bb7dad91af0b2854ffab16932208d272f2c081c13889db3ed0b24646c665af9f4b723898eb1ac0053f2a0f4cf22fd4e12940b5b52269484ebb8abc484c06eddbd9b1a426132f402efdcd88ab29e7e510961af8ec83a642e34015858ac3f32197601a888e16c759c94ec5b8dec0da30643b9d9db2574af29e78f9d3f6a7b4c76f45cd0b2ab5e8524935b886918b5d9e9ccb5a6853e62efad2dff83a8520985ee8442f2bdd1c5f9d48062ade6b288c8ad82a41db6c34e2deba541aaac3cd3156c975efbbc718ebd4961996b3ed1cc5c2987ab779052cdbecf51d17661b498e84371ff859f89906f426f563572f66c279ef3d036a427778463f67f8d4de623fb4b2803007871d0a349ec202a9aa1cffef70137e009303497214ada786357a4d8046255e40f89ea588000634e7f0aaf64d92aa21fff8fbe078baa96961699738b268237eab606c
+K = 39f68875cade6ae208d3043b010541624679df649cc5d97b09a3ebbe2c9d59be
+R = 8636d4d3203aa0912fbfc938be4370077ea9c75195cd2f67e6ee427cde531c40
+S = 93023d97efb4327e9e886e7b783741e9d2c397af9c67b91cdb8aa27f83bb025d
+
+Msg = 86e03bc3f4ddea6a93888ee389b15eb690822c71f9b85efaaffc52e486b1144ad7fcff3f53bf97da2481e85e0983ee1d5279e27a364d0e690f587a31535fb94eece747f8b605724adfb258c9983c9002e0c11b7976627690d58281305ea9308db74c491a28192e354b600e8376811ccefb751bb10c7d97b42ffe304bee97ecaf
+X = 7f56c74b495a12db963e03cfafe60ac95e8019cb212c332d1f19c64615568119
+Y = 23ed5445391a5bb94e00c76ec80d83728d5d461be425da79f921bca27d625cb42b323971022ad4c3f05bca109910fd06ba39e95bebe794ed108d2ead297ad794f99c32c219e65fb726532715b1bc2075dd4b6949297712f91d5ba061196fb25754c34377bbbe6a37f61787ea844d359285c78e733eb65f665a6b157f832b5638d74ebe1d5dce66d528925e44eef13bf23f807da35f34d169a687758229b99a313acecfb20b142b534926d59aaa7643a79030e9335ef28abeddac8ac9471da4997e33f3e491db8668a2c3920a3b3a37225179361d5539beb33f3252244267465e48faf575cdac938133effe9d1f69f19f1b44b245a447b1fc2b859244e2e39053595cf7978933c3d468c65c231663070aeaf2ec23138d1660081a55bdc3dd3f2446176b1d6d9977a14ebd0ed4d8dfcdfc4a433118401f2c2632095ce7ae6200c74bda5d2fd3854524c3081741975a076a1b4f933ec32a2bac9171bebfdf3b355eddb1f455ecaf73396e85fb04797558ba4f2bbc49d9f2329a23b393301ae0db92
+K = 407180cc311aebdc1cdcb4685241597783f34076672362a24a21193c0d45d24d
+R = 68efaa05eb90c48c6a7a45337c29175f8ee5b19b53db4ebd83a02f53c5b2104b
+S = 145f13f1ae3675c521b334ce6a49fc6f502e3ac6b2b5143be0641d0d57b3c722
+
+Msg = 1d0954ee0de1e9ceee0532597ee434c73fe4f66635f7e72d38b67763c66817f53cf36ca0f613e01896cebc9f77a772607f4aeedd3856c73fc2f19100aa7b540ccd057f26cd9564d673228c68088e5f1abf1254a97ed1453ee558e062711ceb7643b345ad33b649affbe8a62067f9d84ed4c8506fcff578d2eba596a205267387
+X = 0b48499625f0c2548bf8a2fed1f6696f59df8fbe6eaf91b82385994209c2d04f
+Y = 2f0d89ac78a61fb74f81142b17766656d1788940077808e3d880ce10ec60e2bbb158d54e020dbc5f6786c0b43cca2cb002c8ce13b291b250f399e8e02f195926978f6c5b007d4f0a66048996a9932a918b2363c4008f547adcaa7d12694baee4fbca34bc6d7e29c5049cda13698fcce61bd3b3db05d2158132dd380cf653cccdf279aa164134bfbddd7ea347760041f92c3a4cfde0092d5cb96bb8c24e98259475596f3377d59f11661bcc0d47e83cb31aae9dcb4a6f25619a29054b62aa8b421e529e61ac95a0de01c50b09e119516c2c5b3563d47eed679a1cf80ba70a50254d851a13a778e1a08da8667e46e35979c15df45cf7886dde5af9d744624b981acd252ec5ba46870b8ee4b32b1be1b944802d91d8148d38f54315a7ad4e38079ea2bed9df8fa59414ddded3a1d2308ba769ae2a652f10c2d96917edfe5874885f3c99d6912f69ae3fc3b4de82decc30edc9314f7ec9e567b7e00de21959486a887d74a5b2180293df5dbeae1e35a6e937b2506d205092cc4c3595db92fc255af5
+K = 1c020abb0e1d52b3ad95467f7baaf665e2281f34c342401ef1fb4c1fc2d7b2bd
+R = a67210341a04cd3a4b63ebc7e6208f37e487a8c6f1134cd2601b844d6903203f
+S = 6b972c622cab48d85a2dde355f947a8151a17a0acf06b7f3659f868d5ece92d9
+
+Msg = 14f566c5fe44aaad6e8b3c627570aabdd4efb7fcfa1ab1bb74f2c6d8795e88233dac4e7d240abd5e9bbd8e1fb03a3bf50c0ca92c9aef1894f2aed600fc5873d23451d3204d75ab9581cbcf82ae8c0df0dfbd3a1f149f70660865726cdc73c015d5ddbf7513eedcd1ef17578d2719fea1e5ba39aef3fa6f00846f0fb8d9a1a436
+X = 7928d3edc11a890fe332c0d3759bc6ecb822438d7f604da76b4fd78590720ddb
+Y = a36a333900035d3453139b28356bf0124e571f55a5e4259b8b2ee1457cc3588056d6c6a645d422cac72474c5901d0a7f410df7f9b4e22f8684867d9332e2d4266a6e595e515becff7fb94d21a8a9ad7211572e44ce8448317b34c3c0b89b3097ab2ec134ec7c178c2278309cf9152b223bb937e68682f1f680c17ee59ecd0698a05c24c135d2b0238e71f807e079f175e11671308f5bd9e5a69712a9c508b3b50925d1276d552bda51cef3bd0fbd00a9d2dddf0e5ecb6b328378ea637b493846480ed75a3152d9e6a4884eebad12b07cad8d101b3d001bc99fb1eee4e98fd6fc920cb5765ec24e62abd32f975a47d50f61553e1c14775193b53b05b7d02024aace818ab659d717d11deacc9877b818a51689d239b60f7f9ed4caf7325ac0b31b316c036599ea66959d525fd16f5c1a2a809f2866ee9e99f6d8a3c42b58d33d0e5d38055c55c7bccdef310ccd3426207dbbc60faf9f2a219ab367ce84623b81104822e2c77ec5b133ce7050caed090946c1f1355d878a1317de694e686c62ffdf
+K = 01f77e5f125a9a1385349f77d7a32f26b1efa5b0a5d4a212753bb54d300d088e
+R = 12b40bd1c866ce38e7da0764d807ae82512b33b51dc908e5a5b3d7c16f0d08a5
+S = 5caccee2bc85e28d506a9bc6d260dbd08205b75d20690e26aa6bed30d7327099
+
+Msg = 60c29d99753d0847bb52e906c862a1b0628496416c14df5dcfbb5e2804f502cb0a2d163e9bc2d84122c0b3f5d0609b82ac16aa15efd55f55c8caa3d1114ac0cb83e5ff3db12a24b89aca5f0514d2ceb09b14fa916000c0f4deb016db755e88b326172144e4f1a705a800559b3da3c27af55cb32b1147460c31186d99dc1cf2e5
+X = 3dd64db4bd8e28e701235ad83a5d5e9dd13ee8a3b3dcb4c99c1bc95b6ae25291
+Y = a37397e6eafbdcf1e0158f1f4ea1cb3a1ebd739c8559a500def3b7551799d652b327101cfea0b87016db591522b9b34ed267132c5255e77653c4eb935ce0c822b4b10a5e8f3cce39ad1b9606de5be2b2d36e1c5411f06aba0461ea8dc48b649f108eba88def44daa2a5c653dccf1d8ae29205dd5c340e34b7bd698eccdcd345bd4aa5eee3c08b9162ca1804872de3c575d572f34dd48b41f8235d0f511c8dc65daeb07095c3b5dbd3a076f8eb24412f3621f492126737a9d73014defa5f5d57bdc6faf53142eb191606f2fd3dc035f4b8ae84d655cb6daaaf889005c3c334ffd7e3b0498fae2a6f8dc1bc62f3704c8f8c005c8019e0bf45b7aa8e0803b93a992675e381f61a898582950b9ce40e7cdb0300f4b26f9b44484e89c9234179b60a372fe9476f84de0ed4b93497216fb96bae43297dcdc8496c634100cf066402c7d290a7cd28cbcf8b08ad4c136db2fe992ffa045bf8cb249234f29a674762a56d20897ea5538c674a14353db64ba60fe4052a0528eb0b25887e3c5ea69b41f68b3
+K = 453b64f2dedfeb1419b5dbeb726a2c92b1a37ef11a7732c911d9a96184285f40
+R = 72cf0e18e4bc3749647cdfa62dcbd2513c7c2b1d397c1fcbc7f6a425ebb897ce
+S = 7b7d0a9e93340941bb55f6afa6cd63f7364963671008ede457d05b6545fab1f1
+
+Msg = b3dea62a20a9ed9da990465bebe18aa71f08f93fbaee4fe5d581ffaa6fd55cbe272a115d7fa18fb9cf5662f595b7cb9bdb97a81bdc078ee3bdceb2c03722610134c3bbfd7a6f8b79ecc6a9a7709265687f9c236fc68b02203ba666e9eced5161de90c110ee7af9bf54d84a22181f17b4329348bdeefbb324962e63569f07c285
+X = 6327d3818c87e4c99b7e5116fc091a9da1e4c02aab9b207d61e859dda8d859ed
+Y = 45013318b941a710b8ab1010d818c3103634658d2e3e2f413165860805e08d5c1e80add9969a3d3a0d23432c8a48cce836b24a410892099bbf53cc5a84a95e1eb3b682d2754e721efc86d3f4248baa337d6f6e5dac4759b296165918a71b31ced25bf1b05d675bfa222980608fda8f9d0eba9aa08475512d04c612133c88253bf3e27e9ffe3a8570be204f54bf8ff1c7fe42aece832050aabdd9415764b8c872697f9c8e78e2f56bd235ebbbb4b9cf8f054b60292963764536d6fd4c6cfaa1baea53546c6ffb56a04fbfaee001228280aec40e66d9dc192f9ba743bd3ffc0eaf277b6ba3d33c3697024892b0b35419534873fb7a3d594dd6ae0751a2fa430ba46237f4a55e4a678072c651fe6ad314a010fdfe8f8b5342bdabe9ae5910c6f44a51f47524a6fe8216830ccaeded26ce1f13f7f216e0b7809e9272563cab3352b8ed766650227bfe16e981b505609c41f03dca98e219d02aa7d91921edb3a89229e78c30161cc13973b35de3c87779378b8d607a19320405661312432dd8d07af2
+K = 94a0f6f58f004e45ce5ffffa6e63abca8daf7768cdafd517f3a5e399828b1e72
+R = 3ec677e91c63e65aaa174aee2791dc409244cb80c0220991dcb497397a3c5e9b
+S = 1de0ec466b2ad4ed1adce3bc38ee521803dc87085e2fbfc561d63844c1a9a2e6
+
+[mod = L=3072, N=256, SHA-512]
+
+P = c1d0a6d0b5ed615dee76ac5a60dd35ecb000a202063018b1ba0a06fe7a00f765db1c59a680cecfe3ad41475badb5ad50b6147e2596b88d34656052aca79486ea6f6ec90b23e363f3ab8cdc8b93b62a070e02688ea877843a4685c2ba6db111e9addbd7ca4bce65bb10c9ceb69bf806e2ebd7e54edeb7f996a65c907b50efdf8e575bae462a219c302fef2ae81d73cee75274625b5fc29c6d60c057ed9e7b0d46ad2f57fe01f823230f31422722319ce0abf1f141f326c00fbc2be4cdb8944b6fd050bd300bdb1c5f4da72537e553e01d51239c4d461860f1fb4fd8fa79f5d5263ff62fed7008e2e0a2d36bf7b9062d0d75db226c3464b67ba24101b085f2c670c0f87ae530d98ee60c5472f4aa15fb25041e19106354da06bc2b1d322d40ed97b21fd1cdad3025c69da6ce9c7ddf3dcf1ea4d56577bfdec23071c1f05ee4077b5391e9a404eaffe12d1ea62d06acd6bf19e91a158d2066b4cd20e4c4e52ffb1d5204cd022bc7108f2c799fb468866ef1cb09bce09dfd49e4740ff8140497be61
+Q = bf65441c987b7737385eadec158dd01614da6f15386248e59f3cddbefc8e9dd1
+G = c02ac85375fab80ba2a784b94e4d145b3be0f92090eba17bd12358cf3e03f4379584f8742252f76b1ede3fc37281420e74a963e4c088796ff2bab8db6e9a4530fc67d51f88b905ab43995aab46364cb40c1256f0466f3dbce36203ef228b35e90247e95e5115e831b126b628ee984f349911d30ffb9d613b50a84dfa1f042ba536b82d5101e711c629f9f2096dc834deec63b70f2a2315a6d27323b995aa20d3d0737075186f5049af6f512a0c38a9da06817f4b619b94520edfac85c4a6e2e186225c95a04ec3c3422b8deb284e98d24b31465802008a097c25969e826c2baa59d2cba33d6c1d9f3962330c1fcda7cfb18508fea7d0555e3a169daed353f3ee6f4bb30244319161dff6438a37ca793b24bbb1b1bc2194fc6e6ef60278157899cb03c5dd6fc91a836eb20a25c09945643d95f7bd50d206684d6ffc14d16d82d5f781225bff908392a5793b803f9b70b4dfcb394f9ed81c18e391a09eb3f93a032d81ba670cabfd6f64aa5e3374cb7c2029f45200e4f0bfd820c8bd58dc5eeb34
+
+Msg = 494180eed0951371bbaf0a850ef13679df49c1f13fe3770b6c13285bf3ad93dc4ab018aab9139d74200808e9c55bf88300324cc697efeaa641d37f3acf72d8c97bff0182a35b940150c98a03ef41a3e1487440c923a988e53ca3ce883a2fb532bb7441c122f1dc2f9d0b0bc07f26ba29a35cdf0da846a9d8eab405cbf8c8e77f
+X = 150b5c51ea6402276bc912322f0404f6d57ff7d32afcaa83b6dfde11abb48181
+Y = 6da54f2b0ddb4dcce2da1edfa16ba84953d8429ce60cd111a5c65edcf7ba5b8d9387ab6881c24880b2afbdb437e9ed7ffb8e96beca7ea80d1d90f24d546112629df5c9e9661742cc872fdb3d409bc77b75b17c7e6cfff86261071c4b5c9f9898be1e9e27349b933c34fb345685f8fc6c12470d124cecf51b5d5adbf5e7a2490f8d67aac53a82ed6a2110686cf631c348bcbc4cf156f3a6980163e2feca72a45f6b3d68c10e5a2283b470b7292674490383f75fa26ccf93c0e1c8d0628ca35f2f3d9b6876505d118988957237a2fc8051cb47b410e8b7a619e73b1350a9f6a260c5f16841e7c4db53d8eaa0b4708d62f95b2a72e2f04ca14647bca6b5e3ee707fcdf758b925eb8d4e6ace4fc7443c9bc5819ff9e555be098aa055066828e21b818fedc3aac517a0ee8f9060bd86e0d4cce212ab6a3a243c5ec0274563353ca7103af085e8f41be524fbb75cda88903907df94bfd69373e288949bd0626d85c1398b3073a139d5c747d24afdae7a3e745437335d0ee993eef36a3041c912f7eb58
+K = b599111b9f78402cefe7bde8bf553b6ca00d5abaf9a158aa42f2607bf78510bc
+R = a40a6c905654c55fc58e99c7d1a3feea2c5be64823d4086ce811f334cfdc448d
+S = 6478050977ec585980454e0a2f26a03037b921ca588a78a4daff7e84d49a8a6c
+
+Msg = c01c47bfa208e2f19ddda5cde5833325d16a83fbda29e666fe67ff3489803a6478a5ac17ff01edc7973d15fe4998f63bbc095fc1ac07534241c643a44444dc9a356fa812d5ca191a2f6ed162a2d5fd6d0aa898a20563d993830254db8a4bf65ba86099cc6b58a1bf6ebb01a19c79304308acebe1da09f1753a195e9ef586c7e1
+X = 9f11370ddb3c43e2f4162dc61f7e08dfc6e86d5d71742c6adcb5340f7bea2ada
+Y = 970d38cd8b3f16659ec42a46a19ff06ce8495b9f477d9b7e35ae1035b08b0ee17a0c3ceedf029846e3aeb912f850881c2277f82281e7c0741d2f87e9fa5c30677fe7268cc5fd9aed29f308d9be8de92b961e39c1dbc46790c99b7e29579daf888176d5ce16db5cabfcbe4209ac4753b0e96b15d0b82c7eefb42a10de88f8a7723492a2be5451c1c6ec68ca759d8b4ee418826e71f39cd07654d00d0e0f88d0924bdb97aaca5a6346ad69fc223cd57f5bb0300477b594aa445e5ea8896cdf3bc882e8fa5523b8a332fd98e9d0a924578944d24a41cbeae3ed7b37dffb2f60c0084eaf005c1251823da41d2a5d977d8e483ddb33f73fbc27254a814b616d6a390513f0567a563ac053a76667197b4558f871b69cbf2c116ce457513f60b4f528e2dcdaa71a9a3a4cccb3738a22937bca2a042bef8a74a600acd26975c891466d7e57cc930984212ee0eaf174ebcbafbeb8cc12bc43bfdb00fd11576c439513ef5b59a88fa5a9ae963d94dafd78f81ee7b0d7fab53e41bbf65f8449a4f58b44f9e3
+K = ab53984e0b154992ace73bba548185b49719bcc3b11fb150b5da279529750078
+R = 5bb50e4f538a6e4638206be119dbf712776154acfb4c06d65d66c80212341739
+S = 7b7e640cd76086d3f640d18ceb26bb53e30282afb17401e7b48aa6818934dc5c
+
+Msg = 47e7af22c9298ad3bfef9bee5086bedbdc513d67416d5f4e7981cddb1002cba24700c45dd6d4dcef4f81d003f0513dab4e04eb4c70d944042e1b726d8a33050d0e4f70c0a8341b75fd4e27c7948754e441208eb93fc7b7c37354252f73b838fd02d078c6a1ae073ef1233aa1c8aa2781e193ba2897ccdd8cf617ca23541ce1c5
+X = 232c1c88d571492779172ce6650524cb6d91174e8a23780d0fdf7c44ffd80c1a
+Y = 75163af15cd6b228251504ba024df51df32f638e37f0f2f9d08837f8c6ecfba43eb515ccbabea11b01e1e1fd3cfe7e405fc7f8142b07315e1dc37b08c78668421e2a21fc5d811d26558c504abc4e6fddf03740b8a27fa2ebcda5460ad785706c53cd2d14093d923df942051cbba2586b4d54709d24babe2f7c61a50da8451895999166e80c0fab892a37eb6782745596b49f96e11e9a957c8ec650d2d9a40aa4b014d2e9a4c08b9d7bfeaf1ecd42785b95c0172ae21cf25c4d368bb5100b6e6d92310b28b7b1afe64d496b9c60b763cac08ac46a6bce1bbd3ac8bb76bb55b649b7594820ab6ef7dd1b09bb12852816b61e6dbefab742e0ea2cda47eac7d9d913ddd4bfd8b2eb5f01951caa4f413eb5e7a41a0685695f8331a394e06b1495c170f30ac294660e8909843f9f11c4bfa64e8792df677da0a08aae32a8a4e7067fc35eee03964e8afbdb6a421b8248add284789e4ed3cace7106c23fe6666c4b12b836e7307a55ab24d92d58ac84e71f81dc9b0b7436ad07f74994af7d0b049bd09a
+K = 101acd88a048a6a87c13ff23225dc2c4d2fe3fff039e072fbb268ef2dbfab9c3
+R = 6175473d7aa7d5ce55590c952a19897206086887fd84bf2b566926e47981c2a3
+S = 71d7857b6ff06ca67885fa9c9c71b8cc246d0339b6c2725247172a297e26a7b5
+
+Msg = 9311d8f951141713f459eb65f01880b961c0a590b36f785f1aeb880ee71300c0cbc601b3a6072193dad6ddf2028eca4c8bd7b8575187928f84bd69c5dcfb0b9d320003c3a863c09ee503e38abe07ce2e0d46b3cec926231a57defa0aebd1a6e01eef4f9b537ae1fcdf64e01434d40ab5019f3965c735411a5c19941f41febf4f
+X = 87bde6350da15832966fe70300e5dc66b96ec263344bcfb5de051be34d76262b
+Y = 287ddc1969156c18420743ade0fa1271ea346c3329f9ca9b5d54ebfa21f676f9e013616239f4bbe60eaf8e1902ed9ac742d8df918876770894b512aaa25c068bde961f56c9b5b87806d7d0a9de7843d3cb0797903126a47bd9422337e3b46bb1f4f4a79fdf9cf6762157118aeee1e71116f34dafce0047f05d43c7f2cbd4cd52d614b7a945d48be44cfebf784332fe99c1ee1aa8310867df20b280da855b19029fa79ecd6dd6919a4d22b5a1400c30e62ce7acc4b28efbdb94ea23afbb64d6e5f7b3975d2ac63b1d048feea835c7f50b425ce3cb418afdf4dc84008473606574e20db5ebf86cb1ad27737d46494b2e485b26b8c95d829cf656f80f96b1a62e7c03c8f20f18dc58bf59916682e6dcc68d34c89c1b1bd6e6b1e15a7dc325e23fd7a35099831dbd75989c738020bf4dc4079ccb0bf12faf3b9d6494a379aacb1b66d07cbcebbf77a6e29aef22f4baa3df40d270b457dde64f00b53759ae57811b64e040cbd42ea90f4e2808bc81dfd663b28584cdb8199da96d3e03d03fb4133e2f
+K = 7d1b5d39e51af0c22a56bc57ba6bf8bb6de18f2c256bb2d6fea684add38b1f6f
+R = 66f729716456a2781bdb8578fa18d1e64af0edf8ec1dee0a50d25981912fc45a
+S = 8c3cccfe6f0cfdc0ac3a542c8e8c85210bbd7f95134c8f035d1ce16f44ab7a06
+
+Msg = 808603f7f8439441277913b21bef4e01c89e4113e07cacc33f65ac9849db1ad1a1cb7dd2fecd88ee4139b1638355c623821309f326c16bc658bb4821518238982e5251f7cd37807292153d2b07dddc066e003c6069c371155d2d191f15111f2089ce423f5c2a1f8534e301313c69623f62ba635adce8551733a82a8fac1a66b1
+X = 9464ce029452e8602214c5236d9637ce7e59f92536a07ac5ba30f639e09814d4
+Y = 389672ec6de0b86655cb10f1199f857013b6320d52c8728fbbb5360a9701b1d6ca4f9eecb8487fb879690f85430c582d3d91ef184c8247d162b94d6dfdfe7c4ae867ac1672827970415aa67a1406ac1a6e2c6c13167719e1d1a536d10078427c211cf682051a75ee8322c1408b89d963bd8e85f9eff7bb8ce05ca42225b4bdfead6b897b0feab76c2272b487d27d4e8dcde0f19e4615f7e1114541f61d43533ce788cc4505600b83266b1bea665912196c2c84c36aa93baf5b7464a6ddf547183e2cd058bb50a12765536f0a4d3524af4f31acc609fc447e1729aab97b5a36b01764b84bc5f77f6cc584866d1a6cfb3aa8437895f777f2dc6897499f6c5f02fa1e6c1ead68f3385b733387c6b58f2d11284a63ae7c7cfee42c3f44a3c926adad8107cca1c3f944f9b9e237d9ab35c81391d7c5f5292d1a322f7a12ce108a86237ba4de3c612fa738f53194ba67bed843cd2d4330a5d194d67cf45fa05183e0cb46c2d23a1bae76755c309fa1c31605c88a9214227ce02fe915bcf0d34bce8c8e
+K = 5c2bb856c4d87b27e01e2ac1ae6f2fc526ab8bb49a67eda5c1d8cd4253610df3
+R = 98fe587e43aa96f9a9bbe8af404a08b02307b36053db87f6db25a3aa36fcc3db
+S = 5c94ea70f99f9ff14b8e5dd4a6688398260907176ea80e19c39b14621149f0d6
+
+Msg = ce2aa3ed12c1b8843a3e11b06b5f0e5e63fe8e19c1a38ac446a48eeca8dac6d8b769d7809442c32ac82e93f686ec64347e9444c3f452823c840e8d0cd334b4152002148da16ac8859d189d87d67164c5db16195c081d2edd7d8157e2bf3b97a90b4b4784324eb8ceac4261809f674256daf007c4ab1f222f5fd28398a5b824de
+X = b887c14673cbc63f04f0839ea56a76154027d7eecf41d8d0b53d4892353ae9a4
+Y = 584fe0eb314afb866c0466c3980a2df54598d8a705dc2d1bf5102eac86312784eebd019b81a7642d4a3c4cc65dbedd8187e3593f0a9bcc06ea367009b7eb4d29b0450061378edbe163efd3f344bb36234fc86fe1c32f2c9995a07c6e957d195e8105f5179c2bd976b3127067c80ca93456c16b98dfcc7de355790f0b15cfd2ff91db09345532d46096c06b40a2304681d62857675ac50e22c7d1ab47589235419cbedd4b7d24b90531e5bfd853e88a28836ac46b6df26760985b962c6a2445809866b46126212aa263ab2a4603ff41a852c7988c2d4386241655a7222fa4e9f6eac6a144a16b059ea25b71a2138491d54ee95a9d6819977f90fe6a59e0cad81b329eba3e68277df04f9828ef6f081610b4595a92113ec6d069ffe97196d956191daabe9877377ad0416b0ee0658663377e07adb24644e8a0e3ce5fc178f152be0cd9b04071890427c6b001d59262f38fe897ce32040daa7807821c40ac8c63505bed0af070443337c9e9a64e44203c36a8ca5064d87aa0d3cd1d403aa6a24ecc
+K = 49548238215fed6525693bc3cca3872944a97790087fb35f329b206e6046b32a
+R = 54c99b21f28feee27f0e999aac6b49b6b07633e1db18a45952fcf7e73b166bdb
+S = 7a18588ea1456f67562d677878346fb34b684b9a8a61a721b3db0e95695ab43a
+
+Msg = 17b925e2a1a51c2036e225715f2f771d8f0a6d98c7ed9cacf5aa4cd30ab16afb94e21a7c953e01ca211c28782a06073fdad27713aa8c26ae9ec449aaaa8ccfda8c947172de94b3f20b54af98df152d5d3a636c736ff01bfa699d6214002dc76dbb3f3860d94e0e34edaba5f2bfd6b2bf660086be876451a50f6a2dc7c2b098b7
+X = 0684a8fad551c8d08beb05033185e3b4b6b6f6f4920ef9982d72d0a9c7549855
+Y = 42a93bf44ec7d2fbd651cc1d1ac391d63cab00971a7ff7a56166768b22e611dc4d729faf8c94e7ed4d6f82b7020b7b4d2fb3591cf2295cc6e1b4be2c256c2fdda43e00051114645da91cbed5cc087085f7cecd8bace67889100bcce7928220266fd3faf2ead9c21e423c9948ec70c2d31b668cdc360ddcebdf429720607f96d851235515d6dbdf163f7ea5ddf351baa76f38663fdbfbd5871bb2157df0a43420648c10e4827f54065614623ed3abad10d317be9d49a4c66564f20dcac176b6605a2e3c3c01c362220f352e477419f2b4b238affbc3920e5bb57cebb9a74746d62cdd070f4a13af001d262def014f29b7f754fac84e02d29285b73bb20ac0c8624123a577be8d6a6b9739185e4458090ddb42b005ea4fa8b51007bd9ca5b4cf2a3dca446a87ec83c9548dab46cf3daf86db3bc69a99baed459d6a197f9bf5032c1dc3a877dd7e5c1161124a6d701324e9a9712b824a4fc3b1b353259af225813c27e820b0ba72fb4e78f5c78673924e7fa2f486030284f26cb6fa31da56f49d3f
+K = 4a258c125db1f7b775432b53c7a0ff47c00bf7af27abec7fcd42a2916e95e26d
+R = 726e4d3baf00b259f4bdca8b0a5e1cbfd37827c48373ef5029f7601a7769478c
+S = 903079439ebde1f766d1a8ff33e0f778d77b5e8b7b0d687443c271e8a63b5975
+
+Msg = 1c1169f0e790053cd7df780b5c832c64147694b4a6448ba14a426d9def7ddc78e3ed36a12da81cf9c3f245d64c859b6b4d8121d112851974df178defc977db691234d142dff99bea1957891b5d6fe8a787e96369d93c24682debd1cf3fdb64379b8c1b3b73e1bc2467dcb08b86cbd494c01477be24d7900f5a578930f4bddcb6
+X = 3fa44778b414ff27436e276ca4904546d3542d128f73c4463c69ff9cea2b7a41
+Y = 7fca2268fba33bf94e76416a9e3869f8a90c3b0d2d37aacecd3f6785b9a95aeefe9324c3ab09ce61ffde37b50f82b699413f3b54f24d6c52eca62325029523deb05db138778447bc3d0d05aff7d85b5525f2b863d26486e84cde13e2e2117d3fa38a38d1073aaa794ed8eaa7b3d1daa4ac3e808c3738a9cbef3546cd79eccb4faa28b50fce57cdc24015fec390f0e7a7dc9f9c471d22b30c3e4174358f1ad0734cf79a09a639bdf3f3eabda2b47b81f92e2a4f9004dd641370338c02029bbf4971aa67483eea7a4bf7dff3889f84faa5765617ccab37d190a94c57f99d792807a6965e2113586c6c5d1a81abfd372e1c7954e2e09064df4d2d8288f5cdd8106ed84ffa798819a09a732bc204a812c0352e4e39d2ceb88f8e7d3624a5a5f3dc56ea0f9c5290788e12dc463161601ff3ab681bd0403ee03af45d5e586d84d9c901986718193e661256f402de735d2ca696ef6b594868950ae173f22d95856656a9d00610fe8c2bd725ae55d791277b1317085b67188da00645ce91bbe62e324311
+K = a05b9ca1c9532bc050cd0c1150c27bc192154cf64d59dc9a949906f1ded57e35
+R = 1026ecee0ac31bdcdbd6103b1343f84b441fc326e1d86ad0903d0b17cfb2ff9c
+S = a5d3cb2e7c39d87640c4547ac6c33afccbfc1820905ba1e5be5b262313277cb9
+
+Msg = 805baabdd018d9e5ebb4dc51435be632d2387869756d743788442790d55bb183e26655ae3aac86dc16a48ddd268dd15e18d8320df9a1a0a6cb2b49bc701d7a15e3fe8ddd584a75c8c9aaaecd1efe17324d6261881f3d34685b04f62e968505966c9a5feb0c39b5095e5568e40f20aa21cb2505356dc9049ce56182d94a2d94a9
+X = 770b99935d393eb90b583d1251696007cbeb1b35e6c3f4f9bcb62879070e0940
+Y = 434d0612b2a8332b0ab15614e3ee9fa245131712fb2ba84f71396fff9488dca340a37e820f44c13aa87fc9df0b7aabeae2ed85a9622b8defad474ac362a7039abde33d1df732a052446aff7857bc24d8f61d258015ed2a3060a8bf9d447e7d83d7b497a8e654731969e437b3f46f83eb58f7884ff2a2390f5d821ecaa7fd09a146c55fc1180073cc5aaa607cabb944f6078a4486cf206ddc5635242def2d3e2edcbc026bb84e849518f197399c22a9009dde9afcd8769b241c75d4ccce7f93900b5f488333df47c026c4f2b2767e70d2d9dde78405e226c9952f6db1a2e55829bc8a76c7de5c2b588f3f3e93ce72fadabacb75c7c14669701e0a2ba127bac56863c8c4e7205cc0a73c429a801e9797da4f26e848982306cc3c3439f9e394ddc80b0f13e0d528190638d8b96bba3af889de373b3549fc90a6822964c22171e7601fdefbe5708988b84f3ea554d621600a876415d5bc1e557e948caace563b3702f0915a90a13aada77709eeba8c50a8629351a4787d0d58808ffb8b217c1d164f
+K = 424a43cfd90f7b84e9e375572f82ebce7ffb197bd3237a353bf15ddc1a17095f
+R = 2d63e6d2568571acfe4a931580a04b974c7aae4ca9aa9610d87be1a91c657c31
+S = 574b10d14dcb8f079461b29ae1b91ed6c5ef32f93cbad306697552c11748fe0c
+
+Msg = be8ca5ed4c22a050d8309c7a31acf667f0c0fbaadc64a34d2b63074a763a2b8db73b24cdbaad26cc6f2c3e90df4b25bfa724fce587faa0fd65ffb719f0a0351648230d5354d721d8fa6d0d686c37f257d7d9dbd15f555d5073f8bc71c92139d1f627d743f7d6586d510d19d0d8a555d0bf79ec70596e712183880c89caf69d6f
+X = 9886138d837d20e8c6be853cd7de1a66a25748c7a33fd55121a27237623d68d6
+Y = afaff7a4d438b464f27415d2e03ed9c416db2bebfbe0ab34f14ee10644885b5a4588877150f46327c2c7a6f712670bfd6237a29452494859948f5e37c0e586656b119a0e01c81acee57c1775a3a146e8fbafc99cd203fc98195687fb94a88a4f44280b03f0895e0eca84db087c1bf7c4843c85597368e839841131e027109daa7b8172a25e11355fa9a9205ac324941a9fe492c48421f0681a47e280803e8bd91b113e0fa1597607430bcb0ad50b9408de0066d6a2324d09cf6e99133654dd64e8c8f70cd6445343758b5cd5a0e77e2d3fa1cb3f7efed76124b2881dfd2028ab5918c389b9c3978271db54a5171515ab2e85eeb10ab307130159bca5fe13cc4a959e88e9267221ac8d14ee6938e149f52ec59125b449cb55c5a0029f018770b31f08440ce6876e6600a32411722f58e6263339bd9d34e17aa574b921228926ff668ce90362c4391ecd0c037454e12fdf80c96bb7a840cd866e8570bb7d6586fbe3d1eae5332931198ba1d5d902d6b7a122dfa77018553a2dd3680a809bb06053
+K = 1689eba0aac66b3d0cca9ae1911602f9638937b6be17c23a187be323d0dec7be
+R = 9c7d40e214082bd5e71f3bf4be99789303f38e851a76f88cb90aff713080c587
+S = 24ca23be94c624b9d736328b53782b5feb384dc9fe6370016cc3f97d8f48b6d0
+
+Msg = 62f0cb1bb07f6497a1dc7a66955765a9cc403bde03fef4e16b09d7ec545b4c75d08b6e9c4c5af7232548d45445638d7194a199ef1534e81241eaa9c7e767fd54e2caceea4d2f7215d37baad6b05e28ea093497e2e8e1db6e41a5eb13ffa4caa27108f2263a74cf54bd5b6a6b62284bac99fd7977aaa8ffff18fa8a70ab0debdf
+X = badece34257da3d7b8713f8f0f9f0107b1909c7f99a765ad8405d8c2a20310ee
+Y = 73554a69e1a09f6191f0aded542a077ee8c814265d745d9ae5c792f442c5fa47b34643d3ba1d5147161898de5188a80714ee36512a618a33e40300ff1187e553f54433e17466af486472bc0778af55ba7346c961d7f13ac6d8d6ac9a42092c01579ee2170590cbc3b45eef795b5d9e5d0a8449439ab307c14c5674c4a7a3eaf8b240ef36dd21f43cced58c2dcf23c314364e8e314e9671e80813d185801358d5df61d7e7ec0dd69e90c2cc75c1c3543efeca82b2ec6ec59e6c99bcd1a8631c6228e216884082da119125cb0a80c8fe344afe66e0f20646432465f3e0096a17725a8867b3bdba3c69a1aacbb8d64755b7f2a3df0a49ba0b2114e112d4cae0ad6d8d0fd618e54d53f07ba109b75a54a989618b2863e4415e176e0bfd88dbf36553ca853bb36316c66eb93da34ff3ae74cd5f187f49bf38af0f393b2d7f854df192ade2df6b39a176d2152c912bba248d84a5b0aa4084a18bb64fd136973f73b413d77db275ea5ece93ce2fa00d7c8887b7e50b00649d0353a7f58cc63f6b5fbdfc
+K = 2d468a99e315c158a1af18abd4d58872d6e281dcd4c9b0b43298eddf346496d7
+R = 54ff5d3dc8767856a10f54088882e28c110980ef9b204eb5f162dbef73a37c73
+S = 57ed0748427c089d6395528b2b4555c01b4c1341ab5fb99c64d1cc247a41c3a8
+
+Msg = baeb12a1ebd8057a99a0137ee60f60eed10d26f1eab22ae2d9adbc3e5ffc3252abf62b614707ad2546141bed779f0cfad9544a74e562da549e2f7b286efb615449b0946dc7c498d8f12150b2eacbd27157966f592ad5f3e43a24c60b7e06630b82a4fdb699119dbd878b13a98bf22a7b3dc7efdd992ce6b8a950e61299c5663b
+X = bd3006cf5d3ac04a8a5128140df6025d9942d78544e9b27efe28b2ca1f79e313
+Y = 00728e23e74bb82de0e1315d58164a5cecc8951d89e88da702f5b878020fd8d2a1791b3e8ab770e084ac2397d297971ca8708a30a4097d86740153ee2db6ab6343c5b6cc2c8a7fa59082a8d659931cc48a0433a033dbb2fff3aa545686f922c7063da1d52d9688142ec64a1002948e5da89165d9df8eed9aa469b61ee0210b4033562333097ba8659944e5f7924e04a21bc3edc6d551e202e4c543e97518f91e0cab49111029b29c3aa1bed5f35e5c90feb9d3c745953dbf859defce4537b4a09801fdc8fe6999fbde39908079811b4b992c2e8333b9f800ea0d9f0a5f53607e308942e68efef01e03d7cca6f196872bf01f436d4a8e05fc59d8fbc6b88a166f57a4e99d67ddaece844653be77819747dd2e07d581c518cb9779e9f7960c17ff0bae710ecf575b09591b013b4805c88b235df262e61a4c94f46bf9a08284611df44eadd94f44cef6225a808e211e4d3af5e96bce64a90f8013874f10749a8382a6026a855d90853440bfce31f258b3a258f7b5e659b43e702dee7c24c02d2284
+K = 16aedfbe554de17a3e5b83e942702bd60702d9823ba154baa6d1e7e94308324d
+R = 8d357b0b956fb90e8e0b9ff284cedc88a04d171a90c5997d8ee1e9bc4d0b35ff
+S = ab37329c50145d146505015704fdc4fb0fd7207e0b11d8becbad934e6255c30c
+
+Msg = 184e599a4c1de86c4151205754df0b1912c2b3c532552c51a61c6459db98c83e59d4a40806c6a2c6b3fe74e3bb9e720d7d0a3cc11ef88959a8990c0fa057a3915fe0dd9a138aa0ec1cb1ab69d93910d8d6f9e14f3b8a135d3f031a56c76a9dc3aed1962bdf05815c2492d14f2324d2da491810d1672b633f2419da4e7ebdef24
+X = a29e90d33f200b1faf61bee5d92ca8a392b1eaeeaa0817cec98b40c97e25018c
+Y = 60159720021fd2d5a2f575b3220905788d328d0c46895a46bb985942467209ec28d8ddfdc97ec34da65b164cf48652ac475d8978959cfc4330743ed98137559391b1204da6b26b451211407e8fc77d819934c48709c8eadc620f6db2592b65483265149a324467d93c375d97230f2b1a682897cf6d280df61a34f20f0c7c729a40141958044876c44e595d2378a7d22c6cda9ab816486c294e4eddea7ada88b15eca5371da164471edafcdefc654e64a1f995068fa85dbbb5516137bc442f60717fe59c629081c234f27195d5f9c2bf85cdc1ea4cae57aa908cbff9b2a53353b13e9f6fe45daa5174cd956236d447b52011d688cd22f23018409b39a36079cb53e03b6d3a752733297fea4ca27c6395becef4081d201f41d4a00e99d95f42281dcf44b9ef6754998d94231937c82594218a78463cc837193de6bf1d3c3ec31d8dc5468cb56defc9c70d08b95b029d97aa043d557f6286b87ee4098442df495c0ad8ae4d4ae037312c5f7239032c03b088c1036fad7774b1519709242c9511e6e
+K = 78e781b2874ca2441e2ce74a2a2a16417b51537eca876831f6593ae25fbd796c
+R = 079d4df14ad703a435b21bc70a03456ca822b876c9accb018bddd674bd6392d7
+S = 6c7765e1f1eddf915a56a57390db45636e52f083ce440766ad4f32580f722483
+
+Msg = b189dd34f58f3efa85b6f97677edfb82664cbe43a2550c336ffa08705bbda2545ef244a275014c6a265971f4c3658e5e8d6a3fafc889f3c4eda6b5616092954b15c60435efd76806e28557c05faaaa8a05c262657840865ff69c511a68d13022a712d35bde138eb7a2f8f1a87b342c7caf388c1a8b95079bc4a8003eef84b899
+X = 9759c24820670eaeaf92370197d0037f9f71dcc283970f341117fb56a1764001
+Y = 05e280310810715d29ea1ca00a700378bd5979493b9803174c932b7dadb7029a9a9f9c91cf8f938af2bceaa052f2273f0de393b0f7544490d693f529a68b812e2e589cc092b83ef847c5306039aa8eaf225128926145893a51551db382fda4b63e5abc10fd076100684d4ca657c89b2265de6e0f0473f01bb222b2bc50ec1c5fcde9161831018aab3014a956033bb0a83866df11915808f9e7461645c89c6e17ab65dbf97cbf4ac1164d671a1516ca81645bc3e09913a03f30641bd0920083578ca84df71f62eb756ba445a0dc44f85a9e4f72ce5f6bf82ccbd674d2ce3c4afc300562a7dbd3e8ab838993f9decc9933dc07dc01b502fee5b390461a8c82c4e69615f121b3f9fd4f0c8b7620a25996df43d7cf355f15be09e2c82178c6f8836c36c1d3ef26ad05219fb57e85ef162c8dd8f0e55014769d53cba478a2aa66d90d8acd6cb0489d1eea46c2c41bd5495ab8def43b2cd5bb2673945c21c80a4833fd75d884c7675c09e7191fb26e92c54c7c8208d0a0e8dee75c2968e962de4493e8
+K = 86050bf276a649b13c18814430eadcff54edf7416f1a8b1559c6c2c808e8dc9f
+R = 9fd105c74a0d36973740867ccc1c731cf1c50c7935d5c09e92f574d7a569157e
+S = 501f50c32b0288672e02aca78f90f446acf92626365957a375550c77980c3c17
+
+Msg = 42c065fadd56d6a1fe68dd4e86c17efd76d0f9db87036bd7b609159d66847f46de01b8ae43590360fa324559a2d709d45cf01034f5facb7f52324e60dd464a583d42e412659d8420f7265e30cf82bbbcb2c99b0f00ca6a46d28556428789f415000dc31babbd67ccc8fbaa84a880466bca4783eaf00b7f78231c667126433e6a
+X = 307555893610e15549a5bfb2b446251f9595eb0c16df5fe3b784ebfc3fc30140
+Y = b265edfed77b3ad511e56d583129b12e5796d659d484a2fce350661f79e545dd0a06c23774c8ba2fb5101a2848c413dfc5b374a7c5ff3acc7332f0ff8bd6f5fa882c0a67689308be7154c4efc51835f349525419ed722a90bf26ddded65bc8962ba11de9e734442571affc2d42b9f3f54a46535ae9eb01361adf03fc28410abf41db3ae4113da4c40e9a368f9cd029be4d98c66d835d034e3c86544b60bcb01feb383b2add9afe7b6251a17ad4e5439a9cd2d1bf62b6cf5377c097b7268bd736cca9ceb822e5d1844a09fa69c78217c3d6737f0bf45e3236508b5a3f5c466dd0d75ace95d447f9bd7aa9ee57bd10ee3c5e8389a06c00857e699794f5cacc7dc5bb1504421dc920565618bef05dc1713b6f08bc00681c5a1c0685359729fe4b544090ccceaa82f4fefa9f1117bf1e371b99fe4ed71635dad415017a62341d704227ee7cfb64a8deae90d86c0cfd37ed363d91a4a06fd06f64dbd8142c12503f49eeb1b9a971aeb343f15cd27d279b99d4cfa51f121259b3c1b55d28d994bb3299
+K = 5359fe067eb9d98ec2217500de743b0dbe88e8d94552b53a0117aac4d3390083
+R = 6ed82af8e89e38c49a58010f0564165a16a76a2bfb348466d9b4a91e5ce53ab2
+S = 8c466a8b3e4c90886f29986a4d513904f31db43a68ce880311403cc755466604
diff --git a/tests/t-ecdsa.c b/tests/t-ecdsa.c
new file mode 100644 (file)
index 0000000..9a0773b
--- /dev/null
@@ -0,0 +1,652 @@
+/* t-ecdsa.c - Check the ECDSA crypto
+ * Copyright (C) 2021 g10 Code GmbH
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "stopwatch.h"
+
+#define PGM "t-ecdsa"
+#include "t-common.h"
+#define N_TESTS 320
+
+static int no_verify;
+static int custom_data_file;
+static int in_fips_mode;
+
+
+static void
+show_note (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!verbose && getenv ("srcdir"))
+    fputs ("      ", stderr);  /* To align above "PASS: ".  */
+  else
+    fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+  va_end (arg_ptr);
+}
+
+
+/* Prepend FNAME with the srcdir environment variable's value and
+ * return an allocated filename.  */
+char *
+prepend_srcdir (const char *fname)
+{
+  static const char *srcdir;
+  char *result;
+
+  if (!srcdir && !(srcdir = getenv ("srcdir")))
+    srcdir = ".";
+
+  result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
+  strcpy (result, srcdir);
+  strcat (result, "/");
+  strcat (result, fname);
+  return result;
+}
+
+
+/* Read next line but skip over empty and comment lines.  Caller must
+   xfree the result.  */
+static char *
+read_textline (FILE *fp, int *lineno)
+{
+  char line[4096];
+  char *p;
+
+  do
+    {
+      if (!fgets (line, sizeof line, fp))
+        {
+          if (feof (fp))
+            return NULL;
+          die ("error reading input line: %s\n", strerror (errno));
+        }
+      ++*lineno;
+      p = strchr (line, '\n');
+      if (!p)
+        die ("input line %d not terminated or too long\n", *lineno);
+      *p = 0;
+      for (p--;p > line && my_isascii (*p) && isspace (*p); p--)
+        *p = 0;
+    }
+  while (!*line || *line == '#');
+  /* if (debug) */
+  /*   info ("read line: '%s'\n", line); */
+  return xstrdup (line);
+}
+
+
+/*
+ * The input line is like:
+ *
+ *      [P-224,SHA-224]
+ *
+ */
+static void
+parse_annotation (char **buffer, char **buffer2, const char *line, int lineno)
+{
+  const char *s;
+
+  xfree (*buffer);
+  *buffer = NULL;
+
+  xfree (*buffer2);
+  *buffer2 = NULL;
+
+  s = strchr (line, '-');
+  if (!s)
+    {
+      fail ("syntax error at input line %d", lineno);
+      return;
+    }
+  *buffer = xstrdup (s-1);
+  (*buffer)[5] = 0; /* Remove ','.  */
+
+  s = strchr (s+1, ',');
+  if (!s)
+    {
+      fail ("syntax error at input line %d", lineno);
+      return;
+    }
+  *buffer2 = xstrdup (s+1);
+  (*buffer2)[strlen (*buffer2) - 1] = 0; /* Remove ']'.  */
+
+}
+
+/* Copy the data after the tag to BUFFER.  BUFFER will be allocated as
+   needed.  */
+static void
+copy_data (char **buffer, const char *line, int lineno)
+{
+  const char *s;
+
+  xfree (*buffer);
+  *buffer = NULL;
+
+  s = strchr (line, '=');
+  if (!s)
+    {
+      fail ("syntax error at input line %d", lineno);
+      return;
+    }
+  for (s++; my_isascii (*s) && isspace (*s); s++)
+    ;
+  *buffer = xstrdup (s);
+}
+
+
+/* Convert STRING consisting of hex characters into its binary
+   representation and return it as an allocated buffer. The valid
+   length of the buffer is returned at R_LENGTH.  The string is
+   delimited by end of string.  The function returns NULL on
+   error.  */
+static void *
+hex2buffer (const char *string, size_t *r_length)
+{
+  const char *s;
+  unsigned char *buffer;
+  size_t length;
+  int odd;
+
+  odd = ((strlen (string) & 1));
+
+  buffer = xmalloc (strlen (string)/2 + odd + 1);
+  if (odd)
+    {
+      length = 1;
+      s = string;
+      buffer[0] = xtoi_1 (s);
+      s++;
+    }
+  else
+    {
+      length = 0;
+      s = string;
+    }
+  for (; *s; s +=2 )
+    {
+      if (!hexdigitp (s) || !hexdigitp (s+1))
+        return NULL;           /* Invalid hex digits. */
+      buffer[length++] = xtoi_2 (s);
+    }
+  *r_length = length;
+  return buffer;
+}
+
+
+static void
+one_test_sexp (const char *curvename, const char *sha_alg,
+              const char *x, const char *y, const char *d,
+              const char *msg, const char *k,
+              const char *r, const char *s)
+{
+  gpg_error_t err;
+  int i;
+  char *p0;
+  void *buffer = NULL;
+  void *buffer2 = NULL;
+  void *buffer3 = NULL;
+  size_t buflen, buflen2, buflen3;
+  unsigned char *pkbuffer = NULL;
+  size_t pkbuflen;
+  char curvename_gcrypt[11];
+  gcry_ctx_t ctx = NULL;
+  int md_algo;
+  const char *data_tmpl;
+  gcry_md_hd_t hd = NULL;
+  gcry_sexp_t s_pk = NULL;
+  gcry_sexp_t s_sk = NULL;
+  gcry_sexp_t s_sig= NULL;
+  gcry_sexp_t s_tmp, s_tmp2;
+  unsigned char *out_r = NULL;
+  unsigned char *out_s = NULL;
+  size_t out_r_len, out_s_len;
+  char *sig_r_string = NULL;
+  char *sig_s_string = NULL;
+
+  if (verbose > 1)
+    info ("Running test %s\n", sha_alg);
+
+  if (!strcmp (curvename, "P-224")
+      || !strcmp (curvename, "P-256")
+      || !strcmp (curvename, "P-384")
+      || !strcmp (curvename, "P-521"))
+    {
+      memcpy (curvename_gcrypt, "NIST ", 5);
+      strcpy (curvename_gcrypt+5, curvename);
+    }
+  else
+    {
+      fail ("error for test, %s: %s: %s",
+            "ECC curve", "invalid", curvename);
+      goto leave;
+    }
+
+  if (!strcmp (sha_alg, "SHA-224"))
+    md_algo = GCRY_MD_SHA224;
+  else if (!strcmp (sha_alg, "SHA-256"))
+    md_algo = GCRY_MD_SHA256;
+  else if (!strcmp (sha_alg, "SHA-384"))
+    md_algo = GCRY_MD_SHA384;
+  else if (!strcmp (sha_alg, "SHA-512"))
+    md_algo = GCRY_MD_SHA512;
+  else if (!strcmp (sha_alg, "SHA-512224"))
+    md_algo = GCRY_MD_SHA512_224;
+  else if (!strcmp (sha_alg, "SHA-512256"))
+    md_algo = GCRY_MD_SHA512_256;
+  else
+    {
+      fail ("error for test, %s: %s: %s",
+            "SHA algo", "invalid", sha_alg);
+      goto leave;
+    }
+
+  err = gcry_md_open (&hd, md_algo, 0);
+  if (err)
+    {
+      fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err));
+      return;
+    }
+
+  if (!(buffer = hex2buffer (x, &buflen)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "Qx", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer2 = hex2buffer (y, &buflen2)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "Qy", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer3 = hex2buffer (d, &buflen3)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "d", "invalid hex string");
+      goto leave;
+    }
+
+  pkbuflen = buflen + buflen2 + 1;
+  pkbuffer = xmalloc (pkbuflen);
+  pkbuffer[0] = 0x04;
+  memcpy (pkbuffer+1, buffer, buflen);
+  memcpy (pkbuffer+1+buflen, buffer2, buflen2);
+
+  err = gcry_sexp_build (&s_sk, NULL,
+                         "(private-key (ecc (curve %s)(q %b)(d %b)))",
+                        curvename_gcrypt,
+                         (int)pkbuflen, pkbuffer,
+                         (int)buflen3, buffer3);
+  if (err)
+    {
+      fail ("error building SEXP for test, %s: %s",
+            "sk", gpg_strerror (err));
+      goto leave;
+    }
+
+  err = gcry_sexp_build (&s_pk, NULL,
+                         "(public-key (ecc (curve %s)(q %b)))",
+                        curvename_gcrypt,
+                         (int)pkbuflen, pkbuffer);
+  if (err)
+    {
+      fail ("error building SEXP for test, %s: %s",
+            "pk", gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (buffer3);
+  buffer = buffer2 = buffer3 = NULL;
+  xfree (pkbuffer);
+  pkbuffer = NULL;
+
+  if (!(buffer = hex2buffer (msg, &buflen)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "msg", "invalid hex string");
+      goto leave;
+    }
+
+  gcry_md_write (hd, buffer, buflen);
+  xfree (buffer);
+  buffer = NULL;
+
+  if (!(buffer2 = hex2buffer (k, &buflen2)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "salt_val", "invalid hex string");
+      goto leave;
+    }
+
+  err = gcry_pk_random_override_new (&ctx, buffer2, buflen2);
+  if (err)
+    {
+      fail ("error setting salt for test: %s",
+           gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer2);
+  buffer2 = NULL;
+
+  data_tmpl = "(data(flags raw)(hash %s %b)(label %b))";
+
+  err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, ctx);
+  if (err)
+    {
+      fail ("gcry_pk_hash_sign failed: %s", gpg_strerror (err));
+      goto leave;
+    }
+
+  out_r_len = out_s_len = 0;
+  out_s = out_r = NULL;
+  s_tmp2 = NULL;
+  s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
+  if (s_tmp)
+    {
+      s_tmp2 = s_tmp;
+      s_tmp = gcry_sexp_find_token (s_tmp2, "ecdsa", 0);
+      if (s_tmp)
+        {
+          gcry_sexp_release (s_tmp2);
+          s_tmp2 = s_tmp;
+          s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0);
+          if (s_tmp)
+            {
+              const char *p;
+              size_t n;
+
+              out_r_len = buflen3;
+              out_r = xmalloc (out_r_len);
+              if (!out_r)
+                {
+                  err = gpg_error_from_syserror ();
+                  gcry_sexp_release (s_tmp);
+                  gcry_sexp_release (s_tmp2);
+                 goto leave;
+                }
+
+              p = gcry_sexp_nth_data (s_tmp, 1, &n);
+              if (n == out_r_len)
+                memcpy (out_r, p, out_r_len);
+              else
+                {
+                  memset (out_r, 0, out_r_len - n);
+                  memcpy (out_r + out_r_len - n, p, n);
+                }
+              gcry_sexp_release (s_tmp);
+            }
+          s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0);
+          if (s_tmp)
+            {
+              const char *p;
+              size_t n;
+
+              out_s_len = out_r_len;
+              out_s = xmalloc (out_s_len);
+              if (!out_s)
+                {
+                  err = gpg_error_from_syserror ();
+                  gcry_sexp_release (s_tmp);
+                  gcry_sexp_release (s_tmp2);
+                 goto leave;
+                }
+
+              p = gcry_sexp_nth_data (s_tmp, 1, &n);
+              if (n == out_s_len)
+                memcpy (out_s, p, out_s_len);
+              else
+                {
+                  memset (out_s, 0, out_s_len - n);
+                  memcpy (out_s + out_s_len - n, p, n);
+                }
+              gcry_sexp_release (s_tmp);
+            }
+        }
+    }
+  gcry_sexp_release (s_tmp2);
+
+  sig_r_string = xmalloc (2*out_r_len+1);
+  p0 = sig_r_string;
+  *p0 = 0;
+  for (i=0; i < out_r_len; i++, p0 += 2)
+    snprintf (p0, 3, "%02x", out_r[i]);
+
+  sig_s_string = xmalloc (2*out_s_len+1);
+  p0 = sig_s_string;
+  *p0 = 0;
+  for (i=0; i < out_s_len; i++, p0 += 2)
+    snprintf (p0, 3, "%02x", out_s[i]);
+
+  if (strcmp (sig_r_string + (strcmp (curvename, "P-521") == 0), r)
+      || strcmp (sig_s_string + (strcmp (curvename, "P-521") == 0), s))
+    {
+      fail ("gcry_pkey_op failed: %s",
+            "wrong value returned");
+      info ("  expected: '%s'", r);
+      info ("       got: '%s'", sig_r_string);
+      info ("  expected: '%s'", s);
+      info ("       got: '%s'", sig_s_string);
+    }
+
+  if (!no_verify)
+    {
+      err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, ctx);
+      if (err)
+        fail ("gcry_pk_hash_verify failed for test: %s",
+              gpg_strerror (err));
+    }
+
+ leave:
+  gcry_ctx_release (ctx);
+  gcry_sexp_release (s_sig);
+  gcry_sexp_release (s_sk);
+  gcry_sexp_release (s_pk);
+  if (hd)
+    gcry_md_close (hd);
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (buffer3);
+  xfree (out_r);
+  xfree (out_s);
+  xfree (sig_r_string);
+  xfree (sig_s_string);
+}
+
+
+static void
+check_ecdsa (const char *fname)
+{
+  FILE *fp;
+  int lineno, ntests;
+  char *line;
+  char *curve, *sha_alg;
+  char *x, *y;
+  char *d;
+  char *msg, *k, *r, *s;
+
+  info ("Checking ECDSA.\n");
+
+  fp = fopen (fname, "r");
+  if (!fp)
+    die ("error opening '%s': %s\n", fname, strerror (errno));
+
+  curve = NULL;
+  sha_alg = NULL;
+  x = y = d = NULL;
+  msg = k = r = s = NULL;
+  lineno = ntests = 0;
+  while ((line = read_textline (fp, &lineno)))
+    {
+      if (!strncmp (line, "[", 1))
+        parse_annotation (&curve, &sha_alg, line, lineno);
+      else if (!strncmp (line, "Msg =", 5))
+        copy_data (&msg, line, lineno);
+      else if (!strncmp (line, "d =", 3))
+        copy_data (&d, line, lineno);
+      else if (!strncmp (line, "Qx =", 4))
+        copy_data (&x, line, lineno);
+      else if (!strncmp (line, "Qy =", 4))
+        copy_data (&y, line, lineno);
+      else if (!strncmp (line, "k =", 3))
+        copy_data (&k, line, lineno);
+      else if (!strncmp (line, "R =", 3))
+        copy_data (&r, line, lineno);
+      else if (!strncmp (line, "S =", 3))
+        copy_data (&s, line, lineno);
+      else
+        fail ("unknown tag at input line %d", lineno);
+
+      xfree (line);
+      if (curve && sha_alg && x && y && d && msg && k && r && s)
+        {
+          one_test_sexp (curve, sha_alg, x, y, d, msg, k, r, s);
+          ntests++;
+          if (!(ntests % 256))
+            show_note ("%d of %d tests done\n", ntests, N_TESTS);
+          xfree (msg); msg = NULL;
+          xfree (x); x = NULL;
+          xfree (y); y = NULL;
+          xfree (d); d = NULL;
+          xfree (k); k = NULL;
+          xfree (r); r = NULL;
+          xfree (s); s = NULL;
+        }
+
+    }
+  xfree (curve);
+  xfree (sha_alg);
+  xfree (x);
+  xfree (y);
+  xfree (d);
+  xfree (msg);
+  xfree (k);
+  xfree (r);
+  xfree (s);
+
+  if (ntests != N_TESTS && !custom_data_file)
+    fail ("did %d tests but expected %d", ntests, N_TESTS);
+  else if ((ntests % 256))
+    show_note ("%d tests done\n", ntests);
+
+  fclose (fp);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  char *fname = NULL;
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options]\n"
+                 "Options:\n"
+                 "  --verbose       print timings etc.\n"
+                 "  --debug         flyswatter\n"
+                 "  --no-verify     skip the verify test\n"
+                 "  --data FNAME    take test data from file FNAME\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--no-verify"))
+        {
+          no_verify = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--data"))
+        {
+          argc--; argv++;
+          if (argc)
+            {
+              xfree (fname);
+              fname = xstrdup (*argv);
+              argc--; argv++;
+            }
+        }
+      else if (!strncmp (*argv, "--", 2))
+        die ("unknown option '%s'", *argv);
+
+    }
+
+  if (!fname)
+    fname = prepend_srcdir ("t-ecdsa.inp");
+  else
+    custom_data_file = 1;
+
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  if (!gcry_check_version (GCRYPT_VERSION))
+    die ("version mismatch\n");
+  if (debug)
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
+  start_timer ();
+  check_ecdsa (fname);
+  stop_timer ();
+
+  xfree (fname);
+
+  info ("All tests completed in %s.  Errors: %d\n",
+        elapsed_time (1), error_count);
+  return !!error_count;
+}
diff --git a/tests/t-ecdsa.inp b/tests/t-ecdsa.inp
new file mode 100644 (file)
index 0000000..196a932
--- /dev/null
@@ -0,0 +1,2626 @@
+#  CAVS 11.2
+#  "SigVer" information for "ecdsa_values"
+#  Curves/SHAs selected: P-224,SHA-224 P-224,SHA-256 P-224,SHA-384 P-224,SHA-512 P-256,SHA-224 P-256,SHA-256 P-256,SHA-384 P-256,SHA-512 P-384,SHA-224 P-384,SHA-256 P-384,SHA-384 P-384,SHA-512 P-521,SHA-224 P-521,SHA-256 P-521,SHA-384 P-521,SHA-512 K-233,SHA-224 K-233,SHA-256 K-233,SHA-384 K-233,SHA-512 K-283,SHA-224 K-283,SHA-256 K-283,SHA-384 K-283,SHA-512 K-409,SHA-224 K-409,SHA-256 K-409,SHA-384 K-409,SHA-512 K-571,SHA-224 K-571,SHA-256 K-571,SHA-384 K-571,SHA-512 B-233,SHA-224 B-233,SHA-256 B-233,SHA-384 B-233,SHA-512 B-283,SHA-224 B-283,SHA-256 B-283,SHA-384 B-283,SHA-512 B-409,SHA-224 B-409,SHA-256 B-409,SHA-384 B-409,SHA-512 BB-571,SHA-224 B-571,SHA-256 B-571,SHA-384 B-571,SHA-512
+#  Generated on Tue Aug 16 15:27:42 2011
+
+
+
+
+[P-224,SHA-224]
+
+Msg = 699325d6fc8fbbb4981a6ded3c3a54ad2e4e3db8a5669201912064c64e700c139248cdc19495df081c3fc60245b9f25fc9e301b845b3d703a694986e4641ae3c7e5a19e6d6edbf1d61e535f49a8fad5f4ac26397cfec682f161a5fcd32c5e780668b0181a91955157635536a22367308036e2070f544ad4fff3d5122c76fad5d
+d = 16797b5c0c7ed5461e2ff1b88e6eafa03c0f46bf072000dfc830d615
+Qx = 605495756e6e88f1d07ae5f98787af9b4da8a641d1a9492a12174eab
+Qy = f5cc733b17decc806ef1df861a42505d0af9ef7c3df3959b8dfc6669
+k = d9a5a7328117f48b4b8dd8c17dae722e756b3ff64bd29a527137eec0
+R = 2fc2cff8cdd4866b1d74e45b07d333af46b7af0888049d0fdbc7b0d6
+S = 8d9cc4c8ea93e0fd9d6431b9a1fd99b88f281793396321b11dac41eb
+
+Msg = 7de42b44db0aa8bfdcdac9add227e8f0cc7ad1d94693beb5e1d325e5f3f85b3bd033fc25e9469a89733a65d1fa641f7e67d668e7c71d736233c4cba20eb83c368c506affe77946b5e2ec693798aecd7ff943cd8fab90affddf5ad5b8d1af332e6c5fe4a2df16837700b2781e08821d4fbdd8373517f5b19f9e63b89cfeeeef6f
+d = cf020a1ff36c28511191482ed1e5259c60d383606c581948c3fbe2c5
+Qx = fa21f85b99d3dc18c6d53351fbcb1e2d029c00fa7d1663a3dd94695e
+Qy = e9e79578f8988b168edff1a8b34a5ed9598cc20acd1f0aed36715d88
+k = c780d047454824af98677cf310117e5f9e99627d02414f136aed8e83
+R = 45145f06b566ec9fd0fee1b6c6551a4535c7a3bbfc0fede45f4f5038
+S = 7302dff12545b069cf27df49b26e4781270585463656f2834917c3ca
+
+Msg = af0da3adab82784909e2b3dadcecba21eced3c60d7572023dea171044d9a10e8ba67d31b04904541b87fff32a10ccc6580869055fec6216a00320a28899859a6b61faba58a0bc10c2ba07ea16f214c3ddcc9fc5622ad1253b63fe7e95227ae3c9caa9962cffc8b1c4e8260036469d25ab0c8e3643a820b8b3a4d8d43e4b728f9
+d = dde6f173fa9f307d206ce46b4f02851ebce9638a989330249fd30b73
+Qx = fc21a99b060afb0d9dbf3250ea3c4da10be94ce627a65874d8e4a630
+Qy = e8373ab7190890326aac4aacca3eba89e15d1086a05434dd033fd3f3
+k = 6629366a156840477df4875cfba4f8faa809e394893e1f5525326d07
+R = 41f8e2b1ae5add7c24da8725a067585a3ad6d5a9ed9580beb226f23a
+S = a5d71bff02dce997305dd337128046f36714398f4ef6647599712fae
+
+Msg = cfa56ae89727df6b7266f69d6636bf738f9e4f15f49c42a0123edac4b3743f32ea52389f919ceb90575c4184897773b2f2fc5b3fcb354880f15c93383215d3c2551fcc1b4180a1ac0f69c969bbc306acd115ce3976eff518540f43ad4076dbb5fbad9ce9b3234f1148b8f5e059192ff480fc4bcbd00d25f4d9f5ed4ba5693b6c
+d = aeee9071248f077590ac647794b678ad371f8e0f1e14e9fbff49671e
+Qx = fad0a34991bbf89982ad9cf89337b4bd2565f84d5bdd004289fc1cc3
+Qy = 5d8b6764f28c8163a12855a5c266efeb9388df4994b85a8b4f1bd3bc
+k = 1d35d027cd5a569e25c5768c48ed0c2b127c0f99cb4e52ea094fe689
+R = 2258184ef9f0fa698735379972ce9adf034af76017668bfcdab978de
+S = 866fb8e505dea6c909c2c9143ec869d1bac2282cf12366130ff2146c
+
+Msg = c223c8009018321b987a615c3414d2bb15954933569ca989de32d6bf11107bc47a330ab6d88d9b50d106cf5777d1b736b14bc48deda1bc573a9a7dd42cd061860645306dce7a5ba8c60f135a6a21999421ce8c4670fe7287a7e9ea3aa1e0fa82721f33e6e823957fe86e2283c89ef92b13cd0333c4bb70865ae1919bf538ea34
+d = 29c204b2954e1406a015020f9d6b3d7c00658298feb2d17440b2c1a4
+Qx = 0e0fc15e775a75d45f872e5021b554cc0579da19125e1a49299c7630
+Qy = cb64fe462d025ae2a1394746bdbf8251f7ca5a1d6bb13e0edf6b7b09
+k = 39547c10bb947d69f6c3af701f2528e011a1e80a6d04cc5a37466c02
+R = 86622c376d326cdf679bcabf8eb034bf49f0c188f3fc3afd0006325d
+S = 26613d3b33c70e635d7a998f254a5b15d2a3642bf321e8cff08f1e84
+
+Msg = 1c27273d95182c74c100d85b5c08f4b26874c2abc87f127f304aedbf52ef6540eba16dd664ae1e9e30ea1e66ff9cc9ab5a80b5bcbd19dde88a29ff10b50a6abd73388e8071306c68d0c9f6caa26b7e68de29312be959b9f4a5481f5a2ad2070a396ed3de21096541cf58c4a13308e08867565bf2df9d649357a83cdcf18d2cd9
+d = 8986a97b24be042a1547642f19678de4e281a68f1e794e343dabb131
+Qx = 2c070e68e8478341938f3d5026a1fe01e778cdffbebbdd7a4cd29209
+Qy = cde21c9c7c6590ba300715a7adac278385a5175b6b4ea749c4b6a681
+k = 509712f9c0f3370f6a09154159975945f0107dd1cee7327c68eaa90b
+R = 57afda5139b180de96373c3d649700682e37efd56ae182335f081013
+S = eb6cd58650cfb26dfdf21de32fa17464a6efc46830eedc16977342e6
+
+Msg = 069ae374971627f6b8503f3aa63ab52bcf4f3fcae65b98cdbbf917a5b08a10dc760056714db279806a8d43485320e6fee0f1e0562e077ee270ace8d3c478d79bcdff9cf8b92fdea68421d4a276f8e62ae379387ae06b60af9eb3c40bd7a768aeffccdc8a08bc78ca2eca18061058043a0e441209c5c594842838a4d9d778a053
+d = d9aa95e14cb34980cfddadddfa92bde1310acaff249f73ff5b09a974
+Qx = 3a0d4b8e5fad1ea1abb8d3fb742cd45cd0b76d136e5bbb33206ad120
+Qy = c90ac83276b2fa3757b0f226cd7360a313bc96fd8329c76a7306cc7d
+k = 1f1739af68a3cee7c5f09e9e09d6485d9cd64cc4085bc2bc89795aaf
+R = 09bbdd003532d025d7c3204c00747cd52ecdfbc7ce3dde8ffbea23e1
+S = 1e745e80948779a5cc8dc5cb193beebb550ec9c2647f4948bf58ba7d
+
+Msg = d0d5ae3e33600aa21c1606caec449eee678c87cb593594be1fbb048cc7cfd076e5cc7132ebe290c4c014e7a517a0d5972759acfa1438d9d2e5d236d19ac92136f6252b7e5bea7588dcba6522b6b18128f003ecab5cb4908832fb5a375cf820f8f0e9ee870653a73dc2282f2d45622a2f0e85cba05c567baf1b9862b79a4b244e
+d = 380fb6154ad3d2e755a17df1f047f84712d4ec9e47d34d4054ea29a8
+Qx = 4772c27cca3348b1801ae87b01cb564c8cf9b81c23cc74468a907927
+Qy = de9d253935b09617a1655c42d385bf48504e06fa386f5fa533a21dcb
+k = 14dbdffa326ba2f3d64f79ff966d9ee6c1aba0d51e9a8e59f5686dc1
+R = ff6d52a09ca4c3b82da0440864d6717e1be0b50b6dcf5e1d74c0ff56
+S = 09490be77bc834c1efaa23410dcbf800e6fae40d62a737214c5a4418
+
+Msg = 79b7375ae7a4f2e4adad8765d14c1540cd9979db38076c157c1837c760ca6febbb18fd42152335929b735e1a08041bd38d315cd4c6b7dd2729de8752f531f07fe4ddc4f1899debc0311eef0019170b58e08895b439ddf09fbf0aeb1e2fd35c2ef7ae402308c3637733802601dd218fb14c22f57870835b10818369d57d318405
+d = 6b98ec50d6b7f7ebc3a2183ff9388f75e924243827ddded8721186e2
+Qx = 1f249911b125348e6e0a473479105cc4b8cfb4fa32d897810fc69ffe
+Qy = a17db03b9877d1b6328329061ea67aec5a38a884362e9e5b7d7642dc
+k = ab3a41fedc77d1f96f3103cc7dce215bf45054a755cf101735fef503
+R = 70ccc0824542e296d17a79320d422f1edcf9253840dafe4427033f40
+S = e3823699c355b61ab1894be3371765fae2b720405a7ce5e790ca8c00
+
+Msg = 8c7de96e6880d5b6efc19646b9d3d56490775cb3faab342e64db2e388c4bd9e94c4e69a63ccdb7e007a19711e69c06f106b71c983a6d97c4589045666c6ab5ea7b5b6d096ddf6fd35b819f1506a3c37ddd40929504f9f079c8d83820fc8493f97b2298aebe48fdb4ff472b29018fc2b1163a22bfbb1de413e8645e871291a9f6
+d = 8dda0ef4170bf73077d685e7709f6f747ced08eb4cde98ef06ab7bd7
+Qx = 7df67b960ee7a2cb62b22932457360ab1e046c1ec84b91ae65642003
+Qy = c764ca9fc1b0cc2233fa57bdcfedaab0131fb7b5f557d6ca57f4afe0
+k = 9ef6ebd178a76402968bc8ec8b257174a04fb5e2d65c1ab34ab039b9
+R = eef9e8428105704133e0f19636c89e570485e577786df2b09f99602a
+S = 8c01f0162891e4b9536243cb86a6e5c177323cca09777366caf2693c
+
+Msg = c89766374c5a5ccef5823e7a9b54af835ac56afbbb517bd77bfecf3fea876bd0cc9ea486e3d685cfe3fb05f25d9c67992cd7863c80a55c7a263249eb3996c4698ad7381131bf3700b7b24d7ca281a100cf2b750e7f0f933e662a08d9f9e47d779fb03754bd20931262ff381a2fe7d1dc94f4a0520de73fa72020494d3133ecf7
+d = 3dbe18cd88fa49febfcb60f0369a67b2379a466d906ac46a8b8d522b
+Qx = b10150fd797eb870d377f1dbfa197f7d0f0ad29965af573ec13cc42a
+Qy = 17b63ccefbe27fb2a1139e5757b1082aeaa564f478c23a8f631eed5c
+k = 385803b262ee2ee875838b3a645a745d2e199ae112ef73a25d68d15f
+R = 1d293b697f297af77872582eb7f543dc250ec79ad453300d264a3b70
+S = 517a91b89c4859fcc10834242e710c5f0fed90ac938aa5ccdb7c66de
+
+Msg = 30f0e3b502eec5646929d48fd46aa73991d82079c7bd50a38b38ec0bd84167c8cf5ba39bec26999e70208af9b445046cd9d20c82b7629ca1e51bdd00daddbc35f9eb036a15ac57898642d9db09479a38cc80a2e41e380c8a766b2d623de2de798e1eabc02234b89b85d60154460c3bf12764f3fbf17fcccc82df516a2fbe4ecf
+d = c906b667f38c5135ea96c95722c713dbd125d61156a546f49ddaadc6
+Qx = 3c9b4ef1748a1925578658d3af51995b989ad760790157b25fe09826
+Qy = 55648f4ff4edfb899e9a13bd8d20f5c24b35dc6a6a4e42ed5983b4a0
+k = b04d78d8ac40fefadb99f389a06d93f6b5b72198c1be02dbff6195f0
+R = 4bdd3c84647bad93dcaffd1b54eb87fc61a5704b19d7e6d756d11ad0
+S = fdd81e5dca54158514f44ba2330271eff4c618330328451e2d93b9fb
+
+Msg = 6bbb4bf987c8e5069e47c1a541b48b8a3e6d14bfd9ac6dfaa7503b64ab5e1a55f63e91cf5c3e703ac27ad88756dd7fb2d73b909fc15302d0592b974d47e72e60ed339a40b34d39a49b69ea4a5d26ce86f3ca00a70f1cd416a6a5722e8f39d1f0e966981803d6f46dac34e4c7640204cd0d9f1e53fc3acf30096cd00fa80b3ae9
+d = 3456745fbd51eac9b8095cd687b112f93d1b58352dbe02c66bb9b0cc
+Qx = f0acdfbc75a748a4a0ac55281754b5c4a364b7d61c5390b334daae10
+Qy = 86587a6768f235bf523fbfc6e062c7401ac2b0242cfe4e5fb34f4057
+k = 854b20c61bcdf7a89959dbf0985880bb14b628f01c65ef4f6446f1c1
+R = a2601fbb9fe89f39814735febb349143baa934170ffb91c6448a7823
+S = bf90f9305616020a0e34ef30803fc15fa97dffc0948452bbf6cb5f66
+
+Msg = 05b8f8e56214d4217323f2066f974f638f0b83689fc4ed1201848230efdc1fbca8f70359cecc921050141d3b02c2f17aa306fc2ce5fc06e7d0f4be162fcd985a0b687b4ba09b681cb52ffe890bf5bb4a104cb2e770c04df433013605eb8c72a09902f4246d6c22b8c191ef1b0bece10d5ce2744fc7345307dd1b41b6eff0ca89
+d = 2c522af64baaca7b7a08044312f5e265ec6e09b2272f462cc705e4c3
+Qx = 5fad3c047074b5de1960247d0cc216b4e3fb7f3b9cd960575c8479fc
+Qy = e4fc9c7f05ff0b040eb171fdd2a1dfe2572c564c2003a08c3179a422
+k = 9267763383f8db55eed5b1ca8f4937dc2e0ca6175066dc3d4a4586af
+R = 422e2e9fe535eb62f11f5f8ce87cf2e9ec65e61c06737cf6a0019ae6
+S = 116cfcf0965b7bc63aecade71d189d7e98a0434b124f2afbe3ccf0a9
+
+Msg = e5c979f0832242b143077bce6ef146a53bb4c53abfc033473c59f3c4095a68b7a504b609f2ab163b5f88f374f0f3bff8762278b1f1c37323b9ed448e3de33e6443796a9ecaa466aa75175375418186c352018a57ce874e44ae72401d5c0f401b5a51804724c10653fded9066e8994d36a137fdeb9364601daeef09fd174dde4a
+d = 3eff7d07edda14e8beba397accfee060dbe2a41587a703bbe0a0b912
+Qx = 6dd84f4d66f362844e41a7913c40b4aad5fa9ba56bb44c2d2ed9efac
+Qy = 15f65ebcdf2fd9f8035385a330bdabec0f1cd9cc7bc31d2fadbe7cda
+k = 7bb48839d7717bab1fdde89bf4f7b4509d1c2c12510925e13655dead
+R = 127051d85326049115f307af2bc426f6c2d08f4774a0b496fb6982b1
+S = 6857e84418c1d1179333b4e5307e92abade0b74f7521ad78044bf597
+
+[P-224,SHA-256]
+
+Msg = 2b49de971bb0f705a3fb5914eb7638d72884a6c3550667dbfdf301adf26bde02f387fd426a31be6c9ff8bfe8690c8113c88576427f1466508458349fc86036afcfb66448b947707e791e71f558b2bf4e7e7507773aaf4e9af51eda95cbce0a0f752b216f8a54a045d47801ff410ee411a1b66a516f278327df2462fb5619470e
+d = 888fc992893bdd8aa02c80768832605d020b81ae0b25474154ec89aa
+Qx = 4c741e4d20103670b7161ae72271082155838418084335338ac38fa4
+Qy = db7919151ac28587b72bad7ab180ec8e95ab9e2c8d81d9b9d7e2e383
+k = 06f7a56007825433c4c61153df1a135eee2f38ec687b492ed40d9c90
+R = 0909c9b9cae8d2790e29db6afdb45c04f5b072c4c20410c7dc9b6772
+S = 298f4fcae1fe271da1e0345d11d07a1fca43f58af4c113b909eedea0
+
+Msg = 1fa7201d96ad4d190415f2656d1387fa886afc38e5cd18b8c60da367acf32c627d2c9ea19ef3f030e559fc2a21695cdbb65ddf6ba36a70af0d3fa292a32de31da6acc6108ab2be8bd37843338f0c37c2d62648d3d49013edeb9e179dadf78bf885f95e712fcdfcc8a172e47c09ab159f3a00ed7b930f628c3c48257e92fc7407
+d = 5b5a3e186e7d5b9b0fbdfc74a05e0a3d85dc4be4c87269190c839972
+Qx = 897089f4ef05b943eeac06589f0e09ccc571a6add3eb1610a2fc830f
+Qy = 62ba3f6b3e6f0f062058b93e6f25b6041246c5be13584a41cae7e244
+k = 5b6f7eca2bcc5899fce41b8169d48cd57cf0c4a1b66a30a150072676
+R = f12c9985d454ffbc899ebbbb6cf43e3debcac7f19029f8f2f35cce31
+S = 12fcb848adbd8b1b4c72b2b54a04d936e4a5f480ae2a3ea2e3c1baae
+
+Msg = 74715fe10748a5b98b138f390f7ca9629c584c5d6ad268fc455c8de2e800b73fa1ea9aaee85de58baa2ce9ce68d822fc31842c6b153baef3a12bf6b4541f74af65430ae931a64c8b4950ad1c76b31aea8c229b3623390e233c112586aa5907bbe419841f54f0a7d6d19c003b91dc84bbb59b14ec477a1e9d194c137e21c75bbb
+d = f60b3a4d4e31c7005a3d2d0f91cb096d016a8ddb5ab10ecb2a549170
+Qx = 40a4ab1e6a9f84b4dedb81795e6a7124d1cfdfd7ec64c5d4b9e32666
+Qy = 83aa32a3c2fc068e62626f2dafce5d7f050e826e5c145cd2d13d1b27
+k = c31150420dfb38ba8347e29add189ec3e38c14b0c541497fb90bf395
+R = bf6c6daa89b21211ea2c9f45192d91603378d46b1a5057962dafaf12
+S = cb6b237950e0f0369323055cd1f643528c7a64616f75b11c4ddd63c7
+
+Msg = d10131982dd1a1d839aba383cd72855bf41061c0cb04dfa1acad3181f240341d744ca6002b52f25fb3c63f16d050c4a4ef2c0ebf5f16ce987558f4b9d4a5ad3c6b81b617de00e04ba32282d8bf223bfedbb325b741dfdc8f56fa85c65d42f05f6a1330d8cc6664ad32050dd7b9e3993f4d6c91e5e12cbd9e82196e009ad22560
+d = c8fc474d3b1cba5981348de5aef0839e376f9f18e7588f1eed7c8c85
+Qx = 66f49457ed15f67ed4042195856f052fe774077f61cebcb9efddc365
+Qy = 3a6e3f3423eec7308a69eb1b0416d67cc3b84d24f251d7cbdb45c079
+k = 5e5405ae9ab6164bb476c1bb021ec78480e0488736e4f8222920fbd9
+R = 7b7beaf9f696ca1a8051527478c4c075ab45aa4768937886dbf38618
+S = 93d4cf110a37c5a6f15c4e6024822118539e860dee2f60b8c3f462f6
+
+Msg = ef9dbd90ded96ad627a0a987ab90537a3e7acc1fdfa991088e9d999fd726e3ce1e1bd89a7df08d8c2bf51085254c89dc67bc21e8a1a93f33a38c18c0ce3880e958ac3e3dbe8aec49f981821c4ac6812dd29fab3a9ebe7fbd799fb50f12021b48d1d9abca8842547b3b99befa612cc8b4ca5f9412e0352e72ab1344a0ac2913db
+d = 04ef5d2a45341e2ace9af8a6ebd25f6cde45453f55b7a724eb6c21f6
+Qx = 8d642868e4d0f55ee62a2052e6b806b566d2ac79dbde7939fe725773
+Qy = 79505a57cd56904d2523b3e1281e9021167657d38aeb7d42fc8ec849
+k = ec60ea6f3d6b74d102e5574182566b7e79a69699a307fee70a2d0d22
+R = 2fd7fcbb7832c97ce325301dd338b279a9e28b8933284d49c6eabcf6
+S = 550b2f1efc312805a6ed8f252e692d8ee19eaa5bcd5d0cda63a1a3f0
+
+Msg = 4cc91f744ac858d3577e48813219aa3538dd813b186b42d1e6218376f07cc1cc448ddd6b37240e98bf953f49cf54d65c12878b33c0bf6eb1c60254f0b6fa974f847e53abc56773eef6f29885dfc619e6a48fc15a667ca94001a0c945b6357a53221b0f4b266181456b0d2d25e90708777f1a6f85971c00140c631c1991e0fd06
+d = 35d4bbe77d149812339e85c79483cb270bdac56bbf30b5ef3d1f4d39
+Qx = 7924b1d7f5920cce98e25094e40f2eb3eb80d70b17e14b3d36c3671c
+Qy = 26c5af35f71e61858582b7cc2b41790597c53ee514ffdf7a289d108c
+k = 751869c1d0e79eb30aae8fbfb6d97bfa332123fd6b6c72c9cd3c1796
+R = 26bb1b92b0f01e94eba5fa429271371db527ce857abba13bd1103f64
+S = 836aba9c63e1252c2b2d72a21e6a41b82241ebe32647e7f814652bcb
+
+Msg = 58f43cc1924de4bc5867664adbc9d26b4f096a43aca47c27c52851b006dc2a658919ef9ce5b5ac48372703be15ac51631c2bd84b88f479f113b0569a9a09e230ec1e8e573474c6075284d3e57d973829af35325d9e7dab4a5f9b065155bbcaff3642a82ef4c9b9e127d3575c050721653da3b087d3fa394192897a5519527d19
+d = 2c291a393281b75264c9b8817af684fa86a1cdc900822f74039dc5d6
+Qx = 18cb5826ad60e6696bf07655032a3749f6577ca36da3ccd6e66a137c
+Qy = 194e14820fe02d784fd1363ff7a30399518309765bd3f4412d646da2
+k = e2a860416229dfd3f5a5cc92344ca015093a543943a0d8f73bf2b2fd
+R = 00e300c1ef4a8c4ca5da6413856f8981db49de29bdf03f32ffc3ceab
+S = f250f18a51ba5f63e1584097841099fa6ae4e98ee458c061d1d5aed7
+
+Msg = 113a2806b052fde683ee09453098e402204155afb3776fd1cad3a9103421d327eab8f9ec0dd050ffcc83f93b34ea707705fabeccfe43ab1a71c95298fd3ec769d99ead1066950eee677d225816e0faad19cf69e1b35d16771689e2092cafe16d7c0dd7b0db73fffb8d0f3eaed83004dd21e753530ec939c89ba25578fa5f785b
+d = 831ea25dbeda33d272a1382c5def0e83929170ab06a629eed6ee244b
+Qx = 076518e393940d42dfd09819409d66966d8c9189c83d554a9cc8a082
+Qy = 44d0ceaf4c0f50e46bea4a52e30423ce3ada19edd363ac5694c65cb8
+k = 6be6dd9f6a083915ccba54626caf12d246d3aece0a7eda7d8d85599c
+R = ff1460946e06fb6f5d35e8d2625ca70ffb9b45308e3fabf6ad8351b1
+S = 6029aa3990918e8cb8a388d53b0772e5cdfff49c3405fe0d3a95933a
+
+Msg = 64cbfc8f2e2149a31b3e8a80c4a552f6c62aaeb7990b6e0ee55500a9d17be04213406578caf315951086dff5c2af3b5ce17d425d185101ef26f86396ba3a129a4f3f8e2dd595f59efb6c0f5c2dcc394569d7268695e9ac7daa84203f1f1895f1f9e4b514a5c9cd23baa63454710144fe735ad9b8f42d8c43267aa434a26d7e5f
+d = 70f74c7324ef137318b610ead8ddc5b964e0eed3750b20612fc2e67b
+Qx = 279649e2a2918e683520cde3fc98b0ae58a7100e8de35e7c9cc797b6
+Qy = aa4de6be34be61f02880139787b9038f4554a8ef1c994b887c2974b5
+k = 8e984864f86f7a2a73f3edda17dbccd13fac8fa4b872814abf223b1b
+R = 3b18736fa11d04e27e2614cda03a63ec11a180f357b0b3192920d09c
+S = 2f0f3dbd570727b14fbb29155538e62c930dd51c4035275c1365dc60
+
+Msg = a10a11c8e30fff118d371daf824f16c08200b83ea059436466a4611ccac93b2dea2de8c1006f946196aef7fe9b0c251a391b0340f21797798278b412ff2b53842eec6450728e2bca062f8337a2c204b9ea04ff660cd4d4db559f2f11c4d8ef199021339fcc82396f7a93926cf5f247e37d8067fe50692de54f102bd5ab51925c
+d = 026be5789886d25039c11d7d58a11a6e1d52cb1d5657561f2165b8a8
+Qx = 3fa617c50b177da1a2bdb98b780ad21ad1195c4bd24465f6187de3c9
+Qy = e3fd8d8876dfd03a4a4e31a1acad3a08d983826d286c250c4e5620c1
+k = 0128b8e3f50731eb5fcc223517fc0cf6b96cd1d2807eb4524bc46f77
+R = 3a6b633f96f3d0b6d54f7fb29ac33709e4f0dd8fa0e51606ed9765ca
+S = 63e8c119dfa51784decd864f6911f2210a80f8f02d472d88df10d119
+
+Msg = b3f720bf566ffa369259f4361959ae0641d2755ec264a4c4349981df2b02563275b2b9adb5aee47f7a456760a971991ffed6b17809bb9694138d1677fa916123795239353158fc6b22d10f20d26f5d2dcd8c56c44373eea5b93067dba2d7c5318dac2e9e8714873cb1b37f58c011fd14fa1e535554efe05f468bfc8e11cd8b99
+d = e79c18d935c2839644762867aa793201f96a3cde080c5968412ce784
+Qx = b7ae1e992b1c7fde1141f40bd913358538ca0f07f62b729f13cea327
+Qy = 811252d12120e04805fc171a439d382c43b68a21e1a0bdf5e4ec1da4
+k = 7abedab1d36f4f0959a03d968b27dd5708223b66e0fc48594d827361
+R = d35047d74e1e7305bb8c1a94e8ae47cb1591c3437a3e185e00afe710
+S = d9c425c9d5feb776ac8952e6c4eee0ecd68aef2f0e7bff2e49c9185e
+
+Msg = 0a398a46df7ccc48d1e7833f8bbc67100f1ef77a62dc78bbc115b2a662f9591fbaaa91ad3d788e2fdd1b3164e45293d4f5686c151296901768028ac80ded4bf89c647ad35f0c7c4cb318c0c757c1d83c44d850e5fd4677281b3f13b1ee54de79c8c042813f9d3312dcc6111a68299cb7e829557d7f3d96e702f65aefc6499415
+d = 0d087f9d1f8ae29c9cf791490efc4a5789a9d52038c4b1d22494ad8c
+Qx = cd95cf8fb1cd21690f40d647f2353672a1076cc6c46bddaad2d0fc56
+Qy = 934262f74d9ee0f8a2754f64cb7415923d64bf00c94a39b52803f577
+k = 557d0e3995dc6377b3911546dd7aeaeec62a6d8f2af6a274382fc37f
+R = 56df0ea6afdcc232ceb41729eec00cf906b69b6e28423a36d3c92cc5
+S = f4f70fd948c9a147f55317fdea7b8a84c33e721014552d5800d63edc
+
+Msg = 8c33616821a6038b448d8918668977fcf1ef5aa0cf7c341837b39bbcc9bca875a3757f4b392630e9995b9bbe4eb66978b877586adaa02f99d2344dae082a7603351d8ffcfca081ab403cd0acb90d078dd1d0789c2eb3185c62bff2d9f04cd38e509e3b83c12ed0a5c6808fc42f7ba5b06acdc496c8ad9be648ee6a4505f8560f
+d = 0830aebb6577d3a3be3ba54a4501c987b0e0bb593267b9bbadb66583
+Qx = b88652020e083ccc1c43dc83d1881884dd4c7e3b4e3460b344b1ea64
+Qy = 22b69b517f86d7c26dc37c0f8feb4bb07fe876149fbcc3334fd2805b
+k = e4f4a3280574c704c2fde47ca81ec883d27f2c5a961a294db7cda9d2
+R = b30b8a0079d9a134b5e1618c2ac63e3fbe0e95866b9dbc5f423f2707
+S = 3dc36746610271ef66e0aa52cc2ccadc5c9b08dc769e4dc4f6538c11
+
+Msg = 94d56535fd4edfe67a0daa6579f9d53bf6b7b8830ae2aeb62892ff59f18756ddf2811b449c7d20d65d54f8507de4e7c50eaa084830637812aa4b250a4d61ab67845be36e4a41cdc0a70f8d6e3a63d4514f0dc197e6486015046a316153d5f3a3a4a0ae1ed7ea5fa55e12e73d333333685c02e0eb636234ea7e6d4b76b4b76b5a
+d = 2acc9b97e625263e8e4cd164302c7d1e078bfcdd706111a13ccda5b2
+Qx = ce1a06f82df874dded37cca03b56c0648e4e8917ecd40ee73ee61588
+Qy = ceb6177b8f1ac7c5c6e6e1f7737cc3026952ee392badd2cd7af32f9d
+k = e401fa80f96480d437ed4f61a783888062ec33d530b188fd48016a6d
+R = 28674f447c4742e4087bbccfb522fbad4e18b56031d2ce8f532b078a
+S = a5a7a13d15b423dd17771f73cea98d89dbffa846cc209b45c0e29b76
+
+Msg = 5d8ebdf9eb28b47bdafaa36bf0b66a9eaf99b6c83959da4f2b1151b4f4ecd28fb115a64c0cb9491093a7e9b9c53ec423e4c72e7765bb9c818da0e8c428667e44474a71db4867130c77c40bfd8544b2d7b9d6464d2b8e6a48482153256a32437c3a747231f51134dd14c703407e31146a6fcde23bededcf16950486e90ca69ac0
+d = f4e873d4fb944fb52323406f933815092b7672221de4d1c45917f3fc
+Qx = 0dc2cdddb990341adb1de73f02d87fc3822485a659a15145f4251d5f
+Qy = cf78b2a83c7352eda1af2c74e1804ea04b35f76c04e89d90281dc2bb
+k = 5d1476c682a64162fd2fdc82696fc8cab1469a86f707ea2757416e40
+R = 82982b38ed465138df4018d7cfb835edcb591cb57446ca49d163782b
+S = 8ef1d7b326cabee7f7ab95b7b98d3c27a069c0fd95a1599c0ccb422b
+
+[P-224,SHA-384]
+
+Msg = 25e4416695f77551fdce276355528ccf1ddc2483821c5d22d751d50111ca2fadc6593b52c74f4b5957494f1df25b0b2f86950d0d19229ec6506fee8581d2dd09d48418b146ff16bd84a17ca0dc83b1888eb407376da6c8a88fa1e60b8c2a2471dfde4b3996ef673d5bde3d70c434dc9f2488e9de16ae657d29e5e59ec922a1ec
+d = 62c572ee0d6f81b27e591d788bfc2f42b5105d2663078dfb58069ebd
+Qx = bd6ba605639b98fa8113a16a3bb004ddfaec901c98a931206165f4a5
+Qy = a3190b10ef39e88abd60b2293b4707512b45c6c5ed5794cc11454427
+k = 0f0bb1e428bcdebf4dc62a5278068efc0f8ce75f89e89b3630f102b2
+R = aac0ea27e129f544abcc77f110e70bbdd5aa3e425dc39d5e8887025d
+S = 10e5dd06aee6b8419a04aa33d9d5678b0039c3acc3c4b61fe106bfdc
+
+Msg = 9164d633a553deccf3cbd2effccf1387fa3177cd28c95d94a7d1a3e159c5e5c027758cc26493301b2f4d141d8d07a5fe5fead987ce5f30abeafcb48c302afc6c2309f0e93d9b6818cbb6972d222cb7b01302dfe202ae83b89f53150ae4a0e2b8fc0fd1091f19b4ab2e6ab213ab322d04f2c5f57113bfad3c5675227237abf773
+d = e2f86bf73ba9336fa023343060f038e9ad41e5fe868e9f80574619a3
+Qx = f5d5346f17898ea6bbdfff19c216a8757a5dc37b95315f5481628381
+Qy = ae61fd172ac8b7a4f13870a932dece465834cbd4f50bbcfb802c824e
+k = 35724ac043e3b44b73b5a7919cf675190306d26aa67c27c28c873534
+R = 535147c265af138eec50c7fb570bcc8d2e6f675597b0fcc034e536bc
+S = 743812c188a1dddf9fb34b90738f8b2e58760d6cd20ccceb1bb9c516
+
+Msg = 019df05929321ecea7ee1de4f412aba1c8d3c24437db04b194a68a0a59dd871be10bd3a4be6edf551350ea49fc7155a4d887e1221486291abe77a30633a4c4f7868fe2df24311cba0c73804883954460e122387ed414111ff96ff1aebac8b6a6491d8a0d16e48a63bf3d027c0f68ee4a4b234d73b412196706af8ea022b4dcef
+d = b0a203438e2586d7575bc417a4a798e47abc22aa3955b58fc2789f17
+Qx = dc5d217862a1e5b00c95affa9d8b925a72b9beaeb7a86dc397e788d8
+Qy = 5f05f8e976ae1eb1036eca6d683a82850795bf9127dee5f8b2859445
+k = 408e9c8b1f33136d6ddb93ff3a498bc09d4eee99bf69cdd5af0aa5a2
+R = 1b5a964c8b1fc634c6e2b82322499df1d7f0c12a4d2a77723c816ab8
+S = cf54599a36ca064fae0aa936de5266f87704409d22a15d28c01b7f2a
+
+Msg = 5d09d2b1d3fa6e12c10d8b26dc9aabc8dc02bd06e63ff33f8bb91ede4b8694592a69e4ed4cdf6820069e2b9c7803658949e877ffe23bf90bcf5ce1409c06c71d86885a94048b05ac0ec9db193e489a5a2bfa367caf6aa8ecdb032be366174343f6875d2fe1785e8d77334f5f469cec64998e08d3303e5c9a1923b34fdc105d65
+d = efcfa50fad6fb2065f9a55f28c0c42fa24c809ccb19b6fc6d8ffb085
+Qx = 61521a0cfb72be77ba33cb3b8e022743cd9130ff49e97093b71aa178
+Qy = ce0819aedaf6fce639d0e593f8ab0147eeb6058f5f2b448231584ea9
+k = d1eea821f286eae6ebc1f61b08f9ad4323a3787e94af4c32cd31351b
+R = b37caaa71103752ac559f9eb4943324409ebfa8b585f684dcaa5c411
+S = 7c28e7619e2944ab4b7be022878c8052ebdf2cae5dff4f976c49686a
+
+Msg = 50f6dfc81c6cf189e0a310f992907fe93356cee9dea9a41c7671a8daf3f4cfe0c459ce6122c1e731dbf7593419d7114cb73b46956158a982c5d52c72f43f0f822046093c69aeff1f7e4cd8af00ba655c5baa2e7b6a400b4be1f6fd51b3e4cfb35a69c80a28c5cafb771b6c2e52e0aeef0e3fd045e8d40745f3f8b74fd969f816
+d = 61a17816937987764cdc064dc7b5b4f5b16db1023acdfe25902957dd
+Qx = a7e975c0a8f87c683bb8e31bc160843a7b69c945f4850bd60e1c08c0
+Qy = 8930a454dcc2aa13bed7ea89368b2c9d689d816b2acf4e52585ee9c4
+k = 44b1fdec2629f9075f89c134ac28ff19bfddaa9db02a5d7f853582b4
+R = b0f5635d8bc9c53a1d54a3ec63de59ed66e6b2358d4ab79755414326
+S = 67c68fe265c7e5aba4232deeafb88545a2aa266fb9f2c2bb3f3ae8d2
+
+Msg = e90129ac6672c85bb7b6b18e9dc199c96c81fd65034b53c77818364d512366fb9cd1bc7c82404c451e561fc1ed916c0948f6ac561b33a1ccca093f07684b8c2bafa9e966377bd208556018a5bafb9edcecf70498c7140fe9c8cf3ad8b8c3b0aa489df797944465047465415bb0e24333235fcdd59a98829a3941eaaf62033e82
+d = 79d5367314ec664aa0f6ca36f95549502a05bf8400bf532d669fab8d
+Qx = 3191f0237102dac159032ab2dde53cf56c9ec827b5caddfe9e83c02a
+Qy = b496b1bdcca4434ac0d0d91ea38ff3bc33f9f54095bfe17796d5a9e2
+k = da529c52f5cc1f435d873109cd991d6cd7e1631d9ff1dd9521dd5db6
+R = 8e0ac63903f4921755430572c3f08bc272790639bdf1009fe2a9a714
+S = 6278c841a2d0a270791fe54b36c49d426d67907aa4e4f59c8638ad97
+
+Msg = 3c9a483c9bee33b601549c592a82e95b4319b1e74b777877f0971bcb4273716b268e8f99f876e42f942f4cf08284896bbc1ffbf094ac0956c3cedfc3580cffa8c74fc6db29a371f2da2d05edb9185ece741fe0d3fabfe9d5b4d373755ebed13dc6840cfa3283b9ea46ec8b95c434f253ae86998182e9cc0e95ee64f323fc74b0
+d = 1320eedad4745121793a7eaf732b0b4498f7cb456cac8cf45a1f66f0
+Qx = 9fdd99906ab77fd29e9021bde947d05a7a9eb153612269bfb0899bc9
+Qy = 681b65b9ac8e4c2899bb622dafb253b7bf5a6e38e5f6595f997c291a
+k = 66ed8d8934633f4125f593cf1b1d3745c4db1f15dde60cf46ca1c7f2
+R = 80199485a3a96447b39f7679cd47412a78675ba17dcbd10465dc5b48
+S = a251fd9f136a3cb0dd0bc80659ae032e4a761ba7045da0034553fb8c
+
+Msg = bfc073fdda63c5fccaa0ca8770c293e8154e7aec56128bbac4fdbd541d602216ebf7ca1e02b514d6e396f20683802ba3f334310a9226576926e3bb19ceee27738d13377cbafeb09d091043501702a07aa31d1f29d50ddc55adcf16ffd40578e734a4e6cb6535f26ad48e0c62ad90e79720000e87d419e92dca3e11f943655b03
+d = e18821329447d3f65ba7279e96bd4624ffa1b32b90f6e8331b1e876d
+Qx = 46c9ed837232c47022df2f1a1578fbe65ac9f2e81c98a74cc22ea31a
+Qy = 6fc5e9568ae62b31412a0b0b367242e9fd7e518c83aa06a069e1d90d
+k = a4c1eb402a2fb3af26e0e14a3d2fc8ed3bc1a8b2475270356a79fdd3
+R = d478b68733d8ad44be46766e7b66af782fbdc7ff7ed0b191176da98a
+S = 5eae9160ccf71fd1d359d89cecce72ef8afaeee2365f6ba828aa450a
+
+Msg = 08079955d1a1f33728128c73673ec9f21a6ce138dcab5adc4dc068e6ab57314b9fbd8b013123b2fdafa9524fbdd0288777a233de8055cccfad83046ada6a19f01c47817496667bba8fc8b9456fc0e044a562d931dab1adcb66af8b66325bdf28d83ded3e2937958ccd19da540d70ef2c189f55a506c9c0d63406394c5bd3823b
+d = f73e030d5a696b358986d3efaca121cf71f775f8835a21e6135145d7
+Qx = 9ca2c6ea87ac8dd3a23a5b4010841a7c8af309038882ae44634bcf55
+Qy = b0a347dbd5ded3b8702ac5a457e8b32bd4de06fd315095fa1b7d5fe1
+k = e3cc786c1288ea567836c51d6d69dd0cab5c015987d936ccc3a4beb3
+R = f1234da71761b7a0f49e661a419d2a739bdc4544bf87690e3d2f96db
+S = 096d16bf8020c3d3c233894ad8eb81206010e62c6e692a215e088fd4
+
+Msg = 23900b768f6cd42b8a8df0dcbc9cb5daec8de36b9d5c619adcc1ba2b649103d5af123746cdf19c3fd0665a6fb9338156182aa06181e3c6e37ce56979612af2927440424f89cef43fc754854b8a5c43370808cf5f9929cf47712512ce2f8a2a20d2e9f568c2848b27dfbe09142843c83905ffa5da3b15501761b03dbc2c5398b6
+d = 7a0789323f8741c157a1753ae165ecaf8e8b03a60561f8b80cee467c
+Qx = 101271a9addd4bd1f19d00bf116c8524f52cefd598e85dc381597acb
+Qy = 2f17d14f4d8ccb28b216553718152ba7c104646d8eca986dd9ddea39
+k = d169f04f05b60c625cda864d187938863964dab7bb3b9dfc04b05519
+R = e4a51be686a764b709da23ab48b1985e153c6ee238d945e743907afc
+S = 118a8f1ffe3cd556ce6345bd1a398dd9cc3729b7fd6d8af9bfd82f40
+
+Msg = 1eb28c0bcdd18f73e347f957ece15b4cc83a771b0877e1feaac38e24028fb38ccea8b54ee017dc7c3d5a1327bc6f40b294aa65d7dc487f278846cd101ee84202f14b38aa2c275046aa2577f65ebaea41cd383e8def2fd0b4444dcf426fa75c4082cd7fa035cdb1e0d34a3c79d42130f5b0273eae75bc701dda3aebe7358f41b5
+d = 78e795d0edb11fd9e28dc26b21e751aa89bea0d87932ef11c95c0e18
+Qx = 9edd544107977134bf6360d43ccabb3c94d627c03963c0a04b439627
+Qy = ece4c61d319a0e41f3de7863e7c355bac94395aaa74cdb5f74a87a5b
+k = 36f7c0f76808b826a0a974a1fd6e155e00a73f1d34674a8f88be405a
+R = 3e319444438bc2cc92f323ea842cb402b3c3c2448c89869ef7998edb
+S = 3420cc38f058f41c31e71f4b1ad488f801111c73541de69fcee60695
+
+Msg = efab51855407438fd5c250670366bca3c026ecec4a59394f00d8a4b51746d0c4564366656d507e3e13e62fe7abeb976b8859895848dbaecf6582f1898ea06f00d4247702ed9721bd375aa83ae4c67c2eaa6e080777ea5ecf2cf787d785389560ac91cf63a52f0373c3185e18a3b8a466e21b61a239f1b77624eb1acacc76c4e1
+d = bee02d8bc5bffb3fd3b4c9d6f686409f02662d10150d1e58d689966a
+Qx = 8848f964c847fe9dddc774618d4588c9cd56bbe588d7b1fb369c8bfa
+Qy = ebbb699fbd0dc08859fe9132285fe20dff3b9d561c0640b6e0717607
+k = 59f1450d857b40e5552a4b8cd4ab0df2f01716635d172c1106840f21
+R = a206d8398a16a991bc217f77f23c6f648384f254f255a8a876404444
+S = eb1169cb5b1423dc0bfaffe565ae57f986e00de06405e3e7b605862e
+
+Msg = 31c29ca10279a417f0cc9b1382cf54dbfdfc89f2e6ef08c403c11f580cbf8674b141ed1a417563282d99a55fc616d836421cde9424815c95e7fb7668bf3f137b29937f14882d74e034b732d78d91af7721aac4950734f5fa5d4b4d35534974f8cab6d2e6dca75ddb57e99148c8a59df9fc5bcd723e546e8356f671cf2f65640a
+d = dc0ddf6e501418bb8eafc5d7ccc143369e2aa441df8fc57d5f94a738
+Qx = 063a5d632f4144376e14cfb03ad8ccf1489b613acd184d20dff66545
+Qy = e77727f057b043d8a0f7458196b72e92d11f85b0891c6aaa9d915f58
+k = ff0e5cae2671db7a1b90e22c63e7570bdd27352d45bac31e338debe0
+R = 5bc0b4998481ecbd3b6609184a84ca41d69b08c37138097f559259f8
+S = 0df8828eb1ca85e46405b94e1a2972c34c5e620a54e2f640f04aecc5
+
+Msg = 8db476f92e332519c1a0ece5d8deded6efbd2d8e8784eea0a6b4c3b4296c35f5f8de4317e5c1627b91fb1973fee86c06e4992aa5a20cb7475c8808ff1da354d07a488dffa7838c6ec1e3f99e3acba831f27bee8434eeda3eb36d0c6df3658883cd40068b1bed841310f6eb38d4a3d07d85848770ff7933c054cd8b34662660b1
+d = 229d89b2fcf8441ffc95ebb2ac2ef156e25825782044b2b8bd6a3e01
+Qx = de616848d8044a44789ef1ba3a6dd66fe9257ddc57f7534e59a701be
+Qy = 26cbf74a6d25e5b34b96d30f327abd574cff7f7dbe6686573a7d6c5c
+k = 3b18ca6ec8e8e255ac88f64302745ca0b73ff94b2b2d48be95b4aaee
+R = fa94fd8b827c06115c1eefd50afc02ce5926ee0e789667783c01c34b
+S = edf766a66973cfc33e4159966c07321a7f6549c3c60e8586ef41402b
+
+Msg = fcb272c828fe8fd3c6f8de9410c7b6e2b36717c1b0e5e359e9109bd7fc378978aa98182a9d99961898ed88999b050d3b64d1457d7a899d6d273b9f4dde2aafa36d76329d62509043c338f265fc4c7d938459b7fa3b230a9f6cb632b61489546bb4181a5ad7f0d7369b8caced48eb374b075b2b325bc86add0f3b680cd9e80acd
+d = 97d747068147c0393a0bb5c159e2c9f1bd538f6204823294883abe28
+Qx = 3858a576eef2ce24d01766997fb81b3f3f78b6104cd188610be221d7
+Qy = 95ffc677ac7bfe3e0bb4cffb17355a964c8356a807151b3cba5d1f4e
+k = c1a2ec1ef16cfd5107c892790daefbed061be78bd8576696b60f64d5
+R = 18c908541843fcdac99b9ff6bb397f3f8094d16b42670216e4eaa2d7
+S = c107a8a508ff57c5d4f78f86cc37e129c864d1c44ed5e73909613b74
+
+[P-224,SHA-512]
+
+Msg = 7522492bdb916a597b8121f3e5c273b1d2800ef8c1db4f7dcbae633b60d7da5193ba53a63d7a377b351897c3b24903ae1cd1994211b259be3e6ae2cbc8970e4957fdf782c7d1bc7a91c80c8ef65468d4ef35428f26e2940ae8b0bd9b8074236bf6c00d0ebe83f9ddb2ade0f835138d39f33b59f244e0037c171f1ba7045a96f5
+d = ba5374541c13597bded6880849184a593d69d3d4f0b1cb4d0919cbd6
+Qx = ac635fe00e8b7a3c8ef5655bdfb7f83e8532e59c0cc0b6534d810ffa
+Qy = 1d067aebeba66e79b28ecfe59ac6fdf5e1970dc3a84499c9d90cd8e2
+k = 187ed1f45c466cbafcd4b9577fb222408c011225dcccfd20f08b8d89
+R = f83d54945997584c923c09662c34cf9ad1e987da8bfd9be600e7a098
+S = 4ff2dba9dba992c98a095b1144a539310e1a570e20c88b7d0aa1955c
+
+Msg = 61097114ff855c3e34a62d9b853f8982d35f29cfa4a89893badbca7849e5fb437a1a38d6451bf0ca5a0d528e352b8e4b57f2ea359a7fc8841d49dd3e570f9b016f14156b0bbc4be822e260bd147ec081454969e11cb0034b7450ef4deb7ed6edb977e2f4ed60121aa095fb0ab40240dc329ecc917f5c64b4410612af065ee9dd
+d = 1e27187134d0a63542adf4665fba22f00cfc7b0a1e02effe913ceedc
+Qx = ecaea8ceea55c3bd418fd34a4ff2499e25e66a104eed846bc00c31d2
+Qy = 3933a356ab1f2dabc303ff0a5d076131e77032e6f502336883bf78a7
+k = 34cb597deae9a3b1cada937abcd247161b19b2b336b20e2e42ae01f1
+R = 58177ba46fb291490b39368774accf72736412c1fb5ee0f27b9b1e02
+S = 58337d78b95a080bfcabb5809bee012501b4da84b8ef310a4628f11c
+
+Msg = dd09ae6c982bb1440ca175a87766fefeacc49393ff797c446200662744f37a6e30c5d33ba70cbd8f12277fd6cc0704c17478bbab2a3047469e9618e3c340a9c8caaff5ce7c8a4d90ecae6a9b84b813419dec14460298e7521c9b7fdb7a2089328005bd51d57f92a1bcbeecd34aa40482b549e006bbf6c4ce66d34a22dda4e0e0
+d = 0905b40e6c29bfcbf55e04266f68f10ca8d3905001d68bb61a27749b
+Qx = d656b73b131aa4c6336a57849ce0d3682b6ab2113d013711e8c29762
+Qy = 6328335ffc2029afbfe2a15cc5636978778c3f9dab84840b05f2e705
+k = dc82840d147f893497a82f023d7d2cbf0a3a5b2ac6cc1b9b23e504be
+R = 583af080e0ec7c1ba5a491a84889b7b7b11ccfe18927c7c219b11757
+S = b23700035349df25d839f0973bef78a7515287de6c83707907074fa6
+
+Msg = 37a73e2774d3b274db426c89b945696daa96035031f72cea01894b24508c7f81961ec254d36ed6a0f448e11cf7950af769dc6cd2c47e52c6caf0ea92c270974f0214b4db436c36a60fb722060a6bb544462a82e1714f5906ec32886f7d59ebf289541c3a00ec1e004892ef2b1286a0194f55d083c6ec92c64b8fd1452e1c68ba
+d = afbaede5d75e4f241dd5b53220f3f5b9c1aa1d5d298e2d43236452dc
+Qx = fe83e59fc8ea8b939355d3258fe53a64d45f63031a0716b7cc416173
+Qy = f151d23060f1c856eb7f1f58be72a7228c3af89e43b56e9695b558c7
+k = 0fbbe7b40136c81a8fb894498d5502157a1cf5a89d0643de92cd38f6
+R = 24f3f457c7b72b7e759d5a8afbf330e31c5d8d2e36f92c0e79c5d87d
+S = 36fd1193def34f12a960740fd79fb38bf2b480726ccad540eb42cdf8
+
+Msg = 9dc2046ffdc6804544db964481abe5d2d276a2a9eeec4c7ad40215b1de23561d402db69bd0f6eec2254711eea4487c64d9a6b62c3ebaf5ffa8db6e7e3a6e17154d126967a47a853a6f8339bdca9be306a13c7f992ded7619b0da59909a49b1e0930360e05b47f18628a36d69b2f87f2bfddd6a5d4a72f84dc76dbdd43f3a6a35
+d = 950b07b0c2b7539a21b5135bfede214733f2e009647d38d8b21d760c
+Qx = f43d13bbfcee3b724063b3910fea49fd591b81e86fdb813b1a492d0c
+Qy = 6b4c8d6fa5dc661889e3cf5ec64997a78222837885f85d2fe9b684fb
+k = 83e110d0d1e700d2f36543028737d2a2f1474aa3b4b28998a39e4793
+R = 2685265bc878e85d10ab13293dec190881a57c4a467f8fc2170432ea
+S = 80a347bb49036522369339bd6485a967cdda818915d8eb947302fcf9
+
+Msg = d9c6847fce688c5e7525a1098b545cb6c15dcd21a02761fc82fc664372a667390680135f91c01a2fa5430c634b1a6d1cd6002d8aa021e7bf5956a7901c2f81bc25d502ba5f55a55f30c0323dc68205cbefec0538e68654e7b327ac1743641896c3e740d8f66f400902b304eafaa4e0d8cffae140536f0922444cc3216a675697
+d = 015bd9f5dfef393b431c3c7fced24385d861ccb563542574a5d2a9bc
+Qx = e868690641e2cda13b289a6c5d2fb175940396044d9cf27b4f2240af
+Qy = 4c78c9abdf2b7fc67ed4497001d7bcf1daca1739dc14a661f91d7c40
+k = e2374350f47c08f3c1359d4edf87e61d1ba4e7dd1540d8d9062efa79
+R = e12dc088d2bc032bb214c77d0e0fb749fc8e61ebe1ed72996f1084b6
+S = 0ab58aa31e0bba5fbc76855e6549f1036fba0a589aeab978ab01b8fb
+
+Msg = 69df8a01b66f04930efd2012ff2243874f256ca8758145d2a9e4ecc84d0dbdbd0dc494ae06db0ccbe819918137c90957114558580d6623efbafdd342b38dad9f08708084d32f874fba04782ce26aaab78de2102ad171f8a8f2b30b5bd3d55fdac5fa3acd6f7def7e61c2533938572b331ba6d1c02bd74bfdbf7337ade8f4a190
+d = 0a3c259df933247445acffb6d8265b601d597fb9997dc2a1eb4deef4
+Qx = e67f4385a9da54253cc371ee9bc6739ae6385a4b87669c7baf0c460d
+Qy = 2bb00b6ddd7b67d9ac5653ec04ca8529fbf16f815c04da3c2e58e82d
+k = 8bf5859665b6a23e6b05a311580f60187ba1c4ae89e44877fb48af66
+R = 653675fb993c3fa9e57b32e33029ec230b966e8077c72c1ec90ddefc
+S = 792723bf87e315147cd4303de7f1dfe95cd7658ebb95c38c1a196140
+
+Msg = 927524982b8d60777c1105c86fac05f634abf58c73f84fb95d81ba0b86e1e43592c4fcad2e395a40fbe7005697d86088e2fb3bb7287eb3f917d4f2dc281f5cbe65d05b4f9623bca849b10a03beca6aa2056a12ebb91cf257ac448c5e9a78f8349a6a29b17c8978bef43a443cbb8a149eb23f794844fc41693f2dbb97181444be
+d = a1c8ef463f9e7e3dd63e677412f87cf9ea4ac9a6a2dae629da5b9916
+Qx = 400e5cd4b315ceb309545cd3277acb70bdae2073fda6ad896ea14b27
+Qy = fbe1d2466cd2e116f38248bd5cabaa6cbe6c4a2694d998abd7b0c991
+k = 82f55a25d3ed6e47c22a6eed0fa52ed0818b87d6ea7950281dfefc09
+R = 16305a46a3f6f9e216ef8f6a6f5f0760d064a885657c864e1c1ea035
+S = 58fd97050bfbca6f87e64e1458c4ad80bae26e280356da344ad3b25d
+
+Msg = 5f9042283561e7f19a436d01c7ef5a950a6d77ede5629cd7e43c0a5d58e8c5673c37945a453291d12938253c71dbe12c8b022ba7276eda6be034ef5ec1ec77dbd1e08f0d7b8e7725b7ec671c075e008a20f77f4ab266f97079b0aa6337df59a33b881954084057b21f294dd14bcb0869a4a6f1f597955ec7bf9d19bb3537a66a
+d = fa511dbf6fef7e5e9c73e4555eb75d435f7884322d9faf5d78cacc0b
+Qx = e8dccd706c31f895f2f261ab979cbab51b8ae28196bcc12a42046380
+Qy = ec246be8e71ea3859cb717a59990fe22e4b76858ff49becd70739a01
+k = a37d665fe4314aa4cd03eb8e6a1f366b43e11fdb419c96b48f787b62
+R = 05e4909bcc172ab4140be291aad4660e375032bce2d762b6269ba764
+S = e347a1c9d3670690e1d8d1d4cd9579848f442199c10526488da5cebf
+
+Msg = c2ae5573d3bf396523bfb703db8502fd0760cd1be528f6ddbfb95aad399e0b19f3bd9e0fabdb05d49e3f893dffec5b627c9c2f7ad5f32e92e4e27a38cb5c28657657377fdfa1b66cd7ac3d15c6d49df92d284db99f69744f37dc7cb4e7d52920fdb200a7942623a7057ba82e467dcccaa5da416b48510d8364446a6a5e2a5aa8
+d = a58bd53646400a646f0e4208320dc679a9664d1c6bfb27fdc8eac7ea
+Qx = e22e0dc4ecd96eb0071b72ba4b4988bf784f3fe73cb81bfb93d9ac4f
+Qy = b3e213e518bee1367a4fb3703b9008bac9d95a1fc4aa61225fff9f3c
+k = 42c5b6f87d3bb1ed74f5ee8398d8f8c61e9e50ffa7a1da12d39893f9
+R = 5c0e5c6f057de1e99ef5d237a60d7a07fa9a42b120a82f573d9fb7b2
+S = 2fffc0bf550bd2f650fed085a84501cacfa6a1bb984df1f9237eaa59
+
+Msg = 03c1a1cd30a039d0dcb22fee2450a7fa79495a0d0f4f43d2de4d75bce003c0334a8860f5c164dbd94888a9f751235a3e570d31070e3e1293a7be616af7176600585d36ac013600157d2569d491da4b8a3bf3630c26e0b9925412189f50b0ae6f04c86477932e2ecd8c3546106ae1ebc684cc3adb27ed665eddece886adea4ce3
+d = 64bd4452b572cc95510ac2e572f41136299ff17f6e8448f4ffb571d0
+Qx = 92521fa25c2e034d127e0921efdb167f0b2ff8b20504487ed87fa264
+Qy = e72c770e37375ad7dc2c4e63e5701826f6606f6ffb9461ee61b4e872
+k = eaf76ee4d7e00d13d8a6d03dffd07ad9a8bb6dc8176c9f93059b1b7f
+R = cf5058e2a6cf5e61a138b013eb292f38a1b9f07239ae5941dbce8919
+S = d14198621650d985d270bc997da6e78588fd0ef843b874c66a3de3c3
+
+Msg = 888f6d9bc7c86c0079fbfd42d8c08d6958f40f6e570fb0b1f03d2f8f8a63df4fcc87b379a222cf835820a999d34996e08961f13b86b075e7fd1c303cd3baa44de42168561589012f7e5300da4f8bdf470c07119a5d9f7ba7293568cd7c6a1b7fc1e41cda40bed7d46e5a28af67ae2aabfefe67a86a1c601e6f5ee543e09bd7b6
+d = 7f3edb710df9d982f486233d0c176aa88f5a0ee81efa9b8145020294
+Qx = e7611e013e7b43ff5b8b57ad83333bffcc9e469ad23070b5791dc594
+Qy = 7784da0a11dbe16208c6e0b6d5029e71fbec4dffc9fa046d3eeb71c9
+k = 94db7ef9a232593091eb9a74f289529c7e0d7fef21f80b3c8556b75e
+R = a971f45bab10b1d16d7234ca8e4ec987da20d9e867f28aa063296e23
+S = e38c538d65a7e1a28fd3ec53f015a7e5beb60e9d309f1e3ba4b2c3d2
+
+Msg = 48453340f1317769e6ee6e103153714365731163dc18f84e9f2fa4b120f9c5a9645ee2f9b66c84c26d95912b422b009b64af96aa418b2427a4209f2e7513ba8e43ec8cf20b34e7529b22eb1199545afe9a9f7d9bcb320aec9ee0162f91c0d1dd9674c9c284f25199c5e109f6f84d7ed0d269cc6413edb81bc2c83e37d644d8b9
+d = b569f8296ff1d9cc01fffd9919016e5730c1858bdb7b99527153751a
+Qx = 242f34959516a4706172f7dede23110efa314bff22eb320ab88feeff
+Qy = 45e3227710900a8acfc9bcce728119d042f64ca40876c2b380ee46e0
+k = ae61523866a8f43e6cdd42ba27a34ed06527e8a5842901a64c393f76
+R = c2732a4e0815f9f785500e80147e9486994446beccf8a6a352b97585
+S = 6ecaece6487d7920e398f7f951ab7c7aba5832dabf03704106ad1244
+
+Msg = 4bdfd3b91d83108409ad765b256e0c9b9937ecf647f8e6f9fc807e2e72af8246178b3fe046b4ea10170450d71a4eec790ecb05f03d7077341de26c4db7eeae24d55c9a9093e837dfdb38168fe8230cb9605825a1282fecd741989bfcdb34678fe077477927f66bd26d003e5dda22043341a14dd31841ba483ad5ce2701e0f68e
+d = 41a4dd8eee39232b728516e2f21e66011e7426a6b25986c3ffa237e4
+Qx = c32988171caab178bf50dc7310bc7f604df5a9d19a8e602519c72d8a
+Qy = f8985d112ad9de05969e5364d943c1cc5cd198359f4c62b19da0e117
+k = 827d4999da81fa920c8492ccc1e2d5cdafed9754cf7382a859952071
+R = 89c61da7422ccd676baec07e2185c12e947a2374eede87847304be6c
+S = 2685379624717ea28422e8d001c090405a130b4ef9f1ac726c3ca502
+
+Msg = e6cdee8558bc1eacc24e82f0624ce8d02cc8d925b4dd3dec3a72f4a4e0fb76076bfa3ef2e2c33bdd7c27b322bdc09bbfee8fe46f75dbd7bbd2af09690b7137943efe21706e0a1b6d3089540fc58d85ddb55ea836616db573e36c521be008893f40a0a7c349602cc178ea43be59d31ec6449e7ff2c5379379f7d7645134df1bc3
+d = 67fa50569257c8cc89ac0325db4902003a62f30b917f53e4035a7e04
+Qx = 6773a0436a9c42635730413b19aa4166f08c69c0e5002953da42253b
+Qy = 555138290b093bf2fe79acda9131d920cd1e7ac43fb8775776cd713c
+k = 557cb45fd3a30b3bdbf08c56eabbd4478736024aaa52bf8448096453
+R = 8e92cf7a674aa5f7542dd95c695589a05747431692edd04804299b8f
+S = af4908b41f8180b71a6ff10fd51f3d143147af6ddddf7534d3284ed9
+
+
+[P-256,SHA-224]
+
+Msg = ff624d0ba02c7b6370c1622eec3fa2186ea681d1659e0a845448e777b75a8e77a77bb26e5733179d58ef9bc8a4e8b6971aef2539f77ab0963a3415bbd6258339bd1bf55de65db520c63f5b8eab3d55debd05e9494212170f5d65b3286b8b668705b1e2b2b5568610617abb51d2dd0cb450ef59df4b907da90cfa7b268de8c4c2
+d = 708309a7449e156b0db70e5b52e606c7e094ed676ce8953bf6c14757c826f590
+Qx = 29578c7ab6ce0d11493c95d5ea05d299d536801ca9cbd50e9924e43b733b83ab
+Qy = 08c8049879c6278b2273348474158515accaa38344106ef96803c5a05adc4800
+k = 58f741771620bdc428e91a32d86d230873e9140336fcfb1e122892ee1d501bdc
+R = 4a19274429e40522234b8785dc25fc524f179dcc95ff09b3c9770fc71f54ca0d
+S = 58982b79a65b7320f5b92d13bdaecdd1259e760f0f718ba933fd098f6f75d4b7
+
+Msg = 9155e91fd9155eeed15afd83487ea1a3af04c5998b77c0fe8c43dcc479440a8a9a89efe883d9385cb9edfde10b43bce61fb63669935ad39419cf29ef3a936931733bfc2378e253e73b7ae9a3ec7a6a7932ab10f1e5b94d05160c053988f3bdc9167155d069337d42c9a7056619efc031fa5ec7310d29bd28980b1e3559757578
+d = 90c5386100b137a75b0bb495002b28697a451add2f1f22cb65f735e8aaeace98
+Qx = 4a92396ff7930b1da9a873a479a28a9896af6cc3d39345b949b726dc3cd978b5
+Qy = 475abb18eaed948879b9c1453e3ef2755dd90f77519ec7b6a30297aad08e4931
+k = 36f853b5c54b1ec61588c9c6137eb56e7a708f09c57513093e4ecf6d739900e5
+R = 38b29558511061cfabdc8e5bb65ac2976d1aa2ba9a5deab8074097b2172bb9ad
+S = 0de2cde610502b6e03c0b23602eafbcd3faf886c81d111d156b7aa550f5bcd51
+
+Msg = b242a7586a1383368a33c88264889adfa3be45422fbef4a2df4e3c5325a9c7757017e0d5cf4bbf4de7f99d189f81f1fd2f0dd645574d1eb0d547eead9375677819297c1abe62526ae29fc54cdd11bfe17714f2fbd2d0d0e8d297ff98535980482dd5c1ebdc5a7274aabf1382c9f2315ca61391e3943856e4c5e616c2f1f7be0d
+d = a3a43cece9c1abeff81099fb344d01f7d8df66447b95a667ee368f924bccf870
+Qx = 5775174deb0248112e069cb86f1546ac7a78bc2127d0cb953bad46384dd6be5b
+Qy = a27020952971cc0b0c3abd06e9ca3e141a4943f560564eba31e5288928bc7ce7
+k = a0d9a7a245bd9b9aa86cecb89341c9de2e4f9b5d095a8150826c7ba7fb3e7df7
+R = b02a440add66a9ff9c3c0e9acf1be678f6bd48a10cbdec2ad6d186ffe05f3f2a
+S = a98bea42aec56a1fcecec00a1cc69b01fcbcf5de7ac1b2f2dcc09b6db064f92b
+
+Msg = b64005da76b24715880af94dba379acc25a047b06066c9bedc8f17b8c74e74f4fc720d9f4ef0e2a659e0756931c080587ebdcd0f85e819aea6dacb327a9d96496da53ea21aef3b2e793a9c0def5196acec99891f46ead78a85bc7ab644765781d3543da9fbf9fec916dca975ef3b4271e50ecc68bf79b2d8935e2b25fc063358
+d = 7bbc8ff13f6f921f21e949b224c16b7176c5984d312b671cf6c2e4841135fc7f
+Qx = f888e913ec6f3cd8b31eb89e4f8aaa8887d30ae5348ed7118696949d5b8cc7c1
+Qy = 08895d09620500d244e5035e262dea3f2867cd8967b226324d5c05220d8b410c
+k = 21c942f3b487accbf7fadc1c4b7a6c7567ce876c195022459fa1ebf6d04ffbaa
+R = 2e6cc883b8acc904ee9691ef4a9f1f5a9e5fbfde847cda3be833f949fb9c7182
+S = 2ac48f7a930912131a8b4e3ab495307817c465d638c2a9ea5ae9e2808806e20a
+
+Msg = fe6e1ea477640655eaa1f6e3352d4bce53eb3d95424df7f238e93d8531da8f36bc35fa6be4bf5a6a382e06e855139eb617a9cc9376b4dafacbd80876343b12628619d7cbe1bff6757e3706111ed53898c0219823adbc044eaf8c6ad449df8f6aab9d444dadb5c3380eec0d91694df5fc4b30280d4b87d27e67ae58a1df828963
+d = daf5ec7a4eebc20d9485796c355b4a65ad254fe19b998d0507e91ea24135f45d
+Qx = 137c465085c1b1b8cccbe9fccbe9d0295a331aaf332f3ed2e285d16e574b943b
+Qy = d3e8d5a24cd218c19760b0e85b35a8569945aa857cbf0fd6a3ce127581b217b6
+k = 343251dffa56e6a612fec7b078f9c3819eab402a72686b894a47a08fd97e6c23
+R = 775e25a296bd259510ae9375f548997bec8a744900022945281dc8c4d94f2b5b
+S = d87592ceab773ae103daebbb56a04144aaccb1e14efc1024dc36c0e382df1f70
+
+Msg = 907c0c00dc080a688548957b5b8b1f33ba378de1368023dcad43242411f554eb7d392d3e5c1668fad3944ff9634105343d83b8c85d2a988da5f5dc60ee0518327caed6dd5cf4e9bc6222deb46d00abde745f9b71d6e7aee6c7fdfc9ed053f2c0b611d4c6863088bd012ea9810ee94f8e58905970ebd07353f1f409a371ed03e3
+d = 8729a8396f262dabd991aa404cc1753581cea405f0d19222a0b3f210de8ee3c5
+Qx = 82b1f1a7af9b48ca8452613d7032beb0e4f28fe710306aeccc959e4d03662a35
+Qy = 5e39f33574097b8d32b471a591972496f5d44db344c037d13f06fafc75f016fd
+k = 6de9e21f0b2cacc1762b3558fd44d3cf156b85dbef430dd28d59713bfb9cfa0b
+R = a754b42720e71925d51fcef76151405a3696cc8f9fc9ca7b46d0b16edd7fb699
+S = 603924780439cc16ac4cf97c2c3065bc95353aa9179d0ab5f0322ca82f851cf2
+
+Msg = 771c4d7bce05610a3e71b272096b57f0d1efcce33a1cb4f714d6ebc0865b2773ec5eedc25fae81dee1d256474dbd9676623614c150916e6ed92ce4430b26037d28fa5252ef6b10c09dc2f7ee5a36a1ea7897b69f389d9f5075e271d92f4eb97b148f3abcb1e5be0b4feb8278613d18abf6da60bfe448238aa04d7f11b71f44c5
+d = f1b62413935fc589ad2280f6892599ad994dae8ca3655ed4f7318cc89b61aa96
+Qx = e0bbfe4016eea93e6f509518cbffc25d492de6ebbf80465a461caa5bdc018159
+Qy = 3231ee7a119d84fa56e3034d50fea85929aec2eb437abc7646821e1bf805fb50
+k = 7a33eeb9f469afd55de2fb786847a1d3e7797929305c0f90d953b6f143bb8fc6
+R = 96d1c9399948254ea381631fc0f43ea808110506db8aacf081df5535ac5eb8ad
+S = 73bf3691260dddd9997c97313f2a70783eacf8d15bdfb34bb13025cdfae72f70
+
+Msg = a3b2825235718fc679b942e8ac38fb4f54415a213c65875b5453d18ca012320ddfbbc58b991eaebadfc2d1a28d4f0cd82652b12e4d5bfda89eda3be12ac52188e38e8cce32a264a300c0e463631f525ae501348594f980392c76b4a12ddc88e5ca086cb8685d03895919a8627725a3e00c4728e2b7c6f6a14fc342b2937fc3dd
+d = 4caaa26f93f009682bbba6db6b265aec17b7ec1542bda458e8550b9e68eed18d
+Qx = e3c58c1c254d11c7e781ad133e4c36dd1b5de362120d336a58e7b68813f3fbee
+Qy = 59760db66120afe0d962c81a8e5586588fd19de2f40556371611c73af22c8a68
+k = c0d37142dc8b0d614fad20c4d35af6eb819e259e513ddeac1e1c273e7e1dc1bb
+R = 25dd8e4086c62a40d2a310e2f90f6af5cb7e677b4dfdb4dc4e99e23ea2f0e6dc
+S = 90ad62c179b0c9d61f521dde1cd762bfd224b5525c39c3706f2549313ddb4f39
+
+Msg = 3e6e2a9bffd729ee5d4807849cd4250021d8184cda723df6ab0e5c939d39237c8e58af9d869fe62d3c97b3298a99e891e5e11aa68b11a087573a40a3e83c7965e7910d72f81cad0f42accc5c25a4fd3cdd8cee63757bbbfbdae98be2bc867d3bcb1333c4632cb0a55dffeb77d8b119c466cd889ec468454fabe6fbee7102deaf
+d = 7af4b150bb7167cb68037f280d0823ce5320c01a92b1b56ee1b88547481b1de9
+Qx = cb3634ec4f0cbb99986be788f889e586026d5a851e80d15382f1bdb1bda2bc75
+Qy = 51e4e43bc16fb114896b18198a1aebe6054ba20ed0c0317c1b8776158c0e6bfb
+k = 98edd59fafbcaee5f64e84eb5ed59fff45d14aabada47cee2fa674377173627a
+R = 261a1cdb0fd93c0fb06ea6068b6b03c330a12f621a7eba76682a1d152c0e8d08
+S = 7ca049bad54feee101d6db807635ffb8bdb05a38e445c8c3d65d60df143514c5
+
+Msg = 52e5c308e70329a17c71eaedb66bbee303c8ec48a6f1a2efb235d308563cd58553d434e12f353227a9ea28608ec9c820ed83c95124e7a886f7e832a2de1032e78dc059208f9ec354170b2b1cab992b52ac01e6c0e4e1b0112686962edc53ab226dafcc9fc7baed2cd9307160e8572edb125935db49289b178f35a8ad23f4f801
+d = 52ad53e849e30bec0e6345c3e9d98ebc808b19496c1ef16d72ab4a00bbb8c634
+Qx = 7cca1334bfc2a78728c50b370399be3f9690d445aa03c701da643eeb0b0f7fa8
+Qy = 3f7522238668e615405e49b2f63faee58286000a30cdb4b564ac0df99bc8950f
+k = 8650c30712fc253610884fbba4a332a4574d4b7822f7776cab1df8f5fa05442a
+R = a18194c7ac5829afc408d78dde19542837e7be82706c3941b2d9c5e036bb51e0
+S = 188ead1cdf7c1d21114ff56d0421ffd501ab978ef58337462c0fa736d86299af
+
+Msg = d3e9e82051d4c84d699453c9ff44c7c09f6523bb92232bcf30bf3c380224249de2964e871d56a364d6955c81ef91d06482a6c7c61bc70f66ef22fad128d15416e7174312619134f968f1009f92cbf99248932efb533ff113fb6d949e21d6b80dfbbe69010c8d1ccb0f3808ea309bb0bac1a222168c95b088847e613749b19d04
+d = 80754962a864be1803bc441fa331e126005bfc6d8b09ed38b7e69d9a030a5d27
+Qx = 0aaeed6dd1ae020d6eefc98ec4241ac93cbd3c8afed05bb28007e7da5727571b
+Qy = 2dda1d5b7872eb94dfffb456115037ff8d3e72f8ebdd8fcfc42391f96809be69
+k = 738e050aeefe54ecba5be5f93a97bbcb7557d701f9da2d7e88483454b97b55a8
+R = 8cb9f41dfdcb9604e0725ac9b78fc0db916dc071186ee982f6dba3da36f02efa
+S = 5c87fe868fd4282fb114f5d70e9590a10a5d35cedf3ff6402ba5c4344738a32e
+
+Msg = 968951c2c1918436fe19fa2fe2152656a08f9a6b8aa6201920f1b424da98cee71928897ff087620cc5c551320b1e75a1e98d7d98a5bd5361c9393759614a6087cc0f7fb01fcb173783eb4c4c23961a8231ac4a07d72e683b0c1bd4c51ef1b031df875e7b8d5a6e0628949f5b8f157f43dccaea3b2a4fc11181e6b451e06ceb37
+d = cfa8c8bd810eb0d73585f36280ecdd296ee098511be8ad5eac68984eca8eb19d
+Qx = c227a2af15dfa8734e11c0c50f77e24e77ed58dd8cccf1b0e9fa06bee1c64766
+Qy = b686592ce3745eb300d2704083db55e1fa8274e4cb7e256889ccc0bb34a60570
+k = 2d6b449bb38b543d6b6d34ff8cb053f5e5b337f949b069b21f421995ebb28823
+R = 5e89d3c9b103c2fa3cb8cebeec23640acda0257d63ffbe2d509bfc49fab1dca6
+S = d70c5b1eeb29e016af9925798d24e166c23d58fedd2f1a3bbdb1ef78cdbfb63a
+
+Msg = 78048628932e1c1cdd1e70932bd7b76f704ba08d7e7d825d3de763bf1a062315f4af16eccefe0b6ebadccaf403d013f50833ce2c54e24eea8345e25f93b69bb048988d102240225ceacf5003e2abdcc90299f4bf2c101585d36ecdd7a155953c674789d070480d1ef47cc7858e97a6d87c41c6922a00ea12539f251826e141b4
+d = b2021e2665ce543b7feadd0cd5a4bd57ffcc5b32deb860b4d736d9880855da3c
+Qx = 722e0abad4504b7832a148746153777694714eca220eced2b2156ca64cfed3dd
+Qy = f0351b357b3081e859c46cad5328c5afa10546e92bc6c3fd541796ac30397a75
+k = b15bbce4b382145de7ecd670d947e77555ef7cd1693bd53c694e2b52b04d10e1
+R = 9d086dcd22da165a43091991bede9c1c14515e656633cb759ec2c17f51c35253
+S = 23595ad1cb714559faaecaf946beb9a71e584616030ceaed8a8470f4bf62768f
+
+Msg = 9b0800c443e693067591737fdbcf0966fdfa50872d41d0c189d87cbc34c2771ee5e1255fd604f09fcf167fda16437c245d299147299c69046895d22482db29aba37ff57f756716cd3d6223077f747c4caffbecc0a7c9dfaaafd9a9817470ded8777e6355838ac54d11b2f0fc3f43668ff949cc31de0c2d15af5ef17884e4d66a
+d = 0c9bce6a568ca239395fc3552755575cbcdddb1d89f6f5ab354517a057b17b48
+Qx = 4814d454495df7103e2da383aba55f7842fd84f1750ee5801ad32c10d0be6c7d
+Qy = a0bd039d5097c8f0770477f6b18d247876e88e528bf0453eab515ffab8a9eda3
+k = d414f1525cdcc41eba1652de017c034ebcc7946cb2efe4713d09f67c85b83153
+R = 84db02c678f9a21208cec8564d145a35ba8c6f26b4eb7e19522e439720dae44c
+S = 537c564da0d2dc5ac4376c5f0ca3b628d01d48df47a83d842c927e4d6db1e16d
+
+Msg = fc3b8291c172dae635a6859f525beaf01cf683765d7c86f1a4d768df7cae055f639eccc08d7a0272394d949f82d5e12d69c08e2483e11a1d28a4c61f18193106e12e5de4a9d0b4bf341e2acd6b715dc83ae5ff63328f8346f35521ca378b311299947f63ec593a5e32e6bd11ec4edb0e75302a9f54d21226d23314729e061016
+d = 1daa385ec7c7f8a09adfcaea42801a4de4c889fb5c6eb4e92bc611d596d68e3f
+Qx = f04e9f2831d9697ae146c7d4552e5f91085cc46778400b75b76f00205252941d
+Qy = bd267148174cd0c2b019cd0a5256e2f3f889d1e597160372b5a1339c8d787f10
+k = 7707db348ee6f60365b43a2a994e9b40ed56fe03c2c31c7e781bc4ffadcba760
+R = 5d95c385eeba0f15db0b80ae151912409128c9c80e554246067b8f6a36d85ea5
+S = db5d8a1e345f883e4fcb3871276f170b783c1a1e9da6b6615913368a8526f1c3
+
+[P-256,SHA-256]
+
+Msg = 5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf416983fe165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5473e253605fb1ddfd28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17cc934a9d791e91491eb3754d03799790fe2d308d16146d5c9b0d0debd97d79ce8
+d = 519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464
+Qx = 1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83
+Qy = ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9
+k = 94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de
+R = f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac
+S = 8bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903
+
+Msg = c35e2f092553c55772926bdbe87c9796827d17024dbb9233a545366e2e5987dd344deb72df987144b8c6c43bc41b654b94cc856e16b96d7a821c8ec039b503e3d86728c494a967d83011a0e090b5d54cd47f4e366c0912bc808fbb2ea96efac88fb3ebec9342738e225f7c7c2b011ce375b56621a20642b4d36e060db4524af1
+d = 0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813
+Qx = e266ddfdc12668db30d4ca3e8f7749432c416044f2d2b8c10bf3d4012aeffa8a
+Qy = bfa86404a2e9ffe67d47c587ef7a97a7f456b863b4d02cfc6928973ab5b1cb39
+k = 6d3e71882c3b83b156bb14e0ab184aa9fb728068d3ae9fac421187ae0b2f34c6
+R = 976d3a4e9d23326dc0baa9fa560b7c4e53f42864f508483a6473b6a11079b2db
+S = 1b766e9ceb71ba6c01dcd46e0af462cd4cfa652ae5017d4555b8eeefe36e1932
+
+Msg = 3c054e333a94259c36af09ab5b4ff9beb3492f8d5b4282d16801daccb29f70fe61a0b37ffef5c04cd1b70e85b1f549a1c4dc672985e50f43ea037efa9964f096b5f62f7ffdf8d6bfb2cc859558f5a393cb949dbd48f269343b5263dcdb9c556eca074f2e98e6d94c2c29a677afaf806edf79b15a3fcd46e7067b7669f83188ee
+d = e283871239837e13b95f789e6e1af63bf61c918c992e62bca040d64cad1fc2ef
+Qx = 74ccd8a62fba0e667c50929a53f78c21b8ff0c3c737b0b40b1750b2302b0bde8
+Qy = 29074e21f3a0ef88b9efdf10d06aa4c295cc1671f758ca0e4cd108803d0f2614
+k = ad5e887eb2b380b8d8280ad6e5ff8a60f4d26243e0124c2f31a297b5d0835de2
+R = 35fb60f5ca0f3ca08542fb3cc641c8263a2cab7a90ee6a5e1583fac2bb6f6bd1
+S = ee59d81bc9db1055cc0ed97b159d8784af04e98511d0a9a407b99bb292572e96
+
+Msg = 0989122410d522af64ceb07da2c865219046b4c3d9d99b01278c07ff63eaf1039cb787ae9e2dd46436cc0415f280c562bebb83a23e639e476a02ec8cff7ea06cd12c86dcc3adefbf1a9e9a9b6646c7599ec631b0da9a60debeb9b3e19324977f3b4f36892c8a38671c8e1cc8e50fcd50f9e51deaf98272f9266fc702e4e57c30
+d = a3d2d3b7596f6592ce98b4bfe10d41837f10027a90d7bb75349490018cf72d07
+Qx = 322f80371bf6e044bc49391d97c1714ab87f990b949bc178cb7c43b7c22d89e1
+Qy = 3c15d54a5cc6b9f09de8457e873eb3deb1fceb54b0b295da6050294fae7fd999
+k = 24fc90e1da13f17ef9fe84cc96b9471ed1aaac17e3a4bae33a115df4e5834f18
+R = d7c562370af617b581c84a2468cc8bd50bb1cbf322de41b7887ce07c0e5884ca
+S = b46d9f2d8c4bf83546ff178f1d78937c008d64e8ecc5cbb825cb21d94d670d89
+
+Msg = dc66e39f9bbfd9865318531ffe9207f934fa615a5b285708a5e9c46b7775150e818d7f24d2a123df3672fff2094e3fd3df6fbe259e3989dd5edfcccbe7d45e26a775a5c4329a084f057c42c13f3248e3fd6f0c76678f890f513c32292dd306eaa84a59abe34b16cb5e38d0e885525d10336ca443e1682aa04a7af832b0eee4e7
+d = 53a0e8a8fe93db01e7ae94e1a9882a102ebd079b3a535827d583626c272d280d
+Qx = 1bcec4570e1ec2436596b8ded58f60c3b1ebc6a403bc5543040ba82963057244
+Qy = 8af62a4c683f096b28558320737bf83b9959a46ad2521004ef74cf85e67494e1
+k = 5d833e8d24cc7a402d7ee7ec852a3587cddeb48358cea71b0bedb8fabe84e0c4
+R = 18caaf7b663507a8bcd992b836dec9dc5703c080af5e51dfa3a9a7c387182604
+S = 77c68928ac3b88d985fb43fb615fb7ff45c18ba5c81af796c613dfa98352d29c
+
+Msg = 600974e7d8c5508e2c1aab0783ad0d7c4494ab2b4da265c2fe496421c4df238b0be25f25659157c8a225fb03953607f7df996acfd402f147e37aee2f1693e3bf1c35eab3ae360a2bd91d04622ea47f83d863d2dfecb618e8b8bdc39e17d15d672eee03bb4ce2cc5cf6b217e5faf3f336fdd87d972d3a8b8a593ba85955cc9d71
+d = 4af107e8e2194c830ffb712a65511bc9186a133007855b49ab4b3833aefc4a1d
+Qx = a32e50be3dae2c8ba3f5e4bdae14cf7645420d425ead94036c22dd6c4fc59e00
+Qy = d623bf641160c289d6742c6257ae6ba574446dd1d0e74db3aaa80900b78d4ae9
+k = e18f96f84dfa2fd3cdfaec9159d4c338cd54ad314134f0b31e20591fc238d0ab
+R = 8524c5024e2d9a73bde8c72d9129f57873bbad0ed05215a372a84fdbc78f2e68
+S = d18c2caf3b1072f87064ec5e8953f51301cada03469c640244760328eb5a05cb
+
+Msg = dfa6cb9b39adda6c74cc8b2a8b53a12c499ab9dee01b4123642b4f11af336a91a5c9ce0520eb2395a6190ecbf6169c4cba81941de8e76c9c908eb843b98ce95e0da29c5d4388040264e05e07030a577cc5d176387154eabae2af52a83e85c61c7c61da930c9b19e45d7e34c8516dc3c238fddd6e450a77455d534c48a152010b
+d = 78dfaa09f1076850b3e206e477494cddcfb822aaa0128475053592c48ebaf4ab
+Qx = 8bcfe2a721ca6d753968f564ec4315be4857e28bef1908f61a366b1f03c97479
+Qy = 0f67576a30b8e20d4232d8530b52fb4c89cbc589ede291e499ddd15fe870ab96
+k = 295544dbb2da3da170741c9b2c6551d40af7ed4e891445f11a02b66a5c258a77
+R = c5a186d72df452015480f7f338970bfe825087f05c0088d95305f87aacc9b254
+S = 84a58f9e9d9e735344b316b1aa1ab5185665b85147dc82d92e969d7bee31ca30
+
+Msg = 51d2547cbff92431174aa7fc7302139519d98071c755ff1c92e4694b58587ea560f72f32fc6dd4dee7d22bb7387381d0256e2862d0644cdf2c277c5d740fa089830eb52bf79d1e75b8596ecf0ea58a0b9df61e0c9754bfcd62efab6ea1bd216bf181c5593da79f10135a9bc6e164f1854bc8859734341aad237ba29a81a3fc8b
+d = 80e692e3eb9fcd8c7d44e7de9f7a5952686407f90025a1d87e52c7096a62618a
+Qx = a88bc8430279c8c0400a77d751f26c0abc93e5de4ad9a4166357952fe041e767
+Qy = 2d365a1eef25ead579cc9a069b6abc1b16b81c35f18785ce26a10ba6d1381185
+k = 7c80fd66d62cc076cef2d030c17c0a69c99611549cb32c4ff662475adbe84b22
+R = 9d0c6afb6df3bced455b459cc21387e14929392664bb8741a3693a1795ca6902
+S = d7f9ddd191f1f412869429209ee3814c75c72fa46a9cccf804a2f5cc0b7e739f
+
+Msg = 558c2ac13026402bad4a0a83ebc9468e50f7ffab06d6f981e5db1d082098065bcff6f21a7a74558b1e8612914b8b5a0aa28ed5b574c36ac4ea5868432a62bb8ef0695d27c1e3ceaf75c7b251c65ddb268696f07c16d2767973d85beb443f211e6445e7fe5d46f0dce70d58a4cd9fe70688c035688ea8c6baec65a5fc7e2c93e8
+d = 5e666c0db0214c3b627a8e48541cc84a8b6fd15f300da4dff5d18aec6c55b881
+Qx = 1bc487570f040dc94196c9befe8ab2b6de77208b1f38bdaae28f9645c4d2bc3a
+Qy = ec81602abd8345e71867c8210313737865b8aa186851e1b48eaca140320f5d8f
+k = 2e7625a48874d86c9e467f890aaa7cd6ebdf71c0102bfdcfa24565d6af3fdce9
+R = 2f9e2b4e9f747c657f705bffd124ee178bbc5391c86d056717b140c153570fd9
+S = f5413bfd85949da8d83de83ab0d19b2986613e224d1901d76919de23ccd03199
+
+Msg = 4d55c99ef6bd54621662c3d110c3cb627c03d6311393b264ab97b90a4b15214a5593ba2510a53d63fb34be251facb697c973e11b665cb7920f1684b0031b4dd370cb927ca7168b0bf8ad285e05e9e31e34bc24024739fdc10b78586f29eff94412034e3b606ed850ec2c1900e8e68151fc4aee5adebb066eb6da4eaa5681378e
+d = f73f455271c877c4d5334627e37c278f68d143014b0a05aa62f308b2101c5308
+Qx = b8188bd68701fc396dab53125d4d28ea33a91daf6d21485f4770f6ea8c565dde
+Qy = 423f058810f277f8fe076f6db56e9285a1bf2c2a1dae145095edd9c04970bc4a
+k = 62f8665fd6e26b3fa069e85281777a9b1f0dfd2c0b9f54a086d0c109ff9fd615
+R = 1cc628533d0004b2b20e7f4baad0b8bb5e0673db159bbccf92491aef61fc9620
+S = 880e0bbf82a8cf818ed46ba03cf0fc6c898e36fca36cc7fdb1d2db7503634430
+
+Msg = f8248ad47d97c18c984f1f5c10950dc1404713c56b6ea397e01e6dd925e903b4fadfe2c9e877169e71ce3c7fe5ce70ee4255d9cdc26f6943bf48687874de64f6cf30a012512e787b88059bbf561162bdcc23a3742c835ac144cc14167b1bd6727e940540a9c99f3cbb41fb1dcb00d76dda04995847c657f4c19d303eb09eb48a
+d = b20d705d9bd7c2b8dc60393a5357f632990e599a0975573ac67fd89b49187906
+Qx = 51f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce
+Qy = 4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1
+k = 72b656f6b35b9ccbc712c9f1f3b1a14cbbebaec41c4bca8da18f492a062d6f6f
+R = 9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c42
+S = 2bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c
+
+Msg = 3b6ee2425940b3d240d35b97b6dcd61ed3423d8e71a0ada35d47b322d17b35ea0472f35edd1d252f87b8b65ef4b716669fc9ac28b00d34a9d66ad118c9d94e7f46d0b4f6c2b2d339fd6bcd351241a387cc82609057048c12c4ec3d85c661975c45b300cb96930d89370a327c98b67defaa89497aa8ef994c77f1130f752f94a4
+d = d4234bebfbc821050341a37e1240efe5e33763cbbb2ef76a1c79e24724e5a5e7
+Qx = 8fb287f0202ad57ae841aea35f29b2e1d53e196d0ddd9aec24813d64c0922fb7
+Qy = 1f6daff1aa2dd2d6d3741623eecb5e7b612997a1039aab2e5cf2de969cfea573
+k = d926fe10f1bfd9855610f4f5a3d666b1a149344057e35537373372ead8b1a778
+R = 490efd106be11fc365c7467eb89b8d39e15d65175356775deab211163c2504cb
+S = 644300fc0da4d40fb8c6ead510d14f0bd4e1321a469e9c0a581464c7186b7aa7
+
+Msg = c5204b81ec0a4df5b7e9fda3dc245f98082ae7f4efe81998dcaa286bd4507ca840a53d21b01e904f55e38f78c3757d5a5a4a44b1d5d4e480be3afb5b394a5d2840af42b1b4083d40afbfe22d702f370d32dbfd392e128ea4724d66a3701da41ae2f03bb4d91bb946c7969404cb544f71eb7a49eb4c4ec55799bda1eb545143a7
+d = b58f5211dff440626bb56d0ad483193d606cf21f36d9830543327292f4d25d8c
+Qx = 68229b48c2fe19d3db034e4c15077eb7471a66031f28a980821873915298ba76
+Qy = 303e8ee3742a893f78b810991da697083dd8f11128c47651c27a56740a80c24c
+k = e158bf4a2d19a99149d9cdb879294ccb7aaeae03d75ddd616ef8ae51a6dc1071
+R = e67a9717ccf96841489d6541f4f6adb12d17b59a6bef847b6183b8fcf16a32eb
+S = 9ae6ba6d637706849a6a9fc388cf0232d85c26ea0d1fe7437adb48de58364333
+
+Msg = 72e81fe221fb402148d8b7ab03549f1180bcc03d41ca59d7653801f0ba853add1f6d29edd7f9abc621b2d548f8dbf8979bd16608d2d8fc3260b4ebc0dd42482481d548c7075711b5759649c41f439fad69954956c9326841ea6492956829f9e0dc789f73633b40f6ac77bcae6dfc7930cfe89e526d1684365c5b0be2437fdb01
+d = 54c066711cdb061eda07e5275f7e95a9962c6764b84f6f1f3ab5a588e0a2afb1
+Qx = 0a7dbb8bf50cb605eb2268b081f26d6b08e012f952c4b70a5a1e6e7d46af98bb
+Qy = f26dd7d799930062480849962ccf5004edcfd307c044f4e8f667c9baa834eeae
+k = 646fe933e96c3b8f9f507498e907fdd201f08478d0202c752a7c2cfebf4d061a
+R = b53ce4da1aa7c0dc77a1896ab716b921499aed78df725b1504aba1597ba0c64b
+S = d7c246dc7ad0e67700c373edcfdd1c0a0495fc954549ad579df6ed1438840851
+
+Msg = 21188c3edd5de088dacc1076b9e1bcecd79de1003c2414c3866173054dc82dde85169baa77993adb20c269f60a5226111828578bcc7c29e6e8d2dae81806152c8ba0c6ada1986a1983ebeec1473a73a04795b6319d48662d40881c1723a706f516fe75300f92408aa1dc6ae4288d2046f23c1aa2e54b7fb6448a0da922bd7f34
+d = 34fa4682bf6cb5b16783adcd18f0e6879b92185f76d7c920409f904f522db4b1
+Qx = 105d22d9c626520faca13e7ced382dcbe93498315f00cc0ac39c4821d0d73737
+Qy = 6c47f3cbbfa97dfcebe16270b8c7d5d3a5900b888c42520d751e8faf3b401ef4
+k = a6f463ee72c9492bc792fe98163112837aebd07bab7a84aaed05be64db3086f4
+R = 542c40a18140a6266d6f0286e24e9a7bad7650e72ef0e2131e629c076d962663
+S = 4f7f65305e24a6bbb5cff714ba8f5a2cee5bdc89ba8d75dcbf21966ce38eb66f
+
+[P-256,SHA-384]
+
+Msg = e0b8596b375f3306bbc6e77a0b42f7469d7e83635990e74aa6d713594a3a24498feff5006790742d9c2e9b47d714bee932435db747c6e733e3d8de41f2f91311f2e9fd8e025651631ffd84f66732d3473fbd1627e63dc7194048ebec93c95c159b5039ab5e79e42c80b484a943f125de3da1e04e5bf9c16671ad55a1117d3306
+d = b6faf2c8922235c589c27368a3b3e6e2f42eb6073bf9507f19eed0746c79dced
+Qx = e0e7b99bc62d8dd67883e39ed9fa0657789c5ff556cc1fd8dd1e2a55e9e3f243
+Qy = 63fbfd0232b95578075c903a4dbf85ad58f8350516e1ec89b0ee1f5e1362da69
+k = 9980b9cdfcef3ab8e219b9827ed6afdd4dbf20bd927e9cd01f15762703487007
+R = f5087878e212b703578f5c66f434883f3ef414dc23e2e8d8ab6a8d159ed5ad83
+S = 306b4c6c20213707982dffbb30fba99b96e792163dd59dbe606e734328dd7c8a
+
+Msg = 099a0131179fff4c6928e49886d2fdb3a9f239b7dd5fa828a52cbbe3fcfabecfbba3e192159b887b5d13aa1e14e6a07ccbb21f6ad8b7e88fee6bea9b86dea40ffb962f38554056fb7c5bb486418915f7e7e9b9033fe3baaf9a069db98bc02fa8af3d3d1859a11375d6f98aa2ce632606d0800dff7f55b40f971a8586ed6b39e9
+d = 118958fd0ff0f0b0ed11d3cf8fa664bc17cdb5fed1f4a8fc52d0b1ae30412181
+Qx = afda82260c9f42122a3f11c6058839488f6d7977f6f2a263c67d06e27ea2c355
+Qy = 0ae2bbdd2207c590332c5bfeb4c8b5b16622134bd4dc55382ae806435468058b
+k = 23129a99eeda3d99a44a5778a46e8e7568b91c31fb7a8628c5d9820d4bed4a6b
+R = e446600cab1286ebc3bb332012a2f5cc33b0a5ef7291d5a62a84de5969d77946
+S = cf89b12793ee1792eb26283b48fa0bdcb45ae6f6ad4b02564bf786bb97057d5a
+
+Msg = 0fbc07ea947c946bea26afa10c51511039b94ddbc4e2e4184ca3559260da24a14522d1497ca5e77a5d1a8e86583aeea1f5d4ff9b04a6aa0de79cd88fdb85e01f171143535f2f7c23b050289d7e05cebccdd131888572534bae0061bdcc3015206b9270b0d5af9f1da2f9de91772d178a632c3261a1e7b3fb255608b3801962f9
+d = 3e647357cd5b754fad0fdb876eaf9b1abd7b60536f383c81ce5745ec80826431
+Qx = 702b2c94d039e590dd5c8f9736e753cf5824aacf33ee3de74fe1f5f7c858d5ed
+Qy = 0c28894e907af99fb0d18c9e98f19ac80dd77abfa4bebe45055c0857b82a0f4d
+k = 9beab7722f0bcb468e5f234e074170a60225255de494108459abdf603c6e8b35
+R = c4021fb7185a07096547af1fb06932e37cf8bd90cf593dea48d48614fa237e5e
+S = 7fb45d09e2172bec8d3e330aa06c43fbb5f625525485234e7714b7f6e92ba8f1
+
+Msg = 1e38d750d936d8522e9db1873fb4996bef97f8da3c6674a1223d29263f1234a90b751785316444e9ba698bc8ab6cd010638d182c9adad4e334b2bd7529f0ae8e9a52ad60f59804b2d780ed52bdd33b0bf5400147c28b4304e5e3434505ae7ce30d4b239e7e6f0ecf058badd5b388eddbad64d24d2430dd04b4ddee98f972988f
+d = 76c17c2efc99891f3697ba4d71850e5816a1b65562cc39a13da4b6da9051b0fd
+Qx = d12512e934c367e4c4384dbd010e93416840288a0ba00b299b4e7c0d91578b57
+Qy = ebf8835661d9b578f18d14ae4acf9c357c0dc8b7112fc32824a685ed72754e23
+k = 77cffa6f9a73904306f9fcd3f6bbb37f52d71e39931bb4aec28f9b076e436ccf
+R = 4d5a9d95b0f09ce8704b0f457b39059ee606092310df65d3f8ae7a2a424cf232
+S = 7d3c014ca470a73cef1d1da86f2a541148ad542fbccaf9149d1b0b030441a7eb
+
+Msg = abcf0e0f046b2e0672d1cc6c0a114905627cbbdefdf9752f0c31660aa95f2d0ede72d17919a9e9b1add3213164e0c9b5ae3c76f1a2f79d3eeb444e6741521019d8bd5ca391b28c1063347f07afcfbb705be4b52261c19ebaf1d6f054a74d86fb5d091fa7f229450996b76f0ada5f977b09b58488eebfb5f5e9539a8fd89662ab
+d = 67b9dea6a575b5103999efffce29cca688c781782a41129fdecbce76608174de
+Qx = b4238b029fc0b7d9a5286d8c29b6f3d5a569e9108d44d889cd795c4a385905be
+Qy = 8cb3fff8f6cca7187c6a9ad0a2b1d9f40ae01b32a7e8f8c4ca75d71a1fffb309
+k = d02617f26ede3584f0afcfc89554cdfb2ae188c192092fdde3436335fafe43f1
+R = 26fd9147d0c86440689ff2d75569795650140506970791c90ace0924b44f1586
+S = 00a34b00c20a8099df4b0a757cbef8fea1cb3ea7ced5fbf7e987f70b25ee6d4f
+
+Msg = dc3d4884c741a4a687593c79fb4e35c5c13c781dca16db561d7e393577f7b62ca41a6e259fc1fb8d0c4e1e062517a0fdf95558b7799f20c211796167953e6372c11829beec64869d67bf3ee1f1455dd87acfbdbcc597056e7fb347a17688ad32fda7ccc3572da7677d7255c261738f07763cd45973c728c6e9adbeecadc3d961
+d = ecf644ea9b6c3a04fdfe2de4fdcb55fdcdfcf738c0b3176575fa91515194b566
+Qx = c3bdc7c795ec94620a2cfff614c13a3390a5e86c892e53a24d3ed22228bc85bf
+Qy = 70480fc5cf4aacd73e24618b61b5c56c1ced8c4f1b869580ea538e68c7a61ca3
+k = 53291d51f68d9a12d1dcdc58892b2f786cc15f631f16997d2a49bace513557d4
+R = a860c8b286edf973ce4ce4cf6e70dc9bbf3818c36c023a845677a9963705df8b
+S = 5630f986b1c45e36e127dd7932221c4272a8cc6e255e89f0f0ca4ec3a9f76494
+
+Msg = 719bf1911ae5b5e08f1d97b92a5089c0ab9d6f1c175ac7199086aeeaa416a17e6d6f8486c711d386f284f096296689a54d330c8efb0f5fa1c5ba128d3234a3da856c2a94667ef7103616a64c913135f4e1dc50e38daa60610f732ad1bedfcc396f87169392520314a6b6b9af6793dbabad4599525228cc7c9c32c4d8e097ddf6
+d = 4961485cbc978f8456ec5ac7cfc9f7d9298f99415ecae69c8491b258c029bfee
+Qx = 8d40bf2299e05d758d421972e81cfb0cce68b949240dc30f315836acc70bef03
+Qy = 5674e6f77f8b46f46cca937d83b128dffbe9bd7e0d3d08aa2cbbfdfb16f72c9a
+k = 373a825b5a74b7b9e02f8d4d876b577b4c3984168d704ba9f95b19c05ed590af
+R = ef6fb386ad044b63feb7445fa16b10319018e9cea9ef42bca83bdad01992234a
+S = ac1f42f652eb1786e57be01d847c81f7efa072ba566d4583af4f1551a3f76c65
+
+Msg = 7cf19f4c851e97c5bca11a39f0074c3b7bd3274e7dd75d0447b7b84995dfc9f716bf08c25347f56fcc5e5149cb3f9cfb39d408ace5a5c47e75f7a827fa0bb9921bb5b23a6053dbe1fa2bba341ac874d9b1333fc4dc224854949f5c8d8a5fedd02fb26fdfcd3be351aec0fcbef18972956c6ec0effaf057eb4420b6d28e0c008c
+d = 587907e7f215cf0d2cb2c9e6963d45b6e535ed426c828a6ea2fb637cca4c5cbd
+Qx = 660da45c413cc9c9526202c16b402af602d30daaa7c342f1e722f15199407f31
+Qy = e6f8cbb06913cc718f2d69ba2fb3137f04a41c27c676d1a80fbf30ea3ca46439
+k = 6b8eb7c0d8af9456b95dd70561a0e902863e6dfa1c28d0fd4a0509f1c2a647b2
+R = 08fabf9b57de81875bfa7a4118e3e44cfb38ec6a9b2014940207ba3b1c583038
+S = a58d199b1deba7350616230d867b2747a3459421811c291836abee715b8f67b4
+
+Msg = b892ffabb809e98a99b0a79895445fc734fa1b6159f9cddb6d21e510708bdab6076633ac30aaef43db566c0d21f4381db46711fe3812c5ce0fb4a40e3d5d8ab24e4e82d3560c6dc7c37794ee17d4a144065ef99c8d1c88bc22ad8c4c27d85ad518fa5747ae35276fc104829d3f5c72fc2a9ea55a1c3a87007cd133263f79e405
+d = 24b1e5676d1a9d6b645a984141a157c124531feeb92d915110aef474b1e27666
+Qx = b4909a5bdf25f7659f4ef35e4b811429fb2c59126e3dad09100b46aea6ebe7a6
+Qy = 760ae015fa6af5c9749c4030fdb5de6e58c6b5b1944829105cf7edf7d3a22cfb
+k = 88794923d8943b5dbcc7a7a76503880ff7da632b0883aaa60a9fcc71bf880fd6
+R = 6ec9a340b77fae3c7827fa96d997e92722ff2a928217b6dd3c628f3d49ae4ce6
+S = 637b54bbcfb7e7d8a41ea317fcfca8ad74eb3bb6b778bc7ef9dec009281976f7
+
+Msg = 8144e37014c95e13231cbd6fa64772771f93b44e37f7b02f592099cc146343edd4f4ec9fa1bc68d7f2e9ee78fc370443aa2803ff4ca52ee49a2f4daf2c8181ea7b8475b3a0f608fc3279d09e2d057fbe3f2ffbe5133796124781299c6da60cfe7ecea3abc30706ded2cdf18f9d788e59f2c31662df3abe01a9b12304fb8d5c8c
+d = bce49c7b03dcdc72393b0a67cf5aa5df870f5aaa6137ada1edc7862e0981ec67
+Qx = c786d9421d67b72b922cf3def2a25eeb5e73f34543eb50b152e738a98afb0ca5
+Qy = 6796271e79e2496f9e74b126b1123a3d067de56b5605d6f51c8f6e1d5bb93aba
+k = 89e690d78a5e0d2b8ce9f7fcbf34e2605fd9584760fa7729043397612dd21f94
+R = 07e5054c384839584624e8d730454dc27e673c4a90cbf129d88b91250341854d
+S = f7e665b88614d0c5cbb3007cafe713763d81831525971f1747d92e4d1ca263a7
+
+Msg = a3683d120807f0a030feed679785326698c3702f1983eaba1b70ddfa7f0b3188060b845e2b67ed57ee68087746710450f7427cb34655d719c0acbc09ac696adb4b22aba1b9322b7111076e67053a55f62b501a4bca0ad9d50a868f51aeeb4ef27823236f5267e8da83e143047422ce140d66e05e44dc84fb3a4506b2a5d7caa8
+d = 73188a923bc0b289e81c3db48d826917910f1b957700f8925425c1fb27cabab9
+Qx = 86662c014ab666ee770723be8da38c5cd299efc6480fc6f8c3603438fa8397b9
+Qy = f26b3307a650c3863faaa5f642f3ba1384c3d3a02edd3d48c657c269609cc3fc
+k = ec90584ab3b383b590626f36ed4f5110e49888aec7ae7a9c5ea62dd2dc378666
+R = 13e9ad59112fde3af4163eb5c2400b5e9a602576d5869ac1c569075f08c90ff6
+S = 708ac65ff2b0baaccc6dd954e2a93df46016bd04457636de06798fcc17f02be5
+
+Msg = b1df8051b213fc5f636537e37e212eb20b2423e6467a9c7081336a870e6373fc835899d59e546c0ac668cc81ce4921e88f42e6da2a109a03b4f4e819a17c955b8d099ec6b282fb495258dca13ec779c459da909475519a3477223c06b99afbd77f9922e7cbef844b93f3ce5f50db816b2e0d8b1575d2e17a6b8db9111d6da578
+d = f637d55763fe819541588e0c603f288a693cc66823c6bb7b8e003bd38580ebce
+Qx = 74a4620c578601475fc169a9b84be613b4a16cb6acab8fd98848a6ec9fbd133d
+Qy = 42b9e35d347c107e63bd55f525f915bcf1e3d2b81d002d3c39acf10fc30645a1
+k = 4d578f5099636234d9c1d566f1215d5d887ae5d47022be17dbf32a11a03f053b
+R = 113a933ebc4d94ce1cef781e4829df0c493b0685d39fb2048ce01b21c398dbba
+S = 3005bd4ec63dbd04ce9ff0c6246ad65d27fcf62edb2b7e461589f9f0e7446ffd
+
+Msg = 0b918ede985b5c491797d0a81446b2933be312f419b212e3aae9ba5914c00af431747a9d287a7c7761e9bcbc8a12aaf9d4a76d13dad59fc742f8f218ef66eb67035220a07acc1a357c5b562ecb6b895cf725c4230412fefac72097f2c2b829ed58742d7c327cad0f1058df1bddd4ae9c6d2aba25480424308684cecd6517cdd8
+d = 2e357d51517ff93b821f895932fddded8347f32596b812308e6f1baf7dd8a47f
+Qx = 7e4078a1d50c669fb2996dd9bacb0c3ac7ede4f58fa0fa1222e78dbf5d1f4186
+Qy = 0014e46e90cc171fbb83ea34c6b78202ea8137a7d926f0169147ed5ae3d6596f
+k = be522b0940b9a40d84bf790fe6abdc252877e671f2efa63a33a65a512fc2aa5c
+R = a26b9ad775ac37ff4c7f042cdc4872c5e4e5e800485f488ddfaaed379f468090
+S = f88eae2019bebbba62b453b8ee3472ca5c67c267964cffe0cf2d2933c1723dff
+
+Msg = 0fab26fde1a4467ca930dbe513ccc3452b70313cccde2994eead2fde85c8da1db84d7d06a024c9e88629d5344224a4eae01b21a2665d5f7f36d5524bf5367d7f8b6a71ea05d413d4afde33777f0a3be49c9e6aa29ea447746a9e77ce27232a550b31dd4e7c9bc8913485f2dc83a56298051c92461fd46b14cc895c300a4fb874
+d = 77d60cacbbac86ab89009403c97289b5900466856887d3e6112af427f7f0f50b
+Qx = a62032dfdb87e25ed0c70cad20d927c7effeb2638e6c88ddd670f74df16090e5
+Qy = 44c5ee2cf740ded468f5d2efe13daa7c5234645a37c073af35330d03a4fed976
+k = 06c1e692b045f425a21347ecf72833d0242906c7c1094f805566cdcb1256e394
+R = eb173b51fb0aec318950d097e7fda5c34e529519631c3e2c9b4550b903da417d
+S = ca2c13574bf1b7d56e9dc18315036a31b8bceddf3e2c2902dcb40f0cc9e31b45
+
+Msg = 7843f157ef8566722a7d69da67de7599ee65cb3975508f70c612b3289190e364141781e0b832f2d9627122742f4b5871ceeafcd09ba5ec90cae6bcc01ae32b50f13f63918dfb5177df9797c6273b92d103c3f7a3fc2050d2b196cc872c57b77f9bdb1782d4195445fcc6236dd8bd14c8bcbc8223a6739f6a17c9a861e8c821a6
+d = 486854e77962117f49e09378de6c9e3b3522fa752b10b2c810bf48db584d7388
+Qx = 760b5624bd64d19c866e54ccd74ad7f98851afdbc3ddeae3ec2c52a135be9cfa
+Qy = feca15ce9350877102eee0f5af18b2fed89dc86b7df0bf7bc2963c1638e36fe8
+k = e4f77c6442eca239b01b0254e11a4182782d96f48ab521cc3d1d68df12b5a41a
+R = bdff14e4600309c2c77f79a25963a955b5b500a7b2d34cb172cd6acd52905c7b
+S = b0479cdb3df79923ec36a104a129534c5d59f622be7d613aa04530ad2507d3a2
+
+[P-256,SHA-512]
+
+Msg = 6c8572b6a3a4a9e8e03dbeed99334d41661b8a8417074f335ab1845f6cc852adb8c01d9820fcf8e10699cc827a8fbdca2cbd46cc66e4e6b7ba41ec3efa733587e4a30ec552cd8ddab8163e148e50f4d090782897f3ddac84a41e1fcfe8c56b6152c0097b0d634b41011471ffd004f43eb4aafc038197ec6bae2b4470e869bded
+d = 9dd0d3a3d514c2a8adb162b81e3adfba3299309f7d2018f607bdb15b1a25f499
+Qx = 6b738de3398b6ac57b9591f9d7985dd4f32137ad3460dcf8970c1390cb9eaf8d
+Qy = 83bc61e26d2bbbd3cf2d2ab445a2bc4ab5dde41f4a13078fd1d3cc36ab596d57
+k = 9106192170ccb3c64684d48287bb81bbed51b40d503462c900e5c7aae43e380a
+R = 275fa760878b4dc05e9d157fedfd8e9b1c9c861222a712748cb4b7754c043fb1
+S = 699d906bb8435a05345af3b37e3b357786939e94caae257852f0503adb1e0f7e
+
+Msg = 7e3c8fe162d48cc8c5b11b5e5ebc05ebc45c439bdbc0b0902145921b8383037cb0812222031598cd1a56fa71694fbd304cc62938233465ec39c6e49f57dfe823983b6923c4e865633949183e6b90e9e06d8275f3907d97967d47b6239fe2847b7d49cf16ba69d2862083cf1bccf7afe34fdc90e21998964107b64abe6b89d126
+d = f9bf909b7973bf0e3dad0e43dcb2d7fa8bda49dbe6e5357f8f0e2bd119be30e6
+Qx = f2a6674d4e86152a527199bed293fa63acde1b4d8a92b62e552210ba45c38792
+Qy = c72565c24f0eee6a094af341ddd8579747b865f91c8ed5b44cda8a19cc93776f
+k = e547791f7185850f03d0c58419648f65b9d29cdc22ed1de2a64280220cfcafba
+R = 4782903d2aaf8b190dab5cae2223388d2d8bd845b3875d37485c54e1ded1d3d8
+S = dfb40e406bfa074f0bf832771b2b9f186e2211f0bca279644a0ca8559acf39da
+
+Msg = d5aa8ac9218ca661cd177756af6fbb5a40a3fecfd4eea6d5872fbb9a2884784aa9b5f0c023a6e0da5cf6364754ee6465b4ee2d0ddc745b02994c98427a213c849537da5a4477b3abfe02648be67f26e80b56a33150490d062aaac137aa47f11cfeddba855bab9e4e028532a563326d927f9e6e3292b1fb248ee90b6f429798db
+d = 724567d21ef682dfc6dc4d46853880cfa86fe6fea0efd51fac456f03c3d36ead
+Qx = 70b877b5e365fcf08140b1eca119baba662879f38e059d074a2cb60b03ea5d39
+Qy = 5f56f94d591df40b9f3b8763ac4b3dbe622c956d5bd0c55658b6f46fa3deb201
+k = 79d6c967ed23c763ece9ca4b026218004c84dc2d4ccc86cf05c5d0f791f6279b
+R = 2ba2ea2d316f8937f184ad3028e364574d20a202e4e7513d7af57ac2456804d1
+S = 64fe94968d18c5967c799e0349041b9e40e6c6c92ebb475e80dd82f51cf07320
+
+Msg = 790b06054afc9c3fc4dfe72df19dd5d68d108cfcfca6212804f6d534fd2fbe489bd8f64bf205ce04bcb50124a12ce5238fc3fe7dd76e6fa640206af52549f133d593a1bfd423ab737f3326fa79433cde293236f90d4238f0dd38ed69492ddbd9c3eae583b6325a95dec3166fe52b21658293d8c137830ef45297d67813b7a508
+d = 29c5d54d7d1f099d50f949bfce8d6073dae059c5a19cc70834722f18a7199edd
+Qx = 3088d4f45d274cc5f418c8ecc4cbcf96be87491f420250f8cbc01cdf2503ec47
+Qy = 634db48198129237ed068c88ff5809f6211921a6258f548f4b64dd125921b78b
+k = 0508ad7774908b5705895fda5c3b7a3032bf85dab7232bf981177019f3d76460
+R = acd9f3b63626c5f32103e90e1dd1695907b1904aa9b14f2132caef331321971b
+S = 15c04a8bd6c13ed5e9961814b2f406f064670153e4d5465dcef63c1d9dd52a87
+
+Msg = 6d549aa87afdb8bfa60d22a68e2783b27e8db46041e4df04be0c261c4734b608a96f198d1cdb8d082ae48579ec9defcf21fbc72803764a58c31e5323d5452b9fb57c8991d31749140da7ef067b18bf0d7dfbae6eefd0d8064f334bf7e9ec1e028daed4e86e17635ec2e409a3ed1238048a45882c5c57501b314e636b9bc81cbe
+d = 0d8095da1abba06b0d349c226511f642dabbf1043ad41baa4e14297afe8a3117
+Qx = 75a45758ced45ecf55f755cb56ca2601d794ebeaeb2e6107fe2fc443f580e23c
+Qy = 5303d47d5a75ec821d51a2ee7548448208c699eca0cd89810ffc1aa4faf81ead
+k = 5165c54def4026ab648f7768c4f1488bcb183f6db7ffe02c7022a529a116482a
+R = ebc85fc4176b446b3384ccc62fc2526b45665561a0e7e9404ac376c90e450b59
+S = 8b2c09428e62c5109d17ed0cf8f9fd7c370d018a2a73f701effc9b17d04852c6
+
+Msg = 1906e48b7f889ee3ff7ab0807a7aa88f53f4018808870bfed6372a77330c737647961324c2b4d46f6ee8b01190474951a701b048ae86579ff8e3fc889fecf926b17f98958ac7534e6e781ca2db2baa380dec766cfb2a3eca2a9d5818967d64dfab84f768d24ec122eebacaab0a4dc3a75f37331bb1c43dd8966cc09ec4945bbd
+d = 52fe57da3427b1a75cb816f61c4e8e0e0551b94c01382b1a80837940ed579e61
+Qx = 2177e20a2092a46667debdcc21e7e45d6da72f124adecbc5ada6a7bcc7b401d5
+Qy = 550e468f2626070a080afeeb98edd75a721eb773c8e62149f3e903cf9c4d7b61
+k = 0464fe9674b01ff5bd8be21af3399fad66f90ad30f4e8ee6e2eb9bcccfd5185c
+R = f8250f073f34034c1cde58f69a85e2f5a030703ebdd4dbfb98d3b3690db7d114
+S = a9e83e05f1d6e0fef782f186bedf43684c825ac480174d48b0e4d31505e27498
+
+Msg = 7b59fef13daf01afec35dea3276541be681c4916767f34d4e874464d20979863ee77ad0fd1635bcdf93e9f62ed69ae52ec90aab5bbf87f8951213747ccec9f38c775c1df1e9d7f735c2ce39b42edb3b0c5086247556cfea539995c5d9689765288ec600848ecf085c01ca738bbef11f5d12d4457db988b4add90be00781024ad
+d = 003d91611445919f59bfe3ca71fe0bfdeb0e39a7195e83ac03a37c7eceef0df2
+Qx = 7b9c592f61aae0555855d0b9ebb6fd00fb6746e8842e2523565c858630b9ba00
+Qy = d35b2e168b1875bbc563bea5e8d63c4e38957c774a65e762959a349eaf263ba0
+k = ef9df291ea27a4b45708f7608723c27d7d56b7df0599a54bc2c2fabbff373b40
+R = 66d057fd39958b0e4932bacd70a1769bbadcb62e4470937b45497a3d4500fabb
+S = 6c853b889e18b5a49ee54b54dd1aaedfdd642e30eba171c5cab677f0df9e7318
+
+Msg = 041a6767a935dc3d8985eb4e608b0cbfebe7f93789d4200bcfe595277ac2b0f402889b580b72def5da778a680fd380c955421f626d52dd9a83ea180187b850e1b72a4ec6dd63235e598fd15a9b19f8ce9aec1d23f0bd6ea4d92360d50f951152bc9a01354732ba0cf90aaed33c307c1de8fa3d14f9489151b8377b57c7215f0b
+d = 48f13d393899cd835c4193670ec62f28e4c4903e0bbe5817bf0996831a720bb7
+Qx = 82a1a96f4648393c5e42633ecdeb1d8245c78c5ea236b5bab460dedcc8924bc0
+Qy = e8cbf03c34b5154f876de19f3bb6fd43cd2eabf6e7c95467bcfa8c8fc42d76fd
+k = efed736e627899fea944007eea39a4a63c0c2e26491cd12adb546be3e5c68f7d
+R = cf7fc24bdaa09ac0cca8497e13298b961380668613c7493954048c06385a7044
+S = f38b1c8306cf82ab76ee3a772b14416b49993fe11f986e9b0f0593c52ec91525
+
+Msg = 7905a9036e022c78b2c9efd40b77b0a194fbc1d45462779b0b76ad30dc52c564e48a493d8249a061e62f26f453ba566538a4d43c64fb9fdbd1f36409316433c6f074e1b47b544a847de25fc67d81ac801ed9f7371a43da39001c90766f943e629d74d0436ba1240c3d7fab990d586a6d6ef1771786722df56448815f2feda48f
+d = 95c99cf9ec26480275f23de419e41bb779590f0eab5cf9095d37dd70cb75e870
+Qx = 42c292b0fbcc9f457ae361d940a9d45ad9427431a105a6e5cd90a345fe3507f7
+Qy = 313b08fd2fa351908b3178051ee782cc62b9954ad95d4119aa564900f8ade70c
+k = 4c08dd0f8b72ae9c674e1e448d4e2afe3a1ee69927fa23bbff3716f0b99553b7
+R = f2bc35eb1b8488b9e8d4a1dbb200e1abcb855458e1557dc1bf988278a174eb3b
+S = ed9a2ec043a1d578e8eba6f57217976310e8674385ad2da08d6146c629de1cd9
+
+Msg = cf25e4642d4f39d15afb7aec79469d82fc9aedb8f89964e79b749a852d931d37436502804e39555f5a3c75dd958fd5291ada647c1a5e38fe7b1048f16f2b711fdd5d39acc0812ca65bd50d7f8119f2fd195ab16633503a78ee9102c1f9c4c22568e0b54bd4fa3f5ff7b49160bf23e7e2231b1ebebbdaf0e4a7d4484158a87e07
+d = e15e835d0e2217bc7c6f05a498f20af1cd56f2f165c23d225eb3360aa2c5cbcf
+Qx = 89dd22052ec3ab4840206a62f2270c21e7836d1a9109a3407dd0974c7802b9ae
+Qy = e91609ba35c7008b080c77a9068d97a14ca77b97299e74945217672b2fd5faf0
+k = c9f621441c235fc47ec34eef4c08625df1ec74918e1f86075b753f2589f4c60b
+R = a70d1a2d555d599bfb8c9b1f0d43725341151d17a8d0845fa56f3563703528a7
+S = 4e05c45adf41783e394a5312f86e66871c4be4896948c85966879d5c66d54b37
+
+Msg = 7562c445b35883cc937be6349b4cefc3556a80255d70f09e28c3f393daac19442a7eecedcdfbe8f7628e30cd8939537ec56d5c9645d43340eb4e78fc5dd4322de8a07966b262770d7ff13a071ff3dce560718e60ed3086b7e0003a6abafe91af90af86733ce8689440bf73d2aa0acfe9776036e877599acbabfcb03bb3b50faa
+d = 808c08c0d77423a6feaaffc8f98a2948f17726e67c15eeae4e672edbe388f98c
+Qx = b0c0ad5e1f6001d8e9018ec611b2e3b91923e69fa6c98690ab644d650f640c42
+Qy = 610539c0b9ed21ac0a2f27527c1a61d9b47cbf033187b1a6ada006eb5b2662ed
+k = 1f6d4a905c761a53d54c362976717d0d7fc94d222bb5489e4830080a1a67535d
+R = 83404dcf8320baf206381800071e6a75160342d19743b4f176960d669dd03d07
+S = 3f75dcf102008b2989f81683ae45e9f1d4b67a6ef6fd5c8af44828af80e1cfb5
+
+Msg = 051c2db8e71e44653ea1cb0afc9e0abdf12658e9e761bfb767c20c7ab4adfcb18ed9b5c372a3ac11d8a43c55f7f99b33355437891686d42362abd71db8b6d84dd694d6982f0612178a937aa934b9ac3c0794c39027bdd767841c4370666c80dbc0f8132ca27474f553d266deefd7c9dbad6d734f9006bb557567701bb7e6a7c9
+d = f7c6315f0081acd8f09c7a2c3ec1b7ece20180b0a6365a27dcd8f71b729558f9
+Qx = 250f7112d381c1751860045d9bcaf20dbeb25a001431f96ac6f19109362ffebb
+Qy = 49fba9efe73546135a5a31ab3753e247034741ce839d3d94bd73936c4a17e4aa
+k = 68c299be2c0c6d52d208d5d1a9e0ffa2af19b4833271404e5876e0aa93987866
+R = 7b195e92d2ba95911cda7570607e112d02a1c847ddaa33924734b51f5d81adab
+S = 10d9f206755cef70ab5143ac43f3f8d38aea2644f31d52eaf3b472ee816e11e5
+
+Msg = 4dcb7b62ba31b866fce7c1feedf0be1f67bf611dbc2e2e86f004422f67b3bc1839c6958eb1dc3ead137c3d7f88aa97244577a775c8021b1642a8647bba82871e3c15d0749ed343ea6cad38f123835d8ef66b0719273105e924e8685b65fd5dc430efbc35b05a6097f17ebc5943cdcd9abcba752b7f8f37027409bd6e11cd158f
+d = f547735a9409386dbff719ce2dae03c50cb437d6b30cc7fa3ea20d9aec17e5a5
+Qx = 4ca87c5845fb04c2f76ae3273073b0523e356a445e4e95737260eba9e2d021db
+Qy = 0f86475d07f82655320fdf2cd8db23b21905b1b1f2f9c48e2df87e24119c4880
+k = 91bd7d97f7ed3253cedefc144771bb8acbbda6eb24f9d752bbe1dd018e1384c7
+R = 008c1755d3df81e64e25270dbaa9396641556df7ffc7ac9add6739c382705397
+S = 77df443c729b039aded5b516b1077fecdd9986402d2c4b01734ba91e055e87fc
+
+Msg = efe55737771070d5ac79236b04e3fbaf4f2e9bed187d1930680fcf1aba769674bf426310f21245006f528779347d28b8aeacd2b1d5e3456dcbf188b2be8c07f19219e4067c1e7c9714784285d8bac79a76b56f2e2676ea93994f11eb573af1d03fc8ed1118eafc7f07a82f3263c33eb85e497e18f435d4076a774f42d276c323
+d = 26a1aa4b927a516b661986895aff58f40b78cc5d0c767eda7eaa3dbb835b5628
+Qx = 28afa3b0f81a0e95ad302f487a9b679fcdef8d3f40236ec4d4dbf4bb0cbba8b2
+Qy = bb4ac1be8405cbae8a553fbc28e29e2e689fabe7def26d653a1dafc023f3cecf
+k = f98e1933c7fad4acbe94d95c1b013e1d6931fa8f67e6dbb677b564ef7c3e56ce
+R = 15a9a5412d6a03edd71b84c121ce9a94cdd166e40da9ce4d79f1afff6a395a53
+S = 86bbc2b6c63bad706ec0b093578e3f064736ec69c0dba59b9e3e7f73762a4dc3
+
+Msg = ea95859cc13cccb37198d919803be89c2ee10befdcaf5d5afa09dcc529d333ae1e4ffd3bd8ba8642203badd7a80a3f77eeee9402eed365d53f05c1a995c536f8236ba6b6ff8897393506660cc8ea82b2163aa6a1855251c87d935e23857fe35b889427b449de7274d7754bdeace960b4303c5dd5f745a5cfd580293d6548c832
+d = 6a5ca39aae2d45aa331f18a8598a3f2db32781f7c92efd4f64ee3bbe0c4c4e49
+Qx = c62cc4a39ace01006ad48cf49a3e71466955bbeeca5d318d672695df926b3aa4
+Qy = c85ccf517bf2ebd9ad6a9e99254def0d74d1d2fd611e328b4a3988d4f045fe6f
+k = dac00c462bc85bf39c31b5e01df33e2ec1569e6efcb334bf18f0951992ac6160
+R = 6e7ff8ec7a5c48e0877224a9fa8481283de45fcbee23b4c252b0c622442c26ad
+S = 3dfac320b9c873318117da6bd856000a392b815659e5aa2a6a1852ccb2501df3
+
+
+
+[P-384,SHA-224]
+
+Msg = 39f0b25d4c15b09a0692b22fbacbb5f8aee184cb75887e2ebe0cd3be5d3815d29f9b587e10b3168c939054a89df11068e5c3fac21af742bf4c3e9512f5569674e7ad8b39042bcd73e4b7ce3e64fbea1c434ed01ad4ad8b5b569f6a0b9a1144f94097925672e59ba97bc4d33be2fa21b46c3dadbfb3a1f89afa199d4b44189938
+d = 0af857beff08046f23b03c4299eda86490393bde88e4f74348886b200555276b93b37d4f6fdec17c0ea581a30c59c727
+Qx = 00ea9d109dbaa3900461a9236453952b1f1c2a5aa12f6d500ac774acdff84ab7cb71a0f91bcd55aaa57cb8b4fbb3087d
+Qy = 0fc0e3116c9e94be583b02b21b1eb168d8facf3955279360cbcd86e04ee50751054cfaebcf542538ac113d56ccc38b3e
+k = e2f0ce83c5bbef3a6eccd1744f893bb52952475d2531a2854a88ff0aa9b12c65961e2e517fb334ef40e0c0d7a31ed5f5
+R = c36e5f0d3de71411e6e519f63e0f56cff432330a04fefef2993fdb56343e49f2f7db5fcab7728acc1e33d4692553c02e
+S = 0d4064399d58cd771ab9420d438757f5936c3808e97081e457bc862a0c905295dca60ee94f4537591c6c7d217453909b
+
+Msg = 5a3c80e608ed3ac75a6e45f6e94d374271a6d42b67a481860d5d309cc8b37c79cb61f1716dc8aa84cb309ef9d68eb7fc6cf4b42333f316a5c30e74198c8b340926e340c5de47674a707293c4aa2a1a2274a602f01c26b156e895499c60b38ef53fc2032e7485c168d73700d6fa14232596a0e4997854a0b05d02e351b9d3de96
+d = 047dd5baab23f439ec23b58b7e6ff4cc37813cccb4ea73bb2308e6b82b3170edfe0e131eca50841bf1b686e651c57246
+Qx = de92ff09af2950854a70f2178d2ed50cc7042a7188301a1ea81d9629ad3c29795cb7f0d56630a401e4d6e5bed0068d1e
+Qy = 6135adbd8624130735e64e65ecbd43770dcc12b28e737b5ed033666f34c918eb5589508e4a13b9243374a118a628dd0b
+k = f3922351d14f1e5af84faab12fe57ded30f185afe5547aeb3061104740ecc42a8df0c27f3877b4d855642b78938c4e05
+R = 38e181870cb797c1f4e6598cfd032add1cb60447d33473038d06df73919f844eddd16f40f911075f8a4bacc0d924e684
+S = a58dd1ca18aa31277de66c30c3bb7a14b53705ce6c547ed2cb0e336f63c42809422efffcc722d1155f2254330a02b278
+
+Msg = e7d974c5dbd3bfb8a2fb92fdd782f997d04be79e9713944ce13c5eb6f75dfdec811b7ee4b3859114b07f263846ae13f795eec8f3cb5b7565baff68e0fdd5e09ba8b176d5a71cb03fbc5546e6937fba560acb4db24bd42de1851432b96e8ca4078313cb849bce29c9d805258601d67cd0259e255f3048682e8fdbdda3398c3e31
+d = 54ba9c740535574cebc41ca5dc950629674ee94730353ac521aafd1c342d3f8ac52046ed804264e1440d7fe409c45c83
+Qx = 3db95ded500b2506b627270bac75688dd7d44f47029adeff99397ab4b6329a38dbb278a0fc58fe4914e6ae31721a6875
+Qy = 049288341553a9ac3dc2d9e18e7a92c43dd3c25ca866f0cb4c68127bef6b0e4ba85713d27d45c7d0dc57e5782a6bf733
+k = 04324bd078807f6b18507a93ee60da02031717217ee5ce569750737be912be72da087ac00f50e13fdf7249a6ae33f73e
+R = b2752aa7abc1e5a29421c9c76620bcc3049ecc97e6bc39fcca126f505a9a1bfae3bde89fb751a1aa7b66fa8db3891ef0
+S = f1c69e6d818ca7ae3a477049b46420cebd910c0a9a477fd1a67a38d628d6edaac123aebfca67c53a5c80fe454dba7a9d
+
+Msg = a670fda4d1d56c70de1d8680328043b2b7029633caf0ee59ffe1421c914bb937133d5a0f9214846b2e0b350455a74c4ab434c56de65a17139bb8212bf1c76071a37536fa29348f871dbb26baa92eb93d97e923a6d2ffd9be25cbc33075e494e6db657bd8dc053fe4e17148d8cf6e2058164f2b5766750eb01bbe7b361cdb848c
+d = dabe87bbe95499bac23bc83c8b7307fe04be198f00059e2bf67c9611feaffb2c8f274f6aa50eb99c3074186d8067d659
+Qx = c2aa0a695125279705917e02a4f258cade4c3ff9140a071414babf87764f426f7f36ffda9d5f3394375d24864235476f
+Qy = 8f9808da0ce0227cf453f9e456f557db9752e23b45cce4baad5fee3844ddd7e1112bcec01ea9d67c7a76f3535bd0cb58
+k = 65a0305854033cbc6fe3ca139c40ca354d45801ecb59f4a923c251dc6b25d12d452d99b5d6711fdb5efac812aa464cc4
+R = c7fc32997d17ac79baf5789e4503f5f1a8863872bc350a91f12dd3ef8cf78c254e829217809e8e00b6b8d4d85be3f1fd
+S = 1422e1838a22496df93486bce1142961dbd8478ae844b8dda54e210afdae0d9e930d587c91bb600b0bde7237186d94e6
+
+Msg = 7843f918fe2588bcfe756e1f05b491d913523255aa006818be20b676c957f4edb8df863c6f5f8c15b3b80c7a2aa277b70d53f210bdfb856337980c406ea140e439dd321471407f374f69877b2d82367eed51e3c82c13948616dcb301d0c31f8f0352f2846abd9e72071f446a2f1bd3339a09ae41b84e150fd18f4ba5d3c6bfa0
+d = df43107a1deb24d02e31d479087bd669e2bc3e50f1f44b7db9484a7143cdca6a3391bddfea72dc940dbce8ec5efbd718
+Qx = 76bd4be5d520471162cb5c36f80038301b325f845d9642204a84d78b3e721098932827bf872bde0a9f86383953667d29
+Qy = 415116b8b878f896a5aa4dbbdc21076f27135d8bbcaaca02489ef639d742bd63f377da0c8e8ab36ff19b4a7cc5d4ceb4
+k = 798abad5a30d1805794540057388ee05e2422901c6335f985b9d4447b3ef75524751abfeab6409ad6bf77d4ae3014558
+R = 98744e5c6742fa5118a74a70db4957647a3cc12add4e876b45974a6a8707809f871daadbfc0b865e01624f706b65f10c
+S = 9e256e8da8eff5a0c83baaa1ef4f7be798eba9543bf97adb0fff8719f5406ea1207a0cf703d99aa8f02169724b492273
+
+Msg = caa83d5ab07febbd2e0fe2d63738b9b7b8752594bea7aaf50345b3d2f316653a8c9222f2b7877b64679e9573e81461a426029e45b8873a575094a1d572e0d32a9f0a9c6bcb9a2868543b7d8bbe4a69a09e7321f05f8366cced1b72df526f895b60aed2c39c249653c7839538770d4e5f47d3926ec0d168ab6a1af15bf1dca1f7
+d = ea7a563ba2a7f5ab69973dca1f1a0d1572f0c59817cd3b62ad356c2099e2cdca1c553323563f9dfbb333b126d84abc7f
+Qx = cf4717c5f5de668b785f06bdc9845df5a09e4edd83f4669756407cbb60807305c632bc49f818f4a84b194369aa07736f
+Qy = 7391e4982af8a2218f704f627d01f0508bfc8304992a2d598a420bf2eb519f33bd7caf79380793733b3dba0cc5e2b9d8
+k = 7b9606b3df7b2a340dbc68d9754de0734e1faeb5a0135578a97628d948702235c60b20c8002c8fcf906783e1b389e754
+R = 0d680010bed373287f9767955b5d2850e150b6713b49e453eb280148e45230c853d99ea2d2f8fcbd3ddcba19aeec0af1
+S = 64329763a930ab5452afdb0557fef16ff71810d6343dfc9c6ae18905c3d274db6554cdc69d6078a1ca03284474a94f30
+
+Msg = 594603458d6534974aeeafba919c4d0f4cb6843a3af41204bbb88aeb2fca2772d305163dba863da050aabedbaf89db521955d1715de95bbcef979ecdc0c976181ece00355385f8a8f8cce127c9eac15ce3e958a3ed686184674ec9a50eb63271606ee7fdcb1323da3c3db8e89cad1fb42139a32d08abcfbf0d4ccfca18c89a86
+d = 4cc70cb35b3ddeb0df53a6bd7bd05f8ff4392a2db7344f2d443761484b3a468a4ee3d1a8b27113d57283fd18b05f7829
+Qx = 40e1fe21df34bb85a642a0abe819ebd128f7e39b84d8dcc4a9a599b372fb9588da1484600ec28b1297bb685f9ae77831
+Qy = f3aa69ada57879fdcbe8df19cefabc308add7d03b17b1fac2f7783fece6a8dfe20bc36f518692677d96e3f730a67a671
+k = 8eda401d98f5688c34d8dbebcd3991c87c0442b0379154eaa2e5287dabe9a9e34cfc1305d11ff68781df25d5611b331d
+R = ff2d772786e159448bba26afd8c3281941a4cb0c56fec6f5cccb4c292c4ee0f7af9bd39bbe2d88148732585e104fdb30
+S = 07a1d890770daa949a17797dca7af3e8163da981ec330c03d63d1a8312c152be6a718163205ffa08da7dcc163ba261f4
+
+Msg = 733252d2bd35547838be22656cc7aa67eff0af0b13b428f77267a513c6824c3dbae533068b6817e82665f009560affcfe4b2ddb5b667a644fc1a42d24f24e0947e0dc50fb62c919bc1fe4e7ded5e28f2e6d80fcf66a081fb2763526f8def5a81a4ddd38be0b59ee839da1643eeeaee7b1927cec12cf3da67c02bc5465151e346
+d = 366d15e4cd7605c71560a418bd0f382fd7cd7ad3090ff1b2dfbed74336166a905e1b760cf0bccee7a0e66c5ebfb831f1
+Qx = a143f277ab36a10b645ff6c58241ea67ffdc8acf12d60973068390f06b4d8f4d773b10c1ebf6889b1cfa73ebb90f6ca1
+Qy = 7a17cad29bb507b309021f6f92cb5c10ba535f4a3e317fcc68cfd02d3ccd269f465169c73d30ff308f5350d881b08aec
+k = dbe545f920bc3d704c43d834bab21e40df12ec9e16a619a3e6b3f08760c26aae6e4fd91fad00f745194794b74bb1baee
+R = cdc39b12bba30da66fe9554713c05880ddc27afa4d2d151440f124c351fb9496dc95046516b0921083347d64369846ac
+S = 797d0344e49f9ba87a187c50f664e5015d449e346b1a7bd9427c5be559fc58173651880d5aadf053f81899d3368d6181
+
+Msg = 5a182bd174feb038dfae3346267156bf663167f713dea1ce936b0edb815cd9b8c8e4d411c786ba2494a81442617255db7158b142e720d86c9b56680fb9efd4298cdd69079a28153494c42a24251c7ad42ecf7e97eabc1b3997529b2a297cbad2474269b87a0b1e385f2d7f8b6eb8d1cd75eaf7e91d1acbecd45d7b2bfbbe3216
+d = e357d869857a52a06e1ece5593d16407022354780eb9a7cb8575cef327f877d22322c006b3c8c11e3d7d296a708bdb6d
+Qx = ce9a2185a68d6094aa5849a6efe78b349946f7380f0c79aa9664246cfcc71a879e90ad78a0474f58644c6a208168150e
+Qy = 8354fa47673cb3e07d446521345706c5515584b2602f921c3b9c44dded9e2c3f90ce47adb36d7e5f9f95a8c5ad8af397
+k = 1e77367ac4e10924854d135ad2f2507f39e2bafdbce33ff256bcbe9a7329b8d27185218bcc3550aafbe3390e84c77292
+R = df3182d49ad70959fb0c95bc7312750ce70fc87f1a328d39d9b29ac05d31305ce7209d6c24d13225d9567b489f7a187b
+S = d812b05abab0e96de13291e1f0da6479444ed5cd9d959b76f6cb43d394769035364f7c831a104dc7b5bd9b4a8e64df64
+
+Msg = aaa99fb1c71340d785a18f6f668e898c25cf7a0ac31d13c5b388b7233408493a5a109af6d07065376b96f4903df7aba2b2af671a18772bb0472490d1240cde28967680727dd4acd47e0308920a75da857a6eeedee5b6586d45dff3d8a680599665aa895c89dd7770b824b7dee477ac5e7602d409d3cc553090c970b50811dbab
+d = 745a18db47324a3710b993d115b2834339315e84e7006eafd889fb49bd3cc5a8b50c90526e65e6c53bddd2916d14bead
+Qx = f692578c6f77531210aef55c9e004ce3b66cf268c6900dde31a8bbb76e7562e3fb76242de34ca330d2501030aa119466
+Qy = 40965833b28de926c46de060aa25beaeda98f8415a6b1e3564aa77870cf4c89bd4fde92c8f5d9bf0eb41721586859d8e
+k = 11b9b36720abcac084efdb44c9f5b7d039e3250cb1e9c47850189ba3cfc1489d858b2a44df357772b61d919c7e729c0f
+R = 02b252c99820cf50e6ce060ab55bd4f682276e29b4ae4197417432e6a7bfb8cf0bac89dfe105456af805d822cee77696
+S = 8e248bbf7d7028d63177e565c9d1666ee5be4d1ffbfffc9c7814b0cd38f74b98f3f2cd59be42b9f132bfe5ee789cd96c
+
+Msg = 1fadfa8254d3a0b82d137cfdd82043d5dc1fef195d5297b09cc5cfb061f59c933451c0dc2a11b4037f34f88dacb803251f8880c4b72585c3c196e6fb23484ca43a191f8e41b9b9a37e2e6fcaab6738c3c62d1c98e1c620bb788b7b51a04f998a510efdba0d3418622fe8ce203b3fcd553b9b4206365a39031797ad11e49745ec
+d = 93f20963ea5011ff4f26481e359309e634195f6289134087bd2e83eee008c962780a679784ee7ac6acda03d663ed27e0
+Qx = 0edcde3533ea019e18f1a3cd97b7962e8823dda36c389f8f9287549f796d11376392b8a01c7a80f127a8f75795e04f54
+Qy = 63d7c458dccfc02f5148d755d59f9bbc8e3c3ea34908777928440747795955741296abcdd5386676419ed8049fedb489
+k = 3ad308faf04c42ee5ac69d36bc0aa9a96aacf55ea0f27dac4f52e088f023d206340a6324874ffad169ff80624de24c96
+R = 209b72f9aae72c4339813573c3a8408a9e0be641ca863d81d9d14c48d0bf4cd44a1a7985cff07b5d68f3f9478475645b
+S = f6292e599b22a76eda95393cf59f4745fa6c472effd1f781879ad9a4437a98080b0b07dadad0c249631c682d2836a977
+
+Msg = 9ecb6f5ed3ba666a8536a81ef65012c2cb8b433508798d84708abb06dfb75503886f78384fb8c7a4d2d49ef539d9b8a0b60938c7f07471dda91f258b0d99691b38a8403a2bb3f956bdfd09baba16d9b6877097a9b6213481b47a06e139d23ec7abad5668d21f912fdb70d31bb9adf9b3ce80e308252fa81a51674f88d02db72b
+d = f175e6ac42fd48ec9d652c10707c039c67c4cc61d8c45a373dcda6e4ca6c53e947e49c24e01b48e7cdf92edfe6d316a1
+Qx = a40c64f595491ce15790a5a87fbe64c1800247b42acd08fe5257700719f46afc8acce0e4ede0517a312092d5e3d089cd
+Qy = d565df9dc2f381cc0c5d84f382a43a98018524c0b4708a44b3e2817f9719f29fbf9c15803591ed9b4790c5adaba9f433
+k = 812dcaa6d4f9a43ccc553288065d13761581485aa903a500a690ccafbd330ba4818c977b98c4bb57f8a182a1afacfae9
+R = d000f18d3e4c162ff0d16f662e6703e7a6f5bff7a333ed266fa4f44c752415946c34945c342c20f739677186b1d80ab3
+S = ae7f1271c89e0aaa238710d039ea73a69110cc28fcf426f2fe6754b63a59e417fa84f903cf7dccb5468b43ff083bbfd5
+
+Msg = e55bfca78d98e68d1b63688db12485578f36c489766f4d0bfaa0088433ff12133aaca455805095f2e655940860958b3ead111d9070778ee3bbf3e47e43d9eba8b8d9b1fdf72f793fcde2bcaa334f3e35fa2cca531ea7cf27fe9ccba741e38ac26129b2d612bf54a34e0ae6c166c0fef07fcd2b9ac253d7e041a500f7be7b8369
+d = 46c4f0b228b28aaa0ec8cfdf1d0ed3408b7ae049312fb9eaf5f3892720e68684cc8ad29844a3dc9d110edf6916dfb8bb
+Qx = 13ddec844731b7e30c467451df08ca11d6c581cb64abd8a257671cffd26f5ccad4df7b9ee8924047a88a5d2d7567609c
+Qy = d74ca94f590fd1d13e190cc1e03c3da6c3faab15c7dda034af3deefee8aeec3628fa8b1978c54cfcd071baa319a46ec0
+k = 2a9dd520207c40a379cd4036adef9ee60fa8bc8c0d39b3ad91850ac93fd543f218b1688581f23481a090b0e4c73792ac
+R = 94e08cca20fe3866f643f53ec65faf3f2b4d80cd9bcc8ff8f88bb28da9eada324fc2d048908dd3d08a9e0ebb547731bc
+S = 8e6f82c4d3069b14f4c844b4ca133a9503493265c9f77a7d4775eda67de76798a23dd7ea48e0ac3c337dd62bf058319d
+
+Msg = 02c6b3c83bd34b288d96409162aa4ff114e9d134bf948046eb5ebcc0c7fe9dfceadda83ed69da2fac00c8840f6c702a3fc5e6959d70f7e8af923e99e4937232ae3b841ffefd2e62fab3671a7c94a0281b8ea5bc176add57c5c9b6893fe7f5d48ce7256b96510810c4e046168a3c5be9843b84d5268a50349b3444341aa5490dd
+d = 1d7b71ef01d0d33a8513a3aed3cabb83829589c8021087a740ca65b570777089be721a61172b874a22a1f81aef3f8bb6
+Qx = 8d2721370df8f097d5a69396249a315f6037dc7045b3da11eacae6d43036f779d5de7053d101768b42cc2b1283a3aaea
+Qy = a046039ae662141f9954d278183eaa2e03917fe58583e32d344074d59d60caa5b0949c53066525d5cca923e2f201502e
+k = d1b25ad25581cad17e96f1d302251681fee5b2efbb71c3c15ff035b2145d015d18e0e52dc3187ab5a560277b3a3929b0
+R = d836f52b14c7391744868daa2d5cf27eb9380b9b6176195573d5b04842e9f2fc3794d6cf877feafee63d11b05f6a6bee
+S = 8b89042fef2c04d4bd6c9d66a06a010514321d623a5f8d57ba5ac3686872eaabca9e0ba2d058ae7028e870acf03ca32d
+
+Msg = 94f8bfbb9dd6c9b6193e84c2023a27dea00fd48356909faec2161972439686c146184f80686bc09e1a698af7df9dea3d24d9e9fd6d7348a146339c839282cf8984345dc6a51096d74ad238c35233012ad729f262481ec7cd6488f13a6ebac3f3d23438c7ccb5a66e2bf820e92b71c730bb12fd64ea1770d1f892e5b1e14a9e5c
+d = cf53bdd4c91fe5aa4d82f116bd68153c907963fa3c9d478c9462bb03c79039493a8eaeb855773f2df37e4e551d509dcd
+Qx = 3a65b26c08102b44838f8c2327ea080daf1e4fc45bb279ce03af13a2f9575f0fff9e2e4423a58594ce95d1e710b590ce
+Qy = fe9dcbcb2ec6e8bd8ed3af3ff0aa619e900cc8bab3f50f6e5f79fac09164fb6a2077cc4f1fed3e9ec6899e91db329bf3
+k = df31908c9289d1fe25e055df199591b23e266433ab8657cc82cb3bca96b88720e229f8dfd42d8b78af7db69342430bca
+R = 6770eea9369d6718e60dd0b91aee845ff7ed7e0fcc91675f56d32e5227fd3a4612bbcb1556fe94a989b9e3bcc25bb20e
+S = c43072f706c98126d06a82b04251e3ecb0ba66c4bb6cd7c025919b9cc6019cdc635256d2a7fa017b806b1e88649d2c0d
+
+[P-384,SHA-256]
+
+Msg = 663b12ebf44b7ed3872b385477381f4b11adeb0aec9e0e2478776313d536376dc8fd5f3c715bb6ddf32c01ee1d6f8b731785732c0d8441df636d8145577e7b3138e43c32a61bc1242e0e73d62d624cdc924856076bdbbf1ec04ad4420732ef0c53d42479a08235fcfc4db4d869c4eb2828c73928cdc3e3758362d1b770809997
+d = c602bc74a34592c311a6569661e0832c84f7207274676cc42a89f058162630184b52f0d99b855a7783c987476d7f9e6b
+Qx = 0400193b21f07cd059826e9453d3e96dd145041c97d49ff6b7047f86bb0b0439e909274cb9c282bfab88674c0765bc75
+Qy = f70d89c52acbc70468d2c5ae75c76d7f69b76af62dcf95e99eba5dd11adf8f42ec9a425b0c5ec98e2f234a926b82a147
+k = c10b5c25c4683d0b7827d0d88697cdc0932496b5299b798c0dd1e7af6cc757ccb30fcd3d36ead4a804877e24f3a32443
+R = b11db00cdaf53286d4483f38cd02785948477ed7ebc2ad609054551da0ab0359978c61851788aa2ec3267946d440e878
+S = 16007873c5b0604ce68112a8fee973e8e2b6e3319c683a762ff5065a076512d7c98b27e74b7887671048ac027df8cbf2
+
+Msg = 784d7f4686c01bea32cb6cab8c089fb25c341080d9832e04feac6ea63a341079cbd562a75365c63cf7e63e7e1dddc9e99db75ccee59c5295340c2bba36f457690a8f05c62ab001e3d6b333780117d1456a9c8b27d6c2504db9c1428dad8ba797a4419914fcc636f0f14ede3fba49b023b12a77a2176b0b8ff55a895dcaf8dbce
+d = 0287f62a5aa8432ff5e95618ec8f9ccaa870dde99c30b51b7673378efe4ccac598f4bbebbfd8993f9abb747b6ad638b9
+Qx = b36418a3014074ec9bbcc6a4b2367a4fb464cca7ec0a324cb68670d5c5e03e7a7eb07da117c5ea50b665ab62bd02a491
+Qy = 4ea299c30e7d76e2c5905babada2d3bb4ee5eb35a5a23605cdb0d5133471a53eb9e6758e49105a4eaf29d2267ba84ef2
+k = 935eeab3edeb281fbd4eead0d9c0babd4b10ff18a31663ee9de3bfa9ae8f9d266441158ea31c889ded9b3c592da77fd7
+R = 738f9cb28f3b991335ef17b62559255faf75cad370a222464a492e27bb173c7f16b22100ada6b695875c7e4b1a28f158
+S = bc998c30e1491cd5d60dc7d1c38333165efe036b2a78db9b8f0e85ee68619cfba654e11ae5ca5ee5a87099c27cf22442
+
+Msg = 45e47fccc5bd6801f237cdbeac8f66ebc75f8b71a6da556d2e002352bd85bf269b6bc7c928d7bb1b0422601e4dd80b29d5906f8fcac212fe0eaaf52eda552303259cbcbe532e60abd3d38d786a45e39a2875bce675800a3eaeb9e42983d9fd9031180abd9adccc9ba30c6c198b4202c4dd70f241e969a3c412724b9b595bc28a
+d = d44d3108873977036c9b97e03f914cba2f5775b68c425d550995574081191da764acc50196f6d2508082a150af5cd41f
+Qx = c703835d723c85c643260379d8445b0c816fe9534351921e14a8e147fe140ec7b0c4d704f8dc66a232b2333b28f03dee
+Qy = c5d0bb054053fd86c26f147c4966757aa04b00513a02d427b8d06c16055c607955efdc518d338abfe7927c195dc28588
+k = c80f63e080650c8a21e4f63a62ec909adfb7d877f365d11ee1cb260baf112eb4730c161c1d99dba98fc0d5bbd00dc97d
+R = 81de2810cde421997013513951a3d537c51a013110d6dbb29251410bcb5ba001a9686b8490f1e581e282fd2ed0974b22
+S = 9cab0bbaffe91c7677ec3dd1f17060211a3cc0be574cbca064aa8c4b66ba6e64f3d80e83da895042ca32d311c388d950
+
+Msg = c33ff63b4e6891e00b2349b3f2907c417ca355560544a91e24a7a0ee260d6850aeded29fc0176b6039ca6187e8333391047cceaf14b1077df8f147dad84d36b2dac5666dc2f69dc9b58b88cc73956efdb3b47f91831d5875051c76b0c4e9fc087012a1f03eeee85d6745b46aa50bd9cb0110c2c94508765cec162ee1aa841d73
+d = d5b72cbb6ec68aca46b9c27ad992afd8ffa02cb3067b234fcfa6e272e3b31be760695ff7df988b57663057ab19dd65e3
+Qx = 135a6542612f1468d8a4d01ff1914e532b1dd64d3627db9d403dc325651d3f82b0f6f0fd1dbdeca2be967c4fb3793b5f
+Qy = cbbd40f6d3a38d0dfb64582ff4789d7b268241bc0c36de2884bccfaeeff3b7b2b46a30bb35719804e0d11124b4e7f480
+k = 9da6de7c87c101b68db64fea40d97f8ad974ceb88224c6796c690cbf61b8bd8eede8470b3caf6e6106b66cf3f0eebd55
+R = 17840911ecdf6ae0428b2634f442163c2c11b8dbf0cc7a5596fbe4d33e3e52f9d99e99ad169867b1f39e89c9180cedc2
+S = dd7ed67e480866d0474379ea4afff72870746f4feef2153be42f13bf472b1613d7faa5c0abb7f7464070f94d7cf3f234
+
+Msg = f562f2b9d84b0e96a52532c3b43c39c8018c738bd8dc3797a7de7353971b2729d522d6961b1f2e4df3f6a4bd3653e6d72b74fc0dba92ab939c4b542e994e5db6dd8ed4f56f651e699052e791237ae1f552f990ad156226ae8f7bf17fcbfa564f749604f97e9df0879d50985747d981422a23040fe52f5ec74caf1d4aaad8a710
+d = 218ee54a71ef2ccf012aca231fee28a2c665fc395ff5cd20bde9b8df598c282664abf9159c5b3923132983f945056d93
+Qx = 01989ff07a7a452d8084937448be946bfedac4049cea34b3db6f7c91d07d69e926cce0af3d6e88855a28120cf3dba8df
+Qy = eb064e029d7539d4b301aabafe8de8870162deffe6383bc63cc005add6ee1d5ced4a5761219c60cd58ad5b2a7c74aaa9
+k = c5d39b436d851d94691f5f4aa9ef447f7989d984f279ae8b091aef5449ac062bcc0567740f914624ad5b99fc32f9af0b
+R = 07d5b1b12877e8cb5e0aa5e71eeeb17bf0aa203064c7e98b3a1798a74dc9717252dc47c7f06aaf1d5fe15b868323bbb9
+S = 69428cf101a7af5d08161a9fd7af212e02e33b6062aebdce4c96bf3a0684b5394cb902ca7c2dec6e2f01f40c4576009d
+
+Msg = ace953ae851f571d71779aa120915f27450b236da23e9106f8d0756abdd25861937941228d225d5fb1aa1b1ebf759b1e326aeb3b6cd0cd87edd2ab9f6a7ad67b63d2c501d6a550edb2e7c9d216cc8af78dd33546af64d00abed4d0d2cfc5c9a7b5a055dbe8f7547902d185cf46937314832bc5c602419a82ab83dbd9d3bd5aff
+d = e6ab171f6937c000e144950801ad91023ae8e8476856c2592d9f7d5bb7180fd729211803d39a412ead6c0be761cfa5d1
+Qx = 38bc42b8c9d8866d09b214398d584b1b24a488dfacc3420d1e9506aa825b19fdf1ba74e7b8f547f47b571467fe8c4d1f
+Qy = 5179d62668d3f6a7ab5c8e3761a685e12008fb87d0529a97645f65cfb5364376c1b6682e0ffcddd0bcd995c41d013ad3
+k = 05e9718aea9669c9e434f73866da5f252dec6d24c47a1c4ee3233450b6ec626de9746ebe095b285558dfc89fc1b622fe
+R = df9bab9dd1f22ec6f27116f38831cb2089aa78aa8c073024a0faddd9a48e810a5e8e2cadd80fbf8dbd6088c71fe30b5b
+S = 1e0e8718567d12d18558c57f9e87a755c309e4ffb497335a3adfc8d7475ce8fd882d5dc33a8f5a16274b7ad74bb7862a
+
+Msg = 9635ab832240be95301bedb94c5aec169eedc198cbbdfedcf41e9b586143d829b4597a6b2a81902828332825fd84a785f187a3894e21bd99d22c4f94dcf34453fc052f15ec64d1447c932cb38fcdd30b7be851963409c11881438cbaad7e96f9efbde317f2235d66af804477a5dfe9f0c51448383830050ecf228889f83631e1
+d = 14acd516c7198798fd42ab0684d18df1cd1c99e304312752b3035bed6535a8975dff8acfc2ba1675787c817b5bff6960
+Qx = 29909d143cf7ee9c74b11d52f1a8f3ebd4a720c135612ca5618d3f432f03a95602ee75a2057e1d7aab51d0648ac0b334
+Qy = 404b6c5adffbadfa1b0380ae89fed96ec1ca16cc28661e623d0f1c8b130fbaa96dd7257eae2bf03c2d3dcbc3dbc82c58
+k = 7f623c103eaa9099a0462e55f80519c565adaeffcb57a29993f3a8a92e63a560be8f0fb9d23dc80bff1064bb41abad79
+R = 932ab291950c16b2b19a8036cd2e905714c6229cb190a73b3ea49c48dd8e76063a453c7c3267a57597d2973678216296
+S = d17d4c5ddbb9c27beebf526f113b416c8abfad53d11c4224813c7f351ba41a77dd4e77d6e4a65bef2c9f62cc37a469a5
+
+Msg = d98b9a7d4fe9d0fd95de5056af164a8b7882cd34ab5bde83a2abb32dc361eb56a479a3a6119db3b91dcad26a42d2206749567f0d97c34a981a91fc734921821a429f6a53401743a5c406ba9d560f956203abc9d1f32f1a13e7d7b290f75c95fdbf857ea597021461c06a3aacfa554ede3d69e4ff03bbbee5b7463ec77de2b3b2
+d = 2e780550984f3a00cb1e412429b33493c6eb6cd86d12f9d80588c247dcf567bd04296d2d4b24b889d9c54954b7f38f57
+Qx = 37dac42ef04663238443ef33e8addee2e78c40d50a1751913a7f5c37d1f23a26c7f86e16055c788b8ca9554f06b2f2ef
+Qy = bbed1549652904e3d00c39b01cc0460dbaf3185e6190c2705677a9701de1fe56dff4f4d8418ee15059ff8fc36800982d
+k = b788ca82811b0d4e4841765c71eafaa1e575378beedcd3860d8b92db3d070ac5aef7c425067860fbee6c50cf0c642bbb
+R = 7292b3851870daeb2555a8a2fb198ead78739fcfb75327e5c32a82c6b77d58983e5ad548ccb75dcf9411039c9576d9b9
+S = a378c61802d9f1dd062b6e18f16416a954018f77df4df95ad1b983570377d5cfce4cc7861759e802c52f81abc4f49aac
+
+Msg = 1b4c754ac1c28dc415a71eac816bde68de7e8db66409af835838c5bb2c605111108a3bf13606ed5d8ade5ed72e50503e0de664416393d178ea4eec834d8d6f15039847b410080fd5529b426e5aadd8451c20ebd92d787921f33e147bcbeb327b104d4aab1157fc1df33e4d768404b5ccb7110055c2508c600f429fd0c21b5784
+d = a24d0fe90808aecc5d90626d7e6da7c9be5dfd4e1233c7f0f71f1b7c1c6fd318fafe18559c94718f044cf02ed5107cb1
+Qx = ec8ae1fb9bb88589d27d6f27d790392853396f37bc0c381631d85800fc668eea0886bf1c6cff801147df19778d5b1604
+Qy = 1e1a8336c1e2506f8ee388b55cc648ae73b9295ea78467979d2affb364536fad28120f51ec62a67cbb6ce7784780389f
+k = 755d025509b73cf1ea8817beb772ad150b4c17a52378be187daffe3db0158921e5e552d1ca3c85df28519939f3cb794d
+R = 23ff2ffa62bbd427d49995d9c9950116e0d5a06ef076a4553448bc109e6482c5e87d4c833bc88de0bc722bc98cae2e61
+S = 9aea13d487c3ea6917e16374caafcf0321c12a80d28902dd8cd81909bb04b8c439e2491e504756742d0d0bfb15a9c34c
+
+Msg = 3cd8c053741dd9f974c6c5dbf8a1e5728e9b5eafb1cbcfc3452f5fbbda32a8c7564dee157e8d902c52514361da6d972934a56b3276e2a9379e328e24282e0db697c5bc29090fc489ec46b7b188325dd4e96494c250de0f4a89fe2ccf919eaefcfb50c288113e6df92714feb7f46e0822478c796d0f4ff3447a32997e892693ce
+d = 1c172e25732555afee7ded67a496f3f11babc0875898619f4519c29321e201e8ba1149f2c20b48e5efba235d58fea7c3
+Qx = 13e9e2c8bbcfe26e8f5f43c86268c5980ee693236a6b8777f3a7323718baa21005b482d08aafc6fa6e3667d91353544c
+Qy = 9ba181b3ee505be030f87ecd249b00670a791489b42af04976013483ff95b630c91c01e95757e906129f2f9b4ce719a8
+k = 08aec9a9e58bdc028805eb5dc86073d05fff1f5fb3fd17f510fc08f9272d84ba7aa66b6f77d84fe6360bd538192bf01a
+R = 2b4337c3dfbc886ffad7858ae2480cb62227e12205a70361c42f1a5ca9e658ee30fc3cf4030d85bd065edad83b99821f
+S = 2550cef8574bf17fb3d6b0c9d04ab266962bac3621bac233ff2e4989712d2a4a07171c0aebd3040cd6a32c3bd3efb8b5
+
+Msg = ed955dda6d9650124804d3deb6aeef900e520faf98b1ef6f14efcada7ca2433f09329b70897305e59c89024d76e466b28fe02cb2a9b12e2478c66470259d7c282137a19e5a04ffadea55245c0f34a681593fedc42931d8b3321b3d82e9cc102cd00540ad311ec7bd8c9d06db21bea4ca3dc74d98931ae0d40494aefc2345132c
+d = 5b96555dbd602e71d4d5d3aee19fd1ea084ee23d4f55c10937056762bc2015cbded2e898a487f5482ab7e1e971245907
+Qx = 6e14c17bb831b0112d7f3543c5fd17c78379a516c9e0539b03b8b4bfdead2820343fc84b0382807573ded6c4d97b7003
+Qy = 7f60021d2de77546db666721c9aec84c3e2ba8de0ba77443600dc77e6839bbf9316271adb22d4cb47d08f745ecb1dafd
+k = 7ad6f4ffd2b429ba10c6f112f800cacf1ad508cf8eba880893bb9659c1ddaaec57dcdc093a114500460d457bdde324f2
+R = faea950ca513806bc59028c638d6302ffc86978c3ff1f06db015dd7c4777050186cb8dd871f5e926e1416539c1939c2f
+S = 2c592240eabb8a1f9878e1b5c9d5d3ced7b3a7ae571f5a86494ed2ca567a36eb72e7bea8934bded29594bccf67ca84bd
+
+Msg = ce395b001da2a58e49691605d44af4206306f62f561bf2394060d2a5591a350277166bed043819035f1e60b5b3fb5ae113ddd0473f8ef6b2b050c472c2a264e1d8b3ca82a4f158c40f2d78d9ce5e5ea6de243f2e1f13f47f6c6f403b270912c81c636be35b396ca58468b3fb60aa83911d61441a0528d973bc31f965d4059080
+d = 8df9c3c710a25192f3dea970910bb3784e3509874cccf4334823eb9f7a8d05b067f2d812d61e878e24b093089a0b8245
+Qx = 92c9e32b20cbe6d4ed0727c6c942cf804a72031d6dfd69078b5e78ebce2d192268f1f5e2abce5aaf1f8d6a35f136837f
+Qy = d5167905fa7689e03b9fb1487c566f62b36f2bc1c4a2bfb6a836113b5c8d46f7c1ca51b628b14397fbc06ec9a07f4849
+k = 258dd05919735cd48627c9fe9fac5c252604aa7c2ae0460d7c1149cd96b7bd2ba195ad393bf392a2499f06aead5ba050
+R = 413793bcce52eda0f5b675a8d687cce86d5c9e1659b38a89e96246b5e05f8b0934d17dbba3b2ea44c838aa5fd87125d1
+S = ce7309fc2d6e3438818a1a29a997410b025b0403de20795b97c86c46034a6b02afeed279aeb06522d4de941bfdf50469
+
+Msg = ffefe316455ae4ffdb890bb804bf7d31424ea060ecacff419d0f7134ff76ad434063c0ec0f8bb7059584d3a03f3625bb9e9f66ace1a47ac4b8f3e76fc7c420c55edb1427d1fa15b387ad73d02b0595c4e74321be8822752230a0dcfb85d60bfa186da7623a8ec3eb1633f0a294b23ae87216b14ccee9ef56418dcfab9427371e
+d = 6002cb01ad2ce6e7101665d47729c863b6435c3875de57a93f99da834f73e3e6e2b3880e06de3e6bd1d51ea1807ab0d7
+Qx = e4216e1a20af8e8e3e74653ac016545001066e53e64af679ad1c85841bb475aed3e00ead052ae9955f48d675ff4ace56
+Qy = 8804c17641be21d4c6386902c9c5c888af25d97ca383703ea4a85cf93bbab360c0bbd2993374da499a303778650270b9
+k = 6b9507fd2844df0949f8b67b6fde986e50173713ac03df2edf65cb339859321cd3a2b9aab8356f95dec62460ab19c822
+R = 018891f6381ed358b422f79a299cf0789cee783ba388af4d82cbbe17f3709751b7fd9400e9702820c28b9afc62fdf489
+S = aef73bd590802b2fd2a65c4f7fec89f9b24ecc199a69254785925f334cd1977c5e1f858bd9830d7d7d243ea707b1af0b
+
+Msg = 304bccb718b3a9e12669913490cc5bcc1979287b56c628fad706c354241e88d10e81445a2853e3fc32ece094ba1abc3fdcab61da27f9a0fca739371049fed462ee6b08fa31cde12720f8144a6f00ce9b1a7a6eadd231f126717074b4efb5c72ce673ca5859000a436f67a338d698759f12c461247c45a361fb6cb661fdbe6714
+d = d8559c3543afc6f7b3dc037a687bad2630283757ba7862fd23ed14e2151a4cf5fed3d249268f780e0b96b6b46274a2d5
+Qx = 5f94223918f2ec9f0a08342cb99e724881c92453957c59672860f69daac01b660331a0f5845e50f1f27766b219c89e7e
+Qy = d76d83396130d10d1168d76c7fc83742ffffbe66d9f4da4ca3f95f5ad6dac8cc7bb65d16d317d37aa99fdbf30ec7439c
+k = 4ad5a92b5b8e170b71c8a7ed419dc624c7680004562b8d16a37b6e639f581ce81d5f0d98cce44d54c4e7136229148340
+R = f7baa6a5488ab462ea59aa31a36402b15880c68110b6069f51ede0c3b52a7b1e5bf926fdbe95768931b7d5f87058835c
+S = 28b1c4ef448a432f7c91b98b0c6471691e888211b6af907369a8930859b8cdb2e94f466a44f4e52f46df9b0d65e35de6
+
+Msg = 64f9f05c2805acf59c047b5f5d2e20c39277b6d6380f70f87b72327a76170b872bfe4b25c451602acfb6a631bb885e2655aee8abe44f69c90fb21ffde03cef2a452c468c6369867dfd8aa26ac24e16aa53b292375a8d8fbf988e302bf00088e4c061aa12c421d8fe3cbd7273b0e8993701df1c59431f436a08b8e15bd123d133
+d = b9208cbfd186ddfa3efd5b71342ae1efb01a13ebc4c2a992a2cbee7254b7846a4252ece1104b89d13d835911f8511224
+Qx = 166e6d96cb60d916fd19888a2dd945a3306ff0d7b0a5e30729f47d3dac3de2be3fd5cd7437e9a80d6c48cf960d2d36f8
+Qy = e6b2b70f131092ae210f29cc6bad701318bddb31bddf921695855c6208941100d0cee5d10799f8b835afe3ea510e8229
+k = da706ab5f61531f2378b3c0a2b342108cd119eadaa88b859df64923bccfb0ec2393fd312826f65c15a6587d1d460015b
+R = d9124c42858080c62400e4d4d8136304e03d910cbe9b9b3487f4d27c7e0540a314d34bef8c850045c8746ca631c11c42
+S = bbf6424a3b70166fa799f49e918439d515327039258ef9bd88435a59c9c19659f8ec3c8660720b0c08354ff60e0f5a76
+
+[P-384,SHA-384]
+
+Msg = 6b45d88037392e1371d9fd1cd174e9c1838d11c3d6133dc17e65fa0c485dcca9f52d41b60161246039e42ec784d49400bffdb51459f5de654091301a09378f93464d52118b48d44b30d781eb1dbed09da11fb4c818dbd442d161aba4b9edc79f05e4b7e401651395b53bd8b5bd3f2aaa6a00877fa9b45cadb8e648550b4c6cbe
+d = 201b432d8df14324182d6261db3e4b3f46a8284482d52e370da41e6cbdf45ec2952f5db7ccbce3bc29449f4fb080ac97
+Qx = c2b47944fb5de342d03285880177ca5f7d0f2fcad7678cce4229d6e1932fcac11bfc3c3e97d942a3c56bf34123013dbf
+Qy = 37257906a8223866eda0743c519616a76a758ae58aee81c5fd35fbf3a855b7754a36d4a0672df95d6c44a81cf7620c2d
+k = dcedabf85978e090f733c6e16646fa34df9ded6e5ce28c6676a00f58a25283db8885e16ce5bf97f917c81e1f25c9c771
+R = 50835a9251bad008106177ef004b091a1e4235cd0da84fff54542b0ed755c1d6f251609d14ecf18f9e1ddfe69b946e32
+S = 0475f3d30c6463b646e8d3bf2455830314611cbde404be518b14464fdb195fdcc92eb222e61f426a4a592c00a6a89721
+
+Msg = d768f41e6e8ec2125d6cf5786d1ba96668ac6566c5cdbbe407f7f2051f3ad6b1acdbfe13edf0d0a86fa110f405406b69085219b5a234ebdb93153241f785d45811b3540d1c37424cc7194424787a51b79679266484c787fb1ded6d1a26b9567d5ea68f04be416caf3be9bd2cafa208fe2a9e234d3ae557c65d3fe6da4cb48da4
+d = 23d9f4ea6d87b7d6163d64256e3449255db14786401a51daa7847161bf56d494325ad2ac8ba928394e01061d882c3528
+Qx = 5d42d6301c54a438f65970bae2a098cbc567e98840006e356221966c86d82e8eca515bca850eaa3cd41f175f03a0cbfd
+Qy = 4aef5a0ceece95d382bd70ab5ce1cb77408bae42b51a08816d5e5e1d3da8c18fcc95564a752730b0aabea983ccea4e2e
+k = 67ba379366049008593eac124f59ab017358892ee0c063d38f3758bb849fd25d867c3561563cac1532a323b228dc0890
+R = fb318f4cb1276282bb43f733a7fb7c567ce94f4d02924fc758635ab2d1107108bf159b85db080cdc3b30fbb5400016f3
+S = 588e3d7af5da03eae255ecb1813100d95edc243476b724b22db8e85377660d7645ddc1c2c2ee4eaea8b683dbe22f86ca
+
+Msg = 6af6652e92a17b7898e40b6776fabaf0d74cf88d8f0ebfa6088309cbe09fac472eeac2aa8ea96b8c12e993d14c93f8ef4e8b547afe7ae5e4f3973170b35deb3239898918c70c1056332c3f894cd643d2d9b93c2561aac069577bbab45803250a31cd62226cab94d8cba7261dce9fe88c210c212b54329d76a273522c8ba91ddf
+d = b5f670e98d8befc46f6f51fb2997069550c2a52ebfb4e5e25dd905352d9ef89eed5c2ecd16521853aadb1b52b8c42ae6
+Qx = 44ffb2a3a95e12d87c72b5ea0a8a7cb89f56b3bd46342b2303608d7216301c21b5d2921d80b6628dc512ccb84e2fc278
+Qy = e4c1002f1828abaec768cadcb7cf42fbf93b1709ccae6df5b134c41fae2b9a188bfbe1eccff0bd348517d7227f2071a6
+k = 229e67638f712f57bea4c2b02279d5ccad1e7c9e201c77f6f01aeb81ea90e62b44b2d2107fd66d35e56608fff65e28e4
+R = b11db592e4ebc75b6472b879b1d8ce57452c615aef20f67a280f8bca9b11a30ad4ac9d69541258c7dd5d0b4ab8dd7d49
+S = 4eb51db8004e46d438359abf060a9444616cb46b4f99c9a05b53ba6df02e914c9c0b6cc3a9791d804d2e4c0984dab1cc
+
+Msg = b96d74b2265dd895d94e25092fb9262dc4f2f7a328a3c0c3da134b2d0a4e2058ca994e3445c5ff4f812738e1b0c0f7a126486942a12e674a21f22d0886d68df2375f41685d694d487a718024933a7c4306f33f1a4267d469c530b0fed4e7dea520a19dd68bf0203cc87cad652260ed43b7b23f6ed140d3085875190191a0381a
+d = de5975d8932533f092e76295ed6b23f10fc5fba48bfb82c6cc714826baf0126813247f8bd51d5738503654ab22459976
+Qx = f1fabafc01fec7e96d982528d9ef3a2a18b7fe8ae0fa0673977341c7ae4ae8d8d3d67420343d013a984f5f61da29ae38
+Qy = 1a31cf902c46343d01b2ebb614bc789c313b5f91f9302ad9418e9c797563e2fa3d44500f47b4e26ad8fdec1a816d1dcf
+k = fc5940e661542436f9265c34bce407eff6364bd471aa79b90c906d923e15c9ed96eea4e86f3238ea86161d13b7d9359d
+R = c2fbdd6a56789024082173725d797ef9fd6accb6ae664b7260f9e83cb8ab2490428c8b9c52e153612295432fec4d59cd
+S = 8056c5bb57f41f73082888b234fcda320a33250b5da012ba1fdb4924355ae679012d81d2c08fc0f8634c708a4833232f
+
+Msg = 7cec7480a037ff40c232c1d2d6e8cd4c080bbeecdaf3886fccc9f129bb6d202c316eca76c8ad4e76079afe622f833a16f4907e817260c1fa68b10c7a151a37eb8c036b057ed4652c353db4b4a34b37c9a2b300fb5f5fcfb8aa8adae13db359160f70a9241546140e550af0073468683377e6771b6508327408c245d78911c2cc
+d = 11e0d470dc31fab0f5722f87b74a6c8d7414115e58ceb38bfcdced367beac3adbf1fe9ba5a04f72e978b1eb54597eabc
+Qx = 1950166989164cbfd97968c7e8adb6fbca1873ebef811ea259eb48b7d584627f0e6d6c64defe23cbc95236505a252aa1
+Qy = 41ef424b5cb076d4e32accd9250ea75fcf4ffd81814040c050d58c0a29b06be11edf67c911b403e418b7277417e52906
+k = e56904028226eb04f8d071e3f9cefec91075a81ca0fa87b44cae148fe1ce9827b5d1910db2336d0eb9813ddba3e4d7b5
+R = c38ef30f55624e8935680c29f8c24824877cf48ffc0ef015e62de1068893353030d1193bf9d34237d7ce6ba92c98b0fe
+S = 651b8c3d5c9d5b936d300802a06d82ad54f7b1ba4327b2f031c0c5b0cb215ad4354edc7f932d934e877dfa1cf51b13fe
+
+Msg = 00ce978603229710345c9ad7c1c2dba3596b196528eea25bd822d43ca8f76a024e29217703dd0652c8a615284fc3edcc1c5ad1c8d5a8521c8e104c016a24e50c2e25066dcb56596f913b872767e3627aa3e55ec812e9fdac7c2f1beade83aef093e24c9c953982adf431a776880ae4583be158e11cdab1cbca3ad3a66900213d
+d = 5c6bbf9fbcbb7b97c9535f57b431ed1ccae1945b7e8a4f1b032016b07810bd24a9e20055c0e9306650df59ef7e2cd8c2
+Qx = 2e01c5b59e619e00b79060a1e8ef695472e23bf9a511fc3d5ed77a334a242557098e40972713732c5291c97adf9cf2cf
+Qy = 563e3fe4ad807e803b9e961b08da4dde4cea8925649da0d93221ce4cdceabc6a1db7612180a8c6bef3579c65539b97e9
+k = 03d23f1277b949cb6380211ad9d338e6f76c3eedac95989b91d0243cfb734a54b19bca45a5d13d6a4b9f815d919eea77
+R = abab65308f0b79c4f3a9ff28dd490acb0c320434094cef93e75adfe17e5820dc1f77544cfaaacdc8cf9ac8b38e174bef
+S = 11b783d879a6de054b316af7d56e526c3dce96c85289122e3ad927cfa77bfc50b4a96c97f85b1b8221be2df083ff58fb
+
+Msg = 54a255c18692c6162a46add176a0ae8361dcb8948f092d8d7bac83e160431794d3b9812849bf1994bcdcfba56e8540c8a9ee5b93414548f2a653191b6bb28bda8dc70d45cc1b92a489f58a2d54f85766cb3c90de7dd88e690d8ebc9a79987eee1989df35af5e35522f83d85c48dda89863171c8b0bf4853ae28c2ac45c764416
+d = ffc7dedeff8343721f72046bc3c126626c177b0e48e247f44fd61f8469d4d5f0a74147fabaa334495cc1f986ebc5f0b1
+Qx = 51c78c979452edd53b563f63eb3e854a5b23e87f1b2103942b65f77d024471f75c8ce1cc0dfef83292b368112aa5126e
+Qy = 313e6aaf09caa3ba30f13072b2134878f14a4a01ee86326cccbff3d079b4df097dc57985e8c8c834a10cb9d766169366
+k = c3de91dbe4f777698773da70dd610ef1a7efe4dc00d734399c7dd100728006a502822a5a7ff9129ffd8adf6c1fc1211a
+R = f4f477855819ad8b1763f53691b76afbc4a31a638b1e08c293f9bcd55decf797f9913ca128d4b45b2e2ea3e82c6cf565
+S = 7c26be29569ef95480a6d0c1af49dc10a51a0a8931345e48c0c39498bfb94d62962980b56143a7b41a2fddc8794c1b7f
+
+Msg = 692a78f90d4f9d5aee5da536314a78d68c1feabbfe5d1ccea7f6059a66c4b310f8051c411c409ccf6e19a0cbd8b8e100c48317fe8c6d4f8a638b9551ce7ee178020f04f7da3001a0e6855225fb3c9b375e4ed964588a1a41a095f3f476c42d52ffd23ce1702c93b56d4425d3befcf75d0951b6fd5c05b05455bdaf205fe70ca2
+d = adca364ef144a21df64b163615e8349cf74ee9dbf728104215c532073a7f74e2f67385779f7f74ab344cc3c7da061cf6
+Qx = ef948daae68242330a7358ef73f23b56c07e37126266db3fa6eea233a04a9b3e4915233dd6754427cd4b71b75854077d
+Qy = 009453ef1828eaff9e17c856d4fc1895ab60051312c3e1db1e3766566438b2990cbf9945c2545619e3e0145bc6a79004
+k = a2da3fae2e6da3cf11b49861afb34fba357fea89f54b35ce5ed7434ae09103fe53e2be75b93fc579fedf919f6d5e407e
+R = dda994b9c428b57e9f8bbaebba0d682e3aac6ed828e3a1e99a7fc4c804bff8df151137f539c7389d80e23d9f3ee497bf
+S = a0d6b10ceffd0e1b29cf784476f9173ba6ecd2cfc7929725f2d6e24e0db5a4721683640eaa2bbe151fb57560f9ce594b
+
+Msg = 3b309bb912ab2a51681451ed18ad79e95d968abc35423a67036a02af92f575a0c89f1b668afe22c7037ad1199e757a8f06b281c33e9a40bab69c9874e0bb680b905d909b9dc24a9fe89bb3d7f7d47082b25093c59754f8c19d1f81f30334a8cdd50a3cb72f96d4b3c305e60a439a7e93aeb640dd3c8de37d63c60fb469c2d3ed
+d = 39bea008ec8a217866dcbdb1b93da34d1d3e851d011df9ef44b7828b3453a54aa70f1df9932170804eacd207e4f7e91d
+Qx = 5709ec4305a9c3271c304face6c148142490b827a73a4c17affcfd01fffd7eaa65d2fdedfa2419fc64ed910823513faf
+Qy = b083cda1cf3be6371b6c06e729ea6299213428db57119347247ec1fcd44204386cc0bca3f452d9d864b39efbfc89d6b2
+k = 3c90cc7b6984056f570542a51cbe497ce4c11aeae8fc35e8fd6a0d9adeb650e8644f9d1d5e4341b5adc81e27f284c08f
+R = d13646895afb1bfd1953551bb922809c95ad65d6abe94eb3719c899aa1f6dba6b01222c7f283900fe98628b7597b6ea6
+S = 4a9a38afda04c0a6b0058943b679bd02205b14d0f3d49b8f31aac289129780cdb1c555def8c3f9106b478729e0c7efaa
+
+Msg = f072b72b8783289463da118613c43824d11441dba364c289de03ff5fab3a6f60e85957d8ff211f1cb62fa90216fb727106f692e5ae0844b11b710e5a12c69df3ed895b94e8769ecd15ff433762d6e8e94d8e6a72645b213b0231344e2c968056766c5dd6b5a5df41971858b85e99afbf859400f839b42cd129068efabeea4a26
+d = e849cf948b241362e3e20c458b52df044f2a72deb0f41c1bb0673e7c04cdd70811215059032b5ca3cc69c345dcce4cf7
+Qx = 06c037a0cbf43fdf335dff33de06d34348405353f9fdf2ce1361efba30fb204aea9dbd2e30da0a10fd2d876188371be6
+Qy = 360d38f3940e34679204b98fbf70b8a4d97f25443e46d0807ab634ed5891ad864dd7703557aa933cd380e26eea662a43
+k = 32386b2593c85e877b70e5e5495936f65dc49553caef1aa6cc14d9cd370c442a0ccfab4c0da9ec311b67913b1b575a9d
+R = 5886078d3495767e330c7507b7ca0fa07a50e59912a416d89f0ab1aa4e88153d6eaf00882d1b4aa64153153352d853b5
+S = 2cc10023bf1bf8ccfd14b06b82cc2114449a352389c8ff9f6f78cdc4e32bde69f3869da0e17f691b329682ae7a36e1aa
+
+Msg = cf4945350be8133b575c4ad6c9585e0b83ff1ed17989b6cd6c71b41b5264e828b4e115995b1ae77528e7e9002ac1b5669064442645929f9d7dd70927cb93f95edeb73e8624f4bc897ec4c2c7581cb626916f29b2d6e6c2fba8c59a71e30754b459d81b912a12798182bcff4019c7bdfe929cc769bcc2414befe7d2906add4271
+d = d89607475d509ef23dc9f476eae4280c986de741b63560670fa2bd605f5049f1972792c0413a5b3b4b34e7a38b70b7ca
+Qx = 49a1c631f31cf5c45b2676b1f130cbf9be683d0a50dffae0d147c1e9913ab1090c6529a84f47ddc7cf025921b771355a
+Qy = 1e207eece62f2bcc6bdabc1113158145170be97469a2904eaaa93aad85b86a19719207f3e423051f5b9cbbe2754eefcb
+k = 78613c570c8d33b7dd1bd1561d87e36282e8cf4843e7c344a2b2bb6a0da94756d670eeaffe434f7ae7c780f7cf05ca08
+R = 66f92b39aa3f4aeb9e2dc03ac3855406fa3ebbab0a6c88a78d7a03482f0c9868d7b78bc081ede0947c7f37bf193074ba
+S = e5c64ed98d7f3701193f25dd237d59c91c0da6e26215e0889d82e6d3e416693f8d58843cf30ab10ab8d0edd9170b53ad
+
+Msg = d9b5cf0b50416573ff3c63133275a18394dd4326be2041e8d97e6e4e3855a4a177e9d26dfd223fe8aa74564edb49bd72de19916fb6f001f44530d5c18e2c332bce1b7415df5927ece5f3824f34d174b963136b53aef1fb78fb0c06a201a40b2db38e4d8216fc1e392a798c8ab4b3a314496b7f1087804ebfa89bf96e9cdb80c0
+d = 083e7152734adf342520ae377087a223688de2899b10cfcb34a0b36bca500a4dfa530e2343e6a39da7ae1eb0862b4a0d
+Qx = 70a0f16b6c61172659b027ed19b18fd8f57bd28dc0501f207bd6b0bb065b5671cf3dd1ed13d388dcf6ccc766597aa604
+Qy = 4f845bf01c3c3f6126a7368c3454f51425801ee0b72e63fb6799b4420bfdebe3e37c7246db627cc82c09654979c700bb
+k = 28096ababe29a075fbdf894709a20d0fdedb01ed3eeacb642a33a0da6aed726e13caf6cf206792ec359f0c9f9b567552
+R = ee2923f9b9999ea05b5e57f505bed5c6ba0420def42c6fa90eef7a6ef770786525546de27cdeb2f8586f8f29fb4ee67c
+S = 50ef923fb217c4cf65a48b94412fda430fac685f0da7bd574557c6c50f5b22e0c8354d99f2c2f2c2691f252f93c7d84a
+
+Msg = 9e4042d8438a405475b7dab1cd783eb6ce1d1bffa46ac9dfda622b23ac31057b922eced8e2ed7b3241efeafd7c9ab372bf16230f7134647f2956fb793989d3c885a5ae064e85ed971b64f5f561e7ddb79d49aa6ebe727c671c67879b794554c04de0e05d68264855745ef3c9567bd646d5c5f8728b797c181b6b6a876e167663
+d = 63578d416215aff2cc78f9b926d4c7740a77c142944e104aa7422b19a616898262d46a8a942d5e8d5db135ee8b09a368
+Qx = cadbacef4406099316db2ce3206adc636c2bb0a835847ed7941efb02862472f3150338f13f4860d47f39b7e098f0a390
+Qy = 752ad0f22c9c264336cde11bbc95d1816ed4d1b1500db6b8dce259a42832e613c31178c2c7995206a62e201ba108f570
+k = 7b69c5d5b4d05c9950dc94c27d58403b4c52c004b80a80418ad3a89aabc5d34f21926729e76afd280cc8ee88c9805a2a
+R = db054addb6161ee49c6ce2e4d646d7670754747b6737ca8516e9d1e87859937c3ef9b1d2663e10d7e4bd00ec85b7a97a
+S = fcc504e0f00ef29587e4bc22faada4db30e2cb1ac552680a65785ae87beb666c792513f2be7a3180fc544296841a0e27
+
+Msg = 0b14a7484a40b68a3ce1273b8a48b8fdb65ba900d98541c4bbd07b97e31bcc4c85545a03e9deab3c563f47a036ff60d0361684ba241b5aa68bb46f440da22181ee328a011de98eff34ba235ec10612b07bdfa6b3dc4ccc5e82d3a8d057e1862fef3def5a1804696f84699fda2ec4175a54a4d08bcb4f0406fdac4eddadf5e29b
+d = ed4df19971658b74868800b3b81bc877807743b25c65740f1d6377542afe2c6427612c840ada31a8eb794718f37c7283
+Qx = 33093a0568757e8b58df5b72ea5fe5bf26e6f7aeb541b4c6a8c189c93721749bcaceccf2982a2f0702586a9f812fc66f
+Qy = ebe320d09e1f0662189d50b85a20403b821ac0d000afdbf66a0a33f304726c69e354d81c50b94ba3a5250efc31319cd1
+k = d9b4cd1bdfa83e608289634dbfcee643f07315baf743fc91922880b55a2feda3b38ddf6040d3ba10985cd1285fc690d5
+R = 009c74063e206a4259b53decff5445683a03f44fa67252b76bd3581081c714f882f882df915e97dbeab061fa8b3cc4e7
+S = d40e09d3468b46699948007e8f59845766dbf694b9c62066890dd055c0cb9a0caf0aa611fb9f466ad0bbb00dbe29d7eb
+
+Msg = 0e646c6c3cc0f9fdedef934b7195fe3837836a9f6f263968af95ef84cd035750f3cdb649de745c874a6ef66b3dd83b66068b4335bc0a97184182e3965c722b3b1aee488c3620adb835a8140e199f4fc83a88b02881816b366a09316e25685217f9221157fc05b2d8d2bc855372183da7af3f0a14148a09def37a332f8eb40dc9
+d = e9c7e9a79618d6ff3274da1abd0ff3ed0ec1ae3b54c3a4fd8d68d98fb04326b7633fc637e0b195228d0edba6bb1468fb
+Qx = a39ac353ca787982c577aff1e8601ce192aa90fd0de4c0ed627f66a8b6f02ae51315543f72ffc1c48a7269b25e7c289a
+Qy = 9064a507b66b340b6e0e0d5ffaa67dd20e6dafc0ea6a6faee1635177af256f9108a22e9edf736ab4ae8e96dc207b1fa9
+k = b094cb3a5c1440cfab9dc56d0ec2eff00f2110dea203654c70757254aa5912a7e73972e607459b1f4861e0b08a5cc763
+R = ee82c0f90501136eb0dc0e459ad17bf3be1b1c8b8d05c60068a9306a346326ff7344776a95f1f7e2e2cf9477130e735c
+S = af10b90f203af23b7500e070536e64629ba19245d6ef39aab57fcdb1b73c4c6bf7070c6263544633d3d358c12a178138
+
+[P-384,SHA-512]
+
+Msg = 67d9eb88f289454d61def4764d1573db49b875cfb11e139d7eacc4b7a79d3db3bf7208191b2b2078cbbcc974ec0da1ed5e0c10ec37f6181bf81c0f32972a125df64e3b3e1d838ec7da8dfe0b7fcc911e43159a79c73df5fa252b98790be511d8a732fcbf011aacc7d45d8027d50a347703d613ceda09f650c6104c9459537c8f
+d = 217afba406d8ab32ee07b0f27eef789fc201d121ffab76c8fbe3c2d352c594909abe591c6f86233992362c9d631baf7c
+Qx = fb937e4a303617b71b6c1a25f2ac786087328a3e26bdef55e52d46ab5e69e5411bf9fc55f5df9994d2bf82e8f39a153e
+Qy = a97d9075e92fa5bfe67e6ec18e21cc4d11fde59a68aef72c0e46a28f31a9d60385f41f39da468f4e6c3d3fbac9046765
+k = 90338a7f6ffce541366ca2987c3b3ca527992d1efcf1dd2723fbd241a24cff19990f2af5fd6419ed2104b4a59b5ae631
+R = c269d9c4619aafdf5f4b3100211dddb14693abe25551e04f9499c91152a296d7449c08b36f87d1e16e8e15fee4a7f5c8
+S = 77ffed5c61665152d52161dc13ac3fbae5786928a3d736f42d34a9e4d6d4a70a02d5af90fa37a23a318902ae2656c071
+
+Msg = 45db86829c363c80160659e3c5c7d7971abb1f6f0d495709bba908d7aa99c9df64b3408a51bd69aba8870e2aaff488ef138f3123cf94391d081f357e21906a4e2f311defe527c55e0231579957c51def507f835cceb466eb2593a509dcbee2f09e0dde6693b2bfe17697c9e86dd672f5797339cbe9ea8a7c6309b061eca7aef5
+d = 0a3f45a28a355381a919372f60320d6610cfb69c3e318eb1607db3cadfc42b728b77a6a9e9e333de9183c58933daf60f
+Qx = 832cbb7061a719a316e73dbad348fa67cd17c33f40b9000a3d3b691a2a2cd821052566717c3ead01089b56086af1366f
+Qy = 1e15a048d1dce642d9ebcbfac7f92b1bcee90fd0240cc79abd29e32e0e655c4ee1fd34fb88178bba92aca100e7794ed0
+k = 2a78e651623ba604c42cf094fc7d046629306f508853427ba091448800d1092c041bb2323035fc9d19a8d44950f7dcc3
+R = 0db0cc9a2bda8dd7e565ad36f91b1c5756d78164dc8a72a5bee4b6bc45ea38c7a16b01d05b1893d4e06b62db24c30385
+S = abd383edaeda7d0b8de1b54fcd3c28874fed62ab266f1f84c8ba796a7b54e5e0695fdb43ce7fe90ed00fa468d87bca64
+
+Msg = 4672fce0721d37c5be166bffa4b30d753bcf104b9b414db994b3ed33f36af4935ea59a0bb92db66448b3f57dad4fc67cef10ce141bf82c536be604b89a0bc0e8bca605b867880049d97142d30538fc543bd9d4fab7fdbe2f703815cdb6361beb66acff764bc275f910d1662445b07b92830db69a5994857f53657ed5ca282648
+d = 2e408c57921939f0e0fe2e80ce74a4fa4a1b4fa7ab070206298fe894d655be50e2583af9e45544b5d69c73dce8a2c8e7
+Qx = a2b24a5ad4a2e91f12199ed7699e3f297e27bf8b8ea8fbe7ed28366f3544cd8e680c238450f8a6422b40829d6647b25c
+Qy = 2732be0075536e6519f6a099b975a40f8e0de337fa4d48bd0762b43f41cab8deafdef9cfbb9973e457801e3bf9c93304
+k = b10b6258afdde81f9c971cc1526d942e20cafac02f59fee10f98e99b8674636bff1d84a6eaa49c0de8d8cfdc90d8ce84
+R = be428a8de89a364a134719141ee8d776a3a8338f1132b07e01b28573d8eaf3b9008b63304c48821e53638b6141f9660b
+S = 866181dbef5c147d391bed6adcee408c339982c307adc718c2b9ab9e5642d8dedc36dd6402559a3ab614c99c1e56b529
+
+Msg = 9ae48fdd9bfc5cb0f4d4761e28b2073bda05a3e3fe82c212e66701dc4573cc67a829b0f82d7520b1bf11db0c6d1743822bbe41bb0adbd7222aa5fae70fbd1a31f2d4453a01c81e064d775388468be96f6063f8673b7b8d4455fe1bd4c801ad5e625a015eaa4a1a18da490d2af8642201eaba3c611cbd65f861d8e19ca82a1ee6
+d = 1c285da72a8eb1c3c38faab8d3bb4e68dc95c797082b9a3991a21c1de54759071ecf2265fb1eff504ab24174bc6710cf
+Qx = 11acb1b5cc59a4f1df1913a8d6e91cbdafb8206dc44aff7d9da45906b664fc33194d9935a82aa4d62f39618897c86025
+Qy = 832ed0b9575fff52a3603bfe89f312751b4c396da98324117a61b3f525d27b2266f6cfb22be07e50b6874435e380ed62
+k = 2513075e02cc7fb3cff7b7adde46da31c5493749b5cf02758bd5b098a838bfd4d5e4c7fb8268bdc37e219c30efebe878
+R = b3d638b3be45f14f170da5bdc22d2114deac93ab340a25b3af2b5c18584bb9147e00dc6c67a2274f79aa4838793eb63f
+S = 876112bdca2c725eb2f6dbd76d07710a31f0c16d38430cb0817f320a25a9ecfec8a66137d0304612ae29a6a484fd3319
+
+Msg = 817d6a110a8fd0ca7b4d565558f68b59a156744d4c5aac5c6610c95451793de2a756f774558c61d21818d3ebeeeb71d132da1c23a02f4b305eccc5cd46bd21dfc173a8a91098354f10ffbb21bf63d9f4c3feb231c736504549a78fd76d39f3ad35c36178f5c233742d2917d5611d2073124845f1e3615b2ef25199a7a547e882
+d = 9da37e104938019fbdcf247e3df879a282c45f8fb57e6655e36b47723af42bec3b820f660436deb3de123a21de0ca37b
+Qx = 722d0ea6891d509b18b85ca56f74deb5c3030d2a30433824123d430d03c99279572c3b28ecf01e747b9db8acc55d0ba3
+Qy = 7e2605ea7092214f366f3639037bffd89fe103c646e990839d3a1ced8d78edb5b9bc60d834fd8e2a3c17e920bdae023a
+k = c8c18e53a9aa5915288c33132bd09323638f7995cd89162073984ed84e72e07a37e18c4c023933eace92c35d10e6b1b6
+R = 6512a8a2be731e301dcf4803764297862bbfa0ac8daed64d8e98b34618ecb20520fc5d3cf890b7783edf86e7ea407541
+S = 4ff10301f7b4168fae066361376007c1d7aa89a75c87719d0b54711ffef5ef3726f3eef84f7ebc025c110bde511b17f6
+
+Msg = 464f10ec6fb229a51db5fd0e122f2cb8a9a022117e2987f4007bf5565b2c16aba0714e2e3cdd0c100d55ac3017e36fc7501ad8309ab9572aa65424c9eb2e580a119c55777676ec498df53ef6ae78fd8a988130ee0e6082bf1ef71cd4c946021018a8ca7154d13b174c638912613b0bdb9001c302bf7e443ad2124ab2c1cce212
+d = 0661ab3bf9f7bef51bec7dff758de289154557beb9ce18cc4b8cc09a871e8322af259cf188b593dc62f03a19e75f7f69
+Qx = b4f100558043858efa728082d9b99ad5192b59b0947434f5ba7ff2514508a6d71ba54e7221c31cb0712103272b3f6fa4
+Qy = 34f6df4eeb2da11498044635067c2715ed15ae251c78ffb9030d87909ea8539b66394e93109ca54c0406cf99960c3e93
+k = 84a87137edb6894f96c5a8e94a3765162034feb84dfea94e1c71411170c285a80321ec7999e25861844143209804882c
+R = 4dc9d1b949b36e3c3847ac1c7ed114e1bc9cbe76119cf6fcd3f1b69ee6ee54e3255f1bb288fe2f8bd6d4049a21793c27
+S = 56a561d647b62ccae1e6df818b1a6fbde66c82ef0ff69ee415f183e7daf76be22630c7e02cd3fd729dfa490f26824584
+
+Msg = 4e3e0fb96320ddccde8b463c273654c4f7164920b1d63430921d2e808dee403e6420eedda0a557b911d00736a4f8798dd4ef26673efd6d190988ad4929ec64f8685cfb76070a36cd6a3a4bf2f54fb08a349d44642b6f614043fef9b2813b63457c76537d23da7b37310334f7ba76edf1999dad86f72aa3446445a65952ac4e50
+d = 66e7cfdeb7f264cf786e35210f458c32223c3a12a3bc4b63d53a5776bc9b069928452484f6241caa3781fd1a4109d4db
+Qx = 3c7682de540ab231daf21bf9fc80bda6abf7e17dcc79d476c7b7c3bd4d42d386877fd8ba495c1b0333e04fb5fd2a1505
+Qy = 0a1582e4f4d72abea9d3476aff8369c41261f0c5dddf2ca82e10f7a163f73df09473d9e5e2552187104e4cc7c6d83611
+k = 2fa266f5cce190eb77614933ca6a55121ad8bae168ff7a9043d96d13b5ca2fe70101ff9fe1e2b2cd7413e6aa8f49abde
+R = e7ecda9da0c52d0474a9f70094dc8f061d7d6a22210d3b69a7be8f389aa666f256322099b87d16ad35357ea856574dba
+S = ba348eb40a2830ec5a1130264ac0a8675420b1ae243e808a778135809ece21f42c0c881166321102b4f02df4c5c7ed9d
+
+Msg = c466b6b6baf7e6ffa876ec06105e2d43534e0517c07b1c4c9fb67ba81ce09525a7721ec3c290f2b1f65b6463d41598e7a25b2238501629953a5ca955b644354fb6856733a2e5bb8f5bc21a0c803493f5539f9fb83aab3dba2c982989c2270c61ab244b68bfe1b948d00c2ed975e09c29b5f8a7effcad8652a148cc880d503217
+d = 92c2f7ee64af86d003ab484e12b82fcf245fc330761057fec5b7af8f7e0a2d85b468c21d171460fcb829cae7b986316d
+Qx = ca43a306479bf8fb537d4b9ff9d635bbb2a0d60d9e854d5b7e269d09d91f78c6b90b616e4c931629453645a2bb371e14
+Qy = 356c4d7f10e690614eaf7f82ba0f9dc1aad98130c0ad9fe353deec565cc04bef789a0a4242322e0058b46cd02f2de77d
+k = 6ec81fb74f8725ba225f317264460ee300cfd2f02092000989acbdad4799cf55c244a65c557113328fe20282e6badb55
+R = cd7a4309bcebc25a8e10899fe2eda5f8b2dbcf329cd2f3d65befd67393e83fba2f8a67a15c01a6ac8314f9f5e87a9dca
+S = 6dcfc0426bc148e67e91d4784e3d7e9bc3b7ce3676be62daa7f3f55dfdff6d9dc735b5e3e0bbd0785db1f76f7ac065f3
+
+Msg = feac892b7720af80b3c9eede51e923f18d3d0c5de4c31f4aa75e36df7c7c2fd8f41778851a24b69e67dccb65e159dd5c383243bad7cfedcc5e85c8a01c34b0b94ba8e07e4c024c09d279b3731e8b62f9562d3c4f5042567efe42a9d0eaaabab28bc6f11232fc8ceaaf4518d9f3b2bebf020294496b7f6b879e69503f75fecd3d
+d = 15347caaad1067f1848a676bd0a8c52021ae604b79d02775a0459226e0391a3acd26653c916fcfe86149fb0ee0904476
+Qx = e5a0463163964d984f5bad0072d45bc2059939e60a826ccca36c151460ae360f5d6679f60fe43e999b6da5841c96e48a
+Qy = 30f2dd425a3fa2c95d34124217250b39e3b4a14f3e6e415ae8e5b0409eb72f43f78b64d0ce6f2d49980d6f04cd1391db
+k = 1a2d224db4bb9c241ca5cab18920fad615fa25c1db0de0f024cb3ace0d11ef72b056885446659f67650fdff692517b1c
+R = 87b4de0fb21df38dfc9a4b1e350da67547e307f55b5b9dd6615e408afe7c3553a6e02722847367439e636074faa2182b
+S = 375d965753b9ed6c6c08576726f8308c2f8dbd2737824464e71265d47907e26f615bbeb8203ec617520d4ecd1851dc44
+
+Msg = cf2982e3bf174ce547741b969403cd11e9553067e6af8177d89511a0eb040db924530bdba65d8b1ff714228db0737c1756f509e1506014a10736e65be2f91980a73891496e90ff2714a3601c7565cdcef5a395e2e0e1652f138d90d61eaa9cba993b823245647f6e07cec9b8b4449cd68a29741cd1579c66e548ca0d0acf33aa
+d = ac1cb5e59bda2eff3413a3bab80308f9fb32c595283c795de4c17fdae8d4647b5f108fd0801aee22adb7db129283b5aa
+Qx = bc6b1a718284803553c173089c397870aaaecca579bb8e81a8cfa12473cd2057567fa8726a19ed427cc035baeec2c551
+Qy = 14f82997d1129b669f0015350e47ad561b1b13441af4fb44656f15ed0c5706984d66655accc52f2e943eef39cb1cdc21
+k = 8053a46e875f446056b06d4318fa3e8977622de7207cbf0996bf35b0e9b19aaa507f642bcf0be9f048f1af09806f6946
+R = a994eb15b64114ce8a9342d18b5edda96a6d76314a5ac03da723699177d352a4a9f3b7121b11a91e43a6af4025da51d6
+S = 8183ae33a888e99aa76882da0a6705ad102f2bbd9572fad0d2e4d6d70151970469e00c5220e59c14724d771c1384b302
+
+Msg = bf9fdd4107ef5a6070108771ac9eee4f0c8043bf0d04db772a47294f4137e2439d94b337114b074e57e0cb78d0ccf352a2833e9788ee2a1a9ffeacd34f38fcefb86653d70c7dadd4cf6548d608e70acdef6c7530974b92c813798add659752a8c72b05e1ad9c65c21834ce6fbe49d8a1426b5a54270794436d284364fac6ec1a
+d = 205f1eb3dfacff2bdd8590e43e613b92512d6a415c5951bda7a6c37db3aae39b9b7ec6edd256609e75373419087fa71f
+Qx = c9f1f63a18c761b077a1ec35fbb2de635db9b8592c36194a01769b57728c7755d4c79b3d5b97a1a4631e30c86d03f13c
+Qy = f8c4a38770054d5cc9bb9182e6d4638242c4fd16e869ac22e44c4b9402d594e0c6f5df6a9a7de32a4893d9f6588f1950
+k = ecd395c5d8b7d6e6b2b19644e0d2e6086c912c6a0f5b8ed4b94b7290b65852c9741ce8eeb08d8751ead8a183e17d76c6
+R = e81331d78b438b0b8d98c1be03385ba5d614af182f1677f259126cc3de7eaac6c19b02be955d936b6bf9c27c6796e6f0
+S = 17c2b7a8e0fc93909762aa9f86f9561e759ecb88f02337b2018363be6095d9e4324a6d3296046686624b5efad6b52878
+
+Msg = 5d634fb39a2239256107dc68db19751540b4badac9ecf2fce644724401d6d632b3ae3b2e6d05746b77ddc0c899878032248c263eda08d3d004d35952ad7a9cfe19343d14b37f9f632245e7b7b5fae3cb31c5231f82b9f1884f2de7578fbf156c430257031ba97bc6579843bc7f59fcb9a6449a4cd942dffa6adb929cf219f0ad
+d = e21e3a739e7ded418df5d3e7bc2c4ae8da76266a1fc4c89e5b09923db80a72217f1e96158031be42914cf3ee725748c1
+Qx = 0f753171922b5334f3dd2778a64ce2da8295121939beae71ad85e5344e893be0fd03cf14e1f031adec098e0c4409449c
+Qy = 45c10a0ffc0eb2f1cec5c89b698061108313ee7d449ad580efad344f0e7cf35be8a18fca620f112e57bdc746abdace55
+k = d06bea06b25e6c30e866b1eb0657b45673e37b709013fb28fd7373afc8277cbc861354f821d0bd1927e52ec083a0f41f
+R = e8d4a31dd0e7d2522be62a32608e744c3775ceb606dc897899f0c73f1a40ce9a8be854cd506e65cd81fd7fa2c616cb7b
+S = 8151b681b6b6046d3c36f332d06d9ba7751e740631cdb759f88c50a25a8e950d5023df8a15c77243743733c4feaf21d5
+
+Msg = c9b4ff721b3e886f0dc05856ffff0aabb64a8504b1746a47fdd73e6b7ebc068f06ac7ffa44c757e4de207fc3cbfaf0469d3ac6795d40630bcafe8c658627e4bc6b86fd6a2135afbc18ccc8e6d0e1e86016930ca92edc5aa3fbe2c57de136d0ea5f41642b6a5d0ddeb380f2454d76a16639d663687f2a2e29fb9304243900d26d
+d = 93434d3c03ec1da8510b74902c3b3e0cb9e8d7dccad37594d28b93e065b468d9af4892a03763a63eae060c769119c23c
+Qx = a52c25f2af70e5bc6a992ecef4ea54e831ed5b9453747d28aec5cffb2fcfee05be80c5cbab21606b5507aa23878adee1
+Qy = 2cf2a9afeff83f3041dc8a05f016ccae58aa1a0e0dc6be9d928e97f2598c9ba5e9718d5eb74c9cfb516fd8c09f55f5b9
+k = 13d047708ae5228d6e3bbada0e385afdb3b735b31123454fdf40afe3c36efed563fd2cce84dcc45c553b0993d9ca9ec3
+R = a0203f6f2c456baac03538ed506a182e57a25151802cf4b2557613b2fb615ebd4c50ddc505f87c048a45bad3b2fc371c
+S = 0eab56457c4080400fa3af124761d5a01fef35f9649edba8b97d22116386f3b8b363e97ef3f82616d5d825df1cf865ef
+
+Msg = db2ad659cf21bc9c1f7e6469c5f262b73261d49f7b1755fc137636e8ce0202f929dca4466c422284c10be8f351f36333ebc04b1888cba217c0fec872b2dfc3aa0d544e5e06a9518a8cfe3df5b20fbcb14a9bf218e3bf6a8e024530a17bab50906be34d9f9bba69af0b11d8ed426b9ec75c3bd1f2e5b8756e4a72ff846bc9e498
+d = e36339ddbe8787062a9bc4e1540690915dd2a2f11b3fe9ee946e281a0a2cbed426df405ed9cb0eca42f85443efd09e0c
+Qx = a1ffb4b790d1593e907369b69de10b93cddbb02c6131f787422364d9d692768ef8097970306cce16c97f2b10c538efa7
+Qy = d0692028601ea794d2563ffe9facc7273938fab47dd00b8960be15549a9c2b3f8552583eb4c6cd212fe486c159c79153
+k = 2226f7329378cecd697f36ae151546643d67760856854661e31d424fae662da910e2157da9bb6dfbe3622296e0b5710c
+R = 20dcc25b67dd997621f437f65d78347fb57f8295b1b14453b1128203cda892bcfe726a2f107d30975d63172e56f11d76
+S = 51cff592cbef75ef8321c8fa1e4229c4298b8180e427bee4e91d1e24fc28a729cf296beb728960d2a58cf26773d8e2e2
+
+Msg = dbd8ddc02771a5ff7359d5216536b2e524a2d0b6ff180fa29a41a8847b6f45f1b1d52344d32aea62a23ea3d8584deaaea38ee92d1314fdb4fbbecdad27ac810f02de0452332939f644aa9fe526d313cea81b9c3f6a8dbbeafc899d0cdaeb1dca05160a8a039662c4c845a3dbb07be2bc8c9150e344103e404411668c48aa7792
+d = 5da87be7af63fdaf40662bd2ba87597f54d7d52fae4b298308956cddbe5664f1e3c48cc6fd3c99291b0ce7a62a99a855
+Qx = 54c79da7f8faeeee6f3a1fdc664e405d5c0fb3b904715f3a9d89d6fda7eabe6cee86ef82c19fca0d1a29e09c1acfcf18
+Qy = 926c17d68778eb066c2078cdb688b17399e54bde5a79ef1852352a58967dff02c17a792d39f95c76d146fdc086fe26b0
+k = 1b686b45a31b31f6de9ed5362e18a3f8c8feded3d3b251b134835843b7ae8ede57c61dc61a30993123ac7699de4b6eac
+R = 9dbfa147375767dde81b014f1e3bf579c44dd22486998a9b6f9e0920e53faa11eed29a4e2356e393afd1f5c1b060a958
+S = e4d318391f7cbfe70da78908d42db85225c85f4f2ff413ecad50aad5833abe91bdd5f6d64b0cd281398eab19452087dd
+
+
+[P-521,SHA-224]
+
+Msg = 58ec2b2ceb80207ff51b17688bd5850f9388ce0b4a4f7316f5af6f52cfc4dde4192b6dbd97b56f93d1e4073517ac6c6140429b5484e266d07127e28b8e613ddf65888cbd5242b2f0eee4d5754eb11f25dfa5c3f87c790de371856c882731a157083a00d8eae29a57884dbbfcd98922c12cf5d73066daabe3bf3f42cfbdb9d853
+d = 1d7bb864c5b5ecae019296cf9b5c63a166f5f1113942819b1933d889a96d12245777a99428f93de4fc9a18d709bf91889d7f8dddd522b4c364aeae13c983e9fae46
+Qx = 1a7596d38aac7868327ddc1ef5e8178cf052b7ebc512828e8a45955d85bef49494d15278198bbcc5454358c12a2af9a3874e7002e1a2f02fcb36ff3e3b4bc0c69e7
+Qy = 184902e515982bb225b8c84f245e61b327c08e94d41c07d0b4101a963e02fe52f6a9f33e8b1de2394e0cb74c40790b4e489b5500e6804cabed0fe8c192443d4027b
+k = 141f679033b27ec29219afd8aa123d5e535c227badbe2c86ff6eafa5116e9778000f538579a80ca4739b1675b8ff8b6245347852aa524fe9aad781f9b672e0bb3ff
+R = 06b973a638bde22d8c1c0d804d94e40538526093705f92c0c4dac2c72e7db013a9c89ffc5b12a396886305ddf0cbaa7f10cdd4cd8866334c8abfc800e5cca365391
+S = 0b0a01eca07a3964dd27d9ba6f3750615ea36434979dc73e153cd8ed1dbcde2885ead5757ebcabba117a64fcff9b5085d848f107f0c9ecc83dfa2fa09ada3503028
+
+Msg = 2449a53e0581f1b56d1e463b1c1686d33b3491efe1f3cc0443ba05d65694597cc7a2595bda9cae939166eb03cec624a788c9bbab69a39fb6554649131a56b26295683d8ac1aea969040413df405325425146c1e3a138d2f4f772ae2ed917cc36465acd66150058622440d7e77b3ad621e1c43a3f277da88d850d608079d9b911
+d = 17e49b8ea8f9d1b7c0378e378a7a42e68e12cf78779ed41dcd29a090ae7e0f883b0d0f2cbc8f0473c0ad6732bea40d371a7f363bc6537d075bd1a4c23e558b0bc73
+Qx = 0156cd2c485012ea5d5aadad724fb87558637de37b34485c4cf7c8cbc3e4f106cb1efd3e64f0adf99ddb51e3ac991bdd90785172386cdaf2c582cc46d6c99b0fed1
+Qy = 1edeeda717554252b9f1e13553d4af028ec9e158dbe12332684fc1676dc731f39138a5d301376505a9ab04d562cc1659b0be9cb2b5e03bad8b412f2699c245b0ba2
+k = 1dc3e60a788caa5f62cb079f332d7e5c918974643dca3ab3566a599642cd84964fbef43ce94290041fe3d2c8c26104d9c73a57a7d4724613242531083b49e255f33
+R = 12592c0be6cce18efb2b972cd193d036dcb850f2390fa8b9b86b2f876548bc424fb3bc13c1e5c415fa09d0ecfcae5bf76fb23e8322d7eecb264a2ae6d20ef50d405
+S = 11bc9713be88e3b9912a3e5f5d7b56f20573e979b1a75d04ce339f724bddffa4665d25995fe24d32507d8a07c5e10169f5338ef2827737f7b0291752b21237217e3
+
+Msg = 7ba05797b5b67e1adfafb7fae20c0c0abe1543c94cee92d5021e1abc57720a6107999c70eacf3d4a79702cd4e6885fa1b7155398ac729d1ed6b45e51fe114c46caf444b20b406ad9cde6b9b2687aa645b46b51ab790b67047219e7290df1a797f35949aaf912a0a8556bb21018e7f70427c0fc018e461755378b981d0d9df3a9
+d = 135ea346852f837d10c1b2dfb8012ae8215801a7e85d4446dadd993c68d1e9206e1d8651b7ed763b95f707a52410eeef4f21ae9429828289eaea1fd9caadf826ace
+Qx = 18d40cc4573892b3e467d314c39c95615ee0510e3e4dbc9fa28f6cd1f73e7acde15ad7c8c5339df9a7774f8155130e7d1f8de9139ddd6dfe1841c1e64c38ea98243
+Qy = 17021782d33dc513716c83afe7ba5e7abef9cb25b31f483661115b8d6b5ae469aaf6f3d54baa3b658a9af9b6249fd4d5ea7a07cb8b600f1df72b81dac614cfc384a
+k = 0c24acc1edb3777212e5b0bac744eadf4eda11fa150753b355bf96b189e6f57fc02284bb22d8b3cd8bba7a09aae9f4ea955b382063425a6f8da2f99b9647b147172
+R = 183da7b8a9f9d5f08903359c1a2435b085fcf26a2ed09ab71357bb7634054acc569535e6fe81d28233e4703005fc4bf83ce794d9463d575795aa0f03398e854cefd
+S = 0b3621145b9866ab7809139795cc30cd0404127a7f0fafa793660491009f6c53724fdb0b1ffbf0fd51c131180b8a957fe66e76d2970247c024261c768dee9abbfb9
+
+Msg = 716dabdb22a1c854ec60420249905a1d7ca68dd573efaff7542e76f0eae54a1828db69a39a1206cd05e10e681f24881b131e042ed9e19f5995c253840e937b809dfb8027fed71d541860f318691c13a2eb514daa5889410f256305f3b5b47cc16f7a7dad6359589b5f4568de4c4aae2357a8ea5e0ebaa5b89063eb3aa44eb952
+d = 1393cb1ee9bfd7f7b9c057ecc66b43e807e12515f66ed7e9c9210ba1514693965988e567fbad7c3f17231aacee0e9b9a4b1940504b1cd4fd5edfaa62ba4e3e476fc
+Qx = 1e855c935139c8092092cfa733db1292530506eeb2bbb1687f9602c36d97a6714e998892d5d3b842d1896a6ece9d549e9792881a256256137b3dff180c96cc5d07b
+Qy = 18d83b6e93cd287311f7bf7c1d7f9eeabcf0b69c12f2d8f40e333e81e956d968532a37a4c04d761874df293b484cd7053b03fdbc2fdcd3b4c412d6f272fb7c93fe6
+k = 1d98619bdc04735d30c222fc67da82c069aea5f449af5e8c4db10c1786c0cb9e6f2cc0bb66fa6be18c485570d648dafcd0a973c43d5c94e9a9dacbd3170e53fa2a0
+R = 0bf47fabe107ce0ec03e2ad60a79b058e1bebb18568b6a8cdbe86032e71aa30c15766105b2ea952cfa79bcab046df601159f96e179bbcf252dc68ac73d31481fdae
+S = 1f918fec69cd07d90f9d892b7117e7519c3224947f4262f1fd97077dd5386a6c78aeddff3ee97e59ea353f06029f1336f0d6ef5c0f4b17ca59343a55319b7bfc3db
+
+Msg = 9cc9c2f131fe3ac7ea91ae6d832c7788cbbf34f68e839269c336ceef7bef6f20c0a62ea8cc340a333a3002145d07eba4cf4026a0c4b26b0217a0046701de92d573d7c87a386a1ea68dc80525b7dcc9be41b451ad9f3d16819e2a0a0b5a0c56736da3709e64761f97cae2399de2a4022dc4c3d73c7a1735c36dbde86c4bc5b6f7
+d = 179fa164e051c5851e8a37d82c181e809a05fea9a3f083299b22684f59aa27e40dc5a33b3f7949338764d46bfe1f355134750518b856d98d9167ef07aac3092c549
+Qx = 1857cc7bbed20e87b3fd9a104956aa20c6502192910e0e7598410526ebfe1c99397b85189612a60c51fb8f4dd5cb08a8cd2e702563062dcb043410715c5323a0046
+Qy = 1fce8d135284310d2f38c216030634b32cd223222f0d9d8d2b7c55477c4b8b74fc6c96a6092f34b05ca44d3633a5037c2166c479a032bb4f949f89fc1ba5236d07d
+k = 16d9704c0cee791f2938bb2a8a595752a3635c2f557efeecefd719414b5f2aaf846080f582c76eae7a8fddf81859b49d0131c212524d55defa67dca1a9a28ca400f
+R = 1c9a4e51774384e8362876a87c572e6463a54413c7c6252c552ebb182f83e45ace436ade4ca373d8a7216e83efb62c8b41c4d5132a0afa65078f16d189baca39187
+S = 1e92a7dd5fea29a666398e1df5775cbb5664fe6943fe4c1d2bba516b7543c84df584458e53919c4ffab579a26fb3c892a5d1a77b0a07428c89350f8b559e627b014
+
+Msg = 14c69f8d660f7a6b37b13a6d9788eff16311b67598ab8368039ea1d9146e54f55a83b3d13d7ac9652135933c68fafd993a582253be0deea282d86046c2fb6fd3a7b2c80874ced28d8bed791bd4134c796bb7baf195bdd0dc6fa03fdb7f98755ca063fb1349e56fd0375cf94774df4203b34495404ebb86f1c7875b85174c574c
+d = 13dabca37130ba278eae2b3d106b5407711b0d3b437fbf1c952f0773571570764d2c7cb8896a8815f3f1975b21adc6697898e5c0a4242092fc1b80db819a4702df4
+Qx = 0bc2aebf40cd435bc37d73c09d05f2fd71321111a767c2b0d446f90dd4a186839c694ceb734e027e7ee948f0f63e4d3f1656d3d543df23c342a599306909b347109
+Qy = 1f4c98ac03f0718e58d5d1762c920445b11dbdd60ec7f60095809204e14965a4ecb0be6fea06adbac8ba431d6f144c75c199225df2a619a34be99897125b3a10af8
+k = 0401187c8b89945a1e48cda9ee52167789f4121e67482a7ac797899f5d3d2e623aed31e4adae08a8d43e69028fa074d2650317cbc765f6ed191cf0317b4bae57881
+R = 1e572afed754016fba43fc33e352932c4db65efcb84e2bd159b40fc5925893b161effc40240be28d8c07154d2615f605c6f0451b976522d95afd37f46602df7a12a
+S = 030370c1c5352c2b663ac1858b42f69545b2f58ed5b2c007f303726977d3c756b5d644ec6788f94c886f78269aa190a3d8d1ae10e4fd24d937c4556fb9e1953fd6d
+
+Msg = 8d8e75df200c177dbfe61be61567b82177ea5ec58e2781168d2277d2fd42668f01248ca3eb29ffa2689b12ae40f9c429532b6d2e1f15891322b825a0a072a1c68fa09e78cfdef3e95ed6fdf7233a43cb68236560d49a3278f0b3f47cb08f475bd9ab2f60755ea4a1767de9313b71a1b9ea87ef33f34682efbda263b0f8cc2f52
+d = 198681adbde7840d7ccd9cf1fb82056433fb4dd26bddf909af7b3b99da1ca2c05c8d4560ecd80ba68f376f8b487897e374e99a9288ed7e3645cc0d00a478aae8d16
+Qx = 057ce3777af7032f1f82308682e71fe09f88bf29dacd5018a725e1caa4b1e2bfdd894fe618f9266f31ba089856dc9c1b70e4a2faa08b4b744d1aafcd5ae99e2c736
+Qy = 199bcfef2021bc5890d7d39ec5dc0c26956801e84cae742cf6c50386eb289b6e97754dd25a94abf81f1cb1b36935b5eb29f4b32a6516d2ff6a7d23064a0daec94b3
+k = 19d2d74ad8ee2d85048f386998a71899ef6c960b4ab324e5fd1c0a076c5a632fd0009500076522e052c5c9806eef7056da48df6b16eb71cdf0f1838b0e21715fce0
+R = 18ecacbcffd5414bbb96728e5f2d4c90178e27733d13617e134ec788022db124374bbaa11e2c77fe3f38d1af6e998e1b0266b77380984c423e80ffa6ff2bcafd57a
+S = 1c727f34b6a378f3087721a54e9796499b597ecf6666b8f18312d67e1190a8a66e878efc2367b551267494e0245979ef4deed6d2cbf2c3711af6d82ccfeb101a377
+
+Msg = 10631c3d438870f311c905e569a58e56d20a2a560e857f0f9bac2bb7233ec40c79de145294da0937e6b5e5c34fff4e6270823e5c8553c07d4adf25f614845b2eac731c5773ebbd716ab45698d156d043859945de57473389954d223522fbafecf560b07ef9ba861bcc1df9a7a89cdd6debf4cd9bf2cf28c193393569ccbd0398
+d = 08c4c0fd9696d86e99a6c1c32349a89a0b0c8384f2829d1281730d4e9af1df1ad5a0bcfccc6a03a703b210defd5d49a6fb82536f88b885776f0f7861c6fc010ef37
+Qx = 164ac88ed9afe137f648dd89cdd9956682830cac5f7c1a06d19a1b19f82bb1d22dfeefea30d35c11202fed93fd5ce64835d27c6564d6e181287fa04a2d20994986b
+Qy = 05cb83669265f5380ccefe6b4f85fdf0049e6703f6f378a0b2e52ed0fbbcf300afebb722f4ed48e3819cb976c1d60e2ba05646b478f6dfecfbae730e9644c297f00
+k = 189801432cba9bf8c0763d43b6ec3b8636e62324587a4e27905b09a58e4aa66d07d096dbce87824e837be1c243dd741f983c535a5dd2f077aac8beee9918258d3cb
+R = 0917723f7241e8dc7cd746b699ab621d068dd3a90e906aaf0a4862744b96fd4e5ccdb9c7796c27f7196e693d06ec209464c3ea60ad6313e9b77cceaa14767e6651c
+S = 0957b0ecdc3668f6efa5d0957615bcfffd6419c5e57579b74f960f65ae3fb9e8284322ff710b066f7e0959ac926d3cf9a594bdb70bbec756c96910b26a2486dee9e
+
+Msg = 80aad6d696cbe654faa0d0a24d2f50d46e4f00a1b488ea1a98ed06c44d1d0c568beb4ab3674fc2b1d2d3da1053f28940e89ba1244899e8515cabdd66e99a77df31e90d93e37a8a240e803a998209988fc829e239150da058a300489e33bf3dcdaf7d06069e74569fee77f4e3875d0a713ccd2b7e9d7be62b34b6e375e84209ef
+d = 1466d14f8fbe25544b209c5e6a000b771ef107867e28ed489a42015119d1aa64bff51d6b7a0ac88673bbc3618c917561cff4a41cdb7c2833dab5ebb9d0ddf2ca256
+Qx = 1dc8b71d55700573a26af6698b92b66180cf43e153edadb720780321dbb4e71d28e0a488e4201d207fc4848fe9dd10dcabec44492656a3ff7a665fe932445c82d0b
+Qy = 1920b16331b7abeb3db883a31288ef66f80b7728b008b3cc33e03a68f68d9e653a86e3177bbc00014fa5ea4c1608c0d455c2e2ac7bd8ab8519ebf19955edf1baf8d
+k = 160d04420e0d31b0df476f83393b1f9aff68389cc3299e42ef348d97646f7531a722b66ddfb9501bbb5c4a41d84c78be7233b11489bceb817d23060e6017433fab8
+R = 08077aabd0a342f03f912007c586cfedfc63f93d1118f720d5b62b3ce141a60f86f111dfd8fc2e31a6778981f1a5e28f29a7369bd7897bb41240c8d3a9c170e0ee0
+S = 00abc75fc154b93840579457820957e89d1260fee0a4b9bb1946f61ca1e71afd76bb5e1077b3e38ceb39d1fac5ef8b217c4110617b3ad118e02b3fcc2a39ef38613
+
+Msg = 8a7792a2870d2dd341cd9c4a2a9ec2da753dcb0f692b70b64cef2e22071389c70b3b188dea5f409fb435cbd09082f59de6bc2ff9e65f91b7acc51e6e7f8e513148cb3c7c4664f227d5c704626b0fda447aa87b9d47cd99789b88628eb642ed250312de5ba6b25f3d5342a3cbb7ebd69b0044ee2b4c9ba5e3f5195afb6bea823d
+d = 01a99fcf54c9b85010f20dc4e48199266c70767e18b2c618044542cd0e23733817776a1a45dbd74a8e8244a313d96c779f723013cd88886cb7a08ef7ee8fdd862e7
+Qx = 1912d33b01d51e2f777bdbd1ada23f2b1a9faf2be2f2a3b152547db9b149b697dd71824ca96547462e347bc4ef9530e7466318c25338c7e04323b1ba5fd25ea7162
+Qy = 0bbe9b1e3a84accd69b76b253f556c63e3f374e3de0d1f5e3600fc19215533b2e40d6b32c3af33314d223ea2366a51d1a337af858f69326389276f91be5c466e649
+k = 14fafd60cb026f50c23481867772411bb426ec6b97054e025b35db74fe8ea8f74faa2d36e7d40b4652d1f61794878510b49b7b4fe4349afccd24fc45fec2fd9e9e7
+R = 18b1df1b6d7030a23a154cacce4a2e3761cc6251ff8bf6c9f6c89d0a15123baef9b338ada59728349ce685c03109fcde512ed01a40afd2ca34e1bc02ecf2871d45c
+S = 0a399f9b9e21aeddf450429fec2dc5749e4a4c7e4f94cee736004dcc089c47635da22845992cd076a4f0a01d2cc1b0af6e17b81a802361699b862157ad6cad8bd1d
+
+Msg = f971bcd396efb8392207b5ca72ac62649b47732fba8feaa8e84f7fb36b3edb5d7b5333fbfa39a4f882cb42fe57cd1ace43d06aaad33d0603741a18bc261caa14f29ead389f7c20536d406e9d39c34079812ba26b39baedf5feb1ef1f79990496dd019c87e38c38c486ec1c251da2a8a9a57854b80fcd513285e8dee8c43a9890
+d = 1b6015d898611fbaf0b66a344fa18d1d488564352bf1c2da40f52cd997952f8ccb436b693851f9ccb69c519d8a033cf27035c27233324f10e9969a3b384e1c1dc73
+Qx = 110c6177ceb44b0aec814063f297c0c890671220413dbd900e4f037a67d87583eaf4b6a9a1d2092472c17641362313c6a96f19829bb982e76e3a993932b848c7a97
+Qy = 0f6e566c4e49b2ee70a900dc53295640f3a4a66732df80b29f497f4ae2fa61d0949f7f4b12556967bb92201a4f5d1384d741120c95b617b99c47a61e11c93a482d6
+k = 1a88667b9bdfe72fb87a6999a59b8b139e18ef9273261549bc394d884db5aa64a0bc7c7d38a8ef17333478d2119d826e2540560d65f52b9a6dc91be1340cfd8f8f8
+R = 015f73def52ea47ddb03e0a5d154999642202e06e6734ac930c1dc84756c67bbb1cca9f21f92d61bfdb2052c5dd2833349610f68139393d77250a7662ef7bd17cbe
+S = 155c744a729f83b27d1f325a91e63a0d564fe96ff91eaa1bad3bff17d2abffa065d14a1d20a04dd993f6ed3260b60bcc6401e31f6bc75aaafe03e8c1a9cd14d2708
+
+Msg = ec0d468447222506b4ead04ea1a17e2aa96eeb3e5f066367975dbaea426104f2111c45e206752896e5fa7594d74ed184493598783cb8079e0e915b638d5c317fa978d9011b44a76b28d752462adf305bde321431f7f34b017c9a35bae8786755a62e746480fa3524d398a6ff5fdc6cec54c07221cce61e46fd0a1af932fa8a33
+d = 05e0d47bf37f83bcc9cd834245c42420b68751ac552f8a4aae8c24b6064ae3d33508ecd2c17ec391558ec79c8440117ad80e5e22770dac7f2017b755255000c853c
+Qx = 1a6effc96a7f23a44bf9988f64e5cfafdae23fa14e4bee530af35d7a4ddf6b80dcd0d937be9dd2db3adcda2f5216fecbce867ee67e7e3773082f255156e31358c2f
+Qy = 1e7760190dfbe07ec2df87067597087de262c1e0a12355456faba91b2e7277050d73b924e14c0e93b8457a8b3e1f4207ce6e754274f88ad75c000d1b2977edc9c1a
+k = 18afea9a6a408db1e7a7bb1437a3d276f231eacfc57678bfa229d78681cbe4e800e6065332a3128db65d3aa446bb35b517dca26b02e106e1311881a95b0302d15e8
+R = 01c49b3c1d21f1678bdbe1ac12167e95e06617190bdee1a729c1c649210da19e2e210f6689e1310513bfe2ac6c0f4ee5f324f344b31b18df341eaadb826d07adc9b
+S = 129d4931ba457443012f6ffecd002f2abc3a4b65a58fee8457917ebcf24b29a1d3055b7fc62939a74ebb0c3582172ee7c3c75e0b2fa2367c6e04df63a7a91d593ad
+
+Msg = d891da97d2b612fa6483ee7870e0f10fc12a89f9e33d636f587f72e0049f5888782ccde3ea737e2abca41492bac291e20de5b84157a43c5ea900aef761006a4471072ab6ae6d515ffe227695d3ff2341355b8398f72a723ae947f9618237c4b6642a36974860b452c0c6202688bc0814710cbbff4b8e0d1395e8671ae67ada01
+d = 1804ab8f90ff518b58019a0b30c9ed8e00326d42671b71b067e6f815ac6752fa35016bd33455ab51ad4550424034419db8314a91362c28e29a80fbd193670f56ace
+Qx = 0a79529d23a832412825c3c2ad5f121c436af0f29990347ecfa586ce2e57fd3c7e0624d8db1f099c53473dbc2578f85416ad2ac958a162051014fb96bf07f9e1d17
+Qy = 17c0750f26df0c621d2d243c6c99f195f0086947b1bf0f43731555f5d677e2d4a082fb5fe8da87e1592a5fa31777da3299cede5a6f756edf81c85b77853388bb3ab
+k = 042d7c36fec0415bc875deb0fab0c64548554062e618aee3aa6670ffd68ab579fe620d3a9316357267fd3111c0ed567dca663acd94b646d2ba0771953cd9690ef42
+R = 0d01dfbef126febbdfa03ef43603fd73bc7d2296dce052216e965fed7bb8cbbc24142bfcddb60c2e0bef185833a225daa0c91a2d9665176d4ad9986da785f4bfcf0
+S = 16627e2614dbcd371693c10bbf579c90c31a46c8d88adf59912c0c529047b053a7c7715142f64dcf5945dbc69ff5b706c4b0f5448d04dd1f0b5a4c3765148bf253d
+
+Msg = 924e4afc979d1fd1ec8ab17e02b69964a1f025882611d9ba57c772175926944e42c68422d15f9326285538a348f9301e593e02c35a9817b160c05e21003d202473db69df695191be22db05615561951867f8425f88c29ba8997a41a2f96b5cee791307369671543373ea91d5ed9d6a34794d33305db8975b061864e6b0fe775f
+d = 0159bff3a4e42b133e20148950452d99681de6649a56b904ee3358d6dd01fb6c76ea05345cb9ea216e5f5db9ecec201880bdff0ed02ac28a6891c164036c538b8a8
+Qx = 12d7f260e570cf548743d0557077139d65245c7b854ca58c85920ac2b290f2abfeccd3bb4217ee4a29b92513ddce3b5cbf7488fb65180bb74aeb7575f8682337ef5
+Qy = 17560186230c7e8bff0bffce1272afcd37534f317b453b40716436a44e4731a3ec90a8f17c53357bc54e6ff22fc5b4ca892321aa7891252d140ece88e25258b63d5
+k = 14b8a30f988cefdc0edec59537264edb0b697d8c4f9e8507cf72bc01c761304bd2019da1d67e577b84c1c43dd034b7569f16635a771542b0399737025b8d817e1c3
+R = 0fc50939ebca4f4daa83e7eaf6907cb08f330c01d6ea497b86becda43dfcad47cb5c48f5eb2cc924228628070bcd144088c449a7873242ba86badf796097dbecd6d
+S = 0ccb6463c4301ba5c043e47ed508d57dd908fd0d533af89fd3b11e76343a1cf2954ce90b0eb18cbc36acd6d76b3906612d8a0feec6ebed13d88650ed9c708b28a11
+
+Msg = c64319c8aa1c1ae676630045ae488aedebca19d753704182c4bf3b306b75db98e9be438234233c2f14e3b97c2f55236950629885ac1e0bd015db0f912913ffb6f1361c4cc25c3cd434583b0f7a5a9e1a549aa523614268037973b65eb59c0c16a19a49bfaa13d507b29d5c7a146cd8da2917665100ac9de2d75fa48cb708ac79
+d = 17418dfc0fc3d38f02aa06b7df6afa9e0d08540fc40da2b459c727cff052eb0827bdb3d53f61eb3033eb083c224086e48e3eea7e85e31428ffe517328e253f166ad
+Qx = 00188366b9419a900ab0ed9633426d51e25e8dc03f4f0e7549904243981ec469c8d6d938f6714ee620e63bb0ec536376a73d24d40e58ad9eb44d1e6063f2eb4c51d
+Qy = 09889b9203d52b9243fd515294a674afd6b81df4637ffdddc43a7414741eda78d8aa862c9cbbb618acec55bb9a29aac59616fc804a52a97a9fc4d03254f4469effe
+k = 1211c8824dcbfa0e1e15a04779c9068aed2431daeac298260795e6a80401f11f6d52d36bcee3cfa36627989c49d11475163aa201d2cd4c5394144a6bb500bbaf02b
+R = 1d59401b8ac438855d545a699991142685077a409de2418c7ccfe01a4771b3870e76287a9654c209b58a12b0f51e8dc568e33140a6b630324f7ef17caa64bf4c139
+S = 143af360b7971095b3b50679a13cd49217189eaee4713f4201720175216573c68f7ac6f688bfe6eb940a2d971809bf36c0a77decc553b025ed41935a3898685183b
+
+[P-521,SHA-256]
+
+Msg = 8ab8176b16278db54f84328ae0b75ef8f0cd18afdf40c04ad0927ed0f6d9e47470396c8e87cde7a9be2ffbfe6c9658c88b7de4d582111119c433b2e4a504493f0a1166e3a3ea0d7b93358f4a297d63f65a5e752f94e2ee7f49ebcc742fa3eb03a617d00c574245b77a20033854d82964b2949e2247637239ab00baf4d170d97c
+d = 1e8c05996b85e6f3f875712a09c1b40672b5e7a78d5852de01585c5fb990bf3812c3245534a714389ae9014d677a449efd658254e610da8e6cad33414b9d33e0d7a
+Qx = 07d042ca19408524e68b981f1419351e3b84736c77fe58fee7d11317df2e850d960c7dd10d10ba714c8a609d163502b79d682e8bbecd4f52591d2748533e45a867a
+Qy = 197ac6416111ccf987d290459ebc8ad9ec56e49059c992155539a36a626631f4a2d89164b985154f2dddc0281ee5b5178271f3a76a0914c3fcd1f97be8e8376efb3
+k = 0dc8daaacddb8fd2ff5c34a5ce183a42261ad3c64dbfc095e58924364dc47ea1c05e2599aae917c2c95f47d6bb37da008af9f55730ddbe4d8ded24f9e8daa46db6a
+R = 09dd1f2a716843eedec7a6645ac834d4336e7b18e35701f06cae9d6b290d41491424735f3b57e829ad5de055eaeef1778f051c1ee152bf2131a081e53df2a567a8a
+S = 02148e8428d70a72bc9fa986c38c2c97deda0420f222f9dc99d32c0acba699dc7ba0a2b79ce5999ff61bd0b233c744a893bc105bca5c235423e531612da65d72e62
+
+Msg = c4bc2cec829036469e55acdd277745034e4e3cc4fcd2f50ec8bd89055c19795a1e051ccf9aa178e12f9beab6a016a7257e391faa536eaa5c969396d4e1ade36795a82ebc709d9422de8497e5b68e7292538d4ccdc6dd66d27a3ece6a2844962b77db073df9489c9710585ba03d53fa430dbc6626dc03b61d53fc180b9af5dea6
+d = 0b65bf33b2f27d52cbfabcadce741e691bf4762089afd37964de1a0deda98331bf8c74020a14b52d44d26e2f6fa7bcddbe83be7db17a0c8a1b376469cf92c6da27c
+Qx = 10038bb9a7aea626de68c14c64243150e72c69e2f8a1ab922bfbdaa6f33d24fb4542c0324357b0dd640bbcd07632ecd253f64ca2bfbfbf3de9b24fffd0568ab82da
+Qy = 0faf867d95308cc36d6f46844a0f535dc70f9768eed011a2464d2f308fa1d8e72c3616aec7e70516908183ffce7fdd36984a15f73efaa3858c2edf16a784d40e6c2
+k = 14aeb96c57d99677a1f5e4588064215e7e9af4027bfb8f31ff6126dbf341b8e6f719465e4273e91ba32670feca802549808322b7ee108bb20653cf20f93284d365f
+R = 075ead62edf7d86c5d1bc2443d1aeb5dc034fd999e6ea012cef7499d9d050cd97d262095884e9fc89a42e15bd3dee80fe3c1ba10f4caabc4aabb86347023028b663
+S = 129a992a6ff66d41948d11fa680f732b1a74315b804c982805190ed9d2fae223f2b149980b9241998cdea0c5672595a8a49d5186a0ef7a46c0a376f925bdda81726
+
+Msg = 1c1b641d0511a0625a4b33e7639d7a057e27f3a7f818e67f593286c8a4c827bb1f3e4f399027e57f18a45403a310c785b50e5a03517c72b45ef8c242a57b162debf2e80c1cf6c7b90237aede5f4ab1fcaf8187be3beb524c223cc0ceff24429eb181a5eea364a748c713214880d976c2cd497fd65ab3854ad0d6c2c1913d3a06
+d = 02c4e660609e99becd61c14d043e8b419a663010cc1d8f9469897d7d0a4f076a619a7214a2a9d07957b028f7d8539ba7430d0b9a7de08beeeae8452d7bb0eac669d
+Qx = 0fb3868238ca840dbb36ecc6cf04f5f773ea0ab8e8b0fdcf779dc4039a8d7146a417504e953c0cb5e7f4e599cc2c168deda8b7f16084b5582f89f2ece4cae5167f7
+Qy = 1f90b5c15eeda48e747cf3ee8183166a49dbfac6161cbd09d29d40a6854f4c495e88a435892a920cdaad20d41985890b648badd4f0a858ffcbd9afdfc23134ede18
+k = 1f875bbf882cd6dd034a87916c7b3ba54b41b2ea2ce84ebaf4e393fcf7291fee09dec2b5bb8b6490997c9e62f077c34f0947fe14cec99b906dd6bf0b5d301e75ca1
+R = 07aa70425697736b298233249f5d0cf25c99e640c9ff88035ef1804820e1bfe7d043755f02d7a079494f7fa6dc26740c4e6b7b430c63f29c67bbd3a5c88d2f0e8d1
+S = 0e0d42e4ff11cf5be37a9fda348514d5097a662f214687cbfb28ff42d635b13029871ca4f464bb1fbce02d5da4d5fb61b2a071844259fc863d136197bec3a61e7c7
+
+Msg = adb5f069b2b501a3ebb83d4f1808eb07710ac4a7b12532996855a20bcc54b2f76812915f632163c3654ff13d187d007152617cf859200194b59c5e81fc6cc9eb1ceb75d654050f260caa79c265254089270ccd02607fdcf3246119738c496dc3a4bd5d3be15789fc3d29a08d6d921febe2f40aef286d5d4330b07198c7f4588e
+d = 17c3522007a90357ff0bda7d3a36e66df88ca9721fb80e8f63f50255d47ee819068d018f14c6dd7c6ad176f69a4500e6f63caf5cf780531004f85009c69b9c1230c
+Qx = 13a4bea0eed80c66ea973a9d3d4a90b6abbb5dee57d8affaf93390a8783a20982eba644d2e2809f66530adeeee7f9a1da7515447e9ba118999f76f170c375f621f7
+Qy = 12f9dfaee40a75d8442b39b37a5c19ea124b464236e9b9a31bae6780cfd50f7ea4a700154b5ea0feeb64e9b35a1b0e33e46900cca1f34d13bb17e5017769841af27
+k = 18388a49caeda35859ef02702c1fd45ff26991998bd9d5e189c12c36cdae3f642ddd4a79561bd1d3e1cd9359de8f5c9e1604a312d207a27b08a6033f2741794ced5
+R = 15c6264795837dfea19f91876455f564f073c5c84a3c9d76e67872ae0447ba0d4850d8721302b25bec7ebfedd2721de140b2f3dead547042b24b0876117e7093cc1
+S = 060eb74236c189a28ed20bd0822eb22d75f7d97c9043a3c8e3f6d4c90bc8ca02ac4d37c1171c799a1c7dfd2fcbf83406b5e48c051e0fbf0fd937bfe6c3db4e18154
+
+Msg = f253484d121d1ce8a88def6a3e9e78c47f4025ead6f73285bf90647102645b0c32d4d86742a50b8b7a42d5f6156a6faf588212b7dc72c3ffd13973bdba732b554d8bffc57d04f8167aef21ee941ee6ffb6cce0f49445bd707da8deb35dca650aaf761c3aa66a5ebccddd15aee21293f63061a7f4bfc3787c2cd62c806a1a9985
+d = 0c4dad55871d3bd65b016d143ddd7a195cc868b3048c8bbcb1435622036bdb5e0dec7178ca0138c610238e0365968f6ddd191bbfacc91948088044d9966f652ff25
+Qx = 014858a3b9bd426b678fdcf93fc53d17e7a9e8fe022442aaaba65399d12fd3a6a381958fb0f07ac6088f4e490506ec0f1ab4d0dbd461126f7eb46ff69cfa8bd88af
+Qy = 18c18ce29ecc6d79d26a2de0cd31c4b32e84b5e90f6ba748f86c5afbd89618aceb9079460cbd1a8261ed5476973e61bf1d17ea78b022387443800c9247d21dde550
+k = 05577108f4187a173e5c29e927a8fc8f5ffd37e184254a6e381ff1018955aec91a35f30085e8cee6a7555c10f9efdce26d62f2b4b52dfdbaeafc3a30983e2d50d5b
+R = 0344375ae7c804cbe32ced7a20976efae5d9c19eb88b6e24514d1d0cfb728b0f4601098b18b2e98f42b5222dd5237d4d87767007bf5acb185c5526d72047e2cb1a1
+S = 02de4cfa908c73c1102d6fb7062baf54a056a9517701e036c9c51e09899d60051612d59348945f845dffebec5aa395b2fac7229929033615788777306ccad96d0a3
+
+Msg = 33bab1c369c495db1610965bc0b0546a216e8dd00cd0e602a605d40bc8812bbf1ffa67143f896c436b8f7cf0bed308054f1e1ff77f4d0a13c1e831efbd0e2fcfb3eadab9f755f070ba9aeaceb0a5110f2f8b0c1f7b1aa96a7f2d038a1b72e26400819b1f73d925ea4e34d6acaf59d0a461a34ce5d65c9c937a80e844e323a16d
+d = 03d4749fadcc2008f098de70545a669133c548ce0e32eec1276ff531bcff53533144555728ad8906d17f091cc0514571691107350b6561858e90dbe19633aaf31bf
+Qx = 10fe5986b65f6e65d13c88c4d2aed781a91026904f82129d46779bdadaf6b733c845a934e941ab4a285efdea9c96ecc9dc784d87e4d937b42c337b3a9cb111a9600
+Qy = 077853768a2a4d6f596f57414e57ec60b76d3cd5ece8351cd1f335ebcb8801a3d91fb82c65caaeb5c31eea9918367bb5906863ff3ccaf7a6cee415e0d75c15ac2e0
+k = 1fbb4de337b09e935a6dc6215ffcfcb85d236cc490585e73251a8b8bac37cfa36c5d1df5f4536d33659be1e7a442529a783452f7efda74a4f661b6a127f9248aaf7
+R = 09d8f10eeff6178594c89d6e8184f9502117384813243ddf9ccf3c8eac5dc6502c472dfc1487a5caffc569f7dedd14a8ebcb310e9bacdb79fb6655aba026cdf87f2
+S = 0f74236c7915d638708d17c9f10e39dda358faf9bbb821d8dcda0d151aac143bfb165ad0a23a65cd3de532e32cad928728f5ae1c16f58fc16577f3ca8e36f9e708b
+
+Msg = 08c8b7faaac8e1154042d162dca1df0f66e0001b3c5ecf49b6a4334ce4e8a754a1a8e4daf8ec09cf1e521c96547aed5172ef852e82c03cddd851a9f992183ac5199594f288dbcc53a9bb6128561ff3236a7b4b0dce8eaf7d45e64e782955ee1b690ce6a73ece47dc4409b690de6b7928cbe60c42fc6a5ddf1d729faf1cc3885e
+d = 096a77b591bba65023ba92f8a51029725b555caf6eff129879d28f6400e760439d6e69ce662f6f1aecf3869f7b6057b530a3c6ff8ed9e86d5944f583ee0b3fbb570
+Qx = 0fdf6aed933dba73913142ef8bdcd4b760db8500831cd11d7707ab852a6372c05d112a1e7fbc7b514c42142c7370d9f4129493cd75cc6f2daf83747078f15229db6
+Qy = 0ef91dffb3c43080a59534b95ca585ee87f6145f6a0199b2b82c89f456d8bd8e6ac71c78039c08177184484eb2ebd372f189db3a58fab961a75a18afec1ee32764a
+k = 13aa7b0471317a2a139c2f90df1c40d75e5a8a830fbaf87030fffdb2ef6f2c93d1310c9ed7fe9d7bcd4fe46537ff2495bc9c4f0aaff11461f5e4bebbfbce9a8740a
+R = 1c7a21800962c91d4651553633b18612d931bb88bff8b743ed595b4e869437e50f8e84fbf334c99061db123a1c40b73b07e203790561a37df65a660355ba2017d78
+S = 1301e1782559a38f1ca0eebe9bed0f5c7c33103d506a24f8a688f500ee1fe37f97b6685319279e82e6fe43cfd823ccbc123309974cffa76c4f8d41ec02a3cbc45f1
+
+Msg = ba74eed74282811631bd2069e862381e4e2a1e4e9a357b1c159a9ce69786f864b60fe90eeb32d8b72b099986fc594965a33285f7185b415df58fead7b8b50fc60d073680881d7435609ad1d22fd21e789b6730e232b0d2e888889fb82d6ad0337ab909308676164d4f47df44b21190eca8ba0f94995e60ad9bb02938461eee61
+d = 015152382bfd4f7932a8668026e705e9e73daa8bade21e80ea62cf91bd2448ebc4487b508ca2bdaaf072e3706ba87252d64761c6885a65dcafa64c5573c224ae9e6
+Qx = 00b8c7c0186a77dc6e9addd2018188a6a40c3e2ba396f30bbd9293dba2841d57d60866b37f587432719b544d8bf7eb06d90a8c0dc9c93b0c53d53b2f667077228ca
+Qy = 1dd2e5c73ab908ae34f701689f1cd3cf5186d3a2bc941e208bf3ef970e5e429ee9b154d73286b2e5da423e75b7c7b78c7bdf915da92279db43265a0cdefca51f86a
+k = 0d03506999f5cc9ec3304072984a20a9c64a22ad9b418495ca904f4bbddc96e76d34672cb52763339d3f3bc5b1701c00a675b972797e3a086314da1a8d338436566
+R = 085406c0ff5ec91f598bb579ad8714ad718c3e133d5dcc2e67c5d2339c146b69919cac07f3bc2bda218f4c7c8be04855e2ca6fff7fbdc4fc0fda87c8c3081cad4f5
+S = 1b45f2066e583636215ae135afc202b8bf3f301eccff2e1c0198b9aeddf695fa8179488e7b622fc307f601e2f6551815117cc836bb09ef888f8e64a45d9c84ad30c
+
+Msg = dc71f171a28bdc30968c39f08f999b88dc04c550e261ecf1124d67f05edeae7e87fe9b8135a96fe2bc3996a4f47213d9d191184a76bd6310e1ee5cb67ea7fc3ef6f641a0ba165198040fa668192b75a4754fc02c224bd4a74aade5a8c814adf151c2bfeda65165a04ef359e39847c84e312afb66d4cd1db50d41ef3fe5f31296
+d = 1750ff0ca0c166560b2034bc5760fe0b3915340bc43216e9de0c1d4a76550e8b2036e8b874230f8d29354aed43e183610f24fd4abd4b0be2f111dae942bd7a121f7
+Qx = 1b4b8947192a7c0166c0e0b2791e217370836283e805f3ee11cfb78445aba3c5bc39fe594e01916617ad59e7c8e740d8f2d07d88905d3f33bd5e51aafd4943c5dc6
+Qy = 1175d117232836c28e717ce2a55e59f4ec550effde30d18e3d99e42c6aa2283c7b3e7f2f6ff1fca605dde78c3a5bffa689347b4c93f51ba59a1787bb7d5e43861dc
+k = 023645023d6bdf20652cdce1185c4ef225c66d54f18632d99ccf743bf554d04c214c88ce52a4f71ec75c899ad1b3c07c34112ca20b55c217ff1d72c9528e2774ce8
+R = 1e933f68ce0f8403cb16822b8e0564b1d39a35f27b53e4ae0bcdff3e051759464afbc34998ba7c8a7ee34ef6c1aaa722cffe48356fd0b738058358d4c768b3186c1
+S = 0a67368a305508ce6d25d29c84f552a4a513998990fef4936244f891a2909c30d5fdc9e8a267ecbf3c597138f4a08f7e92bee57d5420eadd700fee864bf78b2614b
+
+Msg = b895788d7828aaeace4f6b61a072ffa344d8ea324962ba6dab5efda93f65bf64a0f2ac6d5721d03ee70e2aef21cdba69fd29040199160e3a293b772ffb961ed694a8dc82800dab79367a4809a864e4aff6bc837aaa868e952b771b76591c0bb82249034e3208e593d85973d3fea753a95b16e221b2561644535c0131fe834ae7
+d = 023048bc16e00e58c4a4c7cc62ee80ea57f745bda35715510ed0fc29f62359ff60b0cf85b673383b87a6e1a792d93ab8549281515850fa24d6a2d93a20a2fff3d6e
+Qx = 0ba3dc98326a15999351a2ec6c59e221d7d9e7ee7152a6f71686c9797f3f330d3150123620d547813ba9d7cc6c6d35cc9a087d07dff780e4821e74ad05f3762efd6
+Qy = 18b051af9824b5f614d23ecadd591e38edbfe910ad6cbebc3e8a6bec11ea90691c17deb3bc5f34a4a3acd90b7b10f521f6ee7b3cfbfdc03b72d5a8783a4a77c3e4c
+k = 06099d2667f06c58798757632d07d8b3efbe9c1323efb0c244be6b12b3b163ba1b7cf5246c98dcc0771665a66696d687af5f28ed664fd87d5093df6427523d4db84
+R = 10dc80ea853064a2ba5a781f108aca3785c5ec0aa45aa05ba31d4de671170797589e863d54a3a986aadf6f670277f50355713dfb27d4ec7e348f787910b3cd668cd
+S = 018572bfad4f62e3694d1f2e6ffd432faed2e2b9d7e3611a07138212f1e79e6c394839f7cfae96bc368422630016fb9346681eadc5f9699e7331c3b5fde6d65e4c6
+
+Msg = 2c5bd848c476e34b427cfe5676692e588e1957957db7b5704492bd02104a38216535607f5d092dc40020130c04a3aaf0f1c52409834926d69a05d3f3188187a71d402a10ba34eac8629b4c6359b1095f30f710219298bf06b9f19bfc299981d7e251ca232a0a85338a7e02464731d1b25d4a1f68baf97064516590644820c998
+d = 02b8b866ce4503bb40ffc2c3c990465c72473f901d6ebe6a119ca49fcec8221b3b4fa7ec4e8e9a10dbd90c739065ad6a3a0dd98d1d6f6dcb0720f25a99357a40938
+Qx = 1b8c7a169d5455f16bfe5df1ba5d6ec9c76e4bad9968d4f5f96be5878a7b6f71d74bfac0076dd278bc4630629f3294646f17d6b6c712b0087e2c4d576039cfdc8b9
+Qy = 18faffd5422dfd1b61432fa77b9a288b2b7d546656c0dcca3032179e6f45ee3cf61d6a447fc51731cb54457343a41569fcf78cef42895f4da5efcb14ea1fc065f8d
+k = 0ac89e813f94042292aa1e77c73773c85cf881a9343b3f50711f13fa17b50f4e5cb04ac5f6fc3106a6ef4c9732016c4e08e301eefac19199459129a41a7589e0628
+R = 05bc7a253a028ee8b7253979b8d689d41d8df6fae7736341f22e28b6faf0cbbdebbd2ef4d73e56d2021af2c646dc15539a7c1e1c4dc9c7674808bd7968d8a66f947
+S = 0fd71575837a43a4cf1c47d0485cfd503c2cf36ebcea0fdef946ad29acb7fb2e7c6daf6b4eb741eb211081aed6207d02569f1518988f275ad94c7fd4735cb18a92e
+
+Msg = 65a0b97048067a0c9040acbb5d7f6e2e6ac462e1e0064a8ce5b5bbf8e57059e25a3ef8c80fc9037ae08f63e63f5bdb9378c322ad9b2daf839fad7a75b1027abb6f70f110247da7e971c7c52914e5a4f7761854432fa16b2a521e7bcaee2c735a87cad20c535bf6d04a87340c229bf9af8647eedca9e2dc0b5aa90f7fea3cdc0a
+d = 0a43b32ad7327ec92c0a67279f417c8ada6f40d6282fe79d6dc23b8702147a31162e646291e8df460d39d7cdbdd7b2e7c6c89509b7ed3071b68d4a518ba48e63662
+Qx = 172fb25a3e22c2a88975d7a814f3e02d5bb74cfb0aaa082c5af580019b429fddd8c7f9e09b6938f62e8c31019b25571aaceef3c0d479079db9a9b533ee8e1670abd
+Qy = 0ff5516223b6cc7c711705f15b91db559014e96d3839249c5c849f2aced228a8998177a1e91177abbb24b57a8ea84d944e0c95da860ae0925f1b40c0e1b7c9e0a46
+k = 0383eda042e06c0297fbd279a2ad40559c5c12ad458f73458eebcc92b308d3c4fcec20a5b59f698e16fa6ea02dba8661b6955f67c052f67b0a56460869f24cfdf7d
+R = 1b9c35356b9d068f33aa22a61370dae44a6cb030497a34fb52af23c6b684677370268f06bb4433be6795a71de570088aec17ce0c9933d2f76c7edce7f406f62fedd
+S = 06f07ea453cfa20ad604ba855332f62834657b0b795684d50c1562a675456e37f4dae45f0df47d8e27e47bc9ce9c9cbba1554c5b94b0b17401b73c8d0c0902c6cc4
+
+Msg = d6e366a87808eea5d39fe77cac4b8c754e865a796062e2ec89f72165cd41fe04c48148068c570e0d29afe9011e7e7a2461f4d9897d8c1fa14b4ff88cab40059d17ab724f4039244e97fcecb07f9ffeec2fb9d6b1896700fe374104a8c44af01a10e93b268d25367bf2bef488b8abcc1ef0e14c3e6e1621b2d58753f21e28b86f
+d = 03c08fdccb089faee91dac3f56f556654a153cebb32f238488d925afd4c7027707118a372f2a2db132516e12ec25f1664953f123ac2ac8f12e0dcbbb61ff40fb721
+Qx = 193301fc0791996ca29e2350723bd9aa0991ddbb4a78348ee72bdcd9ed63ce110ba3496f2ce0331b5c00d4d674c1b70114e17ce44a73c3e16bab14ed1ee924202e4
+Qy = 0aea9b288cfb2933ec0a40efa8e2108774e09b3863b3193d0dac6cc16ccaa5bd5f9ce133aec5cd3b62cbaeec04703e4b61b19572705db38cfaa1907c3d7c785b0cd
+k = 0d0e90d5ee7b5036655ad5c8f6a112c4b21c9449ca91c5c78421e364a2160bbac4428303657bc11ea69f59fb0fe85a41b8f155a362343094456fd2a39f2a79e4804
+R = 1a8c23a2965d365a4c2ffd0802ae8b3a69c6b84a1ba77fd8a5f2f61e8ec3a1dcb336f136e2a997252eaa94caf9b5ad6c9ecff5bf33abf547ca84985bb89908a11d7
+S = 1cc42a2dd97aa42b9df5ea430e0d4cb13106dd6da6e8c9315c96ed7b052db365bbde6960c9a965954a4398c18ea7db9593bbfc3c3b6b3466ff806fccac3de6424ab
+
+Msg = f99e1d272d0f5fb9c4f986e873d070ec638422bc04b47c715595e2cf1a701cdf88bc6c4b20085b357bad12ccba67cac8a5ca07f31ba432f9154ff1fadefd487a83a9c37e49fb70a2f170e58889cab0552e0a3806ccfa2a60d96e346851d84b7de6d1a4b8cf37567dc161a84f13421e3412457d4bc27f6213453c8519a2d7daa2
+d = 0969b515f356f8bb605ee131e80e8831e340902f3c6257270f7dedb2ba9d876a2ae55b4a17f5d9acd46c1b26366c7e4e4e90a0ee5cff69ed9b278e5b1156a435f7e
+Qx = 0fc7ae62b05ed6c34077cbcbb869629528a1656e2e6d403884e79a21f5f612e91fc83c3a8ac1478d58852f0e8ba120d5855983afd1a719949afa8a21aec407516c3
+Qy = 0aa705da6459a90eaa2c057f2e6614fb72fc730d6fdebe70e968c93dbc9858534768ea2666553cd01db132331441823950a17e8d2345a3cab039c22b21bfe7bd3b9
+k = 19029260f88e19360b70c11107a92f06faa64524cfbd9f70fecf02bd5a94f390582a7f4c92c5313bb91dc881596768d86f75a0d6f452094adbe11d6643d1a0b2135
+R = 07f2158e9b9fa995199608263969498923cf918fdc736427c72ce27ce4a3540dce2e8e5e63a8fc7ba46f7fa42480efbf79c6ed39521f6e6ec056079e453e80a89d9
+S = 08e349eed6f1e28b0dbf0a8aeb1d67e59a95b54a699f083db885f50d702f3c6a4069591afaa5b80b3c75efb1674ebd32c7ead0040d115945f9a52ee3a51806cad45
+
+Msg = 91f1ca8ce6681f4e1f117b918ae787a888798a9df3afc9d0e922f51cdd6e7f7e55da996f7e3615f1d41e4292479859a44fa18a5a006662610f1aaa2884f843c2e73d441753e0ead51dffc366250616c706f07128940dd6312ff3eda6f0e2b4e441b3d74c592b97d9cd910f979d7f39767b379e7f36a7519f2a4a251ef5e8aae1
+d = 013be0bf0cb060dbba02e90e43c6ba6022f201de35160192d33574a67f3f79df969d3ae87850071aac346b5f386fc645ed1977bea2e8446e0c5890784e369124418
+Qx = 167d8b8308259c730931db828a5f69697ec0773a79bdedbaaf15114a4937011c5ae36ab0503957373fee6b1c4650f91a3b0c92c2d604a3559dd2e856a9a84f551d9
+Qy = 19d2c1346aadaa3090b5981f5353243300a4ff0ab961c4ee530f4133fe85e6aab5bad42e747eee0298c2b8051c8be7049109ad3e1b572dda1cac4a03010f99f206e
+k = 1a363a344996aac9a3ac040066a65856edfb36f10bb687d4821a2e0299b329c6b60e3547dde03bdbd1afa98b0b75d79cf5aac0ef7a3116266cadf3dfbd46f8a4bfc
+R = 1ff097485faf32ce9e0c557ee064587c12c4834e7f0988cf181d07ba9ee15ae85a8208b61850080fc4bbedbd82536181d43973459f0d696ac5e6b8f2330b179d180
+S = 0306dc3c382af13c99d44db7a84ed813c8719c6ed3bbe751ead0d487b5a4aa018129862b7d282cce0bc2059a56d7722f4b226f9deb85da12d5b40648bf6ec568128
+
+[P-521,SHA-384]
+
+Msg = dbc094402c5b559d53168c6f0c550d827499c6fb2186ae2db15b89b4e6f46220386d6f01bebde91b6ceb3ec7b4696e2cbfd14894dd0b7d656d23396ce920044f9ca514bf115cf98ecaa55b950a9e49365c2f3a05be5020e93db92c37437513044973e792af814d0ffad2c8ecc89ae4b35ccb19318f0b988a7d33ec5a4fe85dfe
+d = 095976d387d814e68aeb09abecdbf4228db7232cd3229569ade537f33e07ed0da0abdee84ab057c9a00049f45250e2719d1ecaccf91c0e6fcdd4016b75bdd98a950
+Qx = 13b4ab7bc1ddf7fd74ca6f75ac560c94169f435361e74eba1f8e759ac70ab3af138d8807aca3d8e73b5c2eb787f6dcca2718122bd94f08943a686b115d869d3f406
+Qy = 0f293c1d627b44e7954d0546270665888144a94d437679d074787959d0d944d8223b9d4b5d068b4fbbd1176a004b476810475cd2a200b83eccd226d08b444a71e71
+k = 0a8d90686bd1104627836afe698effe22c51aa3b651737a940f2b0f9cd72c594575e550adb142e467a3f631f4429514df8296d8f5144df86faa9e3a8f13939ad5b3
+R = 02128f77df66d16a604ffcd1a515e039d49bf6b91a215b814b2a1c88d32039521fbd142f717817b838450229025670d99c1fd5ab18bd965f093cae7accff0675aae
+S = 008dc65a243700a84619dce14e44ea8557e36631db1a55de15865497dbfd66e76a7471f78e510c04e613ced332aa563432a1017da8b81c146059ccc7930153103a6
+
+Msg = 114187efd1f6d6c46473fed0c1922987c79be2144439c6f61183caf2045bfb419f8cddc82267d14540624975f27232117729ccfeacccc7ecd5b71473c69d128152931865a60e6a104b67afe5ed443bdbcdc45372f1a85012bbc4614d4c0c534aacd9ab78664dda9b1f1e255878e8ac59e23c56a686f567e4b15c66f0e7c0931e
+d = 04ceb9896da32f2df630580de979515d698fbf1dd96bea889b98fc0efd0751ed35e6bcf75bc5d99172b0960ffd3d8b683fbffd4174b379fbdecd7b138bb9025574b
+Qx = 0e7a3d30d5bd443549d50e9b297aaa87bc80b5c9e94169602d9d43d6d0c490c0bed8cc2170288b106bdbf4c9f1ce53fd699af0b4c64b494b08520e57dc01ab9a8b0
+Qy = 1d81056d37aec8a75d588f6d05977416e6f24ad0117a7f4450036d695612e7bc2771caed80e580314eebc88c8fc51c453f066e752481f212b57165d67f8a44f375a
+k = 046639c5a3ec15afae5e4a7a418ac760846512d880c359bc2c751b199ce43b10887e861b14127809754dbea47f6cc0140d2817e3f5b9a80ce01abd81f81b748433a
+R = 0f913de91e19bd8f943d542ae357bacc942a0967abc9be6c06239a379db8cc733fa50013e0b0f088bce9d630262feaa33b30d84f91bcf5ce9976e4e740fcb112f84
+S = 08a73a5c9c24235e0d9cecaac653f68ce5a6fb186ce67fa058d6ddbbd4d0a8c4d194e571148e8ad6c8882b4e33d2f60fb23dd7d07a1ae60864e8277918f592b3dc6
+
+Msg = 6744b69fc2420fe00f2352399bd58719e4ecdd6d602e2c80f194d607e58b27a0854745bfd6d504de2eb30b04cee0f44af710dd77e2f816ac3ac5692fad2d1d417893bb0edba2707a4c146a486f8728ca696d35cc52e9c7187c82d4bdb92eb954794e5ad15133f6bfea1f025da32ada710a3014cf11095b3ff69a94d087f17753
+d = 00a8db566bd771a9689ea5188c63d586b9c8b576dbe74c06d618576f61365e90b843d00347fdd084fec4ba229fe671ccdd5d9a3afee821a84af9560cd455ed72e8f
+Qx = 04f5b790cbe2984b71d41af5efed6c6893d15e13f31816d55a9c2926a104eee66f1ada83115d1388551218773b8b9d1138e3e3f027bb4392c90c14fd232580b4a11
+Qy = 0660eb160e9bfc8c5619e70e948e238c6fd37739bc1bb657b8e8436e63628f91992be7e63d9a7359623a1340642777b22026feb51116a6c50c54c3589b9bd39b6cb
+k = 1e7b5e53571a24bd102dd7ad44a4b8d8a4e60e5957bc3c4e5d3c73109f55233f072e572c7892f425ba5e64d3cb7966096bb34a47e26cd5b3e3b44108b310d9f681b
+R = 1a88bcd7e2bdff6e497d943dde432fb3f855a7177c466319cb53b701230c299db030276269685857d1e3f28110e690f2f529c8d18115eb381f313bc891d92ad278e
+S = 146f1984ea879274dfd5e86ad92e564a4de081523ddbb1c397b8f9595911ef2e6501bc081584d5340f7aa47e1af036234ac6f27a5ac31f78dd3b0ff1a62693c630d
+
+Msg = 16001f4dcf9e76aa134b12b867f252735144e523e40fba9b4811b07448a24ef4ccf3e81fe9d7f8097ae1d216a51b6eefc83880885e5b14a5eeee025c4232319c4b8bce26807d1b386ad6a964deb3bdca30ee196cfdd717facfad5c77d9b1d05fdd96875e9675e85029ecbf4f94c524624746b7c42870c14a9a1454acf3354474
+d = 1a300b8bf028449344d0e736145d9dd7c4075a783cb749e1ec7988d60440a07021a25a3de74ea5e3d7bd4ab774d8ad6163adae31877ef0b2bd50e26e9e4be8a7b66
+Qx = 05055b9ad726ba8a48219b0ecbfffb89f8428de895b231f676705b7de9f2022d9ff4e0114ebb52dea342f9bf76b2fb060c020e29d92074ebb1fbfe5290a58c8bc10
+Qy = 0415af7f20a6e945315adbf757316bb486c80780a0a3a15b4b9609f126d7341053a2b726ab63cb46feee527b0bf532b32b477e5671aea23d9b3c3e604b9029954b5
+k = 05a2e92717bb4dab3ee76724d4d9c2d58a32b873e491e36127985f0c9960c610962ca1c4510dba75c98d83beebdc58b1d8678e054640951d11db1bd2d8a4ab8476b
+R = 104a78ce94f878822daaf00ee527fbdbf6cceb3cbb23a2caa485e4109466de8910252f92379ab292cac8d1eda164f880c0067696e733fc8588a27703a3e1f5b8f1f
+S = 1ffe23e8ab5a31668a81161a234ea14879771fe9866f8872eb6edb672e0fe91d2bb75c9767a2dfbac7c15c802211236b22ea41ecd055a0b8b311ffc4255f86d5c67
+
+Msg = a9824a7b810aa16690083a00d422842971baf400c3563baa789c5653fc13416111c0236c67c68e95a13cec0df50324dcc9ae780ce4232607cb57dd9b2c61b382f0fa51fd4e283e2c55ffe272597651659fbd88cd03bfa9652cd54b01a7034c83a602709879e1325c77969bebfd93932ce09a23eae607374602201614ff84b141
+d = 06a253acd79912a74270fc0703ed6507ab20a970f2bc2277f782062092cf0e60ae1ca1bb44dec003169bc25ef6e7123dd04692f77b181a6d7e692e66b09d35a540c
+Qx = 1f15c6b1df156fdd8381cd7446e039435e445f8f36f0247475058da0e371bf72753f6e39f98066bc79370b038c39687ba18e16cb118fe6538b7568c5403c251f6b7
+Qy = 12d2b4f46b854eeae75f1c63f55b76bf0c604d47f870c28a50ecdeb52bba1dd9a0ff12e680804ff864111207652da7dd10b49edf66bb86be00bc06672de91982457
+k = 165faf3727e42fd61345cfa7b93e55fb4bf583b24bdc14ce635b6c99dbd788012f14da9a210b677c44acdd851e672f1a48188d6b8946c0efeebfe8a597ba0090a2c
+R = 1ad9463d2759abd568626548578deefdcd8b2d050ce6d9c7ed05feca20167484b86e89bdcc936fd647e0f8aedd7b6add2b8cf13ff6ff013c2b5540c6c56fda97a0c
+S = 1645a7d0e11015256cfb034adca198695eea6aedd44d9fbf496850ccfed950f43fffd8dbf41e113f2d3837d8a5dd62b2ed580112ff05800b1f73196e5576810e15b
+
+Msg = 90d8bbf714fd2120d2144022bf29520842d9fbd2dc8bb734b3e892ba0285c6a342d6e1e37cc11a62083566e45b039cc65506d20a7d8b51d763d25f0d9eaf3d38601af612c5798a8a2c712d968592b6ed689b88bbab95259ad34da26af9dda80f2f8a02960370bdb7e7595c0a4fffb465d7ad0c4665b5ec0e7d50c6a8238c7f53
+d = 0d5a5d3ddfd2170f9d2653b91967efc8a5157f8720d740dd974e272aab000cc1a4e6c630348754ab923cafb5056fc584b3706628051c557fce67744ee58ba7a56d0
+Qx = 128a4da5fc995678e457ceb3929adee93c280f851abe900fa21f4f809dafad4e33b381e0cd49ce8dd50e2e281cea162bfd60a1d6a1c0ee2228e6a011e171b559ab8
+Qy = 06eb0917cd72256992c49ea527f6bb0315f13d8047794a0f1da1e93737703b1c2a74a00441ef3b47b6a2ff789c49ae32d91cabe7b29247aeec44f6c40a76597a2ca
+k = 03269983a5c2bcc98e9476f5abf82424566b1f08b17204d29e310ece88f99eb677a537f86fe2529e409cfef2c12929644100099e0de2f27c0f0ac11105a4dca935b
+R = 1a5257ae1e8187ba954f535b86ff9b8d6a181a3b95c250d090cb4e9c3bfbd03aa64696a76c569728ef67780d6338d70ce46da40b87a3e49bfe154b93930890dfa93
+S = 05b6ccdfd5c63c7db76d3a0478064a2a376e0e050cb093be795a72a549247c2e4adba9183145c63d46479dbbdcf09986a6f64c09c7e16abc4853f6376c9558b014a
+
+Msg = 09952b1e09995e95bf0022e911c6ab1a463b0a1fdd0eec69117b34af1103c720b57600217de7cd178fef92de5391e550af72a8dcf7badf25b06dd039417f9a7d0f5be88fcd4e9655931d5b605452a667c9d1bae91d3476e7d51cff4108f116a49966fb3a7cff8df1c09734ce5620faf2dccb3dc5d94e7e9ac812da31f6d07a38
+d = 1bcedf920fa148361671b43c64e3186e1937eb1bd4b28cbd84c421472394552889bc05509aa732ef69d732b21b750523fdfd811f36467690fe94e01e64c9d5cbbe9
+Qx = 0d33c151d202a5d4d831348e940b027ee32e4b0b9b48d823a05c67ff3bdaee0189fc6680565f352c062e99968afc643208b4f9c7af185b861658a88c4ad0fcc8ba2
+Qy = 0e4441ddb546468ad8ffa6074f137edfbb81e82e0e7d8f05c4c54598aa996a9cde54cb371f642bfdd4ae7eca5b769696030027129a4183da93567ad142a2dff5183
+k = 046e619b83aac868b26d0b3cbfab55e630e0b55c461985b5d00f94ff3a5ce90ff412cebf46bbd84550d2031d573ca27d924624428360708c8d8491c29eb01d30f2e
+R = 08427c0f0ac0263472cd423c0fb554bf3c851b9c775c566ab0f6878717bd57665830767b05b7789c5c0b078195bd943dc737325552d32877ecb04a7c41bd07cd80c
+S = 10bb6652d6a624c40a7dd06828f15774130d02369ceb1a7d03b553e16e17b7fa5b5401f15885d5e4fc2e55c0c7a1b97871ab02f76386b93a16aa6e7eb65debac6dd
+
+Msg = 0bb0f80cff309c65ff7729c59c517d50fc0ed5be405ef70cb910c3f62c328c90853d4473530b654dda6156e149bc2222a8a7f9be665240e2fbe9d03f78a2356af0bacd1edb84c4801adc8293a8a0bd6123d1cf6ba216aca807a7eb4dca76b493eb6e3dbb69d36f0f00f856222f24d9b93ec34c3b261be2fca0451c00571928e5
+d = 03789e04b3a2a0254ade3380172c150d2fad033885e02ea8bea5b92db3f4adbab190ae423080a1154dfedec694c25eab46ce638be3db4e4cba67bc39f62d6e7db2d
+Qx = 1dbc2cf19627bdccf02432b1761f296275230c150cdde823ce3141ec315d7d05e16b2c29e2a67491078d5316883e933d85b4b10d4f64c477d3c4e0442dc928983a2
+Qy = 07562e720807dd118d3d8b265b3abc61a71fce43e3dce0e7b5ae18b7a4cb01ecc00d39c1f22e150a9a8728997e502144f5b3f6fa9b4cb8a4136212b082ca394e3f6
+k = 0fbccd8d7804bdd1d1d721b5ec74d4ba37603bc306f9fce2ec241853d8e07334e6b4b12c4ecca0c54bd71193dd7146507933a20737c5f3e15085830fab9b30ca57b
+R = 181915a3998d8fa214f9715f4ca928d09c36de168dc15c6970a8a062b5cea2dc969b2437ca17b684f78a1fd583aad8e6c762c8f4ab0c91b86a497145e3ca440d307
+S = 15a6c18c5c77f5470b27d061eafdc26b78561941a3b2ab0f5c81d40899fc053c3d9ed12d7d61e298abbae470009c7b2157731c58d7b16a66fa5abaf5e8a1b8ed394
+
+Msg = 7efacf213382ce30804e78b7256854d759147dba9729c51b2759465715bf2c421034c23dc651c13d6cce95f71fe6a84dfbee5768163ac5789ac0474c5ddf4115684683c5f7c204b33b8bcc0c03ac58f66cef2f53b721fe2fac91ad841126101a88f512a7c2ded38549d9f050d4b7961dda48a1489f026c5d111701762418cfe3
+d = 124700aa9186353e298edefc57bec0c7d0201cca10c1d80dd408d5d71040592b0ac59facdadfa8712445f5977ef8d4854022720c3f02d60e0732dbb2f171fcf1490
+Qx = 0c80fc4cecae5d53348524ddba6a160b735c75b22fdb39af17e2a613d09246e3bb0fd3f2978577f6db5d2118e05c7898024808f8eb8e021d7969cdcf7fc981200bb
+Qy = 1a880c93943fd446d4b3923b574d2221c1bb7b645fb5534dda60e827b497666ff586b77921f7e7f605147947194cffd2fef0678880b89cc0bc7fb74fa96d4b112d7
+k = 01a05238d595ded5c61d3bf6fde257dbf13095af8a5cb3a2e579e8e4c550fe31d12b71cc2dbcb295e6c4fd0fb8c22d1b741c097cc59d826ced1a8771f09983143c4
+R = 132762bc81e9922a8d642e3a9d0218affa21fa2331cfcb9e452545c5981c64a8f7e4cc8e68056023b2aa78bead59061d19c7f646c931163a91e544b106b3be8de9e
+S = 0c3a1b0b000c3169984132add51d611e2cb7069a262a6983d2ae72b459c36e6469509bdb0f473600b8686700b08910779dee9ba83f82e755d4a4ef5f124eb09397f
+
+Msg = 28edff8b9d85f5f58499cc11f492abdfab25e8945975bbaeee910afa2b8fc1295ec61406309ce4e09f4ab4f462959fc2a2786802466eb26d3b01be6919893ae75d0fdc2dc8a82e662550f9fce9627dd364188aaba5c6faa1b2d8a2235adfa5ad0dc140f88a2b2f103f5690e877d07fe8fd30d02d2b2729bd3d8eb5b23a21f54c
+d = 1f532d01af885cb4ad5c329ca5d421c5c021883bd5404c798d617679bb8b094cbb7e15c832fb436325c5302313ce5e496f9513455e7021ffad75777a19b226acfa1
+Qx = 0c0bd76b0027b85bdd879052220da1494d503f6a4bb972105a48ae98e7dda8c2d9fd9336f5646385b961ef68e8464e3a95b00f96614b1a408ceaa2c87b077b6a8fb
+Qy = 17eb7eb5c78db7819af92e8537d110d9f05a5e24f954f4dde21c224d4040f059ec99e051702f390413d2708d18f84d82998c61847475250fb844b20082cbe651a6b
+k = 14e66853e0f7cd3300ebcae06048532e19cbb95bee140edc1c867ce7310637651445b6dfeb1d99d2e32f2ffb787ebe3fe35032277f185d3dad84f95806924550abe
+R = 0c5b3a57161098e2e8e16e0a5ae8ecf4a14df14927eea18ed4925d11dc429dda145159323ba970174b194b9b4608a8fa2373b7a825c5e8bd80574e49698285c2c82
+S = 1a0c038a51796158b42eb5b0dac37aff9ab93b903a47e06ebbdd15946e4bcc9a3b3875b18cf6294c33fc6c3693cef04ed1a43d08951e664c760e2cf3fb4e47490d2
+
+Msg = bae2a8897c742fd99fbf813351cd009d3f2e18d825ca22e115276484bce8f82f8c7c0c21dd2af208404d8ef45bb5a6c41693912b630897d5246801bf0775aa9bbac8be98cb861d172c3563dc59e78a58ed13c66dea496471b3ad0eeae8995293e4ab97373edc1837ffc95ff1cc0c1e90e64ea8680b2ca5f1e09bf86b99b343b6
+d = 11abf508bca68a85a54bc0659e77efad3c86112c9db04db2883e76144aa446918bb4bb0784b0b6a0e9aa47399fe3de5aaecfd8894a0d130bb0c366c40d9d5050745
+Qx = 05c0ea363a3a12633ea39d564587ebdd3a22a175ef32b9ebfc7311304b19cb3a62b5adc36f6afb6a6f7fabbf810ee89fdb72854fefd613e7798e9b9ff5938ea54c6
+Qy = 0bd06a85e47b885c08124b55a3fcc07ca61647cda6efbfdbd21b24d1ea7a4c7300d46cd798e76063aa979adef6f0698b15e5b7ae8a2ab39ab4f50b2d20614db6317
+k = 19cadb8c7eb10565aa4567e0709873918720f0e4b42b4817afb0b0547c70cd1100229deae97a276b9c98ea58b01d4839fee86336d749d123b03e8b1a31166acc110
+R = 0667448a8bbef1c810d40646977dc22f3dfb52a4d80928ded5e976e199cbed02fbd5a08546756ece14548d721a6eb380d0e1a71ad0660dbcac6163c776eedd3e249
+S = 0ae7f0a238daaddb7fb4a1707fe5132daf653f8e19f732347134c96f1dd798f867c479a4a4609a568a15b61afed70790adbde13ac5f68c468d0230852c1a2c22581
+
+Msg = d57a26a9593e72bfc87322524639bcaae5f2252d18b99cdaa03b14445b0b8a4dd53928f66a2e4f202fb25b19cad0eb2f1bfda2ab9b0eb668cdcd0fe72f5d9ef2e45e0218590f7ab9d2c9342202610c698bc786cce108a7d4a6730a13e9ea1b470e781f1237d3f84f44abde808516975546bd89075ef9a9732bfd7ee33b6f4399
+d = 18dbf520d58177e4b7a0627674d220137983f486dd2fd3639f19751804e80df0655db6afd829cdf75238de525e1a7a9f048049b593dd64b4b96cc013f970c05ea1f
+Qx = 18b872690c37995be324ddb5c2bd5462841bb062f8e63da248a853de79c3d6bb9a2eb1e6933afda0998ca43491cc807b08ace2d5336a43d0ab50563a2d3d98755f0
+Qy = 002ff31221aa32aa6546f35e8fe5b9361f938362a5e89e77ae130ba8bce3729e912dfac35a2fd21efe84b45b8be2a340850e4b574e1885b35c2afbe196b57c6cf4c
+k = 098faeb73054639cb2e4442cd68e7b3a13f4b3f397a7b26f303afa40789f8ddd3d918f1ce4f0be53c8cb69c380744e2297d7fc01e2b3daef4ce64dd3a2644234753
+R = 09c0e7649f814f70a8416cb78bc4601472a363fe97f5c587305778169677860dd97f87b5ab07c3a953bc4615fc34634509d6a25621bdded33ed42446d059509c190
+S = 120b90e1cfb8a1b5e530df7b17d1128bc051ca4f1a65dd9c9d9d3c59d2f00c7c1e994c52b8671d40294b4d574d2c04475d5bebeacd3a0d3870a54dc7a4805614f40
+
+Msg = 8fdcf5084b12cfc043dd3416b46274e021bbed95d341d3c500c102a5609d3a34de29f8fa9f0adb611a1f47a97ad981f8129d718fc0d6c709eab1a3490db8d550f34eb905b9e00663543afc5bc155e368e0bc919a8b8c9fa42093603537a5614927efa6be819ed42ececbf1a80a61e6e0a7f9b5bc43b9238e62d5df0571fea152
+d = 002764f5696aa813cd55d30948585f86288ae05aeb264ca157cd09e1d09a10515a849b0791b755ccc656a34707be9e52f5762d290a7d2bcd6de52c600ff862eaf4e
+Qx = 127279c88719dc614db387f102e55104ea1c704ac7f57f3bca936f728439b76556730dd7cde2ac1ad0a4c2c2f036ab6f00cf34cb87ea36113571f300713044106d2
+Qy = 134a0786c31f5f2291b83c50fb579ae4c620b95e5a8bdc0c7e1ee6b996c89d764f1b20403e7faa203f397425ada297045dd8ba0e4b155d4900da249e934faab7991
+k = 08bffb0778cbb06466cecc114b9e89ca243a2b2b5e2597db920bc73a8bbcbe3f57144ad33409ef7faaab430e13f4c42d304d11347360c84972ca20b1539cce3a288
+R = 1f8f504e64a502e51e7c129517931c3b71f0d8a63b19cfe01ff7c951c6525249608b3ef5d00061d77eb6b3d69581adeaa3732c773bbb9b919c3e7c71fdc09f44d06
+S = 058044fc64b340604ffd02a5b2918d76fd6fb59ea895feab7aa218e6f1e8c8f226eb9ee345ef8140183a69272582005077b008006aab11597e808d7ff1e8382c924
+
+Msg = 00669f433934992257bed55861df679804107d7fa491672574a7624949c60049b0533383c88d6896c8de860704c3e6a6aefce83efa57c4d57e9ab253da5d15e1f53ab6dce218b592772ab0bc01fee8e63368e85c0639301456fe2d44cd5396a7f2b22761cd03b80eba7883eede8249a2f5db2183bf00550c5c002f45a5e4fb31
+d = 1b0c9acd3eeb618b4b0de4db402206f0f29adc69d7ad324b6db6601b351f723ac8fe949eeacd34228649bf0126276e5aceb0137d00c30dd858aef2d6b6449de2e89
+Qx = 1811c8884486aaa083ddee1c51cb6e861cb830bd5eaa929f72efadbbd1286566ae7e7ba7fde7e02529900d35ee64591652d28798bfc1bed0d192602a9cf5a7d22e3
+Qy = 06d7fc9dd494816cfd29613d4689af67f7d0a2e6fbad5d4d6e0130189172a1ab601c5ca71deaa8bfcb5a190d49da191672ff6fc048e146cb902acec5eae6d87e60a
+k = 1fdc4f108070af3c66c9ba7b6c1f2603a19ceb4760399df81228cfc7eafde1082b5a0716a3ff82fbe84726f14dd0db3376ca184a78c3c60679bab6cd45f77f9b9ce
+R = 1ec310339ff056faeb341c4499c43782078b04be1725ae9a6cdcb6011c46d1a4eb3d75c358225e4ec142fd1cd344186f5eb597f7ba559ddfa954824365d5b6edaec
+S = 005b679a33fdb7e04834f071cd0ac514c04add9f2614ab9bbd9b407b1420fed3f3e02a108e7e279899e43dcf64ae4083c289a87cd7d2103bdc036a95d36800ac7c6
+
+Msg = 4be81dcfab39a64d6f00c0d7fff94dabdf3473dc49f0e12900df328d6584b854fbaebaf3194c433e9e21743342e2dd056b445c8aa7d30a38504b366a8fa889dc8ecec35b3130070787e7bf0f22fab5bea54a07d3a75368605397ba74dbf2923ef20c37a0d9c64caebcc93157456b57b98d4becb13fecb7cc7f3740a6057af287
+d = 181e1037bbec7ca2f271343e5f6e9125162c8a8a46ae8baa7ca7296602ae9d56c994b3b94d359f2b3b3a01deb7a123f07d9e0c2e729d37cc5abdec0f5281931308a
+Qx = 0cfa5a8a3f15eb8c419095673f1d0bd63b396ff9813c18dfe5aa31f40b50b82481f9ed2edd47ae5ea6a48ea01f7e0ad0000edf7b66f8909ee94f141d5a07efe315c
+Qy = 18af728f7318b96d57f19c1104415c8d5989565465e429bc30cf65ced12a1c5856ac86fca02388bc151cf89959a4f048597a9e728f3034aa39259b59870946187bf
+k = 09078beaba465ba7a8b3624e644ac1e97c654533a58ac755e90bd606e2214f11a48cb51f9007865a0f569d967ea0370801421846a89f3d09eb0a481289270919f14
+R = 19cf91a38cc20b9269e7467857b1fc7eabb8cea915a3135f727d471e5bfcfb66d321fabe283a2cf38d4c5a6ecb6e8cbee1030474373bb87fcdfcc95cf857a8d25d0
+S = 1cf9acd9449c57589c950f287842f9e2487c5610955b2b5035f6aacfd2402f511998a1a942b39c307fc2bcab2c8d0dae94b5547ddccfb1012ca985b3edf42bbba8b
+
+[P-521,SHA-512]
+
+Msg = 9ecd500c60e701404922e58ab20cc002651fdee7cbc9336adda33e4c1088fab1964ecb7904dc6856865d6c8e15041ccf2d5ac302e99d346ff2f686531d25521678d4fd3f76bbf2c893d246cb4d7693792fe18172108146853103a51f824acc621cb7311d2463c3361ea707254f2b052bc22cb8012873dcbb95bf1a5cc53ab89f
+d = 0f749d32704bc533ca82cef0acf103d8f4fba67f08d2678e515ed7db886267ffaf02fab0080dca2359b72f574ccc29a0f218c8655c0cccf9fee6c5e567aa14cb926
+Qx = 061387fd6b95914e885f912edfbb5fb274655027f216c4091ca83e19336740fd81aedfe047f51b42bdf68161121013e0d55b117a14e4303f926c8debb77a7fdaad1
+Qy = 0e7d0c75c38626e895ca21526b9f9fdf84dcecb93f2b233390550d2b1463b7ee3f58df7346435ff0434199583c97c665a97f12f706f2357da4b40288def888e59e6
+k = 03af5ab6caa29a6de86a5bab9aa83c3b16a17ffcd52b5c60c769be3053cdddeac60812d12fecf46cfe1f3db9ac9dcf881fcec3f0aa733d4ecbb83c7593e864c6df1
+R = 04de826ea704ad10bc0f7538af8a3843f284f55c8b946af9235af5af74f2b76e099e4bc72fd79d28a380f8d4b4c919ac290d248c37983ba05aea42e2dd79fdd33e8
+S = 087488c859a96fea266ea13bf6d114c429b163be97a57559086edb64aed4a18594b46fb9efc7fd25d8b2de8f09ca0587f54bd287299f47b2ff124aac566e8ee3b43
+
+Msg = b3c63e5f5a21c4bfe3dbc644354d9a949186d6a9e1dd873828782aa6a0f1df2f64114a430b1c13fe8a2e09099e1ed05ef70de698161039ded73bcb50b312673bb073f8a792ac140a78a8b7f3586dffb1fc8be4f54516d57418ccc9945025ce3acf1eb84f69ceee5e9bd10c18c251dbc481562cd3aae54b54ab618cb1eeda33cf
+d = 1a4d2623a7d59c55f408331ba8d1523b94d6bf8ac83375ceb57a2b395a5bcf977cfc16234d4a97d6f6ee25a99aa5bff15ff535891bcb7ae849a583e01ac49e0e9b6
+Qx = 04d5c8afee038984d2ea96681ec0dccb6b52dfa4ee2e2a77a23c8cf43ef19905a34d6f5d8c5cf0981ed804d89d175b17d1a63522ceb1e785c0f5a1d2f3d15e51352
+Qy = 014368b8e746807b2b68f3615cd78d761a464ddd7918fc8df51d225962fdf1e3dc243e265100ff0ec133359e332e44dd49afd8e5f38fe86133573432d33c02fa0a3
+k = 0bc2c0f37155859303de6fa539a39714e195c37c6ea826e224c8218584ae09cd0d1cc14d94d93f2d83c96e4ef68517fdb3f383da5404e5a426bfc5d424e253c181b
+R = 1a3c4a6386c4fb614fba2cb9e74201e1aaa0001aa931a2a939c92e04b8344535a20f53c6e3c69c75c2e5d2fe3549ed27e6713cb0f4a9a94f6189eb33bff7d453fce
+S = 16a997f81aa0bea2e1469c8c1dab7df02a8b2086ba482c43af04f2174831f2b1761658795adfbdd44190a9b06fe10e578987369f3a2eced147cff89d8c2818f7471
+
+Msg = 6e0f96d56505ffd2d005d5677dbf926345f0ff0a5da456bbcbcfdc2d33c8d878b0bc8511401c73168d161c23a88b04d7a9629a7a6fbcff241071b0d212248fcc2c94fa5c086909adb8f4b9772b4293b4acf5215ea2fc72f8cec57b5a13792d7859b6d40348fc3ba3f5e7062a19075a9edb713ddcd391aefc90f46bbd81e2557b
+d = 14787f95fb1057a2f3867b8407e54abb91740c097dac5024be92d5d65666bb16e4879f3d3904d6eab269cf5e7b632ab3c5f342108d1d4230c30165fba3a1bf1c66f
+Qx = 0c2d540a7557f4530de35bbd94da8a6defbff783f54a65292f8f76341c996cea38795805a1b97174a9147a8644282e0d7040a6f83423ef2a0453248156393a1782e
+Qy = 119f746c5df8cec24e4849ac1870d0d8594c799d2ceb6c3bdf891dfbd2242e7ea24d6aec3166214734acc4cbf4da8f71e2429c5c187b2b3a048527c861f58a9b97f
+k = 186cd803e6e0c9925022e41cb68671adba3ead5548c2b1cd09348ab19612b7af3820fd14da5fe1d7b550ed1a3c8d2f30592cd7745a3c09ee7b5dcfa9ed31bdd0f1f
+R = 10ed3ab6d07a15dc3376494501c27ce5f78c8a2b30cc809d3f9c3bf1aef437e590ef66abae4e49065ead1af5f752ec145acfa98329f17bca9991a199579c41f9229
+S = 08c3457fe1f93d635bb52df9218bf3b49a7a345b8a8a988ac0a254340546752cddf02e6ce47eee58ea398fdc9130e55a4c09f5ae548c715f5bcd539f07a34034d78
+
+Msg = 3f12ab17af3c3680aad22196337cedb0a9dba22387a7c555b46e84176a6f8418004552386ada4deec59fdabb0d25e1c6668a96f100b352f8dabd24b2262bd2a3d0f825602d54150bdc4bcbd5b8e0ca52bc8d2c70ff2af9b03e20730d6bd9ec1d091a3e5c877259bcff4fd2c17a12bfc4b08117ec39fe4762be128d0883a37e9d
+d = 15807c101099c8d1d3f24b212af2c0ce525432d7779262eed0709275de9a1d8a8eeeadf2f909cf08b4720815bc1205a23ad1f825618cb78bde747acad8049ca9742
+Qx = 160d7ea2e128ab3fabd1a3ad5455cb45e2f977c2354a1345d4ae0c7ce4e492fb9ff958eddc2aa61735e5c1971fa6c99beda0f424a20c3ce969380aaa52ef5f5daa8
+Qy = 14e4c83f90d196945fb4fe1e41913488aa53e24c1d2142d35a1eed69fed784c0ef44d71bc21afe0a0065b3b87069217a5abab4355cf8f4ceae5657cd4b9c8008f1f
+k = 096731f8c52e72ffcc095dd2ee4eec3da13c628f570dba169b4a7460ab471149abdede0b63e4f96faf57eab809c7d2f203fd5ab406c7bd79869b7fae9c62f97c794
+R = 1e2bf98d1186d7bd3509f517c220de51c9200981e9b344b9fb0d36f34d969026c80311e7e73bb13789a99e0d59e82ebe0e9595d9747204c5f5550c30d934aa30c05
+S = 12fed45cc874dc3ed3a11dd70f7d5c61451fbea497dd63e226e10364e0718d3722c27c7b4e5027051d54b8f2a57fc58bc070a55b1a5877b0f388d768837ef2e9cec
+
+Msg = a1eed24b3b7c33296c2491d6ee092ec6124f85cf566bb5bc35bffb5c734e34547242e57593e962fb76aee9e800eed2d702cc301499060b76406b347f3d1c86456978950737703c8159001e6778f69c734a56e5ce5938bd0e0de0877d55adeee48b0d8dfa4ac65fd2d3ce3e12878bac5c7014f9284d161b2a3e7d5c88569a45f6
+d = 18692def0b516edcdd362f42669999cf27a65482f9358fcab312c6869e22ac469b82ca9036fe123935b8b9ed064acb347227a6e377fb156ec833dab9f170c2ac697
+Qx = 1ceee0be3293d8c0fc3e38a78df55e85e6b4bbce0b9995251f0ac55234140f82ae0a434b2bb41dc0aa5ecf950d4628f82c7f4f67651b804d55d844a02c1da6606f7
+Qy = 1f775eb6b3c5e43fc754052d1f7fc5b99137afc15d231a0199a702fc065c917e628a54e038cbfebe05c90988b65183b368a2061e5b5c1b025bbf2b748fae00ba297
+k = 161cf5d37953e09e12dc0091dc35d5fb3754c5c874e474d2b4a4f1a90b870dff6d99fb156498516e25b9a6a0763170702bb8507fdba4a6131c7258f6ffc3add81fd
+R = 14dfa43046302b81fd9a34a454dea25ccb594ace8df4f9d98556ca5076bcd44b2a9775dfaca50282b2c8988868e5a31d9eb08e794016996942088d43ad3379eb9a1
+S = 120be63bd97691f6258b5e78817f2dd6bf5a7bf79d01b8b1c3382860c4b00f89894c72f93a69f3119cb74c90b03e9ede27bd298b357b9616a7282d176f3899aaa24
+
+Msg = 9aace26837695e6596007a54e4bccdd5ffb16dc6844140e2eeeb584b15acb2bbffd203c74440b6ee8db676fd200b4186a8c3e957c19e74d4d865ada83f80655323dfa3570907ed3ce853b6e8cc375ed2d758a2f5ad265dd3b47650517a49b3d02df9e0c60c21576378c2b3a08481eec129b2a75608e13e6420127a3a63c8a3f1
+d = 0a63f9cdefbccdd0d5c9630b309027fa139c31e39ca26686d76c22d4093a2a5e5ec4e2308ce43eb8e563187b5bd811cc6b626eace4063047ac0420c3fdcff5bdc04
+Qx = 14cab9759d4487987b8a00afd16d7199585b730fb0bfe63796272dde9135e7cb9e27cec51207c876d9214214b8c76f82e7363f5086902a577e1c50b4fbf35ce9966
+Qy = 1a83f0caa01ca2166e1206292342f47f358009e8b891d3cb817aec290e0cf2f47e7fc637e39dca03949391839684f76b94d34e5abc7bb750cb44486cce525eb0093
+k = 01e51fd877dbbcd2ab138fd215d508879298d10c7fcbdcc918802407088eb6ca0f18976a13f2c0a57867b0298512fc85515b209c4435e9ef30ab01ba649838bc7a0
+R = 11a1323f6132d85482d9b0f73be838d8f9e78647934f2570fededca7c234cc46aa1b97da5ac1b27b714f7a171dc4209cbb0d90e4f793c4c192dc039c31310d6d99b
+S = 0386a5a0fc55d36ca7231a9537fee6b9e51c2255363d9c9e7cb7185669b302660e23133eb21eb56d305d36e69a79f5b6fa25b46ec61b7f699e1e9e927fb0bceca06
+
+Msg = ac2175940545d4fbab6e2e651c6830aba562e0c11c919e797c43eff9f187a68a9e5a128e3e2a330b955a3f4577d3f826529ad1b03d7b60f7ad678f005053b41dc0f8d267f3685c6abe1a0e9a733c44b2f3ca48b90806f935141c842e3a6c06a58f5343d75e3585971a734f4ae1074ce5b54f74bd9342f4bbca738d260393f43e
+d = 024f7d67dfc0d43a26cc7c19cb511d30a097a1e27e5efe29e9e76e43849af170fd9ad57d5b22b1c8840b59ebf562371871e12d2c1baefc1abaedc872ed5d2666ad6
+Qx = 09da1536154b46e3169265ccba2b4da9b4b06a7462a067c6909f6c0dd8e19a7bc2ac1a47763ec4be06c1bec57d28c55ee936cb19588cc1398fe4ea3bd07e6676b7f
+Qy = 14150cdf25da0925926422e1fd4dcfcffb05bdf8682c54d67a9bd438d21de5af43a15d979b320a847683b6d12ac1383a7183095e9da491c3b4a7c28874625e70f87
+k = 1c1308f31716d85294b3b5f1dc87d616093b7654907f55289499b419f38ceeb906d2c9fe4cc3d80c5a38c53f9739311b0b198111fede72ebde3b0d2bc4c2ef090d2
+R = 00dbf787ce07c453c6c6a67b0bf6850c8d6ca693a3e9818d7453487844c9048a7a2e48ff982b64eb9712461b26b5127c4dc57f9a6ad1e15d8cd56d4fd6da7186429
+S = 0c6f1c7774caf198fc189beb7e21ca92ceccc3f9875f0e2d07dc1d15bcc8f210b6dd376bf65bb6a454bf563d7f563c1041d62d6078828a57538b25ba54723170665
+
+Msg = 6266f09710e2434cb3da3b15396556765db2ddcd221dce257eab7399c7c490135925112932716af1434053b8b9fe340563e57a0b9776f9ac92cbb5fba18b05c0a2fafbed7240b3f93cd1780c980ff5fe92610e36c0177cabe82367c84cee9020cf26c1d74ae3eb9b9b512cb8b3cb3d81b17cf20dc76591b2b394ef1c62ac12ee
+d = 0349471460c205d836aa37dcd6c7322809e4e8ef81501e5da87284b267d843897746b33016f50a7b702964910361ed51d0afd9d8559a47f0b7c25b2bc952ce8ed9e
+Qx = 00bbd4e8a016b0c254e754f68f0f4ed081320d529ecdc7899cfb5a67dd04bc85b3aa6891a3ed2c9861ae76c3847d81780c23ad84153ea2042d7fd5d517a26ff3ce4
+Qy = 0645953afc3c1b3b74fdf503e7d3f982d7ee17611d60f8eb42a4bddbec2b67db1f09b54440c30b44e8071d404658285cb571462001218fc8c5e5b98b9fae28272e6
+k = 00eb2bd8bb56b9d2e97c51247baf734cc655c39e0bfda35375f0ac2fe82fad699bf1989577e24afb33c3868f91111e24fefe7dec802f3323ac013bec6c048fe5568
+R = 14bf63bdbc014aa352544bd1e83ede484807ed760619fa6bc38c4f8640840195e1f2f149b29903ca4b6934404fb1f7de5e39b1ea04dba42819c75dbef6a93ebe269
+S = 05d1bcf2295240ce4415042306abd494b4bda7cf36f2ee2931518d2454faa01c606be120b057062f2f3a174cb09c14f57ab6ef41cb3802140da22074d0e46f908d4
+
+Msg = 3de9e617a6868dca1a1432d503f923535da3f9b34426b2a4822174399c73b1c1ee67311410a58c17202ac767844b2024d8aa21a205707d93865693ac25a24fc87034fa3a7a7e27c3344cb03b87602c15180a5fe6a9dd90cd11af4a0f150207bf2d83f55b12c088adae99aa8cfa659311b3a25beb99056643760d6a282126b9b2
+d = 07788d34758b20efc330c67483be3999d1d1a16fd0da81ed28895ebb35ee21093d37ea1ac808946c275c44454a216195eb3eb3aea1b53a329eca4eb82dd48c784f5
+Qx = 0157d80bd426f6c3cee903c24b73faa02e758607c3e102d6e643b7269c299684fdaba1acddb83ee686a60acca53cddb2fe976149205c8b8ab6ad1458bc00993cc43
+Qy = 16e33cbed05721b284dacc8c8fbe2d118c347fc2e2670e691d5d53daf6ef2dfec464a5fbf46f8efce81ac226915e11d43c11c8229fca2327815e1f8da5fe95021fc
+k = 0a73477264a9cc69d359464abb1ac098a18c0fb3ea35e4f2e6e1b060dab05bef1255d9f9c9b9fbb89712e5afe13745ae6fd5917a9aedb0f2860d03a0d8f113ea10c
+R = 07e315d8d958b8ce27eaf4f3782294341d2a46fb1457a60eb9fe93a9ae86f3764716c4f5f124bd6b114781ed59c3f24e18aa35c903211b2f2039d85862932987d68
+S = 1bcc1d211ebc120a97d465b603a1bb1e470109e0a55d2f1b5c597803931bd6d7718f010d7d289b31533e9fcef3d141974e5955bc7f0ee342b9cad05e29a3dded30e
+
+Msg = aa48851af7ef17abe233163b7185130f4646203c205e22bcc2a5a3697bcab998c73a9ffe1d3ea0b7978ce7df937a72586eb5ca60b0d939a7d1c115c820171c89c8116b7e2c7b98cf0f14e4c4df3cb2f319ad3ab0ea25ff14526ddc037469f000bf82100acd4cdf94feb4eba4ea1726f0569336604a473aee67d71afebb569209
+d = 1f98696772221e6cccd5569ed8aed3c435ee86a04689c7a64d20c30f6fe1c59cc10c6d2910261d30c3b96117a669e19cfe5b696b68feeacf61f6a3dea55e6e5837a
+Qx = 07002872c200e16d57e8e53f7bce6e9a7832c387f6f9c29c6b75526262c57bc2b56d63e9558c5761c1d62708357f586d3aab41c6a7ca3bf6c32d9c3ca40f9a2796a
+Qy = 1fe3e52472ef224fb38d5a0a14875b52c2f50b82b99eea98d826c77e6a9ccf798de5ffa92a0d65965f740c702a3027be66b9c844f1b2e96c134eb3fdf3edddcf11c
+k = 1a277cf0414c6adb621d1cc0311ec908401ce040c6687ed45a0cdf2910c42c9f1954a4572d8e659733d5e26cbd35e3260be40017b2f5d38ec42315f5c0b056c596d
+R = 0d732ba8b3e9c9e0a495249e152e5bee69d94e9ff012d001b140d4b5d082aa9df77e10b65f115a594a50114722db42fa5fbe457c5bd05e7ac7ee510aa68fe7b1e7f
+S = 134ac5e1ee339727df80c35ff5b2891596dd14d6cfd137bafd50ab98e2c1ab4008a0bd03552618d217912a9ec502a902f2353e757c3b5776309f7f2cfebf913e9cd
+
+Msg = b0d5d52259af364eb2d1a5027e5f7d0afe4b999cc5dd2268cfe76f51d2f17b541bdd7867e23a1bb897705153d9432a24012108979c6a2c9e2567c9531d012f9e4be764419491a52eae2e127430b0ab58cb8e216515a821b3db206447c235bf44ee304201b483b2a88844abaa18bca0147dfff7e502397dd62e15524f67eb2df2
+d = 13c3852a6bc8825b45fd7da1754078913d77f4e586216a6eb08b6f03adce7464f5dbc2bea0eb7b12d103870ef045f53d67e3600d7eba07aac5db03f71b64db1cceb
+Qx = 0c97a4ebcbbe701c9f7be127e87079edf479b76d3c14bfbee693e1638e5bff8d4705ac0c14597529dbe13356ca85eb03a418edfe144ce6cbf3533016d4efc29dbd4
+Qy = 11c75b7a8894ef64109ac2dea972e7fd5f79b75dab1bf9441a5b8b86f1dc1324426fa6cf4e7b973b44e3d0576c52e5c9edf8ce2fc18cb3c28742d44419f044667f8
+k = 1e25b86db041f21c2503d547e2b1b655f0b99d5b6c0e1cf2bdbd8a8c6a053f5d79d78c55b4ef75bff764a74edc920b35536e3c470b6f6b8fd53898f3bbc467539ef
+R = 1dce45ea592b34d016497882c48dc0c7afb1c8e0f81a051800d7ab8da9d237efd892207bc9401f1d30650f66af8d5349fc5b19727756270722d5a8adb0a49b72d0a
+S = 0b79ffcdc33e028b1ab894cb751ec792a69e3011b201a76f3b878655bc31efd1c0bf3b98aea2b14f262c19d142e008b98e890ebbf464d3b025764dd2f73c4251b1a
+
+Msg = 9599788344976779383a7a0812a096943a1f771ee484d586af1a06207478e4c0be9c200d42460fe837e24b266c8852d80d3c53cc52ffb1913fc3261145fc6da575611efd16c026059a2e64f802517ffd1b6b34de10ad2909c65c2155e8d939b8115400c1d793d23955b15f5d1c13c962ff92b4a815cee0e10f8e14e1f6e6cd38
+d = 1654eaa1f6eec7159ee2d36fb24d15d6d33a128f36c52e2437f7d1b5a44ea4fa965c0a26d0066f92c8b82bd136491e929686c8bde61b7c704daab54ed1e1bdf6b77
+Qx = 1f269692c47a55242bb08731ff920f4915bfcecf4d4431a8b487c90d08565272c52ca90c47397f7604bc643982e34d05178e979c2cff7ea1b9eaec18d69ca7382de
+Qy = 0750bdd866fba3e92c29599c002ac6f9e2bf39af8521b7b133f70510e9918a94d3c279edec97ab75ecda95e3dd7861af84c543371c055dc74eeeff7061726818327
+k = 1b7519becd00d750459d63a72f13318b6ac61b8c8e7077cf9415c9b4b924f35514c9c28a0fae43d06e31c670a873716156aa7bc744577d62476e038b116576a9e53
+R = 183bddb46c249e868ef231a1ebd85d0773bf8105a092ab7d884d677a1e9b7d6014d6358c09538a99d9dca8f36f163ac1827df420c3f9360cc66900a9737a7f756f3
+S = 0d05ee3e64bac4e56d9d8bd511c8a43941e953cba4e5d83c0553acb87091ff54f3aad4d69d9f15e520a2551cc14f2c86bb45513fef0295e381a7635486bd3917b50
+
+Msg = fdde51acfd04eb0ad892ce9d6c0f90eb91ce765cbe3ce9d3f2defe8f691324d26b968b8b90e77706b068585f2a3ee7bf3e910528f7403c5af745a6f9d7ba6c53abd885c3b1be583415b128f4d3f224daf8563476bd9aa61e9c8518c144335f8f879c03696bddbe3ac37a8fbede29861611feaa87e325e2f60278b4893ed57fb0
+d = 1cba5d561bf18656991eba9a1dde8bde547885ea1f0abe7f2837e569ca52f53df5e64e4a547c4f26458b5d9626ed6d702e5ab1dd585cf36a0c84f768fac946cfd4c
+Qx = 12857c2244fa04db3b73db4847927db63cce2fa6cb22724466d3e20bc950a9250a15eafd99f236a801e5271e8f90d9e8a97f37c12f7da65bce8a2c93bcd25526205
+Qy = 0f394e37c17d5b8e35b488fa05a607dbc74264965043a1fb60e92edc212296ae72d7d6fe2e3457e67be853664e1da64f57e44bd259076b3bb2b06a2c604fea1be9d
+k = 0e790238796fee7b5885dc0784c7041a4cc7ca4ba757d9f7906ad1fcbab5667e3734bc2309a48047442535ff89144b518f730ff55c0c67eeb4c880c2dfd2fb60d69
+R = 1d7ce382295a2a109064ea03f0ad8761dd60eefb9c207a20e3c5551e82ac6d2ee5922b3e9655a65ba6c359dcbf8fa843fbe87239a5c3e3eaecec0407d2fcdb687c2
+S = 161963a6237b8955a8a756d8df5dbd303140bb90143b1da5f07b32f9cb64733dc6316080924733f1e2c81ade9d0be71b5b95b55666026a035a93ab3004d0bc0b19f
+
+Msg = beb34c997f905c77451ac392f7957a0ab8b23325bd5c63ca31c109ac8f655a1e3094240cb8a99284f8091de2ab9a7db2504d16251980b86be89ec3a3f41162698bab51848880633e0b71a38f8896335853d8e836a2454ecab2acdcc052c8f659be1d703b13ae1b090334ac50ab0137ddb5e8b924c0e3d2e5789daaef2fdd4a1e
+d = 0972e7ff25adf8a032535e5b19463cfe306b90803bf27fabc6046ae0807d2312fbab85d1da61b80b2d5d48f4e5886f27fca050b84563aee1926ae6b2564cd756d63
+Qx = 1d7f1e9e610619daa9d2efa563610a371677fe8b58048fdc55a98a49970f6afa6649c516f9c72085ca3722aa595f45f2803402b01c832d28aac63d9941f1a25dfea
+Qy = 1571facce3fcfe733a8eef4e8305dfe99103a370f82b3f8d75085414f2592ad44969a2ef8196c8b9809f0eca2f7ddc71c47879e3f37a40b9fecf97992b97af29721
+k = 0517f6e4002479dc89e8cbb55b7c426d128776ca82cf81be8c1da9557178783f40e3d047db7e77867f1af030a51de470ee3128c22e9c2d642d71e4904ab5a76edfa
+R = 1c3262a3a3fb74fa5124b71a6c7f7b7e6d56738eabaf7666b372b299b0c99ee8a16be3df88dd955de093fc8c049f76ee83a4138cee41e5fe94755d27a52ee44032f
+S = 072fd88bb1684c4ca9531748dfce4c161037fcd6ae5c2803b7117fb60d3db5df7df380591aaf3073a3031306b76f062dcc547ded23f6690293c34a710e7e9a226c3
+
+Msg = 543c374af90c34f50ee195006d5f9d8dd986d09ad182fcbefa085567275eee1e742bfe0af3d058675adeb5b9f87f248b00a9fbd2aa779129123a5b983f2f26fc3caf2ea34277550c22fe8c814c739b46972d50232993cddd63a3c99e20f5c5067d9b57e2d5db94317a5a16b5c12b5c4cafbc79cbc2f9940f074bbc7d0dc71e90
+d = 1f0ec8da29295394f2f072672db014861be33bfd9f91349dad5566ff396bea055e53b1d61c8c4e5c9f6e129ed75a49f91cce1d5530ad4e78c2b793a63195eb9f0da
+Qx = 09ec1a3761fe3958073b9647f34202c5e8ca2428d056facc4f3fedc7077fa87f1d1eb30cc74f6e3ff3d3f82df2641cea1eb3ff1529e8a3866ae2055aacec0bf68c4
+Qy = 0bed0261b91f664c3ff53e337d8321cb988c3edc03b46754680097e5a8585245d80d0b7045c75a9c5be7f599d3b5eea08d828acb6294ae515a3df57a37f903ef62e
+k = 0ac3b6d61ebda99e23301fa198d686a13c0832af594b289c9a55669ce6d62011384769013748b68465527a597ed6858a06a99d50493562b3a7dbcee975ad34657d8
+R = 0cef3f4babe6f9875e5db28c27d6a197d607c3641a90f10c2cc2cb302ba658aa151dc76c507488b99f4b3c8bb404fb5c852f959273f412cbdd5e713c5e3f0e67f94
+S = 0097ed9e005416fc944e26bcc3661a09b35c128fcccdc2742739c8a301a338dd77d9d13571612a3b9524a6164b09fe73643bbc31447ee31ef44a490843e4e7db23f
+
+#  CAVS 21.4
+#  "SigGen" information for "xpn_test"
+#  P-224,SHA-512224 P-224,SHA-512256 P-256,SHA-512224 P-256,SHA-512256 P-384,SHA-512224 P-384,SHA-512256 P-521,SHA-512224 P-521,SHA-512256
+#  Generated on Tue Jan 14 16:20:46 2020
+
+
+
+[P-224,SHA-512224]
+
+Msg = dec6c226a325e24fc7153c059df1ce1b34da4758cf5a18329547cdd98aea9e77be6141b6c54203846681171397942e23aad44883c127c9d587dccf9322d6c34f63ed2e3f4091cef885b0ea7ac6dae26d98a40aaa014ab8fd2c989c29610a502d353230c6fe5a6c358a6b5c42110d1381671036d4760b0f31ec42dda631cd6e9a
+d = b31f3734625313a199dc1c06a8e2a4ab1e4ad0cf84ce7446da2566f0
+Qx = 09eff4d220a7186492df6025c191b59341f8a613ad6300147a4113dc
+Qy = 9bdab9710b244c43a54288e1a6db273c9998278501a11f915451d59c
+k = 6baabf8efadb9ca44902850152a76d8c3faa74d4020478f9c4a9ba37
+R = b3ccf21410c44f8ccb4b959a1f12e8323929513dc47efab93593d925
+S = af3f04d85dfff072f2322c1f867df830fcffbcbc469dc1d6513ced0e
+
+Msg = ce44fb7c3aaefa0f15a1d2b8ccad62265f99e7f900a82927dc1cf29f39f9c42dc10bcb9e1d2a1124c6bdf1fc187dce4da97c0554d8651fbea9054c55d00a0ddf0b0b3043b5c901ee99b5bf7504b24d7c1e1b2ad67908a3eeebcd476599c49cfc554d10b52a1232353490226db5d3467966803fc80b191c7e4a7dcd16bdaeda4c
+d = f92ee713c0d961847f7168fa8d369199d6c126559559714081eae5b3
+Qx = 345e917a16d36797617b70a7a2d25d23ed1fc77a2c8b9ca94d037b8b
+Qy = 05addfbda8b6d752a92d1c9e6c85c608b224946ea0f8f9ec4458e150
+k = 9d7770f2883298a8ae0ae07f57193d80a69df912a335c7744751ade1
+R = 0f5b91d838ad7d18a17417ede90962f841dbe3497499bdf2f1d7f7e0
+S = 5aea31bfcfaa07d8785dccdf32fb764afbf8657e5cf0b37dd93b9ef4
+
+Msg = c9c5080e3aed61cbeb659a83dd79db8aa9b3965a6ffe1bd9100b67da9df43de50f1f793b3866a015f974bb2db672667f07e42451b0cdf571d41a2bbe653d79e9df194d7d361e5f1d0cb58a0d28dedcf52417e9e16581648b513ef0ddbb1d33b2a2792cdd1c5ec76c8deeaf2e1c03647268168d1276608fb0ef3e5e4088da94c6
+d = d96c34aa9a5f6d1cf135632b527701aa80eb60aa76b814d54277e25a
+Qx = c31cd778599ab919662974948186db4a28dbc32611d4bf7130ee5612
+Qy = 77c3dc320f12e95268bc2062f4c708f9830f38bbd23c7e8ae17815fd
+k = 8755720e1420d250ada22a63de6db96e049940fead68485bc33c8210
+R = b8c06134622ab105bb523f01b93b362dde43136ed38de4b4d7df72ff
+S = 2770d2328b2c10e4ff56669b18c625ef5a3f9dbab4945487dcf52ef1
+
+Msg = 0aafef52b31f9d90621dcad66aba14dbf392724857a5bc25cc626e914405a9b791237afdcd835f7ef93007bbe4cc5a8d4e27b95f4e118799f16ce85f2485c87cd4a4209953e174b3fe3aa1cc1de3d5e00adddf1a96caa948a800028d27dca1551a58678e0ee0e516b8621e6fdca58eba6edb6be3f6792a193946458115b23c2b
+d = 0ea8e4e45c96e586af8b2f8e8802e48f293698b051a80192ad5ed11a
+Qx = e90b1033d44ff017ac99e145f2bed0d9c3ad23a4b2524e35a036c93c
+Qy = cf8a3e27af987a54b5607cc1d97b88d6137d1cb073586e3100dc88eb
+k = e74247352ff6992ef11345e0e1d8904b81b8854e35b20f159bc69f2a
+R = 2b5d5a64c8e862f4d0c7bbb2e7d6db69082fc43bca6d016b1dc3c330
+S = 0ec9b1b366864795ebcdc2208a8aa1d3a1e650f9d3abc3b11425f5f5
+
+Msg = 3ad3afd32819ec3407ba90f20f1d36ce4d2af80c485d3324e5188bba883e2fd07cfd5e3b95eb2b5313557defcad35991802064dd9729a350ec64862efe6325bc53a9c9b017bcaee6077c07548db243402cec8fb01f899c233d10a27e20c6a549867ff71bf7b4fe53a9d63709a0e27b451936816e29a3a505a2c3e793368c37df
+d = 837392202e98e9020faac1ac81f7735e3d2714dbe79bfab1f83155ac
+Qx = 96fa530717f6f59e9cf44122d736f8ed9cb643b0555d29471cbe7597
+Qy = c2038e451f4518873a3a639dec92296c17988e8b9a669c2b2cdd9b35
+k = be0f9b276c533129aca13ecc48ab683ea4468261d64194e7e1a54a3a
+R = 9a24aefff902b5347fdf57d2f50c2869901fc8b21fe7df9589e2beaf
+S = 9b53c596d87772b643114477a792a9856343c10c83b64eefccfc4038
+
+Msg = c471786af1f702b97f1e5b88c5732af244029b812cc90544226dcb21402c806d5d134eba8f7198f0ef8bdea09c91e19403d108ab5d2b03e478c5aeb8bb0038ad65aa84281575cf828fa7945fbd14ac3bf449ba46790bc672440028ca03aba805629ee35b8aeaf197e7db446e2fe2d30fa0d378fb895097170b8501ff2117189e
+d = 89b7ac3cc2a663f91d6a12c332de24fe2392a07a5e3a032b98ac304a
+Qx = a28fe57e80c887f48fe4fa8b330e6c42af893294c28092b98f11c1c3
+Qy = f264e621559bb0b95c265944302bf26bb1d3a892e73f3b39299dad83
+k = c5d16a4ea602f181d2f35091582d7399eb2447e423b8a7d137270537
+R = a1b22cb97d1803cab7ef842937265d265d06d052c2fd2fc2d52f7331
+S = 01fbeabb77fcc31282c94505c648c44f357320483a1d3f5b86d71f36
+
+Msg = 56fb51edf33e75fa9e0ce65aa2cb7e50cd6a86cbdcfccf2f34a6fe58d3bc28dd85279f915b0a0b5059a5bcf86f793eb5abac2e82acb04dec5a20d319d4ea060aaab30a1d4d77fbd6c37039de9f3a034c31344824fa29b91d623023a8aed0fc2d2c683c98b0ce6e14443706161c57f59ec8c97bbaadb03c4bb69f970b47b633cf
+d = 39b3fa8f08ddd2f00b584bd98b8ab69512dbae3cb5f738f5a852714b
+Qx = 791106c5d90c93a491d3015e26612bd32eb07727bbfced21d8c65073
+Qy = 7eba40fca8347ed340e3609169ff12a7b18b2c8c203959e98cc789a1
+k = 5e4062d6202736baa9e3ba4f0ce4a3e7974f2a7411b66e6e9237ea10
+R = 34d150d4e4a1d85e544b56666285b88e7da315937fc112b3ef1ccf27
+S = 977aa92beb61fee4b2566c886c63ea7e1b1efe01f9a4deecf938ef0d
+
+Msg = de9b5870af108686cfca44c8d3a05ce973f6fa77d5ea0db00fcef098e7db4a48dc2333896bc898a18b6ce06d7ae8cfb0bb41abab60d89eee85e05c6d1d1505d6f1ab4d22e585da6b7da8eefda1ef45af9d0041746c7e442d36815dc117432870221cef64a6b01589af67b59fd01d868e201b02f98346c7152b973dbc5ecb79bd
+d = 488e4bdc820993695636f9edd75c60a1a5a5fa1341487bdf608257da
+Qx = a5a9d31647759ee612a4f5bba2fe1dff4e7b0e50bee5ff820a2ef1e5
+Qy = 18463d7dbf9597f882b8ed13ed379b8cf57aa07369191447c0c45e73
+k = 0f781629a8474e8cacb3de93565d64c26b01a8d4b4bf6548d37188ff
+R = 3d8c43931e75b671046ef92fffacf00b3aa82896465c33b38af34d6e
+S = 4ba8c12098b2115eb37625e19c0d488664b7f9e48465277a43ebb0b4
+
+Msg = 45cdaf47b20ba39e575d26ed250443a223f5ea7f592ff092ec4b57688a55d07e08da7ef84a42fd956460a3e3fe4805affd61bdc060bb6bc567a2fa8bfb7325734aae3924b24d1c7de0548ecd39aaaf477827c1b099ee305bf7fdcf57b10265e751706832b0d3083c146170159cd14851de707eb7ce71463ee2845f3573ab98c1
+d = bdfc1a44afd4ad215dd3bec810235151741156a13c55a81dfbc7d27c
+Qx = eb56379b8403a2594779f0e692a215e7ebc92073fba28b9efb8cb447
+Qy = 199a70f85ce5ac251713f3a4e8db31b4f20a35c20e26b7e1db552f2f
+k = fdc0a5388f883cb8255cc4d2f966eda6711db36a06af307acd57f87a
+R = 7167909debe198485b9cd079bc942a4bddee74d9e801cab981bcefa7
+S = 292f60212b5814375bce48c4d7c94d6adc8277ee499bf9a4581e7045
+
+Msg = 1be72b9c005aa9d3829ad4d14a3f3117a2f901f07c806901b6cecf209c8b876aafc9af8fa5f15771b0fde6ee03e8b8f993630cf01aca1e29625690cfc0940eecde1632c6be68a56ffc458898540b12a6636d7a08b26817c7f078c65e7f0b8ccd33367ce956a7dbf6efdb8377439185459d7e12df4b429c01e99b3878e2d84734
+d = 077958669b85a420c44e8fc0df8a9e845ec9de3047bb9df9c089e105
+Qx = 8d12bf332e7d117aa17b4ddd990adb216c2751d9a8278264eb8c26a6
+Qy = f0db277cb4f9389769ca8b1140e9de3640287e828219dd7ef5f8d567
+k = 864e1e31e8196387d2cf29bd86155e75beb46e07d1f7cf468f73117f
+R = 37bd81fc3bdcccdc2ce59fbdd744a3c2bec6fbf3ee222b4ec070fb03
+S = e6a3372147122576cadf08ae06f3d966a931b3f07300fbe6861b2406
+
+[P-224,SHA-512256]
+
+Msg = 657196794b15e717027b4e4d59c9b27b056b1a98e84d1311934d53d409f09ba7c553e2bfff65af8e2c54c7dcc4450819474895f2828b33220fcef38b1b1612856ba61d76a12b58a3bc376145dff011e0530aa3d0cef21824f64cd9b021a09f5e5f5090c5baceabfdbc0b65b13233947530978d5a55eb89c050b14e6ca3f50bdb
+d = 2924f2f043f653f95beac4aedef8f167409f7c56ae28f3c58a855123
+Qx = ff1a7167ef90b91d7a19d53bfe818d30cbf3dfa64a9ce5e665eb7c5f
+Qy = f46570eb4a7475eb22e19c330c5a9bc3a0266884b317f610814952ae
+k = ca44f58a0c9be045177b9b3598f83c0289b787ae542669b5499ace2f
+R = b4e8b1df0564a6cfa188af5edc2287980ffb9ca4f8fc8fda9033e2e9
+S = 3453508bb369c4668f9e8fe26c407e6ba82312eed6badc459d4ef496
+
+Msg = e048f37abb2b343b31df12f15fa225e34307055fc4eb674ef2a9890b9092d176d097b1445d49cd999e0460d83a66dbbad706d09d28630f1f261b0fec9d5e8fd4eba17c2104971627ba5d4f1c3cf5732adcf50ec315800b35cc76197ed6e85361bbcf1fb9b9fd560e0c53a6666d35355dd93b87789329a2b76c22706942186444
+d = 65973abe18266d1e9f10ded9c12e18da255dd9faf62f479ac11672e9
+Qx = 1dfbcf46c1f30ad3b3e1c6821ca5997edae8af86b0ba4b8d10baa648
+Qy = 3cd5e4e758a48a928b8f114054818f37bc1ddacdd1ce49a49247d349
+k = b28a6d34659b49e9f8f6220d3c86651682ca6a6f874fec85b1681db4
+R = f49305ab29c79c9125867c2b6b52a935cc6e1326a6feae243d7db45c
+S = 147cd38cded030ee06872f0268b8f7fa799b75b901efd51d17f1de31
+
+Msg = 46e8a5b134668d14fa8523b8184f9820d387f63837974be75dca09e7eabbadd5d80e9f84795d5997b875cc4fa3c3ffa12609fa8c1955e2a97e3465040323592acf469f837a5d4ee25df30d5b0dd8c15522d269df3d90454849df3ee900218246b1fa6f56414cb21e7166b0855e7825634e4a0adba92ebdeb46345c41e89c7150
+d = a86ce94ac55c687377f5f46303e6005122b91543f21474ee7c060461
+Qx = 9dc59b49a38ac39db009ec0ea1e6fb2b6a1fbeeb5b7b8e6190239f83
+Qy = 92a622795855a95faa8b3c8d4bb640fb9f2afc34f595e6e4c497b473
+k = ca4a7cdbc4d41114df6c063a382190455d0fa5cd54b089e1c31aaca2
+R = 52548ba9bf71989edb26bfcfea522c8ec996a88dd4acd8c1169fcf89
+S = 49f8efd1fbdf103a5f9205bfa11e061c18a00d1dd16be4d38bc7f30f
+
+Msg = b04802ff7be386bab6291145d6cc5c04f9841384c95fd96ba4598daffb2ccb07f869b69f64c8f510c7bcfc8fd14b8d64f81d7e9f63d3bc06079a905110ff219a82053b0f20744eea8d75baa3b15c49635ec5fdbd33e20d99c1132a70edb706bf954317b57791992f4e7ad2e73da699e871a319460335d30b1bede2745bfd835e
+d = 0c4fd85c6ef6d25e8cce8e44510cd23e71ed703ec616b9b158bc6e41
+Qx = be0aeff766fe90f2cf310590c0f733cdea6f9eaf53097beede604962
+Qy = a3a1c4b037846e914bddbca705c7b4a9c684623d817dc8d459c21354
+k = eb84a4f7aa4d21509ceb63da4d525b0b2c7107ec97b85e15c8b3a65c
+R = 693fb03b4cca78481758112e8fec8a4ce09486ed4875b5376ffbbcfb
+S = f89d8de8f4e5b6dc4dcfc5afd2fc258a4d6b09806b7d5f829a260e4a
+
+Msg = 4b8a682a438607dbc872157cc7139317eff13e8d6f096be501c236e52722dbdfb44264ce8fff85a2b4f3c4d77ba4dc4c1dfa645374f7ac0402a2e8d835449073e9d706c02fbc7a434dac0bab06f12ea71bd654fb115cc7d3352ed557ded7317ff2339629ab23ad699b853120ee6451d0f06b56aecfa085f9a14f478ba84387ae
+d = 906ad952a965de9ccdf236c3626ffcf50d2d5cb612504a96039dcfc9
+Qx = 068e4f9666bfc76308754d6ef686c1d9a89f1e07083267e8984c903d
+Qy = ff2a72e673db44a54ca6aed517bd6695258a36b14e7be81476973ac9
+k = 53d51ef1e81d269b418605429b27ccb04e2535543d086189bb55066d
+R = 9f665034db0179d9d4e7ffe3f5220fd8e10b66ffd5e47668d8ccc41f
+S = 945faa66c412730b05ba9aa74a91284b780c15715b0545ae15cbee02
+
+Msg = 6e1ba9ef3e1aa06be228c35c4793f99545df86e2c65d443f2bff2f48eb6a27f17d4df27779f18197fa1274fd46eee0ffb19b4f8bbe9d085e88b89177600373ccb83e3d3b4065cbc34e85c8f483cf72a4aceb9de4e68ffb33064f9af137b7ae16e5979123da9e0859a72ac829465f39edfd7779d58558a4246c6c539cb8ad6236
+d = 53d551e8c8939c47f80c0c439054bcb8f8647f8d5b16e60e50a2de42
+Qx = 5e09c453381e94ccfd29978b0ec16b6b5c8b002d23de520d6ade7811
+Qy = 04c7c5d4828a622fde46c8b9e6b9eeddf8cc7b61fcd7d222a73c3d63
+k = 0b8b6b3898e2b0e739c1ea2308902dda84e19acb7e728ad139a3e3b9
+R = 04d28ff01bcfb2f0fe2f848f3f93e02c66b292195caa07c1dd4a6eb8
+S = 83bb0dc1c18d5738de274eed0aed82c41244128cc433541495894c6c
+
+Msg = 7666200508190d6a938cb3bc16d5a0db45e9c5872cb2351914612a70aa06492f5e5d27260aeb0b0dd44af67855c2e007fb1945ddababe054abbdb7efc00e579193af61ec5915453bb36d4e34d32fdf38e1f6fcce9d8f0b4f454fdce3b9aae8abdd02d6403fbd445dfa9ac3d8da4523d7c029f24048853f71aac2a332de0483e7
+d = 478e35dcc828dd49cbf4aacd41bc114da6a01d27b54712cca69c272f
+Qx = 67d8459ea6d3992ffe9faa1a3fb76a1ca5e7cb65ed692a0bfeee6d03
+Qy = e1bc15d013b35ff0eafb15fdb818779991586a99cbd1f56d3759d55b
+k = 1509a8331c97138ac6d5acc0e2b9e9d568d8d38c01158cf700022b80
+R = a542f134328bfc6e87299f435de819c402618df3a46777a4c000c916
+S = abfb8c39a194efcaf78387f5aa288defdfb6eda8379c54525eb64215
+
+Msg = 5695d02a2f56f0e6e4b97d5d65c4f6614e6c0e2904595c3f01ea549a6c797606ede0c5cdbf3b7b9007f0fb7664ed0789c731335c858e99f1aaadcfdb915216a0b1e1d461ba2245bde1416df277195145c1b166a504074a8bdf0db224ddf2a4b24ba2e6304790b6341ab3bb1ac8ce3c5fe5f5904ba94dd5d34713e5bd7be08605
+d = 8af51be7727e3daafcc03dbf3a95f8de1cbc2d91ac303075c0956016
+Qx = 1c476980e7c06a650d4ee1e41426a0a40b44b14ee25cf8c42b6dcd99
+Qy = 4fcd261995d5cdeee1051fd72abf8a999213c3b6d2fdd316c156df00
+k = 8c16f8c96a6b35d5b21198427b2e0fa9b1fc2a4c8f650a97683e0f65
+R = d7fba364229f30069e04cbca98664ec50a7519f685c2421cce278173
+S = 3a38e571ecdd4c446590b30f21ce3d1ff55581c4da399b22079ca26a
+
+Msg = 1154660e316618807fcf21d95dbd0b46d45b5ffdd13c76c68efd8cba4e26164b4d525585f7902c9458082f85d4e2fc511863ce1750594fa99abaae4abb88f2b612f78e63cad23507531bef5a12f26d1d57b7995b907372efbd74174624382166468d362f11f5dce1574f8adf7fb405b37ba0ea51fa5286a0de75ee36f0ff4c63
+d = 6769dcffef3c76d2bc33dccf69a524ebffb5d4c8eefc9aa412667a61
+Qx = 5cd78f03b48839d289148476d837ffaefd5a928ccd49256cf8b0b9e3
+Qy = 767f06de8953e2dc19f2e3813f1c5f9c0411f00ff2f70b791cf16de6
+k = 20374865e9a73e3cd6dcc55a9996f1a5a84433466d307c0439a17690
+R = eb0780d279acaae3e86254a16a176bfee7b30adcf57942d739cc0451
+S = 5f315c9251c71e675e25c3491f47b1d063a87fc99500913981113000
+
+Msg = 6d3003a426638ddc3c20973be41919acec3377d5f1e7529bd2e8a4e864060cab68526621ba839f54cb98c7e150bf68fd3c7617baecf04887a2ba67f6359e24c307c80e11362763f61716263ae03c735ca4b010d6856144a225b6ecfd5d71cb6b32d922fb041880cc09e2dcd0fa57e1d00c2b89b12204edf541235c854447aaad
+d = 568ad644b27089e6d24cb1d584761bac5429f6009779def94757654a
+Qx = e353f3b57f0abad77f0f8071ee820ed0e914dd82742a836b69a624af
+Qy = a1e732045d86cbfa4c8dbf2d44482ec270fec72ad3d643188951ec98
+k = 20a5d8862effd0fdef58a7fef652eced8a68c32a2f6b99223f304d5c
+R = ce76e8ed998926c0f58c362e3a98db7620108677c36b7af2a96c5863
+S = e3722f1cf8c3d01045ae3dfc7c47b42e59189ab24c4789d85f38b91b
+
+[P-256,SHA-512224]
+
+Msg = 221f7924ea78a2568f156580ff3dbf36ca535b0d84a8110b6c93ae5b4ac4f3459ed5e05ef62232fca0db2aed8157906945abf844b97c446874116a83bdac77fda91bd42d848ac8cc729b3faa56b9ca9ff3a9e6c5526181e4631eba2ee6b1e92d8c19dff95a576fae4f7e2d1d460a75c21e72aff71701d2667fe127c48f7950bd
+d = 2c04f0202c9d8b7aff3cbb4901353ade2d020f5a5696496eb8943e39929e85b1
+Qx = ca905779dff535390930267043301b633d6dc4208ff31dde1d00e3c3a1243f99
+Qy = ad62d483a4c8b0e756fa3ad921d17daf3dce59e46af0cf89ff06d64ac0dc1c90
+k = 821532ef969e7eb9a866492788d8a34c50914db1bb3979718c672fb6602d802f
+R = ab16d4afd643c265626e635e701861033c9c150f523f45132279681405e3b37e
+S = 13e31d55665f75f85b25ef2edad525f9a72fc80d9654f33ea80c8f1edcd5232b
+
+Msg = 657a2a3dce2e8025988a8317136a316a468cdc753e9622afa65b2015985ae3ccb3871f086e4f242cabd60d3390833b4e92be02ced2f8a145adec78e88e25753807c1d0e22174f8e3f0d0cdef6ac30f147961169b4ee3c42ff9f0b941361cc5aa8aafa3928fa7e4918c0029154932950422fc82a2596073b4b1ef4ae63846bc6a
+d = 89f5641ad698f975921673d8a46637e13e0cf89d62b1a3d82a528758f99a39ac
+Qx = 47250532d55f55cfa9cb393678b926e6152eb2bfa8bbc9c7e30796fd2cd10f94
+Qy = e6b61540e597ea0fc94df345936ddd142239613e18a943d4c2141d92b89fdc08
+k = e8189faad3eee54300bc201bc8628a1bad48b97caf7c53100bde48798d6a43f2
+R = 271f0b39ebd0b2701821e405ce9101c4877ffbe444044709fe32aed62c90b46e
+S = 77ea3470e6a2cf40b583433564d00fbfa6c72d462abfba372f978457bba05e5b
+
+Msg = 8b5860f177a77cc2d5584706562a1319faed04dd2541c4a5f5a07951d39ff4ba48702b5012acea01784fc55dda0551f88ca49410e5f9b97092c70894300d160e1b88392980793fcbbaa860a0dba97074885e5ae10bbdc92ba3d328681e09cde4aaa771c3e996e4e8436afe1680a0d95596233d98bf155c9ccfcdc013c51c8102
+d = 24473b6921d25d3c0dd4e350bc5286f61aeec3811453a1a18ada2e6ab11c35ab
+Qx = 1fe9c67f7c6983024138703507d664336910665a617d7bc585b98eceed0bb343
+Qy = fa10bae4ce9df1cf86c5206a5a57748c33edfadc822ff35407c917fca04b65cf
+k = 3058478e2f8ac246e3d70d175a1eca201e116572647556fc0948d16ac87693fa
+R = 133e38befcb9a4f6d633b6a7bf4e7131ebd5f27d1496e92f6b2319f845034a12
+S = e90e2d67b27522df7a2320fe30ea30949d30f2b11a34d93923a4dddbc307b508
+
+Msg = 01d68cb87cc8ccf50b868efd461c3ce306caa785be08f8b30fc7e99396fa354309554cc182544c081a802d7cbaee3b882e08ca867b8f25df73e1c7738678ce3bdbb4ac2ca0da205f9e5c6570105ba924b56ac04e24951af360a2f2acac96c94ca07b13c37d613042bea39da0ef6b6cfdc278f1a5601fbf36fd90d306af5b0ebf
+d = ab0b2d543b5c0fa830dc21477f2384e09d7938e564e3ddf1818361c0bee43102
+Qx = 42c16d4f3c0a89446a92b2759e361e6b44fc83d34c20f7c330ce256371937883
+Qy = a24181e3ba5819018f44125fb2a866510294c4050ceb7782434ee042655224db
+k = 541b74005cf2d3595436063c9ad439e2efea965d7b557dd453ab0fb97220fa08
+R = b0a19644a69ac150cf12fcb9eccb82c9198b2210ef217588cfe73dce25c3b939
+S = fb521564e6f46b62e72860c29a6c184b89ea6a365a8b5f9b8b7a7a014954c030
+
+Msg = ee4a82e3cf52a8f84033a84e7a139fe1986daf9af111f474a66cbadf770aed62db59d0834fb0f2ebee8f5fc6422913695a1fb4371c8f80c5dd4d843c2f700efffa11668ecf4fb9ab789656bbd4221d6ee2be33a21bd2fb85059c42fa05beba3f74f9aaccf638e37e07d0f6f4d706a43a58d296a495e24ffd45e25ee1a0fbd868
+d = a46132eca756432355c4ce3cf326ba4e522bbf0c363fd9c27d6924bb3e11acb0
+Qx = d0011081c23774b91269546e106d428d84bbe864d1fb1cb7361e64a5ceb40d75
+Qy = 8d8830e6935a99bfd3a2db094aecc1499f408e6529e46eacdaa5d405e7bd3b51
+k = c4c42618b321be89785729248ff524ec291605b195905ca3f92d927b448c8488
+R = 4d14804aa5a11dfa242d3e63725c0597f3d9eac79ee21a2b96ea72455b75677b
+S = da3f784e748f61f738b790a15500904b86382e8e0e4908e5a7844c71b92a017e
+
+Msg = b4b4daab5ffb6df3b992fc9146fbca460c39a635f59a6e5374d5d6196b54667c4dd3c21e802a2ec60567510e5a20395b9f08a012f9bf6e0934ef7f3cac94a5c26d9bf1ff99af2e1a0a50afb139254bcc5e93a510d98eb136d1af73bb1b870ad85d34eeb4733176d911739de4aab1058191033c975fae3fc0943e3cfc81d69ca6
+d = 1c777fd1ce29469a8051fb0e1872c349d9748c1266d9df8c01e7b05fe85852f6
+Qx = 93e158b63e505ea3956574782ab24d52a4edd728232092bf97ca72ae0122c445
+Qy = 93bb16825eda2f33eddc51f4bf4bafe6a721cf2ac72309b0d5f79b4dc0ffddd5
+k = e041ca52a8d3afb8f6bfc2f78ab0dd0615d0eac06caed73c3fe5c71943e51fec
+R = ca90c19bf89572971e39abe799737f4fbe6ddef7e493371f550d4b3c27f4d73d
+S = d7cda5f633bacac7295d53e611465699fd08a52241593c59ca82665aed6e5622
+
+Msg = 0b6c3e9afe95f9ff4c7b1a67ee420048da18f05d26c85ce4718c650a7f239ea42324131f62928abad5b008f24f17973ec00547fd59f873adf17c455da8417c65ca706d54f63f482a7fc49dc812061fa4995aa7c160ed7cdf769dd1ef570d8fc9c7f8552101c5bdb7115ce2cf7f391fe12dbe199182ceffe1c89710a6d3af5e39
+d = da9e6faabf720b2d9bf87ca8f5f2e67c523110dad8f839fec7f5a1678ed2a868
+Qx = 9e19e114bfe1c0431ab4c1acc10f924aa1f5e2b641166e461a5d5d1698a77621
+Qy = 348a2c4092fb840ba112e53b019b0cdf8db984bd6a20e1c3efc00a82e91bbb69
+k = f83b748a310f2b8e6e7578ccc6c0d672d9daacfd8d04d4a15279df70b483e714
+R = 75f3f871dda4378e08f64d1bbaf70c62e13d89cfaedd6ca1cec019e5b70bcc9d
+S = bc168e973520b6634b8b4b64f5bc49088e742ebced0e502a52d0543b2cffc085
+
+Msg = 6827c067535b8e01b5e03c7bf74e96c651ccb6dee1d2beacfb34cd2cc15c2bcbf3d6c7130813e4897d660fd66d5354266209b1ce6b2dcb316ed9e0e4c0e5fd10f3657118ef72817c442e5dfebf0253033c2a433bba745384b544e30cb0dcc4b611daa4c03102cda2b43e103916e3fb248736536ff92fbe6e777dbfecb8c9e786
+d = dfa280076a9bf9e20566bc0bb5512d1dff874ea16667a69fdd0d033aacb846d9
+Qx = acce5290ec8e35c10f92bfd4c1a033e45f38c79024240004621655f41fe841e4
+Qy = cf584718a543dcfca053f4b3f99fa7e18b1902ee7f6e0d92e7fd0aab109a8250
+k = 2e31dc2e58121b44d80b86d005ba61dc7d80da6bfa7214967f9fefc62fd89259
+R = 1a1cc4ffe0dd2851fa624cd2725a52f70cd378604ea7acd09f3c590cbfe812cf
+S = b09c4dcd9beb6b66d47660477ca7daec56113f68446f05a4843171b1ae1bcd9d
+
+Msg = 057e3b7a896660b323076ef4647f9fdc7c07d02352c13581d3b14ccb89080f6070a96ec306e6fc89a28ae976061d30e3376311628d26c2a50635629cdfad2ede6677f74a0a12d4eeb49314285aea760ad1669d03e27cbebca1c49c41fa44b6618df1be57bc734eaa0129d751856dda1bef195a4e7a49918e4b63e20101550fb1
+d = 783d993075ef0c62566bb71b4c392f187cdb360cd62ea49cb7dd5c5607ed9de5
+Qx = 764d8f0e2abd40b34f331def0c4cb3fd5768f9c6ae36668955b377dc10e6ea5d
+Qy = 342f2ba0568694f17ffbf5600a92fd4998a3eccc6fd7cc4252c59dfe9f74e6dc
+k = 7cd4407b56b876a8e685442c99b7f1f0bbed65c3fa3a145115e6c9e66ea0ac9e
+R = f49c7ac85508f90923cbe3a25fb66bdc5d36162c29afb29d03526ab4ba40fe97
+S = d9927640cfe2d759b11ec9355288f10deac35c9e1aac098a6e451cc594acd8d8
+
+Msg = c68a7b9f388aafa09f5b6c1c55fd7d3f2813cfd502f03101caf4583285192653c1c92c4233f36d849f5d6437f83c4947c90291e5d377b435f70b3247576ad849b9523ffb2ca19763edb3a2c18bea03c54a8eb900c5d8e799d849d641bd403c6875ccbfb16abfb5a452042ea4563234207460510d223c529334574b06ffc3db19
+d = 3f0def7ab825e09a3169f4e964ede3309a80172393d74e2b025a5ef753deb571
+Qx = 8aa2d1f1cca08305e7ad05f1899467bb058f47fdbe07d0da759fd706115e5dbb
+Qy = a8911299edf3d8b098ab373730e0ee438b4ade49d2a56c34543ffc1586682620
+k = da54a28f2bc2962273f1100b3a6cddecc8ac3aac458d337235595e0bb31088d1
+R = b956a1518d8a7818042dfa8ebab668ac81f2eba6b76ae95be12cb491287dc9ef
+S = 2373176223c7ab95366b18edcac35fb7c4168c484c0b676d8d97742cf592456e
+
+[P-256,SHA-512256]
+
+Msg = cb492d9d676831a551e551c6a8ed4ecdd9cf8f951d6bc42043e6c9e6afa3cd6da36fb31abdfcb847c191579699ff6a849ad7914109dad7bfdeb19308c7df8dd670f3625d02022a6cea5457b4db5ee06716f0a006e9b0f97475c7bc4eb5da4d7fbc3c020e3e62cd3b52971bcb76f0fba0d483838cc4d46f6791900c5f807e5590
+d = 136a856a9f959a8fbd9faaca6620b666c135572c7b978999d45bbe90dd7de837
+Qx = 8b03b116339ee6163d7afdf0609a8853c09d4d175b4d50e70f13626ad1158309
+Qy = 572dd200bc68d32b134cdc6cf1fd84e8eaf4062b596a2e96fd814a1b495943e0
+k = c7638a25ad8f5959ced7991b77bc60f7719b7ecc8743964c92f4a4a153d0a212
+R = c7a71db942fd9c60f34cdf67d77d785686af21d99cdd46eebebda43e735b0747
+S = c26ece2f87ec6312c4df3b5d84325a456892e4e981e8630c341887c763f14bbd
+
+Msg = 9e47fd3b10dbc97d969fb2614c9ab6c036063051bef9f47064449b1db19b1c486cf79d4c113988b97f10e056f11cd6662f54972b06a569a9f5dbf6ac29c5e70cac94b530d985bcd113c09200b67f966b4e72ccdc0763e8026516a874357367f3c4e6f0ef4e07904db9766f6883091f56fa2a766cab7a99041cbb5a7dbeecc484
+d = ee6a3e370c98591d09921f369f2b99ce2f47c5ea4d0fb1f998918302d2a1e1a5
+Qx = 6967bd314e9f1ac3efa7d4db0db392bcda18bc5a2b35f929395562c52d308b9e
+Qy = d3740746988dac40fac09c46d58571a89f87de1307831e06e3c0bd3ac4d3aae6
+k = a9bf07f8f5eb836ae69a864872de75e4e672a637128c43c3a3d3b5a062a57db2
+R = df354a4eab7f967f47181d6859d0ca3540d3bbcf5c68732e7d0907e74ed25644
+S = f7192295fa9c324baab0228dcf04f043db873d194bd8448cb994d6b8a7f74799
+
+Msg = 2b254088d99aac23a4a19a91f9096e3108517c956abbcd3707a12067370c30882783357c7f21ad5d41eb5c6ef46092510351ac7a60f2dde36c322f011b48c4f8538e620b96932f56e16bb8bfd44a382a125218eceba8b28239cd5a84872c9fd479efce1b6817b8764cccb56cdff1e924fffcc6d45405d27d341cabd6c3e04885
+d = 3cb5f9d50e431ec38175e6dd91bdfe665d632301fd1a9852d0239f81ef83d4f5
+Qx = 8e6bfa666b4a419279418576cc6fea4f02c1968f2a00105b61f24a38f4161d0f
+Qy = df8aaeee48c21d10dc89db56294363e2acd321afc6e15e1eb94bff9cd2f5aa0b
+k = 380e26a59774057f817d5d91a417811dcd75cae76d2b6c94d893fe08db25bc96
+R = 7ab3d10230b3d5cdff53eea799f4fff050332934e3e6485cfb7b021eb312c8f5
+S = 5289c674a5e7a46844dfa7a31efcd03cd7b3d013de8ff4b0d63978ad99f016ef
+
+Msg = 02fd033f0fc32d8ffbb18f2253adc82c539b7ece61d0fe30daca22d0111e781a95b1a038b32bf62b3ca9721b89b3ccebbb6de31147115fa5b39c95b79ac8ace6f63bfe2e9ffec1020e30e79b67fc428fb7c8eca579afe6e86032fffa502af8abad01e5cad922d63cf8aeb74af771753fcc146333ff94db2269f328413c2da391
+d = 7ddc248dc8b895ff00642bcff7ad93004bfd59a3ae831e52406402872c1cc590
+Qx = fae3bafdb38d92aa307492e285f33718d7e71bf835107d585609f991edf2987e
+Qy = 341ee7a28093c7dfa473618709da8d398f3cd358b02e7b0c162982c5b2562e31
+k = f484443f605a3c2fe3b6de45ed8e4c481b8143622f6fda414a6e7702f5261007
+R = 2ee855fd329f48b8bad3a9f0ab1eb63a887dfa47e2c1336a909b3cb1600c9e4a
+S = 1279a9232f7138fcd3b1123a6c217a5cb46b789dca89e0d24ccde4451711e3c2
+
+Msg = 82c3a82e6debaedf50a3a6d706e7eb1561cd898572bba2d204d8117c6ac04c2a7b7c8f41dab137b57b176c20622d0211ae2ca1a6d739245d34de4027c0bb66be1d79ea39d90064def1ea5737933710682842d1bf92f32f8db237b9342eadda8271a3013df340feffba02b044216cddc2d8f861f92c538b0a88c9c4cc3cfe711d
+d = ae141a648ff47bf6bc872e1ddc65d091abdcb163157af70cf0ef722312538dea
+Qx = bc242cf7e203bab5a9ff63075c344e672c0877106db1230d1b26fe571bd18f13
+Qy = c5a4836e36f993bedc802821a199cead6450e08a89a25b8e46c8e4f5621225a5
+k = 5d17d7868bf2553c47e2a40e6e4d89b7d0d2a151a32d141faea7fddf6920c661
+R = 110ac8ba8cc032ecf37a6c1c7a33b76bc192e7b98d7c970029ba804943fb9de9
+S = 33e4814cf87d2986bae2f9b672c653ef39221131eeece427aa32f55bacf17a2f
+
+Msg = 5bdae59ca4f5fb6c3c51b70357a50a5e878b348e3126da733e0958c81254585fc220a4ae811e388b5c7a9c3428067092b89448bf53a3bbc5643fb7a9742217a8561f78c0a1c14872642f1fc714525391c93ac7f3aabe0323a6638a6f6680677e7f9f0ad9eb2552a9ba36ebc305d3dae12445563220bfda166b3f7822cfb5706b
+d = de19c62b715911065eb47eb424211a6da551929d98b82b56b85fd7761f0973c0
+Qx = 67c29bf9c8b5a9d1f0b543edf8fce58f0c2d49a0471ecf9a36f7c0c70a56d26c
+Qy = 075bfd0d1c5b89ae218ae61ce860288d0c4cbaa53eee59bfacbf3f047eb72668
+k = 7fe82bc28af73b2b9b6f8b58da3665e019c020dffc5ee7937f53fc417dd891ef
+R = 6f33de0c204bacd68536789eeba7b82d2459223516f65802c400be848448134d
+S = 08e00e764fb95b0a1dcaa7313c72f259cf34c35c7a04c8523e8300ccd20e9f28
+
+Msg = dc86496fa344162d3277206aa6d70ace59669e880704118a2f3e88f6bc68dad3e5eb980552df4b7c80ddfcab660efa3c5988d7022ddbb42f9de6bec7ecf0f954cdf43ddc813b7e103f3050c6d871a9a99b22e92f768619cc5fd07066f2361c085c483fda77803751361a22a34425a17ee8dbddf92c2ec8cb3ea3a6ba1663cb57
+d = 40d5fc8194e972ada2a8308294d2000f0bc03147aac80c53e482880401031b75
+Qx = 1a0f8bffdbbd8c3b61114782306abd1c83952ea1ead33bf5b4af3b9a39f852e9
+Qy = d691e1fd8b2cde3b4507df553a066285eca9a295b5e32cdc86780340654c363c
+k = 3508ef35cc3f3c5445a5dc5f7dad83775e638532a50de4b602787b033efd43d9
+R = cadbfdea305ccb0683b513b0945d93bc9ebd8afd251a7436aaebe20767ac9741
+S = fbadd6cf3b6b6a6e21253f0dbff499a90507439a2ad32563774caf06db2a82f2
+
+Msg = da515d96c3e102e1735d30b51a3e4688a4d523489999314d41c0a38c0b0cfa0d2fe8ce9f93b3cbcaec5cfa05252f412904ee2e260b24f0f49cb6a6cd61bbdd9aeb8d53ab992001aabc9359d2f805cd5ceeaa903a171ea008f3f9044064a352ad546a75229ed1ad6b2c2bd7845d69ef09a931d3ee87304a708eb0444bdb6d642e
+d = 1a5823bed902bce337ef03095080a8bfc3731a4392da49657e85cdd3aa3d1be2
+Qx = 006b72c7acfbccfac1fd918ddb2d8020c99a8ae3862766195aca220350e4b6fe
+Qy = 591eec5c7d1b5486aa27e72e8a898177f8a79c70eba60e480c96b0cd0c10f4b1
+k = 490fa8deea0097bae772692ec1e418a3d3779753133216f569802ba4e89cbcc6
+R = ddb0955a24bd1a4ef21467e6e0c2d3b3844cea91ff96daa1c0c18a6c0c333d86
+S = 2b4e70d8d2d254dd5edb1192a8341ca28ea7b5ec71afe57b349755d52f85d6cd
+
+Msg = ed10a4e26982d9dbf3c4b6a0d8be10fbc5372292dd9a3ac609f9b2dc8f52225ae711d4b4cad778288b7a19e7aa4d5075a7a1b852148ba1daeee8096a2d9fc8c49a260ab5e14802f5e725dd4e5d7af5009622486595dd28d16b5134bcc04e8623af562e2bd75ddf08aecde91d19cd67643ac3ba1189173672273b1a1a6fe8c63e
+d = 23343126cbcda891084f3affb4f37dc21df81d2d27edf46d3dfd58257c199887
+Qx = 63ed07c197c554bbd6073d995887f9f46df9b166767127efef9679e65bf3c9dc
+Qy = 8a45f45d3ac6ac1db2b82eaa44366763039c2de1672a37ba6901f3ec267d15a3
+k = 4890dc8cb2323c18360bcaf6bcf2551f76b6225e25bd927e3467c42ddc1fda32
+R = 14ab784e94b98773fa86933fcc77a08e1f8a1dab4db101d365615325cad44113
+S = 3dc3a24f372a1b1a21a889175462eeb77d14a8e10d24bd5f659c230d74775046
+
+Msg = 17a209697bde5d9aa18271a1072355dce038798db9296f8b5ca9f238f54628b2733e244e3195af42d66448a17a74698d0a0b0ca8ed066ecbe72813fb3eb20a981c3472d835a23d74a9aa34a12c453b42648dd75c92ceedca75dfcd326cb36e37da2bfbf0ce2e8f99e4fc3e8966bf5464b764e192f2a875f0ce7628c5c570ddf7
+d = 9c3ad92801202721e9a1dd3bcc51b7f45035b1fa242127f108f63abeda65cec5
+Qx = dffb114a1bd8a06341b34206925cbc3d5fc5ac7fcfe73bae54dbccfbdc07ce23
+Qy = b185aaaa56ef67b6a405e06863ebc295023fce805e78b137d5f0b4ae442fb244
+k = 91ed7c1d5d592d534f5b824da2644100838ad2fce7a9fee9b1123dc1f99c04af
+R = e37fe267466a618e3c02288298ff0d820c761eca09baf4cdcf3aec9cc5041144
+S = 2830c565c2c8269bda8929d1a1ba6ef6d7fa857a7bd0a6598dc82d3cf8c2eba4
+
+[P-384,SHA-512224]
+
+Msg = eb18845ea3c83061bf439109a91d782eea8bdb404023862ef1e20d86607305dddeae7371c260850dbc4a802d666cfa631c8349f90ed03bd8931b08a8c1f884393a4999224804f5a82d3600e1b44811190c81e174d6cd40d57dbd06ffc6ce4dfaa8eeddb95d3ce8f9b910f86cbb3b251762908bf8c1a3fbed56d0f1d1987fc6e8
+d = ce811cebf0e014b2f0d4b00a9d7d9a587b53743d7ba0abe634974460e30c6b0d9e18b05e59c8247b220d10848bd2c120
+Qx = f37ac09f376304c83922f13ccbc72d788a1874850d7db29c63e2c5d1003d9783e388e9432e2eb20c64d731cec5e987fd
+Qy = 6f568a47fc09aff63951635f2df1cd6a4433f58dc8f738d438a833a743dbaf282ba58eca3ab91bd90ff06ce5daa3f072
+k = d1bb9a49ed2ed87f1e4f5ae0c08392d05a33a7fcaeb09c5783749c826123aa80cdc83759ba0a92f6fba0f849f157e1e7
+R = d04f288434340cee4075fa96f75cfc02b3e97421f8ed58c02a629e41cc56fc0388bfb833b6dda89fd7a04ac67500e49a
+S = bd0fd04e9e15bef8198878901d78d26bd279032f10f29265685bd10d8ee4781723bf5c4ed0250bd19ba4a1b76028c603
+
+Msg = d21460b2cd39e96ed6a744ab71213bddd15cb8194aabd8d409dc40ee035cb4ef2ba2e690e8cb8b7dc682b4596c235c02ce203d17a3a3e9b81a75158dc81e380ae54e55f1b97b141851cc186c76368d36e0e5009da6dd746cf9e1b2161293e0f869de55dd2891acc7df4c17ed79a0f6006f72a9b23ba0a27910e8be90c805d540
+d = 937d9753cbc451ff8e0bbeff68c3a6c1217bab7c447537a582b5ff5034ec441e16e2479eb5451c5356839e506607fed6
+Qx = 810d79baa603c4930f12c32602bfdff839f8c3aaa03aef1ec70561cd56b30c259bfa07388e1b7ed174189c29edf35a85
+Qy = 75da526249a2d8d852e82c7956da99c5675c51da83061b0ba8a202d6533caefd59802858d6f5db7faf3050669c4ceb21
+k = 44ebcfe8ee1c5522972756de2190bd7b5f55e79ef0d11c440ad27b130e2a820deda84765493e8945db85d467140c929c
+R = 172a3df0a9d6c38a985b7a85146dc42c6039c8a643379fdfbb1d8f0feb36f362b3636bacb0ef498b25791e9b6f0badae
+S = db2a7f86cba36a2fa6837752726c18cae4b2ee16a345c40f001697876f366b961f6b5f90e0bd03fdf97e2f816f7396ac
+
+Msg = 9e5a5ed55ac19726b0229025384055bef89ab591e5e2eb00a7b27e859d7b654921be6ff30d7ee2be7df562cfd78615c509f3059112d0c688c43758b6c8be4e76e2a6304076551fc14c06b73190c03ae11d84ea13fbcbb60f25301973906940cb6a7b6b619f2e9557a2bf57f26ad60a39bbb72cbfa6bc04bd53038963fe648170
+d = 1059b5385b14f53b1c2f6f1711c68af552828119347e89a8c0923532e52864c217057c52fc35d386f7866c990f0ac494
+Qx = b7a2b89d83d524718739a41c532a8a0b0e8c2a4fef6742643d2dbc1bf2870fbe9e304fcce0a11169fb110b6f1dc8f750
+Qy = 09ccb8f61ebf83b64d21457165edd6de2d17211ea0c78a026e0db3351e41d180a27d44ff1ae888b23095dd5a3a0f20bb
+k = 5caf7239edfed7b2aa59664b606be37e175c7cd7f7f62c870b2efa5c092f0842eab6d7d2ce10d368d7d792800e3c6fd2
+R = ce508784d3acb23b0b7219b93a420f127eec6123b96a06d684334ec4afd572ff0be60483786b7c36ea50068bdb0c7fd7
+S = db244b0decc09c402923170697b313eb9c19ca3b2ce9eeeb178160f37183220a0069134ca28e42520643be5e2af5ed40
+
+Msg = d4f539281d24c861f83cc7d1a295fbb8a89504c44e81e2863292b7272d4cce577a0bdd871adf8758769925534726c6dab31c745eb893bad3ce366361c89a835dfccebc77a333ba35838d00a0cb5be73d3e64e33e939309fa1c04ce9ba75f1216a2655d6182c868e06540df20f5db65c79095d9cba728d7e36425823b9044816c
+d = 2b581f56b1a82c7cea300771feed1f4f198f69d85b2d4d5136fc96d98dbf51f484378d65d8b4f1e0a5074317419af5f2
+Qx = cf9afd5de0bb5c4d43dc60e202570d701ee41781c0e7c5aaea0e58bc1dcfc0f3df702adff1f20f641cf5527d596d351d
+Qy = c831d94943eedb4caa01d2d98ee0c2d91d136e72fda3ef1464223a9367d62bc052d96b6ba51f20e87d9a567060505544
+k = 7fb103f34aa7daec05c961d44ec8635e410e445c9983e68a9d5e3eac2c6e1ba851703ace0ac42abba4f819fcda1c1c88
+R = f9b57422f8eebfd32c03de9535412fd5b0aed46773d6b04469fa5a7f671cc72df0414f21ce0569d58b6403245f1ae208
+S = 362f4f0aff574e2ccdc5f99689028ec7b496aa010958dd94e7d749c924ef2b183ed2b295d1a6a362ed08ab1729d236de
+
+Msg = f30b2ef5c1e60765b9668ff4d9e1d63fd87b783f5f9275cc76593c5f3dc2091cdca27110bc103cb7f80d72c10e6bb815dbe7dd17c699b1263b8e16695bb359ccf1f4c245a8a6695c7c224cea6fb39f217db363ccd1f03ad839557a14d8c680351b4b471dee71395d2fed44f86283316aa72631e8ea61b9ea5af590e71cc4275f
+d = b1f7f89b247e4c690bb84c1a05a77ebe4b0267949b474bde391994efde3018791f62972b84b27a9079d33d3f8779cf81
+Qx = 8295f8cdf14fba5f8b8332a10792f5d260c5af209891d7776d8fe93375c8bf96435f13778996d96533cedb1bed263a65
+Qy = 159665c81b511596e5e1ca7ed511653b477191f14f3662ab0912d10fc61e1ca81279d8ae1c54519e5765e746d0d9feb7
+k = 483d2d938d48b2288c98f1ea14cc6d0113d5b007913c9c419ec7655d91040cdec756756e926de9cc6e18d0c4715fa222
+R = 887bf02ae53a264c35ad2df86192d358c0f79c919cfdec0dd76a575386e3aaa20eeb36046422dd08f96d9c2362e949e9
+S = b9d698b5df2c2f64b35199875babd33ead533d27d6bcf4c5ad4dac00bd7f78c210a9ed752b3c82815aab6ee1842dfd02
+
+Msg = 7c03f63718ba6d3918e4b64c58fa35d007802c9308db3a479867213332c5cc28af7290b7b29eb2a1433b298fba54a603dfa0d28f4f57d6452244216eca1c657f3e0ee348599be96f7ca8991d7bd1ebf7b701f650873f6b9cddcb6228266a590971fe7953d4591c8b0b538d5e631a0e92d7ca203e783efe3612256bca0c58adb0
+d = c51046377bbaf211ffb56dd7b35877537bed471ad51c11ab44d2a5d1024e6c43bfc52d29f97b224e7792a980fc9b76eb
+Qx = 907e58064086d9819f6dbdc3975c7539d440762cbb6abac748f078d3feb9f5443638f4744c05ce1ccca5aba6df6b7619
+Qy = 336ecc05195249e2b6b661c0d254a16732faaf10759189cb31debcf4a32bde19ffed60d11bba2d3806882c79b02e8518
+k = c3e48d431ed6060e8d14a05008e8bb809435833319eb97b9958c983692fcdcf8ec86907fe475f27f7c7a2ae45d34a99e
+R = c8fdff15af8bcde730572fc3788ecc4962ae080a6e146f9acacaeb90b934e44fc8b67f8c21660fffd9b559457322bd4c
+S = da9be58b37c97e67118f8cf040f7c22f640dfc36e3475972ae35d5e03d06b7fe867682b7d6639dfc3e0f5313ab9f1495
+
+Msg = 59d743fbcd9adbcfbbcc8f130dbe3bc70fa022abd04f7ab2cc6e2cb4c7b8d563fc94108077eaf74fc036e748b9db840fc9b9fda63a0192e2e048531bfcdb2a285f531b8ad369cbe8b60b3fbce8afe74be8e7dbda3935641f0b21bef6178a1c55cb3aed82a7bd5e83e77220d762e26b63b25143af9593fa529321f6abe16cb4d2
+d = c5ea360cddb0ba6c87482c09439d264817f9c02ef4c511a8932629590503ecff33ff727e68a1823ddd93729706a40328
+Qx = a2de3a5c4a8179e12329eded196e28a12ea580e9b952930be794d01944267921c49cbf7afac6db7a7dc83a5b295335c1
+Qy = d076c4c2ea3304b172e93435f0e4d0fc1ca7f26f263dd17f5aa5751a32245e0a8b88cc76c51970467c619ac86e379f16
+k = 0ed0834accb4f6746c71e339281ec006e708a21a6823984cadc2d9535f35fb5eb871a8e61631bdbc21df2f53df6c1576
+R = abb1673a3bf33253bef57ef0986ec36dc5b3c34e82cf6b13faf91a6456055ef6ca1073a22fdb0224b4b23e4d54a96f53
+S = b5f564dbd605e0d249301763e85badbc41993640167ae5cb4663c533faab5d747d5942183a37625c4a230fb4883cd162
+
+Msg = e14500467f64f7acaff525bbfce124b278862dfabca938b72ab2649d75189a04641a6d3fd2b0452afac1bd03f196497b748f1c0ce414498c8fcf28033118fbbabbb1d19452b4aba19bc9def1369cb8a6888f664dbeac156f0edd5862405fca656e74f4ed085871391a774f2cd2ddb95c3deed3675157e6863044bd64abd44f30
+d = 85acc22930ec67486e0e1007312ddc1fb92934c2a4075445a049e0dce7f45787993ab069c8a9480a61a5976e4ff08c0b
+Qx = ba6359a1c08bff44d9dc4e9301c4b8535dc82b2bcff04407652bcf9844379ee278ad544557dec07998fa15ed13a77eed
+Qy = 881326bb1c251e1ad8b4923e050729082049abf8d73568c4018920b4d74f20a4a07852b85114a52b8613632b2b4b64ca
+k = 407c93f29d7e470aa5794ddb42a5198ec45f0e9dfd6ce547debe20af9a41ec13d4d9340a0d1244067ac55948c67e71c6
+R = ae9b2324b01c4acc65aaaaa19a430df67cf2c31c5b71c764f1eac9bc637c7c723d10323bc00d6bd5fe3d674bce3a40d0
+S = 5b16547367645d823709cadca581e80a4d56fbd40adbca09d064c7a55a2a0d06469be6b896b630b2593e994fcfade21a
+
+Msg = 077269cfef060efd4f699b72d66051bfe2a0a1de9791e5152f514d1d90fc1c84242b1450e5ba2ee5b7cf8f29fb17b8e56153fd6ffd1438869ec2be7d5be3929c6e9ad9c3466e8e50d74d774335d158a061c2661562dbfedd98d197e44e91f62c8ec9a16f39ab950657ee3b09ab1599b88af3c519ee6fa0e3c785c09b918daefd
+d = 4a3e09d005856862e61566aff6ad5b1eff194864764d66deeffb188287e5a42b95587e003e8f9887c32ff3b24dcf419e
+Qx = 43c23e672a4206cf7eaaff77c9c1c92e5d965e815dff4a1753cb03c7d03896d05d059e4f7c029e11b3d4427aa647286b
+Qy = cd01bc133b86cc6455c0250bc82c80b645c384982bfafa56a4b3966fa7fafff0e923ea7860cbf7b5ac03b2518e86dcde
+k = 21435b3573ad060071ee2ebd071c85051ec6147aa31136718630fbaf1dc5aa8953a523d27a91b48e7aa9a82f7aecc4d1
+R = 46f7ceb5f5ff00169bf7aab5caa68750dcefd73aed1b065ded4f44bb2c0126e0d82bcc55949aa112440228d857d74667
+S = 2deb54886f2849bef8b5ca45bd2f578649ab85251b2468ef47e9b445373efb3eabf8bc9e4354d844b7522f15ae625dab
+
+Msg = 3ec6a4174907fef144b7493f099b46927371c84013d60a6424674526c127823d5621adb2554eece62ab82fd670e0079e655dbb3c9bc79997f1d38ac0c2bfe9775cf195f1b4db45d858211c94a4fe7ec939e42120ab62674b7a4beb43441559d4387f845cce76b2d0b53a3aff0dbd521bd74c2275aa701d88a7179039afef7b5d
+d = 0db0a731f94aa1f5fef2a6adfdbcf0ba513c64a0a2f214ac83457329caec5453eca28d4044d6c404503b5ab113a8ed77
+Qx = ad64b1bd9b1f12cdfbd2b2d315d5338b058b834397d7064cd66853b7fb149cd515ba5d1c63da14becd0b7ca530163661
+Qy = 1ac816bc0736f1a8dad4036ce23ac9425ffcdbd4af9f8a3c5ae6f1e7ed67930e58517bd507fcf8c22f48816fd7874f1d
+k = a09c6a7ef7d53f0b1c217ecdcdb55177578369b7ddd1ba877001e86f76d9e18f886fca4a31000af83056ded7e1677fdf
+R = 2c7640d111928f50b0e89610e24d759b58394b796e33d01ab3549adaf5591b640c82a7178c7930ddc5dbca17d875e435
+S = 55952a5e3299047644908e258d7d84bb30ee008ce861d9f9792be9f16cdc60e519e91c9518f268bc0dee8e5b782f840f
+
+[P-384,SHA-512256]
+
+Msg = e560ab0300eea6690e4367232472c67df0c0067def07ab69df588b8978e4282e571d3df43b1897437336261c97035412775e959651db407847659dab0f283f49edae94d6de47bac916af9448adeb1e349674fd65d0975b37e01cf1457e2665748f5ad7345343b702e0f5d931cff1cbeb35496673d505a3ac93c4b0df2ca743b9
+d = cec1f7a9e5c58f204575ea5d2541ff963350306fca9ddb71346bc0fa96b77c419bd87339368689749d1549f140ee177a
+Qx = 38a459be1008b5eddf78d0090d0b31b9ab9af00f9e52f57c6df7362cbeb14a24c9bcfc18be46915999822dd0b9b6d163
+Qy = 4158770b468e2b61f222dc7aea16f37dd92cd614ff4cfcadd2a1c1c07458acfe4c1a0b156ce2bd9f8ddb99922858a214
+k = a4c40b62e52e785d5648291513e5b15b5c4e740bec9300cc4c988d3ffc251a88180c74a4eadc56512505975cd67c327d
+R = 131047ab56d9f2e3eafee6f6eeae020a82ac2e065b5613eadd68bf81171f6dd96fbda75742a7fa4954c050419e1194b4
+S = 4def595fad5fc7bd3ea5d25a740c63e1158710693037b08bf11799e66c3541252bfacfd51f9db9895fdf09854d568db0
+
+Msg = 3a3fd1273454cdc7d3324181a4053b7b42c85a256e08861a62ebde4b6372f25a96fb3344140aa8434048e2f359cc31b34b9a184ecb69ffdba2aa28e149c5e4bfb7a6074b777899bafdb0cec03a4e38f76e5f3c853ec7c3fa063d317770979b1546483584842709f3b272ef307012b9115320ae12efa93a3f35aee355006f7f24
+d = dcdcb6fa7d75f397f3ec75eb1a9192b2ebbd878f819f241fef2ac1a6314ac59d991555ec68733919df8e48eeef01b098
+Qx = bb4b5d418a1a6599faf18aebc92ccaae924b1e9177611ad96a06c8b7cd33fcb6c80c66f396323b2b6edfc30db04959cb
+Qy = 961f3360ebf22663ca07d4eb25cce4cf72ae6431948cabbd054288d36c66d7bbe5c45bde8b45acfc0187bff109fa5647
+k = 7ec7c21744ec6a5332b541829a4a9c131e367c5bdcad8db6485758dc16bffc3c1742b7f68ac4e3364db40ebdeeb7cd95
+R = 5a253d25485a23ba689e0b65c51f3025b2525574df0ee081a28baae9f145f434ea5196beac334b835c37b1ef516fe957
+S = d5bc52109f3d9e3b564c21e5f5aa67cc47199a4ab1fad60c8d9c103ac7bc9358f536d122b8a621a443fb151f30de12a5
+
+Msg = a470de51357faf2618eb67442bae6f81bb7018f74643815a8590ba89a9512962e6812ddb2ed1024e3f9de515df1e785766e167217e784cb9276fd02ffe821334be0c4f2f07c3b88e5ea3a65a7628f50fadc0acaada80de034616ce5df8ff563c36fa8a7748bc988d7fe5f33c7633b05098f530bae2c3ffe1ea6dfc3d2131ba21
+d = 88033b34889647b103f03dea7ecd1ceaa9d8f4f1505076bce43fec582b25ff7fa2a4b18671dcc7a41803e74051f37213
+Qx = 4532fb8ceb9f01e81b6975c6b3261ee48f72b61d9fe0772efff837421ccdd983397d7ad12365baaa7f50b2b2499c45d3
+Qy = c5e544c01f2a682459ecc16e6916973725c725613f102404d8eb6e37ed6e731bec63db8aee56beed907d8754cd0f9531
+k = 27b52852b3c9f9dbabdcd9da31e8f6f1d886af52ea71033be335954e283a6071ed727da9c010d0fc2288b888f7fea463
+R = 8e3a0ba1e6b71cd980995ebac86d9f34e2afbfa294dc9bdbe12781487b4a82388509dd928a2a56f38e5a4804054be423
+S = cab0bac0da5685fa24c2bb58f869cc8ca3ac925fe69363e704e25c8ad25b70a280c614a8347ccae80e2268cbbe1553d7
+
+Msg = d4a30c3e9444d044ceec130dfff94b896289ae64073de9e5253e1616b17ee8252f41290ac9db676a9ebbeabb5ca8e9aa114bfdb93eeed52d2e832c2785e8f8111c69e43b0c8701c609f7b8c2f2ee0493a59cde9918f6f810a6b9ad34a6ac38a94225251b87ce0622b8a96768e852040dc785394abddfb95535e983853c5212b7
+d = 87e8966b73e9bad37f7ad77ae9514d1350822d5c2427d34be34179fa0ba76c892a63d24c73ce38cdc8ba62bc9e540052
+Qx = 9e23bf81a3c01b4510c793b7240a5a48a7199fb81c80919efbc7f298760c538176383846e167f2407363abebc0b0566e
+Qy = f77994a12623f86b73d676e861784963a4f289afc3ccf4414b456733def0587608a7ffa61288387e4b2d32976f9e50e9
+k = ea4ee5d72054f02203272d3380ce004ea06e18f11967c44514f015d49e833d97fd0328ee2832a0df0ec4f02ea80a15b4
+R = 4af6d52c97c933bf8880b20273ad28788e4fbb64867ae6df215e02fc5000132c814757e9188ea7338a3fb03927692122
+S = 83ab668fd7938eb62db990545e7d06cfa5db31cd1d0905ffa81b2ef90cf9c24126eb91a2cb1abaca28f82ea3afe54035
+
+Msg = 97c075f7fdf7d40d69f36606b1be5d5c3cb3f56bc53558c85da1bfd5af80db92880273b697a84eff714053c6d716efd63c69b77e821c4fe505ae8a9eda6cd27c59e5cba8d89f33f0ba080d62a9affe1a1fb4f7582b7e14d672abc458744d2b841053c4f44a454b8a4d35da03acf252cfed7efc2048c27042ac81b62a038bac51
+d = 863a4df2738157d7cf2e1f7bc3628d55048f26154b0e94bcf8584b19a096638a894630121ed7003508984e3119d494b0
+Qx = eca6edb1b0a9db77205ec9849e0acdde5224d5acd79edf1c25283940d13fa3084c8ff6a72acc3035cec4e693d903b976
+Qy = d249ad89535d99b8e5cdeae602d27c5fb67c475a555713143c0bf9f8f37b76b6166d1a322865f9487a28350ec8d7ffa4
+k = cfa4bf90e4d9883ff36e6a4438fc08fbd45b50e27ec6f23b65070bf628b687791a2b11dd0e9eef12a642bebe3f196117
+R = 3189cb38580596c5c5f5cbae7b74cf1782b9c46073320858e34c76430d88156bb9975a2efbf1c3669d203139fc15dac6
+S = 76fd30464e39b14600234f5991e36747315a89b3873d1461c1e3a15872e54bc5c7ff7ffe9966fa0fb9412e3cb7a10c63
+
+Msg = c9c315d42478e3ddeeb0b72dd4b6be1088c35b27b622c1ad3a92c1ff90ece05c8c05ade94bd652f869da688974b81011a1223f7bbefd596d68c202cc7e243182d6f3857f2e40ddfd65c22309eb78683f769036d5f68821dbcc93a0c0363e1b190e53459eb5fdac754a2e8fb41f3eef216dd5e83c460a427fcccc44e4a181c8a8
+d = 4b5bb0b4542f5e9d6ddba05a45516a278649e444c82557d50a7924fcba95bd5f5a8b7747d55b53b385e7c4dab2193a97
+Qx = 162ae589bdf300839f3e4a3a078342a58e184f8397b831372207e693fe6f23af4d64e7a90f07ef8f0a0680c4bb5c021f
+Qy = 93c020440f2d5f71bfd6c3986c2ca9f885acb64c189e924151d39818582a87b2489879352aa5e5aa93f61e5cd0e72649
+k = a0155454cffc8b06db01b3f7ecee2b4fd4705cfdf23c0de746411de4220aa10163773ede68e1d4e8c65147186c51438c
+R = a0c894aebd42e578112b48b60eeaf4dd7545f8d7df74e0a0cdddb79b69d002cdb813aed023b2317fcb6c9e18d5297967
+S = 7eca24630bb7929936ff510dfbd850861e8bddec0a4b82ae6d2d76c89b61ac3b6d36cfc7a7672c9ede22d97be1945034
+
+Msg = 53188b1d16cdb8f1c48295a411b1059a9a13316c6b1029f3c479cea21d79ef1967c9b2f8952436f15bfb7622356971a1ac698858d54727131a54a7d73cde7376995f6a60abf585bcd212bab75375201ca0595326daec1a92940247f7da0bdf5a71427bfd6128ee79b131280c72bd5b34ff495c7d82e74b97baeb76abfce87bef
+d = 170fe0d70c61a5f31fa8ed1774b44e659f9aea70a26ce6cd1f8aac675b394ea96ace87292a1516bb971637524cc6fe24
+Qx = 512167b505900bcc38720671082c43378740530a3328add7a876ec90e3a84105290928e989a58109ea6f9b60dfb41817
+Qy = 4f23ed17a4610210c2a014aaabd06d8cfb994817779c7c756ab194c1e5e7a7d51695edb79d0d8f20425b8535d0f159d9
+k = b625c76f56e607133d5e3e174e001fabb2fb33502dc99a9eed035fbede1cb5e6b9652d40ddb909acc16b88862aebfc47
+R = 385f4a61a43077dd4448d63f486594ff77bdbce21b971cf43a0163f64d38bee43105999b4fc40a8eeac6672756e27b13
+S = 8714a967394827e95e8337f35250829e9eb4aa979bd9a2cb951b815fda03216ba02318ec4a27d35071167d42b3208bbe
+
+Msg = dd3bbd1561b67b901b4bb5385b1bd75d8afb31a00dc9f9ef6d018fb7b58b05541cd7dfcde42c17be823d6595fffebd019eb518a8bf54771903062501b1083da159ba6d7fb7f6f95cd9a00367847e09b0d54aafdf2406bf262d906e747276e1ecdb0bef95a0bb2953689b1716b344c55175e27eae0388d80033c7f178bf7ef71d
+d = da23ef68052336535dda9a6edc014a077890f8494daf01de517e7041df9249bed5892f3c77589ba9b7f487cbb9d89252
+Qx = 63ad040431923ee6a4da8b1b2531fbe385c01713d98b38df766a08c4491543e631796d22d9af292c8a9c1e8c9eee320e
+Qy = 25baa0b44e98adc4e83c7aba31eaaec22f3d28c5bc2ce65ece767eb428a9a692aee930ebae672599e7d8bdf472f1b420
+k = 099a8e632858f0b85fd023360003be24a098620c5c7591cde1afd7b898cdc16017a73043c3de74a5acd660cd65dfefa2
+R = d01e495736bb77e53eb843f4d2645a98b71e4c66619073cc38fa4eaa967af18fa0cbb43b2a27fc81416be064c19310a5
+S = 8bf770a23d105011036e5df7115c08ad8ea808ac205b7e303c5e496125b0f1887f0492a82ad32f3ee5a74a468bbbfd96
+
+Msg = 3ec9916bfce09aa782e122b0c43ee32579216f26d0537b5b5e5c7e385bec7b7f0f791a06872afeba8cf453e4d603a6ab7c5bfadaafbf18e4a8d12626df7c7b6b7e8fb2b515aafd3b8f5ebcae65904fc0111e28e7c6c6245e5e431b6e94b8b6eb735280010e29403172688796d9ae856d20b420d47b2f48d268f88498e16ad106
+d = 946059d2ce4aab0b4d698cb3573b6da26448090665b00bcb3758aa470f4a753a3675e21931aef6347e9833fabac96462
+Qx = 3656ec99cbfe60e72b947c68bd4eeb6ccd960b53ec8e92945c731c9298a4421bd5abd98b36d2570154119405a5e93a1f
+Qy = 55dada4c3b7e3eca3b1f10d4fb1e15f5bc9eb6889edb2ceec994aee383043ee448a066f80327707e285f3b78058a6a62
+k = 2f607b897978be74ea47b1132c4e22448b53640fe36a6e16731dea06eef0c9247e898c007b228c4bfc1aa533ff14da1c
+R = 50d65bc58941cf52997bbda4eafa00fd770cdbdc9c4f0c94fde802b467cfec6d2d54429abe1c7f737065f7eefc0fbf05
+S = 930da7d1cb0ad53cc2a7bd8b29d3abf76041fce4aa5f2ba58aaad2e44b3ff032285353595132b1ab7558283ff0f37a89
+
+Msg = b25e120087aef613537c34a20296ae1f12136f729844d59184e8f551259f3b7cf0a251237db04235d24ce051e42563d95bd6524896cfa7c5ef932ef840252e1ca6bc4b5584beab44cbec58d979dae56960a3550129da38f998c417cc12c412275c16c83fa5c07768c7c664e4ca9e7ef8a9e33e45594ed15608e17976a36531c4
+d = 189d0c48ef734e7e9b6bf114ad8845d489f07a1325c4ab8e4fee83c425a1ba003eae139c195e09f2593252f2a9c91748
+Qx = 73d01ee4a4baa79f9b7fe67f3e4ebed8fb315700bebbf474d9be322fa5f687d6a37bde2200d481604036eb6a96ce4f18
+Qy = 41f9687c6ab0c50ccf39ebf304064df8a67addaa301eed5e0218377709d1e9761dfd7ee27a9f6ab7f5a8f39d1e0eb223
+k = f8a867363d51f68113d29c092b41a0c57f4acced4bfa40a82ef5760b4b130529dd475cfc23c55da6b3e6cf55c8e95545
+R = b99ebe5e22bece4f8c7914ca3db2f4b3ed3247cc02831a6fa281a5586980587c4c8d7b320344aba9334afc795b035ef2
+S = 7f1351a51d27fa67c217b49f8e4172c16b612176e62f03aa1660aac2388f8997c3b54de1c98176c0865f01d225cb29c9
+
+[P-521,SHA-512224]
+
+Msg = 14d3a434e8526e3ce17bfeae62af7c256f75a86e6e26c0de2feaa4e92be238f109a70a5c67f435e9d69f854426cedbd8e567d3e422c8a5d176b949c3469edf6e42f24d2b31f02a4af193dbaab9c1fb88a2c3019566f91c4b67cc6280f3e32a3cc69ab6c8d0b01607393f4809a3f2a4deaf7278a8c221eff4090b374bba1ae203
+d = 1210b9483bc79f3da0005bf550c983b3f1704ffd4607f5b288e38e9db60883e5d88a2a83bbad96cf451d10c982924ea04154418b0d0a127748e84bcf84e72a98b30
+Qx = 0d105fa68bfcefa4cb15e08bb750dec73733816b4429ea6e26d77e5e630d621358b8623907745ecd555cfde67cb71208ab4129305f937b136a50ba7d477031a40d0
+Qy = 1f4e66f68269f2be811a9e755ae8a5c14d24ba5aa9ea64815895997b66305036bcb9d9052ed6fb25267d41f00bc32f95c5785adb821df0034b07a7eccf13831c41f
+k = 04e1025ae8306985b0ee5c17ea54063e361bb5da9c20cb78fe57bf872b8471f72ffe875d1e05902bad8132bf3816c42effbf6cea1b75df65bcb8defc555a53b4f7c
+R = 1c760c42d9a35e00a3222eb120dd7162cd25d5e964f4b7f949a9fc3e2575780727e8e91a15bb8f191fccc8cd6616dd814e5e7995e27b87d155e0aad1491e0de16fd
+S = 06511469c77742123b7bf26c73bc918d8ca837da222e6a008878d995296145ae046e2c99c918456ecc49edc82b6f89cb08e3aec46057f843a7310b5d2fe3a0fbddb
+
+Msg = 3fa3cf318c67bdf4d511710a45f08ae19f8b02d9d1e563a8cbff38fd919fc2638f50ed682eaa82ffa4d39e24104663bec6d3edc9e7e788b4360e200826b6f94b3836a024830f21c094717a73790150a319d9e1e2c7d03a5a16fca96eee76769edf5dceabb61e00fc4ef2ec41a9a8b7563fa4c46a9628e06013d2bd751066a224
+d = 1dca8491dd2fe91c3205f243fba788b2849eb20bfe32c2c7228a43b0d55d9cbd9ac18f926836542a9326bb63ec24d88973036bcf80973a7398d488613e91cd3c287
+Qx = 0de867680e27335ae411406724ad4850ef30e21ea14901b0eb4af74181644c5fff4af4a1e386eff0e7774594e51ea1526a4071f2c2a26d697aa47dc192b2fa365be
+Qy = 0e761e968761b85ca6a2f6cb839473d0d08086e887b7f2d2d20d09c739acf757acc7641fa91e53b715e4355166d2f256a451228ae79afaad11f563985defa7f1a81
+k = 0757a13770d5a000a7dacdab90b793621eb8c48ae433959ea2ecf8266d48d5ac375fef23e189869da3b8a3877745b3d7e53ca86bd316de91c8c6d8d7ff450dbb926
+R = 0b1cd00839dcc098279488f47b0d22ac884d800c1aeaf67b8fad8d034c2121191513f7242bb66019717d88f6d2c70f29996442935aeebe1126ecd885096e4dd1a9e
+S = 0445625e926c8862a3dd32576f9ee2637dea9eca0051824156daf172f7fceb7515e3adf7dfc58e675991925e464fccdfa020dc0b5763b3384fb577807e370d316fa
+
+Msg = 6d6bdbbf2a977ac0cb048005384f29aba52a70900aff2415d3d73e22d97b726b92d804f284a8ddcd004fde2a0c037490a1306d68171b0abbddc5553d6d12b48b7f2abfb17d204fef38d2d7bdd910f80c1a004fcfb6c092ba1d4edb496da543059e29b303fc45f7addb5314c486bcdca67860bfcdcf38e499fd39794fc17c4761
+d = 171d3089665d40b623fc0219137c6b424ef6a566c44576e453b0f3eefe6cfafce5ed5680116b5c9c015e359cca3054381b8217c76bf467f0c53eb8074dd031ff923
+Qx = 136f35407429a2814d0733ef2c5089f7e967c661b19aec49357b654d778cf7b9148266499f5fe355ea6e58b65a1c4abd5a74d80f17c32e16cf94c9cc6c7b2999a81
+Qy = 17c22101244fdb26e4d754c5ce5a6b09fefa077b83edb0768639666cd412de20e84b9f5b024aef5f476a820810f347e72fb7546b0bd7b3275928b693e7ccf269ea4
+k = 153f1c0e4b3a84147126c0a26db37584e09bb4d1146e316ca7994648c6bba40fd1b16dd6699cc773075b857bca886ae67099e6407bfeafce4b0e9c79f5cf4de2580
+R = 1bb24883f3db39271112344ddf00c27b364892bd5a0e42bb2c26ea559b45eb96f45e389179089ab4e1682da91dcf1b6bf27fd30ca15a58ead7ac6658d1e0846e78d
+S = 1beace80918834324036d29d305ad3fdda58375f43dd3a117437263201b4d7d2c817d2788ecc3f44162ae6420a3bdc46cc77f278aff68f319e66f3fbcc8b47dff3b
+
+Msg = 25af20d02893e95442991f1de5f86a4397ae20d9f675657bf9f397267831e94cef4e4d287f759850350ce0898f2e29de3c5c41f4246fe998a8d1359a2bed36ded1e4d6b08682025843700fee8cab56703e342212870acdd53655255b35e414fa53d9810f47a37195f22d72f6e555392023a08adc282c585b2ae62e129efccdc9
+d = 1d11c36d16be9dca40e8dd9f19390b574f50d297bf8b651d6d7e000eb5a1e01e17251a5a6565aa01600f8242f6b497bde7486338e88e36bd2cdccb2f0ae5b54759b
+Qx = 147c872810df0b70baf1142abc44c22c3feed8d81b783555373af9669a5da8a6965aa6846b68d1c95cee80ebab24543ec780d4b77e0285e501a7b1e8e6f8b65467d
+Qy = 14b89e4414a91c8fdc8b8e87f04512fa3a958c3bdae4fdadfd16579c5bd6b2026b33a82332325f666f0ba13c7ca0a0647cc7645675b12c53aeae876794cf7e06e91
+k = 00638789567c6cc017ece43c617baab56e9ff4e9751fa9e24d40509e436a52d6c66960c1fd870df41c59e932c95b93d70c5cead0549dc4cc06e74a1240c102c8691
+R = 02324e4cbcf863844d1da44e16e480b1d0fe609becf965f5d7788899775a1fa05306e1cb54944ce3776d350e989ce75d6d5167bbbd5786464bea61f49e99c982187
+S = 1b02110c0a25c40b2fb4fb10457f54ef2b3ae4b21cb8e38d3c32cbeb563c0452dd88dd4ee855ddb08b8c31edd1eb278e33326f9c4f22cf3ca943fd593b5e309475c
+
+Msg = 6a609e6e93d89e7d7c1924483fa540f47b70a6b5a7e4a3eea528569a9aa21ceafebb4c2fefe225fbcbd30483fd19da4817d1def722b27f8d314a9dbe3d8af8982c85e964337550cd5effcd446db833a2e2e7390f588d732316a2814ce4a287701e48ddd30699073a5e25e751378a314a043920c7f27d67fa7cb96b0a39f1afb9
+d = 1e1e5b9b60116497102c4609b42ca9e11b960aedc8af13148aacfff37e311701003bcce90d0a0d2c9b1867fd0e7fe1c508d0020cbd86aa7ed8adc77bcba9213f08c
+Qx = 0538b8bb299e850e798df9c235e507f38accd26417e79a37820fe39a57d7322d1ee9474caeb48665772a8b67b934161119a7f12b7a8a1a225c92169f8e695558921
+Qy = 004ece97fa3945c006da0e4f5d6a37a8d786de3abe6630fcab8d0aba06564b4181718d66ec8b3c6f11df5f4cadfbeb9fd1059e2fd9d914e7f636b69f2e4c032d41e
+k = 16e6a6b32cee8c8dc485c3807e3b37374d02f6b662b1717a1f0470d845d767bdf8c53838976288995c4e672738440474b253dfbf08fddf3c16886854203453924e7
+R = 05862e695fec1490d37f64867e3fb79e0aefc4b0c0b002c4b8384495656a89c6358e9cda6b08e61c3dc8e4378f20beaabdfed055d725a9ddb6a36740c89f75d785e
+S = 1a25462abf93aeac6d58a61e269dace518bed39ebc09bfb964e682094358aa936fd0e2b6b9907e6f11c9861ab7e32c173d4be73313f8d5cbd5df23de61fcd44ce16
+
+Msg = ea11e8a909b7335c7713671d545943c7e24ec07a8d453935284dcfa67aa90c40f980c78fd5d647c838bbaba5cdc2886f7fb5d55c8387041c988a72af8de20179043a039877b65b757828de993d8600c35b9cac37d2fe73584a41e9799c6a4cf194a7676df63db68bbec2cba4ac8cf0e800690eb18390ce11c6d8fdadae2835cf
+d = 14134033cc18a98df3bfa245d245d148cba9a37ab8bc20186072977df7e572da9b9e4021cd305c8a99ed1e687d2597cf0553cf5c7ff2a050adc9bf242b4cbc4e797
+Qx = 088ca279e3189f0413f47c33733222298a3847addb5efb970938ef1464043800e266137ac043fd010f8671681caa5872852731786c17363240ae5946fac17bcd53a
+Qy = 11c223ff5f685283f4acde2b147d42958501b14f00639c4a737fee8d6699d7f645858635cdbaa93b44cc10cd6a9fcf54b80a76303367fb489902a4b0210615aa778
+k = 14df27de07da0084ec9b748201056816d9ad37acb517d32ef9f72ff83216ed42ea3ace145cc45fa9a1dd2374af759c8391cefdaf188c421d0db6a722ec149f583b1
+R = 06658e087e803abbafb63268f1242f7f85542cfb1e12225aef3658abda12d23b4c0a2fe70ff58be4db9f0206f599aac1ba3e4fe312db705c37ec78cd28ffdbd1bd3
+S = 1a18e26088f81097dedb30dc1d8a9f4caea1bf783fa23e074ffb534d7781c7ce1412bce3d03515e9c0e6d11d17074971224c3e5f111bcdc0577498c04c96d186356
+
+Msg = c9458bfb910e1108d05f29d65f067f3660e47eb3bc93655fd14c9dd364074a71dde320ecb3c9770b254ca2a92bd47d01acfc4628f138aedb5abb2f7b4f989f567a27062833aaade23c3077a9afba7422349db4ed7727596fda85f0d567e4025508d7e5b7faf9d8157fd350dfd3008c21628e6f0938a88fa4b9728ae8923599f7
+d = 16ed2205409c234f19b55564f954e2501ddc2b722839375103b2d5d778e8162ac65dc5c0727a70a696f452dc25394f17c35bc2e503a227271122a6cab93181e46d4
+Qx = 0c5fe64950361c6eed3863eb2e0bb2259f2290ee9ed0fc5fd75b9300ad33dfd5e16f0c02c0f354f80f16d9f0452366a1a80a6f787d617c6dc65078c94e695949e8e
+Qy = 1700d0ed780c8b317e501c0c1b82718ddffb0ec80574c04774cbd3f7bd8aabcac2cb79a83e74b959365e0eb56d907daf5193a586ee77d85cd1fec897aeb90818fc8
+k = 0c195bc3b71db166f8766fdafdc2d141f75482b63cfbc2e015cd5d81662b07a68c1d91e75592f05dbe65a6b2b23d07d4dc768a4bd812e213cee94e62318d34b6bc0
+R = 059ffca8540ca65dc818b6045eb549a663c44f3284912b05d25858e08714c7df90cd08e0ca3c9fbed25eccfbaecead483e6064decff0da325a35d1499998665af6c
+S = 19d7940ed17566ac9f0dbf7cf93d68e509e0e6005a60642e789753fe1d7c4507e04754a92aea7721cf3f0a903bd5f721c740b84fa6df8599d2365e6a034c56f2304
+
+Msg = aaf0cbe588ffe9f0783280d217c7aec602f49ae53cc3fb9cd020da5cb7309893fbe532dc1dd0c472b5364ceb5865b123be480476243a0532f018e94b949a5a51b4e3c0a08b56bfd78bac008b4343353c86b95787caba329ece1624f68017223f1d11fb999a3ae10543bc2519a20942f9a26f1d82f4ec8bc8b24314c3424ff745
+d = 0f40d418ca14dd109f4957ae71927643efb644d87c3adc3d4c86fec759a0ba241c7c9b84217e8348040b21176ae253eb57f9624dd82885b9fee20308ba87b6c8dcc
+Qx = 0c61d5e190ffc32e5084280384b9982a148dcc24c60d95cf79f1989f709ea24a2e9bf8c67d80b29ddda57892d5625ade689d9cfdefc6132dda749af3ccfa1ee2837
+Qy = 1c9bc63a14e62b39843b11860b82c65b7f45fa72457da3676a58353f0e63be4fca1fa01762166333c87defdfa46774d3c8530e4a8d6cafa7e4426e72514becbffa1
+k = 0167c297b96dc795ab3f815d80997566172d27833de8ceac1596fc0e704d4866de2583c699aceffcd3f24b47cdf8b64fb12a18bcfcecbaccc21da4c9b278695f751
+R = 0afbf0b01600ced366c5bf45850f8079fc9080a06a90f7d7853269c9a5ae455e13bc40aaa1cb83c59d2ae94dcfa48f53f9ff15ed234d3ab6afc976ae94f02f1fdcc
+S = 0b86981f67a5648d79fe65e931b440d89f0f74ff68d533151fbc1f817cb2aa601627b0f50953eae5c2136b2d3e8d2f1ac2e35a7c8974f602914ece881e7bf2481e4
+
+Msg = 0c94b416dc35d8da4711304eafcf55007a0d020b675c0d3b228c9c71162b9549824856fbcf7ca77f212cecf52c08a04349d7fe00c8770191881f8f91c6e8f177338c8772496dba98ded93140fa8c48ace676beec85bfadfee709c03a1cf5a0ee46e8af45f20ff96da9a068f8c16337837972a896463dfacc67d09534bf5989f6
+d = 0f7e59596d77aa11a0d467f9c72fe05a284571756e97033668e2007a77fcea1282fdd92720fca0eb45e093094631df38308f5ccbf802b1961cca00ce227f3426c56
+Qx = 1d19401b7aa5f615e929009143c4522a5d8747eb9791b4e85c0f3bb7779ac08b9c4ff0dcb90770a300b33dd95577df5388e2eeaa3ba561fd47403dbad25200c9a07
+Qy = 0aba38cce711fc3f71133672308b6b18b7d807c88b04b1557c9eef2ff9c7af2865de0b5eab63acf110ba866d7e4e4e0da127e94462a6b7d82d110379d64a33a4cda
+k = 086f471533aeed8ac470914779a04a97e7d21b59f0f2edacf6fc0a1e1023aeab88ccf5e5cee98eb763e6ca30cd78045e00f197f42f0d4c43a8f13f19dcfce1a405b
+R = 1bf8108524d736e05c4185f31c6244b9d7d1539d3d4cfa98c7265c3468bbc435f9a0586596d6a3790e6d89dc29274a32c169fb59ece2d3182c7303ee1b210ce39f2
+S = 11935b3b635ef107191986baed6ec522d68832cf468a78589400ca12fc9a2b2590a57c40d8e30c402f8dc22345c774c21f6b3cbfb1f0399bab9b7bd688612f5a92b
+
+Msg = 42b0059cc18ab8ff6670c3e2ef7af3b0ae05386638a1fc9a5e2ab3bd5e34b49d5aac472d08bdff89acf14a35439946a5016ed603fe78f62c2d2f4bfc8de1fecba353cb3727ab5524fe8dbd026885724f7ba54b5cd06fd3537cf5e479413e77b106ecba42851c63d9448e44d2c60620b302f1bef9144c3b1833c2a4bde314c556
+d = 174efb7c5d04cfccf772b743aa7791088d0676193e8138a1c04cf381bd5f4f646532a0a2e091ad3bc7583811be8d433d1874d1325c6edf7b39fa65eb055fa7c1201
+Qx = 028ce1c7c7263f0d28f8e2f334a8976e543a979fb385861430f8f38b4ad61e99b1a89175a02ca5f25faf8f0a15a74e48b6cab6321564d6d6beb71145d1899550ebb
+Qy = 180fbf22abd172fca8801541084f539d705f4f578d6a0eff05e1ef9a6bc93bd058e7871305f257538b4f89e762eebd76d580a1f7e294140a49ae41c7427b76f6dc8
+k = 0097427a6c74de115d3627872076bb6adcecc22a1fe317863550a05583fdaa880c0021db2d4effe7eff5f7991f4f9eba57088ab5c9f2497f57f6b41b13bd449dda8
+R = 04617518821b18a3541864275bdffa17cc10833661207f66bff8e0a5fbd7129f7e81fc8bbc355601cf2661c19888e9693086d88a7be57e21c9c97989ef9c01246d0
+S = 1bebff5d0060baa8197f6f16b4d8df1e4df38af09f3abba7a96d5b9c724ad3dcee8af34e65c988933bdfcccc27b64b28ea9ccf0a4b2799a3748a8b423e4e77d6116
+
+[P-521,SHA-512256]
+
+Msg = 3b4b534445f444eb203644dbbf4b7246df0726b632693143bd7066097e2f59d95324662f17c6f5640e5dfd258316c724af57f50ddd50c2bcccd38bad55658fb44d95f3eead8c09f7f0e6d15dbdc0c055c612c1adf0407a02b4ebd033c50dad15f34500694f6f060b9078c96cb570e641ece1927db360df7d3d613c8317503b66
+d = 09d8541ff8732bae4f0244dfaad00d73fa14f9e55c312b2e21e74f74fe3cf970534b8863def9b0a2f649639ea3abc4d7577093b9fc97c8adab2c7678192bfa146fd
+Qx = 06276c7037d9beec4b08971d0df52926496742abadde7a2b5dc7a361904b8e550078f705718729de2ef253bc614cc46a2ea52c28ae66b19bd06a08011fa5179cc58
+Qy = 11f28ceb69f56a0dbed831d10a6175a391aa0e86ff04a6dc43e515901272eb194d266c09ad007b10cb9c02bc49dc2de7fdccc65697c3382e843d56e065cb55414d2
+k = 1744badc4b7cc2284b34b65247467094f79c11cd8efb666289087f9cdc15d607f4a16fe8b2b16cc52c1902c6315cadcf4938999bc3c5908c713ab7d5d29ff43bfe7
+R = 0fadf082860592535c792f1c34056b557dec17f4082b1e20ffbf8566b7d81aa8eb6e009fc7a0fb3bd5f990bc5d66f40e2b573f2be9ca0bd5da3c0e9ecf5ffd0cff0
+S = 140d950b3c824c5f01a36f05f5c305c58c788a90dcf927e88334c6a53ccb381201082f2daa32235cb5ca9a259eb1890d9f38f31ebf0d2bb2196870624961f2c220a
+
+Msg = 0a7030c95fb0f52e549a127fab00e6314e2b65f47e6f61e82c02090ea70faffd7805ced68a354b798f9cfbf99efd664e2134ca4aeec663cfb4bcea3e99b25c32212bfc6f52279b1516f8171ae05122f692a044a09f9d23ba6c230308fd408927cd88c47cfdae6e6ab1556ec8b823a2926b17dcded71d2a121ee05b551ae0be43
+d = 1d93c32a1d3e75aeaf75fd5e24d1d661c9d74b006b9ef1bfb6cc31e617f0ee62f010a247056bbfde830d1310f41a8a00f41d8f12e646f2bc5a795439f9cda9cac31
+Qx = 1d0dab83c3ec880600114aa41be7e300bd913d72ef0aa72326689a331779430bb22ba5d50ebab013e300bcc69d19605ba8c1e1bc337f6a0a14ad1d3d3396a68b31d
+Qy = 01779645c17708c583f2fb0afd6bb7e82b23abd159a3b15d656989434e7ab8c39f4b5fa1924b238d03337b27c257dc1958a2ea3c5c343966f91f83556b0617ee6de
+k = 18308d60bcd3a146380e8ed3eb83f57e6b1a6face046e2423a6fd2a1d87b4ffbdd8dd62b11fcecfde1048ace30e9ae99951828588046b18545db8f49a0e602ff5a2
+R = 17483decd97d9a62fcf69e1d143e8dc03c7306c82026401b3af9fd011716f6da68a0f6dcdf30b84ba8294324d204c8be58a8de4b53e07abd1ac462b6e55eda47611
+S = 1b02f5e68ccfa7b82d41fe94ea94fddfdfd2bda31b42d3e7b9233814c2f7abfcfd918f5cca0154c73d897d2595d1484715a8289991a573040e55086009f8ca9d65c
+
+Msg = d72dd9426baeded6061b1cc7706dbb7022852463fe125b673eb48ebdab62eea80f09bd2cec75a8156e75583b9f3a4405da01c92c82f27cc1f347bf72b9b0920901f6ac354cdfcb8d6b5348d2a7bcee7440b30c5819d8c9d9b101b80d5598ac49943ecee7f4b4ec46e3fc1413f0bb62c73be216712a8de9b65e2ca216e6e0e471
+d = 05d5c7953f71cdaa6905352f765db42616c5ddbdd56551b1bcf3c762cd2242cef2f42a2b43c9147b67016cb6ae42d2c12412fe03fc3fe6bfba4749f186ad99a354a
+Qx = 0478a6871a271fb4487ede50707be625cacfd0056e09367c5a513e1f6505c4d31c6633c92e962dff77deea8f71faaef1349f0d549d761d1525cdae83e01307fe65d
+Qy = 0d243f112c4092f9fac20788ec331ce4c42065e9312510014077476757a3015306cebf9cee1fd7f0e7b20b035e6828a68a8b912137257be54246a2c6e82b719fde5
+k = 04522ddec251f1166eb957e7174e2f2eec5675c8030266cff301a62ceff528ffbf1f6cb3c7d16ce38b5a40b3cbaea3fa49b23e12b5cd90358c9d21c40fc95a1ce5e
+R = 0241066926af34f34d1f659ea8c5209fcb9c4baa7b1ca8b145bc655e5965b96523b56d49bff99c46de98289c34195a1b69d6070e6c4b266594a3c4eb283c639670c
+S = 1d6c912d509372e2ff35655c39366fe57d1074dcd391f2962c91229725ee537f5b9e2fff0c9b881ef7656ade09a5c23cf4f8514b99431f538053da014be92e1f3aa
+
+Msg = d32e5c01b230b41d375a4b5bb28c0f439b2d581f25731b5d15de6036d506f68dc497651ad19a24c748f60c5aeb360d55458c201a3b167c53e4610d919b2c2233526e668a299a113b3f215fe4c73842025fdd53129e140ff6ec77409b97edb9d923ba469ae1b8e33fc3e32c3f6e1b15119126db4d75f53b0ed628e19af2d42345
+d = 1af97fcbb08309b39974b6b416ad8e40a21ceae9330d1c6b6dc6c3848e47ff04141affe4a73fa5a0852ef39750a747cf6545d9c28f2def55f8da9d501003ca105c7
+Qx = 1f00543ec647eed091ff6372079b4bca3bda865901b26a16368ed017c3cc1e97745269acf2b09212e61c2adcf63bda99e6d0a423fa9a16bdc3f2d452992c95efddd
+Qy = 13a3f1267c14c33b862852014da06f76e36d0cea7e48924bd3595f73f7bd2af1f570f7517b01d5e7e82c6b038e36197f143c3d2c1f55bb2f7f1f9d594052d41a170
+k = 0de04d967df66724fc4143e6ec99c3116d0f6e6bb783ac98029e8ef433c229a1b21ea7e77801d18159916d41bef2207b39691881ac529bf63bbfcb16f43ecd87e20
+R = 0a27aa963bd4e5032dc8cb77f0eb409d7e92726082ee3cb5e5dbde0105d6346fd02b0634c713a19d0e727f27e9c92b02aa952c8dedab349f5d0debb9390169a3cfd
+S = 1c0974518cb5e463b9a2c228af8616b77184e231222ad440ad8da7692fe63a5645e592d54969157affffff6ff9dc70b4e2ce57fb06bc0f18d8531722d2708f77312
+
+Msg = 1a509f93000b6b77bed82a05eb07ba38ec7752f65c650b88b2829f4e1d4870b1b38dcc58cb596f9fa7f5494557448264d956bca7853b98b7a9157bf67071927008d8130f03a0c60efe08c5af81858031275603fcff5e7c203133f7fde5736d436057fd1e708a79aa0b3b24ad3371ba851c9eb15f9178bfaa94049ccc45f30913
+d = 0b764aa62d5d7d7eef19e08e82fd29eef93871342bd32b4b2304cfccafb2267a1b3c44462895fe1d6ddeedc6a3e62ced8d7e4a8be8b42da42d24b00a235a9485295
+Qx = 02bb2b0899db082c9d7695c72f588a6bec6b8269945fb669fac99102fe02f9b494d8ac99cd5d65e4414cd832db68e7c3f20a5eddd0e4136038f93f2ed4916e20249
+Qy = 0493a163cfd26f2308f2c9f5bba2baaab24e854597c57bfaa748686cf509afc3584365bff84342d38342afec89784b306615936ae15f17b0843e9b84c0d8977a76a
+k = 01c33db9d2429e525262ec9a434ddb82848e858035deb9604a134c261f11c8fd3457a6b7eecb3a906f8531bb49ff3ac8ecbad4ef97c2e54b15f40a9bad9364de4f8
+R = 1a19450f1fa19bbb859cb6c1d4d375f0989b8061a570edfa782c2529228389f253fc96408a32b336a26aec36345ec6c088f561563cc10016d66830faa3e1f91c2d5
+S = 0a7ee175a68b7332714b8a248e3c6b055a81921f4f815cef188c3ccaccb7e496840d71734bf493c3a683e8784f70760cac4ed27116014127712721b1aa90017aac6
+
+Msg = 9f933ddc9b3da7a2775b78f28097ffed213ea568aaf4d04151a707f377c156692ca2f410f44d2330cb61587c684c9ce8bfbb32bac9547ae487a8159145634afe1cc6a88bba58ed1266d827773e751980c342e0e798e4d7ae878db7b3c52f038477e9a37474c6ceef4da62e0a8b7c3f5e37baf917a00aae48583f3582808b48a4
+d = 009ca7625e1f54ff10d123139aff740a56c990ec7d1c2bd88c4ce264adda5f3f1ab706019bac0fa5a66e7cf1801add7f0921a2685b781743806f344afee694ba407
+Qx = 0a0c47fb20e031e7e6ae9a4f8dbc2a42eac82f9b33caadf27f4db951b1d1be3d3fc289ed2868cc09ab58366ca330c4e7a2febaa556e50c3207e15f621ce8fe9e404
+Qy = 1fba9d36cf61a51aa740593188e80860dccdcfdf41a17de7f0dda198fbf2fba0000f7e85567b2aa48ed7b5de933f68b816227b1b52a3b52d884bea48ab0a8dcf05d
+k = 13ac6ae9eed3b614534283e81853c681c0e4dbfb9588ffb0583ebeae206e3ecc8556c899d2bf9d88545ba6193813f7802cce86f515ce3685fa86857e4aa2503539c
+R = 0ed154af918b0fb7494fb68ff2f47bc3ea163eb0b97e9ae2c20db673b83dee2781065707fcfacdd5434c83fe30e25f1d05a1190fa5998ce356d4393a68c1de900e0
+S = 01f41ab67cedcc208bc0adbaee5c68369e351e419870d342d4006e606b529e1d690676f25906dd3ffd2c41f6214066ce0f080591162d132e2a806ee0726d7ffec38
+
+Msg = 8435653ceee5ced7de15767296964073b4166a33fcdf6c5658c223581d4d2e699045997ba950b89917f1567a83b9105619bcfbf845438d15bac0badcb9075dce90badad06105017e248c36c3efa2cfa675bcbe67ce2570cb76f3f5b4973960f48b7e71639c6e71300fd05e7462b8480dd1fefba91feede2192411b09404d0085
+d = 17dd34e6439204f04762786c0cab675236e1fc64347a27ea1584686bebb0891861915055b3b9a36529e6446d667a1022233957167bc8cc4b2f4f249e5da9146d006
+Qx = 10f1639515bc1a996c0eb88ae6e2ca1bdc3510845f8a27b6b6e29bd7595c8a70d747bed6cbbf1e67e5a3a4504cbfd95640810250823ce24b5ed16b42c010b500aa2
+Qy = 108309373d0220f5522f297549ff3de91116e08f3a8e7752db99be5231362f2505d0adcfa2ed8df3dadce8813c516a73fc3f02f9e387afdc5257453db746d750a87
+k = 0be444a503d0d4e493459da6cf08c2b8087f1b2b71026c38fa64a3df0094da3cdef6a8d1ce2b2af59412186238f715c1087512e1603314c1714d541d7988f62e80b
+R = 1c555654c39aadaf4b058621b2f6622a27e1bee1900b332cd646963301015b0c4f8f61442550734000b81ab7a9121ca06164df0596cc44589dce0f4c60856ba41f5
+S = 15069c25ba5d69504b6bfc8b98c99b629a531c449cf16b620fc4c382a80c8fa85942ab9b8fbeb8e8ef7b5aeadaf249ac5cbeb424ff7a25e82e86dac6ee0bec028f5
+
+Msg = 26aa3968b2046f363dc545af1f7668e002ac6f0fe6f2074b68044d48433e7b6a1753c72069428873eb869bdffe8d0561766cd9d19dd15d727a3968c853630ea970047f9722bc2d4d04492d9881fbe0689667d227d960e249bb23a4250ad20303ba242b76e45aa6ec0f75c483afa6411eeb0622b9a387e0f9b22ac8077073a29f
+d = 026531f826e38fe8081dd1da7c2090f635ac2d4107f32e1e7ee15b84aa5cd4334ec2b9cae79784b2aaba55a0d6359cb47fd9a1f96784198bcb22e5f5338a40e0cbc
+Qx = 1954434758598eb1c6ad946bf43838c619bc417aa9a3f82ec49285b23a0c58ba0f36ddb7cf272afbaa8e63da7c79e27626e75f657e66dac559cf0c1517e275fd853
+Qy = 04f8c29883a111ea97739543b33be7171b81bee570363c798ad76e5eb4668d173c1e2760cdcf7e961e673d25c5ac52103e2139778775f6d80f9b645229514a01b60
+k = 09bae46b30706dc2786c121a17dd292b3712e9bacbd54bb186d91f1e2398942a1b2b9d4fd0d4b143fa62550c6bde513a9ddc5c241dc7751003941820df1dcbbe18a
+R = 0e20128a47f42d578d52dfcc50dd08ade26deae5919e7b55e85d53de8a016335aa163c8de9cc1190e5a15289e3e9c5d93f1411ad2051498a0432bbd1c7bde42665e
+S = 0f2f96423e929bfeecc3cbc654c49f9b37096e5910ccd5a754610a8e93c5a7a9f3b5551604df65585c2926c491b1820c6c9cbca1aa2390de98c1cc62e33082a6ff2
+
+Msg = 17258090e8748bc68331e34a91741602b8599b19bf9a133df363ce0bc96191c7c41d96519988d55492d682c13090d77c14e513551f42c339d92240a90f26796cc168f2813b0d0d5881198942f0874825239a5574146e255e83d21d469c5a5574d4af9c0a142abc3919a1ffb41b81f165ac1d6860e446c215bb1c6ec9b623ae47
+d = 14e8bb3cff13171764101ea0feacbb82462aa6fe7023c1d0127a472ea225a28d0a04bf4f9020ceef418f4f38f349608eb6a4a751a98377559d3d111adc6bb7bbfe4
+Qx = 0c9c466db5b13128240e7f78b2bed2af618e79b81d50399d1cafa7c3f8fd8d2cb9dc6e648fbc7dd90287728195f00bc8b8352f4ab5ee07a26ae4ec0ec8a9acbbd6b
+Qy = 14d638688f3455adc2919d0f8cb7d2d83dfb8a03ad82f715ff98771490942101b8766c7b8da57f4b57824d683c5f462c6f7661a99cc97bd91d5f720563591c12d94
+k = 132a7deee7a9c6eb8be67d09a70305bd17a82ba68dee66cb55088feb6d96e2b2e019414de4b80dbfef269889744b51c1b61c4adefb3857fd9089227317de42cd5eb
+R = 1f925efdc1c307b18820d7d7606942ec5070fbffc424393cf039a73a9cc3254d5cd5e6e3053f2c95ca57575380d056401c6acea104fe8355e8bcb1a624178066b3d
+S = 08d96e9e155c608bea9d55a68613008c7da96b0b9f76e1055b74cf3559cb6bded7e061fad4fc7ed5f9883c6edcc0ac51bbdb79b78ba4afa262cc9f6c4e1b2659923
+
+Msg = 68fd56b15e463138bd95443e2cfe249390e869fde862b42b74bbf0ea1d4cd79c1199b8e5ae9978a7a151d8314fa8f5b3747615f509dea0496cde6dbfbb243f97802390fc94678def3d2561819a17b6454186790526a9deb4bf2da5a465159bf9fec4635ed95876f6d93a6995d6f36f3140421e93056b7652b5d11f02e5c7f2a9
+d = 11c4576a39f346a622a9498df8aed7f7df5e5242e06a8c670e77aee9954a990d1948fa4a686f3eefe1cecc3ad0bc29d126f8b9c80818e5bd94c50edfcd97fc6131e
+Qx = 010859173dc50af4b840838b14b0954d78c09aea0a850853b96222689fe16d9b156bc206f4cf03fedff039cd2d0a227dfee087312b327fa396e74e97144a24e54f4
+Qy = 0ece55d1376b3d194dd102e1af983bc2361ce6c05b614a0a799c526a1de6b506e1629457dbe267cce8a733b4966e50ba623a3ceb98ce6a4f11d0036039be8fe64cf
+k = 192c87ca60613ab419ab82156cb7a99f8b1767bdcdcbbb6dbf1abc1565d9b18bbdf4b0a278227cb8b018ecd43101b9256bfb16b959d5091065f5ae6e1b3e0dfc74b
+R = 1a360501505dea23824d4af13b4f311d64fb72cfa9fb92cf03171a4abf3760564687bc5953bcbc26d0d88597296322d73134634c7595588f05545c1f70400fb62de
+S = 0ba5bd677335023839977f09c3e146a60f83388bb10eae463e0fa55fef5b39e559cb53e36b4ecbce78e9d0c7ea565c78f52b4a22a4640ee0869505a9030b3bdccaf
index 73628a8..cc12976 100644 (file)
@@ -35,7 +35,9 @@
 
 static int sign_with_pk;
 static int no_verify;
+static int no_fips;
 static int custom_data_file;
+static int in_fips_mode;
 
 
 static void
@@ -271,7 +273,17 @@ one_test (int testno, const char *sk, const char *pk,
       goto leave;
     }
 
-  if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk)))
+  err = gcry_pk_sign (&s_sig, s_msg, s_sk);
+  if (in_fips_mode)
+    {
+      if (!err)
+        fail ("gcry_pk_sign is not expected to work in FIPS mode for test %d",
+              testno);
+      if (verbose > 1)
+        info ("not executed in FIPS mode\n");
+      goto leave;
+    }
+  if (err)
     fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err));
   if (debug)
     show_sexp ("sig=", s_sig);
@@ -463,6 +475,11 @@ main (int argc, char **argv)
               argc--; argv++;
             }
         }
+      else if (!strcmp (*argv, "--no-fips"))
+        {
+          no_fips = 1;
+          argc--; argv++;
+        }
       else if (!strncmp (*argv, "--", 2))
         die ("unknown option '%s'", *argv);
 
@@ -473,17 +490,21 @@ main (int argc, char **argv)
   else
     custom_data_file = 1;
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  if (no_fips)
+    {
+      xgcry_control ((GCRYCTL_NO_FIPS_MODE, 0));
+      xgcry_control ((GCRYCTL_FIPS_MODE_P, 0));
+    }
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
-  /* Ed25519 isn't supported in fips mode */
-  if (gcry_fips_mode_active())
-    return 77;
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
 
   start_timer ();
   check_ed25519 (fname);
diff --git a/tests/t-ed448.c b/tests/t-ed448.c
new file mode 100644 (file)
index 0000000..3e3dd34
--- /dev/null
@@ -0,0 +1,547 @@
+/* t-ed448.c - Check the Ed448 crypto
+ * Copyright (C) 2020 g10 Code GmbH
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "stopwatch.h"
+
+#define PGM "t-ed448"
+#include "t-common.h"
+#define N_TESTS 11
+
+static int sign_with_pk;
+static int no_verify;
+static int custom_data_file;
+static int in_fips_mode;
+
+
+static void
+show_note (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!verbose && getenv ("srcdir"))
+    fputs ("      ", stderr);  /* To align above "PASS: ".  */
+  else
+    fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+  va_end (arg_ptr);
+}
+
+
+static void
+show_sexp (const char *prefix, gcry_sexp_t a)
+{
+  char *buf;
+  size_t size;
+
+  fprintf (stderr, "%s: ", PGM);
+  if (prefix)
+    fputs (prefix, stderr);
+  size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
+  buf = xmalloc (size);
+
+  gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
+  fprintf (stderr, "%.*s", (int)size, buf);
+  gcry_free (buf);
+}
+
+
+/* Prepend FNAME with the srcdir environment variable's value and
+ * return an allocated filename.  */
+char *
+prepend_srcdir (const char *fname)
+{
+  static const char *srcdir;
+  char *result;
+
+  if (!srcdir && !(srcdir = getenv ("srcdir")))
+    srcdir = ".";
+
+  result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
+  strcpy (result, srcdir);
+  strcat (result, "/");
+  strcat (result, fname);
+  return result;
+}
+
+
+/* Read next line but skip over empty and comment lines.  Caller must
+   xfree the result.  */
+static char *
+read_textline (FILE *fp, int *lineno)
+{
+  char line[4096];
+  char *p;
+
+  do
+    {
+      if (!fgets (line, sizeof line, fp))
+        {
+          if (feof (fp))
+            return NULL;
+          die ("error reading input line: %s\n", strerror (errno));
+        }
+      ++*lineno;
+      p = strchr (line, '\n');
+      if (!p)
+        die ("input line %d not terminated or too long\n", *lineno);
+      *p = 0;
+      for (p--;p > line && my_isascii (*p) && isspace (*p); p--)
+        *p = 0;
+    }
+  while (!*line || *line == '#');
+  /* if (debug) */
+  /*   info ("read line: '%s'\n", line); */
+  return xstrdup (line);
+}
+
+
+/* Copy the data after the tag to BUFFER.  BUFFER will be allocated as
+   needed.  */
+static void
+copy_data (char **buffer, const char *line, int lineno)
+{
+  const char *s;
+
+  xfree (*buffer);
+  *buffer = NULL;
+
+  s = strchr (line, ':');
+  if (!s)
+    {
+      fail ("syntax error at input line %d", lineno);
+      return;
+    }
+  for (s++; my_isascii (*s) && isspace (*s); s++)
+    ;
+  *buffer = xstrdup (s);
+}
+
+
+/* Convert STRING consisting of hex characters into its binary
+   representation and return it as an allocated buffer. The valid
+   length of the buffer is returned at R_LENGTH.  The string is
+   delimited by end of string.  The function returns NULL on
+   error.  */
+static void *
+hex2buffer (const char *string, size_t *r_length)
+{
+  const char *s;
+  unsigned char *buffer;
+  size_t length;
+
+  buffer = xmalloc (strlen(string)/2+1);
+  length = 0;
+  for (s=string; *s; s +=2 )
+    {
+      if (!hexdigitp (s) || !hexdigitp (s+1))
+        return NULL;           /* Invalid hex digits. */
+      ((unsigned char*)buffer)[length++] = xtoi_2 (s);
+    }
+  *r_length = length;
+  return buffer;
+}
+
+
+static void
+hexdowncase (char *string)
+{
+  char *p;
+
+  for (p=string; *p; p++)
+    if (my_isascii (*p))
+      *p = tolower (*p);
+}
+
+
+static void
+one_test (int testno, int ph, const char *sk, const char *pk,
+          const char *msg, const char *ctx, const char *sig)
+{
+  gpg_error_t err;
+  int i;
+  char *p;
+  void *buffer = NULL;
+  void *buffer2 = NULL;
+  size_t buflen, buflen2;
+  gcry_sexp_t s_tmp, s_tmp2;
+  gcry_sexp_t s_sk = NULL;
+  gcry_sexp_t s_pk = NULL;
+  gcry_sexp_t s_msg= NULL;
+  gcry_sexp_t s_sig= NULL;
+  unsigned char *sig_r = NULL;
+  unsigned char *sig_s = NULL;
+  char *sig_rs_string = NULL;
+  size_t sig_r_len, sig_s_len;
+
+  if (verbose > 1)
+    info ("Running test %d %d\n", testno, ph);
+
+  if (!(buffer = hex2buffer (sk, &buflen)))
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "sk", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer2 = hex2buffer (pk, &buflen2)))
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "pk", "invalid hex string");
+      goto leave;
+    }
+  if (sign_with_pk)
+    err = gcry_sexp_build (&s_sk, NULL,
+                           "(private-key"
+                           " (ecc"
+                           "  (curve \"Ed448\")"
+                           "  (q %b)"
+                           "  (d %b)))",
+                           (int)buflen2, buffer2,
+                           (int)buflen, buffer);
+  else
+    err = gcry_sexp_build (&s_sk, NULL,
+                           "(private-key"
+                           " (ecc"
+                           "  (curve \"Ed448\")"
+                           "  (d %b)))",
+                           (int)buflen, buffer);
+  if (err)
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "sk", gpg_strerror (err));
+      goto leave;
+    }
+
+  if ((err = gcry_sexp_build (&s_pk, NULL,
+                              "(public-key"
+                              " (ecc"
+                              "  (curve \"Ed448\")"
+                              "  (q %b)))",  (int)buflen2, buffer2)))
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "pk", gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer);
+  if (!(buffer = hex2buffer (msg, &buflen)))
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "msg", "invalid hex string");
+      goto leave;
+    }
+  if (ctx)
+    {
+      xfree (buffer2);
+      if (!(buffer2 = hex2buffer (ctx, &buflen2)))
+        {
+          fail ("error building s-exp for test %d, %s: %s",
+                testno, "ctx", "invalid hex string");
+          goto leave;
+        }
+
+      if ((err = gcry_sexp_build (&s_msg, NULL,
+                                  ph ?
+                                  "(data"
+                                  " (flags prehash)"
+                                  " (label %b)"
+                                  " (value %b))"
+                                  :
+                                  "(data"
+                                  " (label %b)"
+                                  " (value %b))",
+                                  (int)buflen2, buffer2,
+                                  (int)buflen, buffer)))
+        {
+          fail ("error building s-exp for test %d, %s: %s",
+                testno, "msg", gpg_strerror (err));
+          goto leave;
+        }
+    }
+  else
+    {
+      if ((err = gcry_sexp_build (&s_msg, NULL,
+                                  ph ?
+                                  "(data"
+                                  " (flags prehash)"
+                                  " (value %b))"
+                                  :
+                                  "(data"
+                                  " (value %b))",  (int)buflen, buffer)))
+        {
+          fail ("error building s-exp for test %d, %s: %s",
+                testno, "msg", gpg_strerror (err));
+          goto leave;
+        }
+    }
+
+  err = gcry_pk_sign (&s_sig, s_msg, s_sk);
+  if (in_fips_mode)
+    {
+      if (!err)
+        fail ("gcry_pk_sign is not expected to work in FIPS mode for test %d",
+              testno);
+      if (verbose > 1)
+        info ("not executed in FIPS mode\n");
+      goto leave;
+    }
+  if (err)
+    fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err));
+  if (debug)
+    show_sexp ("sig=", s_sig);
+
+  s_tmp2 = NULL;
+  s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
+  if (s_tmp)
+    {
+      s_tmp2 = s_tmp;
+      s_tmp = gcry_sexp_find_token (s_tmp2, "eddsa", 0);
+      if (s_tmp)
+        {
+          gcry_sexp_release (s_tmp2);
+          s_tmp2 = s_tmp;
+          s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0);
+          if (s_tmp)
+            {
+              sig_r = gcry_sexp_nth_buffer (s_tmp, 1, &sig_r_len);
+              gcry_sexp_release (s_tmp);
+            }
+          s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0);
+          if (s_tmp)
+            {
+              sig_s = gcry_sexp_nth_buffer (s_tmp, 1, &sig_s_len);
+              gcry_sexp_release (s_tmp);
+            }
+        }
+    }
+  gcry_sexp_release (s_tmp2); s_tmp2 = NULL;
+
+  if (!sig_r || !sig_s)
+    fail ("gcry_pk_sign failed for test %d: %s", testno, "r or s missing");
+  else
+    {
+      sig_rs_string = xmalloc (2*(sig_r_len + sig_s_len)+1);
+      p = sig_rs_string;
+      *p = 0;
+      for (i=0; i < sig_r_len; i++, p += 2)
+        snprintf (p, 3, "%02x", sig_r[i]);
+      for (i=0; i < sig_s_len; i++, p += 2)
+        snprintf (p, 3, "%02x", sig_s[i]);
+      if (strcmp (sig_rs_string, sig))
+        {
+          fail ("gcry_pk_sign failed for test %d: %s",
+                testno, "wrong value returned");
+          info ("  expected: '%s'", sig);
+          info ("       got: '%s'", sig_rs_string);
+        }
+    }
+
+  if (!no_verify)
+    if ((err = gcry_pk_verify (s_sig, s_msg, s_pk)))
+      fail ("gcry_pk_verify failed for test %d: %s",
+            testno, gpg_strerror (err));
+
+
+ leave:
+  gcry_sexp_release (s_sig);
+  gcry_sexp_release (s_sk);
+  gcry_sexp_release (s_pk);
+  gcry_sexp_release (s_msg);
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (sig_r);
+  xfree (sig_s);
+  xfree (sig_rs_string);
+}
+
+
+static void
+check_ed448 (const char *fname)
+{
+  FILE *fp;
+  int lineno, ntests;
+  char *line;
+  int testno;
+  int ph;
+  char *sk, *pk, *msg, *ctx, *sig;
+
+  info ("Checking Ed448.\n");
+
+  fp = fopen (fname, "r");
+  if (!fp)
+    die ("error opening '%s': %s\n", fname, strerror (errno));
+
+  testno = 0;
+  ph = 0;
+  sk = pk = msg = ctx = sig = NULL;
+  lineno = ntests = 0;
+  while ((line = read_textline (fp, &lineno)))
+    {
+      if (!strncmp (line, "TST:", 4))
+        testno = atoi (line+4);
+      else if (!strncmp (line, "PH:", 3))
+        ph = atoi (line+3);
+      else if (!strncmp (line, "SK:", 3))
+        copy_data (&sk, line, lineno);
+      else if (!strncmp (line, "PK:", 3))
+        copy_data (&pk, line, lineno);
+      else if (!strncmp (line, "MSG:", 4))
+        copy_data (&msg, line, lineno);
+      else if (!strncmp (line, "CTX:", 4))
+        copy_data (&ctx, line, lineno);
+      else if (!strncmp (line, "SIG:", 4))
+        copy_data (&sig, line, lineno);
+      else
+        fail ("unknown tag at input line %d", lineno);
+
+      xfree (line);
+      if (testno && sk && pk && msg && sig)
+        {
+          hexdowncase (sig);
+          one_test (testno, ph, sk, pk, msg, ctx, sig);
+          ntests++;
+          if (!(ntests % 256))
+            show_note ("%d of %d tests done\n", ntests, N_TESTS);
+          ph = 0;
+          xfree (pk);  pk = NULL;
+          xfree (sk);  sk = NULL;
+          xfree (msg); msg = NULL;
+          xfree (ctx); ctx = NULL;
+          xfree (sig); sig = NULL;
+        }
+
+    }
+  xfree (pk);
+  xfree (sk);
+  xfree (msg);
+  xfree (ctx);
+  xfree (sig);
+
+  if (ntests != N_TESTS && !custom_data_file)
+    fail ("did %d tests but expected %d", ntests, N_TESTS);
+  else if ((ntests % 256))
+    show_note ("%d tests done\n", ntests);
+
+  fclose (fp);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  char *fname = NULL;
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options]\n"
+                 "Options:\n"
+                 "  --verbose       print timings etc.\n"
+                 "  --debug         flyswatter\n"
+                 "  --sign-with-pk  also use the public key for signing\n"
+                 "  --no-verify     skip the verify test\n"
+                 "  --data FNAME    take test data from file FNAME\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--sign-with-pk"))
+        {
+          sign_with_pk = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--no-verify"))
+        {
+          no_verify = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--data"))
+        {
+          argc--; argv++;
+          if (argc)
+            {
+              xfree (fname);
+              fname = xstrdup (*argv);
+              argc--; argv++;
+            }
+        }
+      else if (!strncmp (*argv, "--", 2))
+        die ("unknown option '%s'", *argv);
+
+    }
+
+  if (!fname)
+    fname = prepend_srcdir ("t-ed448.inp");
+  else
+    custom_data_file = 1;
+
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  if (!gcry_check_version (GCRYPT_VERSION))
+    die ("version mismatch\n");
+  if (debug)
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
+  start_timer ();
+  check_ed448 (fname);
+  stop_timer ();
+
+  xfree (fname);
+
+  info ("All tests completed in %s.  Errors: %d\n",
+        elapsed_time (1), error_count);
+  return !!error_count;
+}
diff --git a/tests/t-ed448.inp b/tests/t-ed448.inp
new file mode 100644 (file)
index 0000000..a2766f9
--- /dev/null
@@ -0,0 +1,75 @@
+# t-ed448.inp
+# This is from RFC 8032, the section
+#
+#     7.4.  Test Vectors for Ed448
+#
+
+TST: 1
+SK: 6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b
+PK: 5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180
+MSG:
+SIG: 533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4dbb61149f05a7363268c71d95808ff2e652600
+
+TST: 2
+SK: c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463afbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e
+PK: 43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480
+MSG: 03
+SIG: 26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f4352541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cbcee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0ff3348ab21aa4adafd1d234441cf807c03a00
+
+TST: 3
+SK: c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463afbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e
+PK: 43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480
+MSG: 03
+CTX: 666f6f
+SIG: d4f8f6131770dd46f40867d6fd5d5055de43541f8c5e35abbcd001b32a89f7d2151f7647f11d8ca2ae279fb842d607217fce6e042f6815ea000c85741de5c8da1144a6a1aba7f96de42505d7a7298524fda538fccbbb754f578c1cad10d54d0d5428407e85dcbc98a49155c13764e66c3c00
+
+TST: 4
+SK: cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffdf60500553abc0e05cd02184bdb89c4ccd67e187951267eb328
+PK: dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e365fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400
+MSG: 0c3e544074ec63b0265e0c
+SIG: 1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d389dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b051068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5028961c9bf8ffd973fe5d5c206492b140e00
+
+TST: 5
+SK: 258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d939f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b
+PK: 3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580
+MSG: 64a65f3cdedcdd66811e2915
+SIG: 7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4ae90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457eb1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861e72003cbae6d6b8b827e4e6c143064ff3c00
+
+TST: 6
+SK: 7ef4e84544236752fbb56b8f31a23a10e42814f5f55ca037cdcc11c64c9a3b2949c1bb60700314611732a6c2fea98eebc0266a11a93970100e
+PK: b3da079b0aa493a5772029f0467baebee5a8112d9d3a22532361da294f7bb3815c5dc59e176b4d9f381ca0938e13c6c07b174be65dfa578e80
+MSG: 64a65f3cdedcdd66811e2915e7
+SIG: 6a12066f55331b6c22acd5d5bfc5d71228fbda80ae8dec26bdd306743c5027cb4890810c162c027468675ecf645a83176c0d7323a2ccde2d80efe5a1268e8aca1d6fbc194d3f77c44986eb4ab4177919ad8bec33eb47bbb5fc6e28196fd1caf56b4e7e0ba5519234d047155ac727a1053100
+
+TST: 7
+SK: d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bff21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01
+PK: df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00
+MSG: bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944
+SIG: 554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b18dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722ef552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba5f30e88e36ec2703b349ca229c2670833900
+
+TST: 8
+SK: 2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d37569b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5
+PK: 79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9bfe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00
+MSG: 15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567cfa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072fc1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a6039c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b590316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce012d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11
+SIG: c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc60987fd08527c1a8e80d5823e65cafe2a3d00
+
+TST: 9
+SK: 872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8
+PK: a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799da08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400
+MSG: 6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e972660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd323219b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab797172b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f52096cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db977025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f0410a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf9696149e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a6059d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87
+SIG: e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bddf7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed573603ce30d8bb761785dc30dbc320869e1a00
+
+TST: 10
+PH: 1
+SK: 833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49
+PK: 259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880
+MSG: 616263
+SIG: 822f6901f7480f3d5f562c592994d9693602875614483256505600bbc281ae381f54d6bce2ea911574932f52a4e6cadd78769375ec3ffd1b801a0d9b3f4030cd433964b6457ea39476511214f97469b57dd32dbc560a9a94d00bff07620464a3ad203df7dc7ce360c3cd3696d9d9fab90f00
+
+TST: 11
+PH: 1
+SK: 833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ef7822e0d5104127dc05d6dbefde69e3ab2cec7c867c6e2c49
+PK: 259b71c19f83ef77a7abd26524cbdb3161b590a48f7d17de3ee0ba9c52beb743c09428a131d6b1b57303d90d8132c276d5ed3d5d01c0f53880
+MSG: 616263
+CTX: 666f6f
+SIG: c32299d46ec8ff02b54540982814dce9a05812f81962b649d528095916a2aa481065b1580423ef927ecf0af5888f90da0f6a9a85ad5dc3f280d91224ba9911a3653d00e484e2ce232521481c8658df304bb7745a73514cdb9bf3e15784ab71284f8d0704a608c54a6b62d97beb511d132100
index e011ef4..4c82fed 100644 (file)
@@ -31,6 +31,8 @@
 #define PGM "t-kdf"
 #include "t-common.h"
 
+static int in_fips_mode;
+
 
 static void
 dummy_consumer (volatile char *buffer, size_t buflen)
@@ -858,8 +860,7 @@ check_openpgp (void)
       if (tv[tvidx].disabled)
         continue;
       /* MD5 isn't supported in fips mode */
-      if (gcry_fips_mode_active()
-          && tv[tvidx].hashalgo == GCRY_MD_MD5)
+      if (in_fips_mode && tv[tvidx].hashalgo == GCRY_MD_MD5)
         continue;
       if (verbose)
         fprintf (stderr, "checking S2K test vector %d\n", tvidx);
@@ -1104,8 +1105,25 @@ check_pbkdf2 (void)
                              GCRY_KDF_PBKDF2, tv[tvidx].hashalgo,
                              tv[tvidx].salt, tv[tvidx].saltlen,
                              tv[tvidx].c, tv[tvidx].dklen, outbuf);
+      if (in_fips_mode && tvidx > 6)
+        {
+          if (!err)
+            fail ("pbkdf2 test %d unexpectedly passed in FIPS mode: %s\n",
+                  tvidx, gpg_strerror (err));
+          continue;
+        }
       if (err)
-        fail ("pbkdf2 test %d failed: %s\n", tvidx, gpg_strerror (err));
+        {
+          if (in_fips_mode && tv[tvidx].plen < 14)
+            {
+              if (verbose)
+                fprintf (stderr,
+                         "  shorter key (%u) rejected correctly in fips mode\n",
+                         (unsigned int)tv[tvidx].plen);
+            }
+          else
+            fail ("pbkdf2 test %d failed: %s\n", tvidx, gpg_strerror (err));
+        }
       else if (memcmp (outbuf, tv[tvidx].dk, tv[tvidx].dklen))
         {
           fail ("pbkdf2 test %d failed: mismatch\n", tvidx);
@@ -1202,7 +1220,17 @@ check_scrypt (void)
                              tv[tvidx].salt, tv[tvidx].saltlen,
                              tv[tvidx].parm_p, tv[tvidx].dklen, outbuf);
       if (err)
-        fail ("scrypt test %d failed: %s\n", tvidx, gpg_strerror (err));
+        {
+          if (in_fips_mode && tv[tvidx].plen < 14)
+            {
+              if (verbose)
+                fprintf (stderr,
+                         "  shorter key (%u) rejected correctly in fips mode\n",
+                         (unsigned int)tv[tvidx].plen);
+            }
+          else
+            fail ("scrypt test %d failed: %s\n", tvidx, gpg_strerror (err));
+        }
       else if (memcmp (outbuf, tv[tvidx].dk, tv[tvidx].dklen))
         {
           fail ("scrypt test %d failed: mismatch\n", tvidx);
@@ -1215,6 +1243,253 @@ check_scrypt (void)
 }
 
 
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+
+#define MAX_THREADS 8
+
+struct user_defined_threads_ctx
+{
+  int oldest_thread_idx;
+  int next_thread_idx;
+  int num_threads_running;
+  pthread_attr_t attr;
+  pthread_t thread[MAX_THREADS];
+  struct job_thread_param
+  {
+    gcry_kdf_job_fn_t job;
+    void *priv;
+  } work[MAX_THREADS];
+};
+
+static void *
+job_thread (void *p)
+{
+  struct job_thread_param *param = p;
+  param->job (param->priv);
+  pthread_exit (NULL);
+}
+
+static int
+wait_all_jobs_completion (void *jobs_context);
+
+static int
+pthread_jobs_launch_job (void *jobs_context, gcry_kdf_job_fn_t job,
+                        void *job_priv)
+{
+  struct user_defined_threads_ctx *ctx = jobs_context;
+  int ret;
+
+  if (ctx->next_thread_idx == ctx->oldest_thread_idx)
+    {
+      assert (ctx->num_threads_running == MAX_THREADS);
+      /* thread limit reached, join a thread */
+      ret = pthread_join (ctx->thread[ctx->oldest_thread_idx], NULL);
+      if (ret)
+       return -1;
+      ctx->oldest_thread_idx = (ctx->oldest_thread_idx + 1) % MAX_THREADS;
+      ctx->num_threads_running--;
+    }
+
+  ctx->work[ctx->next_thread_idx].job = job;
+  ctx->work[ctx->next_thread_idx].priv = job_priv;
+  ret = pthread_create (&ctx->thread[ctx->next_thread_idx], &ctx->attr,
+                       job_thread, &ctx->work[ctx->next_thread_idx]);
+  if (ret)
+    {
+      /* could not create new thread. */
+      (void)wait_all_jobs_completion (jobs_context);
+      return -1;
+    }
+
+  if (ctx->oldest_thread_idx < 0)
+    ctx->oldest_thread_idx = ctx->next_thread_idx;
+  ctx->next_thread_idx = (ctx->next_thread_idx + 1) % MAX_THREADS;
+  ctx->num_threads_running++;
+  return 0;
+}
+
+static int
+wait_all_jobs_completion (void *jobs_context)
+{
+  struct user_defined_threads_ctx *ctx = jobs_context;
+  int i, idx;
+  int ret;
+
+  for (i = 0; i < ctx->num_threads_running; i++)
+    {
+      idx = (ctx->oldest_thread_idx + i) % MAX_THREADS;
+      ret = pthread_join (ctx->thread[idx], NULL);
+      if (ret)
+       return -1;
+    }
+
+  /* reset context for next round of parallel work */
+  ctx->num_threads_running = 0;
+  ctx->oldest_thread_idx = -1;
+  ctx->next_thread_idx = 0;
+
+  return 0;
+}
+#endif
+
+static gcry_error_t
+my_kdf_derive (int parallel,
+               int algo, int subalgo,
+               const unsigned long *params, unsigned int paramslen,
+               const unsigned char *pass, size_t passlen,
+               const unsigned char *salt, size_t saltlen,
+               const unsigned char *key, size_t keylen,
+               const unsigned char *ad, size_t adlen,
+               size_t outlen, unsigned char *out)
+{
+  gcry_error_t err;
+  gcry_kdf_hd_t hd;
+
+  (void)parallel;
+
+  err = gcry_kdf_open (&hd, algo, subalgo, params, paramslen,
+                       pass, passlen, salt, saltlen, key, keylen,
+                       ad, adlen);
+  if (err)
+    return err;
+
+#ifdef HAVE_PTHREAD
+  if (parallel)
+    {
+      struct user_defined_threads_ctx jobs_context;
+      const gcry_kdf_thread_ops_t ops =
+      {
+        &jobs_context,
+        pthread_jobs_launch_job,
+        wait_all_jobs_completion
+      };
+
+      memset (&jobs_context, 0, sizeof (struct user_defined_threads_ctx));
+      jobs_context.oldest_thread_idx = -1;
+
+      if (pthread_attr_init (&jobs_context.attr))
+       {
+          err = gpg_error_from_syserror ();
+         gcry_kdf_close (hd);
+         return err;
+       }
+
+      if (pthread_attr_setdetachstate (&jobs_context.attr,
+                                       PTHREAD_CREATE_JOINABLE))
+       {
+          err = gpg_error_from_syserror ();
+         pthread_attr_destroy (&jobs_context.attr);
+         gcry_kdf_close (hd);
+         return err;
+       }
+
+      err = gcry_kdf_compute (hd, &ops);
+
+      pthread_attr_destroy (&jobs_context. attr);
+    }
+  else
+#endif
+    {
+      err = gcry_kdf_compute (hd, NULL);
+    }
+
+  if (!err)
+    err = gcry_kdf_final (hd, outlen, out);
+
+  gcry_kdf_close (hd);
+  return err;
+}
+
+
+static void
+check_argon2 (void)
+{
+  gcry_error_t err;
+  const unsigned long param[4] = { 32, 3, 32, 4 };
+  const unsigned char pass[32] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+  };
+  const unsigned char salt[16] = {
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  };
+  const unsigned char key[8] = { 3, 3, 3, 3, 3, 3, 3, 3 };
+  const unsigned char ad[12] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
+  unsigned char out[32];
+  unsigned char expected[3][32] = {
+    {  /* GCRY_KDF_ARGON2D */
+      0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97,
+      0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94,
+      0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1,
+      0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb
+    },
+    { /* GCRY_KDF_ARGON2I */
+      0xc8, 0x14, 0xd9, 0xd1, 0xdc, 0x7f, 0x37, 0xaa,
+      0x13, 0xf0, 0xd7, 0x7f, 0x24, 0x94, 0xbd, 0xa1,
+      0xc8, 0xde, 0x6b, 0x01, 0x6d, 0xd3, 0x88, 0xd2,
+      0x99, 0x52, 0xa4, 0xc4, 0x67, 0x2b, 0x6c, 0xe8
+    },
+    { /* GCRY_KDF_ARGON2ID */
+      0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c,
+      0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9,
+      0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e,
+      0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59
+    }
+  };
+  int i;
+  int subalgo = GCRY_KDF_ARGON2D;
+  int count = 0;
+
+ again:
+
+  if (verbose)
+    fprintf (stderr, "checking ARGON2 test vector %d\n", count);
+
+  err = my_kdf_derive (0,
+                       GCRY_KDF_ARGON2, subalgo, param, 4,
+                       pass, 32, salt, 16, key, 8, ad, 12,
+                       32, out);
+  if (err)
+    fail ("argon2 test %d failed: %s\n", 0, gpg_strerror (err));
+  else if (memcmp (out, expected[count], 32))
+    {
+      fail ("argon2 test %d failed: mismatch\n", 0);
+      fputs ("got:", stderr);
+      for (i=0; i < 32; i++)
+        fprintf (stderr, " %02x", out[i]);
+      putc ('\n', stderr);
+    }
+
+#ifdef HAVE_PTHREAD
+  err = my_kdf_derive (1,
+                       GCRY_KDF_ARGON2, subalgo, param, 4,
+                       pass, 32, salt, 16, key, 8, ad, 12,
+                       32, out);
+  if (err)
+    fail ("argon2 test %d failed: %s\n", 1, gpg_strerror (err));
+  else if (memcmp (out, expected[count], 32))
+    {
+      fail ("argon2 test %d failed: mismatch\n", 1);
+      fputs ("got:", stderr);
+      for (i=0; i < 32; i++)
+        fprintf (stderr, " %02x", out[i]);
+      putc ('\n', stderr);
+    }
+#endif
+
+  /* Next algo */
+  if (subalgo == GCRY_KDF_ARGON2D)
+    subalgo = GCRY_KDF_ARGON2I;
+  else if (subalgo == GCRY_KDF_ARGON2I)
+    subalgo = GCRY_KDF_ARGON2ID;
+
+  count++;
+  if (count < 3)
+    goto again;
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -1274,10 +1549,15 @@ main (int argc, char **argv)
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
+  if (!in_fips_mode)
+    xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
 
   if (s2kcount)
     bench_s2k (s2kcount);
@@ -1286,6 +1566,7 @@ main (int argc, char **argv)
       check_openpgp ();
       check_pbkdf2 ();
       check_scrypt ();
+      check_argon2 ();
     }
 
   return error_count ? 1 : 0;
index 7e5732e..cacc383 100644 (file)
@@ -27,6 +27,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <unistd.h>
+#include <time.h>
 #if HAVE_PTHREAD
 # include <pthread.h>
 #endif
@@ -89,6 +90,7 @@ struct thread_arg_s
 
 
 \f
+#if defined(HAVE_PTHREAD) || defined(_WIN32)
 /* Wrapper functions to access Libgcrypt's internal test lock.  */
 static void
 external_lock_test_init (int line)
@@ -130,10 +132,11 @@ external_lock_test_destroy (int line)
   if (err)
     fail ("destroying lock failed at %d: %s", line, gpg_strerror (err));
 }
-
+#endif
 
 
 \f
+#if defined(HAVE_PTHREAD) || defined(_WIN32)
 /* The nonce thread.  We simply request a couple of nonces and
    return.  */
 static THREAD_RET_TYPE
@@ -153,6 +156,7 @@ nonce_thread (void *argarg)
   gcry_free (arg);
   return THREAD_RET_VALUE;
 }
+#endif
 
 
 /* To check our locking function we run several threads all accessing
@@ -208,7 +212,8 @@ check_nonce_lock (void)
       else
         info ("nonce thread %d has terminated", i);
     }
-
+#else
+  (void)arg;
 #endif /*!_WIN32*/
 }
 
@@ -248,6 +253,7 @@ print_accounts (void)
 }
 
 
+#if defined(HAVE_PTHREAD) || defined(_WIN32)
 /* Get a a random integer value in the range 0 to HIGH.  */
 static unsigned int
 get_rand (int high)
@@ -311,6 +317,7 @@ accountant_thread (void *arg)
     }
   return THREAD_RET_VALUE;
 }
+#endif
 
 
 static void
@@ -355,7 +362,8 @@ run_test (void)
     fail ("waiting for revision thread failed: %d", (int)GetLastError ());
   CloseHandle (rthread);
 
-#else /*!_WIN32*/
+  external_lock_test_destroy (__LINE__);
+#elif HAVE_PTHREAD
   pthread_t rthread;
   pthread_t athreads[N_ACCOUNTANTS];
   int rc, i;
@@ -384,9 +392,8 @@ run_test (void)
   else
     info ("revision thread has terminated");
 
-#endif /*!_WIN32*/
-
   external_lock_test_destroy (__LINE__);
+#endif /*!_WIN32*/
 }
 
 
@@ -426,18 +433,18 @@ main (int argc, char **argv)
         }
     }
 
-  srand (time(NULL)*getpid());
+  srand ((unsigned int)time(NULL)*getpid());
 
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch");
   /* We are using non-public interfaces - check the exact version.  */
   if (strcmp (gcry_check_version (NULL), GCRYPT_VERSION))
     die ("exact version match failed");
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
   check_nonce_lock ();
 
index 91116ca..b66809f 100644 (file)
@@ -340,12 +340,12 @@ main (int argc, char **argv)
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
 
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
   one_bit_only (0);
   one_bit_only (1);
index f2378bf..72d7fa9 100644 (file)
@@ -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.  */
@@ -748,23 +748,11 @@ basic_ec_math (void)
     gcry_mpi_ec_mul (Q, tmp, G, ctx);
     gcry_mpi_release (tmp);
     gcry_mpi_point_get (x, y, z, Q);
-    if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0)
-        || gcry_mpi_cmp_ui (z, 0))
+    if (gcry_mpi_cmp_ui (z, 0))
       fail ("multiply a point by zero failed\n");
   }
 
   gcry_mpi_ec_mul (Q, d, G, ctx);
-  gcry_mpi_point_get (x, y, z, Q);
-  if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
-      || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
-      || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
-    fail ("computed public key does not match\n");
-  if (debug)
-    {
-      print_mpi ("Q.x", x);
-      print_mpi ("Q.y", y);
-      print_mpi ("Q.z", z);
-    }
 
   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
     fail ("failed to get affine coordinates\n");
@@ -818,17 +806,6 @@ basic_ec_math_simplified (void)
   x = gcry_mpi_new (0);
   y = gcry_mpi_new (0);
   z = gcry_mpi_new (0);
-  gcry_mpi_point_get (x, y, z, Q);
-  if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
-      || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
-      || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
-    fail ("computed public key does not match\n");
-  if (debug)
-    {
-      print_mpi ("Q.x", x);
-      print_mpi ("Q.y", y);
-      print_mpi ("Q.z", z);
-    }
 
   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
     fail ("failed to get affine coordinates\n");
@@ -1310,6 +1287,3115 @@ 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"
+    },
+
+    /* 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;
+  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;
+            }
+          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);
+      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);
+    }
+}
+
+
+static void
+check_ec_mul_reduction (void)
+{
+  static struct
+  {
+    const char *curve;
+    const char *scalar;
+    const char *ux;
+    const char *uy;
+    const char *uz;
+    const char *qx;
+    const char *qy;
+  } tv[] =
+  {
+    /* --- NIST P-192 --- */
+
+    /* Bug report: https://dev.gnupg.org/T5510 */
+    {
+      "NIST P-192",
+      "0FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830",
+      "000000000000000000000000000000000FFFFFFFFFFFFFF00",
+      "030A893B61A4E76AF2B682FDB86E043C427C1AD2DFDABB62E",
+      NULL,
+      "000000000000000000000000000000000FFFFFFFFFFFFFF00",
+      "0CF576C49E5B18950D497D024791FBC3AD83E52D2025449D1"
+    },
+    {
+      "NIST P-192",
+      "0FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830",
+      "000000000000000000000000000000000FFFFFFFFFFFFFF00",
+      "0CF576C49E5B18950D497D024791FBC3AD83E52D2025449D1",
+      NULL,
+      "000000000000000000000000000000000FFFFFFFFFFFFFF00",
+      "030A893B61A4E76AF2B682FDB86E043C427C1AD2DFDABB62E"
+    },
+
+    /* Test #1 for NIST P-192 fast reduction */
+    {
+      "NIST P-192",
+      "09977FBFF49FFB1F115C20E3378819ACCFB2A2A19EF9D00C2",
+      "06D9D789820A2C19237C96AD4B8D86B87FB49D4D6C728B84F",
+      "0000000000000000000000000000000000000000000000001",
+      NULL,
+      "019298C549B3982415E831422E8FF991D25C589B214B3EC20",
+      "09CF5FFD92F0218F704E1F5D4F888FEB1AE5C09674428D9FE"
+    },
+    {
+      "NIST P-192",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCD",
+      "019298C549B3982415E831422E8FF991D25C589B214B3EC20",
+      "09CF5FFD92F0218F704E1F5D4F888FEB1AE5C09674428D9FE",
+      NULL,
+      "06D9D789820A2C19237C96AD4B8D86B87FB49D4D6C728B84F",
+      "0000000000000000000000000000000000000000000000001"
+    },
+
+    /* Test #2 for NIST P-192 fast reduction */
+    {
+      "NIST P-192",
+      "09977FBFF49FFB1F115C20E3378819ACCFB2A2A19EF9D00C2",
+      "03DA9DE5C6BFA357FDAD6F1B64479BFF526480BF1647D1DDE",
+      "0000000000000000000000000000000010000000000000001",
+      NULL,
+      "0FA56FFAE18551DEC7B10335F9E4D9844B11EEF9C3124B7CF",
+      "06EC4073A143832560600767FDDC0499A1721BE8C2DEE9B68"
+    },
+    {
+      "NIST P-192",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCD",
+      "0FA56FFAE18551DEC7B10335F9E4D9844B11EEF9C3124B7CF",
+      "06EC4073A143832560600767FDDC0499A1721BE8C2DEE9B68",
+      NULL,
+      "03DA9DE5C6BFA357FDAD6F1B64479BFF526480BF1647D1DDE",
+      "0000000000000000000000000000000010000000000000001"
+    },
+
+    /* Test #3 for NIST P-192 fast reduction */
+    {
+      "NIST P-192",
+      "09977FBFF49FFB1F115C20E3378819ACCFB2A2A19EF9D00C2",
+      "06D9D789820A2C19237C96AD4B8D86B87FB49D4D6C728B84F",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFE",
+      NULL,
+      "019298C549B3982415E831422E8FF991D25C589B214B3EC20",
+      "0630A0026D0FDE708FB1E0A2B0777014D51A3F698BBD72601"
+    },
+    {
+      "NIST P-192",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCD",
+      "019298C549B3982415E831422E8FF991D25C589B214B3EC20",
+      "0630A0026D0FDE708FB1E0A2B0777014D51A3F698BBD72601",
+      NULL,
+      "06D9D789820A2C19237C96AD4B8D86B87FB49D4D6C728B84F",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFE"
+    },
+
+    /* Test #4 for NIST P-192 fast reduction */
+    {
+      "NIST P-192",
+      "0FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830",
+      "06D9D789820A2C19237C96AD4B8D86B87FB49D4D6C728B84F",
+      "0000000000000000000000000000000000000000000000001",
+      NULL,
+      "06D9D789820A2C19237C96AD4B8D86B87FB49D4D6C728B84F",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFE"
+    },
+    {
+      "NIST P-192",
+      "0FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830",
+      "06D9D789820A2C19237C96AD4B8D86B87FB49D4D6C728B84F",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFE",
+      NULL,
+      "06D9D789820A2C19237C96AD4B8D86B87FB49D4D6C728B84F",
+      "0000000000000000000000000000000000000000000000001"
+    },
+
+    /* --- NIST P-224 --- */
+
+    /* Test #1 for NIST P-224 fast reduction */
+    {
+      "NIST P-224",
+      "05793BE916A89FC5475A3267BE6F3530901AEC6010E8C2EA2D79F9EE8",
+      "03B5889352DDF7468BF8C0729212AA1B2A3FCB1A844B8BE91ABB753D5",
+      "000000000000000000000000000000000000000000000000000000001",
+      NULL,
+      "0B5457C849D65FBA90C724C9528F500C10930B744F1ECFF60015238D7",
+      "05BBF4A452ADCAFB15484C0E3AAEBF37153543DA0785EBB61A8F2A1B9"
+    },
+    {
+      "NIST P-224",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF012345",
+      "0B5457C849D65FBA90C724C9528F500C10930B744F1ECFF60015238D7",
+      "05BBF4A452ADCAFB15484C0E3AAEBF37153543DA0785EBB61A8F2A1B9",
+      NULL,
+      "03B5889352DDF7468BF8C0729212AA1B2A3FCB1A844B8BE91ABB753D5",
+      "000000000000000000000000000000000000000000000000000000001"
+    },
+
+    /* Test #2 for NIST P-224 fast reduction */
+    {
+      "NIST P-224",
+      "05793BE916A89FC5475A3267BE6F3530901AEC6010E8C2EA2D79F9EE8",
+      "02FEB134F401D499197917C3470242239093606F5B8EA463A763C3AC4",
+      "0C0000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+      NULL,
+      "0384BD56C5E3FA9C109C841485CCB0B8C90FB5928A87388A658E164AA",
+      "04701B697F333FD522787DF61F3CDB3F964FF43F288858BC4524CA3CD"
+    },
+    {
+      "NIST P-224",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF012345",
+      "0384BD56C5E3FA9C109C841485CCB0B8C90FB5928A87388A658E164AA",
+      "04701B697F333FD522787DF61F3CDB3F964FF43F288858BC4524CA3CD",
+      NULL,
+      "02FEB134F401D499197917C3470242239093606F5B8EA463A763C3AC4",
+      "0C0000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"
+    },
+
+    /* Test #3 for NIST P-224 fast reduction */
+    {
+      "NIST P-224",
+      "05793BE916A89FC5475A3267BE6F3530901AEC6010E8C2EA2D79F9EE8",
+      "03B5889352DDF7468BF8C0729212AA1B2A3FCB1A844B8BE91ABB753D5",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000",
+      NULL,
+      "0B5457C849D65FBA90C724C9528F500C10930B744F1ECFF60015238D7",
+      "0A440B5BAD523504EAB7B3F1C55140C8DACABC25F87A1449E570D5E48"
+    },
+    {
+      "NIST P-224",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF012345",
+      "0B5457C849D65FBA90C724C9528F500C10930B744F1ECFF60015238D7",
+      "0A440B5BAD523504EAB7B3F1C55140C8DACABC25F87A1449E570D5E48",
+      NULL,
+      "03B5889352DDF7468BF8C0729212AA1B2A3FCB1A844B8BE91ABB753D5",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000"
+    },
+
+    /* Test #4 for NIST P-224 fast reduction */
+    {
+      "NIST P-224",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3C",
+      "03B5889352DDF7468BF8C0729212AA1B2A3FCB1A844B8BE91ABB753D5",
+      "000000000000000000000000000000000000000000000000000000001",
+      NULL,
+      "03B5889352DDF7468BF8C0729212AA1B2A3FCB1A844B8BE91ABB753D5",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000"
+    },
+    {
+      "NIST P-224",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3C",
+      "03B5889352DDF7468BF8C0729212AA1B2A3FCB1A844B8BE91ABB753D5",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000",
+      NULL,
+      "03B5889352DDF7468BF8C0729212AA1B2A3FCB1A844B8BE91ABB753D5",
+      "000000000000000000000000000000000000000000000000000000001"
+    },
+
+    /* --- NIST P-256 --- */
+
+    /* Bug report: https://dev.gnupg.org/T5510 */
+    {
+      "NIST P-256",
+      "00000000000FF0000000400000000000000000000005D00003277002000010000",
+      "00000FFFFFFFF0000000000000000000000000000000000000000000000000000",
+      "0CFE26D107A5134D6FEB38CE3577075BDC7AA70FF7523D3B203C8A973F2D3DC8E",
+      NULL,
+      "0FD351B304AD50F36153D8193C4BBF7D4C3BEE26E5AF52A9C70133EDFA62C273E",
+      "005DA8312615436E9C81B5B0624E68667233ACE6307AFC8056EAE85049CA63226"
+    },
+    {
+      "NIST P-256",
+      "096D8332E8F1265354CB7D213EF7809BA2D9639DFA634F321420C238CD2ED1830",
+      "0FD351B304AD50F36153D8193C4BBF7D4C3BEE26E5AF52A9C70133EDFA62C273E",
+      "005DA8312615436E9C81B5B0624E68667233ACE6307AFC8056EAE85049CA63226",
+      NULL,
+      "00000FFFFFFFF0000000000000000000000000000000000000000000000000000",
+      "0CFE26D107A5134D6FEB38CE3577075BDC7AA70FF7523D3B203C8A973F2D3DC8E"
+    },
+
+    /* Bug report: https://dev.gnupg.org/T5510 */
+    {
+      "NIST P-256",
+      "02020FF2020202020202020202020202020202020202020202020202020202020",
+      "0555555FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+      "073A865E2E128733884FB82CE625ADE822F7D8A59A4DCC09266966CF1BF082856",
+      NULL,
+      "05549408909DD3E772D7D669F8FBA2248D334B54BE3D18833223D944A328948C7",
+      "06198AC3B29712256DCD9CE1A09471F04267684E1EDD45910D61D0B7847DB2D58"
+    },
+
+    /* Test #1 for NIST P-256 fast reduction */
+    {
+      "NIST P-256",
+      "0F14DE6DA4CBA6F4C7B7E988EEF4D168088B6300BAB207054AA24E6D3019D5A23",
+      "08D0177EBAB9C6E9E10DB6DD095DBAC0D6375E8A97B70F611875D877F0069D2C7",
+      "00000000000000000000000000000000000000000000000000000000000000001",
+      NULL,
+      "0688856989B61877BC62ED4D2EE8E0FCA4588D90C2F9A282FA4AD6ACCFBAA95DF",
+      "0D2B9F7FA3982EE114FBBA108E132CECB5A605520661B3C4F7CF2906714B400E2"
+    },
+    {
+      "NIST P-256",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC",
+      "0688856989B61877BC62ED4D2EE8E0FCA4588D90C2F9A282FA4AD6ACCFBAA95DF",
+      "0D2B9F7FA3982EE114FBBA108E132CECB5A605520661B3C4F7CF2906714B400E2",
+      NULL,
+      "08D0177EBAB9C6E9E10DB6DD095DBAC0D6375E8A97B70F611875D877F0069D2C7",
+      "00000000000000000000000000000000000000000000000000000000000000001"
+    },
+
+    /* Test #2 for NIST P-256 fast reduction */
+    {
+      "NIST P-256",
+      "0F14DE6DA4CBA6F4C7B7E988EEF4D168088B6300BAB207054AA24E6D3019D5A23",
+      "0F650B5048E7DE9587399E64274C008A4CA0992BA29DC05F7E51243D34C2949EC",
+      "0FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+      NULL,
+      "0BEF9CCBF964B86724C97CF35D3890CAB3E9802EDAD1A3D9070695FD04C640087",
+      "0E540F49BAC4AA879B7A1D7C40CE03F7097A910B77F098DA2F7C441407BAD119B"
+    },
+    {
+      "NIST P-256",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC",
+      "0BEF9CCBF964B86724C97CF35D3890CAB3E9802EDAD1A3D9070695FD04C640087",
+      "0E540F49BAC4AA879B7A1D7C40CE03F7097A910B77F098DA2F7C441407BAD119B",
+      NULL,
+      "0F650B5048E7DE9587399E64274C008A4CA0992BA29DC05F7E51243D34C2949EC",
+      "0FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"
+    },
+
+    /* Test #3 for NIST P-256 fast reduction */
+    {
+      "NIST P-256",
+      "0F14DE6DA4CBA6F4C7B7E988EEF4D168088B6300BAB207054AA24E6D3019D5A23",
+      "08D0177EBAB9C6E9E10DB6DD095DBAC0D6375E8A97B70F611875D877F0069D2C7",
+      "0FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFE",
+      NULL,
+      "0688856989B61877BC62ED4D2EE8E0FCA4588D90C2F9A282FA4AD6ACCFBAA95DF",
+      "02D460804C67D11EFB0445EF71ECD3134A59FAAE099E4C3B0830D6F98EB4BFF1D"
+    },
+    {
+      "NIST P-256",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC",
+      "0688856989B61877BC62ED4D2EE8E0FCA4588D90C2F9A282FA4AD6ACCFBAA95DF",
+      "02D460804C67D11EFB0445EF71ECD3134A59FAAE099E4C3B0830D6F98EB4BFF1D",
+      NULL,
+      "08D0177EBAB9C6E9E10DB6DD095DBAC0D6375E8A97B70F611875D877F0069D2C7",
+      "0FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFE"
+    },
+
+    /* Test #4 for NIST P-256 fast reduction */
+    {
+      "NIST P-256",
+      "0FD1AEFA76594FC4D14169064B1AE89B2224AEB9F9C314E21BDCFEB5F2AFB3B81",
+      "0FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+      "0AFE89640E5A59FE8F69ADB58DB0059E522E5CC1D0CEDAB7AC6F8455F49AADED2",
+      NULL,
+      "0063257268860D4F13CFC6071CE09E3D1BD8B77B08A0714CFF42880F430A4F1CE",
+      "09665C75111B793CE3BF6E2BF45F9B55E065D22F93C4063A79DF8C9D139E83173"
+    },
+    {
+      "NIST P-256",
+      "0C0DE4C0FFEE1111C0DE4C0FFEE1111C0DE4C0FFEE1111C0DE4C0FFEE1111C0DE",
+      "0063257268860D4F13CFC6071CE09E3D1BD8B77B08A0714CFF42880F430A4F1CE",
+      "09665C75111B793CE3BF6E2BF45F9B55E065D22F93C4063A79DF8C9D139E83173",
+      NULL,
+      "0FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
+      "0AFE89640E5A59FE8F69ADB58DB0059E522E5CC1D0CEDAB7AC6F8455F49AADED2"
+    },
+
+    /* Test #5 for NIST P-256 fast reduction */
+    {
+      "NIST P-256",
+      "0FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550",
+      "08D0177EBAB9C6E9E10DB6DD095DBAC0D6375E8A97B70F611875D877F0069D2C7",
+      "00000000000000000000000000000000000000000000000000000000000000001",
+      NULL,
+      "08D0177EBAB9C6E9E10DB6DD095DBAC0D6375E8A97B70F611875D877F0069D2C7",
+      "0FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFE"
+    },
+    {
+      "NIST P-256",
+      "0FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550",
+      "08D0177EBAB9C6E9E10DB6DD095DBAC0D6375E8A97B70F611875D877F0069D2C7",
+      "0FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFE",
+      NULL,
+      "08D0177EBAB9C6E9E10DB6DD095DBAC0D6375E8A97B70F611875D877F0069D2C7",
+      "00000000000000000000000000000000000000000000000000000000000000001"
+    },
+
+    /* --- NIST P-384 --- */
+
+    /* Bug report: https://dev.gnupg.org/T5510 */
+    {
+      "NIST P-384",
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF"
+      "581A0DB248B0A77AECEC196ACCC52972",
+      "0000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000FFFFFFFFFFFFFFFFFFFFFC",
+      "1B0D6F8FB7F2DE5B8875645B64042AE20F119F3E1CFEFC0215857EEAE5F4A8FC"
+      "A737057D69A42C44D958E7CFCC77CE6B",
+      NULL,
+      "0000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000FFFFFFFFFFFFFFFFFFFFFC",
+      "E4F29070480D21A4778A9BA49BFBD51DF0EE60C1E30103FDEA7A81151A0B5702"
+      "58C8FA81965BD3BB26A7183133883194"
+    },
+    {
+      "NIST P-384",
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF"
+      "581A0DB248B0A77AECEC196ACCC52972",
+      "0000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000FFFFFFFFFFFFFFFFFFFFFC",
+      "E4F29070480D21A4778A9BA49BFBD51DF0EE60C1E30103FDEA7A81151A0B5702"
+      "58C8FA81965BD3BB26A7183133883194",
+      NULL,
+      "0000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000FFFFFFFFFFFFFFFFFFFFFC",
+      "1B0D6F8FB7F2DE5B8875645B64042AE20F119F3E1CFEFC0215857EEAE5F4A8FC"
+      "A737057D69A42C44D958E7CFCC77CE6B"
+    },
+
+    /* Test #1 for NIST P-384 fast reduction */
+    {
+      "NIST P-384",
+      "0739C89BDC9F071F1DC8391A52A0764EE0E15387DBB56E4FDAD647993F52C9121"
+      "D2DCE779834057EEAE390D113E337DDB",
+      "02261B2BF605C22F2F3AEF6338719B2C486388AD5240719A5257315969EF01BA2"
+      "7F0A104C89704773A81FDABEE6AB5C78",
+      "00000000000000000000000000000000000000000000000000000000000000000"
+      "00000000000000000000000000000001",
+      NULL,
+      "041CF9FB4C86482B7EC4850FB8AA31771D5F2D3944168B16D47C307468929A860"
+      "B21334F09C2F33AAA565E7190225C793",
+      "00512D4C3F17BA90EEDBCC74C7CBA4410A4F68C8FC0EFB9B981501B454F574744"
+      "8947DFC29E4BAEE30439A84D455627C6"
+    },
+    {
+      "NIST P-384",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC"
+      "DEF01234567890ABCDEF01234567890A",
+      "041CF9FB4C86482B7EC4850FB8AA31771D5F2D3944168B16D47C307468929A860"
+      "B21334F09C2F33AAA565E7190225C793",
+      "00512D4C3F17BA90EEDBCC74C7CBA4410A4F68C8FC0EFB9B981501B454F574744"
+      "8947DFC29E4BAEE30439A84D455627C6",
+      NULL,
+      "02261B2BF605C22F2F3AEF6338719B2C486388AD5240719A5257315969EF01BA2"
+      "7F0A104C89704773A81FDABEE6AB5C78",
+      "00000000000000000000000000000000000000000000000000000000000000000"
+      "00000000000000000000000000000001"
+    },
+
+    /* Test #2 for NIST P-384 fast reduction */
+    {
+      "NIST P-384",
+      "0739C89BDC9F071F1DC8391A52A0764EE0E15387DBB56E4FDAD647993F52C9121"
+      "D2DCE779834057EEAE390D113E337DDB",
+      "0C4A2DEA4D2A725EAEEFA6CA6FA301155510309F46EA1C70C909B988B49E1D612"
+      "468051EB758869259D1BF892E0A555C2",
+      "00000000000000000000000000000000000000000000000000000000000000001"
+      "00000000FFFFFFFFFFFFFFFF00000001",
+      NULL,
+      "0ED97AD545DB70C379C94BDA35926921F26FA9B9B338D32D8F2A163DBBEC5CFAF"
+      "600830D133A14C0B599B53E57D206DE2",
+      "069B72397B725CA8FA7A59173D4F588273C8303B5F6A5AFD8ACBD6B56CC7CCF32"
+      "B6FCE2DBB991DE4C6E9CCFAF21B8ECCF"
+    },
+    {
+      "NIST P-384",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC"
+      "DEF01234567890ABCDEF01234567890A",
+      "0ED97AD545DB70C379C94BDA35926921F26FA9B9B338D32D8F2A163DBBEC5CFAF"
+      "600830D133A14C0B599B53E57D206DE2",
+      "069B72397B725CA8FA7A59173D4F588273C8303B5F6A5AFD8ACBD6B56CC7CCF32"
+      "B6FCE2DBB991DE4C6E9CCFAF21B8ECCF",
+      NULL,
+      "0C4A2DEA4D2A725EAEEFA6CA6FA301155510309F46EA1C70C909B988B49E1D612"
+      "468051EB758869259D1BF892E0A555C2",
+      "00000000000000000000000000000000000000000000000000000000000000001"
+      "00000000FFFFFFFFFFFFFFFF00000001"
+    },
+
+    /* Test #3 for NIST P-384 fast reduction */
+    {
+      "NIST P-384",
+      "0739C89BDC9F071F1DC8391A52A0764EE0E15387DBB56E4FDAD647993F52C9121"
+      "D2DCE779834057EEAE390D113E337DDB",
+      "05ADE55A6BD4FA27FCA00D1C38653843E3E8421E018DFC7DDAD34076C4D41A621"
+      "980D62417D12330DAE5948C2C6D7D347",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFD",
+      NULL,
+      "0A85779C7427F50E92166268399F4ABEDDAA7B8866B0A495ED603BE80A8900786"
+      "DD287FF5C28708D039AF02DD1FC197CC",
+      "0CB97C2A5822A86B82DFE300E7F6278A087506A718EBD4FF317D7529581E98470"
+      "56FCE58652AA1B6D6FBB62851099A9FF"
+    },
+    {
+      "NIST P-384",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC"
+      "DEF01234567890ABCDEF01234567890A",
+      "0A85779C7427F50E92166268399F4ABEDDAA7B8866B0A495ED603BE80A8900786"
+      "DD287FF5C28708D039AF02DD1FC197CC",
+      "0CB97C2A5822A86B82DFE300E7F6278A087506A718EBD4FF317D7529581E98470"
+      "56FCE58652AA1B6D6FBB62851099A9FF",
+      NULL,
+      "05ADE55A6BD4FA27FCA00D1C38653843E3E8421E018DFC7DDAD34076C4D41A621"
+      "980D62417D12330DAE5948C2C6D7D347",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFD"
+    },
+
+    /* Test #4 for NIST P-384 fast reduction */
+    {
+      "NIST P-384",
+      "0739C89BDC9F071F1DC8391A52A0764EE0E15387DBB56E4FDAD647993F52C9121"
+      "D2DCE779834057EEAE390D113E337DDB",
+      "02261B2BF605C22F2F3AEF6338719B2C486388AD5240719A5257315969EF01BA2"
+      "7F0A104C89704773A81FDABEE6AB5C78",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFF0000000000000000FFFFFFFE",
+      NULL,
+      "041CF9FB4C86482B7EC4850FB8AA31771D5F2D3944168B16D47C307468929A860"
+      "B21334F09C2F33AAA565E7190225C793",
+      "0FAED2B3C0E8456F1124338B38345BBEF5B0973703F1046467EAFE4BAB0A8B8BA"
+      "76B8203C61B4511CFBC657B3BAA9D839"
+    },
+    {
+      "NIST P-384",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC"
+      "DEF01234567890ABCDEF01234567890A",
+      "041CF9FB4C86482B7EC4850FB8AA31771D5F2D3944168B16D47C307468929A860"
+      "B21334F09C2F33AAA565E7190225C793",
+      "0FAED2B3C0E8456F1124338B38345BBEF5B0973703F1046467EAFE4BAB0A8B8BA"
+      "76B8203C61B4511CFBC657B3BAA9D839",
+      NULL,
+      "02261B2BF605C22F2F3AEF6338719B2C486388AD5240719A5257315969EF01BA2"
+      "7F0A104C89704773A81FDABEE6AB5C78",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFF0000000000000000FFFFFFFE"
+    },
+
+    /* Test #5 for NIST P-384 fast reduction */
+    {
+      "NIST P-384",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF"
+      "581A0DB248B0A77AECEC196ACCC52972",
+      "02261B2BF605C22F2F3AEF6338719B2C486388AD5240719A5257315969EF01BA2"
+      "7F0A104C89704773A81FDABEE6AB5C78",
+      "0000000000000000000000000000000000000000000000000000000000000000"
+      "00000000000000000000000000000001",
+      NULL,
+      "02261B2BF605C22F2F3AEF6338719B2C486388AD5240719A5257315969EF01BA2"
+      "7F0A104C89704773A81FDABEE6AB5C78",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFF0000000000000000FFFFFFFE"
+    },
+    {
+      "NIST P-384",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF"
+      "581A0DB248B0A77AECEC196ACCC52972",
+      "02261B2BF605C22F2F3AEF6338719B2C486388AD5240719A5257315969EF01BA2"
+      "7F0A104C89704773A81FDABEE6AB5C78",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+      "FFFFFFFF0000000000000000FFFFFFFE",
+      NULL,
+      "02261B2BF605C22F2F3AEF6338719B2C486388AD5240719A5257315969EF01BA2"
+      "7F0A104C89704773A81FDABEE6AB5C78",
+      "0000000000000000000000000000000000000000000000000000000000000000"
+      "00000000000000000000000000000001",
+    },
+
+    /* --- NIST P-521 --- */
+
+    /* Test #1 for NIST P-521 fast reduction */
+    {
+      "NIST P-521",
+      "014395758AE77FEE059DA0B5ABC00C374ACA51984B95451C08AD8309DC8CEFB9F"
+      "0B7D03950131E54E63319D4592D679C1F8CFD610289F7B791D5C1C09B7BC5122195",
+      "00D9CB7A32DAB342F863EDB340F3EA61DDF833E755CE66BB1A918A42714BA05BC"
+      "DF4FF10994F616A9D80CD0B48B326E3A8A2A8F5634D824875B6E71FB7CDDD7B5018",
+      "00000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000000000000000000000000000000000000000000000000000000000001",
+      NULL,
+      "0091EC67F53DC1C752724942D6B94A3D66D91C16C997F42524400D3CD10074C07"
+      "FF6F7981A44292B25B478AE551DE980999404EC9221FD3FACE26C40FE783576EF1B",
+      "00534EE41FFDDCE7E171AF630593437896A4C0344900671D1886ED21EF61AC26D"
+      "A3DF4C6D7F1330B3EA25ABB6CA2127A605A650F2A6E916EAB757FE8B43116227FA1"
+    },
+    {
+      "NIST P-521",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC"
+      "DEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890AB",
+      "0091EC67F53DC1C752724942D6B94A3D66D91C16C997F42524400D3CD10074C07"
+      "FF6F7981A44292B25B478AE551DE980999404EC9221FD3FACE26C40FE783576EF1B",
+      "00534EE41FFDDCE7E171AF630593437896A4C0344900671D1886ED21EF61AC26D"
+      "A3DF4C6D7F1330B3EA25ABB6CA2127A605A650F2A6E916EAB757FE8B43116227FA1",
+      NULL,
+      "00D9CB7A32DAB342F863EDB340F3EA61DDF833E755CE66BB1A918A42714BA05BC"
+      "DF4FF10994F616A9D80CD0B48B326E3A8A2A8F5634D824875B6E71FB7CDDD7B5018",
+      "00000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000000000000000000000000000000000000000000000000000000000001"
+    },
+
+    /* Test #2 for NIST P-521 fast reduction */
+    {
+      "NIST P-521",
+      "014395758AE77FEE059DA0B5ABC00C374ACA51984B95451C08AD8309DC8CEFB9F"
+      "0B7D03950131E54E63319D4592D679C1F8CFD610289F7B791D5C1C09B7BC5122195",
+      "01A255D0D3B19B08BE171002C6D73096CA0E41498E805ABF61016EBF1A41E8018"
+      "D5F876D2870BFF35AA254BE8D6A303A79C4E4A3427AA4BDF8EE59DCAC22F4C83CD6",
+      "01000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000000000000000000000000000000000000000000000000000000000003",
+      NULL,
+      "00CEA3C8CE463F76789E7B0FCBEE5253E64BFA0FCBE101944CEFFC04D1786FF88"
+      "C9EC5650BFAC13D4037C34064E6E0CE00AA666EAC026F7EE4CE6F7805A10AD9C743",
+      "01F2D67A2DD50C916C48011BEE7BADFA488CD8C4F8BD69064C8BB454579E7B2FB"
+      "EDE9B52418239251C5B81638970916D1B3CACD25487927978CE7B0CD2A25916F9FE"
+    },
+    {
+      "NIST P-521",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC"
+      "DEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890AB",
+      "00CEA3C8CE463F76789E7B0FCBEE5253E64BFA0FCBE101944CEFFC04D1786FF88"
+      "C9EC5650BFAC13D4037C34064E6E0CE00AA666EAC026F7EE4CE6F7805A10AD9C743",
+      "01F2D67A2DD50C916C48011BEE7BADFA488CD8C4F8BD69064C8BB454579E7B2FB"
+      "EDE9B52418239251C5B81638970916D1B3CACD25487927978CE7B0CD2A25916F9FE",
+      NULL,
+      "01A255D0D3B19B08BE171002C6D73096CA0E41498E805ABF61016EBF1A41E8018"
+      "D5F876D2870BFF35AA254BE8D6A303A79C4E4A3427AA4BDF8EE59DCAC22F4C83CD6",
+      "01000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000000000000000000000000000000000000000000000000000000000003"
+    },
+
+    /* Test #3 for NIST P-521 fast reduction */
+    {
+      "NIST P-521",
+      "014395758AE77FEE059DA0B5ABC00C374ACA51984B95451C08AD8309DC8CEFB9F"
+      "0B7D03950131E54E63319D4592D679C1F8CFD610289F7B791D5C1C09B7BC5122195",
+      "00D9CB7A32DAB342F863EDB340F3EA61DDF833E755CE66BB1A918A42714BA05BC"
+      "DF4FF10994F616A9D80CD0B48B326E3A8A2A8F5634D824875B6E71FB7CDDD7B5018",
+      "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE",
+      NULL,
+      "0091EC67F53DC1C752724942D6B94A3D66D91C16C997F42524400D3CD10074C07"
+      "FF6F7981A44292B25B478AE551DE980999404EC9221FD3FACE26C40FE783576EF1B",
+      "01ACB11BE00223181E8E509CFA6CBC87695B3FCBB6FF98E2E77912DE109E53D92"
+      "5C20B39280ECCF4C15DA544935DED859FA59AF0D5916E91548A80174BCEE9DD805E"
+    },
+    {
+      "NIST P-521",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC"
+      "DEF01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890AB",
+      "0091EC67F53DC1C752724942D6B94A3D66D91C16C997F42524400D3CD10074C07"
+      "FF6F7981A44292B25B478AE551DE980999404EC9221FD3FACE26C40FE783576EF1B",
+      "01ACB11BE00223181E8E509CFA6CBC87695B3FCBB6FF98E2E77912DE109E53D92"
+      "5C20B39280ECCF4C15DA544935DED859FA59AF0D5916E91548A80174BCEE9DD805E",
+      NULL,
+      "00D9CB7A32DAB342F863EDB340F3EA61DDF833E755CE66BB1A918A42714BA05BC"
+      "DF4FF10994F616A9D80CD0B48B326E3A8A2A8F5634D824875B6E71FB7CDDD7B5018",
+      "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+    },
+
+    /* Test #4 for NIST P-521 fast reduction */
+    {
+      "NIST P-521",
+      "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+      "FFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386408",
+      "00D9CB7A32DAB342F863EDB340F3EA61DDF833E755CE66BB1A918A42714BA05BC"
+      "DF4FF10994F616A9D80CD0B48B326E3A8A2A8F5634D824875B6E71FB7CDDD7B5018",
+      "00000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000000000000000000000000000000000000000000000000000000000001",
+      NULL,
+      "00D9CB7A32DAB342F863EDB340F3EA61DDF833E755CE66BB1A918A42714BA05BC"
+      "DF4FF10994F616A9D80CD0B48B326E3A8A2A8F5634D824875B6E71FB7CDDD7B5018",
+      "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
+    },
+    {
+      "NIST P-521",
+      "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+      "FFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386408",
+      "00D9CB7A32DAB342F863EDB340F3EA61DDF833E755CE66BB1A918A42714BA05BC"
+      "DF4FF10994F616A9D80CD0B48B326E3A8A2A8F5634D824875B6E71FB7CDDD7B5018",
+      "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+      "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE",
+      NULL,
+      "00D9CB7A32DAB342F863EDB340F3EA61DDF833E755CE66BB1A918A42714BA05BC"
+      "DF4FF10994F616A9D80CD0B48B326E3A8A2A8F5634D824875B6E71FB7CDDD7B5018",
+      "00000000000000000000000000000000000000000000000000000000000000000"
+      "0000000000000000000000000000000000000000000000000000000000000000001"
+    },
+
+    /* --- secp256k1 --- */
+
+    /* Test #1 for secp256k1 fast reduction */
+    {
+      "secp256k1",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140",
+      "0CBB0DEAB125754F1FDB2038B0434ED9CB3FB53AB735391129994A535D925F673",
+      "00000000000000000000000000000000000000000000000000000000000000001",
+      NULL,
+      "0CBB0DEAB125754F1FDB2038B0434ED9CB3FB53AB735391129994A535D925F673",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"
+    },
+    {
+      "secp256k1",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140",
+      "0CBB0DEAB125754F1FDB2038B0434ED9CB3FB53AB735391129994A535D925F673",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E",
+      NULL,
+      "0CBB0DEAB125754F1FDB2038B0434ED9CB3FB53AB735391129994A535D925F673",
+      "00000000000000000000000000000000000000000000000000000000000000001"
+    },
+
+    /* Test #2 for secp256k1 fast reduction */
+    {
+      "secp256k1",
+      "0D1C9BD73010C07E357CBBD709520D081A5423846B5860C97ED2553F765A8475A",
+      "0CBB0DEAB125754F1FDB2038B0434ED9CB3FB53AB735391129994A535D925F673",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E",
+      NULL,
+      "0AC71D7AB263AAD9929E3324B857C31FF3FF3E90571C8BE45AB7D5833B1A19533",
+      "0CA4B80E756494A1897628246243770B3BE1AD0EEE79581D8C8EE80F053CBB44A"
+    },
+    {
+      "secp256k1",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC",
+      "0AC71D7AB263AAD9929E3324B857C31FF3FF3E90571C8BE45AB7D5833B1A19533",
+      "0CA4B80E756494A1897628246243770B3BE1AD0EEE79581D8C8EE80F053CBB44A",
+      NULL,
+      "0CBB0DEAB125754F1FDB2038B0434ED9CB3FB53AB735391129994A535D925F673",
+      "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E"
+    },
+
+    /* Test #3 for secp256k1 fast reduction */
+    {
+      "secp256k1",
+      "0D1C9BD73010C07E357CBBD709520D081A5423846B5860C97ED2553F765A8475A",
+      "0A7E45D967E07558AE405F7F571ADD1ACF966F3619FD4F2A9708EEB766B98F423",
+      "080000000000000000000000000000000000000000000000000000001000003D1",
+      NULL,
+      "0173E9E40BA3CCD35E4393C219A15C375783112C4C965C70BC043E8B17A342E79",
+      "0AAA2D3810F2BB72D06FF8CA3B19027F4450CC73C0338F6379D6006CC239B1CD6"
+    },
+    {
+      "secp256k1",
+      "01234567890ABCDEF01234567890ABCDEF01234567890ABCDEF01234567890ABC",
+      "0173E9E40BA3CCD35E4393C219A15C375783112C4C965C70BC043E8B17A342E79",
+      "0AAA2D3810F2BB72D06FF8CA3B19027F4450CC73C0338F6379D6006CC239B1CD6",
+      NULL,
+      "0A7E45D967E07558AE405F7F571ADD1ACF966F3619FD4F2A9708EEB766B98F423",
+      "080000000000000000000000000000000000000000000000000000001000003D1"
+    },
+
+    { NULL, NULL, NULL, NULL, NULL, NULL }
+  };
+  gpg_error_t err;
+  gcry_ctx_t ctx;
+  gcry_mpi_t scalar, ux, uy, uz, x, y;
+  gcry_mpi_point_t U, 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;
+            }
+          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);
+      if (err)
+        {
+          fail ("tv[%d].'%s': can't create context: %s\n",
+               idx, tv[idx].curve, gpg_strerror (err));
+          return;
+        }
+
+      if (tv[idx].ux)
+       ux = hex2mpi (tv[idx].ux);
+      else
+       die ("tv[%d].'%s': missing 'ux'\n", idx, tv[idx].curve);
+
+      if (tv[idx].uy)
+       uy = hex2mpi (tv[idx].uy);
+      else
+       die ("tv[%d].'%s': missing 'uy'\n", idx, tv[idx].curve);
+
+      if (tv[idx].uz)
+       uz = hex2mpi (tv[idx].uz);
+      else
+       uz = gcry_mpi_set_ui(NULL, 1);
+
+      if (tv[idx].scalar)
+       scalar = hex2mpi (tv[idx].scalar);
+      else
+       die ("tv[%d].'%s': missing 'scalar'\n", idx, tv[idx].curve);
+
+      U = gcry_mpi_point_new (0);
+      gcry_mpi_point_set (U, ux, uy, uz);
+      Q = gcry_mpi_point_new (0);
+      x = gcry_mpi_new (0);
+      y = gcry_mpi_new (0);
+
+      if (!gcry_mpi_ec_curve_point (U, ctx))
+        {
+          print_point ("  U", U);
+         die ("tv[%d].'%s': point expected on curve but not "
+              "identified as such\n", idx, tv[idx].curve);
+        }
+
+      gcry_mpi_ec_mul (Q, scalar, U, ctx);
+
+      if (!gcry_mpi_ec_curve_point (Q, ctx))
+        {
+          print_point ("  Q", Q);
+         die ("tv[%d].'%s': point expected on curve but not "
+              "identified as such\n", idx, tv[idx].curve);
+        }
+
+      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 ((tv[idx].qx != NULL && tv[idx].qy != NULL)
+         && (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 ("     scalar", scalar);
+         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 (uy);
+      gcry_mpi_release (ux);
+      gcry_mpi_release (uz);
+      gcry_mpi_release (scalar);
+      gcry_mpi_release (y);
+      gcry_mpi_release (x);
+      gcry_mpi_point_release (Q);
+      gcry_mpi_point_release (U);
+      gcry_ctx_release (ctx);
+    }
+}
+
+
 int
 main (int argc, char **argv)
 {
@@ -1322,17 +4408,19 @@ main (int argc, char **argv)
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch\n");
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
 
   set_get_point ();
   context_alloc ();
   context_param ();
   basic_ec_math ();
   point_on_curve ();
+  check_ec_mul ();
+  check_ec_mul_reduction ();
 
   /* The tests are for P-192 and ed25519 which are not supported in
      FIPS mode.  */
diff --git a/tests/t-rsa-15.c b/tests/t-rsa-15.c
new file mode 100644 (file)
index 0000000..67dbd2c
--- /dev/null
@@ -0,0 +1,478 @@
+/* t-rsa-15.c - Check the RSA PKCS#1 Ver1.5 crypto
+ * Copyright (C) 2021 g10 Code GmbH
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "stopwatch.h"
+
+#define PGM "t-rsa-15"
+#include "t-common.h"
+#define N_TESTS 120
+
+static int no_verify;
+static int custom_data_file;
+static int in_fips_mode;
+
+
+static void
+show_note (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!verbose && getenv ("srcdir"))
+    fputs ("      ", stderr);  /* To align above "PASS: ".  */
+  else
+    fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+  va_end (arg_ptr);
+}
+
+
+/* Prepend FNAME with the srcdir environment variable's value and
+ * return an allocated filename.  */
+char *
+prepend_srcdir (const char *fname)
+{
+  static const char *srcdir;
+  char *result;
+
+  if (!srcdir && !(srcdir = getenv ("srcdir")))
+    srcdir = ".";
+
+  result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
+  strcpy (result, srcdir);
+  strcat (result, "/");
+  strcat (result, fname);
+  return result;
+}
+
+
+/* Read next line but skip over empty and comment lines.  Caller must
+   xfree the result.  */
+static char *
+read_textline (FILE *fp, int *lineno)
+{
+  char line[4096];
+  char *p;
+
+  do
+    {
+      if (!fgets (line, sizeof line, fp))
+        {
+          if (feof (fp))
+            return NULL;
+          die ("error reading input line: %s\n", strerror (errno));
+        }
+      ++*lineno;
+      p = strchr (line, '\n');
+      if (!p)
+        die ("input line %d not terminated or too long\n", *lineno);
+      *p = 0;
+      for (p--;p > line && my_isascii (*p) && isspace (*p); p--)
+        *p = 0;
+    }
+  while (!*line || *line == '#');
+  /* if (debug) */
+  /*   info ("read line: '%s'\n", line); */
+  return xstrdup (line);
+}
+
+
+/* Copy the data after the tag to BUFFER.  BUFFER will be allocated as
+   needed.  */
+static void
+copy_data (char **buffer, const char *line, int lineno)
+{
+  const char *s;
+
+  xfree (*buffer);
+  *buffer = NULL;
+
+  s = strchr (line, '=');
+  if (!s)
+    {
+      fail ("syntax error at input line %d", lineno);
+      return;
+    }
+  for (s++; my_isascii (*s) && isspace (*s); s++)
+    ;
+  *buffer = xstrdup (s);
+}
+
+
+/* Convert STRING consisting of hex characters into its binary
+   representation and return it as an allocated buffer. The valid
+   length of the buffer is returned at R_LENGTH.  The string is
+   delimited by end of string.  The function returns NULL on
+   error.  */
+static void *
+hex2buffer (const char *string, size_t *r_length)
+{
+  const char *s;
+  unsigned char *buffer;
+  size_t length;
+
+  buffer = xmalloc (strlen(string)/2+1);
+  length = 0;
+  for (s=string; *s; s +=2 )
+    {
+      if (!hexdigitp (s) || !hexdigitp (s+1))
+        return NULL;           /* Invalid hex digits. */
+      ((unsigned char*)buffer)[length++] = xtoi_2 (s);
+    }
+  *r_length = length;
+  return buffer;
+}
+
+
+static void
+one_test_sexp (const char *n, const char *e, const char *d,
+               const char *sha_alg, const char *msg, const char *s)
+{
+  gpg_error_t err;
+  int i;
+  char *p;
+  void *buffer = NULL;
+  void *buffer2 = NULL;
+  void *buffer3 = NULL;
+  size_t buflen, buflen2, buflen3;
+  int md_algo;
+  const char *data_tmpl;
+  gcry_md_hd_t hd = NULL;
+  gcry_sexp_t s_pk = NULL;
+  gcry_sexp_t s_sk = NULL;
+  gcry_sexp_t s_sig= NULL;
+  gcry_sexp_t s_tmp, s_tmp2;
+  unsigned char *out = NULL;
+  size_t out_len = 0;
+  char *sig_string = NULL;
+
+  if (verbose > 1)
+    info ("Running test %s\n", sha_alg);
+
+  if (!strcmp (sha_alg, "SHA224"))
+    md_algo = GCRY_MD_SHA224;
+  else if (!strcmp (sha_alg, "SHA256"))
+    md_algo = GCRY_MD_SHA256;
+  else if (!strcmp (sha_alg, "SHA384"))
+    md_algo = GCRY_MD_SHA384;
+  else if (!strcmp (sha_alg, "SHA512"))
+    md_algo = GCRY_MD_SHA512;
+  else if (!strcmp (sha_alg, "SHA512224"))
+    md_algo = GCRY_MD_SHA512_224;
+  else if (!strcmp (sha_alg, "SHA512256"))
+    md_algo = GCRY_MD_SHA512_256;
+  else
+    {
+      fail ("error for test, %s: %s",
+            "d", "invalid hex string");
+      goto leave;
+    }
+
+  err = gcry_md_open (&hd, md_algo, 0);
+  if (err)
+    {
+      fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err));
+      return;
+    }
+
+  if (!(buffer = hex2buffer (n, &buflen)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "n", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer2 = hex2buffer (e, &buflen2)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "e", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer3 = hex2buffer (d, &buflen3)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "d", "invalid hex string");
+      goto leave;
+    }
+
+  err = gcry_sexp_build (&s_sk, NULL,
+                         "(private-key (rsa (n %b)(e %b)(d %b)))",
+                         (int)buflen, buffer,
+                         (int)buflen2, buffer2,
+                         (int)buflen3, buffer3);
+  if (err)
+    {
+      fail ("error building SEXP for test, %s: %s",
+            "sk", gpg_strerror (err));
+      goto leave;
+    }
+
+  err = gcry_sexp_build (&s_pk, NULL,
+                         "(public-key (rsa (n %b)(e %b)))",
+                         (int)buflen, buffer,
+                         (int)buflen2, buffer2);
+  if (err)
+    {
+      fail ("error building SEXP for test, %s: %s",
+            "pk", gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (buffer3);
+  buffer = buffer2 = buffer3 = NULL;
+
+  if (!(buffer = hex2buffer (msg, &buflen)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "msg", "invalid hex string");
+      goto leave;
+    }
+
+  gcry_md_write (hd, buffer, buflen);
+  xfree (buffer);
+  buffer = NULL;
+
+  data_tmpl = "(data(flags pkcs1)(hash %s %b))";
+  err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, NULL);
+  if (err)
+    {
+      fail ("gcry_pk_hash_sign failed: %s", gpg_strerror (err));
+      goto leave;
+    }
+
+  s_tmp2 = NULL;
+  s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
+  if (s_tmp)
+    {
+      s_tmp2 = s_tmp;
+      s_tmp = gcry_sexp_find_token (s_tmp2, "rsa", 0);
+      if (s_tmp)
+        {
+          gcry_sexp_release (s_tmp2);
+          s_tmp2 = s_tmp;
+          s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0);
+          if (s_tmp)
+            {
+              out = gcry_sexp_nth_buffer (s_tmp, 1, &out_len);
+              gcry_sexp_release (s_tmp);
+            }
+        }
+    }
+  gcry_sexp_release (s_tmp2);
+
+  sig_string = gcry_xmalloc (2*out_len+1);
+  p = sig_string;
+  *p = 0;
+  for (i=0; i < out_len; i++, p += 2)
+    snprintf (p, 3, "%02x", out[i]);
+  if (strcmp (sig_string, s))
+    {
+      fail ("gcry_pk_hash_sign failed: %s",
+            "wrong value returned");
+      info ("  expected: '%s'", s);
+      info ("       got: '%s'", sig_string);
+    }
+
+  if (!no_verify)
+    {
+      err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, NULL);
+      if (err)
+        fail ("gcry_pk_hash_verify failed for test: %s",
+              gpg_strerror (err));
+    }
+
+ leave:
+  gcry_sexp_release (s_sig);
+  gcry_sexp_release (s_sk);
+  gcry_sexp_release (s_pk);
+  if (hd)
+    gcry_md_close (hd);
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (buffer3);
+  xfree (out);
+  xfree (sig_string);
+}
+
+
+static void
+check_rsa_15 (const char *fname)
+{
+  FILE *fp;
+  int lineno, ntests;
+  char *line;
+  char *n, *e, *d;
+  char *sha_alg, *msg, *s;
+
+  info ("Checking RSA PKCS#1 Ver1.5.\n");
+
+  fp = fopen (fname, "r");
+  if (!fp)
+    die ("error opening '%s': %s\n", fname, strerror (errno));
+
+  n = e = d = NULL;
+  sha_alg = msg = s = NULL;
+  lineno = ntests = 0;
+  while ((line = read_textline (fp, &lineno)))
+    {
+      if (!strncmp (line, "[mod", 4))
+        /* Skip the annotation for modulus.  */
+        ;
+      else if (!strncmp (line, "n =", 3))
+        copy_data (&n, line, lineno);
+      else if (!strncmp (line, "e =", 3))
+        copy_data (&e, line, lineno);
+      else if (!strncmp (line, "d =", 3))
+        copy_data (&d, line, lineno);
+      else if (!strncmp (line, "SHAAlg =", 8))
+        copy_data (&sha_alg, line, lineno);
+      else if (!strncmp (line, "Msg =", 5))
+        copy_data (&msg, line, lineno);
+      else if (!strncmp (line, "S =", 3))
+        copy_data (&s, line, lineno);
+      else
+        fail ("unknown tag at input line %d", lineno);
+
+      xfree (line);
+      if (n && e && d && sha_alg && msg && s)
+        {
+          one_test_sexp (n, e, d, sha_alg, msg, s);
+          ntests++;
+          if (!(ntests % 256))
+            show_note ("%d of %d tests done\n", ntests, N_TESTS);
+          xfree (sha_alg);  sha_alg = NULL;
+          xfree (msg); msg = NULL;
+          xfree (s); s = NULL;
+        }
+
+    }
+  xfree (n);
+  xfree (e);
+  xfree (d);
+  xfree (sha_alg);
+  xfree (msg);
+  xfree (s);
+
+  if (ntests != N_TESTS && !custom_data_file)
+    fail ("did %d tests but expected %d", ntests, N_TESTS);
+  else if ((ntests % 256))
+    show_note ("%d tests done\n", ntests);
+
+  fclose (fp);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  char *fname = NULL;
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options]\n"
+                 "Options:\n"
+                 "  --verbose       print timings etc.\n"
+                 "  --debug         flyswatter\n"
+                 "  --no-verify     skip the verify test\n"
+                 "  --data FNAME    take test data from file FNAME\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--no-verify"))
+        {
+          no_verify = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--data"))
+        {
+          argc--; argv++;
+          if (argc)
+            {
+              xfree (fname);
+              fname = xstrdup (*argv);
+              argc--; argv++;
+            }
+        }
+      else if (!strncmp (*argv, "--", 2))
+        die ("unknown option '%s'", *argv);
+
+    }
+
+  if (!fname)
+    fname = prepend_srcdir ("t-rsa-15.inp");
+  else
+    custom_data_file = 1;
+
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  if (!gcry_check_version (GCRYPT_VERSION))
+    die ("version mismatch\n");
+  if (debug)
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
+  start_timer ();
+  check_rsa_15 (fname);
+  stop_timer ();
+
+  xfree (fname);
+
+  info ("All tests completed in %s.  Errors: %d\n",
+        elapsed_time (1), error_count);
+  return !!error_count;
+}
diff --git a/tests/t-rsa-15.inp b/tests/t-rsa-15.inp
new file mode 100644 (file)
index 0000000..a771d3e
--- /dev/null
@@ -0,0 +1,576 @@
+# CAVS 11.4
+# "SigGen PKCS#1 Ver1.5" information
+# Combinations selected:Mod Size 2048 with SHA-224 SHA-256 SHA-384 SHA-512; Mod Size 3072 with SHA-224 SHA-256 SHA-384 SHA-512
+
+
+[mod = 2048]
+
+n = cea80475324c1dc8347827818da58bac069d3419c614a6ea1ac6a3b510dcd72cc516954905e9fef908d45e13006adf27d467a7d83c111d1a5df15ef293771aefb920032a5bb989f8e4f5e1b05093d3f130f984c07a772a3683f4dc6fb28a96815b32123ccdd13954f19d5b8b24a103e771a34c328755c65ed64e1924ffd04d30b2142cc262f6e0048fef6dbc652f21479ea1c4b1d66d28f4d46ef7185e390cbfa2e02380582f3188bb94ebbf05d31487a09aff01fcbb4cd4bfd1f0a833b38c11813c84360bb53c7d4481031c40bad8713bb6b835cb08098ed15ba31ee4ba728a8c8e10f7294e1b4163b7aee57277bfd881a6f9d43e02c6925aa3a043fb7fb78d
+
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000260445
+d = 0997634c477c1a039d44c810b2aaa3c7862b0b88d3708272e1e15f66fc9389709f8a11f3ea6a5af7effa2d01c189c50f0d5bcbe3fa272e56cfc4a4e1d388a9dcd65df8628902556c8b6bb6a641709b5a35dd2622c73d4640bfa1359d0e76e1f219f8e33eb9bd0b59ec198eb2fccaae0346bd8b401e12e3c67cb629569c185a2e0f35a2f741644c1cca5ebb139d77a89a2953fc5e30048c0e619f07c8d21d1e56b8af07193d0fdf3f49cd49f2ef3138b5138862f1470bd2d16e34a2b9e7777a6c8c8d4cb94b4e8b5d616cd5393753e7b0f31cc7da559ba8e98d888914e334773baf498ad88d9631eb5fe32e53a4145bf0ba548bf2b0a50c63f67b14e398a34b0d
+
+
+SHAAlg = SHA224
+Msg = 74230447bcd492f2f8a8c594a04379271690bf0c8a13ddfc1b7b96413e77ab2664cba1acd7a3c57ee5276e27414f8283a6f93b73bd392bd541f07eb461a080bb667e5ff095c9319f575b3893977e658c6c001ceef88a37b7902d4db31c3e34f3c164c47bbeefde3b946bad416a752c2cafcee9e401ae08884e5b8aa839f9d0b5
+S = 27da4104eace1991e08bd8e7cfccd97ec48b896a0e156ce7bdc23fd570aaa9a00ed015101f0c6261c7371ceca327a73c3cecfcf6b2d9ed920c9698046e25c89adb2360887d99983bf632f9e6eb0e5df60715902b9aeaa74bf5027aa246510891c74ae366a16f397e2c8ccdc8bd56aa10e0d01585e69f8c4856e76b53acfd3d782b8171529008fa5eff030f46956704a3f5d9167348f37021fc277c6c0a8f93b8a23cfbf918990f982a56d0ed2aa08161560755adc0ce2c3e2ab2929f79bfc0b24ff3e0ff352e6445d8a617f1785d66c32295bb365d61cfb107e9993bbd93421f2d344a86e4127827fa0d0b2535f9b1d547de12ba2868acdecf2cb5f92a6a159a
+
+SHAAlg = SHA224
+Msg = 9af2c5a919e5dadc668799f365fc23da6231437ea51ca5314645425043851f23d00d3704eeabb5c43f49674a19b7707dd9aa3d657a04ba8c6655c5ab8ba2e382b26631080cd79ec40e6a587b7f99840bd0e43297ab1690e4cec95d031a2ca131e7049cfb9bf1fca67bf353cdc12cc74ceee80c5d61da8f0129a8f4a218abc3f6
+S = c5dfbefd35cec846e2c7b2434dc9c46a5a9b1b6ce65b2b18665aedb1404de1f466e024f849eec308c2d2f2f0193df1898a581c9ea32581185553b171b6507082617c5c018afe0c3af64d2ec5a563795aa585e77753cd18836f6f0c29535f6200ca899928fe78e949b0a216ec47a6adf2223e17236cfc167cf00ed6136f03cf6ffd4f3f7787aeb005840978d8d6ba593d4f4cfe6920be102b9847d10140dff86b0db14ffccc9a96e673c672c1128ae45489d2cbfe6e195ca5206eda519cad3d6e0abf4653e36b5a264e87494a4d63ee91ff7c35a6ab12adfa3bb537f6198b06f5de0717076b0ec83ae0da9ea419cc0c96669d1d7c9e529271428401e09e04888a
+
+SHAAlg = SHA224
+Msg = 59b5b85b9dc246d30a3fc8a2de3c9dfa971643b0c1f7c9e40c9c87e4a15b0c4eb664587560474c06a9b65eece38c91703c0fa5a592728a03889f1b52d93309caecc91578a97b83e38ca6cbf0f7ee9103cd82d7673ca172f0da5ebadef4a08605226c582b1f67d4b2d8967777c36985f972f843be688c67f22b61cd529baa6b48
+S = 29b5ac417226444bc8570a279e0e561a4c39707bdbea936064ed603ba96889eb3d786b1999b5180cd5d0611788837a9df1496bacea31cbf8f24a1a2232d4158913c963f5066aad4b65e617d0903359696d759d84c1392e22c246d5f5bed4b806f4091d5e8f71a513f1319bb4e56971cd3e168c9a7e2789832293991a73d3027072ecee6863514549029fb3553478c8f4103bf62d7de1fb53fe76ce9778ada3bb9efa62da44cd00d02bb0eb7488ac24da3814c653cba612301373837a0c3f11885493cbf3024c3572eaed396d0ebb8039ddf843c218d8bc7783549046c33586fb3428562cb8046090040c0e4eea50a19a428bde34626277ff48a84faa189b5440
+
+SHAAlg = SHA224
+Msg = 49a5f3930ad45aca5e22caac6646f0bede1228838d49f8f2e0b2dd27d26a4b590e7eef0c58b9378829bb1489994bff3882ef3a5ae3b958c88263ff1fd69fedb823a839dbe71ddb2f750f6f75e05936761a2f5e3a5dfa837bca63755951ae3c50d04a59667fa64fa98b4662d801159f61eefd1c8bc5b581f500dac73f0a424007
+S = 604eb637ca54bea5ad1fd3165911f3baa2e06c859dc73945a38bca7ff9bfa9ed39435348623d3e60f1ce487443840c6b2c000f1582e8526067a5e8923f1a1bdaabb1a40c0f49ee6906a4c8fc9b8cfa6d07c2cc5bdf2ada65c53d79548089c524fa364319a90d46213febdce6db795914cbda04d7bbbf26bbb299fc7d1449dcc81d139e3c33d4c1de96473994730a4b639633d677db25695ffd157e591bddead03dd2f1c1b8f5c8a213b785879bf7c9a992bb11dd5e91df3aff0931ca76c406230a19e307f33419c9d9d3f6f64bf8881c0ddf74a5716cbc433329368d6e55f1f751d7b9f9b0a26eb5811772f5f698530efc1eaceee6e1dc6839b2133c2fccfa8c
+
+SHAAlg = SHA224
+Msg = 9bfc4dac8c2232387216a532ce62d98c1aafa35c65dc388e3d4d37d6d186eae957f8c9edac1a3f2e3abcb1121f99bd4f8c2bbf5b6ac39a2544d8b502619f43ea30ddc8e4eafad8bf7256220380e0ae27fee46304b224cc8a1e2b1cb2a4de6fb3ee5452798de78653e08b01ec385f367c3982963f8428572793ed74cee369f5ae
+S = 444f7efbfef586fad431e17fea1a2d59f19b3d619bb6fa3664301833a4db1243459e31aa6a703b22572f0912754e56f7231a55ac7abca514c79d9fb3564214b4af835d7d1eaf2b58ceb6a344f1c36890f5e83b50188c0147d6d1156da289ccf4bdb0b9a66f1e4a1f2643591d5ffb53702cf70ddf351592575488f1929010aca37714b234eeb5b952b9323ae26533e9ecd516df26392d1254228bd9ca21a369bb6ab0a33d5eb44cee92b0ea7471ffe5fa43c21de2a8975d4c5c8e185fcb7aab33d88a8365ddf0119c108803c56288643a056e781abd4a0242a92e2529d405efcfd4248662cfbb332d6e6fad6aceb90b5b58a5541abe07bef25d9d89215e398426
+
+SHAAlg = SHA224
+Msg = bf5ff1968a39f809de73e6a8014fc6e8df159367f46340da6cc5fb468985b37446c5d89f3aca626fbe9b142b52cb022a3d93518a74243e25bd3a61c114f533874ee5cfb7fc63f599922854b7c9180949415f63f16bbfe9a8a6289ef8a88a836d20e75e4699acba6fa2412fb42cdfe32f33a25102a1df494c6fb738550decaa0c
+S = 017e053d1ef85c43193a0009a903952aaf400fbcfee9c028975777ab540d2d22ab5c25f4cf1d3794afac6697e1f243829052a84e2843cc0e254dbac1021572999f2dcafab58b9dfef2fcaf701e431bdcd16dbef110095bcfba501059d7994dad5b0b54d0812a4380a1f0ba8ec2bcba768bf5b544695626a5f395e784d4b2962fb7533818de1d6ec686edc9f66868ad03ee64361a6cb91fd8ef536ca6454d16c537c07aa42923e62057df9dd9e7fa4ad0384f35721f6eb3b816d352a095c605d5c10e0a7a2e8640e27307cd44b9d71ac50c0043caca28ae8d6f8fa5bb483158a4e415ef6cfad47f34c0042a2d588ace0f1371d93865397bd21516da2cc15e909c
+
+SHAAlg = SHA224
+Msg = 2ff4fcd0be260bf4a0d73112d0e5649c0bef5bbcdf15423a05ffb2a1f021e09da63d15a8cf295ee50bd2844c89813e08d65da61df232ea4ea970443e20772cd5af11cce5ee40b40e133bcfdf7bb3953d865a8309a8a6c8fdbdd242d79d27a8baf17909d145f475355e19fa11cd03d204c4efdac629fb460fe92e93b48fb9be13
+S = abee5c868f850c17794f021ee9709cc2301320dd246fb3eadb7802a300a98a67083a2e4e250df13314c25453b898110801f7e7acb9b694644e5c4a2623dff1884913c05e636fe77ed5155d954ee38f1262c6c2e38d1114cf6cc5143c7277c8649f5a423f83dfd5f829d9dc74aa4b2fcdc8960cde5ce146b289136064b13bd0d36a1e64a261d680fb7e23d2ae92efb743c3db54609eca7a1be0e47e6f724dc5cf61cb2a369c2bb173f2c6cfecb9a887d583d277b8e30b24ec8549c4d53ba3988642a61f1f939f0f3898005c5d13aaaa54bcb8ae83b72b3cb644b9439d1d2accc800271d23e52f98480d270fad6aced512252ee98332af903563d982d8cbdefb7d
+
+SHAAlg = SHA224
+Msg = b5dca1532dffda0831cb2d21ebd1bdca23c9319c6427fdcc5aefe3a27fc9b92df7586c36b7c84572eda66bfb9cf5aa01877e72bd516723a7e20787e90df9a0136f6fa5109ac9475973673868d8bbee7086a2a54b3af4a3b41759bfb6485f2464e6ca53cb1c2c672589b59d50e54b137ee8ddd02d67f5055ac18d92f17924cc89
+S = 9ae5b9633f9adc7ff923d8875748bc6220dd8f6781b3d46d6008ae69fda072d205f87a12d54c3c7ecc85b88b6ef4770eeb4b71debeff8401e329f6b3e8dc8a9af13a533b60b962930bc0ce3d65d0b5a276e85a0c74f459fb072992991ba96849023478ab28d381aa67d22c9c3b092a023f06c96e11fd2f1b4d9daf0f3449de1797612a8113d6e626cc3f995e1c110e65d17c636c92929f913639a97cd049155830dc0f76049123be3d3d79159fc2b4258e94b8bf808d7c46beefe6df0a83037d15a72a581d8adedd8f013b38f5502d736d1d2f04b0e5dc22eb1a414e52b1a9e8735e0592288c9e5a0a78531e95974a5d48860f8e5b04ebd3eb56ad12adc46ec7
+
+SHAAlg = SHA224
+Msg = 1e563fc3ad027a9cc606be19b258bf70dd8b5273e296236ee8d7a65331585014f05006515bedd6330250e5985fdaa870aea65766ff569fc48913989041cff6fbabcd83fdf064cd3932001b261c69a670bd48069c96e7ebecf1380d82751966c7f8d69e0e94efc775fd1c4a0c118f213ab179475cd0cf6daec94eef6ff6bd0640
+S = 80d3ff1f74a81095d0baa2e9de248c0312ca5a817bc9f5156a293d80896adec5507ee8f2df417afe8779668e25b46f49e4357a7170531ed30761103dbb994135b510d91db9fe1f1268f437e0f3a7a4ba6a4d0b9eb70dfc09fed4b44b35608501c2dfd7a230a28dad14926da4600ba785e496212e57738dd575b40c23347b1635ecdf2b9194d96b1450a6876aa76d04aa5947cce71d85121e0bf578e81cf78c6a047e30fc1d87cfd3019de4bb48294c25860b450355bc2662aa36d6e33f00ad79257d2d8b91f73f27c32a9afcb1e1f015f77cb6b0df51fb39ee1bd76ac42c20791d79cf3f363fb324db30ee82bcc1df1a9564330c12a549659bd3010001573133
+
+SHAAlg = SHA224
+Msg = 900ae7e2e7e5f615750c4ee4c13cca8f9f450714a6b273f2e4aca632d11cf6a8821045771f601ed39791010b92f9fac6a824788cd0775d891b13528ea2fd5d59bc7bb51675c1d5263ccccf1edc8fe313ae4d50150c466af90895ed5c5e5991e4a813dec9d14f4294cc8761278644acfe198635b44266c1c915fa1fa2ef79b9d1
+S = 39c64891d9ac4741a57dd8aec7f7243613d155df4492814b40ceabee79eadb8d8bc5fa611bdebe0e0d9714c43d6d29ef309f782bc8e68a4d317ce1ece468552305a73db9d0d2891e2804f4201b1bf8a3246fa082adde1fc9b3d299f88cb93b7b47fe9f73137096c2b8c59ec0612a085363c04cc374769a964feaf1f8e491381e16d7ae2a0c672e69a3667310feed012156dca630a68d339ec80496c6b594fed17091d3a1c6ac3e4da1419b05d589cb32468288f7df4daaceff5a39bcf297dc508ce9549f602e973edbc2aa44332ec3661b19c8c58c5616924beb892f77b5e200d6fb3fc759263a749d157eff9f736798d281b25b71fb470bdb700f211f841db7
+
+SHAAlg = SHA256
+Msg = 5af283b1b76ab2a695d794c23b35ca7371fc779e92ebf589e304c7f923d8cf976304c19818fcd89d6f07c8d8e08bf371068bdf28ae6ee83b2e02328af8c0e2f96e528e16f852f1fc5455e4772e288a68f159ca6bdcf902b858a1f94789b3163823e2d0717ff56689eec7d0e54d93f520d96e1eb04515abc70ae90578ff38d31b
+S = 6b8be97d9e518a2ede746ff4a7d91a84a1fc665b52f154a927650db6e7348c69f8c8881f7bcf9b1a6d3366eed30c3aed4e93c203c43f5528a45de791895747ade9c5fa5eee81427edee02082147aa311712a6ad5fb1732e93b3d6cd23ffd46a0b3caf62a8b69957cc68ae39f9993c1a779599cdda949bdaababb77f248fcfeaa44059be5459fb9b899278e929528ee130facd53372ecbc42f3e8de2998425860406440f248d817432de687112e504d734028e6c5620fa282ca07647006cf0a2ff83e19a916554cc61810c2e855305db4e5cf893a6a96767365794556ff033359084d7e38a8456e68e21155b76151314a29875feee09557161cbc654541e89e42
+
+SHAAlg = SHA256
+Msg = c43011f3ee88c9c9adcac8bf37221afa31769d347dec705e53aca98993e74606591867ccd289ba1b4f19365f983e0c578346da76c5e2228a07e4fc9b3d4807163371a52b68b66873201dc7d6b56616ac2e4cb522120787df7f15a5e8763a54c179c635d65816bc19485de3eb35a52040591094fe0e6485a7e0c60e38e7c61551
+S = aa3a4e12eb87596c711c9a22bcabcb9dadffcabcecbd16228889e9bb457d5d22571a72f034be4783384f43ce6fffc60534b8331cdd5d7c77f49180bfd194b5fd43a508c66d786c558876735894e6a9300952de792f747045e74d87fd50980230707a34a4df013ce050bbff0d6f570885c9c7bf8dc499132caee071b41d81ff91b8ce21aa2f282cbf52389f239afe1490890be21f9d808b3d70b97efd59c0b60e466088bb42714f212bc90db7e942ebcee60e7b107fff44fb3564ff07d6d02850215fd357d897c4d32bef8661689f2d84ff897637fb6d5568a7270e783426b74b7037493e5155fd7cb3ddddfd36bd8a9c877d71d2a966057c08263d2939c84987
+
+SHAAlg = SHA256
+Msg = 61d7b3150131351e7b4c8e5645d38be9335b40289af34cc6b6fc5e48493bf8b7852c73982c99441ef66c7d9d33c29742b1406e02e0aa8dd034b1ac13cb0d775750cc91421fead9caa921eca61a02eb023a457e77915e183acf517d946bc68292896014fd214b7c8c5e14e15944be0f9296127771f736766e4f81dab3708ea2d0
+S = 84e92a145ae6be1ff9242d9ed2d68de668e802524e8ac0a79de62fe74048c35491fd2ffdb185057e666dbfaac84c34fde7891263f8b2bc74746230320f67a7bd7319c9b9de4190547014e2d7a2a5060d6200aadc3a44bac029ff3992edd30ec53ab0d9123eaa6b147352a073a98161e64f394bb99492c6977e24f445c7125bfb90f87faf262272134acb18823a99a5228d1495463297fd774877fb63d4918106347e6f29315e48363f39b33299eaa32d8da71b229d8ffee5f66f722ad3aa4175d3f84ece9cc8eca8d6f2f356a85c1524896c18f7b5c8f9bcdef45c496d539179891ddc76e5208ad8353d48c624054f3440eeba4432a10654a11ef53783bd116f
+
+SHAAlg = SHA256
+Msg = b6771ab0e128b41b32b8b05e05add23ce0fb877b40bfcc3b992f4c8698d1c828abecbcc1c33d401859ea2cb2afbc7fa4588802a5faee2867534639287ad8af84674be18db661de1da8e19c6b6bd452dd9bf3221d0861fb6fba96be42329b9f04f37dcf3b41fc58d2298348b0c15d1190b125300cf27e0dfad60522fc49846053
+S = 6276925568626f0cbe6f5150b050e1702582f8daf99a6f880ef75cd96c2d4208fb6e91b01ba6aba2a816b2d3cb975df850b1d268c4662dd1ea3a300c1d7171c633dd2efbac3000c56ab80f989dbc18243e636ba5d4d26a7d3f1965ad3cb0f1a8513f998003f7b67e2ac5c718cb688b3201d56e68f0b9f86257b84794cdffbc1fe3ea24b7bb6e9ef0539bd4fbc1afb55bc1dca39996ea8a63769f6e225707f69047555e1a4ef3c639c5f2a497b889424a90148639bb64df0a06e0b7f0e8ed466a977baca32f482337b2abe3983eaec3fe1075016e5867521760fd0607d799f1766b3ff6e2ae155d69250f8bf08c8edca0b4f31d0f838cfd298cb7312df93f0997
+
+SHAAlg = SHA256
+Msg = 6a81cb6c7b268f4b9fb9172adbbb36a237a0dcf1c3c83a95dcb0271aac6ac330f04a5a00fee38bc00631a98598186159660d9d8e4c14a9528dea94836083dac4abb73fd00e38fe0e23c7236604a736540e52193ae56c33fbb8f5cfc5c7c2be2e222e4483b30d325c7ee14f742851fcb8b6d6189e98b822b8e6399d89e90fb997
+S = b67991050c083e645097db03fff34758868beb19e9c0c48475f0f913361e71d3d6f27a8c4f0b269b49e8534039e53ad3bab9a3e62abe078ee75e7fb5959006fbfb014ca7b81b3d5afe0ee5f6fc2dfbc450f2839543002f33f4f354f827278c76c041686eea7886ebb2a7afa5995c6cddb1c0b58066ddb8dc54a6927c146c3b2a0fa7cef28903c6c672bc20ef68ffbfab247eb688ab4bde7106d9c59d2153096dc9e5207267038d88e2174e76adc1508ae24eb602332e53c0c2e33154a66a97a0f12f66c61258c7bf6bbf3f1dcbe9caf2fd30ec68c0a9d09f4fd776304b540e62fc8512beaabc4be2107a1ec18e87f61f9db25e871dc0693cef17c2a687fc854f
+
+SHAAlg = SHA256
+Msg = 056c1e4644599e3183dd8d2f64e4bb2352ff00d012ab763f9ad6e560279f7ff38a5ecea9c2e4ea87d004ef8cc752ae93232aa37b5bf42884baa7e7fc6a8c951cd245de2d220d9bee2b414b3a7520c1e68bcf1ae99a9ff2bf3a93d80f8c1dfe8b85293517895c192e3c9e898295d65be334f44d62f5353eb6c5a29edfb4db2309
+S = ae05204e409d727eb9e4dc24be8f863328c2813da4fcef28866e21a5dab21a485321b735274af06bf17e271518e11164d722ab073548f02e1b441923db6f1cee65a017edfbaf3361c67fbc2b39fe038cb5cb65a640f95887389ce8a5ad2ec6e69d3d603505b025f6d6330c8b648802caf7e6fa3fe7b38141659986cb89e6232f106222564d5e5195eda6a25f99068572c2fafe97f147f7f2f4119f21385af1fced97f78632d8bf4fd9a9054d8b9aa2a9f4ded587847a91d42c6391125f103ae288547e8489693ae8686b84891b772b10c4796883f66cd459a8c1a6a4187bd6b387d349e92d7b604953727c9e9fdc449e7345e7ca6b339e26b086f5548898cbe9
+
+SHAAlg = SHA256
+Msg = cec5c9b6f84497ac327f68ef886641fec995178b307192304374115efcc5ee96270c03db0b846d674c528f9d10155a3f61becce1d3a2b79d66cdc409ad99b7663080f51a102f4361e9dbd03ffcd876b98e683d448bd1217e6fb2151c66964723b2caa65c4e6ca201d1c532bd94d91cd4173b719da126563927ca0a7f6fe42536
+S = c48a8e01d4bbfe0f2f05659337ea71d21f38d7f7a10b00b06e1f899eaf40a8e97ead64bca37f13a55ef1cf3fb52cee279cdcb096085a467afa97b03d78d6076e472b12d6be9647cec32d8d91a26247693771687460ba5269de18e1edef6022533a9579f91d584f9e0cee1100c447b77576b1b4ee163ed4700147a9aa61bdc4e2316d2d818c1028ed1c3e372c9f6a1745572444637248091b83f7b539f9bd58b7675676034c20e4ca119b91c4ca5dc76acbff3d0462898352c591c2ca6f2d8b09e2e6338a84336e06f0cc020e9eb8da785889b497f3b98e827ee7a7d3f1b0b73c1958e16aa97861e6675970ce31d9d119bb340be80fd0f43c3dbe64f2a59d629d
+
+SHAAlg = SHA256
+Msg = 9193f8b914dfe0e62521f35afa4fa5d42835e198af673809377a3e7a99733142a180dc0e13e6bb7ceb3b60e5e9d515794d82c392e07913423391d22e2bb19aa0bd88afd7f77e27a240ea4e2de085481ac31ff8d37990211f82f2cbf4c90de98d6e1338bbc88e6a80ab9684dae64785dd107248048593abc9ab03f1737a6f6530
+S = 5c2fe453a8b08c90b02eb2c9994242d518f3f21b368895cffd624050e48aa714005ae675fe79aa3cadd4df55bdf12bec5be8a41d87538f7e031b782e34d392468e5f14bc613b8f4d28c8fb79a2537e1e601031da720acd7b2c8dcbe9858624a7a9a92a06f91845f732370d67365c6464f7b68f22eb3edfeec97e3285024d7f6943b6d50a16cc96d60f680351deaa25f0bc868948607a6ba7f1949b85943c6a92bd6172e81bcc055014b78a733972e3f39d14099d1607a20ff8681c29ae1ef99ef115ed6a1084b514b81a69d4a15ce1e2576fdcf2b2af615b52fec70132112dcc5bc19ec17f32281460623420317353e8a255fda502bd1fb11a58832ae2c04f9a
+
+SHAAlg = SHA256
+Msg = 0e57ef40b021bf87f642c5756b6515a0e06c15a01856d716c566a6edb381dfdf44d9033b1cc809e61dfef9a096dfb689b7271be449d04a1a9c354102c077af5ff72005ab6b06cf131d7345c21e821d6201cca4e090440d70be6009d2dd7a98d311751e1605a3b914dce6d2626b16f233a5a3d71d567cc820152f25e473514242
+S = 7643aa3fe63e66f79d6b409d145ea820c9f7356f71b4acdcbd43fe1e99f8802cd1662b16240f5cfd94a769b0b3f2cb0b11887e886e5ba43733367490b3fc188f2fb3a0c0c8a68b5d2726c8f7a31902b6b86cd402287d385c3e3c06503ce17fd6e54e582f4a907a91f952d2a360e2fba00028e4d3b02aabf7d220b31d1f8ee7faa070147682ccc8bcc756ca6a68fc20954550c317e87918781a3d1f1923503091090c3c60ca1c0b1c699906fbf85aa70ad9ae48709ff743b82dcc31074cfcea623ea45e48644b19a21772ca107ed64239c56574a087f1a6aadf0f4b00ffe581c1410274c875e4599063e46e5168803f0d28d21fcd3509b4c6222995add7753bf3
+
+SHAAlg = SHA256
+Msg = 0c8491fc348d341fe85c46a56115f26035c59e6a2be765c44e2ec83d407ea096d13b57e3d0c758342246c47510a56793e5daeae1b96d4ab988378966876aa341b7d1c31bba59b7dbe6d1a16898eef0caca928f8ce84d5c64e025dc1679922d95e5cd3c6b994a385c5c8346469ef8764c0c74f5336191850c7f7e2b14be0027d8
+S = cacc8d9f5ecd34c143488461135c4951676145c6e472b92f12f758046f172142fa388f285f3fff068242028829047e248059ed4fd39d2c5ade469dc7c39345e5114950d2031cc7465fe712c4041d05c756d3f2d88a46ceb99f2e24a52e958a03cd2519a9b137e62d5ca2b353f7b047b625c3602313fdb53c8db23d83951a599db328fedc4ae06da89ce7f56259b5c8222f7bd3d9740478fd28e5810db78aee8623fdd39f603f8ddf98081d7873980c4eb0e22a9cd408f7c4134c12d2049a2d120f4b62e6b382b997fc375ef7ac955fcf80b045c3d6385ff422dad350c68870539068a162a2edbb93ceefed9677939b90bd3dfa0dc053460b4e2332efa692179a
+
+SHAAlg = SHA384
+Msg = 6cd59fdd3efd893d091afdc3155d354f10d6d88167427a2cf7246207e51791a6ca6200a914cd2834a9b3c79fcd59e26e457e0683bc33d49267edbdd6e5d90902696f1e7b1a4affc4ba371339868c28015ebbb73e262669866c35db974ba69e468f2583b9191d15d686cd66fb0b9e0ff0a3b4721a6dc342f14f2446b4e028595b
+S = 3974900bec3fcb081f0e5a299adf30d087aabaa633911410e87a4979bbe3fa80c3abcf221686399a49bc2f1e5ac40c35df1700e4b9cb7c805a896646573f4a570a9704d2a2e6baee4b43d916906884ad3cf283529ea265e8fcb5cc1bdf7b7dee85941e4b4fb25c1fc7b951fb129ab393cb069be271c1d954da3c43674309f1d212826fabb8e812de2d53d12597de040d32cb28c9f813159cb18c1b51f7a874cbf229cc222caeb98e35ec5e4bf5c5e22cc8528631f15117e8c2be6eac91f4070eecdd07ecc6db6c46eaa65f472f2006988efef0b51c538c6e04d7519c8e3da4b172b1e2761089ed3ad1197992ef37c168dc881c8b5f8bbfee919f7c7afd25b8fc
+
+SHAAlg = SHA384
+Msg = acb30be9092b2f18f25934a0d678b6bcd6b67c2b88e75884f47b4fcae3adfa405afe2c7e61e2d6c508b92790ac00f76b77c965082668bf900f70a33762de6413af93af2ea8086fda293ded4475f23c4cc31ad494f98d7dd7b7fd6f7d972bb76cb35adc206804c3fe5acdd0e5b8b54e07c29111f788bc5902f40afac30afdbaf2
+S = b5c60d8da9b3943878cb2359cf65e4817c0794f950453ca77c81a5a1c1585591aa50a67468e3b399e4faf1d606bea0d9e6cc1d2d70db8063739e0c27d3dc9f9afe88dea52e73298a07d05c7d9707002efa537c389e38bd37bca74eb0af6261a5da06136202c8ad487eebd50bef74767089c70870be1d8fab9156f9fdbc2f2e9cc330a95018ce7943984becc25621bfa66018ef8320b60059f941156e9cdd87ff0d82cf7be77465e0203e7120aaeced84abd8186947d4ac3daf3f993902aec47c3090475c857b5d359f0a5572d4688e5a76a4653868ff54ce9f999e6bb559d1c11c67c15be9d7fe5f8c1704301d055f3d2907722779d6012036084e950de36f4f
+
+SHAAlg = SHA384
+Msg = 601a6aad3faa7988d5ae528a6969031b10a6f39216946aa89fd4532c8ed141f9a650b126ef488f7c5cf3fb2daa254cc28bdd55560419e80214ef999896dac4946852d24fcd9fb77610eebfbb6ba58bca26f4567f03ac7e56da553f23817bc103ee485592a058fb5e3bc8299c7290c71a29137e75dbf5328c3a2dcd34165b3f2e
+S = 301d60d56576f3663a7fbe8036bbe4fbc0fbd82cd6a42e36d7bbc8b206543dc2d56d3198e7911ad138cad222dd99050dd1f85fe19c8a88bf67135e7f8f11b5f5e485c91fc7d478069b72f46ebcdcf2d2ae7de6ac8fe53bb6c04911d122cc231dc210b2147ebe8b052e8b2ccc09f338b349de2025cc87b2619a7b163347ca66a34791a2e46b4e2ac57eb9f6029cdbe024e896d57f7d0491f7783312f8f06c790770150cd139f61fd2b3e7041b37261c6e7ea86d4e06d9300b1a5667cb0288c550b2afb355944834b461cead13794276bb46e5e20aec7b63aaca4d491a500facd59a37c52779cf467d74af1e62b1ebe0fd0be1cacb7ce6d050d86e4eb76cde0693
+
+SHAAlg = SHA384
+Msg = 44d3e0fc90100a1c9316063f26b180326cc2e3834ce56e4324528a0bbb015b3d7812958cd26b91bf08a3a0b1121f9f9dd77acb98a02ad75fcd613c53c732d1c235f59b6873ece6363f279452b6a4b65e80bb59fd47b9a2936dcc1e4dfe1f5362e3459b9859db3209a2698d27fa8aedfecd4d35b927daf8686c59d700490f0aa3
+S = af2229e94a857b89e0e890daca3a8fe12ebdba04948d1883a7d7816a3b682f7da3032540a8769f9ccac9586cf24e8c204b45b85d1bdcc5a5450a215b4048ea42983b3456fa8c76c6786e024f705e088d694559d668caa8684cad0fc57850fcaf34e458aee8fad4e09e6f196557d4e8860284d982c0105d98ce4912e96c3550e2a0c7e8bad5abc29a9a542f57a8c60579038067b3d5391abc21b4f9deb024ca58f9b0c38c0d1f82373f528e939bd73a24d501c591168814c872c525db0e56cae47df00fa3728dc3a0976965323ce8d2dee2b138b50ab7afd48495114673e91bb3ed2205e26a8455474c3d4ec8739bbff6df39b2b72ee050410930423b1472b6ed
+
+SHAAlg = SHA384
+Msg = 5af09077a1f534b89822b26c3272adf8500d3c6bd90f9b5e0d8b211f16d0720ee0eaf6462b6c8a80df6d75359fd19d03a0cafb52bc9d4c37c2aa099911a79a92652cc717f0746fdcad627c72f1c216b243d2175f6d00bf07d3f6aa2a04d4fe9f8fbce93218944b92aa07af6b4fcd80cfde2d7ada15c05e96e777ea1c17df08fc
+S = a56823fa577e8946f1d2f6e351b738b53592544358528af88807ea4f19017dfe81a3d69f62fbff649550d9b310faf27a041fe624f0a02bdcddb79bfb0a465739ec8b64b748cc29e5a02c777e1826d3e2f1eee6fe2edee4a8bcac519c7c7ca5c039e76d630668945a1e5e8618e235864561a440e73e39f6d6842ad7da64ef5b0ce1c4ab88db157b68107174ad7d5c9a6065068768c11c4c96ff67050b5d07b8cd027fcd0d347ec79a197cf43435985bc1aeb479db0022289e8dd3b31bb7c62d8831cfe6952f41d24f89d753789535f918ff68b36950af6fd31dee1ac476a0cf93afe9f4a766f3c4d2c0c3f92825d5572eb2eb8a2b644e329eea1683f90810ed77
+
+SHAAlg = SHA384
+Msg = f60a3a543768fabe37f003009a8c26f7dc91f1422d4429ed7f9d744cdd4b552afef75d241acda04ffc39672159ee248e602dab7192449e2ed4552995c258f00a476346e36a29a0126bc249040faa57c9380bdd74b83f62c56790920574433432f8d65c5cd185e24fad13127265c6a5ef8db4f114493d5cfa61d91664981408e9
+S = 08d396481deef18cb0bef7c3e826fe6e5c9ecc85e5230d35d66772b8d2d015d4e5f5794fbe0550df2f745730d6f8d1d3b850d164fce4630805e711b59308f8608506b7e01e8e9294ed8b7e7582165677f180e965169dca81b3daf24d7b92fe32d6a9ac63821d48b1a0a144fc7a04b0bfc63a3bc16a0fd837b02037ed76e50d46cbfa3857e658e370c586ab1eed825076321ac8e82be374bacb295e4d3408f0cc1fc4c300b84275a51c3573e9cabfdbe3dc51e4a6f5811d860d725aaf8fd0af19a2437b0f1c80f5ac222f6b25f1fa09e93399a6976b1b3ca76afe6086e9b232aae6c7b818255bf963f31c04ae3fa2136c0a442997d4cf12f395fb804a4755b56b
+
+SHAAlg = SHA384
+Msg = 2c07a81de58955b676fec0572d48d1955b4875ff62a44b0010c7a1072b299ee44dd0c076f2178a83d0ae76e767e231f1d81e070afab29c97abd4de2164e437b311f507841f8851d6d69ab51ee9e29e654b54bcee45e9b519c6a21787facb927f1d7d6491926614792fcc6346dcd080bb5cf07bf56ad0fc4e083a358214631510
+S = 9aa391e7c2f0e920aac27ed9fc2081d3c9caa3735883d01ad7a7e3b11867d0ad624156477bbbdde659f474682d0d774489e2b5b039d1eb35454c9e3eed78cff9c4262e3aecfca1d817542b486096598e1114bfc03f20a45de36f6df70d144d01dc4866a0f83319e7c2b8530f8c27a41b7add9f692d8a8e646455b67c9ec47a4d2ce3dfe35d6a2e89d9be50c5b6da39bb0254bd23a809ab97b2b48a068a87abde6b6a6e35955fc92a9626f9607d5b3f401517271594bef73859812b6a621ed6bdaf3c5f2a90b1e1680f68dcfccacb65e0081f1ccb6a2073709d1ba067065016ed73ebd7ebe9e7a7b60c8c9dd04a56fab30702c8a6df6a353a301047df4c7aff62
+
+SHAAlg = SHA384
+Msg = 35ec92afdbc2fcefe48f1e2f6e4829ae53b3da0459cc4ea8a96818b5831891ee2f506fff37c89906d3233a51a5cf1469a62c185061f033085fca6a54e24529c3d6f0d8e904bcb0f089a5cd50869484da1a84f6fb8de4e53fce3dc714201519d11013f6f6aa64e8b5ec5cfeb27b611f0895059d8c47720d55e00b577ca5500920
+S = 6b0f5b50e678da083ed0f1b64e943e8c6279c7246af5ad079cdbf223e42a0d471e56314bc0d58f202aa6c5e1e5255985b0795d48eb3d4b8e3fc92240ae02b4088c6ce8ab0e8c79c68dfdc48657d6a28295391b9a5a5f35255126bf8ca53cbcc0082eab52ec109d22a1185f6dc792fc290aa8dbaebb2fbe404f1d039aa6343cd7af9fcb2d1e05def48096c237e10daa7cfac5ae9b3b3022005d0d2d5c9c5c502b2f23594e80d1604bbb8f5dec07cd3afe1f777743b0b58a4e0e4e5caa148830eee047968e7f40661f9f1a02e1a7fd2b6caf19326a75e9565efdc0114bcecb14dda06c329cf322a5bd3e6ab48d95f2d2a9c1c1233a0aa015a738f901f13148b454
+
+SHAAlg = SHA384
+Msg = 80c9debdf93174d75750a6cf09af71fc18fd513bff9cb491be60af112a93f000873cf43858a07aca760a37e760c8cb01d276f42d997f01cca5e08a6a602f5fe63edcbed395b8c91fb0b336f21fea49d950e1ff24640c8d8d3b95081ad1596644ce34a558587e4a1e2cd50db9ed1dd3cebbc6dce8084d3e1ba70692e82618ed61
+S = 4a15a783adbf274622d5a610bb6fc73337999e445dc2133accb788d6203d70f3cdc63e67daa4171a7952a4986456fab3c077a8941fb259e37a5c0cbb20c408fa24ad0ec850e9bf028c3604609941f5ae2f18bf1ac37a24f755abb9c85ddcd0bf4a12fabd9d253029e081f628e2bbe9f9afe9224954d8315db86c2125512bb98ce9b36930994b091a8a1d7d4e2f4a0e58d0a35876adad14300530b39c8dc11ded3ef2fa95d5f22e67cae34cc21ad5e23f9122b53dfb79f1a2ac63c1844e9ef069a2e41f178d6dcedc518aafcf81e0ebd882556e731cb0ab41d957274a3fbbb7cef2608791000c6b860868cb7393e7d03d945689ffb77555efe08f461451d33c11
+
+SHAAlg = SHA384
+Msg = 31395cef349551343a49271a8d812b4c7b65b455b7eda811fcf74161f397112357ae446257be26c93cfce55e4ba7976ded997ec10d1c8b1ac2fe22dc2ee81d05a6eb1361125cda0197e24ae974cd44092aa9f36fe01352ba05ccefd2370ceed6641950562f1776c39522e023d09a3b097bbe9bc5f87d05d80f8830abd7ac8c80
+S = 162f387695cf9d82dda89c749318e46c9be895ec364ea4aece97ccfa63925af3710894da2b7b5967e46f4efa80ca25d2a965a7e15f75e0aa1bd4250f8f41099e6e9714c3fc4311077ae9bddfe35ba4727531529c239d546ab1c298187f165f708ccc0ae3979a8da193e34859a59c2c3bc42253c8346688e6bba6fb1b01b10c1ec2c6493dedcc2696269d851bde63e27e37bed357455c8fee5629f94afa7a986695cfd5b99212657a6c884644596086b89e0c7c05e819faebebef745fd295af8866e0750f5479baed50cbb3d059f8a5eb7e0e61e2733ae50f0c1ec42be71f5dff324195cb4f0e941a21561513c3037db92fec9556b772ccab239e34b1876c56b1
+
+SHAAlg = SHA512
+Msg = a7c309d44a57188bbd7b726b98b98ce12582228e1415864870a23961d2afb82cd5bc98bec922d5f2ac4168b056da176ef3ba91f6b699ba6acc4144868ff37f26fd06720868d12ad26ecb52572cf10416af68df03ab645a8b704857d2190ffc3f07eabe3a8e2abe34ed6159e884c4fae141d4333d5c3e0db044ff9cccd9cbd67f
+S = 148af61ed5ea8a87a08b3f403929bf8031db4fd3999b64409ba489f97a3ee5208ea4202d2ec18734f615003a51f77441085be6ac0f11810ffa2dad58f0e186d5520ac2b8a5d3966e8d2abb8074e13b50a4e7de83be10a66fdc7ca18118c5774f781212de9efebc6376fcdddc65a3b1b8f1ab31492fe478259ce719b3db587498d879a01dec96e8eabeb07ff7073f3f3eb446084955ca26329a791315a2c259d225e26b2154b2047b21faba68115bfd962e5e24ec52d7c5d231e3044cbcd8c8804855703cbaa622b15b6ef78c7421a367166f1b02576c87360593da75b7189efafd1082bd59f6857f1701f646c24d70c95273c49d5b11e6afe258821b55c1680c
+
+SHAAlg = SHA512
+Msg = ca505d4591121664990747d95d9555cc75bfc3fdaeeceeaa60eafab3fc320cfce56eb9138138bf138f25f3c8bb027b136f5d3d90ed4897779b5951c09df5d08ba9ce8cbe17abc4f038687086e93d771b684322266633d0d65d71ec41234a1dbec07abc8f7df28bc43dd8a45b10ceafac06775805413701914e3bb37eb6ba5b5e
+S = 589ccd4ebf9764f87e6afa7f13c4062579b02228117b15a8738ab39cd64477069cb4f52cd8d5f4574c657b453835ca3cedb824f03b92a573d6d3d91361313f11bdcb34d2059fe2e6ce2b854461af58a9294c88cbfb2a639976b56e4748026f3040e2fd7112d6ad44500689ac777c071d17391969762e186417c4400abdda5c16dce0077642f1fc1354e0e8c14e558c923c1bfb85488b8350f415866a60871ed7151f5fbc5b880500011977c778e17fe8918c5d343f70b00d58f718956125fe28b3a5e2d07604a2b8a877204434ce903b35a030936bc71951ca593df97d24e8e8ad8f2dc9b78f76ef13a1d386ca857ced48f19f3ebe39108f9b33ff59eb0556b1
+
+SHAAlg = SHA512
+Msg = 237a7e44b0a6c268bb63364b958ae02b95e7eed36b3ea5bfb18b9b81c38e2663d187144e323f9ceafb479507d184e63cfbec3ecdbb8a05d2dfc8929693ed9e3e79e5f8abfc417ba1e17e3e281e8a0a32f084117f28c3dcbec51b86f5c85b2822441a9423b5b446d3928f977626a334579b39cfaf58f214c98d0cdf640be1ac59
+S = af076bc213caf75619f4bd1d787cc198f7df3324a0dd87a88416e0a4b81c2fb9a9db5f98aed43bc15fe2357143a6e4ff701d9c48f51de9eb803670bbc4b0aea7220be2f84b8300318c77a9f615986c4980abda85e3ad0089564dbaf7f44d81b6664eec0311adb194d46de96bb17d5a5d47426845802ca0f49a169eb82b75afa191027a0cc8fce9dd16055350df9745fc7200ff9f4ea3cfbfc66c42848113e3be3293d510382d0999f032515527bd99f66efa2a755e011247b223a68e51258b6bc319a7cdef4aec533e9dcd8ae26e349e5b33c79121907de509a1cb83c2e59a47c1a884bf68e7229316a62e3c49d1f542ebe7105cfc27099268120a7743908471
+
+SHAAlg = SHA512
+Msg = ab18939230b096646a37a781629fbd9270f3891a5ceab4a8c3bc6851bc34115dbc066541b764a2ce88cc16a79324e5f8a90807652c639041733c34016fd30af08fed9024e26cf0b07c22811b1ae7911109e9625943447207dcd3fff39c45cb69ee731d22f8f008730ce2efc53f114945573ea2ddebb6e262c527d20f8bb1dc32
+S = 95bd0bf2362f34b2e04075b2934f404798703ea472b81ac3cc223aec486e4c3d9c5d1c2f9ee22417132964ed58e49937f5b257d316ca7fffe290b19f5b58103836812bef30ca0327039d8b9ea91295392fc394b881e2d2ac9e30c5a44256700fc9de0dba298273aec30c4f778d2e7127e8b8a88b0274fce04081cc13adbefe555014e1b5d5dcf6224c5ae2775423a66c81818eec014a3faf9ee75a3f6c3e51c556b0a288e8c262946684eb628b88e3f875e62ef6e801cae75f61cee404971c39d24a9712eb342ddc663515dec103b18d97d78ed68212f27900e77c049b60c853002b08022df56f707efa71027589e1a3ca6e415ba5f4437e978b07af3b73ba0d
+
+SHAAlg = SHA512
+Msg = a280e89ceb2c8cf26297191baf9a955d0d52375da023633e0afcdb0d39dc335d8295852ef4d06714e6511a95d37c04d26818606ada54359b7d0784aa933cc68561ee96a88910aa3d93d10787cd1d7580556731c174a6e3a32d9dcfa416604f0c671481d051f63db6919f4aba4486d1b0fdc6112c1521559f424523c26b4fb738
+S = cd60de3b4a1289a84ca761f90fa63f4d5688bd885f4b531c8515add2de1251f993ff7f986bef3fba692ecdebc81942d7429c7a59c5d3f1fb872fc1da1915e94586a5c3d963603619008f7efeded1d70b0a11ce2cd81b5b0d86b3760c9483674f55e9fa47f2f310d588fb2160e8b5c32be4e7a968d5a8d4ac6576b71a2b91cd6af0016cbc816d4aae8c70649e08dce90b3ce52ab49ce2cb5b0ed8a45e33d94cf2d4cfdee1151270b2073aeffeaf717d39e04192b8b693c53f21a6123813280806920b7dc582201c9d117050320671e86139a027976b7ecf413369a9fc28e0bd719ceb5e107de799f1bc2e255a9f29476d4574d1332f66468afb9004ff7b535302
+
+SHAAlg = SHA512
+Msg = 85ed1e3dfcd5bca24cad1d01ebe192b7d059ec9b884436e18714a43fbcc9c64f687301352ff240817001e757d27309cd1fbbda9456b267dbfb958470b24d06280cf43382a19477875f3259f4210bac9b831d0a07f5e97e5f0f78818c259c289e1a789b6c7942c97bc1485a220131e5eba586643b9071e5366bc482dd3c3c9279
+S = 138134bbecefafc7ca8b102cbe87b012f8aada8878995002cf1887694b5be3b8f0bb616bc6e07962d5482d3a52c52ab91b3ee0064d24558e13c75c80f6a95b7dc498442879d5baf8ffa7e2f638808b97ff70136bb645e30944dd97a997a0205169553a5b9e874c5a9441e18c15ebed76043b639dfd64db79e174847a102724a2a05c649473cc7dacd39e2e1d5666bbb5f01246747048fffcdfcddf782da24a6dcc022b2695f70781bd9f8ff7d03be22eb8fc793f5c071a66d9a6ea46c6a2cf0556526ba8b085073546448081732ac15f12833c1db1701ff7f68344ca65dff86211a003adbf5189cfae79eaa8c8b7141ea378e44cc9c5bf024d2c710ff5cd68af
+
+SHAAlg = SHA512
+Msg = 0bdba34e35fca65a1781d4d7c933a5f210d3a59483aebc95ec71b32df13ff4abf401916937fd88ff44ab46b78cc369414e9bcaa8bab0bb8557828d73a2a656c2f816f070b5cb45549e8eca9d7c0b4a7b0a27e51c119358dad2a17fb3a45718f9dec3c94af78d65c3ecd36b71e230cf080d1efdd8d07f1cfc26768fd5407bc2b7
+S = 9f48deb96bec0b72fbc4f12f08afb46bccf19d9e0cd0368ebeb312d83872626380ac928b612c5cd77438d47aa9ceea905a9de7182c8ef76e8a7a03d6efec8400b6496362bf6a30ceb1ced2185fc7c2117b6a6d888ac20c1687b0f2aa9b76705fd3154889b6acaf4e63be25880c71e6c239ecfb965004cd6321257f846afd2a6590c72ad83146eefc7b0dc4796339a7f64da0fbe359f94ace1fd151c5ac7bb5707b32eacf564fe1622e66e1844e639602ca36274ae01f93e6b2bd1effd34ab63d852cc9caf3ce8446c29c8ae3c6110fb7538cc8371c2a3981249cdc1be2b24b6a0c951764d0b7efa92a22cd8ed165e182863579377997a9ee50c8ac3aa4df1aca
+
+SHAAlg = SHA512
+Msg = 9aeed85b40ba7f86a228b5a1515ba190b2efff66993a5ece19d18baa9b4e4df92e5152fe1ec56a9fc865f30bac7e949fc4f62f0b158d10b083636b4de9bb05db69fe31b50103fefc5f8daf3af7156b4552ca3667a9d720bbb2e4bcdabadfd4b7f4fc5bc811faa36710a9d17758a98d4a0474fec27e9ef5b74f5c689935442357
+S = 9eecdbd7fbf618ddddfb6e75d64440f60445b853c542fe0fbaaa6a431294e6cb6683ae1a71ea055eb49cd2a3cb5154dc93d9aa166399f4e6294f0eb0652800d71e041c1ce1ad849c03c963bc0929dcdd11be5d67a050d02b64b29eaba655642b6436fbfb163690bf432fdceedd106c2f4972ecbf3077ed8b753bb605ec1ea03020839a318a24f8d4c1d7d8df99a7f0010ae41a8b068e2888531056a7dabbe921878dcd3c7d69416867f4012a606ae86855f15aed0da1250e59687706e89c9494baf37f61fb1703b79928795f90ccbe293a1e9472f6e0f4b890fdda3ea2522e3d11d5abdf0069519424d147b5646a5a601f19ec89729a8b48461e71c08bbe9cda
+
+SHAAlg = SHA512
+Msg = 654e189f06c7d42d5539a5872184f8336cf100691f190818fd02082ad68a7609fd095e62fc32b529853aebddac3dbf0d54dd571be72c90404bcc93d01154a9bfeff65065705f8e7eeadf8575b1ca48e28a1eed516265e34540dd867c79d7f175235d1330cb1706356b709bd796f43abaf6fce993f88eaa2fc67f0ab776daf732
+S = af90298bcef615309f235d5c3360f0df11f5fb988789f213d4c46134fee5eb104aa1fabb1307c9a904709de88673ed9951cba93167c67c09d827021b08a22c0505828ab4beb42e59a38832cb4da24ecf91f470a3b412c0712a8a59f6f2739d4e9eb4cc58d2c52592f1452dc65759abe43e8d2bc804e2efb3efc9b23cc1734ff7caefa46b03ba4b397d0714cdb8501a812c1b9f47411c91cba53a3d3b139edbd7cbb543f5bf3829ba7f5fafd8a712c0b111943f53209353afaba176b3f5dc060339d09b1fb3c213dae5d0f004d302828560fb5debf9fe491eaa66f597aa4de23eeef9176358755c952ef96e3672583b6ecd95a02e8ca7b21d7c20cbb7a757af71
+
+SHAAlg = SHA512
+Msg = 121f80b43f9757b3fa80906aeab232195f0e2c41e5bf8c091ac0f1e0bc9e43640680a1823d649bdf86aba277fad8bc85fc957da2caf7323053025ff949706c1476ae9b0953283d34d7c6266f8db65eebe96d195fdce8e965a6383320ec3de0230ab2548eaa69a47a96d80398cad57e14ce9eeac0421c1a6eba69559dcd8f0659
+S = 06a2d74585f12ea7a80527b8c635a21cc11b45dbb0885a12722126811dd25d657bfa9fda774301ca3498d05dfdfb78a6aa16a9f8a95f40f1f04bd354a522f6a2d62b324efa3c006c22c2314b01fa0e91a3dba49aa35b46b19804b07ad98fe4bc990393a4a273ce8f1c85fc19cd5eae9af0b7d1957bb23409778a010b00c6959e1b67066fdb9f8495b4de4dcbb987358145b1ff6a39ef6fc588cda1744e0ab9e7eb002c29a78531d25157c5c2cd6470551560a02845db6dbee242f965a255406f6ef47b3221a5110edb44d38b94191aeaf433c0ece3480b9d1b06d8b8b6c0a232a04c567888e6372f2e94bc2be6b827f8712af48c6f1e4f223f5528fcf348799d
+
+[mod = 3072]
+
+n = dca98304b729e819b340e26cecb730aecbd8930e334c731493b180de970e6d3bc579f86c8d5d032f8cd33c4397ee7ffd019d51b0a7dbe4f52505a1a34ae35d23cfaaf594419d509f469b1369589f9c8616a7d698513bc1d423d70070d3d72b996c23abe68b22ccc39aabd16507124042c88d4da6a7451288ec87c9244be226aac02d1817682f80cc34c6eaf37ec84d247aaedebb56c3bbcaffb5cf42f61fe1b7f3fc89748e213973bf5f679d8b8b42a47ac4afd9e51e1d1214dfe1a7e1169080bd9ad91758f6c0f9b22ae40af6b41403d8f2d96db5a088daa5ef8683f86f501f7ad3f358b6337da55c6cfc003197420c1c75abdb7be1403ea4f3e64259f5c6da3325bb87d605b6e14b5350e6e1455c9d497d81046608e38795dc85aba406c9de1f4f9990d5153b98bbabbdcbd6bb18854312b2da48b411e838f26ae3109f104dfd1619f991824ec819861e5199f26bb9b3b299bfa9ec2fd691271b58a8adecbf0ff627b54336f3df7003d70e37d11ddbd930d9aba7e88ed401acb44092fd53d5
+
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eaf05d
+d = 2d6db91eb32e36e5d5127deb034d14072fe60c1cd13c8c3dd9adbc87140b5e7136f4f89e61bbee7826f45ac1d99194fbaa8c5a0bb94db31d93723b51419d9c6f6eeb5f3610b67f4b4e2ade05cc6b8990e8832cf4cd40f2df0388c9a52072e27efebae20b4ad5951f4d20dd18943e58b786d8797652b2bb759c319d2b0046dbf69c53c075d00c287b876042fafa23fe4dd705e4e423277c9000311e94ea3f7456e32fd12afe4a2bde358a65824f1055064823c893fc93be3b8c658bb441d7f0b00ac246bf043a9c0053d319f003ef5a5533f74d630d8ce93bab416a82951e05b82c6036593eca89f0ebacd7d51ed9610af43537fcd266e5e47c0d25fedad6d047a1a1ee3eb444367e3eff7c7520ca4f779f2027fe45036204168454df4918b547a4d19e938f3c6db6ca2702ad9bbda1261c64d00b578285bdcfc9851f96a4f2cd14d66b9c1f65742a1344948c9f1da8d338ed4e3deb1ebadf11f8c281944e8849823496f86111f378bdd084c99f65fb9b4ee6271b1d1be424c294d185d9fd9cdf
+
+
+SHAAlg = SHA224
+Msg = 254ce36e8ed62e0887d4be00eefa82515acef956540cff45c448e7f9a9d5c9f40de61da439f389e5255ef8c83257ec921bfd150829c522eaa720d7be965860cea2bbe57454fc5e9588d6a96c22f2d989fd0bd21924501367450ad2a3627e4ee3ca15616748ba54219a84f8742495f23de6425710ac7479c4844d0031750f3c38
+S = 9dfd3f32091b916a56f4f357a961a525a527fd29b114b3f03829df1b25c0c5973b1c51af36633116f4c77aa2f677a3b0f82368a538bdb33e49db9fa704bd5123edefbd3a86dcc39283c2a03c96c69030f04c648417f544f08a9b4e01ae4d429ef21422ddfe76834f925c5653b1227835a9a4413da7942b0a015196faec31504111c9f084d6dd6d5a6956c55412c1bd14aaf95d828e844961fdd60cc078f169f6e1186cb0cb6ba3d21168c5bfd067dc6e460784e7c6a76ee3d8b332acfa97e5d4b656ec8c611ebd896fe90e619b588d0c615492464a1b3d05d3a963f451051c65d8f81feea925bcbee9ce7a39ba3c915a18a24a451e470e761d09855a965e83edae3fca41678cc9d098ba9928b525b50e48cb030c510c4ce727c6b93bd091b7d20b4b961165ae0e2848aa995bb73abe9a2634378d224128541ab056a31b784885aef8034dedac13167402f9f62b55741220df8aff5defb69c035d9a31e2a5b8817057241bcf854932f5edee7ee66e8917aa4a718b6c446bddf084f5cd769caeff
+
+SHAAlg = SHA224
+Msg = 35adcd3f24b6725518815cf4606f7b1d940c396384370a376e84456974de32ec4c7164da3ac749b73b30fffa836869c92a74830523cdf2866dc0e0a88d1506063bef0a855cf30c9530ac7cb3cd2e2e32ccfab03c4222db14f2aea89dc03d452069f0684a7283e4745ebd7a28240bf1e0e0686810c97fec6763144652f6a016c3
+S = b5120be98bcdfdc1e1e3312dd7b5910f073132a42776c4da75690c641f32d2899187d9b39b55f99ebe6ca0a08036372749816706664f39b27312135c50339f2bb17b2ceee25768c2bc0ac37d6ca6ee903c84e82e2f4d005d73bdc335f135399c49123662e8908119918437edb615b14e906c9f8ba1b85d5b45909f439cc8992951be1684a99eba04ecb0f6df923353516977774f69e826651190affa86a40be75b06a4128e5509c51557ae4fb410c7e5841ac9fdc4bc1f97e2862429f371aaaf99824dacfee0bc3961fb98b3ffc091f77956223ebf5bb546552358208a32ef9c37825e81668fd2c230f788ca16ffbcc0f1d884b30fe8efe6498295004ca7c7f2b173e5666b8b0fdf9d32756559f99d105c1e8042a7aed7262ca9a17025aa096075fe4433f34db6b0f197776c21fbe00e832eba028e6652653018079fee04eb3e3c12803c39830d072ab4971bcab4b79758694b5d3d8ab21ce874b7c42bedd52652219ff516fd694c3d7cb0bef0181bb85eb4b13184ea3aefe3cceea5c57596f7
+
+SHAAlg = SHA224
+Msg = 0ba573a9dbb7f62e5a4d3d841bfd9298e8bb299eb4fdb256d11d2f8d64fe03e615f24cda0bdb73fe179102842f84b5051fa3d37e7b7cbe98d8a4c92c3b594b06d266f2e9e24759d4018edc848585ab3a3c151dbe5ee647a4bfc8cece4952f932aac80add4a42cf38800b748b05489bbfa9daae6844857403f051e37b753036f3
+S = 36fd6813ab411c4dcb2d7be1ed616c1e40de291a00acd87d2b4d9d4b73c8864a44413c51f09b37844a9804f823b27a9094627aaaf00a6be942d7558be11b84a73d98029c2e26eb8f650580ecb11b4ec2363597333444569634351600212962fef5352bdba367832899d3188a747236f08528f086d93ca33a06b10392bbbd625c867ddba74bb151dcc6afdd4ce41016dc2ef0ceea2ca20917fbdb0777e23503464d0bb59cd4e12c10945250889bae2ed839b70964b2c9d957eac6222a49b337730411984448e58c027371bcf9c2c7d686de3bdae16738db5276e0f538d15b3541c0ed86d318b423d8c7f1859602108a4b11c2772941396a14a2a88ec7971297c18633020998ee02b3114d19012a09a181d01f11cb8f8cb5f438e82fb45e7678bc8df9a26f1a3495439a7ac1f1bda6fb86c9b3ed6cb5f788634946348b7e24b0894c39c506ced2da657a335e54e8f997384e40c56a17a28a9bb64875a159cada5a644ab3bd6ea7bc4ccaed43dd0955f6be6e459e2e6a7ba652f1e9a3f8a83e4795
+
+SHAAlg = SHA224
+Msg = 89530f816a5e2abd4b422fdf968ffd964e0ccf82a4fc6d9ac5a1a4cbf7fff3e1e4e287ab35226a5a6326f72bcaa7914600b694e564018cb8fa52a5897658631c96aa9359b50982ac9ee56cad9e2337fcdd1e616fedec3870a4e249a0275a1ac148b31cd2129adb7ba18878ac388c59828d4b1f6a6745d8886b5a765a338c8198
+S = 27c796caeee6b4bcd750d8df13cbe5164fd726f91baa575f702fe2966744cf2bef38c93efa1111c9277d77f3ecf697d02030f01e3d964c3125533d408834b7ce652824303eb278dca61023a2f9280352f89b5d03d008c103032b2b5c6b8cf7befc1ffffa9b559a995759a8d33c6f49ae574a2d31805ab055e646abed71b30ecf7367030bf26b962d41a2c7d7735ddc0e5f1eda30b1ae6efeaae9a4cf50b68506c21b12e3df2b993feaee448a6443e613cf536e2a711aa526487187b4fcd1fa684e99478c28b84d9af0eb6a4956c0377d08ee26ebd2d8d2f4ce7e66048da3c09c0538ff8efa178690d42f0341b28a8fcb649b531a07af1f21c4243242e045b194a04ad0f92edce482f355f66969cd90254ab159ff9d9c0c6680f78c996d7048e2c5f007ad36219d672a0e76f1bf8bc890faa56e493f0c52d09fa1265ce538e166709a00a2cd64e45b9e5acae2b95dcb22bcfe9630e32f37d0bb529efc8d298c0ba7b8d65e16dee99ad7446a393946258724d08d8476e7f16ccbc0e42638381a58
+
+SHAAlg = SHA224
+Msg = e37656defdeedfb46b14628dff3f6917b8420e5a97ef6c54afda55e07c6043dd75e7908be466e938f629001d0ece81835f94482abad5d1eaa4d0ef9bacacc133fcbae22e2dfbe13360e2f1f48a5ae1560f0b4ed293d9171a0cae11001c7afc949f78b68d80b2afebd0c79dda19ec71d8ef31891ac906272c0ffd22d974d1db4a
+S = a927ec4ceb2ec147cc457e66c12a646fdc412d9eeb1d51f3b5a3e5a8f4b0d36deba3a71914cc6f2321c39d834addb4857c82abe9280c7c8231893904bd27474cb2cce1012b921f0a4d6380aaed614356d653653388ce86ac71a27c976747c9213cf297e759fc3e2d7b1ad5ba8cb3106c0a67624479ce55d0cd67c24b5a45c180efb5830fc20d87ad3b1515e90b77af87f06c6b0e7129718a2f93aefbd1028b1ac63f6bd7eca0a00269c0473eaac55797511950b11525c24141cb5ac4cfe2d9fdbffcbddf8412a70eb1b8f45648553b7067581bc8ee2d6aa089b97e40dfe61c33faf9fcd5650f61078571f03c6df94e01dd7f90f1dbeaf042d9bbc8b3635c4c89932852b311f63ff619550aaba00f061418886224f8478708f9ecdbd96f0f2515353192ad93d46cfa8a4b3ac3eaf7ab9d1a3c4dfc62746ceb089ed3ab4051ae09274f54f2a9c379ffe8c8c0109487b6883a4849415c6a0cccc68b3096938d6e54669edaf7b82ec901c05333e6c3105541f031ab590461e7f1f776a293e593d00d
+
+SHAAlg = SHA224
+Msg = 99ea30dfbb1eff6f56ad6e0b055989a2cba11fd39e386b0026b5f3a4c28cb1e6cc3d716e1ecb7a77d4707025548f79198cea9f447b1576f8f32bfe459dbfca823d15622a3792e7ea5372f5f7bdb9cda5506cb436130096ef0413ef72155aec4775dbcdbc105c8def591bc52947bfce6d9d8f25516fe2140de2d68fd233455d5d
+S = 69210ee27a00dfbfcd50aaf2eb502c5706ddff6d9d23fb38d1112f25c047eaac57dc90a6da673876319d5c04494ece8037c2fb60203c9f23322e2c2063fa7d19165eddd89e1b91935a2b50021e626825bf19cc46aaebfab09b4904dedef8c4632aaedb429feb687bbac2b406f923ff1e844941b0c02b08dc2d8b4265fceb61a82fcef0624f28eef3a9193b86f15f7ac470df590ae855a7aa7540499dd46a67855a5bae6ec5dca8b0c16bcc69c0a1f9218ec7ccae217ac9b47e8f7caefc1e102e3bdb42a677fabe18274a5e69447b33414df5bb29cceb2abd35c94d369eed256302d758df9948bee4efbdcc4ae356e78be735f7425b6443cbff7e85c653a666ded2e74ec7f61103d6e8bac110b157aebf61ce32f8b6f567acbe92f6e3e26efdd3942af6c279c2c7b4f18398cc0ab4e276881b6046cc552594cd9656f22c3ee49807cce0f09f2bfa7abb879727b734dc19c468f4af4d720da8ffd650cdd6938249b6a4c847a51383888d1292a6163222126d5a42dca6fb2283e7bbb6c20d7b60b1
+
+SHAAlg = SHA224
+Msg = 1ee43de2d8797e65bfaf52c25a0b00b6c04e0e40469205565a9674d6af5737bf9be0f9a1bd62f852e28708e32904dbd2666e7f81c54e28e7b0773086f2975c9d1c0d619e27faa7e25c9b4c9c71d66c0cf512a0f5ee4cc450c067fe4250c4fb4c6a137cc26069127ef49225d578a83bca34e4778208b560f8530fe5f213069d34
+S = 3dd722d2f0543e66743f8cdb60341d61fd7b6ef8cb23a9e9f34057d7a0af49e30826aa0aaf1fd34efebdbfc93ae5212711a160f2b8786f4f5becc49209bd05ddf8de9fecd00af5304d6615272f2e4940bc8c39c2fbc636f8c105565ec0f15700cdb066c5ca1fd0e3e3f49452e4f6715a582227d59ec104575c174f8cd13ecabc4d5899e02ebd3e81bd2c003242738b3b95b0e0cf0ef02f8ee02896df646068ae233ffc4436f1e97d37d45d497e1a54a0d6fc5aaf275ec50cbf0b402052200f6bc35373828bcdb48a178c9688658a2363a8683ab9eafa9790eef2c79da148a9d995395d9f6a7b310f6f7141d3cb0f206e8baa82a338d519ee881cf61d5e1f906d42c2e85f25cd19d9864ab54a32969c8edf29e5ac52f62006d9219c21140007b05c63e3ba4c04ece5d8805026dbe8ff665252d537d013f709d84999f84b4382a894c1ba0318493783a598f637bc2d8d5678cf65d0383380ada0db5a510737a8b70c3baeeee47085088e96d99438ba5e988788f2886aa7e295d8578eb27f1d6838
+
+SHAAlg = SHA224
+Msg = 740322953bfc8e840cecd9963f58bea70d2bd20a506366d78a0bad86296922bd097824673b99e3060585804a298670e26ae722924da8e1861d77fbe631dc23aa72b414b017e0770bb33e079f72d8f3eb9f5c83256acdff8ce977cdfa5c28d9b8b59d3a97583b123c1f00b5bca1b80e69b4743feb30388892f6f46aea31b50c90
+S = 7c414840910ca08fecd23ff12ceebcd48b7afa4e6a87a40654baaec6c9050087b1f0b6fa04e36cd595ad293d0827e9e1c94fe033ec42bbd021f7ce2e75da6dd206b99151768d6d5ae7b1f04416804c2ad7c6744c7343c8f01be259361c116810f0ada1c64348055b2594a06bdc08db390d750e4aeea5435932a04d0e69d5906304c84e19d5fb8688ca2598b6fae6d169593fac2909238c553c664de92cba6d8915e01a6e99d8d92fecbc6eaefd93151c61fbbde2eacf2634e7b6116ad2fe8859b65a7066d7b5b77638650b60a43d8277dab0aca145065b3cf00d963b7f818ddadd7c54be5b4ba769ae013446a574dbbb8f7c22b2d1543e7b5ec08dfde38ef9ad843c1bb6d9558aefcd45d3b12c8206b792ca72bf4950befbeec04fc1a28c3720588513a29af9691d2f31dd7d39a56bcb5f499fb14ca47fa541e2ea67843399e0c8ab89c81e5893415942bfe4e470a678c0e561ed64554711b16be3350c985b61f29219c5274d879308dd25fc033f819c385904654399e5438fd9c8cf1ec76ecc
+
+SHAAlg = SHA224
+Msg = f7e37820a19d5f6a05eb4779c240e7fb586ae8c3df713bcdf9c2af7c058cc327956bb8d42244eb43ff70622f8c1ca5d0acefcfa479eee46f369d658184672237d94050c42f89db31f934fea35b2810dd9ae7a105d26ec5abe75db007bd578382acac66792e35d73ddb80415e982dd1290b98856f52b98688f448b79817248e11
+S = 563e22617dd889e7be8dd26a176ee9f67b9b3eb040ad7a7fabc089b27ed4e7a782f1522b446f42a567492137770c612dc5e428ec28a3c502aa2508fb46b703d79d1fde8e1a507d7062e26440b3a3ff16bc82fcc9b301f2b58fa81852b57f951d925164be0c70bd281d726c9a71b984280352289f8c1b394a85df9e1732a4539a30a759e8f126096bf73f7b25a5ed34c32af345bc32e412e08b6ca9b656a6928519655ec9769cf1dae7c985505a812ee44bb3b42ecbec911beced8fe87365f113aac00a659c0eb37bfe7536f9176afe9c459a08ae23600d4c8543ef3c3af4cd1011e08fdcf199ba49024f08808c475986870561d6a088b79c38ae8ce0e6ec40268bc9fb7a3b618587f55fbcd31cea9370243865492e5f13c9fdad61f40b32d3a915194244949add15026c0ae19f52ad5b70365e77f2cf53298c9e2bad06171b0908df26b22ef1c737c3b321395ffcdb71c8228fe9de027f0d310686b1683a67419ea08971cf0bf1a3e5a1072724834601d5f944fa23f77d8e77e887f88ddbeeb1
+
+SHAAlg = SHA224
+Msg = 8710a877b7a4c2e578793bd3e4d19cb56de97fcd1f2af5fb25a326d68fb737fb521371a690e49f7f1a46b7b634ffbd51986de5c5bdbdf8c4585ef85724b5072cde13853194e47962202932def0282e4108613a2e49c5db2bf323edb269e38a8434f62d414b0d17369109f276a0b3b52cc5aec72f4baa67d7fdd94b10e6a787ac
+S = a78358ef28303deba1bf1bc3cae59ab0ff6614c520eeb7d8c8fd5ced34da7454ad140b539ef75e2d65dd891ebf899a88ada25bcc35726053da68e2e02b6acd2e7e21cb8b37355d19bd4c3e36a8c1647e1a384c8ad2ab39bd22f3d30f0f9dd685fe4dd7f836ec46bbcef0805d08a784a6964cd50f58071ed79f882491a331b445390b43f2a295a13a28ce0f44bb6d63f319d8de90e39017f4cbc14533da33380f553f097e796a671ba29c94582cd519f1f64db3be894b6615f6844ff2fc62101382b044f5856b9bb97871cf137c4e9e484e84a3cd2daea8e1c6358d66cd8326c1925ce1f7d2d2e90457adaa65ec3a67f4865bf6120effa06a79deb6b6ca9f85c9dd967f2f31a22d5db25b15530a9e850aca486bc0cac2be6b0af66ecb568c0955a30495bdd5d05a220cd06cb06f04f216076aaad4382a94040dccda68a19d55b49338c9315aa802910655fe9394aa73590a6b2a0439bbef5ec7ccb520f2c5cb71d393a6cce25bf77d8033444fb3da8ac861c63dc2561ffdcce8c2065b35b5c83b
+
+SHAAlg = SHA256
+Msg = bcf6074333a7ede592ffc9ecf1c51181287e0a69363f467de4bf6b5aa5b03759c150c1c2b23b023cce8393882702b86fb0ef9ef9a1b0e1e01cef514410f0f6a05e2252fd3af4e566d4e9f79b38ef910a73edcdfaf89b4f0a429614dabab46b08da94405e937aa049ec5a7a8ded33a338bb9f1dd404a799e19ddb3a836aa39c77
+S = d1d21b8dfa55f0681e8fa86135cf292d71b7669713c291d8f8dc246464de3bbb961b596dfc8fda6c823c384008d05bcb3dccc36accf1b2bede1a95e52258d7d1bdf1fc44e18072abd45c1392015ee71692690ef8cdaaed337dd8546783f961bb9620eb5c7b8b6716e8c600351fab7765ee38a15d32d8a2c0949825c49a7f25eedd9be7b807bbfd517913786620d249823dae6fe2fd39ac639dd74821b0c120b42f31c2c639d2c61b395f09f86851bc809b34c4981ac65cf25b2e8adcbce190ef2ef67a0189039c9110f26701c3eed731c8d9ead178220ffcac7f0f678aa22268e1d01942ec51e80eef06e2112830855e87bafe8cc9c22fd737c7abbca5eb7a221d3835a86610d24b507b5dcb4618aa421f63a5609ef5d68f5760fddf970135602efad0851bbff98fe87fa58bc365f38ee7ec8ef5aab17fd11d89d91ef4c604e0d1f001d0e08869df9225e3b4cef52ff86815e13b3efdf45776f9353769a8a51fe7d891a7ef7035eecfa259848738376886edc91cc78f6da31c2f07ee362c3d82
+
+SHAAlg = SHA256
+Msg = 2bcad6e744f2490ba6a6e0722832417ebd910f9146eb62baaa5c749529f79d6ced0b81a2e2a48852c8558e338735dcbfc2285794ae60f81a25237c66f6ce5d5e801a001e7f9e309b2595cb866de2bb74ac51283b6820ec9f6ebe482e1fd2d5680b7fbd23c1e62a2ee4edff35823fc7e4a295ea4f1c332792aeb53eb44b0bedd2
+S = 37d960fe391298bbdc223fa1eb1d3cd9a46ba8c62e1da8c563c89a8f0e67b864fc89837ffc08aab7122b84c435c7f9406e165a1029857c1e4dea653569277273b1d9b0a9f5b0dc24afdd214476d47208ad5221a7d793cab80671fb4987c86bd6144880c59d24871400f64bdc6d496dbd497f3dbf642864fe49af3e21515e62d60f0071db4884f49670eaa9e4e4982f269abe724244288859c2adf60a09faaabb07990e09e56de254babbee14be7eb6eda0cdb22f3d0de8724804673fb99f86efb4263dcc5017abc91bd9cd833679475bfac50a2be8db86296bbf8017889357371314604e83d68b6efecd4b79f0a8afa0dffa448fb7fce6d344709a670e0cff432c3e187bcff7fdc4f4e9abe1095c46b01d88b6044bb950e92859010d9a0e3b2d1f27a096eacaa24263a2a0523d6e0da1fba8af768196f7a51f92fdf152bef062dd1f8327cee1d344c200c2115ac6ec1dd8514cef9e36d0ce8c32e58783c4fcba901aa70c2b42966488002ff171d36414a144bf46775183a8815de9ee3e81f31b
+
+SHAAlg = SHA256
+Msg = c3978bd050d46da4a79227d8270a2202953482875930fb1aeae4e67f87e79495289de293b4a40d92746fc84cc8318c2318fd30650e2bb9ce02fd734eb683410d44bb31ad54fd53cf9296ccd860b426f5c782ea5cb49371d56184f77911ddf1ba0039a0a49aa7e763eb4f5a04575997808b0ad9f6b330ca38edc19989febf4da5
+S = 9aed20a8bdaf26f1f119020d8f3ea6ce915138d4c87dce025e7f4e49536c8ec079edc6caf0d603bf42bd6a454a6d52d0d99fd0f59ffb3b22e9e67b3d0bb2d275d9aedc6da96a72cbff35c43e7f39a996fa8a6d338a0725f785254fe91a20834ba557fedfe7152b9956feddfd941741eff9177c2fbb55e200bbe42162b32a940cc300ab375557dffd48dfa539f50edd52df158d9072d14982e96303bc612c2c2506dbca3a939d626d2e7fb444c6ad7d8d9f3bba8210b2ac2f696783c349fc5280c105402a4b3d86bef5026c3dd999e3b22380f9dcce40e3a9cc9f1d7bc38ef3dd7e9413bb579800c0e6c3e9ab912da8fec1a4ab21398e9680ba0d04f3b4c8d53c02f05c7ae49b70a5611cf82e38de84aa8c2426f0b63ea01b289f201d3af40dad5d6e5bccc75b9959e5c9758e79105af7a9afb12aee577cb3991879db0fd8662c5bc49022752498a301d95f4b1d08c01ebc313f89c00b1ec2735a07983fd528e6388245036f0ed4a2dbb65dd33ab7f124c014ec1679f1c2f11edffb93fa2d1d73
+
+SHAAlg = SHA256
+Msg = 0c119502c2a01920a090e43357e7b28e33c7ee858b4330e05c71048931c0ed88468ca931ecf0b79c2fdc1756b7675156ec66b8335e3df09463f5aee7028fbf560f984cf698fe5c4280229ac96a2e5923d8a9d5299449bb665008ecc889797e9bb15d04b88c7210fadb8bf6f238e5d2dc41b9ccd1f80e9a3e6ad147948f273341
+S = 8abf2a30774e6e7338eca09cccaca3684399940492fb94b23b5ad62ce3e11d2dbef8966ba5269979eb9653baad719516d3e8399079a2f670275a2ed42c820a9a31fcd703a76637e0d713f32d792b9ae36d7288f60c2d1ae52683bb15941b1cd890d2cd64998b772585e76032a1702e0652cbf259a1ceae695d40cf2f4f6d81341c8bc9082cb96c752c355dfbe296dd21d69846fa37613e73817b2a07046658c9e3fc6d091e17591bb1a4fb6e2ac00a3194c1488e16a9d2903786db86ae90e96acb4de9901aaf1b0651fb76a58dcb3db473efbfb831ef8e30f89967ddd3a6c2f18979a0450657cdaeef6e59377c6db1ec46065f614024a69c518a559942594a46266e0d3ca1334296b968a23a4b11c63a97e29eb16b24c02d545d5b427e6aa585333318e63a204524e0e42ac1edb70d3456780dbead31f785f0b2a77ffeb0d37384cb5f65b4e36ca241f3b2b059105faaa3222d6c135ea5a36651aea396d22fc4ea1b404d7e834b6df1fb838bb5ba0d784a96e2ae2843db3eeea496c7ad2b4241
+
+SHAAlg = SHA256
+Msg = ddbd8468bdb036f4799f428bc8b4374ed9b7cde541337ac439d441ac0614cb75b816b80c17d237b8db73d4a11bfd929208333afedbb8f2410c741129c53932b596a7881c6a4d7111ba104d4600d1902f6f4a1608e139b71911c11c390a0dd091df369aa29d670b8a7e3f53825f7659ac74c40a0c3bfef0d3ae8307e4bdd6cd91
+S = 4e377e2459815d5b33915fa63cd477b5be7c6b7f7814d1350034ce710be67ed69139db622ef60ec6b7638e94b202368bac631e057702b0e6487b324a6b98ed7e03d1f3f20a9814b00e217a4648e4bbc449a2af405ca4b59f8438ddfd75d34d1064e58bfb325c55bd54ea6cdf7712ba807c3e4c665d620cd59513d7bc0855247eb670ecc292509661812702703275d9b2f87ef279d7700e69d995db98144a14c81774a4cd890ec03d13f858f3769e5048ed55caa81201e8785d3771ce6da51175d017d211fa703794416f469b1129d731abde744da5b2facd7a9b093d6c9743509b0103bab9c81c6e5f38bc9718e3e4faa86475d13725a829ac61df8d15f0b27cb40d0eba0b246b9c360b569b81b3abf380eec27492316bc292e5150ee0607219a2bd80ba984c7e3f1989bc51e4c5da3ae5070676e0c150d037a86a0f91bfc07cde64c19f9c7a7af44d6929970041448d3b17c249d5e0b5862e9a25209e8f97d7a0f030181504fead2266c873fd235983df3d0657b92096e2b490df33ca115733
+
+SHAAlg = SHA256
+Msg = f996f3adc2aba505ad4ae52bc5a43371a33d0f28e1950b66d208240670f352ef96185e9a7044f4ce2f2ff9ae01a31ef640e0b682e940c5105117594613dd1df74d8f2ba20c52223b045a782e850a12a2aa5c12fad484f1a256d0cd0872d304e885c201cd7e1e56d594930bb4392136fb4979cc9b88aab7a44bfc2953751c2f4c
+S = 30b348624faa9985fcd95f9c7ead3afe6456badf8c0fedbdadb3a9003a6702973acdb4e86652367db23e0a8141880d6631834f9f171c94a8fe9c315bcb8680ecfb5a4f59b45d4e4c3c05828b7faaa8e4234aada4e766646cc510d07b42bd3883a83b5bcb92d9e7cc1ddf590a690111bfc62a51af7e55543ea5188c92453d41d3e8fdabee3e1defa9d0afdb85c8153a5019ae45563ea3080a3022668168f0c273a6db1afadcd5edbca5021c2e53f4d951c604206ae10f287f451867271d370482791cdfdcb6a4010f6b3d9b928563d168da19f1c1e570f8c158f3d490b29aa23abd1ffdf20866c34c6e63b9e8a9a02d7a1b196d055f4c53ce82b400e4ab9e1b9d70d0049d6d57cf0a4949cfc68d633882882dcfdfc50cf449df10acf20305c2aa43bda10fd8a10b4ecaa23100aa47e92936dce1bfb8d6595235bbfe2c8585cb1647b2beacb1e1d4b6cef758811a68330fa9c3a82573c08fa2cda5a03f3425554e45d98c1645c5bd27d12e6c20b2c462a746e882a3421a7b1b1e25b4c36c8b16a1
+
+SHAAlg = SHA256
+Msg = 6ace052d7e99cd973bb5c9f6679b1c305e07208965fe58c63b10a692f1dbbe22fcd0db15893ab19e107ba2e42c9934a9aafac32adf6c73473f6969e42c983b8f0c96a4639ef77d2c8e88e8cc47d7cfdd08f68d973a7beaf401cb4d1311992ddac3a9c9e067da198adc6304745f5dd312a182e6971c34a515a6c1bae647e57e4c
+S = 5f0e74f454754a3074faafc605f3c9af47604a8983650a9b6211fb191d9afa5315df4db4501fd4f04c741d764656d4a5d006388ad8fdb219ec6b756908e23b30cb639ffa7bbf2874713bfd5a1062c19d04e0e4a74b14446a7fdf5cb812e9ac7b6012d9ae991c47656d2aded24074bb8a38b1a88b1c2b131e5b09c93757fdb2d6b69aa8265a435fba00aeb36a1f629bc34b876089d28a948dd6ab4c899430da60a26f6c13603fc889c7b2936ca3c5156bd7fa6e34eac9e04800833ef0cb9b6eef788c0ef0021a4536fb8371fa3e2c8bb8befac16e8092d69c571c1e15fd255ec0a07acf9ae9953831efd3dcbef44e0fccebb1af959d71f50130e8acb4fa2319261fba12f2715def82bfafbf40e345ec5dcdab5c1bf5f66b1d0e9f7a9c62c9375746e1ae0c8f14a489184383e81dce2070ad4b525df76b446b1f22921d424d9ba3ce21577501df6280fdc69f0239ae1127b69950759d5f0b693f54e87e0763623bf5d3ff69430081b9c9e2445a05e115675e090bcab2aa1d75ceee2ad619ec8b80
+
+SHAAlg = SHA256
+Msg = 0e49740fdcca6bfce294c11f45407805b3da412b01ef3fb513e70e62fd9504c0670db69c36b6bebd69a0bcd240179ba8a47816a0c3437a61fb72adcaf9096f2a22efe0b431fc422d225301e850f2f0f4da87d6944a8529ef79781909ad96d1f20596f93e17c57fb4d756974bbbf900521cb089eee0ded5c956a15b096162b07f
+S = 7bbb3ddd17a42be7cc4e7eaf456509a4ba58d40c49a3d99573b733e1942f9fca20ba8b910708d6e750367e847302fc603b8063c19af883e7507fb0d9cc2be37479a37cca25b8c7c46f6bf661dc6a3232f88b483f1b8f41b46d49ba3f1795d68eaad4a2556fb5d7873bbb6501ecf06ac558235ed13990b0e16f67965b09366bcb362cfc6fb978f4f68d8146dc8b819804df424e8ca5b63cf1fcf97bbf300d0b998860798a63424383fcd81d37773d59bb13b4fa5d468cd128bbab18a8ce5173be5d9d54d3177f0245788409973df4a9016b944baefbf3bf1146a9393d22e35ec2be0ae6f4c31dc4981f40fc1baf382600699eafcea92cbe24e26ee846fa23bc193b6e721401b7ac3f5f4ebeb633979f8ef35f4ab1117a869d5b9dbb7482f0d5a59e4163548d2512ae067205b57d030c483f720d2c44350428f5268943fc5f6ea1c88e2ec13ab3dc1456e96a3b8e7c121af4d6a5fe4ee55e99fbc3592a487c194bc2f2bf6e79fb79c2876cf3365e075beeacc7db4db7ee69e7f1fe12a327e6cb0f
+
+SHAAlg = SHA256
+Msg = 0e675dac9aec910106a6ab219b4cceb52ded2549e899c9a24d5ee55177761888a3be1a2def6aa32d62f788132d6227d9309806fdc02db7d8a850ff2c6dff37fcd777f1a0acefdf18bf85f1a12979be86d799253945fc34a288f348b7923d764db27a2a2d5ae20e6b25372ef318f8596529d8ca23fd6f08a8f62e0a1b6d989f23
+S = 8052d95f12ce0e6e53a5a356a0eb353bdcc1a66514d6cfb3a3d96155310bdda0a0d1795f97643f3a4496634f2dd9b95a2138ee390e1e74be3134f3f47a919ee7b59f8ecd272ab88c82cbce7c217e5f92d057a5b00fbf0575cdaecd7dc285a4218c8a955216598f0742671e018e8e4e76839a575f50b2102a8b77d1b84f6dce98d78e5758e0a6f92bf35d6a2f18ad400925d7880f9efc774a8c7ebf64885cd2f6f629b54a7c12ec91d39b3c2518241fdc322d9b235a8ea44f77e82f3dc4f728f620c07d1e7ff4094f29c674ab0f0802efa1c9e6481ebb84e0bf13ef468d8cca114570b9edcddf98ac4a834fe7a0d5c6fae8a60a48399f3c8af42ff4026e42a81aac36114ffc053f3f729b7cf9a97a56848ebea0115aa8298341aa226963ebdf57ab2d8e4b9000dd051a6c5d69f60e1dc1b33f2094fdbf8e5b627bc0764db9522cbbc081dbf38c21b13f980813bd2b00c757ebb8c0b21213152e694039f306f7342857651f722bdda01212a8552799bda6ef07c5207dc744ef7969afd5af2e6f12
+
+SHAAlg = SHA256
+Msg = f6a7a6e52659125fbbc8727417283b9a64441f87121e27f386d5019f10cc9b961e09f1b3b0db23630cc0caacb3858c6f93afeeea7e1a6a80dbe0c2bd9c7c939570302dec39a4a25cc0cf1d32a71a75b9a0c302bcdd80b046c86651acf30838cd52e30399a8fab8d03fbd140cdc2f1f02f2480405169820ccb32e5974ffb8b1c8
+S = 84603acbfe1f2f769f1a62b0f287f306940b225476714a4b6827c02d7bd052f303f30a5fa6da83e60615305669ca9ec177c5b32b1415eebef78620296ebad6dbbd520839d3aacc9781ac8602ddce0736dcfa7290b45f155b8e924d0afdf7dfc8d199bf09509d0176a68b145756eef53de456e17078859849a352a5bb654239d8ebaf8800ca8263d34a868d52bf8f22644dd9f3c05bd891cd92f263530c5896023c6b213ddb64ede1770ff1686c34036e281e911d9dc960354fd844cb7b22dc0cd81a96203ba818401ccc225f857e59a5cb7ba6dfc7f5135ea32781e63daa14fbda1bacc18ebc50824d4028b8fdecda49e810bae5acc8adc0dca2e236fc832a97330a1214fa0aed15cd10c049efb65ce855c060f05befb317b8065843c4eb5a0371fc6f209f6ffb948c881f2f2091caf0f59f60b72c5f67271bae96b913fd21fa1dfa975d5ecd62b0d50873b686d29c880d36edcad33ec3e2216c9cfcfb4f984c23fde815e280a802428608bed3739af9200de1f85edee2834c04942c068aacd2
+
+SHAAlg = SHA384
+Msg = bb294b95d913005b110987cde45887484ae6df794873dfc5c41fb7e8992c2fdce70699fcac8004699961b3ad1e1fce9ec8ea5685ccec5e80e4d0792559816f68613434bfaca81a843aac459a6fe35f5369c48e9191e4a32c70789594c5152db8d4bb02260012a8739cf325ddff2aa42fd67b6ee5bfe31591131ff27d0273d292
+S = 32637c60798b450bff100bff12838357deff281d5b31e4f4c2cfc96eb779ce6d31b1ce8bd7aa7fa88ddc4279c8c3280604b018ccf452004a1488ed4750181c5025636511ac6724fe51761c27d7cf9a0c8782ea2231268853c4b1f7acb0005e5687c8f3df16c962f02ce56b23d387a2baadc8bec94229c3557526e61707a8b59293a976e32c7fa133285088f3ce3e677788aaa947e7622c757e844b117592be99fe45376f8b3013e8772ec92c5bb0b9fa301b95544599690ad93668d83b2daa7df05c66214e275014780a912d8b1932d7a655058e743f50b074b1d9691ca23a2f95f6affbd516d64ccb2aa43c236eb95d36d272545e3beb8ff5aacd95b30f7f1d6418af042cd9a0cf0189846262322a18875ae4c3e68e4e8ffaa0276cdd99a0047c86c0f71d2deefd50642d29c195e6d14fb46fbac33a508c1f03a232de08aae09faf1da8ed2ba2ae84bcca88b78dccbde9afde08a3beb322dc79356b29c84841698914b050beb75a7b2f6701aa8101a5a4955ee27bafe81b21d03b43e3c77398
+
+SHAAlg = SHA384
+Msg = f946c6bd5e1d6b89092f3c487c0568fa07c356fae9b8e831b8320289039746a435b122cfbc4a0d316bf90d481d3b7d979cc50d98c1190af8dc58e0035557dd5e94f437f41fab513202643a77748f76c6b77302bf40c392cd18731da082c99bdedeb70e15cd68bff59619cabcc92adcf122753c55afde0817352bc247d1170b8d
+S = 50706ba49d9a316688a3ee80a0bd986757d43ec83285af9e78196bd52c900d40b280fa0de54e35ace7d6660012f1a66204092f0e634b97e0e51665b4075e36f1422266c7cad7b2d9981b913df3fa3e6a5a1cadfc6378a8540e0faa26f1cc6fb2fb492a80d0a6945bce5bbc23ddb3b10701f0249b27407a6700802e8842ef3cc761c4823acb5d1453508dcdbb979e7bd8d00128e60a9b3789167c91417d93f0e9fbb00c9af1498e09eb6485eb94cea4883f6a256eab2caa826de4fdac01baca3a216e3d204a3d837ffd4d0be2b2cef711909054c4da1d5b93a8f98451c7002ae84a5e7080d98671c50e3c91c4087d0477b104f916010e742f2d207fb40d122d8f211af6d7c5eca49542d9acb0f166e36abc37155070c12e9f28b907d67a2ca70bfce554e1c44c91520e98fc9ad0c0ee477f750516476a94168066ce47000030a99c23e2c38755de946d5edf0d6aa94212f992315b248c1f82723b29c42216c78cdcb668f11278261cee9252c8fd0ed37d0a8580ca9b9fde7505615943712da19a
+
+SHAAlg = SHA384
+Msg = 9a337d4c0bb9a005b47f4765d696d19dec58bc8482f2173a4a203a0b6d38b4961f6a852e76468e807c7e457683eead5cb8d98642fb76c0a1eeab36414c1899597d57aaf96782ada586f61a423f57953771d520cc4ead90d569f23d950f8dfedddb8355748576e6bbfb6f2e91b3da71753fd2f4ea229f6d20e27db8d05e9fcb68
+S = cff7aa7f875642fb9343e07ef5e7303bbf5f069b44c19fbf83e59d422e25267ef9307414b6b1ef61711ed0013276d1a2ad98390474027a0a703bfe8a6e87706059d89c060980c9c9e60dc7e1fb9f777a41785ab4d2b663ba0e3c1921545c479c2a383a50da8e489cb22b71101d0ec148ac70928732a772195a140d080152762a9c40803a39fa2a6978c2a75ac4d8bd1bccaa1f4204ba65edddf32fedf2d9d0a3aed9b06c47e717733c577812d723dba74a852b2905235c812dc5f1d0df0f0de73dfb86221c6ffdd1eda119bbe98d148add36a4fe50489b06aaeefcb5c2066d90fa79738706cd18e474d69609ff1210c77de7cd23ba2a775a4329cb271a826d602c401a71439019cec10cd9f184c4d04584211827b19eadac3258d8a0f2631613f051aae0c613050cb24442f15ed4fe0dbd290e42629141bd2cd56d20584a1d10e1f2c2a9ec731433d5bcd1d318bed5243b4b7d0f9a7982061c55dfaa86b2c01845c021fdd2a978d42034212f43b3351b6adeb03bdd6caf7de059502f16d77348
+
+SHAAlg = SHA384
+Msg = 32fd45e73f6f6949f20cab78c0cc31d814baea6389546a365d35f54f23f1d995b74101187760c89bb0b40b5057b182e2fafb50b8f5cad879e993d3cb6ae59f61f891da34310d3010441a7153a9a5e7f210ebe6bc97e1a4e33fd34bb8a14b4db6dd34f8c2d43f4ab19786060b1e70070e3ed4d5f6d561767c483d879d2fec8b9c
+S = c389613717ec7476ecda2144d0e8c8f9d66fb469c167c4209ec0bdeebfb471665d33dad47b8f3c319a76fe8a8a9f662b6c690b74903d17f61e2314e5ea8d26670ee4db4dad295b277ca08ade880de2e42d12b92952764c1dc808c266dbbedb670158eef36e896f55a203fb99556ded0597410ba37486b1d841f3d6d5c0b39f2f49f0c5794824fba94a8ec7c2b2c91eadd5c8cbe44895fe3be3bc1727d6fc0e5364f53578639d3b3af696b750a07853694ffe145a28c03620c78dd7377d094d92c3e09546883d4703e62a98ddf81fd01fcdf3c4b215224fe2b1b4992abf31f20d12afa868202390de334a846b2d58b253ea8ab3c5265d84773a659e8bac7af44123d9ea15062e65d4d419cf2d97077d0624f8e5c36f2c7b35ccf95435d5c36886ff9105a6c1ea225e15ea8cbc7b6bf6856151cd76fbb75b5b98f0e3db516a8e218189fcb1cd5de3cafeaa33ef135c5d8b8aa5f881afaacaf4c08bd7281255bc2a33b76d4a36e0b170c45588239e5b38c679b08cf802af73b6d79b3935949461e7
+
+SHAAlg = SHA384
+Msg = ab66cc487ec951f2119d6e0fa17a6d8feb7d07149bec7db20718e4f31d88c01f9a53d5ba7ece3a4dbc67af6a35d130eae762cb7962b9ae557ca38452464002223f61bcd3c7353e99d62558ceedfcb9374d4bbf89680c8e2b9585603e076f1cdb0058299b4246845dc79d1043b1422efe84018e4c932c45beb8851fbf485e36d2
+S = b51331552b08be35a1698aa6203d84dbfff9001ed5dd776f2be4ddfc07dd4620e9654e82a33465bd20f11863c0ed02a0aea27a44d414c328a938bf877e15838ab99d670d01414262e8865dc1d9fc30fd0812699fa690c34f302f637ec802cd40ac8591e976c0b8bccb1b0137af64a2870210e8fa3dc431fe0956b8addff1e4b18cf07e078aa93af81bb3023c9e594e66595fd92b10226ea126005f4724427352c38e9e85fc2e0723f80af1f61599550b5ef54c5b38ca405738017b89cb9468d9741cd6bdf7112162251ba1d083cc370a4a8261c39b6b94bf21a53b7564531ae9ebc4ccea7ebb8bd314b2e13b58ed1018ae5b415e0f9e3e19a5ead3a44603f90674a190febde25f8ad8778aeead4d0f64fbae37166a54e3a763e35559bf8c3f173f19ff7bab98f3ef803dd56c07628399aff87485ee73dbc3db34ecc7bff3a53226cf87bc81d256e80c09520c8f38e9bcda095e3635128e1bedd9970600546a751eb11dab42e289d6fdfea04bd58d4571a79d24bce4508c54e1ec4cf75b985fd3
+
+SHAAlg = SHA384
+Msg = fef7fe89b9a59902a70a1d9caad09ced8bee4145edcbe3ef7fa6dab37635129f3b8c5e0860410ecbd9cec3d8693682f25aec08b071f05dc8213bac8cff5d52b576653560bc01575604e6ab90f67227fb5c901a781eddc027700913e54a7fe51318482c9ab42c9d2b911b7ccc39ccb290f9a420a5dad93394d4d7b8c53fe3f242
+S = 45068ca6d82f2c123925cde11971215d8fa4a4df6848bb7654868700978764854638921bea5869280dc6ad9581ab43ff7012969948a5677fa0a66136a316a4bfecb89adf4131b5bedf3d4693b780d133af9bf9c133305be78374afda3ba3854203324481a9d10b9ca9b92dc7d74df531872ddfc76caa82de020e2c415643cbcc4280e6d2f4371fda7d9249314a8f437648991a9b03d71b5839ad38a1555ad34526994ba56870b6ea18011295f2ca2b0713b2e92ad77680c0dc5bed8d3b9b31ac14df769949c4a43ea67f6deeb3dc9ed589ea4e8a2cf6695df46f946f1467b28e875477ae4e645080fafda6dd551d2c02fd6b2b194fc0bdb050e06d4c784105f5a33b53e73098055963071efc1bf397fd325f3a6f4e10d76f0411a001e62ec73729018316f56310f893a59363d1f6fe5c17444b6c728a4933b75212fdfa258e4018b7763951ab4e5096411df9e5bc16df3896e46c973d32ac9276a4e2b5b80e3d8d798dc0470b45096b4d738669ce052ed818e560af1e92c915187d66cc308b70
+
+SHAAlg = SHA384
+Msg = 82b3840eeb95c9c57724c70f112b6c2dc617c31785acd0c823f8bcdda285325eb3d308dc790522bc90db93d24ee0063249e55d4219ad97145feaf7f30668623cc8890a70f4f149866f82cf86f98b0053b23c98c8dd5e9107e341460e9bf5d88cc8bcd1f2e4c007cc1c02c4529b93233a0b06bdd15925854ab9e3f156eb925bf5
+S = 0593b9fd4421452376d27bc7a280101cfd6e88a6727d7d77cf65ceb723ecd257f32fe10277e85798e0da75917736da1a3bfc22adc7658fbb84da6ebea0b07d1cc405732fb040b585c1b63c8034069bffb8220656f1ac54ce693720d6fb1b5aec67b03c887c8077da148d10f48af7c028f992b18f13c0e57530c086d775483da5f66f3a6a19187868340ac63c6212bcbd6cbb7beda8620afd9b66de47473ef24d1b6a36f4ece9add49514fdf1d84c7a785b7f0e00f382235899790f472d13f48558a4314742f376808dec96edd2e229e943f7b983bea5ec6edfa5e9bb37f588e55ef62ebc9214beaf9da502434e1088df272c6c77c1e1d897c47beab77e3bbe317f8d43d21fd7e94337c7e263e2867bf580a2a8ecb9e36ab7d3e1d5cf9a23230953d59df0d7e23558fb612b7918abba31b164ce178818a1a9e6b6687f4de685d70e16bef6e192faedfe0b2b95477d37b0a3a2d002f33ef4321cb905040ce06fda1c98a008767fbc781a1eaf3375dab8664b590336b99e157b8687a6602fef6a3b
+
+SHAAlg = SHA384
+Msg = e153cca4431ed9713f4744ba054f5f191cb37b280108ae3a114ad349a872d1308b46211a83758a3b4be32fbeac42ccfee7e23df853ca400147077bb43a44c12f299b917f3aabdf589eeb1709bb3d60b08bc71eaa3ffeba4e2903a5dbd8339aae85fa24b9aee76130000605857a6aa197d00926270dcda58b7de758a6ca67e617
+S = a835cd4146bef465642d494936268a311a5490d2c9f9166c6ce98216a9a23a643597300a0050e6445abd5a9bfc7a2d9b70726c824c383bf5acaddddc34d434a31e5314d25fb58e258f518866c136e52855c16fe64ff8f1c4d66c4e9e39b8cb1196d80944d0746c0a3e1769cd4167df72ab5e4c9dbae9cb35f4828e12099f9b36a5a70c48d4aec9872d7b19e1291b33cbdf08a2263d500c0a83b5237ef6ce92de344b3b41d0d07404fcd5467b046b52b8f85fc6b5d7afc437f1ee9e78390ca9bb6cec618885ece29758f2fd6f4e5f4f896935de5f67cc04055a4c4c0fba5def8d2caa179331a85501ed25822ae79da9bc815cc39c6a979211083e8683136c942e1e17e9eb8f84aacf091aa1e51665fae446bc48c304af65391f279afb98b92e04c2b73d9d94e991198fe7781f0f9696fcba2c03485f76e6de30b9535cf3903db2f3afa851a47bcde72d4ed2e8fabf9bb7d4696cb4ab8c289b0c21e1f979ebc532e280cd9010df4ee72f84bb9e82752828f167030c0fe348ebc31ec17b8f07d94b
+
+SHAAlg = SHA384
+Msg = 9c63899dfc7bdc0db384727244caf71ecfb9b8792b9f57e936b3c2f5695565a9b0979f3c78fd73f00981813a16da342392fe3ceec6e63ffba191cbeb4f4b90050d2fccd83beb0622b2c3fff159d9e608f3abcb843bdd56c03339b975b9f4e3265b32f6bb6ccdfc6c5752d6e0344d749699c74c85b30c04ff95b272dbcfd6c7d3
+S = 4d38a297302ad0770d9729ce5b7212eef287ce0250f403e32b4acc3617dc0d2edcccc2d580ddbdbca5722b70704058a3b807f592e400bd563fcaa8b066a614b4906f1433968ed2f520a2f6b034d4b2d6890a241afd1adb8639a6cad9dbfd2e278dfebf79740d75f295759d29130b19ab19983dd68f779de41ffefd4e82b5e62f72f90efb73437f08a2503dd9819dae20ba9706c199de9cf884433eeb756286a85eae14bf9f6dbeb705461d91822282f18efbb10589a578f2c9c345b079a7e9dd07fd4b34051b27119729906c77dfb7d2f8fa6bdd5faa1e132bfba9d391e66395e67f01353fa275eace8b53aa91cb6fb693e19191d42a4c1a85a0c504b1c85f49a4d60936dee4646aca62a94aa4bc7828c1ffafde8be656317d506abec179cc90191d12356ff50644d3e01aa5bcfdd71d3c828dc3539dc0cf3fe8b9b91e0c2524f6a3710379c90affd0d0a50d74387f9ca88b46463ef1bdba58cc9a36e5c2c435a20d968350d15d941c3212cdce815592b310d259860de1dc1a3d70ac22302a51
+
+SHAAlg = SHA384
+Msg = 04846c2e676ac73160bf4e45652bdc6cc4d4c9284577b4320ab77f6ebbb59a1fe0e085588e0f90b346cde6441af3c9d0117d1f3bcd962e406bf5a465ab6cda2d51be598fcbb29ea713651aacd7e47d22d8fa3450904730f51792ea374761a4dc1fc6f1bc657b77768f31f463e4267fc8dff61150d4b343b9d53759cdd7b98094
+S = 103bee57e25be8c3a2f774e739b47f93435e414932c0494b6b6aa2475bf7c9305c73747e0adf82c2032007b3f75a69c93112617a62566c5a2deaa25fb95209da49fe9c161cb2ffa40fd9d77f1ff660c8b6cd3b54e3e79a759c57c5719802c9311db704ba3c67b4a3113754a41b8da59c645be3909e7db7e7cf7294dab44f74240f81a281eecd6ef31c7cf18b1a19c7d02a312b91d6edfaa954462d34740af5ab708db5a10b00c542be82fa2b2026b09ef38a4001457e27a6023770e4b4d5003267c85c9eea1d5f8d770bd40b554d5b4daf146dccabac3ea8a13a05c3bddfc971c5158fac027ca19b7232621e9d2e37b6a655af545e44a298be78cd475c22a48bff7c3494a5f8a6abdf1a46f9de082e374fd598867d61e4d51daed84152e43cc6a2affae205edc52613480d411aba84fcc9b69d1c28f16f76836901a7c5b3eb2f2c940d0a3fad38a8efab968a0c85eb22e11d3d0861136ced5f06734fdf8d4f151d23861b1cba9b9c580d3350c76d4dc808461d5f872ec548b2b427dff74b1d1a
+
+SHAAlg = SHA512
+Msg = db6c9d4badb1d9b74d68346448b4d5340631783b5a35ac2458563ed0672cf54197587fb734c4ac189b2dda954cdfb18b41c010a77e90464eea6f863c5da0956bfa8cc636bf0a28be5addfe8d3e7e6f79f71d7fcbbae23ea141783f91d6cc4c8fad125811760ab57133818892471a79c6d04eafef37b2fbe506785318f9398377
+S = d480d5a979ad1a0c4ca329ebd88a4aa6948a8cf66a3c0bfee2254409c53054d6fff59f72a46f02c668146a144f8f2ba7c4e6b4de31400eba00ae3ee87589dcb6ea139e70f7704f691bc37d722f62bb3b2cd303a34d92fde4deb54a64dd39184382d59ccaf0c07a7ea4107d0808260ed8d421cb8b1407cdf9e915159282b9f7bffdbf40d877885da7399edebd300a7e77a908f756659a1824f95c8a812aa540ebaa64ab54a233723db55caa8b4466ea9ae6614ad1bb869e9d8e0d032f3901671e94c0b673be6537cd54278ed3da2e1edbc04ee3a9e8070d73ba0ffb93e60f30b87ff3862e9c53908f2c8e99915668c1f46635e05bf7163051ff9d92bc71a626553c69dfdd06a49f7ff1ed51e918f3ed801dae62ca276d7063d72a6ebc136ba06cfedf5aa23277e81008c63b2e0083d0fd6814f6d4b4b40a42e8c0206f3c356a5ec709b7c8a4b74b7b48d53c9d8694d27359c2c7701938d2f0161721a57313bb1a2e11da215872498182493d8517043b4c03f93446aac93830276542026ce83055
+
+SHAAlg = SHA512
+Msg = d5dd3b6ce9772d9a97fe21648497783bac5bb5254aad82b6f7cbf43b15a40f386eea8d151967db149e9465865968133f246e1347301adad2345d6572ca77c58c150dda09a87b5f4da36b266d1fa7a59ccd2bb2e7d97f8b2315431923530b762e126eacaf5e5ac02ff1aaef819efb373cf0bb196f0e829e8fe1a698b4790a2a05
+S = bf9e8b4f2ae513f73d788958003733dbe20957b147b17c3f4fd6d024e8e83f07b65d9f3dbc3b1fe84da021ceabfccd8c57a014fbe5a2bce3e4051b7d03e09fc0350b6a21fad214ae7a073277c77a40dc44a5aeea5194a756b69c93977b69ee9294360eaa73a574548fa6a974a7cd5a6adcf09e80631156af85a8e5c5317e189eead47e2ead65c381396b5cacde260e937284a8e90eff2cbcb9dee22925f2f7256f74c67cf3ffc7b8ce657e8d135f0f376d9d936a79792c981614d98e3f7d662a4fd46dcda96916b32f366ed27dab188f184b984df0b559710d8ff2040be462f91943501bda4840fdd5c8ec15d189064def756e545db319e007c433f0468a6723357ba47d156ab7652b06ae2b18874f0771c626466dbd6423e6cbc518b5e4ae7b8f15e0f2d0471a9516dfa9591697f742862324d8d103fb631d6c2073d406b65cdee7bda543e2e9ebff9906985d1cb365172ea623ed7aa4c7a322f0984680e34e99bc6231b02e3d14581608bc55bca7fbe22d7f03e904da4552e009e5607f0418
+
+SHAAlg = SHA512
+Msg = 591652b6eb1b52c9bebd583256c2228680110b878917dea5ad69e8c5d2ab514277b0ac31e7e2cceab2e5d9c45d77a41f599b38a832f6b2d8097952be4440d1ff84baf51bd70b64f130aeb686145fcd02953869fb841af7f6e34eaa2b996ccd89697c58fa255cc1e81f621400e14146361e31c709e84a56082231199539f7ede9
+S = 1de79d7216dde125deb77c34d90ab321a4de5fb11c296656ad9bf9a24653591117ace415e18eadce92823f31afe56fc8e29494e37cf2ba85abc3bac66e019584799aee234ad5559e21c7fd4ffd24d82649f679b4c05d8c15d3d4574a2e76b1f3ee9f8dec0af60b0ced1be8a19c2fa71bcbc1fb190899ec8556958e0782ace7196b36658656cf364d3773de86260fd8987604ef35eae8f38ec2cb0da864cca719219c2ad71c08506c412ec77995f37439c856977b71dfb9647990ef70faf43273ae60839cd0679ec9aa42bf914e421b797cba218a400ff9dbaa206cb9c2b0596c709a322b73cb82721d79f9db24211bf075a1cef74e8f6d2ba07fe0dc8a60f48af511ad469dcd06e07a4ce68072139c46d8be5e721253c3b18b3c94485ce55c0e7c1cbc39b77bc6bb7e5e9f42b1539e442da857658c9e771ccb86be7397647efbc0ccb2c3ad31ac4e32bf248cc0ced3a4f094526b25631cb50247096129b08a9c2cdfb775978b0feee265a6c41991c1dc4452615b78c906c7ed1bd207969d98d0
+
+SHAAlg = SHA512
+Msg = 8dffaa9151271ad22622f228c892e1d9748b3c394397f2cbb6febeaa9244a027eef28db48a9a660162152764830f617e1ec6ea1cdb0ed25b6f999a107175a16669d6dfc92b16d50363fac4a570371ea976343a55ae124b6301ea935ed655d44f28320899dba35122505933b3371201a2a45f95ae65ab442a9479125e68ed212a
+S = b329aef83a56ddc57cd9a0e15eb0b0b7aea7d78d5e8ca3982bd31cc825a0cd1c444d9f7bea9e7a27f3bbb3761060ff95fee1a3e864d2108fc40b64786a96a6d62d201217e03a8ba2c07ee94c267149d1e72cc5779b737e8547acd6aa4bba3ff38bf9687e9e82f511b597ad7ec1d795c36a98bf83a90fc86b0cad41953360738921936a458674b2e9a7012ac3029fdb0a9d12318202d2544a0d976ee536e03b7e8d894b3b9c762dab0110849cc1eaad747e3d88d7dcf49f824df027e645c0b9294e655d9fc9e1ef95eb53aaff5775c349486d4b5d67dba29b6217f8b9976612b57e16fc1f99983f2af04579938606879b7c7253e870714b4f0f24e26dc8c7a6fceffb5f98e3b2fb5db949d2f98cd1ae1aa552696b48c39f678e154351cc756d3e9a97f79279853ebd0db9ae6859fb2d5721385d06f5565a3a8ff0992d517acda1af69a92854a1b32a79cb9e442a90b055bb2ec3af8d9926a0d857e3cb1e7e4a7300d1accb9492ec7832af453529ff0f4a6ad3259757f707f713aaa5df231f7487
+
+SHAAlg = SHA512
+Msg = 71d4163e708c121e931bb9692b217dddd35c7346f61cfc9591f7a4313abd4a9262af820bd7eb37e78c2b95b89daf25ec8e783aa1d4b78dbb96852433b4d478b109a6d65eed7d06f3fe122b172149eae7c365ced66578ebb7571ec218c36b65d2ee22dcdebb28c66a7138432cbdd712f7fb8bf78cb14860b25c2b4789706b5a1b
+S = 2522ee3bda30c0434e54b199da8c9733964fd402b707f5b330f4f754a0502c7a713c7814f0e851a4a4db72690db96ea8b8813bd8629a948bb30c1b8272a816b30a755fc6fb1754167c3eb1f194395907a56cf5a73b4154383a05b78b731fedd9077f3c2267a5cf926697871fe0a4bed9c219552dd1c87aff50613094bcaa2dec42a35380a6bac673da2594f824a8f32f21d7593a3e49c78ee280193a478621d3b095c16dce72935314d4a2323eebe7855ca4738a19b5a31a5f95ab91fbe1289c02fea7a65b91327b7b9790556289e1b988e45d50eb8cea1581de5d5dfd21001c73b43921d8b21b9644b0f2b96ee6b09d73709c33338143d6a2fec559a436c5ec865d3acca5fee654f1325ae57255dfd42188c84dcb1f7c1e86028a74e31d736078741ee97c39a56e4de00fc12b8051835bbd0d8fcae737322099adc1017107022dd15c114da57e78b95681ba9945615b59da90f5a2a99a252eb42b2006eedd6e78476c2905473ee6b4f23c1c5cf0b80451c5426ea009141cb3fcb0df2ded92be
+
+SHAAlg = SHA512
+Msg = d00e1529228c79a20a1c3668ffa4a54140bb170bc5c669fd7560d9309900175e91d5a0e9c5f5471fdfb714bc385d52b08ff7e4230184d8b735593f0dd8c73b8a49f8595b951a21b6a5bfec63b684f67c0af1b471dda1684e9ba3f241501fe957603dea86784230f0c4fd65666361b82b187330fb4267404c0e059bd4eb52494b
+S = 1835dd97e5093a33ce1e62d683863f6b3507f358a62fc879b524350fbc7330681cb0c682eef4330419caf8543bd9269b6d91d8e107ec38b6e9c6eaabf906457205d52a900e05579aa11fc581375264e69a925798e5a348e5a16f1567d5d0e40853380b34deac93ad7377aae8a27b090d0d3a92bf7a824d926e2e35a0c3bd0e990b591120d74dd9b052a73568e3c3f29c5a77fb1c921bce9c1e7f764aa67bac119f5839a5303860edeb634814c2386c831fee6200cf55b6bfea058b795a0fcf26eb7216ae1b7587c82e5685e584170cbddc89a77e0989d4ce5c3c7fdb664aaeaadbce1f231e64798f6f9a85456b5a93a502126a80e2d21f46921cc3601f5ecdbd56998a63b865fce7eb299f76af40e91281bfc019f40e0d46811e383691e4024c94566f18024ff2b22aa7e1270233ff16e92f89c68509ea0be2d34511581d472207d1b65f7ede45133de87a5ffb9262c1ff84088ff04c0183f48467996a94d82ba7510cb0b36cf2548209a50603375cb82e678f51493345ca33f9345ffdf54be9
+
+SHAAlg = SHA512
+Msg = a35926685561f09f30925e94d74e5661892a2ddd524f751f8321163d611ea1591a08e0dffd46b208e98815a306aa8514b4db859dc1fe7bdcdf50c095554bf8b2f4cb9f884d70e55c2143bc26199c2f94b743f5528dd54689ad69eda660749f5c1bea8becaea632a4bf0c79a577edfcea7baaa6861e9d7f2dd5b4c4f6eb5f3d5f
+S = b1a9c45a264d2c9af441a7b2d330dd788089ccef205d5d666bfe864367be9738124e9d74648ad99160bd3af81a81858babe667a5d95c980fe2f6ac34861eb2ec9b4b4e8b642ef3820f56ca388a556530d42754c47212e9b2f25238a1ef5afe29be63408cf38caa2d23a78824ae0b925975d3e983558df6d2e9b1d34a18b1d973ffaccc745e527ce76c663e903719355e45cd6d118ed0b85b70cbb8e496411353f84f8866a01fadc819ca0ff95bbe2cc68c8cf78da5581becc96247b911d185ed1fae36c4cad26208eb80883f42a08123dac68d88f2f9893cde02ef5a57661db2b3e1e9269cbb0e15c407bcf55d92e679383c90802cd0bffd469646dcb60ca01a1dead43228934018391dd81f8b7e797e527fbe1815b91bf3cd6a1f2ffbf5dd166acd5526761ca8bab5d463fb9fb820659f5cd50f8150f12f7e8d52e77773c1e6480c2cc184d411d641f71a9dedc2c5fc2ec37a2770a9383bfbf6a489cf32b56a12cf99378e39b50bdadb9f0591b2065f9d44e511c9dfb6158fddddd1bc2cece6
+
+SHAAlg = SHA512
+Msg = 1271a0ddb99a0e1e9a501ca33c131b0a1c7820a397790869090fba373703ac38ea00a9a0ddeed199d97be1801ffab45206710a61e5ed894c3319012ded0ff414386e56b548ad915d80afcc2bdb976d7c8adddca7dfa28aeb694033a5612660c644e32f85c2805651d713660a38914d70f0e41fdc4b3d162ef3acd70659eef637
+S = bffd010b2ec4e4a32777b77619b87622f8921dab56e102c8d824fe52b5df7a203fe71799eeafdcc0c8872dba6a374407b5639aeb5a30a904712f15097dba0f2d62e845412395cf09540abd6e10c1a2e23dbf2fe1dfd2b02af4eea47515957fa3738b06411a551f8f8dc4b85ea7f5a3a1e26ccc4498bd64af8038c1da5cbd8e80b3cbacdef1a41ec5af205566c8dd80b2eadaf97dd0aa9833ba3fd0e4b673e2f8960b04eda76161643914242b961e74deae497caf005b00515d78492ec2c2deb60a57b9dce36e68dd82007d942ae7c023e1210f0be8a3eb3f004824074b8f725eaf8ac773e60fbbb7cba9630e88b69c8bcb2d74dbdb29bfff8b22545b80bb634e4c05f73e002a928efd5a6aa45621ce1b032a2244de48f4df4358156678cbe039c9ebe4cee945a25b9038469fe00c3092936a8cff9369045f906733a9d2ab3660182069b157ca8f9b99a71fc153c68301e97a38fc3a87ae2b6f03754e6da82d0b0726e0703979c9320289feefbcddcd9d706b71b51e9a1b9dc1412e6ed4b56676
+
+SHAAlg = SHA512
+Msg = f30c783b4eaeb465767fa1b96d0af52435d85fab912b6aba10efa5b946ed01e15d427a4ecd0ff9556773791798b66956ecc75288d1e9ba2a9ea94857d3132999a225b1ffaf844670156e7a3ea9f077fe8259a098b9ee759a6ddfb7d20a7acd1bcb9f67777e74615e8859ea56281fe5c400748f02d1a263b1867a3b51748ab70f
+S = 345e2f60f7c82c89ef7dfd7dff2bc2348bab020479330899d4410213b35e98d9bac92fd8ae806b5bce8a6c4bd8275b0facb4dd13f9d68ba67141fa5085264da6dd685a6d212170a2c9cbf2cf5930180effc250868c984bf50ff69d6069ea28f5bc1b63705d0732416fd829a5f5d6217462c22a33fd4652f7c1d198794646c08406024e8163a7ebe39cfb514c5443897b5894dd19a213e037f27e0ffbd6c5447a805a54dfdf4f65819d4e0fbee25e3dac47fb6b636e8de6190adccbcee937d0977b35b973606b0ca348758b50cdbba028b73d0ef01c56014c031c598fe8db87d2ca4644770aaa0451c376ded82ff5c6b8e7d2ed9d1c8a17c3122c128273c60fd1b0088dfbc9c927f162e43879405964cb11ef7899123feb8f88dd2734df98aa696d936a8df07000e84af90101f7006a9bd2549fdd0ad3f9de093012d32d2afaa828017ee9c607cbf5b54f223666d4b5f3e26e0dfec003961b83d83de39ff6a0e81e1883c1db4aaaf082fec5aa30a7e578553d89774c67907790c96dc4f5be4c8c
+
+SHAAlg = SHA512
+Msg = 132cf50c66ac4cc54339751a0ebb865e1d3d320562fc905c4abd1e78e464066c46c3a0c02db0371ee35a104d66dda864c6133e37cfad9116e883ebb73b295e7016c34ea9911a309272ef90114d8f59fff0a75193fe5ae31ed99121f9c59209bc4bd507b1dc12bc89b79ffe4d0df9209762a1730136290cdee58ec828ccc88eba
+S = b12503b7b2f783618884174bcb9be10877960431ed6363c807e12db71b8b6bd9d6401d064e253740158e8b900152d37faf20333a7d80b3d47c7c7a3fa12091ce31cd8aae272a4da15fe2cb5cfdea541195a469c96bcf695e0b526dfa48a59003c6763af8136392c4b8d24db314746f42aca550acc65e074913ab82232eb8593509158a8ba34bc0f0e3125a834a3ed2d6a8cb1d085f234ae868b86aea8d6f82e13a08842485066e48aae4837873150f44475e12602b552dcb34d1f9fdaadbc6bff5134c6fc76263888be67efe63ee1840fa08c49938858a9d48b1058d18976bf2e3bfc625552f75b3ea44eb91dd366865f240a0c336a0110e0fa09d09cd94c70cbc8895ae3d44ae3dff545f0e8c8cc662ecd40f9099a952494396c6b423ebb463409969281cdd54ad87a308e487ce19745b30d5da76b98d2aa9a007a55783b3037e5b8662322810bdd11d86dc3f61451149391fb2f14ed9c17c751623a4042ce7edb875ee27bcd1f19d6dc9283ad06d15e097e2b0b15a7eb7128adbca0aa6adcc
+
+# CAVS 17.6
+# "FIPS186-4 - SigGen RSA PKCS#1 Ver 1.5" information for "testverforgen"
+# Combinations selected:Mod Size 2048 with SHA-512/224 SHA-512/256; Mod Size 3072 with SHA-512/224 SHA-512/256
+# Generated on Mon May 11 12:12:05 2015
+
+[mod = 2048]
+
+n = d39a426f8b81cd954f3df5512d6fcdb796457c172b6d510247e45ebecd1e0f7e8aa3253a61293a7b70094b70d65d73828719ef6aaabbb24e083b943be775b0bf3b5a0dc8388433de78e0c113ef7763f767ddd1542bcbdd9845919886ce20e28922754af2a733204bce9b5bd50140e18e5ba91e4800b50ef30ecd48b4ecded67a2f7be8bf7d7f14378a8c9ba0e6103d02f1685a334e46713033c89908da2e9f8bf72cb2a529281d4dc66799cc2a63c872b6bd5ffc1fa9ada236e7f8d5796dd9724e5e4ccadaf160de7f2d69c84009d31e952ac808c89a784be70cf60f42811928abdec6f896a0fa5fb164f9f4298a5a8831f6684dae31f2e76146d6be14c3ea7d
+
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101957
+d = 057076fbab758efba2945f16d3456c21df4b7cfe1a8a762af8389e42e0b648f4d452d8bdffdf2097f75bc661efe939dd99c170c1672c9a0f21ad450347333fdc52f350d02ca1e6516cdbee38d3eb56b15f3f062b0d4f0901ed9a05a566917c5c108b20e0da091b8ca9da43b7b066d8c28d849068f6eb803d8e84ff243172c258cd7bd18858d2648dd7a55a2cb4db3feaf3171846e3e2c883f50a192be5ab4c79dd330584adcae17f1458bcb2ab43e3929cbef840e9999bf0eb5601e88ff8758db564a756346d65d8c55f1b11b9b092fca7f6b2394ebc3109b3d02ec5a0967ea645d127fe0fb9f9fa71637ac6f0b92671809f4aad1278a6cb5e8a7247fe53afdf
+
+SHAAlg = SHA512224
+Msg = 2ed1a4a7188b534678ece3b40ecca29e2359d2c8b5aff149d4a93ef84cf67822846fe97ea6a7a36200c40a36ab8e922a6ac6ca24d4b99afcb615c8ecb3fac1422d549758696946c6edae3bd62ddf1739674eb0f8cc7c58ade0e663f22321e31af129b61fa7f7c3dc0751807cdee6b833e39a8b2ce31fb6c21bc514f2e6936510
+S = bb2969df7eac0f17e07992c00c8b561d1c21482f042a4fc95b739aace629a12f6086e399bff9aa71268203c1656ddfc890570bf49dc75d8a7bc510413135ef931473b0ba77af4e5691970466bc2a5ef811b4eb94269173bb365ed28688c0078a11e0776ed7f539717209536079dc7af515386698c1e539dcf0b3c08e584e3bef987702aa02e5ab329725026dcf3fe64193a4e27451e5e77713908f07c742af0a2583a04c1f1a0ac4e9af5878a9c8e53ac1eba469ceef836f3f6eb9ee2625feaf933905c308c21aa75a76cde1d8bc41cf77beeed6919dd75d3834b3135a781cce01a04b468f339bbd21c74a323793c8f439e6df0f3dd4226e5ba8c712b29f7acc
+
+SHAAlg = SHA512224
+Msg = 0553550199e9dfb9ac4260d6b44e1376e7b9083af2ca764bef8b529b912a206ea29f0a18b08f2f0803703d05d2ef42b8b68ebf6b5e92ff10851ca68521968d16dd50cd44ca6b1ac451f753cb6d58568917ee19f301f5f7c686a947c9e1ae33529eb0c80b4f4749f6801dc9afed52f8f2f21f3e5c42ba0676dc7a5def3b3cbb29
+S = 7cd30a88ee2da986e79b74a23a1831e4a95f9cbe665c9ee2e87b55dd13cc71791377c532a55a437dd4c473aec38bb094c876f67b62b03d473cbf868eb56add83981ced4e4aac6deef6835378e8916a434b9119d5d89204b858913889a4a1682c711bd1b951d354902758d0ef78cfd63b6b45d7d5433f3d4dd52e945be9d9d86c620585df3592a51b5855fa412ace6131c14be6ecd77f15ab7e77f55255bd5ad2edfdf8a1830b4be0836b21f806920c6998ccc3262b971cd4ee0ca48a60fb90606fa0c16d7141a92cac3c3c561d0673d700b0539e8b512d4764e5be5a9ab41d295d1a1e80f342a4ae2df75ac5dfc7d5f44d3e9bdee9cf25e7d2f04fc707b92cdf
+
+
+SHAAlg = SHA512224
+Msg = 63f2e16f20af0c0366156f5c16138b075bb7879f30a1d2e523b60a1358191d6ed057ae1bebe1ba332cc07b1a3d848c0c337d4ff8122e8c9294ff5aa4263243a43418a38ca68551e6ab818126b540e93dc555236be822535501930957ca0c691b169f896b59831a4369c14b2b8631eac399a5cca0b9647056f3dadfd64b8dd6fb
+S = 796cba47cc498f03e78aca4b5919b6f0df5ed22e8d62b1124a6633033dbccd2a54aa9721d00a1e6854c1fc348686ad5cc86055e0454ab55365cd871d1fb6be5575eeecc10f1b66e4d4e4930bcadce6cd2d8bd4af1abb2ff7d905475e29e4e2eefb71d6ac7da59ba2efdc8ea16c2fe5d130fb6d002a7ed81e88a29c08010766c74f192c8741bf36f739198bbcce1e44a86d09251f8737b3089fe145e110bd2ed116635d7a6ee09590a390ff4599dd08a50900f283e2dd1c1760bd9b0eb8603fc17c6f8bb58aedf985b5a58784b1b0162d8532244835092afe4f647ce3110beb934192c8fa80c202e1777511f74734d8ac138c3d18a605b4c7250757738e2c86f8
+
+
+SHAAlg = SHA512224
+Msg = 4b94be1d97d9b71f112bbc5abc55fe9160cab66726e65cc462771a7ab07c8029422d7960783b7e04b15809f662fa4df0655c24b093c64959940fc716f660b1007d3a1442babb2a7adf1dd063d27f3ab280e8e63d7489ce62a842e2a79b68b59ea3c6770c85e123494381f9ea356c2f9e5b75e456f2b555a945195376c61df5cb
+S = ac4dd101f9d7afc504da2d6f920a4b0075eb04604bab6fb9602eed006b3cb19ec14ff9ecd175df7ced0a06f0c2b6270b9fb022eb4950c570f636dbe134070c8b2b3b4a3f47f843c3a9ef27806b5ce8d857807491771134ca4df42b68c51d2181c788ab78916b296b75796b7b8e65487e962fca3f1ef941748cafecb184cd1ce5e0a7a9af1c4c11b08b0f78f287c9e4227621da2d5040424645c9613b0630a239cc46977e9bcc92099d471a696955b939831454b4896cf0e453d2daafb56793adda28fd5667e7448f594a4c7c080f2707dcffceb739e431e0309fdcdc6129167c083ac223d1d5490fe6c9f6b46338b6482589850cc5815777099d48432155d39c
+
+
+SHAAlg = SHA512224
+Msg = eda30ca60e21329172c70ed55f113a716b911222ec91c629b0faad4eee75dc257dcff89044a24885f2320e11ef95189d9217927194dc1e76c4c72740fd9b714b5560f5859809ed0df5532b3bf6f0aee0b6e577cf4e31999c90af90a3f83dd34cdf1ead8ef29d48b2e3f30b5a5e6b25c13fc46a4402d75f227a7a9080c6a32ab0
+S = 5f7c8326b43a402c8593c4972a127b6573fe9f482ccda74c476981ba329da45d4d4c5b1b5030f6b9bfee4f5d8baad7c09f0e25b69b938fb61519ee37fe8f3b9ac22b8dc34fa30d02d5ce942ddef0bbdc0d1a340ca06d0433ff319eed5963c0e647acfdb772623e743334ba2514dc67095cb4c3ded5ea0236ace1104cb9092b9bdd1dc9e730ef5d2f8b2a34735d33ca86b57fff5340e0e7ef4693e6cb0c178b26524e250376f7eb0a52c33891f7e19aae2b2647f5104606b7f6638c0782f6daef8186e22d35de9329447eaf4a61e8411edcfaa19c2d39332671ba402b96e1769001278aa1218589b15b6cb154e6283b43e2537db37a8080583b09a4788a5cbb7e
+
+
+SHAAlg = SHA512224
+Msg = 0219c1b20f988cb51c781ea982b5528ca14810363af7ced31a715696f99acaaca124e66f535f86dd66526848310a324e2b32b70c51e4768fc8bf638bc43aeb50a83732f96fdc9fe74a9e9a6e8a9e94cdc139486424da412134139d3c9eed10245f7c2cb92bb6dfbb10853d82571a7ff0ab854ca57d823871a6968b0f4e5b4310
+S = 858b91cc53411dbed6483fd904ab75820f8c8c9519297c472438492a2bda440aa6ae35dcdfdcefd26641a85f33540e0880da323f09af8787cdf5e160e793de127882edeb1eb045f29146616cdad622abd183b60c051b54adf8fa20726f4e88cc54c0bd9723d3553eb7d0687ce0fbc43e53e2e8eeba009b7545e97de3a457a8e7516d3d5ac4f18a98cf678e076d3a8e3644919afebc2a785567abec9f8de54e5ba051620a709d2bfddf0679666ae17b1cb6d7cdc5164728d2d77a7013392b418c0e87a4a89d396ea955cbc347365f67a5e711504fbe499715ff0764feb75dc0956eacd964ad41d399bf17825a2f4c33b710783903367d3f50994e3eebc634caf0
+
+
+SHAAlg = SHA512224
+Msg = 8bf4a151ce9d8b24dc1a65e006c04024ffcb7c9d4cfddecef688e210822e53d722a718382d4351a8cdd0a307f8becfdda1818ae32f3789c52e8bdb2644d97be46793269e4ee36a742591000e85285be0a35481acc88f1a4801fcc6a11793b400c17f718c19c4fd114d2524ff97450bb66f0c0a00ff4cb9dfd7a54e8ae2a626b2
+S = 2da985add2123356dbac7b673198cedf499d7f0fd0db13dfd4e56ffee3f267d82e0c4dc0e64696817255b8dc6db336ef0be6a170dc30ada05466edefc04f5e36afe144debce14be4500bfbf87619c0968283b2d2e4b8068f10db18b64668d1d0345befac543971a2c2fa9f1a41fc2dbf6a4ab0f649b6c639af54b52a39d7d1af0da135e0414ae89a1cccb3a944a99a719e4fa6461757e0d1ae26f551a9337c557435832b30a3a42dafdbd43294d3aeaf52e7086ec8e47509e0a281207a3d4980240d2c11a5a577dee6e8fd61b9b90e91c4bc8f5157d004d5e4cf6c42c2dd8bfa253742f27d36d709cb2382e54103d911ba9230e4e348c822f9468525d46abb5a
+
+
+SHAAlg = SHA512224
+Msg = f1de99141084e4bbbdd13b3ce88c97bdec31d9a8599fb000f611bcf6064ff4b7cb26458949157b164c496507accc34d5d0f925dc713360b2a0d61fb60b6e12ec7c270308a285b6c81455138793e486108f6ea7b0edd9168f08a3a93ff61aca960ccb1ab9a43c5b7a1dde8ce4243d5513327aa64a56fb9c3f3561a4b94fbae25d
+S = c6201050e62d28500cce52aaebdebf30a008c6f491715d75cd60a3e9b5230e88e902120e536fa269b391e824f262457529e744f13e098e8c43832dc1db1432235b58d88fc35edb4c5de8854d2198a708dcdd274f267d40079169b29b78edc969462fc623cc04269f6eef15b1e6fffda09d618eba04512371a855225ae5cb95b3ad455373ba2734879ef6e711c3cc7cdad9b107bed385a29124307e8e3b2bc506923f08802446d1c0e6d91208b5242f20ed2637cd47a20f7e1839de8fb77109467f4cfd6e04080d5d8fbcf2c3ba7e7324c2d26ded80b90b053d8b431879ab73fc587c0383f59ad7382fc20589a740d139b8b60aebddaed1866a6c47788207b782
+
+
+SHAAlg = SHA512224
+Msg = daa7f32aa297904a9cd29e24437efa2f02e611393c73fefd8fd8f2f75a8cd9777c7d3af55f035fa43612b74982b5784edbb78812eda39e84c1f0a5f03e756119ef23548706f2e322a11cb5004d8a5c7cc88b37880ccc9644888520cfb1f0725cb9ff09899e4e62ed67575ff0abe5ede052cbe4419fd52f646fff2c3bbbe5556b
+S = 1a38bf4fdb86d3838b7ec493930b8833a65aeec2cff022f24cbdcef0687e00043d815bb680a394bb64922a97f92b908a028698dac233219801cb353406b5dbe638d0e03865916905b124b88c58dd349b7cae77964a54ce019e9f98cf3fc48f9f735b28d4ac471a423851e13cddc377997b33337f0496720b3bcc628ff33d1f710b6880f19957c144748d0c189a9c3502697c0f06f5e29271cf52c3a3f8ff489abb55eb26cfdda242b0e7f9fe2c9e8cfba5fc20dab7220a62b391f61d8d95f7d4d623f6c39951f07f071918b462f971c70937674abfdd2c4eff79e7953d4214b217f972e0a2ea6fabeea818d830d723af1c07c23cefd7b55a30c0be2d452d1f02
+
+
+SHAAlg = SHA512224
+Msg = e46df524b45b52dc601c061ad57317e1d6acf4eefd8ca04cfc8413232929ded13ae90d3b4cf651652b875f41cd4093c51feed9400578cdee9b1321cac2b43fa3d8cb3072c62ebdeb4053d45248c32d90f4cb2c8672750aa149b730afe1e9e3f1467c267129eadc9528e92ef54fe42c6adeabb7674c6a9e8d8dd8077991b011e1
+S = c66d6dd789496caa62af318c023b24fe99444c0a2f179414c03c03aa3bcfd547d74e56cbc2c48a4678ffa3904964c0b836717d115538d386138096dec8e5a329e16183a2096dddc6a0e3c559c3d273568eefdf3d75e5af3bd433e3657892700b95fdb408f8e5653c48cf5672cf9d838a9a75fbffeb5b85fa8453198f566195a3bc2e2bd900d15b752b5395b8f79226748fa2e39d6d2efd701bc86d18f6e1582b2129bc7b961d8fc0d00f464c7922b8ab3d860d021ecc40df63bd8844d47a8f9d1c4d919f85da59c0c048db5b5fb64057be25fee66966c7486a796fe94f6c32b5464e87b6b59e30cb63253f5896a03ba55866ed2e8c8414af2823b11b43446a8b
+
+
+SHAAlg = SHA512256
+Msg = ebd3a776554384912b8b900160a07c024f3ca4d05229411090bce06b16a0137c2ad466ecdbf794dbddc4fb8294d94e176fbc8af1771f2bed28639f107f5cfb6e5454ed4aea52f17ec59cc81ebb7a27584e3dac9e3980150849aeb4f36ec41eef125824d8a9db04428a1be01afd0b6e8b95c7f21fc0d369279ca3075c0c61e4c6
+S = 802fed875ef06dd2fad2ef123f14b360c0ed51eada42b4db56d8e62627a85a18fc15eacd2467d76e84efd1245e4e62ff9dd7c5dbcfb3c83d9cad6e0be064a3cb0100f3ffcd4c4025d654174a91a0b13767f5f8352305e61d54cfc61b9b801c57e1287e759ea1599b68bfcbba043d776e3f1e75887a1cc5d1ab878418bc15a356b479e6b4d12b7d49de850b2976b8113135c0df094ee476a5d6ba3b2a3a03ecf1f6e97f1e0c3ad17245221449a1e0b69b9441d97f596cffdbd93041b11757d19d6a3a07c7d204eb0f53ac94a5e3bc69d8c49cf1bfa4ee9c1e4c077c5a18296bef3a0db41524feee3cc83c2c2642c633436e635f11b43056c8c590f02ba3d2dfae
+
+
+SHAAlg = SHA512256
+Msg = 266070328b55680fe6ae6154c257ea69b71cf487eb177bcad96a69875134b7dfc0bdd594b2f44c1c951ca2f4c0c27d37b4f20c6fa1aaa3ab2c8fa5d26fdfa73641a7d26cb836895cedd14c94ffa8dde25b09a1213ad448536b2fb1f0527a077e31863162a60169f675352adb88f3509134c97b44be7bb4e91eb1538a02ee1fde
+S = c0ac3e5e77fedc499caa520f186135588f3e49e2034c22ca5b74951d41f73bc656ee958bc43e9fc460db006c94e46b03f05c5a730b16e6f0ee78ae32cc6fdf40994fdc978529f97452db1f7acea4b8eed5aca0a29d7e27e5625aefff258b8f1468590445202cac19d47fca0b0f51e1f4d6dbe53d9e5abd26f889354ec2ab369782f4f1974f6a96141d509cec6e575e83dd7175c61923bde8c022242c089e080eb209604d90aaf8e75771b13497236ab10c37fb9eccb13ca8ced8f54ece38b0ee40938464d9a423bed7d99a2d5ba186bd0950b201511bcd79e379fc3bf254bc519f61beb06ab3bb1e1efaefa185fb9db286043752cfd9590a292650bc86e3f8b8
+
+
+SHAAlg = SHA512256
+Msg = 379c93ef037a702fff952ffcb463419aa861f99682aadbfc6ec816cac3ca4fa5e496a0cb6481e1496d1d266e6252887fc3b129ac51047243732a9f24d9227e755f6573963479c0573bc30369b19d001311a8a12634633b33bdfd13fbb468212771af143abc8996c3322ed0d7eb6931be59ef6bed73efbf3413ea7b399dc5c125
+S = 4f11c9706aadddb4e1b7eb2bb3bb103622e196f1910263051797eb50144be64bff13e9ed98a0359010fbba008b326b2b32b576d027dd27f72b25309af9f9ed7055ba450bed042aa6139c7267bdb0a2e7ce42825e85a408c436cb34777229709d1002e8cc674bac7181de213976a204c34aacb705c09d113df285a3033f8d613efc0a1b76c323931c9ad57ece6c92ee5943d3f25edce1c909b2abe53421df9617acf1eb954957feec82270d75818710d0e6902ea907b8ec7b7c46bbd02d5dfca53f7d7638dd600eaadee55d897d03f3be1305f2b55d75df913d2954f0076c622d79a1f6d64e7a010b0c4ce4243869375be5348a330c79d6f23ea022db1848b73e
+
+
+SHAAlg = SHA512256
+Msg = 5621976367502d7cca6282203b39be61d495771076e3322f6a5627a548394535188476b1b8ad246b7ec0fced1db2f2eacdf38574a642446e4dc59145d359a5dbda27d4c4fa7812b563cab739c3227fa66aa5d550ac6251fc86737f988544e229e4323804f4580041c1a53a6df3326e7ff2d3ef0d4eed61c05d87790626a30406
+S = c7af1eda2595e00132dddaa70c0c661175446cbd0408c22d63e6c3deb0beb7788ea2980996c3bf9ac54237e453ff0c17e50972b1a9ed6edbf36beead7c95b448b6d071595bc768d67813c94da0ad60e0234520db54e8d7c0f1830345d5f69a42fc25f0e4bfb0fc2ab3cc16d6bc1326be091f60f94f4c5329080b4946907b5e65dbb9469da47b6acc0e91784491de3118916837d34f20d6370111c31ac9435f31957c2e11aacf0d8bd035a5babcd24b9c86eb063d60aaba2d82dd2a3b0a9a9d6ae1e00587e10062f9b9e79abc70786ce5f236f76edd3844e094aef5b545e9a1491615a15908e1dd462f0464c2eeaf65bfca63b16e41639bf6329feb1a23f9d4d7
+
+
+SHAAlg = SHA512256
+Msg = 320844c2661569bb86cc39aadca462569e49f26865406a2ae0ca148eca0c9772196cc922793ec41ff8a03c1f03a2105491ab1ef19e185cebdb2525fca411d0ee327d87161216561fd57383090a401e70699dd81251c1198c75e34c64d25a7e4ce40327a519e34743860db570d8c6b4338ee8c8d26684c89515cb33cd3b2fc715
+S = 9895bac5cc4c597b67fa64d2fdfa04a80f939aeaf2a77008ee3640aabeb7f4c9c9985180943ca6b1f5c69c2a80b82481203a273a097ab695dcb34e5156c2dbc91f8130bb7ad5c41611896f765e9dc00403864f1e0b356ed033dc2bc1ce80af7c5a4db8b5adc46291c1296b4bd07b9b8939b251d6b16e7c381bd9d15679216fdf26d70caef87e98d5626040e6330a1403175ff486fcbd193e490b68874231f286a41ae8d4064746b56d05dbb44606544b826c1a2a640311fea0da8c334700cd24f23dcf04cca02b1ccc926660a40eee4ef52b499e1e6d621adc5d5fba3dd1ad8ec821cce5fdc4f483b37d034b1e43c75260b6e8279aa19368ed11caef97767645
+
+
+SHAAlg = SHA512256
+Msg = 27ca9976ae87ae9965460706f263a58e73d5b08a6f560b1c0cc52cb783c82be1d2b51837b1b392b2c61c952a1c269418d2c3c8a010c5c7cf3f4658217a4786463f97f3256bf76f22657bc99c9933e5ba280b0f68ddf08f9c64347edeb634d807d838d249c59a6d6fa92b4b664fd2c1fddd762fe9bf1e8c0ce15745f721d748ad
+S = 55e970eeb2e59d99e8dd99624e17dbc6fcd116440a3c52f3ccbe44a1cff830da6ca689eecface8d741f75caf86d32a6c39f40c03fc5c139bac8534c58f110843b7c3be2029077c03c2bba8141f9d3c6ab6bfbc9b50e1e9f01b86c025e8e53dfb08945a9bfebe21d92eca4d6ba17e9287887870aa6128862536b8edec77ef67f7a487cf3efe1abef05c0f91c7bc754a9eaa76f6c52164f603ddac34fcaa48e4b108f1510d0cc07865fcdcce9137fb6e5e9b6056783ae28c85078ccbe79ef13e17bcfb9e144887f7f12e465331ec1aaab017881d7d8535852814a30ce30cc8f43abd8ac1221c3b9075e21a0c7b0b403adba4ff4f03fde2d453fb7982aa045e10fc
+
+
+SHAAlg = SHA512256
+Msg = f807793110d50bc5b9e8e63f6ea36cc6c60a231c9184677e24de5cccf19427ea5b4c5e66c8a4bc5bf72d1a9594b79af509d0261798871933a6763b415afff36167d5b87926bec920e8981ebb8a9a9ee54add9215d81b5a7ab1b65e2aa8fc487cc5a971b253ad98dc3530daf979d4de5e303a515c7cc7921deaa8aecf02138e04
+S = bc1b30f08663959cc99613a77fbd5fb4708601f3ccb0ea60e8e4097d841dbcee0ccde9c981439f7bc57e4e731b824206c9fc112bacbe1202f241e3e304348ebfe4e1c5fb1ce2f7b8ca13d951b159632743c31bcef015f5b1721adef6dcc8272314e04ff6132aec675899062d22017cebdf9f137c46d8e60136364ae3c1a6ebe162e61e94345b5f01c383a1d0d0e8b40638aa799c2c9232aec1cff1a335b3ca81eea40810ceae8ba0861cc1c58c7167c62e71e2348cbc975cb6d544b11bb18e9126677ff08ef2dda191da6a6b0335830fcd497cbdbc0e93f1af6e76a3d04f0fdb00ccaccf433e395acc3f46a33656a36bf19738e055ab700ac6bf7bf340c3bb15
+
+
+SHAAlg = SHA512256
+Msg = 6dd9bf3b2c5d312ad15baf8a61d6ff9a751126d8e0a42fb892d0279cbc106c0135f028f61d2218d3c0cf9227bc2bc6f2674c44156b3cbe06b34d0fc88bac7d1b02393bf09396321f057e025c90594368410d1084a016c62b8fd90900753508069c5c020fd8e10a776a1207112387fe62cdfb940dc65bce8fee1d1c2cc3d39629
+S = 0a77f1a9adbecac036af4ac6d9cbb3174cece1e49bda029f488293c560965ee5d4da14739a91f5592363e4e48524e4da509ef42cf89ec1dc0ac15228e7cfcad359294ec054552fe8b4f3b326ae4a423cfbda45035ac60d253c0fc3b8a4f97b1e2868d32ed3d328fa3720ec6930953538ebfdf2ab152df1b7a4d759eeb75a9dad89612819100d60491e0f5df6db1823f6129029a97d3b1b83d167cb5cffde87eede6c866b4c1527b710628c15c9d2506082efe7f3ca29a27853c2b8cf3ed38f95c119c534c69b67d42fc84bfa26410d9954a70a0845bc6a7a360126346861eba3c01a88191c1153892c253f2b9f94848735767abba4cd61b606fe98209b1839a3
+
+
+SHAAlg = SHA512256
+Msg = 1120ebd1bed0fe7773fbdef2f2eb01f1feebd5381cfca7f297c9c549c6dddf359114b391324fea74396c3cbed376dbf14b180f43d1581df17b826ed58961ed3bedb5b1f10be2dc9dbde6c3539a8d4f6778e8a3802ffbfeeea0b6e33ef627780b2ced2d17d0f09d9a064fb9d9cf9a23fb8b42d818bd4d12940f4e6dab9695484c
+S = b6d865ecf7a530f44db0ec48c9cbc3344fca90f3f995a797721690064481430f70d1c4895792fa96cf30538399bf0d72fd72cad522a0bd8844711767be2ec124afd6721ac1da69b27ab82299e9a04e727114bc18aa7926e2c5d023e9dcae02aefe0dfc6558af44cef4bc2743767f883c61402f6340111610c22fb0bac98bf4ce59f3a68f7bf3b972ab96ede3929a0fc6de4d1ff345fd240554a4a94b9ff1dda1e9f201cc76a68ddbe81a869cbc308051b4d23f4364504c29242c0106a9ffb86c185f70759086a176a0b02387ee274ac7663eeeb7e90125c3c3a939e63b2c6aa7009af62ceae5985e05e8aa9da33f7dda6afe2b2dacf7c67627e1fbb7f627ad0a
+
+
+SHAAlg = SHA512256
+Msg = 5c8c2f1d7fc7da4e9ba6e5758be726e6e227d7bddb0332228f7e3ecb6ba2e8c3e06b556a5ce077be7a83ded876ebd1b9e3b09e47a0872e9308aedc5d698b87dab790e6b582611c5326398d5b428aef766be3a453211747ef019c85133d312e1e4ac38b04d892f39707909905d809a8a2e18992e846fba4bce40edff3cfdd0315
+S = d1c062a5caade51ffc1b5da0f5aba1c737b5b7b745c8a3afbf8d14806cad6e2707d664aa89266dbc1ed6815659d8481fca830e0191119670f386951420d7347d40f2e94bda8e74db2d169ca4c169fcf63e49d062f96e7fa843f85042a9e291a1c2f1460c6169a529355dd951fc1ad312d6a74d95ab38bce753328f181bfd6973787910b17b31c819b2fa02765ff7567fb99741e1f26a400e754ae01ffc2b1c1cde69b019982697c471fc3091a67c2f08f6728180b22f793cdded0c5ec15ce611ea353886c97bc45779fcb2ac07a40877c1771bba6b337c706f6718d40e1e7591d5a0371d2ee7003c087ce9244f56381a9431ff56ba8d60b170c19e02d65cd226
+
+
+[mod = 3072]
+
+n = a5e68e379f3c4c3c908a04ce63c460423a7a10a16df4da6166fcd8b141000b14c113b216fe4f5f174a5935c937e0c6d83286ba13b137c4d0be7d7b415ced1d6dc0951098a477dac41df6382b9a50108f57455d853d4d8663fefdd5017a533cb71a8707ae4803dc2cb93e5453573652485eaf9e175e095c7fe72df7dbae96902c15ed0ef968835e72cfbd5290d2e3ea35ace7a2d30e58687d388a3a6540cb4706a6e596a8a7cb9e18741c6eab632a2300453fb47d3b543381519b7c727913dbd6e037af5bc8d013c3fd16c04ad2ca464041898c54b0067db757b88dda0a2986b4520c514caa0739b30d1da85c0c84188507ed3979bafb9f8cca0b2d6dde20c6ac06eda11e6a69bd9e9bfc3c35a1d4b52b85568105ed694c33ddc810b1d4a506538cf9f4b3de2fca2bf899c9b8b8911466fc0830cc1f3a9c70356fb9b2cb9a62021674e80e024b89bcfff00e633c548852d4eea21a5e5ffe7f7ff86ace07926f4cd9ebdcfeb90fb2cbaa9152f79223aac5fbcce9e66b6ca9d721f0714e6def0699
+
+
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c9c53
+d = 06903d86fc4b1351727ec45d3bae17c70b180f8824a087e8afd452850ee2803afaaf599b71c07982c23cd8b09713cd1e93526ba803898a2674fdb2d8c2716b8da670116ca4aa4fc5f6c020796ad5c27a6d1a27afe8c2806794623116494e6374e773c9b2686f2453da69747ad2e0b68a490e7e513289ace6f6d1a0dd990b222cfadb6a800f9dce7bd3995cda61e1f590e412555515af9b919bb3823da1b5d6beb47fff2a28acf8d7f40dbae7263038680a4b642d8a28048509e2db9d41c65c23eb605a4d1cc64f140ff5ec7d46afaef5532ae140f9a50f9d2763f2d25080b9afc7d35bec13a11d34c4ab95ceebfedf0ceac76e7ab1d66b9dab618aa00667715e6054a06add76a73ac5b9a0fbb7f14015757b9d07c70114f4d3759fac34c22ea8ea1cc9af9761b688fdfdb0f481615675c5b70759a202ed80eac1f60259653537d132bf2edf7770fb376f513056594a558ea9ff66df859ca4cfad1447cde2299fd2658f8db01bdd15abfcef391a1ce4e0d6127dd9464048b2f92a185da88abc6d
+
+SHAAlg = SHA512224
+Msg = 1480473f19360f666e20dba9f0f29b073932ced8cf9b50529ac473529cfd525adc7962d5a3b34aa3eb0af5d115aee5a8dac0caea84b553585efc447769e0c99450af09069e1cffb32fe285d6e4aab2ff9b2f665b5fa02335db461fbd1566970859696559723ad59f21f0b53ec7adab1265c5ccb1c62369f1fbe92cab085764be
+S = 1f954da53b48fdcf3dc3e82c623881756a17bd938fe0c3610defb7b648b7ca0c274df369a5548edcde37ac77e8ff0703e238a11881e7a9da5b62bdc6147c29526126de03fe75d5e8602cf32936a205c26928d6b590cb10d4d0982f2b7201bbdbeececb9e8bf55ad67012b722243c4aa721ce8370968316fe9326fce6c89c5951ebfdd7c3ce847532a4388a980495af4a6733d823f9dfcd0c19c15332946282f998d38e1992ba4b721c45fca9e51289a9693421206a968a49b14911d89a2fb030e6cb4b949b0a3d6b2486807c8e2f6be81ac4369cce00d600009880503dd4f5635cdeb056b20ed320e9e9eb4432e9c13cc2d091f2be459b3900cff12b2c270d56775ca61b2d80b83528c02d9ce35e42bc36b1a56b3dd6ce4e334b331034e6fc0ba07831905e83d0231e3468db4c04918b5a90d508f597573caa1f265c5e9a25e21801aa6c39ad95b56dd024b3818f82a72892f9827f65e9f5f1346eb71baca0c2f4f2f1ae5f7f249286a4f301e5e32c5746220d41335078cfbc511c19b2ad5ec0
+
+
+
+SHAAlg = SHA512224
+Msg = 8a09fb05b7e6779636123ac0a347603aa71f6d8f7787ed2a9d7157affbca37920dac8ce26ed46f659e56f6ea028f58db2c5c52125d89c9ed488db0a519742cdbb61cf67445a402a7ee225e54e2945c989c1af39e676263b8206318ae3d4ed1560ec10164433e7584afdd38a64b3db4997ec019dc9bf803b1ac5c57726e406d28
+S = a3baa7ce193ca98c05aeb3defde2820bea072d4dc02737fe8e3492ae4b329a7b1631c9ab4ffb6180d33aa6ca27b639d04fca9dd46ea82f0ce060ae56ac15b52e5116432184ab009e57df080c2ae17ec7a4f33613b846b1609766b084de34c0080d3695eac5dd3eee83ee57bf70b303d5ea7b1a96de0b32578008d6149069767125fa1afd05a54b734c70dd8c58b07d46e7e0d065717a2b445dce21b115522d5c0598504e1fa69a633228b713e4ad280d4d855fd1caefbdc0ff877a003584acc57fa62e791d165f5d63d33d8087c302311d7889c59443406708566bd2446bebbdf975dec7d42af661f75ea9b37a0e85de3e7d59fa53a62ffdcae04b1ed6d9cb69ac586b948dcb645bc6cde6789d465a1b723d8504cbbff1c27aa7c9fc0e8e8c697e253ad1d81ca6f56e6c7305b7b51ea93081a75b5d8588357f6afe8919122f79e63ef7ecee572bc1d016e68ba1ad93c5d4aa26faf638abe09a34b1afcbafaf4c32d15998119350a39df6b48affbda59ea642bc4aeb869a8dbcbd2a5a31e68f8b
+
+
+
+SHAAlg = SHA512224
+Msg = d3472740773ed7b3d637edab7ed397711e591121f758bc688d8e6f8da20911ae648c684de6342c0bcd5b60b24cbde27952d94084019bcdab6337f47c5858cd83d37aeec94694849a5bfba28be583d8bc16e7085bf26b756903bf1dc14f27495687d962bc81a606eae8dd5b3e336da3c1d34911adb111db2cd7ee91636dbeadaf
+S = 9289ade35270d2b5081036fce186ae1dfbfccd4bbddfe1ea5e685fbc47d6705f02122be8633370735ec308676ccb8b969353faf5fc01b8a30b35fd6db088d216380bc0076f54e77eed258b382bc051d8ea37b986074ad2bdfc51faf4facfb33f9d5b007836b9edbc857e4ffdd13fd54a167d54492cc4a5b808a5cf23d31639ae195390ebfc8b722014f1c1a1806ce6d7ad9432f706a55cf6184737e99beb5880e70078b821ff414c0c65506da170b2613418dcf2d1dffc51fb9e4a109382c4c5661201cd3a696b64186f184b5ac1ac3fa50fcfef1f87757d01685d3929e997a3a23ef35f2bfab09c605cdc82dc322c290741f76b4561f1dd388a1b916030f00a4ced805c68b833fba956413f77aaf4ba08cf2cd04f2d91f5cbdd4b6555b8bd4960b43dbd244464d6efb5e35ecd19102b4bc27b43e40e624505768900c165a23f4074d54206c2e116f1576529b29bd8385c1cd91b83aeb520cc4ba9d08e133f224bbb0dffa95d9ff5b60504ba9b3c008a90b0e49521570d586c4ae96f89892095
+
+
+
+SHAAlg = SHA512224
+Msg = c4db70981a925eccc116a6bbd9597e9763a80eb1f68cc984b3f3fcf57b8ba7d95f6f8db8570587d037261d5de0805718b339d1fe4cd50e526c5a0ee536b223959f500014201713ebad7715beebd9dfd19e3d7fcb60218bba99a5b558abeea08d6dc8f234db8fab220c4fb564642abbc90afa3fa19c38e7c3221d18d54106c6c7
+S = a58c3f480e1871ea4981352e8501f69c91fe6c8674bed6be0129eda5d86f1425584bb4c1a0399e5e1a8feff2190e8cfcc9945236f527c34a35fdc3448535c8287ff7ace9994519f78ca5304984c449165f37172b99bf2095b12c8e58f57faadb77ffcf76a3d5329cedcfcf825edd254d379fa8c4abbb5cedf75aadf04e841f8d0f4bd4a170c3f6ca6aaea4ec6a2eef57f402f02b99aa454af1916a8b117a48a8743c2be2642d8bc9b51bc044ea661dc7a0985772346c1f05355e03fd16f12af24e4baebc28538537b8b79f0c81e4777aa7afc7b82ae76a0b8ee96185015d6586e2d7db07cf503ff41ff43eaa97ccb7a1c48e45d2dd45cd0c531ddf1a34244a1fb155d9bc4990099c4b2f692f951d5992afe88dcc98fd18f32af13c479dbd6a725a01fb2f4a82a7957ee2896f384ecb3d19c5c1c802e9e1dd97ff2f8bc67031225aec773d5d52cc9b9079f3543aa0d053e9122f6b68a2224b8727189038fdaf439a1d03671891c3c7c13b30643672ceb7cfeeddf79bb5063004221ecb284fb6f1
+
+
+
+SHAAlg = SHA512224
+Msg = 4c4d20122e7676d8be5f347b853a4d6b41a08e96388e8b8ccdadd9e151d67dd31bd5a52ddb6d966c2b9de61f6722eb94bf3d73b08ab6b51fdd2188ae5d60d3f451694538fc4a468f296a2d450711b37e372aa71d2448e4e593e881de7bf647fb169268f938136d8ae04c71b30c0f8d73d2f093a5ad4bff2715892a3c529ec12f
+S = a2793a4988185c97755437fb1f0bc536f5f2d913ccffbbab02c4c61c96795d5d6d3229607576ff902f2314a3347e89b31c9ab74c102e7a3e6f6bb09a405fc7d210d3dd707a8330127ee437d498946680e0e37eec8318a06aebb72eb77006de51bb43661190c0a06454e72fa811b6208b17222169b0834b2adaffe35b5f9ff1f2a55ae94e9680ae1596e28a9d9a7067a7a1858b5b8ffd1e94b3274520e14beed4f8ac3eddb161b3fe8afc2eee5dc203814b665d6252901717d6de61dbb86c74b82134adec317e19f7456d22ed40acd41674bdde76be7da452349ce9cb5211489ba9b42e3af4a0e6b6ae6ff345a4c4c89f7ebf5d88c610cb87d6cac609a1e32fa9d613f4f2cde329984766cbc066a5f61a015e7cd7e08c61ff2b9ceb5ddcabac7c5c41a57f56829c5a3b86e85eefac304406047ef6ec320e1d27c237f59b456f5dc2fe4a351e56283da7da6b41e5be7e9552a2d41fd1a564be8ddc3e9cea9f1cff9f76fd808f9e9d73354217ccd93244682ee006aaa465754bc6d1ea936aa68d47
+
+
+
+SHAAlg = SHA512224
+Msg = 5dc60e1fe596a96be814d8232d3cb5ccb65d64c5f07becd02cf145ce525ab3cad4b25239e2b9f180dd9823b70dc794ad962e9a2ca88b0c7ef713572f6b5cce15187a428e7069d309b7ab05c8b83117e4b77f9091a60c1aa39ce7935182a06239106607a5f86df60d6093a6dd9642e577ff986e7c51c5bd4802b522bb01f0153f
+S = 556080ed70dfd893ef304bce1e8eb40d1c1542f76fd95b9923211bdba627eeb11f686ef91518cb9c8416d1bdb2b4a5c539a8fc729ef4a7512d75ec14fb70c877341c9f85d34e439af1f6669af16f47a62c5a45a3c005933221af60bd36cd2874a00f09d0fa85e615b3322ee6b53829803634e65bd122e41ee97df1ec69959dc29702f323a7b445aa4acbc778304ca5658661c38e078027ec5b28315762a963b82efd4dcbb68793e41e271d4f374004dba5edcae3039c92e02f97e50f0e7bb1150726895eaec38214e654dbab1426ba280ce4cfdd549f47cde618025e741dbe469ccabe3ed341deae95003da5503e232dae9a27e3a8a198f2c7653ba867cb37c983b29e66eccefa746821670bb5657d6ed8bccaf4f6612402da4362f7e6dc9c1643ff796572d00f17fb3783e6c532ebcc42ad36008656584844b69a25db5f77ca9b234e45587eacd67c49635d6ac7d24721b3fa61a67e40fa65941e6ae45b2b4c6b5af86c1729c5be6ed979c2be035ae2ba285692b5d5f5e558ce9866a7fdc329
+
+
+
+SHAAlg = SHA512224
+Msg = c37ec28ba564ae2cd1f7fa7e76747b552aee89f23a4efb263e9953bbf171350f40df1e02a14f5212a6dc16c5d2ce2048ab614c5510c99059cd7232d76d8c380750c721c4fd5bd2a5b84cd36958ecbb9853a1e9671be875dcad9a6634666f268219c033986091162a2fce9931afd5358e4935caf000b593f70599589a8520e5c6
+S = a4d5891dba2e4fdb5626d2c92a3874c8d378c8725b510041b3234af3ccd1d3744469ab4f9705ff9e16fea91922f02cb0e816b65c19f4ac5abff1d18871d8086e5d8c846f43e6cb6e8817c99ecdb94f5f2fc9c43091193bca25127670eb2c006b20e5f27f32d4a1cc8ffa14dfe910a3b3813a8bffd2eb656753ca667cfaab81f9ad7e6a48184ea05ddb980aca5731171bb7cb58dc30c379dd40186e689fbde378aa9d76ea5a4128cf58e4440c1a6929ac1ade86fed75a4a10f61ae7892f6961db17b0e2ca99d24ef3fe72d647b98ed83c743ce004b70863a35cd35616358ea2342288e74b5e4b229ff569ed47f97e57af8b55e8968c8d0315600b0bc049ccdfeed4904cd5aba05538361febad22926469e44acda42b4663a2c2755fe26041a5b8491f824a405ea377b55d4d86951736b699a1537d24f99fb9b72f142c25a49b62165691d6202c9ccf2b149005364b7d455f6b235a953097fd6aa2f5b9c5f4297a473f1fb883bd74b9a48f71fad4376737ac3906d6e1b14c53a3c035b585798711
+
+
+
+SHAAlg = SHA512224
+Msg = 8aa66795a6d68e37bae9a93420e276de2ed29bd45c61eb30a4aae5022f4c7dfe2dbd207105e2f27aaedd5a765c27c0bc60de958b49609440501848ccf398cf66dfe8dd7d131e04f1432f32827a057b8904d218e68ba3b0398038d755bd13d5f168cfa8a11ab34c0540873940c2a62eace3552dcd6953c683fdb29983d4e41707
+S = 3976c37b7625b02d799594d2cb853419ee714d72e895a107d49e26a356409f9d8470d437a248296ea4c141d4ad3a3fdcaab0cc1c84714550567c1a9a3009234b8786f5912e9c4f6c02470e665f71638d5599ed8c1d66645ab56ea11211dfaedf53dd4ba64e26492b4e83cfa7ea7b9af3da713e8ecbf90b6dd8b4ca35a29ccda80e337a40e67111e266586593a67ade79104d51fadc33506177fddada9ec9bb6908f5d25ff85423694ad66fdc2c4a34ba13bf0f25f096ac2847263aad34e917cc0fc3142c237f073922a76332598ee49aaa1816ebb88d054f35e03a25295d6f5f320a949c73428ee9ebde930ece4de633aed10f1d502086cb4666d06384d84f4fb0f60558278713c49cf007268b9870734ada1ce820fce3c5ac3b95d3956c2a38b03c07b16009ff673e2f3f29f8cc3d92eb53f138f1d4653e4203f7fd05e0e1aed0ecd7d4bcab95e5296ac63b58aee6164fcb74d7a222eae82cc5b5050620fa26171ee0ccfeb5377ee52758905a4cd759a8b2da02e15401afab3b56f345fb59ce
+
+
+
+SHAAlg = SHA512224
+Msg = 10f58ddbd998e26004300e4079d656fcc6a9eb55b91619b22d56c0c324370864162051c4894f69c6e26602a77b2663e2f57a5d50d0b78194382290b622b3330e9818ec6451fd4d55858b68f8ff2e86c2749c1ca71313fa825de1c6b7372aa9173ee648045a29f6d596a7277c2f772865ea170ea2abb1ed46449c4a0e8b26d247
+S = 8e3a05bae94408530cc00a60fdfb33405b2a087fb2613b30f446ea5520c29c6615f5122fb5c1d29a2e45b488ca118b97088560fa1a7d86e11cccfad237264d4fbb951a3a4fecc4a1171a508e1b7ca4619047d6d216e97c1955ab73ac77942e005c07b2ee95dca824e13545f67d79847a53bcf0d4222e70e2e26b2b28c1be915141c638e77bc93e8f1d4793fdce77507ab710007e07c1b553f57e599d7fd9d4ffe208312d8447281d1ebada5c517a7735a46768213e856ea1129ad326f7c15124223c33ce136ceff3e6715a47b4ae7cf8e95be94317142d12ead5ed59fa91ce157db293f5f2bd3042500e7f0a7a281cf825171d6620d61b5188e0951c53c17bd22b72e7d7520b490781a846e50ee21aed2f3262b6369f59de19d0888434180d367b553c0eb47bcfd085ba1b8cc2b5e48a11758fcbfc8f5adba95b0658107997d53207d2205fd33f0e7891c54eb5a8cac031c7f138824b15e5a1d276ad9c642005442c6ada0b2161ad5ba6dd339a38946475e2efd0a5c01a6b6a93360f2698e34d
+
+
+
+SHAAlg = SHA512224
+Msg = 013d90b2699ceb79cb94edfaf8418f565bee415080898c5bd855f6f7b6df263e9e3348babf4fb37abed8c965b50c1fce7cf8df4827eb6abbcf2a41b796e52509e56a7d8cf899f9429d9875a338c820350bf7dd5db4d7e975f7aebe1ebe5038d85e4bf7d01c6104f8f03bb75d895bd8b690530438313452b2d84a37d53806a7d3
+S = 21e65d04c41bfb837cb9b9f26bd1d920f6c16f1178980adf3db297c16a7675f9e1ad15e00e1c86b397250e1c5fabd7bfe69155b8db4b5e18c5c8b16948348f8b73dba274c9a47d7a35329e4d6ac3601a08af34fb6272264e4ae5268c1e59a73fe4abde5be02cc14ab33e3de77ab06446fc4f320f0805279d74733645bc2de6b6f518b841350048e1078c07521a02d7569f5e700e80099b69b8c4dcf6d4aa896a644754a3a97492f82a9664b9fef041f6fda2967ddf88da8482158a1797856bf6b8d071a1eef50df83d6f6484e2a3db02c652531d8c04466a55e79f467fbaced5670d65325b87885abd6d16c78cb424c19a090b4dbdacb1fa8eebfde97ba4faf51e576521756be3c761cdfa85dab3d4ba89f276fff9436f176b839fa5934c88612d7a775ccdbac8ea59e3b6f7e2479022172f17f1ad749ac6fca28d698aa50bc4ab92d8ea36e4b3409dd4b671cb00cd2f7d3e544b96d74953d0509a15bcb0b52aa6671a5e132814d18908b7da88fc9e3a7ee843957f6bcd0a793f41ef9054823d
+
+
+SHAAlg = SHA512256
+Msg = f23660b33375dade2f5119ecdfee7c53397a4ace54c0f59bccfa9be768e7d287fa1ea5e887a2da49a8b6772730f384f90f97111e77207b143d1aecea813521f8919a70cd0b7f096942f97cade3127b0fd91ce1926d45f4f6b26be72b2031a40c7f52c84a0735eea6c5c230644075ebfc5db0c3128056e7a8f49596938d03e32b
+S = 31f3551b299c1ebcf1a67111e64e56ba6361a0fcf6ad813fcc3f7bbc937bfcb991da384b7c6b5e6a110dbd6c4c9d94de2145437855442d1eca3a4bcbf421de8d7b5a8d54525abb1df6095d52fff33d4d74ed2fb4c3af430fc0cc3bde9fd05f1021ca267e95bc82f09cd50bd5cc7ec7ede63f3e5b8eefb3d024fff0ec7479de983bea9ed36ed871ef5c65389d833264382bbb6c48a6dc5bde540a4ba8d94163e66d93c415c34b5c06b965626e850d1ec794540db27c551801177a781aaa321f77124e63c63b428ae8816c5f14505b33e4f10a93060cb4105b034b54575c6252d1561bbe242fb9be1371e47261472f91472f81f602942357cde641cf73015e161d03fcce0755ab6a7c9278a535b27a9da4c002f6f61231221543be579e9bc9d0d5239e2fce7fcd1dd6ea0ac1954aaf27d7d804f549256e957b7e8266eef02b6b905f5fe6ecb47288a5f3d97449846ccb3ac564046697dacd05f1b6357637e000052e4431d42a484afe7db85d821b1ccd37eaa0131f8d1667af940f32f2c2fe969b
+
+
+
+SHAAlg = SHA512256
+Msg = 43e2cc2a6a8ea64565ff6ce2fd2c4f43fc02926ee44ee02fe1dce25cfde0115c9396c9ea06269f17b2caf58e2332cc1c8528d9705c70da1f76f22aeb1d1b93449180640fb5c4c4a708bc4621d7d2bed5b1a752191cfdd45086d34f247ed1df0f24e7c620de32bdfc4d1f882380d2cd7467c926f48abc75cbfac8788f88cd9dc5
+S = 85f3e1c60a2d06290b0c8ad0b2d92194048e3ad17bd0a1f2271f5cb1457513db2d0601186508cd151a7a86c238cdbba8d451eebec42f3c7bae0317e02ae9fbe29a0451ee7dc23be3185f76c2b3c8f302b205958d3211d244a3b021e6a703f0bb346512c73d0a2b656798471da493e1813e1317b198d4852bf2e865fb53c1eddc4ce8f446a7b32bec755c0c570dc1decc62fc051d2729226db93f39a01499f945e85c0723e919c1d0a00401dfa0d1c21f4a19db8174aca10b07dc70bdf0914e15235f1483c25139932a8eb33364e7ee7956cb2fdc5f6747898b808f0d72276793e7ab7982283d0721d7d560fe36db6fc8e6761245f964a04cb49abfbef8d2ab330a0d507c7a147f0ab17ac1ac6f8ddf97a74b7f63df61f6c690d5c5209c788201a0f22c429f8f0524861f3b780ba03facf9949b570fe620db18c556b2ca8379295248994d6a4ae8e593751dc0bc908bef26169f48b25d16ad634ad13bd3a0d9f87e2d0113680996c84722a6f4c87e4693146901e94e0793e1e1eccff336adf697
+
+
+
+SHAAlg = SHA512256
+Msg = 6e3280f4edb24513845083560a176549a81b04b1df668b1fcc3599c5ab65e6899b282a58a0fc3abdeede74b265ba5eb658278a1f9251bdb29b364f713716d5b43024fe7b5582bb03c36ca39763b495a9b46e9f21cbec1ef598ed27fa6a1126fab590c506142c100d8a64d6ae0deb524b45580a5f911ff8114bc0e8094d3e2182
+S = 2b146c0a9963500795dcc7fccd53ce8ad223ba899a980726c1d08040688ecdd3cbd7f648fc7e8865da6b12e743c4f34a544a746b1c902cf5f2f130245cca3c500675d1786efc2f6685bd6c82f9c06dfea9840a172de27be6788caae3ffc5365eacc7506f88f60bdf9b9e95d78df1020ff897ceadb35d006dcf080a25f45e65d74880d5a005a234146277332283f575bbab122789dcb62b685290648d1e240f471e8ea036c4b2064efa533d5887670b8eb6067e1b99fc2d44d2afd134f26b716811767e8de06963f84988a6247aeb58d9c86a860cbe48e997848cb5aa7d42d833d4e72826ec67a822ae618796f51397f42ffe559db9cd33140e482586c8142b4341392839d41ec1b5e9e5c83eb35b5f53ccc79086fa4e71deda678db71130a73f7f68d45c1354f1536da781aa5c17575f78cb58a456fece8d9d9755e6b8d5b8c82c42b037996a30fc823ccfb4c1d06f6a5897bd64d2a4912ddadb7d247eb1b56140cf8b435788d6cac7c9563f019da5afe350efdccf5545e882ec59fc7660be83
+
+
+
+SHAAlg = SHA512256
+Msg = 59dcada047c130bd4026539fed6023f7d037576e7b4b242d00b059a3a8dca782e8c3400b9040a58c46b7b82733f919d4fc67afa9f45b855a90c3d8fc1b0f6e0eaa4e29b95393db579a9e5c332cb8da8fd0df71ec9a23fb8561502a1d74cdd4fa89c48d32f6837b252423664b40670f3033e6c3bcd56d2fb85d9f768e1dde8150
+S = 84ccaa672f52af4f285e81153df426883f535021e89716c307706c35d93fd61be14131753c8bb5932fe1236e9ada13765fa74be339796a7501e3fdf153c4142fbe4248fbd91048c4ac76645715b991490c0f463febf4893c02b542a655f073c64efe20ab2b5cb77c8ecd41c39a7388a5b530f6ebf822e263b88cdd312964e85c7588c8720b7fcdcf2b5289b044949640036249fed30e347c1a40d9574601ad8637faa4acf92959729664c41103da6bb66edf95d1a20dab6dc6a4010de76f0ccd8ee6129696b2e14053da514943685d6f52700389d931bead03af43d6fc31fa281b1e41da244c1b69f377e4d7b1d75d1fa5f1e63af83a39b8c59b2a19281e6f65af83568d04e283a5e744cecfd4a261db48d2159b0b7f0c8a3416d873eb72c76898a11bf9ada070f4b9d3762f942ffa74a5b57d26dd527e95d762e1d62f38e1693c1688e30b6e56812f0e01e425bf4cc2a297deb14319e5a3f0ec244cd050437d9301268fd55a9f758123985d4a0ad596fd456b4b24c09572c0781ae21364e0c3
+
+
+
+SHAAlg = SHA512256
+Msg = 073b071975d8b6b8cf609fc0b307f22e74e33fe3bffe38587faab98dfd1405424c1c536ae46489dd8da7474d7f4d277bc73c43aaecf0f854d3ceea1de0b548055ed752e121c7180c69d2845a0a939a4dcac2ff8c0b4db890aaaa35a1266b8e0105130c677328ebae2d895ecf9d02d40d461e7a6f633c0173cbe5a101185d5e9e
+S = 099d03209073b4009482911b6dc9a2a9d938397cee5694b61de28178e40fd07435121323b36d1074b9debd50386c0bdd63e1f26bd1f29c7beec2be3e4e0233bb88552319daca3d35f4602a6eb653e22926315a95231d9cfd7aef40e280ac1ac572d45f11d11539b858bdf2bf785cb31cb38dbccbd707b63eafcb0ca1626448ba810caaf1edd6faf3d53a0229c1effa6256e41d3eb7962fb93bf4adc0dc835b6c460e4db28a3dd7ea6e818cab8dc0fe3c3525aeec5fa6f64ded105ef90c46b5598f39e8263e20268d072ead3cfe07bc73dfee40cb257b55938ce1b7dd402367710a18b505d58326d2def24e1b76b342c5b996a5991d9dad6f369b9158eb603d7a9d783eef6bc8f16c1c458c4ee11127096fb3e78261e3965e0be037aa02fee083a2c661739faf44c1017a225f6d7e1b9fb68608007fa93fd5604e4c0c0ade97834f102bfdad72fbe32dd7ea070ec4d0a7345d2ebb2eb405285ab4a4c9c6e6a1153f1da84202752e4ecac38c809ae2b7589979cc624d683d054c17ac336ac18f83
+
+
+
+SHAAlg = SHA512256
+Msg = d3c6aa33a80cc85035fc721da56357652cf85b48f58830835b5026f15bab445249ed974cc38ecaafe48bf7fdb909bd2af93b93a0f0875b86bde43b42bd87a83c47bec3e59a1ce9f913d68501a46d291b818ddefd1c36b8385419adbae945a6973402d70915fd4cb52ca6c52f4cd7c4c12cb6e46860dc6c2088b72461c82c68ea
+S = 9befb09cfdd96b3e4232e66eadb8858065f15e5e6ef00b6c1fe66defe61696bf05766a81830ec88d875f33062845905591eea0dacb004cc0227a497ad62d89a12cc2cd3fd1f8d03a744dae9129e8382d9cb35ee04213bd02de5f4c7fc7b2ac0bea68bc03ebcb9e77c2ad3c624b5bb3a969960b1ebafc70f226cdd6daa2dea5f8475b77706e3f341fb428833c4485127a078785500408dae6bef791c839d8a0e1a935f5434777d52a47b8b8bd6bd14244d6129dd63f0ed53426d6b0344714ed68773b59eb3a4e2c39fa0907969c40be6618c8355aeb5269f5ab328aeb355211c8eee72fe8141cfacc8b22ae1e1d6b45443faa7c6f8909385f785db074b317b37a7e9460148f7f440f142ce03bbcd7dcbc2539031a4e334d5dd9fb6ca6ecb367e0a78a2153dd9bb9aead009578fef558dd618c022548ff5bfd63bc2a401237d48b565bb02bc55c92466ef29a754573e146d8b02effd116a5175063395bcbdefdc9dfb58027e6a3f61a323c73670075004f3e53979074f99fcbf2dba3fe0e47f030
+
+
+
+SHAAlg = SHA512256
+Msg = 849e5d6b17802aea210dc2a5ab7b9418d4bcdc63c6a22f96ea47542c58ac56d592a0d77971e4a7795f8c9638c7a886daca24c44b34ed9883ae551a0935b948b6ca6156bc6ba745e7435cb7221e67023c1faf83ecb53c3513cb9981423f7c587c96a8803dee132bba3344ce6b960030c73b25c24f32d62ecda9d832de603cafae
+S = 7a2f7a8a22dae7021167b40af37fc2793602b34f1bef039bff7ebfdbb8d89c326bf92957d8e4218cb15839128e6f6c71f9cfcc52132a320057b0415f831762aaaef1b19175d5186366df74963dbbc402023aa416d17e2aa515e04c8eb0b26e8d8c00f1a74610fbea45747fefc6fa9a9002b82028e444eb45302e2ae93a4bd4a126e413c701226a234382c92d38d846acd663b5ac99f2d3374c1a34cafa8cf4db8fadf8d6ac6f84c8c1e82a34cb948e3c21bac80587ffe8864c7bd106a4572f1feb1dbe8bf47bea91c5b4f8ecbd5c3a0391c35a2429ef66184ef7649192b961005cfe96572ab1f1479fed569b9dada7cde74a0329eb63f6e91e1647c424aca2a4be2c106eb9e67b8192021fa23f3eb17595d5b0e6bd3ce5d9c9939192b786acab778a456b4ace7bc8aa96f80c1f407607d3fe0130d82193a4f63080800de10ddff692e385489e67dba5fb33a877860aa1f300376220c57117a3f411dd18ec603cd2b66a56e57ff4b9c4431267643f3f99ae6b769d860999bae7b74303583e8b1c
+
+
+
+SHAAlg = SHA512256
+Msg = d7f95e001d6a826e7f7ce4c05f9995d3f6a737d0993762003aff46e1318a91793d2e93eac53f9f476482b5a6a5e45f760b6cd913556f7498ff033cf50cb5d941037fb35138f45a894cbe24f2f74a188d05c20ae79f3c08eecc31f5033830745033d3085cfcf379dc401879cdde3387bfed9014740006e4a9a871b8343b622a4f
+S = 72364e031cd57ceb29a47bb0685b1213d7e0e971728673fd19c0265879c5896958e3d78ac90a398f636c093f979bee99f5ff70539830e4ad44e988b63bced427728ad43f8df064c82e9fb682185f2abcde5c52b29a5918173c13e9890eff41f7a15bd9efd4b65b2ff5a2f706821e38f627805142e6f5ce527641ae7b46c1e9405e6faa7848ac7da98d00ab2196074b1c092018337a0a25473139ff0cb71e6880e7aa6ea2ea0d6b25966de48589dfde90e49a741134e0489406839abf97a2e378def59df53862878305699063052001a4297ee1dc9938c4db686c9bedab9a8d95ee84e016365c812c407d915dd1eaf38fae32fa40ce0bfef6c092f30c4b9e9edd7741e3a4a1f2c79b52d3e75c23bcb641ff1e81d863a941902aeb87b7d9e8d17576620a35d75e23e56e3c2e23146324ac31740c1bbd30aaf427efb1a3b850589cae305a9e516ee21f0045c213661394674d589b2e66534992d9bd0938cec8289167c824a49cb095d7de57ee8e5ec7bbf107888759d4d13d81243018c62d60efa8
+
+
+
+SHAAlg = SHA512256
+Msg = 0074ba726144b96dc93c7b68575723c968c629f853dbae6657250ccfd1ddb2bcb2802f4b31be8c32bd93df0236b41da95c2c303b884749f29aaf787332d57a522392d2d9240f1b05c9e29cd2b2791db803bcf97613ee750e69d45011e41a9b1c39f2cba3a3fe0dedd570d9603470caff43bead315e98d8c4acdebd314f74be22
+S = 99eb491965dc7dac3793cff573bf1178a03134ad9977db883c4b4188fa574e7ea892969c6a0e084bf03cacb4d2a756e5adc82a8b8db7af9f3cee6f77f1ab23f0a5dc40c1450d2d23539ca29336558a5201b67432a22e881fa3c304ee5e796dbdec9dd5e9aca63e99c4b2e52baf292bd278b4c131efbd54ee953b7e849eb835cd17b9f0df4a1b869c0313df23551aa60f570515c6c186aeda72135aa8c1ff5a42e8bf312f14b0d9f4f042d5e69c4467e9ba8715f0d206eab291a288981109bc3cb7512f1998f5d2ddfc99040b108f15c7d4f70620fc4882f8b17654dc70cff93c5d4ff83480e305683c73b038e10bf5f0c4ea56f03edf38d5e84e0ae6c9364846acbaeaa2729314064666f1d93f6351e610edbe30e2952796dc01ed8e7727dad32ecfb40d78ca23e526be97ff070c919f61a2b9dcfe10d8e35442ee76cc1b3c22d60af7b7c23dc2fea3b0a89d1eded7c7fcf89826011bcab7430c31ac86f7b0b9c857066a6b7d1f4cbfcc64b4a14f7156d3d69dcd3b9fa6e2a468fe13861624a3
+
+
+
+SHAAlg = SHA512256
+Msg = b6b26aae4d1fcbd43d6205595758939917dfeffad637607441af13500a7d6e2fdeeda14f96be7e0ab1c88a9f02e35435a605051d39aa395849790d590b24790b4d90e116ac36e65f07c982cd34185453f137382b1dd91b5f28010e8ec8da98edede2518cf84eacdb27ab156c54c13cfae0bcb0abea8eaf92c48f3d78a76673dc
+S = 460876efb3ade4c119b9a1ac22c7f3fa7278af8fb0656292d03453c68352c5a462bc720af460add40fe28078d9dda46922ddb9b78c858feff5c2433688902bdd3447850dc88f9d8c1b003891bda081116800e2bb32f9795427db84ed1084342283f5903ea9b898bc8ee083d069da457333c26f4c4dc75682dd0be73c685d9acdabe5a59de8d12c4d8e7d62cfd4299238f849325e1abeaa7763e392a5019059e33f31b0a6a4cad36b3b5801c23358e7b9d055cc4dd0c9b1991169edf61480e05f74f4388145afc447f1704114818205096c117d2ae8ee747efe03b6213a6f8cfb6aabed9f85902fb9682c17bc92df250bbfcf57a94fd9cea74c90f1bb92a77dba5f318cdb0950fbce14f4d82ca09704222d01c8d6f08c31b11e11d55cb99856cbe6f199da4a41a34ce878a3b3641a1f4b6921977025f4d2297823f773dabbb8b587a280bf87f3045a6609090b925cea7676a4f1c63d4fd8efaa6e8c3be7dde035d8e9433499cd1935423db18e92add2d7a595ee6f80c1a233d10de1a3febaebac
diff --git a/tests/t-rsa-pss.c b/tests/t-rsa-pss.c
new file mode 100644 (file)
index 0000000..fa8392e
--- /dev/null
@@ -0,0 +1,525 @@
+/* t-rsa-pss.c - Check the RSA-PSS crypto
+ * Copyright (C) 2021 g10 Code GmbH
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "stopwatch.h"
+
+#define PGM "t-rsa-pss"
+#include "t-common.h"
+#define N_TESTS 120
+
+static int no_verify;
+static int custom_data_file;
+static int in_fips_mode;
+
+
+static void
+show_note (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!verbose && getenv ("srcdir"))
+    fputs ("      ", stderr);  /* To align above "PASS: ".  */
+  else
+    fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+  va_end (arg_ptr);
+}
+
+
+/* Prepend FNAME with the srcdir environment variable's value and
+ * return an allocated filename.  */
+char *
+prepend_srcdir (const char *fname)
+{
+  static const char *srcdir;
+  char *result;
+
+  if (!srcdir && !(srcdir = getenv ("srcdir")))
+    srcdir = ".";
+
+  result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
+  strcpy (result, srcdir);
+  strcat (result, "/");
+  strcat (result, fname);
+  return result;
+}
+
+
+/* Read next line but skip over empty and comment lines.  Caller must
+   xfree the result.  */
+static char *
+read_textline (FILE *fp, int *lineno)
+{
+  char line[4096];
+  char *p;
+
+  do
+    {
+      if (!fgets (line, sizeof line, fp))
+        {
+          if (feof (fp))
+            return NULL;
+          die ("error reading input line: %s\n", strerror (errno));
+        }
+      ++*lineno;
+      p = strchr (line, '\n');
+      if (!p)
+        die ("input line %d not terminated or too long\n", *lineno);
+      *p = 0;
+      for (p--;p > line && my_isascii (*p) && isspace (*p); p--)
+        *p = 0;
+    }
+  while (!*line || *line == '#');
+  /* if (debug) */
+  /*   info ("read line: '%s'\n", line); */
+  return xstrdup (line);
+}
+
+
+/* Copy the data after the tag to BUFFER.  BUFFER will be allocated as
+   needed.  */
+static void
+copy_data (char **buffer, const char *line, int lineno)
+{
+  const char *s;
+
+  xfree (*buffer);
+  *buffer = NULL;
+
+  s = strchr (line, '=');
+  if (!s)
+    {
+      fail ("syntax error at input line %d", lineno);
+      return;
+    }
+  for (s++; my_isascii (*s) && isspace (*s); s++)
+    ;
+  *buffer = xstrdup (s);
+}
+
+
+/* Convert STRING consisting of hex characters into its binary
+   representation and return it as an allocated buffer. The valid
+   length of the buffer is returned at R_LENGTH.  The string is
+   delimited by end of string.  The function returns NULL on
+   error.  */
+static void *
+hex2buffer (const char *string, size_t *r_length)
+{
+  const char *s;
+  unsigned char *buffer;
+  size_t length;
+
+  buffer = xmalloc (strlen(string)/2+1);
+  length = 0;
+  for (s=string; *s; s +=2 )
+    {
+      if (!hexdigitp (s) || !hexdigitp (s+1))
+        return NULL;           /* Invalid hex digits. */
+      ((unsigned char*)buffer)[length++] = xtoi_2 (s);
+    }
+  *r_length = length;
+  return buffer;
+}
+
+
+#define DATA_TMPL_NO_SALT "(data(flags pss)(hash %s %b)(salt-length 1:0))"
+#define DATA_TMPL_WITH_SALT "(data(flags pss)(hash %%s %%b)(salt-length %zd:%zd)(random-override %%b))"
+
+static void
+one_test_sexp (const char *n, const char *e, const char *d,
+               const char *sha_alg, const char *msg,
+               const char *s, const char *salt_val)
+{
+  gpg_error_t err;
+  int i;
+  char *p;
+  void *buffer = NULL;
+  void *buffer2 = NULL;
+  void *buffer3 = NULL;
+  size_t buflen, buflen2, buflen3;
+  gcry_ctx_t ctx = NULL;
+  int md_algo;
+  char *data_tmpl = NULL;
+  size_t len_data_tmpl;
+  gcry_md_hd_t hd = NULL;
+  gcry_sexp_t s_pk = NULL;
+  gcry_sexp_t s_sk = NULL;
+  gcry_sexp_t s_sig= NULL;
+  gcry_sexp_t s_tmp, s_tmp2;
+  unsigned char *out = NULL;
+  size_t out_len = 0;
+  char *sig_string = NULL;
+
+  if (verbose > 1)
+    info ("Running test %s\n", sha_alg);
+
+  if (!strcmp (sha_alg, "SHA224"))
+    md_algo = GCRY_MD_SHA224;
+  else if (!strcmp (sha_alg, "SHA256"))
+    md_algo = GCRY_MD_SHA256;
+  else if (!strcmp (sha_alg, "SHA384"))
+    md_algo = GCRY_MD_SHA384;
+  else if (!strcmp (sha_alg, "SHA512"))
+    md_algo = GCRY_MD_SHA512;
+  else if (!strcmp (sha_alg, "SHA512224"))
+    md_algo = GCRY_MD_SHA512_224;
+  else if (!strcmp (sha_alg, "SHA512256"))
+    md_algo = GCRY_MD_SHA512_256;
+  else
+    {
+      fail ("error for test, %s: %s",
+            "d", "invalid hex string");
+      return;
+    }
+
+  err = gcry_md_open (&hd, md_algo, 0);
+  if (err)
+    {
+      fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err));
+      return;
+    }
+
+  if (!(buffer = hex2buffer (n, &buflen)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "n", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer2 = hex2buffer (e, &buflen2)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "e", "invalid hex string");
+      goto leave;
+    }
+  if (!(buffer3 = hex2buffer (d, &buflen3)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "d", "invalid hex string");
+      goto leave;
+    }
+
+  err = gcry_sexp_build (&s_sk, NULL,
+                         "(private-key (rsa (n %b)(e %b)(d %b)))",
+                         (int)buflen, buffer,
+                         (int)buflen2, buffer2,
+                         (int)buflen3, buffer3);
+  if (err)
+    {
+      fail ("error building SEXP for test, %s: %s",
+            "sk", gpg_strerror (err));
+      goto leave;
+    }
+
+  err = gcry_sexp_build (&s_pk, NULL,
+                         "(public-key (rsa (n %b)(e %b)))",
+                         (int)buflen, buffer,
+                         (int)buflen2, buffer2);
+  if (err)
+    {
+      fail ("error building SEXP for test, %s: %s",
+            "pk", gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (buffer3);
+  buffer = buffer2 = buffer3 = NULL;
+
+  if (!(buffer = hex2buffer (msg, &buflen)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "msg", "invalid hex string");
+      goto leave;
+    }
+
+  gcry_md_write (hd, buffer, buflen);
+  xfree (buffer);
+  buffer = NULL;
+
+  if (!(buffer2 = hex2buffer (salt_val, &buflen2)))
+    {
+      fail ("error parsing for test, %s: %s",
+            "salt_val", "invalid hex string");
+      goto leave;
+    }
+
+  /* SaltVal = 00 means no salt.  */
+  if (!(buflen2 == 1 && ((char *)buffer2)[0] == 0))
+    {
+      err = gcry_pk_random_override_new (&ctx, buffer2, buflen2);
+      if (err)
+        {
+          fail ("error setting salt for test: %s",
+                gpg_strerror (err));
+          goto leave;
+        }
+    }
+
+  len_data_tmpl = strlen (DATA_TMPL_WITH_SALT) + 21;
+  data_tmpl = gcry_xmalloc (len_data_tmpl);
+  if (ctx)
+    {
+      size_t len_digits;
+      char number[21];
+
+      len_digits = snprintf (number, sizeof (number), "%zd", buflen2);
+      snprintf (data_tmpl, len_data_tmpl, DATA_TMPL_WITH_SALT,
+                len_digits, buflen2);
+    }
+  else
+    strcpy (data_tmpl, DATA_TMPL_NO_SALT);
+
+  xfree (buffer2);
+  buffer2 = NULL;
+
+  err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, ctx);
+  if (err)
+    {
+      fail ("gcry_pk_hash_sign failed: %s", gpg_strerror (err));
+      goto leave;
+    }
+
+  s_tmp2 = NULL;
+  s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
+  if (s_tmp)
+    {
+      s_tmp2 = s_tmp;
+      s_tmp = gcry_sexp_find_token (s_tmp2, "rsa", 0);
+      if (s_tmp)
+        {
+          gcry_sexp_release (s_tmp2);
+          s_tmp2 = s_tmp;
+          s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0);
+          if (s_tmp)
+            {
+              out = gcry_sexp_nth_buffer (s_tmp, 1, &out_len);
+              gcry_sexp_release (s_tmp);
+            }
+        }
+    }
+  gcry_sexp_release (s_tmp2);
+
+  sig_string = gcry_xmalloc (2*out_len+1);
+  p = sig_string;
+  *p = 0;
+  for (i=0; i < out_len; i++, p += 2)
+    snprintf (p, 3, "%02x", out[i]);
+  if (strcmp (sig_string, s))
+    {
+      fail ("gcry_pkhash_sign failed: %s",
+            "wrong value returned");
+      info ("  expected: '%s'", s);
+      info ("       got: '%s'", sig_string);
+    }
+
+  if (!no_verify)
+    {
+      err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, ctx);
+      if (err)
+        fail ("gcry_pk_hash_verify failed for test: %s",
+              gpg_strerror (err));
+    }
+
+ leave:
+  gcry_ctx_release (ctx);
+  gcry_sexp_release (s_sig);
+  gcry_sexp_release (s_sk);
+  gcry_sexp_release (s_pk);
+  if (hd)
+    gcry_md_close (hd);
+  xfree (buffer);
+  xfree (buffer2);
+  xfree (buffer3);
+  xfree (out);
+  xfree (sig_string);
+  xfree (data_tmpl);
+}
+
+
+static void
+check_rsa_pss (const char *fname)
+{
+  FILE *fp;
+  int lineno, ntests;
+  char *line;
+  char *n, *e, *d;
+  char *sha_alg, *msg, *s, *salt_val;
+
+  info ("Checking RSASSA-PSS.\n");
+
+  fp = fopen (fname, "r");
+  if (!fp)
+    die ("error opening '%s': %s\n", fname, strerror (errno));
+
+  n = e = d = NULL;
+  sha_alg = msg = s = salt_val = NULL;
+  lineno = ntests = 0;
+  while ((line = read_textline (fp, &lineno)))
+    {
+      if (!strncmp (line, "[mod", 4))
+        /* Skip the annotation for modulus.  */
+        ;
+      else if (!strncmp (line, "n =", 3))
+        copy_data (&n, line, lineno);
+      else if (!strncmp (line, "e =", 3))
+        copy_data (&e, line, lineno);
+      else if (!strncmp (line, "d =", 3))
+        copy_data (&d, line, lineno);
+      else if (!strncmp (line, "SHAAlg =", 8))
+        copy_data (&sha_alg, line, lineno);
+      else if (!strncmp (line, "Msg =", 5))
+        copy_data (&msg, line, lineno);
+      else if (!strncmp (line, "S =", 3))
+        copy_data (&s, line, lineno);
+      else if (!strncmp (line, "SaltVal =", 9))
+        copy_data (&salt_val, line, lineno);
+      else
+        fail ("unknown tag at input line %d", lineno);
+
+      xfree (line);
+      if (n && e && d && sha_alg && msg && s && salt_val)
+        {
+          one_test_sexp (n, e, d, sha_alg, msg, s, salt_val);
+          ntests++;
+          if (!(ntests % 256))
+            show_note ("%d of %d tests done\n", ntests, N_TESTS);
+          xfree (sha_alg);  sha_alg = NULL;
+          xfree (msg); msg = NULL;
+          xfree (s); s = NULL;
+          xfree (salt_val); salt_val = NULL;
+        }
+
+    }
+  xfree (n);
+  xfree (e);
+  xfree (d);
+  xfree (sha_alg);
+  xfree (msg);
+  xfree (s);
+  xfree (salt_val);
+
+  if (ntests != N_TESTS && !custom_data_file)
+    fail ("did %d tests but expected %d", ntests, N_TESTS);
+  else if ((ntests % 256))
+    show_note ("%d tests done\n", ntests);
+
+  fclose (fp);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  char *fname = NULL;
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options]\n"
+                 "Options:\n"
+                 "  --verbose       print timings etc.\n"
+                 "  --debug         flyswatter\n"
+                 "  --no-verify     skip the verify test\n"
+                 "  --data FNAME    take test data from file FNAME\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--no-verify"))
+        {
+          no_verify = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--data"))
+        {
+          argc--; argv++;
+          if (argc)
+            {
+              xfree (fname);
+              fname = xstrdup (*argv);
+              argc--; argv++;
+            }
+        }
+      else if (!strncmp (*argv, "--", 2))
+        die ("unknown option '%s'", *argv);
+
+    }
+
+  if (!fname)
+    fname = prepend_srcdir ("t-rsa-pss.inp");
+  else
+    custom_data_file = 1;
+
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  if (!gcry_check_version (GCRYPT_VERSION))
+    die ("version mismatch\n");
+  if (debug)
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
+  start_timer ();
+  check_rsa_pss (fname);
+  stop_timer ();
+
+  xfree (fname);
+
+  info ("All tests completed in %s.  Errors: %d\n",
+        elapsed_time (1), error_count);
+  return !!error_count;
+}
diff --git a/tests/t-rsa-pss.inp b/tests/t-rsa-pss.inp
new file mode 100644 (file)
index 0000000..02c6a4e
--- /dev/null
@@ -0,0 +1,676 @@
+# CAVS 11.4
+# "FIPS186-3 - SigGen RSA PKCS#1 RSASSA-PSS" information
+# Combinations selected:Mod Size 2048 with SHA-224(Salt len: 15); SHA-256(Salt len: 20); SHA-384(Salt len: 25); SHA-512(Salt len: 30);; Mod Size 3072 with SHA-224(Salt len: 28); SHA-256(Salt len: 32); SHA-384(Salt len: 48); SHA-512(Salt len: 62);
+
+
+[mod = 2048]
+
+n = c5062b58d8539c765e1e5dbaf14cf75dd56c2e13105fecfd1a930bbb5948ff328f126abe779359ca59bca752c308d281573bc6178b6c0fef7dc445e4f826430437b9f9d790581de5749c2cb9cb26d42b2fee15b6b26f09c99670336423b86bc5bec71113157be2d944d7ff3eebffb28413143ea36755db0ae62ff5b724eecb3d316b6bac67e89cacd8171937e2ab19bd353a89acea8c36f81c89a620d5fd2effea896601c7f9daca7f033f635a3a943331d1b1b4f5288790b53af352f1121ca1bef205f40dc012c412b40bdd27585b946466d75f7ee0a7f9d549b4bece6f43ac3ee65fe7fd37123359d9f1a850ad450aaf5c94eb11dea3fc0fc6e9856b1805ef
+
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086c94f
+d = 49e5786bb4d332f94586327bde088875379b75d128488f08e574ab4715302a87eea52d4c4a23d8b97af7944804337c5f55e16ba9ffafc0c9fd9b88eca443f39b7967170ddb8ce7ddb93c6087c8066c4a95538a441b9dc80dc9f7810054fd1e5c9d0250c978bb2d748abe1e9465d71a8165d3126dce5db2adacc003e9062ba37a54b63e5f49a4eafebd7e4bf5b0a796c2b3a950fa09c798d3fa3e86c4b62c33ba9365eda054e5fe74a41f21b595026acf1093c90a8c71722f91af1ed29a41a2449a320fc7ba3120e3e8c3e4240c04925cc698ecd66c7c906bdf240adad972b4dff4869d400b5d13e33eeba38e075e872b0ed3e91cc9c283867a4ffc3901d2069f
+
+
+SHAAlg = SHA224
+Msg = 37ddd9901478ae5c16878702cea4a19e786d35582de44ae65a16cd5370fbe3ffdd9e7ee83c7d2f27c8333bbe1754f090059939b1ee3d71e020a675528f48fdb2cbc72c65305b65125c796162e7b07e044ed15af52f52a1febcf4237e6aa42a69e99f0a9159daf924bba12176a57ef4013a5cc0ab5aec83471648005d67d7122e
+S = 7e628bcbe6ff83a937b8961197d8bdbb322818aa8bdf30cdfb67ca6bf025ef6f09a99dba4c3ee2807d0b7c77776cfeff33b68d7e3fa859c4688626b2441897d26e5d6b559dd72a596e7dad7def9278419db375f7c67cee0740394502212ebdd4a6c8d3af6ee2fd696d8523de6908492b7cbf2254f15a348956c19840dc15a3d732ef862b62ede022290de3af11ca5e79a3392fff06f75aca8c88a2de1858b35a216d8f73fd70e9d67958ed39a6f8976fb94ec6e61f238a52f9d42241e8354f89e3ece94d6fa5bfbba1eeb70e1698bff31a685fbe799fb44efe21338ed6eea2129155aabc0943bc9f69a8e58897db6a8abcc2879d5d0c5d3e6dc5eb48cf16dac8
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = 5c61546b848a36e8e51f8beb1140823dbd95b06660924d16fdf9a1c33ca0b994c0745e7eb5be48ada8a58e259cf461a95a1efadb0880d1a6fde510d9d44f4714bff561e81e88d73a51ba23e8ca0178b06698b04dfdc886e23865059ca29b409302eb44f2e9704b588767327ec2ee2d198a0cba0266f2d39453806855cf0b0cd9
+S = 134e6acd94b76a86e7ff730f064a3d480d1cff1687b993163ce09f21d494a4a15e6d92758a93f7c83ead21c4ca290f9478241c9811c231f32d9d17e0b479a9b34cad02e5bbdde6c8e4ec4f35f93524f8afde49e6a4740bab2f2fdeff3fc5d92a1b50adc7af964eec82fb80be24092ab28791807c664a9106b5df3296747c014b75d69d181f2e58dafbbf9127164f88c862a48d5e9edcd6d2b2cbc20abceb0e98c7e731d27c8d04fad95ff50dd64af20e6388ed74b9b3cf33b4a316b0c752f33697e5a7445ae2f726f30333f107928872776225a3e0b1b14a7e84f9a695c7b3910330d225b4834110b54d6b05e69df6b7a2c9dc352942e3bce970cec677253230
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = 7540edea54a4fa579684a5b59c51eb20e61106f82157917c6173ee9babe6e506b6198d8af24e709dcad6ea372684d2e335635c1569a43ebec3da121e506afcd9f43c8c4e66b7e6247ced2025a912eb50c43376290a248f5467bb0c62f13b69ebb513b2ddb7c9a31334310f2a2ae27e901bea1add0dc1cc67d57ca21095437463
+S = 45541aa65fbb0773b1434c4fdaafe23fe800f78eba900c6104a6f0e76dc08daedc28a3380c8078f82055cd4a20cf30541c32d9ac625378355c156880b35a29645325d488f7a0d2de7df92cf9bccdf851445c2b834ad0e6849a6549db72affa7ce66fbbfc5bc0194504a5fb031267b6ca9b57f583e7e11c927e3dc203f7d6d4b9df675d2a302231400008fbbd4a05e17f88bea074de9ab8211a18dcceae6c9fd8fad96ce0626eb25c9ab81df55ba4d0a6ae01eb25a2529e16c98ded286cb345d4fd59124297ba9b3efcb67884ed853ea96d74e00951987bcda54d404d08f2baf7f0d7ff13d81d1fa20cde1d21663684c13ffc7164448f4e85a6c811a850a3faed
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = 840ff32993223efe341eeb55558e6ab1fbae15d17bcf0731edfd32d4dee0ac4145e04accb88c7016e03d27d72bf670dbc08fd94bb8134d2e8b66302fc82baca10ae445c0275bb43aaa42f2ee841693f3fe4955dcf29ff93a3bd951636a919b72ba650d8f4757b1717a747320c8b479009c22b20b913cb25ee59dbdf72bd921bd
+S = 07f07ef5e793d59b0c3f899dc846bb831d88dd4d2d8345ad2d726c5c532d13e05b26f0fd03b2b9bde7b6d5b6febc8fe5d3228887eac443c99ec39fffeb939785f87be8a93e497cfdea3d8d06356518a5254c5946236458b29f1cd47e97718c805b167791d10f9304328635330116a2aeae1e0ecc16bfd5a31356d06892b8ca04aec27a417320be7bf6fc1083d70fa522c23850f5d6beda1a251d1a5e71762bc8fd5f16ef0c7a961f4858a5b760a8032f3fd6bdce2ed26351f2beab8b89d9312d88736ee5253a9da6753283e5b3d0d9cdd3e19ca0b60b9fae3e3dfd67831df72ed9611d5f2b3ac256052a207a5245d2cdeaad0d1266c7177b1a0844d5974a8a41
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = a5fb396eee4045f886191f7ff9ea68aaa1bcd8e781903b6071f3ba2b7cd35cc08691cdb131575d9502ac4b45c046444c1d1f279899cb0b76a20883bd00972148704a38aa8f5fe61efa0c52bdb45b33f4c83892342fc8d0ebf3fdeab49568fccaad4e04c3d0fde97bb660bc4e9cd23d8ae830a1230c3292a9acfb787803eef72f
+S = 4428c389d0c80a9320e4859e41cbd4a47f78e4da5d1c0644ff50bad172de9ffe74d84a76d6de4f72bbe34d7dccaa03e1324041cb98308d73dcff0bcf7ffc35936473cf3ec53c66ea8a6135742e0ea9056a4897a7cbd2b0654b344786bf3047d122dcbbc4bea1840e84bce066c3385dccb021a79e8de18dc114a40d824141d8331a4df6901b3409c30552519b097a96ded6793cbb9ae18bb9a4185b6f4e83aad6dce878c689bf595d272719b9f50b3ede1803dfae6dd3f54e4ca9c458c14463f4f19af6cc8127bec80a6a9e5a5fe0d3e14dfcc6ba052750ebbf84a652adde9d6be68d5b134cd09bb94d0875e5527fe3f3fa2a516dc05c14fd5516dff2d434f0c4
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = 6e891589d71d2eff6cb986b071a31e2696d8ce671fa18c244267eb33d0c8e24018ebcfbf0910bb24966be0575f3268628df5786dfd2e6deda219661824c5029ccd6b6b90a60093abdd06bdb46aa74039f2048784eccb5dcb020767a7ba3df2c755b4f0e6f8143cfa093326afdc2b2b138fb0049332a0e3262bdcf9c8d9573b2a
+S = 01909328c24dd0ef912040f61492e3711243f8ca1262067cca6bdab165efe4157982323f13152999e9f21e6852d8c2efc4130e2c46a38446aacfc59fbca5d1a38946923b7e08be397fb787bc79a71ba08fc2b693d1bcbe897d1dface2858ba80a086a0e0a45efe66fd5350add819fd0dc1931d3eba2765f84f147422f5330d0efa0cd827197a5d89e2dd62db9051d5df8b9680169f349086dd038a9ac62f9941565b3f747d528ec4c36e9c948ad3a73240d07ef14b354ffef1b1965a9aafb13d0fc88a09707c6a0ad3028d5a5c6efaab50aad05304b1d5b2930abb8f58c0188b6a94231f8698c96ddd614343a0218494dfff9a293dfc7d5c3b5afbed8f079458
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = d66747638d8276920352b215158cefe0727a5e2b079d892cbb969f265d470ca2da354dfcb4300322af374699ce963bc17d51e95910c548456c8d9b8f04a300ad08c74602d825fea7bf32d56aded7211766d1b9f70b580a97b5fe67ca78dba1f1c6e7d87ae3a790a79a0c07912f98c76c94c2770cdf9cf6a8fcb3abdf9f3616f8
+S = 85f296084bda823556aa369e5cb19e10ce6e982a6d10a85ba6af6d3fed8f2c05599faed069215cc9eed9e72a4fe510a6c09ff721cf1a860e48cf645438c92c5c86d0885e7d246ccf9d0cfd8c56ca8d673b7094a3daa77db272d716f31b1380f72b50378f595471e4e481851c57a6b574bfb3fc7aa03636632045fcc8e9cc54594759f6014b527877e605ef60cf109b4ca71e772a99acfc7243318655ec50f74e48485668ed42859ff2c5934581ba184d926c8467d7c35257dce9964049568a990f65d591c2db86b48a7256da947fd7d978dd6734bd8685025d1a87e32f52a0299394c93e6d518b18e0b8db1d763f46905f405df0cbc8455e039f173e2b68c9de
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = 23d92665e88a4f6f732de384034d493d5df37b767a8260557de05688e8d60dcd0eba9cb8cc4bceb174dcbd3c0ab5a37db3b6ecfb6a3d90a4f54a9f1117e11e0c08b0114f22f2d98fdd93c0b9fd95d37c0ab2f00701431f1449602525e849570df704adb353481713969a148546b680424c30ad24a75bb6ad616a104bc2d562da
+S = 8beeb201aedb9fe7d535fc7989713062497a03e18ef9977b98a93f18f37545c38f5e5206e2b5df7f4a41ab9e0675f7d46d172dc3af90fb7b1a6fa6c986b803a7f2ea4ed217872cc686165b1278450c23c329ee2855f65e651c3db085e407bf3e3a96eaa833ba2056a084031546cea2f454f7acf84c3b90fd7b6210ef6d1ad71ed1b0049262f5b4e3ca99d10a3307752b2ad8e8fbba3a3e8432bc966553901e87150738aac9170fab1d27219274ec528299f8afbbd861ee837f2c86ecce7e73c9b7bd6f6661d1efe3fd2ff7b3efa0d1fc7b84fefffa14b55a2c5fe3252cae0cf0da6e50e3d615f86ae6721aa5e29ed3a1c71c243c2529eef483c56b902e93718c
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = 40abb42db34067fadb5aacbb2fdedd2d0324030bb75ca58f2e2ade378194b2c5f51ea2892b337ee297c77b03333b86f37581d7d77e80c87494bae8f0d22c4bd81e7525685c3b9706e1cbc90f2bff39d6cf6553eab29d41987c0304b14a8fc48ea4f96450ae205a6ca2acbe687df2a0dff9199fcbbc7bb704cf4e5b035184c4ec
+S = 54bec66241dc197ad92e695526b3b6a030216b48af90d93c36b2d70644e40cda2cb259f27ca9d141e5753f938497e84208b380ffe1788701c71d89bbea3edd352dabd32d9425edcf9a33e185cbc4031aa6069863fe47d499536a59da12a8bdbbf2a3a9f0039318d066f5117bbf6fce4f6752088ccc3a081d85da461a8bdcaf349fd4054f76384e668d00a6f747688c8420c7e452b0736ad62e1738a3f10cb62bc7ddc12fa670f858b2d5def9a42ac8f2fc91d488738a7c23168f51ddfbdae6a5d8ee1fc561cc3add4a7e14eb103bf9593cebf391c1f7a07d262faf03d47d07424ffb3a916a9564652a1be020a0e922e99a57da1abf931f74cfbdd484c0a9568f
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA224
+Msg = ef10b03c04578bd5f783358df367456a73de38c6fab2c35405bc685e3d4c4850f2cb387ac59e1612a44e5e78fce6f8be299d546832b5b970b3a3da8e1a70abb6165f72e14dd021104e64e38ec662f576f65ab776640803d2d17abdac6c75ab82451687f804b553d8db0eed57b9a3e39ac15c8878fa714882488938409b24f1be
+S = 4a183b82616f3bbc27a146710b28729161feb17900be62e69eed5d254d15f34bce52d6f3deba89a787ebeb0611e240cc23e16add3796d4a29783e2cbe8797e066cecbd66059c394f0e2f9e377f1ffa194fcb895e1c48874b9b6430a13c779f5ca29e3f42bca4b916710590ab6501809d645a4885b058dba0647971f04f6f2f4a296c45d89dd848b7c2f8777ec50846c97d35c12d54ebb6ff167327b1d4daedf4468031b59057d57ceddb79fdd013167ee6e46d9130693322c3ae6702901a1e90bd4b621d141977d0680acd524921bc540e34ac640ace02f89d5436808283e026e138ba3a5a4310fe1e048833f9b581baef5f891f9cdb2f0673bafa11ceabc7d7
+SaltVal = 463729b3eaf43502d9cff129925681
+
+SHAAlg = SHA256
+Msg = dfc22604b95d15328059745c6c98eb9dfb347cf9f170aff19deeec555f22285a6706c4ecbf0fb1458c60d9bf913fbae6f4c554d245d946b4bc5f34aec2ac6be8b33dc8e0e3a9d601dfd53678f5674443f67df78a3a9e0933e5f158b169ac8d1c4cd0fb872c14ca8e001e542ea0f9cfda88c42dcad8a74097a00c22055b0bd41f
+S = 8b46f2c889d819f860af0a6c4c889e4d1436c6ca174464d22ae11b9ccc265d743c67e569accbc5a80d4dd5f1bf4039e23de52aece40291c75f8936c58c9a2f77a780bbe7ad31eb76742f7b2b8b14ca1a7196af7e673a3cfc237d50f615b75cf4a7ea78a948bedaf9242494b41e1db51f437f15fd2551bb5d24eefb1c3e60f03694d0033a1e0a9b9f5e4ab97d457dff9b9da516dc226d6d6529500308ed74a2e6d9f3c10595788a52a1bc0664aedf33efc8badd037eb7b880772bdb04a6046e9edeee4197c25507fb0f11ab1c9f63f53c8820ea8405cfd7721692475b4d72355fa9a3804f29e6b6a7b059c4441d54b28e4eed2529c6103b5432c71332ce742bcc
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = fd6a063e61c2b354fe8cb37a5f3788b5c01ff15a725f6b8181e6f6b795ce1cf316e930cc939cd4e865f0bdb88fe6bb62e90bf3ff7e4d6f07320dda09a87584a0620cada22a87ff9ab1e35c7977b0da88eab00ca1d2a0849fec569513d50c5e392afc032aee2d3e522c8c1725dd3eef0e0b35c3a83701af31f9e9b13ce63bb0a5
+S = 492b6f6884df461fe10516b6b8cc205385c20108ec47d5db69283f4a7688e318cfdc3c491fb29225325aeb46efc75e855840910bbaf0d1c8d4784542b970754aaa84bfe47c77b3a1b5037d4d79759471e96cc7a527a0ed067e21709ef7f4c4111b60b8c08082c8180c7c96b61c0f7102ed9b90e24de11e6298bb244518f9b446ce641fe995e9cc299ed411b65eb25eaae9e553484a0a7e956eadf0840888c70e5ca6ebc3e479f8c69c53cf31370ab385e8b673dc45a0c1964ec49468d18246213a8f93a2a96aad5a2701c191a14a31519e4f36544d668708ff37be5481cb0ffa2b0e1f145e29f8575dfa9ec30c6cb41c393439292210ea806a505598ebdf0833
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = 7e6690203cb068b8530cb1ff4eeaf0fc69a4e304f556072dfeef5c052c886c83e7f58a3dbe9a58dc0a808ccdcea9f33ae2a0b6395153dc43ff2510e78f40a4bf8328d7a4a596531ea683fa1e0683e2f033549e6bf5b7c06b097e9b810de74ee89c28febbb94b6266713c855bbc21c706a5e92502aa28bb8d662287396d2570e5
+S = 509a01bb0360d1160ed3ff33432291cfbb63daa2933819600db7dd825aef13dd1e9a888a9fb6fea93debd4cf4bc77129b06dd4727193d7e8a2e5aa5a6020b64524e93abb0406f5a18f74ff0aa804919df4072e319ce8234431c94e8eef8c5ce813a07b2f66dd6a032c3e69a3c58c6b54acf08bbbb019df15f3abd22c67f3e2cbffe99887adee58a39cc30ac45a6e6e59283ee0890aa87072a857845f5cf3ddacdc776e58e50b66e95eb13dec49ce45505c378734e964e8095d34a01317768b7b9fbef6eb24b08b1bf0312ab51e0acea4a3dfdfa6fa7bb115b8b685d354841d1901bc73cc655ae246a5453ea8d160610425c2c14969bf22a7e11e663cff1501f1
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = 1dce34c62e4aef45e1e738497b602e82c1fe469f730cf164178b79fdf7272c926d69bd1b5e2de776055753b6f2c2bcbf52795110702a5bdf7cd71f6b8ccf068ee0ddfb916abf15458dd9764f262b73c4c981f5f64de91e8d8a6a30d961f3ab66fd92b6d159e6c0db02d767bc1f8499baae7df9f910338495c8ad74ee807c6443
+S = 1bd79d25ac6b0f242f39555c85d858c23680e1ebf9590d05463ebc58454a7822cf0e0c2ab9872b6eac5ae8ce3da773d6b2039e9b26ce751dadc48579320ea63b978b0df038191d9128102128a365c01d9e2b43fe2b5ef1ce9ee8f4a1e12caef1bbe7f3a8d1a93c9f399753bbfd60d22d8f39206a511ea448dc23cc0e4fcf0b77d3f3fbd9188b740de3f85009de94ee157dbf7edc3165e9f69b59db37f7fdc507496de8941a2a2628774b06c8cab034bbe3d2c04d253b5948d6e5712373ada99b7f860612440c5eed81efeea18d76329dc30bd9fcc500e92315677142d5e1b6b45ae0e6e725122f046c9a544ad1ef1ddc7c6b2a7809715ab75ef870ee6670627a
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = c32976432e240d23df6594f2885f00db7fa7e53b7aa84ef89798ec149fab74828b86423847f64285b7e210a5f87e5e93e8c2971ee81bc13fe060a8aa840739a3d6992c13ec63e6dbf46f9d6875b2bd87d8878a7b265c074e13ab17643c2de356ad4a7bfda6d3c0cc9ff381638963e46257de087bbdd5e8cc3763836b4e833a42
+S = be69c54dad9d8b6db7676fe74321a0aeb08d1cc17f6607e87982f99489344e99378c38341e0e605b8ff903c74a973872a9880e05a8ef0bd3e6049931acf152dd54fec9105a57b73f77631db736b427f1bd83275e0173d4e09cd4f8c382e8b502a3b0adbd0c68911d02de17fff3d927e250e1826762efc0b895dfa502f18dc334b4c573f99b51b74fdd23009861028f1eed6875bf31d557acd6de8f63fa1274f7bed7a1b4c079f5a9b85bfab29f552c7f647d6c9241563fac123a739674b0ad09c3f94208795d9a50529d799afc597e025f1254995f043234891620b10d5c5569be14b0f463a495f416024618486c7ff5ec775cfb46fbdff5379c5e09150b81a3
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = 218551f425b3557d09ccfdecc9ab499085bd7fe7d60820be626c1a9aae293f5734a2f60fb661313dd15a9f22d5742268d4458306f91d65631b4777be928beecd4af733a416e0d8d94623d1e67bb0e1ceba4a5204c088e98895201953646477f58a0d6e7ded3834998faefcfe63686e0a5f5354a8d2509675f87f6821cbbdc217
+S = 96a269e0ca4af626aa8b7f45acdaa76d5dabfea5a7d762ab39b138dc7575fe196aeb182bee5b18503969b5ba111f057ccdbf292d7488173a4a4dd04e62c254d502673d5a076d326c66c9a71a3b83b1005c6366f8a0902987dbf08cee7562d0abffbdd661c3525be8e12dfd73ed31efaa817f61e7fef700a3215e77b6231d59c098fa455b69ec6e658a66cca2e8f2e090ef704270995170ba9a1f561b848676804413645a943d883191d95b024d6ffc9cb611c68f3319403bd7c07ac6694501368e8147a256e928604b63d50e2c65f3b2c30df1eb0363e29fe448f94b6907cdf42fbc9c27b31a43a8f5c15ce813f9b20d16da6c298843f052ed37678b4ef1d78e
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = 06b76aaeb946fe6867e4716a8f1ee8d61c483ab345cbf8e5b2bfab5ce0bd5c8bc6ee5a1cb96837e28dbb140ffdc61ea74cd059342dd49dbce11bdef09f10b0a638510989fb02490fd66679acbfb0d04652167ce8bc289fbad760973196fa8283a405015e48bb3dd98c0e28ab9e83069a76432b37b97006c9deb55e878f21dc0a
+S = 65e2358bafc9fcb65536a19d27f710596cc31f9a8328cf9de21257506047ab1340a74505581a54f258bcbe0c1520f84ebd2e36913560dbd71574e3738428097d6b819e6900f27df159dcaf08c6e1591b073bfefe3da6bc827a649e0bae9c52fe9ae180d1efc01e5a38adef102c6d106af12163b1a0f6d1543ffce3980ca0f8b70d38007288d47bc565e995b8c21da2f959c928aa2f8574a660226048dc9dba59526a30e3274808683b41c0cf086ea5afc48eb294a88c4b8b7383dae6469e8483345b1daf1d2801bda93ff91ca75dfaa8dd5d47e73cecf0efb0629fda16c601070bee2e8cc0695150739202e3be270b9801d085e11e1df07f9a4cab54fda23da6
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = f91670bf6b8bf5c8c75056d844168fc6ec0c28d09400c1df11c7ef0da9e04664c854b7e8f4e01dd8035612328c4107759bc894aaa9d50ca5cb7655892983f68ab28172f70ec6d577d4de8c93fe2e79749ad747eec2ddfbbecd89cc10c70b35451f6448f2a083452ca2ae6b0382240e4c4f01eaa4c661b7b181c8feab6bc22a1b
+S = 2eac03233c4e24b3328447cc09661c259676b569e6a0848b5a193065296a59e3b6d35a2ecd91c6cefda4f2bf9f2252a27334fbbc2d79e450d44bc282f7d7321b46f82028c154f30f6d62edf3672a1019d914ec617aab2d007f844e63e295bbd8f66163deb278d99d66fddc58cca2b911ce0af95265134af55a4b786cc214fa11ffa29bcdfbed12c5ce6438e9b6beaeffa3587978a83409c29f115423174c05cb8c30198da8b193f9446b9b49f7e3e2862ec9a350e8441ba4e5550e87db54712865fc2690a5938aebb28409b88cf0d172111a74f678ee0819ff8bdc22b08fc6fed37b676d0705396f3247a267c60f7ccf1fb260c0c2e924c1ef5540eb6125f3b1
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = 64e3f541453170db952c09b93f98bcf5cb77d8b4983861fa652cb2c31639664fb5d279bdb826abdb8298253d2c705f8c84d0412156e989d2eb6e6c0cd0498023d88ed9e564ad7275e2ebcf579413e1c793682a4f13df2298e88bd8814a59dc6ed5fd5de2d32c8f51be0c4f2f01e90a4dff29db655682f3f4656a3e470ccf44d9
+S = 76c297fbe302f686377cb155ae8a2b65a6c577af303035c4a755fe67014c560476e7a789b8f2195b0f80416f5f33b7fdccc380f988cebadb640e354bf5679ee973a1e1485b68be432b446ff5949504515a65cddb0faf6dcd1e1188656ce941af3ddc8600cf0e4087ac8382f0d5061d3d05f58c9362eb88f30a724d18a15ee68a60c5e4dedb4084c9d01522999092094c85622e67a66ed034564ac286b0ff8791e9933a23f83b4a88d2e79e3a29d6a3f87e63bb1a96a6bfd6898edaa938f74c72d6c10cb94d055ef3fda9e6dd097d52738754800ed403b1444195a311fd6962007999e31edcf2870d1c3ae3b3646bc7da55e5f1e6627e6248839e8f70b997fc1e
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA256
+Msg = 33ba932aaf388458639f06eb9d5201fca5d106aaa8dedf61f5de6b5d6c81a96932a512edaa782c27a1dd5cb9c912fb64698fad135231ee1b1597eec173cd9ffd15270c7d7e70eced3d44777667bb78844448a4cd49e02a8f465e8b18e126ac8c43082ae31168ed319e9c002a5f969fe59fc392e07332ba45f1f9ea6b9dd5f8a0
+S = 2891cbe23ccf10c396ef76a5840adaad6498b6fc8c6a2f6c26496cb428a9221ed59b3645f9a25f5747feda0f51b45319e0978f22ac4facbc15db9a4e5849ac2a1404aeb6c00e5eed3c07eeeee2435668fd17f16ab244c9d38f9ba0de9d3f3ef0d994094e92e327948f1409ef827752344a1375f608dc3cafe74970745a023b320b3bd3171b62a68a5ccaadbc64b82cee4b8a81840ed8b751ac66a29eb81fb819ec54c76b01c7b412a43ea057a80202f1c3c06a4ee60547c13c6c2fac34a5d5aae982b9dabd119b470829bd77a560e0973409115bd1ab5bdc6bb46fe4048022b0cf4fc6aad4184c28621ec6f82edb54733c902620bf45f2517f24902e56d58038
+SaltVal = e1256fc1eeef81773fdd54657e4007fde6bcb9b1
+
+SHAAlg = SHA384
+Msg = 833aa2b1dcc77607a44e804ee77d45408586c536861f6648adcd2fb65063368767c55c6fe2f237f6404250d75dec8fa68bcaf3b6e561863ae01c91aa23d80c6999a558a4c4cb317d540cde69f829aad674a89812f4d353689f04648c7020a73941620018295a4ae4083590cc603e801867a51c105a7fb319130f1022de44f13e
+S = 2ca37a3d6abd28c1eaf9bde5e7ac17f1fa799ce1b4b899d19985c2ff7c8ba959fe54e5afb8bc4021a1f1c687eebb8cba800d1c51636b1f68dc3e48f63e2da6bc6d09c6668f68e508c5d8c19bef154759e2f89ade152717370a8944f537578296380d1fe6be809e8b113d2b9d89e6a46f5c333d4fd48770fc1ea1c548104575b84cf071042bfe5acf496392be8351a41c46a2cab0864c4c1c5b5e0c7b27e7b88c69f37ffa7e1a8cd98f343ac84a4ad67025a40ed8f664e9d630337de6e48bb2125e2552123609491f183afd92634487f0b2cf971f2626e88858879d45a29b0fefb66cd41b2e4e968385bd9fc8c7211976bc6bd3e1ad6df60856985a825f4726d2
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = 8925b87e9d1d739d8f975450b79d0919dde63e8a9eaa1cb511b40fe3abb9cd8960e894770bc2b253102c4b4640c357f5fd6feab39e3bb8f41564d805ceafc8fbdb00b2ea4f29ed57e700c7eff0b4827964619c0957e1547691e6690f7d45258a42959a3d2ff92c915c3a4fb38e19928c5ce3ddf49045f622d0624a677e23eb1d
+S = 43ef93d14e89b05d5e0db2dbd57a12403910646b4b0a24d9b80d947954591afa6e9809e96d7d3e711003ee0a9186ab3d8e0b4d3425c6da4b5f7899537e737b71df9ed6355529aace77a7cba96b5b0a86399252f1286a6fcab180b598455dfe1de4b80470d06318d5f7a52e45b6d0bcc00bd365819a4a142b83072775f485f63c8004f53378a9a0d2345d07b1b326238ed070d1e69fc0b5cf853a807cfb723562d1f5682482e8a4840588bcc7154ce0740c768616cf04d7aa103642917ec5b4b514a3734d9e0c58427cff42f27f43fdfc85991e045acd17af6fba7bdab818e90eb4117684e89f9163dff7b98b82a08baa2b49acde480c5702c335237d1be771b7
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = d0eb4623eedbd97ee03672f8e4174d2e30a68323ce9980e2aafbb864ea2c96b37d2ab550f70e53d29cda03d1ba71a1023de78ba37dfb0e1a5ae21fd98b474c84338ff256b561afc1ca661a54d14db2e2661315e13581731010f6415d4066320519a363fdd2dbd5919362214bceb26716d3b188a39f32950cf5bd87b7b193307e
+S = 213ea3fb11cdd71bd5b839de8a598b6a142023825e24db7cb1a4459e78092b32b07643c7270839f247870efbd320b419ff3b1914c41b6ca4bc3cf17017d9a94d86f0f022f4495666c4a89f08e216a161d4664f2d616fa4bb2a17ccb85004e63f488ba29564ca136aa3a6f9561f85cb550b8cf8b0a85afbc8aee2c76891a53e7cb66e36f8709e7990d8de8d0c73865c1cb44727f18c0faf25c53f15e070c430e73f77b1e9c8f8ec13114d7e7ac790ade4ec6f1de0cec13f25a48d534965a8ede12090a928a91d5a1f214aefe6cee576ad43eaeccf635409a8646853d9cef93c9c04a884253380a49e682bff0750577c5a80becdef21a4a9793fabb579eb50e3fa
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = d58e0997224d12e635586e9cedd82dddf6a268aa5570774c417163f635059ea643c1f24cabbab82eac004a8b9a68bb7e318fc526291b02040a445fa44294cf8075ea3c2114c5c38731bf20cb9258670304f5f666f129a7b135324ac92ec752a11211ce5e86f79bb96c9ed8a5fc309b3216dde2b2d620cd1a6a440aab202690d1
+S = 4385e67819283d81eab2b59357c51ce37b5ea32b76af345a457e5aa2dd61113865a587d2c8a8f1c8825281c052a88fc67797adb6251d28efb911564671affcbfc7e1a3c055dce8d93497fe80da459647ac71f17e9aa07d1aafd5260ac284d622a03b6670c55b0d40696d436c638f9b48bd08f37db4eaf1d9746d2c24de347dcca0a62df244bd2a554bd08d047efe52cb1266ee5988447e1b2740f960d22e9ed3f2573ea8753a60d306d654a26503a5416a4439ee44aefe08cfebbed56585eaa01a64bc812f589da9e9d51849b4d4feea04e2b03c4d4fe516decea1e3d9e7e35bfec17d7b2c218d8553bab921eab6410ad30cc131579497d186fa25cf62521fe9
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = 3b9dc97a36492a68816aff839c135da2d7dec5505ddf496670dbf0e0f6b65ce9352baa38dbc09a9f41f8f0e1f0ca1ac56552126811c786d7a4ad37dd8b4b9f1ab760d655a112b6148b273e690877340ebea10eb46bfe139926d3be59e8cb63064aa4147a9028c6ece75fb0c2eb03f4a66c3481dc726d38d37eb74efa131cf1d4
+S = 3fc0e79913fc234e4f271cd6f5aa63bcd00e0c4fe2242815645d384781d5a00485076bc011f4412457bb7a2cb2695abfa18471ff6087038d585f802995159c8beee7607330759f310107c35b4a6a9a48fc910f45f70bffed1281f2215af34759ab08b68acd539ddd37f98a528434cf11ae0e85ef221f7117c757d970f3181e9ccda927469aa88de59ceae91c270818137761e56d75a3c01ac128b65818f28dbf7dd268337356e97bd104df6218db3b1292ec2652b62e5aeaafd905ec8fe67d6ed42e805048deb55cd9d75f818236687bc5b2cf33e17678c45a9b2144d58a4c77c163e57c1ee42cbd92bab46678092aef867968d8e6a387f7cef3920e4ee046eb
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = 93ebc05837d0d50897a1d10bf1b08a6a767e52bfaa887da40d631d6cfb0b1011d1793d6e51731aae48a872056dfc659e8d21b0d4e5672ea4d0d59f62a278a9acd3fb1c9d60787a426e8eb75230b43d190ccc33b6f9fcff862cb909e0f324c203e19ae64c2b86fead527a285a027f1ac53ba965cdaeeef7326a37e44db7b866fe
+S = 19b1bbc3e4a23b44ec429dc4479f3fa45da87037136ada535bb325c0c03193a2ed8216a9621e9f48ad2c53af330570fdfc85fc1dbb077105af39e8e3a9faba4a79ffe987e1a37e5a49c60320d086e9292060e9fe671f1bfa18ad79f1ae559551a1d5520f8164a877b3fe1938fa51cbe8b5110a332c500585d288d8b30855afdddd233254f62e56eda75ea6854b84bb05e5b4497aca3d20baaf2d6d228a400135ecc45161c3f2e7258f8e4742aa687bd9f7a4468a61558fa0ddf79e5e0ca51ffaf0151bb255152219c76a08c3e46557ed6b1415622bdfd94f733ac10d8f388c0ef646d8f5d71a3205307db703d627287e2b7be15c33fff19147e5daa36d4252b1
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = 8bb56404897a19140d112d939f73fd7d18a5d107aaa20332209664a0674cdba64eea4fa48adcc791fd0ed0da385e206d3e5178108a04cff85466ac9711a5d4b539e625c24c39c26b17cc706b345f40a4d0f76f6eb0d78a2f76acd52c2108ee9ed411ae09d87b50c9e3b3d5ed9b5da64956017cc724017dfe0fcfa806a15c728a
+S = 12f03c6f02b34f921831df384cc6e30d0b64f8ed133133ff190caca2503f1a4f4f721de6824ffde125bf41ae216e5feb8510e4d6337cec56f18550e78c69b1618457bc1b604d109e526c788628391ad8c29ad6c5da268922a55e4eb3053415a9de109112b5fac1f996236f46ed3a6c2f845c36bab09a4c21da20b17d2590c7b058fec130fbec4856ade373b6b0773994bed5ac7a420a09df8c1de246ad453dc8a62310accc9f0bdff16104dfd74c7752c33df20ef08c52d0bcdeacdf2a31298a3c72bb7397c3f9306fdbec45287688877fd6c965b8dcc513c9bdefc2f9ee7e92bac62438e4d80bd3ee2ca50a024d6fdedf39266480b2ec77eedea6b64a9c58ad
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = 35ef7f038e9b98a421b9f6a129ebc641596380ea1648bf9fe35c50c71ddd8930e8a9dc5369a5acda365e5e5f0af1b477be2956ef74e8b25516c806baff01bbb7f78ef5ae658b6852c0e26d6a472655d2f2bffdc2a848a252b235f73e70b975e74ae7f39bea177616a88b4a494652525ade6d9ceb1831389fa0ec4bdad8cb5fc9
+S = af809f10fd160a88d42dc9d92285e2b2afd8162c38eb91a6b6273a66c30c79d7caec94a00fa732710d9f751219767185da5064ce26fec0647cb0670ecc68f2a601390dff07ff0237f284dd4fcb0b11148835c8114c5a15c513713dbc16286707eecaf2c450f588fc96217d34f59e0c716c7348270041b2c4386f5a5877f7fa48510cca8b07b70490f9eee957ec0a52ab955a3f1054695a7f5806f705fe3e9802770d591eddf2a83fe03d8adbf553ae59528051218db1f3fd070f8e1d3d4b4083588cf2710271ecca5d9369468d045b0f2e0ef285f9cfa65a04cd223fd84c01b8c740a4e95b9fb675c0d7c470b3598d06489bb7d6722eb72ab8120d7f0ae29a06
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = b4422216f1e75f1cea1e971e29d945b9a2c7aa3d3cca70bc8dab8e61e50d6b038f9f46fa5396d5323f5b2c7ea880e12e6bf96ee37889d6a2927a8c285091907d6841dbcc2c1ffd725596055500dca177f62486cb301612479b7c303a183e7de0c790a933856a1f05b338e84c3ad4ccbdcbb1bb9c6c596cd23019444045fa7953
+S = 0f31c8fb4cef7233cc20bca20eaa5b42a9aed4a4f40855e2c518501ae1cfd71f98bf9ffdec1a74bea75bdf90b9c67c5824a7054ae57ef49806359ed64b2c5efdaf52829395fe426c802665bd7530ca3cbb40d5f29367ea55eba29903e8eba5df7556b5527335ac06a211c597e916fd6978ea5bc6daadccd4fcbc61ee64aacc902f652e545ef48579cd523944461d9161a542e2e7bd2a1da72ec9a751651d184fb75b16951e1b5a98107ab3ba680df0dd06131a9318e47e15326f27fc34dddeeac89b11236fdc9b8f799828dfa9714e6ca3982d8f79efa2a455e6d73421a1c933c92902790eb79adf0e4fb6202b6a0868aecac2208ab673b249a826646518aabc
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA384
+Msg = 882c97fad763ca235b162fba88fd714d023bf7380133681cfa9e6a8d7cdab00b58853334044bbf3741fcb28cfce201e372517b5a987f52f2ba96d744620885707b234157b6e5e00a2d11ea8147829d91dbc0351898d16b7ba4523c5283c6eb613b2d49cbb5d93482677d5e023087503f83afaedbc8d0bc9dfff7211fa7baebc6
+S = 0c4850b815169cda5c11f77bee14ff2fa1399af8dba09fb9485211ddd458e4152f966b2162cced299e496ca0c6cc891fce52fde9be554aa213c9f9dcce053452fe0702bf2e953ac6490c97660d8dae7ae557d94e4de409100951bd3f8be77ad5e6a7f8551190a1f2ede40fa5a12e5d995c7739221fd9be3970c05dfc990a103db1e9dff25e37234be4f70b372a4071a9c921a34de8f6c56f1106a2431b2fc2d60026c7f2cfab11ee75afaab90d72dc8e15c6d6ddee0d4302341f107c541b23368995b6e95a0efb3624e70e7980533a4d6cd823e26072a4bc88f2c01349222472ee394b86ec83f4fb9df8fd105fedc77d28b7a7e9d71451219eb42c25764bfec6
+SaltVal = b750587671afd76886e8ffb7865e78f706641b2e4251b48706
+
+SHAAlg = SHA512
+Msg = 5f0fe2afa61b628c43ea3b6ba60567b1ae95f682076f01dfb64de011f25e9c4b3602a78b94cecbc14cd761339d2dc320dba504a3c2dcdedb0a78eb493bb11879c31158e5467795163562ec0ca26c19e0531530a815c28f9b52061076e61f831e2fc45b86631ea7d3271444be5dcb513a3d6de457a72afb67b77db65f9bb1c380
+S = 5e0712bb363e5034ef6b23c119e3b498644445faab5a4c0b4e217e4c832ab34c142d7f81dbf8affdb2dacefabb2f83524c5aa883fc5f06e528b232d90fbea9ca08ae5ac180d477eaed27d137e2b51bd613b69c543d555bfc7cd81a4f795753c8c64c6b5d2acd9e26d6225f5b26e4e66a945fd6477a277b580dbeaa46d0be498df9a093392926c905641945ec5b9597525e449af3743f80554788fc358bc0401a968ff98aaf34e50b352751f32274750ff5c1fba503050204cec9c77deede7f8fa20845d95f5177030bc91d51f26f29d2a65b870dc72b81e5ef9eeef990d7c7145bbf1a3bc7aedd19fa7cbb020756525f1802216c13296fd6aac11bf2d2d90494
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = 9e880ce59f547d592c309c22a2974ba5a52cf1c164f2d8a81ebbd4ede6e326dea33d9f135a4e0947b0b9c267aafbaae9b8583f5ff215074ca1e82f3601ad71fc455a3b6adc350d0bf345223e3b06548cec613a390ada9319e70ce7a5e9526b4e8dc82612ac72524cfdba05d0dc201037492d277834a843b9f80d4564253bdc7c
+S = 8c4f819e682081bb16ddd459662a8078bca4793e18110033539460b408c0af747ea5d941f712691f5d9ddb643166fd965f5b51b819d55141d67c1553b27a4682e67d5555b64d7cd3db7fc5c2e701dd26e422af8a1fb52cd5f5a09e0d6db900a992f318deeb6f6e39dfd6af44cb217c6854089ceaa16e3f9b100ef8e78f6b453458b8ef6d71493e7c6e45282c617fa87ccdd4a0f2f9f7166281806fb41d0fe188e00c40afeaa07d2da09a2cd78052f8d56b7af40d4c7314ccf02e490d5e2123bf676f2bcbdabeffcf58792998dd0f67ed24e483d8976b00d6151a6e0ba740bdb57c9bc27fe5df9126a47020075eb222d5ca2470724460c5adf067b5750287cd00
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = a6133ca436d3f2e0a6562f138975bcf785cd0c3b58b7671d197b483bc0c003a6e947aa39d5d93229b27ed2dc1cf0acffe34fafd30f16bcc7214e074c9c02c1e5c4f2f47da68baefe5817611f82328a7e1d7d91ee7b96f0128847982b4ffd902ec07ce01ab0d2ad882189a583c4219e9bbcbe7935a51d4d25d5ccc27fe19bbaa9
+S = 20ceee0fd620160ef6a40966fa4ef3d8f68c002a66d0103eb62a868a7ad7dce9523a5b83607b8cd0ca54f833f3a68c9fafa1de7fd723e22a0f724dfca1fb6bd1a88a7dbd17255ba1e06102c2cddf584f511bdd09e132b016f867896a592a28c53c70752a0b10d86bdbae9503928d2e0203ab8f845c1f77adef2bd2f4e126066fe15af4a5282d5d9fa73bec18d2e6a5969d766eba55c0bb95e13671f82646c35b31d894e7f95f2fd35f60d88c3e70b20f6f387326400f0a825bb9517df88bbcc4798861144782dd92ccaed36aec47d5365d3b61a495339ed58e2553b74f06a295ae47a309d8477b9ca838e77094718565903432ce243c9dffe6dad464cd5ee279
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = 6d60a4ee806bf0fdb5e3848f58342c0dbab5ee3929d2996e1f6aa029ba7629c96cec6293f4e314f98df77a1c65ef538f509d365ebe06264febc3666755a78eb073a2df3aa4e5d4606647f94cc8e800be22141208036a635e6b3d094c3a3a0e88e94bc4ea78bc58b9a79daa2869675c2096e22a40e0457923089f32e15277d0d8
+S = 912fdcc5719a8af7389db8756bb0f630a4c78a1bd1fec7c4a6f3e50924a9818c9eca4a4efbaf9e8bad55d6468d83c54d0450b53a267a50685e7fb93550c2ef3554f69b4e49d3be359bc0b88f3e753714684ac047b4dfb436140b13129fc4bbfeed86548500d487094d222ed4e249db0a46b34ba5247c1b86e8650a703c9d3e0374433d3af52578d35f0f9108439df0701188da206b579e1712811c1e33b3da32f33acc9cd0bed60cfe977a4a6c6aa6498ecebab9be86c216a7214eecb13c2b7d4d309f5488012056905060c3eabe90f36b01588acb328869034e00bd19bf5c1a44d8ea2a89b747b2875d97047c53f2903f67b5a60aa87aa70a9479735198a508
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = 1aa215c9f16050f31f0ce5adc8cfa594e44ef29087dc23ac65ed2a2595ce73c0959410618f5314dada903c01c4f8d5058f52d902b9b25cd281ef2627a658a2d672a3f776f726742a994a31bbcc3cf3ea1fe551047a1d15b6a31be52307302334b8b6112fb243398c62220c046903c9ea9df1a0be50851800d659ae4241c0be81
+S = 6ba800b8692ae568344c448094e3e16f50dc2c53edcfbbc9c7be9c07461c0e0686fcfed607af2a66291fcf8e9653fb3e9857b208ba210100df9e6c0495ab4d13f1029089cfea49a6be8b62036f30e0d4e4c1d95a5eb9580397d3bcf65a9311c2d8de249c2d1d7472369537cccedf8a7feb0c170eef41341f05e7d17caac4261b62498776a5eb1d9ce7e4746b4849f9021f0aff917179750253c719017fb5dd6855672eeb0847ca075e589e320f356f49872455b30f8cc1a3a7e1a4276ed6a909be06bd9f89c3494ff7db432d0d4d3f3ccb0be71b0bda4f66ff79773004905c6102d964b3b5a5e28e4578840c0e488b7f2b4f31066b61e13821e88a0ddd2b1c2e
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = cce6ea5a46bdd6805160dce409d1023cd71d3893303ca0497f392d5c5f936fe50ee2ade61ebd35426edcf00d597a39062dfdef62dfd9c9ccfdb2eaa9e3c1b6a03278e35a7e69d386476421212bdf7af4599bae5e49850653abdbd9a59d8f5a8220f0b43fcd875953c43f96a7e6ca6c0d443f9b0dd608ffe871fb1fd7f3c70494
+S = 9a465479c1474c1a54f16f309bd87b0c641a458d86173a4f29c2829fea0410787a81b3c1360cfc525d133dfdecc13acdd5199954dd8440739608545724cf1270caa39a221e9c6bfba399b9b05e55708875bac1578642ba7211260662299bf5ef68a39594e38faee14989ac5b2daa13211ece394cde46afa1b110bb55f631bdae5b848dfdb8920d7c74eff82ecdf59f2c6ed9b818c2336364b2a56d34a22ac42089dc5730e8e57b356cc4822c1e646268dc6a423e034b8b1512d41b88c70b27e431d68151e61a4fa5c89f1e90d621e07228c0346ca46f767a989f1b0d007237645d448030a7fe45ee0f46521272a8cc453a835984f8268752bef801b6226140b5
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = cb79cee1e7c3546750dd49fb760546e651e2a42ba4bbe16083e744bd1385c473916d273e9566673e98995903b44590e7acb580a02c6fdf1552af51716c134376049817151ac5823bb02633ed8cfcb697393397a14f94ca44f43c4a9ca34d01fe2ce3e88bfc4a6f059f6e1fe283927e9fff45335793926a9472787a653d9ac5b1
+S = 7cfcc23518bc137b94dbc87e83e5c942a5297ab4f70a4ad797b1dfa931c9cfcb30449ba3b443fd3abf4d350b80feaa9687b39e7b5b524ffa35063ae6b4e12a41fd734a24f89c3652b449c2154099a1c7739d5db77ba9de0358a69ec99bcc626f657213a256732631461851c919a93b04ad39800f02d0e627cd01d4b80697a9a1fb0d71df4f32ecaad3f1d5c80cac67a58c71ce81e23fc8a05ec840019c834d78ee1955c5e41065b323d01fdbe81b768448b4a7388886c9740b1541ecd8454f73ab64f90dd46cce6a2329beae9f3ee0bf567b507440ab3ca9de2e855374ddf6e105b3d0b33a138d716d138ce9f9570797a82eae557cf321fa09b862e31ee8d85b
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = 3ddc491798c6d8c2d6932502e14ca0d6cd90016c219438427268a38b377c84d4d862b2e708d58ff055fb39defde7050c0462292183ebb83543fcd4358a8f1f8835e172f20776d2b9415d9f0773b50f909170db7449573867944e090f8cda53ad7de0f1003eb08967c241be45eabea7a99d42802f1be1a0218ee7abe2e364098d
+S = 68a46140382dbf84b1794ce86937812d8220fc59e83dd1afa087efc41883616bfffb8283bd6dd5ee1930337951ded3be23fdc657e1bc07f41b539eb779ec98f436b367259b6841e495bf84555aff07674c9fb705c85a9cc1fde4bad40506e3373cc3a490daada1c10705177c165719104daa8ab675666625335e09a24f7a2363d7b3b878f34fe68fe01425275881c34b60ee78fcc0a54d56ac8304fc7a4bc0d5a447ab89b9206401e3c445bb1cc8e0c2541fe0f3634bb49d5af3a1b7c2e7651d208392718311247f0f15e4041a46301b93da2cda7af833d80191565833926a78468abac9eb4b02c5f047ed38851c3ed7add4edc05e8407481b8b942ab627e03d
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = d422e63e3c65eff3ee15c7eeb2ef0de7ab96a3c37e2af9c2b71d8ffa6842b504122796f5c9a5748f94b535b913851f2d64cce071465ad1087ff37be97c5d5b3038b8e2145f0ec019b22b6286adafb91a67613efbbbc633efa5f32bceee9fcc380c7cd48344c85af7111e573ec99364167efec5492297a7dfefc4a692062f9282
+S = 2bc6331715b62972a0a5dab2138c5663b0e33961063ce973e68e1ad172723bcea293f7ba35af24504cb2e373b11f80b49f79d3905e0aaef838fc7c7fb5df49a322d7c3daa294a1a0a8b71a52e2c5dd94575f319c64ef9f6fc6bbb70c0c97fa12ae78f73234aaeb93df299f81513458ecd243fca5284f44a1afcd0575dbf5f81d406236ce315e98ba4c9ef7c1d43896af3b5d172e7a786fc58c4220c27b56e5c7a9be49a40b49158305034a295a6c5743cda6c2c69f7ac02f87ed6cf7b4e989ce8218e5e7cbdac12fe7de3a5437170084ef8ce33e3530392c25a58ebeddc086685a4dfb9c0c5b91d946df65161ffbf82aa3d6a80c7c07995aa3ee06b1800a54ee
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+SHAAlg = SHA512
+Msg = 6e87214fc1a8b0116f04a45a67e101ac75e9933366c532f96cee4559c4c085b695d1046d1c806d0706d18db41d7812f5273393980b5dd1e936c13d273dacba35c446a3929e21108b361355af2d41cc84447dd5787dd21a1a7d5c188a355ddb2ec18e08a790b32104c6720535de65b6c2946e5fbd024b96f5096ade6cf2fe700b
+S = 802db067a8d90967c2860c9076c1a0227560b59b66350490af1153d20b31840918e7d7262f633d37880a153b1a23e40d3cf9fcbd9c1610878b6317d9d1187f80074512524561f1c0f99f1b2ba168a15eac098b2b20673ac63f9b002e60887ff296d1212dc696450e7bb14a3efbdcdbc7f4ae2210ed35a3bf028d3eb99ab696f63a2fc69d8cce4b45846ab88943f89d588a72f00f15e1ea16d99961084542467b8f998c118fe76a2a326cb1ca3f9959c06c810a004a67cb0655f8c6202ff5e4ced43c4d8e0c3683d55607d4ddbcc0d9dd4e1783b58f51f95e159fe593066cec53b544f2391cbf0e3dc4172afd5ff6de23088404f7a496bbc6a4ce22826204b6aa
+SaltVal = aa10fec3f83b7a97e092877a5bf9081283f502a0a46b50e395ab983a49ac
+
+[mod = 3072]
+
+n = a7a1882a7fb896786034d07fb1b9f6327c27bdd7ce6fe39c285ae3b6c34259adc0dc4f7b9c7dec3ca4a20d3407339eedd7a12a421da18f5954673cac2ff059156ecc73c6861ec761e6a0f2a5a033a6768c6a42d8b459e1b4932349e84efd92df59b45935f3d0e30817c66201aa99d07ae36c5d74f408d69cc08f044151ff4960e531360cb19077833adf7bce77ecfaa133c0ccc63c93b856814569e0b9884ee554061b9a20ab46c38263c094dae791aa61a17f8d16f0e85b7e5ce3b067ece89e20bc4e8f1ae814b276d234e04f4e766f501da74ea7e3817c24ea35d016676cece652b823b051625573ca92757fc720d254ecf1dcbbfd21d98307561ecaab545480c7c52ad7e9fa6b597f5fe550559c2fe923205ac1761a99737ca02d7b19822e008a8969349c87fb874c81620e38f613c8521f0381fe5ba55b74827dad3e1cf2aa29c6933629f2b286ad11be88fa6436e7e3f64a75e3595290dc0d1cd5eee7aaac54959cc53bd5a934a365e72dd81a2bd4fb9a67821bffedf2ef2bd94913de8b
+
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001415a7
+d = 073a5fc4cd642f6113dffc4f84035cee3a2b8acc549703751a1d6a5eaa13487229a58ef7d7a522bb9f4f25510f1aa0f74c6a8fc8a5c5be8b91a674ede50e92f7e34a90a3c9da999fffb1d695e4588f451256c163484c151350cb9c7825a7d910845ee5cf826fecf9a7c0fbbbba22bb4a531c131d2e7761ba898f002ebef8ab87218511f81d3266e1ec07a7ca8622514c6dfdc86c67679a2c8f5f031de9a0c22b5a88060b46ee0c64d3b9af3c0a379bcd9c6a1b51cf6480456d3fd6def94cd2a6c171dd3f010e3c9d662bc857208248c94ebcb9fd997b9ff4a7e5fd95558569906525e741d78344f6f6cfdbd59d4faa52ee3fa964fb7cccb2d6be1935d211fe1498217716273939a946081fd8509913fd47747c5c2f03efd4d6fc9c6fcfd8402e9f40a0a5b3de3ca2b3c0fac9456938faa6cf2c20e3912e5981c9876d8ca1ff29b87a15eeae0ccce3f8a8f1e405091c083b98bcc5fe0d0deaae33c67c0394437f0eccb385b7efb17aeebba8afaecca30a2f63eac8f0ac8f1eacad85bbcaf3960b
+
+SHAAlg = SHA224
+Msg = c8ed14895c80a91fda8367cf4aee386b8a378645f06afee72f7c94047fddc7aef84c26c83fef13bf65a3c7750c91967ecc02748fd574b933d5ec21c01c8f178afe6c3356789d0112178e04c3169cfabec6e2621b334f3c6705fc1099a4bd3147a0f7431a4fb1fb80b8ed26a0af38ed93428057d154260fe98854687661919e4e
+S = 27b4f0aa139565fbd7860760610f6866d5b5f0d777921f06f5053291123e3b259d67294ccb8c0d068b8dae360aad2cf7d07296b539e4d2e9b08c343286d522f7dd63c6620e8672be492f3b039f73d88ab9d22a5463cd1f07d688e8ba3fbad531b0c3870ccbfebb596ce4ec643d309744bdbd675d5841284cbac902cfb70ade6d33946d8dc6109bbbc42412db25b8c62222c5ff94f8eb868982265392a44e807474910b4b39558bbef33197907178ce146fdd7e94092ad58bf41a474e626136789fc2fe6374a1b5fefddd5fecb7f8ca5893220d1ab9e822c3ae8adda1ebaddb18a6a12bfc165d12071441a991377cee6dc8e50839497346fee13f12c5b7b6d024b8ecfdad80d5ef6e9e4996ac21c4eb6036bb51f5be5e38f265181154000824e3c1f231d18589ccdaee90fe307ba56324318b5358468e9f3913b83ab8b34d949629ed7839f8da85bdcda52f3da5a419f777b3860dbf2ffe28d96244312549528a20cc7399fc010844365806167fe43235521c909587c2c7b8db4e296dad2aefa2
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = d04be758e97644ee60a9212e5eb81a1088041aab31e428b0cd4a8437a9a3f3bedafe576e747182a1fcb84ca21f20e3b3a3a463559f55a7c3e7ff5ec0cb096192019d444fdf092a57cd65de22fb76203c4fd33d8da246e3de2b7532993bc216d02b6fd5819306e419bdf8ff365a8478b173dad0dca281840881f6294b6396bb80
+S = 4aba732c6255f0bc443939c131dd4ce64478d4f58dcbf1d73f5f0e660c492315e987cafbc83a1a0be3d359a960783d293d375ccc3ec0d82c72abcacc339f1b42207a03795be6808ba06a891e3b4251e1b3001dfb537252572a33b4c52846dafefb24aca53fc08e63c39da02c4138b3de9510fb790f87566cd14380b138c728c243543b89d1f916ce27cada85fa32d8185deefa25c323c65c7ed578ca57276b66744a7a1a78e66d4e570999d17015bdbdd8d3d6185a3eb1dec8bc3a1287a2e235e4f116a8b91d06128d36b58ed4c9a6ed84773dc49f755e2e27a6f1aea31417069bd066b848095c002f22dd6caa72957e21a1e640f9ab9b9180df8ef8963e3611df2693a7ed064f348221e7edb1a5a81acce24acc335c6ee7d4f1af6d68acaf15d77e128142ca9bfc55a121b1b13fe5bafe2e4d6a5546b8cc631bb9d304c0e9f3d6d5dfe833c346965f0103698d34a51bca5db266afded271d8490645b3f63efc991e01683211f9482d214cfa9220f7bc81e8cbb4d118a2c306709807c070c60d
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = 39d8ec4816fa9365cdf299ce60053b9c1e99540ed29d2d163a249718ba5337ee527e222fce8eaab13ca6774ca306d9e1f22f5c9b37479d7511c05dfd6835d4575b9447847a82dde536fbaffa95391e702bd8695b45377fc067211156f9adec8d3d6286d0849fd607a23a69619f68b350afdda3d564347afd2390dcacd5842799
+S = 0df81ec6e9c2f0ebe824c445009902cd55e2718523546f08ed13faf811ec4e57e6f5772037e07025c3c0c99cd9d6c885682e0eb904a3314b825948819acecd195c845a81e22ae62c13251823d6ee386e0be17a604bafc6497b7a6cdaad1a33cd5ae33bdd50e62063bddf6d12b878b31d3b7d490ce86810f9d456739bcebde592b07808350aee542455d1761154188e6e02cbda795e48e4f28acb819440bcd8da53fdf19808456898a18fba517af06b51156129b0b8029547ca9bd9436a0673e5b5cb995340fc425fecc566acc99884e0b4fc87248f5b35bbf08b0dfd0b9ead06737b67c85f94e1eac8802fea1b1dcea446b7cab8a45b25429750946bc8b22e076828a0a9718277568b9b7202a8cc3688d44194e834e0a405fb9eea46bc7e94255d600ff6c95a46ebf46449510fdb39b6ce05a20ac1832938b659318764dc0b7e4a0215fd253f5219296fbc82f03a7b95a12628d219093e2cdac42e20eba3dd5aeeb9dd7bef5d647f151b04ab85c48970cfe73ef9fc3e7d1d8a138dec3f5d5fb5
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = f7b22de3bee8295c4d8c8a94da8cd704c5541c97214390bc6f5c75baac3f40458f57fa4e0c54e61f1cdc64a6c07d151143e7409cc05874a7e5576f0cf6a53faf1571a757c0cbc4bc9b5bf0e17053e7a374a22992cc6b9f014fb580598e6476b31168fda5e4340c5b5371f8eaf1f495e2dfee9e224a6357f136de704a7a622d76
+S = 727669abeb6bcc9502d7e88162f4a6c1dfe1a0f5141d3763e0f7e16744f9063874f153cc2de48784de84426b548b03e05a9074cef6a951640eaf9b32014d97cd9f3a828b45def13527f72a3e5e5adccaece82212c016c28f9f3312853bf52062e719081bc028f70831f9fc9132e8b63824e37c7cdeba463f9034d815683e27750cb9b383c3420f122a3b7fc6e9440925a77d766f93d586161e9607beb8a6e4ac72c32ef7b69ed52f5077a881dd0e494591e2ba552b74731c18cece9905561459f4553d49acfd6cc6be027833a220429d46bcb88dfcff0d2c5cb567371563b4852b7e628c4a6432af967e8ed69c9b6428ac552cd370922a0a4b01ef1bdfdcbc9088cdfb6d9fe326bd6b2bb1fc2acfea3bcf60d1fac5880b0510736b7e201ee8f6bc6332c0756315789700350fa549009d16e0bac084bf6aa3492f63367819506bf0c4f9c232fbd7c4d4ad663a7566108238c31fed887f368666dc75a623f222d357f8e523ff084111be4db6baf444f191ad1468d077349fef8a22f3fa56085975
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = 8d48fddf28b05b42c9b4df4742ed8e735a140a6972165ca6696bf06ebea4e106f44478243bd1efa44c2b7a7c951c88f2962f450d8bc664494b671d8e70577163b86ab560ab194ee17ed5ba02389bd0c713c9489a25307dfb3f6a7273166d13c9a061be79c1af0262275ba7bf7393ee58998819fa897c2e240f1cf903f71150a0
+S = a1a4d16956d718830f625f06c42e99189e36a80523b25f0c9a7bb85568ce76d1e85e437db0a7728b8a9c90d25e6f38150208debe54e1e3f648ff01798a8ce132e4b33f3d26fa8963771440fdc4f5d852117b3ccea975da10e5d4f27af1bec1b853b7b5c9b420012317a6c33b2596dbdcebf97bef821b3076ce86345309b6bdf29a4acd391d3b2e5c4a6866136287d17cb0e2d4d6a6cf89d64272d5c01849ed57fa2842074d3b7734c4c92be50a922d0517ebb9891072b1b47a710887004b238f90079d10fb2cad7f5013e7243089f3c601865c6bce1cb8d0d669f2bb709253e3f1e421936f6a1643bbbb7d503b0631f7e1660382bacf4680de8d70e24abf4450510e6b40475bfc9fe547752d0d5f63f40f62f4dcc903fe6d260fa45a1b85a7501065aa1900a3f841e54c136d686fadbb33b225d15ae6fc348be57fc9ccbfdeb57d5cbf53e3479d9bae9f4ff859cbd3fb076073ca016ad94086700cc85aced83aebb4254b0cfc814585f930dc623c7f85e89de6a554b9898918d7cbb4cd2db075
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = 4753183ce5607fa03636db2fdc84722aeb9d98a6ed70d0282aba3571267a189b6aa6eb65871c5dcc59dbc7db8973c7c355ba2a2e94c110d1f4064a4087eb07077e67b0f634fc10bc6ee9b8b8e1a0a20bf47a14f2c8aac75375704995978fa0b50a003096f1e8df99fdc8766eecf34a2a4f461d9991133fd5355ef8175f4c2bce
+S = 2e078b29b5288a77ed25ecececa645f6d9298e4294e3ef08173cc37ccbf727ac9b092cd27d6fbd378fff7b1061b56ed5cf077fd1a227771f58cbb2c1195a01f830f0366f989aa2d0c486d441e112daeaf83e85958f65a9e60a1937d2a7022781fcd1a83b3f7641a743001ebad53a4669405603ba0393bcd94f64324f1b777068a3ab101a086a6972b2c11376307e7d2485fbfad85be7171d20a5251cf9a5f004847d172c77bd80fbac0870a0b6bb9733537ca72bb6eac351c21588287c317625a25f416129e6f53c607ae08f43e5e0339740775a531c720f3f731840184ac7cd3b1f7bb820ff30ba7bb120b21b4bae7f9d7fc34d7418f700b142cf8fff43d81599236ebabe93d2e89f4702fada8742dc3bb4bc8fc5e55b4f874ae59f5dc9636868828efbe1025a8ca5c61ed8cc832686d5d00c08775590b316060285dc5bb9d32c90a474a727ddba9e7a8b7d69bae555604add9de0dab0eb0d551bac067c0088523d134b2e50dfe3ff73eefed934c0984aa4a5c563b862d46ed957ec3446fd24
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = aad03f3aa4cbd236d30fcf239c40da68de8ef54dcb36f5a6f64b32b6acb6834e887c6a35423f8bccc80863f2904336262c0b49eb1fa85271ef562d717b48d0598fed81a9b672479d4f889e0ce3676e90b6133ee79cdea5990e2e02db7d806db4e6adee5ea76cecef9119e8393eb56beea52d3c08ebdfd7677d5a1bbc5b6543a7
+S = 1bc325412cc952a8dd6918db8fb08192cdf81bf4111cb5f0a580a82d4dd2e14d7445eb7cb94cca6da06d2b5cc43e6ec22a5c9c845d99ac0353050c1374866befd9b6b849cf3b0efcc644ce17cca0dafcf7700c9c7d870c1e14511651b1d03a535110139c53b55938cc4a471d756a55b50d1bd280c324ac4dbaf526590c48c197573f3a91c70373ec62bd168288b0d163a09e623589d1ca5a70d17aa54c8627c7a64d921aad12626f7d32d61e8f14d0aa97c2d6502021e70855581f5e353e27f96efe1bc78c7fbaece66a560b93c0e7365d97dc4c729235484abe10bccae99fa8db9425614b673d5bbc188ea8f465424f768d8031f7eefbb698f058e1578ac41426739410aa7eacf796f43a4e4b2b4a463984d3d17d6d667cd15bf2e2b487aec3493440794c09908545f416b701a130f08027b8bcab4dc4a78cf4a55a688b2e1ca3a73a08ff0ed890bee4a0fa858cf69142f2f765400e7c29c4b540530a054641961499c709dbb4f36e7e75a5993cb3ab8cd4c886f6a3f5e3bdd3d68ef0a77750
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = c828eca460b39703696750999e23486a432d80000882d061316b2e3ef4512d6d22d2c49a0a1551399b5addbec8d5a21131bcca3cff9f7a670ff80f075403a85276cfe4f6bf95ed0a384ab5450f707f6e3c31a21364ae897efe95ffe5b4f1a9e10c47d42147de72608a5e5e943b9de869aeb58ded015a068d446a8540ddc63b02
+S = 799450a1256d245df0bb7d5290abcefe69d3b0e3b94924072f2d67d53a966513955fa7a01b830ba2cbbb056716fd605a0cfdc05f8ff58d88cb1bf32248f117de41ddfdc466215fa4e704096947a2dbe836a99071ea7344be0ffc782d14f995e4bfc74dc3ab1fa96d7223ec456497a2f51e1eb199f0464d415aef00f841e39f4578a0c26d726f3065ee687adbe40207801857160d440151fa374257eaa3f777337d129dc8b8c701eed56a276ec90c03df54305f300ef8c51155db30b68c0b06dae4c4aa07e75ef0fb09299b2b04d73d0b3e874ea1b6ac4e16f1bed0cd8dd3cf958a27e14e09705d4f0e10f8d46c75a195380126b437c68183e6bd39097e2f45b1184f519b2eb101110db74519016297683aca4b461cec1d92a7e68cbf30c2bb0d96c3b33dc62d278b9a640478258c3405a6ab5fcef5280408d4573b7ae42408b9c40483768f16a01c9ee4163b325bbb8e377034fd31c787cc0db8a53f6c0ce93e7d854411a136e1013d69fd03a0171176dc0712640ef2f792c340eedd0d07a8e6
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = 87edd97182f322c24e937664c94443a25dd4ebe528fe0cdf5a3e050adfe4b6513f68870cc2fdab32d768a6cab6130ca3455d8c4538352e277de7d923d7351826c9aa1d2cb52b076c45cf60cf0af1eaa763839b9ea1a4e6ec68753cce5829d333ed5ca6b8a4a6bdd6606fae5a0b05641680eb1fd7a975bc97e49137f3ace86edf
+S = 9cba01f79f3551acfccf56e74428e270949f78a00b4ff3507ef180ce4c78ef4c53f3b7347ee37633c653aaeca834fc004385f87798922c53f8fd741cbce15de8dcae8bb04c7d481a823eadac7d4d4546fa4b0cc7e25e67b166edde4b6f66748017a4dcef85952cbf37e802fe534ecb984cb32f446c02ccb60e257a18ac368c2d2ed21975093499e35880930f8529790c1c7762ae11526e829dc0621ac904b822ba4815d8f83ac8f0fb0f8fc11bd33b02aff4e406f8fda5efabf39e6641a791cf8241b0946b675fa48d07e48639cc1ecf420380b8581a539a4de60adb0da22e10ad41f8ba6af40d11e2720086a63db72a5d7fbe97929ab23cae1d75c485d614ca38094baca699e47200f7a792292b5c7ab95b960d6921f8beab94d26f9629d8702c40df696787a6fb6ab9d6f3c1240c2fe58c565c9328dcab603897693d9dc7dcdaf500850711e6f30b5d8498a38e348469df79c3628fe1403a7649e82f06161e0ece42479a56eaa845f0582cbf817d4ba7dced36e93a6dc7dc7362f658f06461
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA224
+Msg = 02a1a65f8af90a298636fe8fd31164b6907d74c8d38a0ef59a8a4eb80572625cc28398bec829bb544823a06ee0e4fcbc13397811f62d08662b2a782213604899406ab9d2292f288d22079b848b209af2471f4052700a916948650e86739b870964a0312216d5f8dbfc2c16593a8ce55e1577f113a8ea5205d984396d8cebc8b4
+S = 740eeb1c71940ccbc041cf204469bd2d6a461558b1d15c9eb23361cd55e1ad418a7d2851ed3d44f9c02881a22f9e4be042d451998bc181887950da38246dc1656243db15fef359fe50d2af8711b3973a57763bfc3964cfe3c911b937572e639aee53a98752598c4b15dd53dd9355aee866d5f1e48137c12c342e8f274690b7b277acd087f293cb8b8c9a3e4b3f0277e831a6864e503f925557511e57b5285221421879696802066587ce6f993aacb70dafd39f63f09cb3dcc28e56782dbfb8b4ccb1b19876101573ee9678a5f6265f808f75e7711946c27c7a22dce9f592acddac81c67afa17bffb766058e2318a1211079842bd5fc58f9cef4b50ff0ee1a293f80ac1bf2eb64ce4e1051e1abe55ee067db6c24130f0bf4c134b0abf1e2f4465dc50fd3799f6dc206b9a7d2fe34b4f4257065d7494ae733c28d70aadb057ce1bcff36edf9f9ca6908cac2141845310660ab759d1f3e651dd9fa8056a624efc714f51f3a4f85adcba68f4a58e3a956af93a5a52f2b89f9c914b48e8dfb919cfc6
+SaltVal = 3f805057471aab0a28cfc8430dabcf990612e8a908b158ae36b4ed53
+
+SHAAlg = SHA256
+Msg = c16499110ed577202aed2d3e4d51ded6c66373faef6533a860e1934c63484f87a8d9b92f3ac45197b2909710abba1daf759fe0510e9bd8dd4d73cec961f06ee07acd9d42c6d40dac9f430ef90374a7e944bde5220096737454f96b614d0f6cdd9f08ed529a4ad0e759cf3a023dc8a30b9a872974af9b2af6dc3d111d0feb7006
+S = 4335707da735cfd10411c9c048ca9b60bb46e2fe361e51fbe336f9508dc945afe075503d24f836610f2178996b52c411693052d5d7aed97654a40074ed20ed6689c0501b7fbac21dc46b665ac079760086414406cd66f8537d1ebf0dce4cf0c98d4c30c71da359e9cd401ff49718fdd4d0f99efe70ad8dd8ba1304cefb88f24b0eedf70116da15932c76f0069551a245b5fc3b91ec101f1d63b9853b598c6fa1c1acdbacf9626356c760119be0955644301896d9d0d3ea5e6443cb72ca29f4d45246d16d74d00568c219182feb191179e4593dc152c608fd80536329a533b3a631566814cd654f587c2d8ce696085e6ed1b0b0278e60a049ec7a399f94fccae6462371a69695ef525e00936fa7d9781f9ee289d4105ee827a27996583033cedb2f297e7b4926d906ce0d09d84128406ab33d7da0f8a1d4d2f666568686c394d139b0e5e99337758de85910a5fa25ca2aa6d8fb1c777244e7d98de4c79bbd426a5e6f657e37477e01247432f83797fbf31b50d02b83f69ded26d4945b2bc3f86e
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = 60402ded89d0979afb49f8508eb978a841abc2aec59cacef40b31ad34bac1f2d3c166611abbed1e62f6b5fbb69cb53df44ae93ab7a724ea35bbee1beca74fc0188e00052b536ac8c933bf9cf8e42421a795aa81b1bc6b545eaad4024161390edc908c45aae1f71b4b0228e3104048d816917cba4ae7f2afe75e7fcad3873241a
+S = 5f183009708b379637dac2b14293709aa6d7e86c267a0b690a3c275031139891267c64e5edecdff14c2cc2f2d985b62f900aee6e04ca51a70a5f946463691cf16c2d45547c5374f15bdb8881641d3040ef57807532cf5b2ced07623d0f638b39ebc2f2ce283eea2247e1df3af5430554d1d4b88b7b21622993419971b7d0d5449122a10fc31b2ddcc53ff751ff4bf4d336fac667b646780272db89a3ea4226afa20877bfb86ba3ff4204e5cd56e13a1dc9d53f5c9465b97a182b2bf671512ef89e6c3969f97307a3e4beba39a78e0ad1bb9799cda92976ca39d99db4ac149c84bb9bc8997e8d5e056d67ca23fe4be28e66c4bc00a25d65bb9d7d623fea2d3b9cf859dfd9efa9e52268bfa297afb1cc2883db0c9c42fc04180e2ec6f49657c7008e4025061f896886613895a35bc2d3655a8f50a9fca2ac648f352eb06bfba2fc340aaeead4a8457c65e2e8fdba568c60a6d8d381f5d9caa30127771f4a94fdb8cde7be4fa7b4f89fe379dd3e1ca66ae1fdd63bebdc0015448e61ef1666594b8f
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = 2f03701c2fe07d47f5fa2c83a8ea824f1d429ce4fa1df2671bfadd6234ca5775b8470249fa886dc693d2928603b2a3899b48062a9ae69e5196da4ceb1d87b5979dbb46a2813c76369da44bcecc6f20edd753a51099d027e1610712ad98cfb418a40643100b2522ffdc1760454b4c82e59b09827e4102177e462a3792edcada61
+S = 8291bc1be9c981663156ec80c1ed1675763de06199b9f2760caaed5207fb4b3d6037bd08462b100bb1767e3340105b1a68728bc45c7d6fd078dc1b5e7cbfa193006d52f67e77fcf809cf26172a46db384eaf552a5fb8e33840fa3ef3d6b20c7b46c32ef019e8d15dd38eab66f6e40399ad0bbb07f94b8c555196901c27e2d4573958f53060d800cfff40c602308044b75d6451801c688d276525c3fee17a6792882a074c8a41420109e2511418c9eeaf3ab47350dd8c2d3e066abeb7913e08f0a40abe71d397c3dddafc41fbd04cc8fa3b0641bf53a90031b61a2a9b63d8ed8aacc9b301593c9f425105498cc4f84627f4950758e01a291b9b1a33ba918aacc172b68c9fb2c767c65910816921281aa8e5482512cee686e51cabe88e18f923fde170a506ba3c340fd1d68261986347d30d124931db2ce17602150000b794c050e137f4ebd45cc41f70ef3df1656218ff76f2e75ad96e4167eed524fa2ed9fd1a0cf76926f382ffb16124dfc87bb1a4110928d5b1cd3b16204ceeeccb7db88fce
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = af90f131f9fc13db0bcebfae4a2e90ad39dc533f34165e3262bc23ffe5b20450538669bf6a5210e1ffe4a583381d9333fb971903a68aa08901f14c2a71e8d1996e59889a36d7c20cc3ca5c26fbcd930128541a56a7926a8ae49a5ae786c4ef2de6527549c653ce6440c80b1ffc06391da65b7dc39ff4643bf3fe74bf8c0c0714
+S = 8c45e38eafaaf10a710e131bec63e51e67741774a9ddbfccdd131a123ae2a03067e7a6a92e653a25178bf527b93d6aa83fa366a2bd44896baa8b7f3f54830e4d9f5632c2d1bcae2aaae8c55782132aa7279cf1cbb6b7a81e4965ff84635c296c5ac206a04680e91e7b1ee7e5793701b1feb832250010d4ad4017c1608de8f405014ca73c39adae7c4adcbaee35fbbc71151cf955acecd8083677fe49ececcb62353c0a89c9dcb9c507979b56bfe060fec45567517c05f29e262df50767df7547630d8a7b32483b923bb1e3d510422dd4cc2d61a647e4f9636aa7587d4f8ed84b6174c1fdca9a217d9b907972a66c1f5a2ec2dadb60b93b515bf74072d315d17d54d57d721c8f4ce1a43eedf2025e51a48e9ea28160cf300d7a26010383c3280a186c44a53b7188e6caa364bf4dbe0baf4dcbe37d70e3a475cfdae339386558ccbc119873b1863975e2300ede1e420031b4cdac567e7b9c5d575c8bae27eebb37097050acdc87008ca2380f5631d190029a1d712acda147c5c4378cb6eac81731
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = e57debad3563fa81f4b9819405e41f98a54096d44f6ed119dceb25f8efe7d7329054de70173deb344c59a710cce03b16af9d168f6745eaf0eb07f80916648e804941ce7e583ab0a8a43a4b51844850edeaa4d7c943135efa9e770e9411a2411c586c423fc00353c34483f5bff5c763079f7e60eba98132213d64efffa94af7ed
+S = 851dcd2d4e1d34dae0fd585af126be448d611acaeacfa34f1492aa7d1caff616707dc31b05186cdbef769479243afb341577803b579e105070ad5406a6744f56e55f569370b9fcf6ab10e1aa0383f9182d451afb41358a2f8c29d1a571e11c404e6870cbb04f6ef30414d9b6d7f1416bacab0184eebd8deae72f2a48bea3a7844a8bf472a5f8d349d5973ffde3b1c40623dbaabd6f681485a9691c9be12618bba393b396f41cfeb89e18e378c51f147c7b0ededbc403bb1306454848c9bdb89f947843d0aeaadcdf09bad99efb76e742322521929f034dadffa483958df58a71af7da45461fc408c7c45973fc60c37a6358743315169b3100d4cd54f810d6e0369b9847ee38795cfe58443019523c3c9003edec4cdaa70de31d00958653058d8509907a5149a9f81be0ed028724f7232b57f93dc62ccf093a2635ee1e5bfe6ca9ea017ffab79182eefff542d278c471e1a2b34231700423bd0e757f6a572a14a99c90329dd0701f347d8a679cff25fd6b0d380ee5dc330d6ff1b4b1a347fc98d
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = 28db8ffa55e115df7f188d627cd291fdecfbeea1109e1155e0aabc2157f7fe2a1284611e190365d2fd972d2a23dc793a5f28d4aac4100f5fbb2eed57532220d5d8d774bfa7084b44400249c19dab50e6c3c3af15966a960af1e2cec1f697a694a35c31a5a6f8ae7b73e148f09347004a3f54e7a82db390a0aa4fc526e95d79af
+S = 72c5555111eaef954236163753674a6ff81f182cbb379bfc6b548a52f9a5f260a0ed58f562a6086cf5ed00ed30adb023e90076a8adfa17cfd7d74f1e7b1978b210da847eda6b49891e6bd3fc6cd4c87b9326e8481a16c66e40021e5f878c303d3d8532bd7d966513717d5499865b2d03e378e76f7940f0448ab4d112e3c52cb332d340af122de3ee849f2e2544a40691ddf701d902bfe629766b36d82449286fd03f75bb2632dd61d6b3c6ce1c9ea8e5aff92ad2ca95a950eecd998e495e90e1f0966f922b7fb3f03380385f3b143ac1960c3bb688adbfd91d8fe1a1c32160243d3bd231a31c95dd78b6648c1175fa9c3c1244b1fa34d7c6f3255853ebacf5b3ec19b864e0a4eaee63fd719c21a72fc25b30b03207cf2aa45fd15d7102e5bae90882d00a812959593031ea3a436898582cae5eded5c7ce43de3dcac30b8690631e8db9f7a0a7f3f67b7524db275aafe02448727ff629d13afa94801d37526fbd9176fc4c216211037f8ec26b4f2672975887d70bcdbeef1e6ae99edbfb6c9a9c
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = 4839d71aabdad8b15d9f37c3d37a346758d8941b01c83909e460f589855ca0e691096865cf62698353787e7ff517561801a6ca98304f6d11d76065e75ff17a8ef5c86d9582798be4ded181424175721afac7477e6309476c14c5e750576ce3cbdc3d8db3ae68655b6674eb149fdeb1f3a903b4d5823feca1015722cd55140224
+S = 796ac3f6adf4eabcb7a528ca63a6168ca6d31d5e357ad7a3fd180334a90d22bab20b762d767a6e3077c2cc8732784e81330041dc79068d50753bd4109c9c6f9ba03b5ac44efbcc23ecda27948511645fa17897dad7c122957ae56bf4ffe3d7bef85010b33d3b91785b0427417d94b11f73fda90e6a8748e6acc1d2d582e8836bc7dbe196876a9545b2a3207c1d4ec28acf8fe6f24c240b56ab3b4e4313a3d951aa1a558230e5f1eaf38cd7fd9b393d58d359f58f4ae51dd3971b418c5b81d0707cd9e2c33a148e492e74bfdd565eba8b1f3935e37a9d1a8764cd30497066e3c4622611fc14c45bf46fc85b3ed3f6c9d4d65e9925fe4b85ed30ec35ffc69c5fdc2bfa35d1bbdcb20e399cf934fe938f4c5798cf091d51100b4db4be42e81901e5dc79a98074119b7980b02821f4c3ff8ea07a2fc09a701978364bbd00ce4c5e2e45629526e34a3652719d27a47371480daf52fa49844f6495f35e6f5e3116c00b27042b3cead283bfc577905f8be87f0d5daa13d1ca74203a9e0d9199e885f4fb
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = c0b8b24f4b8e0bf29168ba73aa912c97121f7140f3259c40a72a6d6f78da2dfcabfcda00bea48459edaaf7b5fb5a9aed2e6d97959c393cd1a524a269c15e8c207cd09142be4f7e7d5016f6f19c735b8ab4c0f28e96954172af3cbcf29d65a161391b213dd5f7c006c294fe5016423718abffc8546ba373cdcb5a053196573564
+S = 8503b85dbd9eba8d6fc57c6ae2103a78df1fff3600585e3e18f6ba6436a3acaf8e49fd12dcbb37c25b4b765037f545c3da8c39ef6842bc9ec264af6f519272f3d8698ef2ceac55393baa9846a7961b738e41f6360053d866763c824bc5873da14a28eb47d68d67f0cad7880853aeb561045f757a31d9f5c756f54d793637d721c88fb1f60126d3d16478f1fc15e0c4edbb531c2ca2e2fd9e8dabe1df2c09fd55bbc724ebeba290a7646249cd779fa1a923909b29345e54a2e25dd935bf0612a5580018b233d765a6fae3b46ef51bd8325912f439a7dc40148fdb754e2d866f357b8f0ebff6f18a6504ba31d10fe45226c88c9207b9be3c63261d75270466b43c271f75b1ab3c1d6b5a00dda8457b4d5c2195f320b0bd545fdd0679c84483c14a46b4d43c8452879725aa91d01fcc2c3867391c72200ca5d628ed9b566389f02fe74ba2a428a7ba31c00ef6b8d38c6b82b7379d2feb11031848fec0fac5b6091eb7607138bf0b96c3d2c174b5713d0dc8470b532eee6ea0ca1e8ffa3b15cbe0bb
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = 4935eaccd2af7c5b99405471bed9b21da8965004f5e6f2a6b7ed3ee2dd26cebcef4d845fff7c1d5edc94093f88de7a3aecf2bc3ecbd8c435f56e0b89bd099de7ac5f6c4377a5eb1c2ff4d801b8f159547cad4b4e60cad743f8e04627f61e1652e9354d8024710d1cfb2969be365a77f2bf8fa63b9e045257270a96c572ad6285
+S = 66d1cea94b9603efad92b6ca8a1fbe0c6c4b9dc60ec0ab2c33bb62d27a100e839378a39208715de2102eae384ca407e92787ce1118f91a0ca2640a5c93fdb78635bc91082c99968ceab289890b3ec210d6cc6f1cf7e0fbe2dae88155e88f2fb7b325ab5e529e4b63493e551c53ae38c3fbfae49810050a81cdcea627da21b63224612d4361b9df19761d6ead44488dcabb50127149f077c2963afc049ac8837ff2c29e6a35593e22531ecc2e9ef8bcbaae4349bd7227ff3e13b31bb929bbd49e50059f28fd9ffe8c296a056c2760e5f6d8dab43e9bd557793f0759ad8e08b5c3773a305a0d316ff9bd07b43106335942055adc461a4346f05ab455780f32027de8b8bb6d4845bb24d0c5a21c293d2b0740e8d06ef5fb9dbdacb4fa1c6225fd4e19dae69a8e2cbfdff1ef8b7f21804ead0a45274c735fccbfa1d60bf497a3aa931bebac2e0c8beda9af596dff0cbe11e8d4602d36b2f6c6f5bb80f12f4b9daf2c0748f591098ea63d3193f50a1f4737efacb62ea85fb6fb212b3ec8effe788e55
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA256
+Msg = 3b8a68da11b61b5fee1c2ca00a6aa35bbfdbdd42855b284320ec8d0c1848edcf6ac850427d8479eb57bcbe9a11771637886974bd561a5387014592cb717e8364a8183fd4ad463c89c980215ff629d867956ee5e75f71f7a19ea7bd589d7efb915d44dd9789448bc1ac32fdf7a2c911734db2dbc589a83c1a61dab6bd83907ede
+S = 790058355d7ab9eccb46ea12368f3be9cf6b895e1734eb20a13c749557b9fecf92b316870f0f765864b607439ee5f7e510e2c83b2756a0d9877b48e0cf257b13c997b9dc70421d2d87c9b9e5625c36a17e21e20ed389657a3e544c677464eefff08a9ee4adb091a9fbce7626cdc127b5cf817c2a5f069e32c720bc2041cd21a6bae816dbbbe28552d022b7b608fa99da4d217dae8a69f54004fa3c004d50540957648296e14cca729f791b38e3645204c2c6d4cb678b0db63a181b40cd9851be84629a068415d54cab5cb5244c8dac8dc9799a0df1b58cebfbcd8377a391778869dd275e0dc8305eb0351d81e3afa46719355eee4f90894f7fed662dd3b03270660adff637b91e18330a4f3a62c914f0d32b4eb6a30b79371ab55190578a1e7d43294bb0a721def7dae3e021981707930bd9b5cb58675851c83acf330c6ba3aecb3a890ad3c151a1e2b583a7dccbf204850daa9f4679e759ec056abef7ba4d6e0bdfa57a5c5afb6368b048a2b74e3530bfa8991c55de7cc8bbfa990d118ada80
+SaltVal = 3e07ade72a3f52530f53135a5d7d93217435ba001ea55a8f5d5d1304684874bc
+
+SHAAlg = SHA384
+Msg = 9221f0fe9115843554d5685d9fe69dc49e95ceb5793986e428b8a10b894c01d6af8782fd7d952faf74c2b637ca3b19dabc19a7fe259b2b924eb363a908c5b368f8ab1b2333fc67c30b8ea56b2839dc5bdadefb14ada810bc3e92bac54e2ae1ca1594a4b9d8d19337be421f40e0674e0e9fedb43d3ae89e2ca05d90a68203f2c2
+S = 9687115be478e4b642cd369392b9dd0f3576e704af7218b1f94d7f8fe7f07073e3e8e1186fa768977d6b514e513459f2373df6ec52e3de9bd83fcc5cc3e6b97f8b3fb534163c64f5267620700e9d8c52b3df61a7c3748ef159d6b390895afa3af59109a5478d016d96c49f68dfc735ba2aafd5012c13515ed6644f0d4109c45556e14a3821e1aa24beb8a81a48da27f131de84f7ba51581d81b8ff31ba92b8a1fde867f07e32e6c2709253448174dd31324dbc32b05f07587f76a9997decb80f38d8c13d0f6eb3c10e3d96a2293f7464f1e04602ef6e84c2d0245d7db256a67d132a47cae9abe06b61a8968f50a1749995dc15ef0dcb1d5f5959e4d454c8547bbb4d195698f484617bfd122acaae2d0e8c76d28b24005ab03caa781ea97b1c4d9396a16f7998eee7ddd9de4cabe57032d9438a5d99c6b34a956122350263c7e998bc61dec91381012e686d079e39e96b1ea4bfdb7cdf630ddb422c6b580e5506c9cc3d6c100f2041d17ceaaaa54589249f04a1370ffa3bf3ff1adeb890688698
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = 752a9916f449aebf814ce59ca6e82fa8038e4685419241c1488c6659b2ff3f7b7f38f0900a79c77a3b57151aff613c16f5020ad96ba945db88268722ca584c09b4054a40c00901149bb392f0916cd4244699a5e6a8c37e9621f54b471166797a7b58502cff4083140827052646501f5b5f1bc0b4e129147d7cc157cf6e73ec58
+S = 6646a88ee4b845da4931274c23840dada6145fe0af954829d1d56661546a25e46316e216bb6b9446b368884ba14969a6f68ccbc1cf5b4e7a6d3aabec67f64963f63b088fa817c855d776ddcada57e5daa50fc1c877389c3cb9d99095a869a963bc91ec24b2422ef6b8dd18fd20d2b215fee6e98cda415ae44d2d2616fe1708292a3ef50a075170b3a7ebab02918ab0301794c17fb35e2038f369d94dd49569c066f7c392889dc4b878c50c7e52586b5081114d202338d23304f16f912d519a9ad21baff0e3d21761f373d08421e10108a983048fcb90eb2adc7c7f12ffa1571b091c781b255a77a880e97975f14f42baf5aa285ecc142157c3e1addd6aa0c09253a11c59144abd3b1e212d89e27ed96fb75756afc20ec67423b151194cb0b0648c659987a5583cb7757779d8a39e205e7101a5351ce1af2c9c6b0847cca57af52593323905e3d2297c0d54541a0125621640fe1deef13e759f8f6c56a2ec2a94831ac2c614b911e79edd542fef651f5a827f480575ae220c495f2a2842f99ec4
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = 0403ef219938b8cdbf85d3b88cbb9c60d174134e43a7284cd87936d37456cdc3c541b4566b682e575dfc7d8f883fa581b9df7257bc82bc1bc6a2ea2a109bb5e6c5022fac1e390306cb40fe2196cece8143a10af3ba1273c368ec7a30e27e021dcbef6609f9d2be41d3fa5e54fd90a0c83862e40b837ed4ac8600edcb31283bcf
+S = 0a217503fc4870481264d8308292c663476b25f8dec08ea1d1276f0951ec6df27aae3beb93d630bf8fac08b6cce50bd92994851b4f310fdddce8e0d6a8b7a1e866a567b298c5577dc50d8a906ab1be880084e681b26456279149b4b85201621c445de13d127fb77e7f236c39df34052b4629572abe1c02c09eb198188003dd852f88f4f767f1000458680258fa4b63dafc761822ca8b98c1a121b72b1455393bee416d24051290f02a28a7b49b18b30ccb29c26fbac991401a3a6fe01fcd0608920facae9d5bc56540c80f4740af02c9b7a078958a8d8a7a93a5e5b6d2571f49d775ef7c35a6d674290b52cfbcd67277e2b2e829ec437fb70e90537eaa6fe4548551939bfa98fc98e235b264aa6064a505a8d67946e2c33e5c6f0f34fa86ba65715c258f238b69e4f6e36d86a89822b4802d21ba0ba760b2f3a5bd061f50aaadff12e0d86627294bd0c4cd1085b5dab6a6ab30146c9bbb37de3ac5c4f8ee29736d46047e450cfdcb1279e4ca83ab69e858741bfd01a779d475dfc0f71c621d78
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = 453e0835fee7cde81f18c2b309b804c67b9fd9e96ef0a96e3da94b640978830e5cd1c8940c3d4af763f5334a7caf2d20f0b82541b3434fa138016b92dcf14638817a833d79b79bc7a71223a7e0144ed4977bb217ba8d4f07d7adcd38832c05b0fc61c39a0dfcca3f32971931fd8e6dc9b81107d44c77af8a62d5f9c0c7d0c75e
+S = 6ec22bd58c32d41374c017a77027e770f678fd81017e20cdaaab48a8324b050749e5d864082f1f77fecf67a59c2885e931c3c2f58130fa6806fe1ca899045114b09d09cf9c513ce1109d2210511a3b2e93af511badad2716f48555310e6c5f547afbdb0b9a684491ff3588df933d6b04dae8883f5f8aad62a4570646f72f3656c4a7085623f5152164a81a06ccb59ca478c5c2315414550b0ad8eecd0328b2db01fff7db0f26596c41f970d032925887f1c8a446da889be64d48925b9c6b79a3d897700ab40af20b451aaa6b427ed162864db89f7824b6ae9b475b5433b865335d6f91491c1e32f635cb930dec1aa3ee7ddaa08e8ebd67b6b11a46ba049922446fa69f1a804acc29f6cee487723f2e61a40007865d80cde0119f3fe6e161a339487f5789e1fd23ac0a63b4673969fd8722e3edc9439778928f09610cbefbb42fe6242c73b68d466cef889da156d9d4ff888362db4cf9a941e80f577c944b79fb27dbe0a6967e88f1f67b91b0d38e083fc0c0228cd49d27352521312163f90fba
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = 9aff46c14fd810a039c0a62eda403f5ca902ac41b8e225c6944748a36cb45f8a769ae2a18f713d362206d2af4a1742bf3b1de8e0de69a7fdbb72e66e1c6ed82a6f1f0138edf0f6677940643fcbfe5337cd76ac29456af902b5656dbe7f4c24944d36ab6db07dc39b081662c8a31dfb2c29b4ff04370ea43f4ac7e57adf77ca2e
+S = 62a505b3f3adda45c6badb61b464a28bc45d4c66159a34b63c1cce32604242eb8fcd9ac6929ec6ee4ac1144932d725cbf4638511464ec70dbb5543a4487a241396adb804c9794b271f9d35310ee560368d949a20a2b64cb4617fcf63cf7b60978cad734650dae86c7e51b766522ef0be48bceafe2030564d5b7b17ba125097bdafee48e4df60fbb7ac2d9f14af9a270c2b7ef18cadac45b9b54ef230794339d279d72ba48783bb09b1d1d5c1c65301276523fe90e63789ffbcd489e45f8aa9cf98f33de8f7d9c5cdd21a9ab2847896de6dce0b92f07b1ffb4230ee71ba1fe8048c22dd38af80f8762e747cdec6e99f1ce0d1c743ef98ddbaf7c764412446dca58e6ff5ac0dd13322649acbc96f1c5e0bc58d1a8211853a7d2f51538c5e5e803de0b13044608d6e650bace12945a7008194586e3b74809714b2a52e9f3824be41de9fec3f36175a289baf9fd68b7e92f3754e00b41782d055faa65433c25259aa653fda069386b083fb31aeec8e30c769553f8f0389b6e6d4b392cadd24ce3f74
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = b50bf2767250f14fa7b6f5ea21a54da8d01e91151eb491107fd88b2d4a5aa157c72d89ba896b87e0fe989819442bf0213e4aa7fde8d6b026e7a70ae965193a0e1bc7f8b8af96298c41f60d154164ba678333c903958d4ffb50b50f57ad8eedb6da61a6398ddbbf9c9955bba6bf5991c4c6615df1cde156d8e188003dcbc3a399
+S = 1f068bd083a26534040f41c1387e71a8c00370c5f1c958127e0bc721751b5940513023fad02a6101bbcefaaaaeea2875952bf859d494bfb23fd89149d91290359ecb44ecf2fcaa5775e2e61e5f8d5151343576fe9c7167e919a5d081dac6bb8117229c420fd2b0fcb521f4e72366bfb443e688a65fa392eaa5115c292ab05bb4db65468aab267178653dfa0a5efc960636fcce86433528dbce955a0b1aa188ac33ea128206ecc0feeab8f7df6f8c381b10489c8cfb2d02459e4cffc16f43a66aa4eaa19bc518ccfcf9fc1e4861cfa13e9b41fcefade2cd2ebc001ec8430a1cb949a0f2f876badc568c703e4209e7ca16f688ba9705c14fa1c882e6c4871b9deff31521d2d418e0342e189c40ed19c1b6f4320d89a36f78eca143d3c16dd3eb338c0743646fd314c725c2d36a13080bfcdeea0e431de71d61f652033a75424fe1e1586695c3dc463ad553c1cf3ab24a41ff4e031f9e0c2cb0024cef68273ea3b8c1be9d923d3e9c9686c41977ac7be94a6d23181936131c17a39a898c943dcc8b
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = 5ff000f84a951dbfdd635a4d9f1891e94fc2a6b11c245f26195b76ebebc2edcac412a2f896ce239a80dec3878d79ee509d49b97ea3cabd1a11f426739119071bf610f1337293c3e809e6c33e45b9ee0d2c508d486fe10985e43e00ba36b39845dc32143047ada5b260c482f931a03a26e21f499ae831ea7079822d4a43594951
+S = 18cb47bbf80bad51006424830412d281c66ae45c0b756d03e5d8d49f73037968d13df46ebebd9b5b4c58b164d91d0608e8ebe31d8644cb0bebfaa8e2ccaa1f5746ac8f3bc02ff6930e219f53fe13fc070f910ba1cff0617aea6eb312c1ef285869746673ac1348e89c3646f583d7633f5a2341626bc2e7e2087ff9d8f13d573dc6455dc0068c7ac6eaf5b3093b081614f7b252170c4893891e469121fda655a2a55d67f5df0ff6e29ce5f9b0c3a1a88342140ead748edeea9706d6570e900f1cf3a9adcd7ae64f207585417946b104b3990d1a2d950e0e6a5533d3cfc8c470250e4c797273210f248b8922ab00422f2ecf85aef73587e8c5cd1c2ee6ed9509508409673fe07ee2c462c52d091e7a795d8d3c55fdd5a710d5450695a5a31ed76f115e71a73c6757d2def7ef472571b0bdc7558c71eaefeddec946860b0c77936db31f2001d0499a381e5018870b41ba04c8d42ec0dc55c9fa2af237dc1c405dd8f555b07a237cc50cbce46c3016118cf4ea06c047599283ad4719d647a225206e
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = 531dc2b8566e01a8bfc580da607ec212fc1fbebd5a2590d897046f0ec069df20a1c2278ad70006642d9ba28625d7c1efd4473b68f38fb064346d762bd2fbd5376c2e77de13a31a32a29b88264d44c9f27d3a97b8dc4d1267ab85b5e05c6389575d6a98fc32dea5dbc6cc1a01034a42e1a000b8f63ae720a9a7511474872a6148
+S = 80baa663877615c2e7ca9dd89958a74e54012efad55ad05868dd74b0ce78a661e2b893c3ac1fd837f282327efe4b041220942649b5472c1ac702070787ae5549398a57653d5fca69cd5446d63f6e9d0684925a235acc96b8a10bdf14fbe209fcd4930b5945910d84b08867b2055fe8eb1d771b753759593b90d6aec5ef182cb33bf2fe29e8c67ea4e8433ecfa3f9ba4ce461f0ab19997f299e95409af97bf57e2de410ef7538f699f385c1abafdf9337f7f9d268da87b2b389131fe3dbefd8c67bd2a158cc4e04f9ab7fee2a58d74d063e6c16958a90574e3e4cb881d32c3116987e46bf5bd44f80abe6b9eb717a9fcd4c0cfe80dd2ca62c33b5dd3a59c64810073e0476085ec7b76638983291b69559c815cd3bb87d4b07e24c6b9ebb7028e800a04f09b110c167f6ee3a3bbb73695d89bee92407d4adcea3eaa47811e23f8c7f2fdfe891f8cfc071cb984a63846b95ec04d6261bb1c5980018feee15c4e7bf632dc8306128fa22c47decfd9e8b099554f17253635e6316712e0b95efa3fb00
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = a454391a7c3695486c337a41c2add417d8e9e9c6466d2ebb56ad5f97b9e7ce30784cfcd82d6066e372a3a1639a71a9369f2777435c87d100fc5e6638b3631a0bac639f36429b4594726613e5901816cf3a29f9228b96d66090844c7d0026d2e327e24ab924afda6554c2f74f0e69c2e8913798ec3a61e4e4fb6838ee08f89dc0
+S = 261180717edd905b647bc869f5259203811606221f545a3aee5fc123f297cf7d8a7ee6cee3dc8f97d24284ccdec2fd4680f1428ee75797e0379512aecb9fc1667523413e323c4bd7dded5caf9e5c606e5ee0c694d4d1b5a1f1cb613b980129f64146e42e8261c1f7ef5603954d34d56a50f7431beee5ab291a4759168655a5123640d596b744d97979d39f874ea7ff13a7466a7655d02edb492b58049f2208852297eb023e657f3240c5da9a99fd377728bff3cc073109c31712d94bc24e08c433533d4b86a73b58fbf2c598ccad78d46ca0a055601850960195aac1364dfaddbd06f14a78aac2ab4d374505cc61fc72c1050647d95a733517b709aed2d896721e7484208501480058fa4f6044302dd705c273fa7fb42eaeb02d025092b252e16d270d88dab6f68fd7ad571011f89627683e029d1bf1edc149d47452ebe87ec68679579940f5aec25999b0dedb820a5483ec6901abfee041c03b1a7f743548a2caabca613ff5d9f8fd7c694af12b29f2c2468eff55f9e008757443960fae459e
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA384
+Msg = a05e5782a96ee6d6f10be8830d8c27c0acf272abbf77e684dd6a6c19e5398381e5d0400d3a21927cf904cb6e8e425c1ca3ece04544f25d6c40f0c640d24bc45c807db53044adf63fea835d8cb93a0a4e55f760ebe4594e247051d38d8c34c1413b0ec1d30d3a97888b2fa7c3d59db8c08ab9f985e8d4411635339be95d1b0299
+S = 87d80275df7b196b7e1d0a41147719d773edd80b5627301a500d91665ba86076e6a31c8f3ae86aedb643fe2af223976ea4eb3d4dca2cbcf81ffd14b7ef7de3ee355a8d0f4143e5b0f0a0950a42811102e602cd214e1c945c47e8b7b66d507103c3456f404f9c48aa7fe48dee0aad05e599f242adcf8ccb0cc9db3a6c244a913551ab595600ecfbb67c25a95b54f4054397abe47650e5c4991edaf1441ba9c8e3fbed904ffbc977142ebdc84769865a215158d5b052e75de318d75012172e28c31db2d8bd4edca787216dde2a7387c543f162fc91924918fd6c845bf1ebc0220a1027fb4227340ca4cb0f183e5b34b1e7f93e14fa57bb9d2d2ea53f86d838bcbe3f055b473b0b469afd2960c0d76ce2c30f3d49a3b29065bb9260248e728cbe328bdf502b109e1f20b9d037860cf9e261611b4cbf27ff9b5bf425b2612afc7cfa3138f78ad26077cbfb947fb2aae6f4be85ab2d1a15860839b822dd03a1a92a19a5c7244e98bdf561625ca2a8df410ff855752ebdf3d49f5eb98f228acdd52791
+SaltVal = 61a762f8968d5f367e2dbcacb4021653dc75437d9000e3169d943729703837a5cbf4de62bdedc95fd0d1004e84751452
+
+SHAAlg = SHA512
+Msg = 44240ce519f00239bd66ba03c84d3160b1ce39e3932866e531a62b1c37cf4170c3dc4809236fb1ade181db49fc9c7ccd794b433d1ad0bc056e14738e0ae45c0e155972a40a989fa4b9bcdc308f11990818835fa2c256b47ee4173fb4fed22ccf4385d2dd54d593c74f0004df08134eb8965dd53a122317f59b95d6b69d017958
+S = 8f47abc2326e22cf62404508b442e81ad45afff7274096b9a13e478cdd0a72f99a76bf517f1bb0f872a523d8c588d4402569e948fd6a108ae1a45c65830828a10e94d432765314ba82ead310fc87ac99a5b39f30ab8820bf69e6934a9c1c915c19f36ea7717eaff7af67b4991315b1873ba929bedf18a975be808e7aa14a6726126c79cc93f69541c5cefdeb5b67ec279d8f5a446583e4b4faed1685140ee4b3b757c8ff4a1ef9cd76a88e05319ee62003d2d77290c94c579b0ca2ab0deb3176ef10a3fdb85c80ffbc9e2a665a23744fc836f9a9a103cd9fb756952356a2f1acdd68a645e20179006558b5d4d0b9b0bd3adf5e290f49dae60b9d19920953ea8bb237d5b3dcfe149a60f12a4ee3a889b33bcd3a3b753d610757cbcd093dd5a734255333689695ab636963e3d215a8e77ff31973718a4944a1e9e44f45754d39f6fa431c53f9a2ef36e16a5f70636eb5fba54e15c20a714f2809a7cff4b8dc1165f836607eb5a5a3bb0c4567eee26941fef46fb41e73b565c0cf8c72e404221264
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = 06d5534b7769256e8cf65c6ce52a3e86965a1fd12c7582d2eb36824a5a9d7053029fbeac721d1b528613e050e912abd7d9f049912abeda338efa2f5213067777edd91b7576f5e6fa7398696599379ed75028cb8db69fa96de7dbc6de7ca128dd51ea334e8cd9cd8fdaefbf53fc825eae836b6c6cd70039a77e420d999b57caae
+S = 913fc118d5ac1edffb4b8fcfa4e85986b46231cef3dad911d5e9534cc88261f6b6969b75a3f25d83ece7ec2034b01d3b2be6c5bd958cc4afcd44839e3953f01e4a15ea5ef6e1b4b0e8ae90bdfd404199e8f86547f67ff6b84f2162c4311cc9eee06bfb2fe46198afb9745d9c443833bf2387eb92406a6339521396f2cbda55d98fe64074d2f2e27b8bc6a79be3d1cc568869b0b50fcbf702b0831668fbfdedc2d1b5491e8ec623edeb60ac870e6e8d058593fbbc938fbf741700efc2b2467e7eb254ae008509e91607f8e50aa16a4e851abca7c8d20c6ff61cfee6c1fb676098e5cdf127c9b79538fd1e6c014161054caf43b734fa69fe06a00d76f710acc198f3da906a7d2e73a2ca882526cc354dd7630a303d8f32c655b5b33cf78859beeaba3f9ae052c8d7471cd2bd9edf42fd8f70c3b0aa79c076928068ca9770959afa632ca6aaba6679e45d6888c50125a73b9deb00d42a125f25df5434beff0d5b0ee13a16b17045cece0f2da7577d79d7cd75a4b6c5bc345f460a173487b51bc6a6
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = 756c51bae61d75e8cf44930e1781dd6b8db6bf8b1f68b4ca4c685d14dcb2d4eece953eba92149f36788df34769987af5d53253b6ec1b4cef117cf9b88bcd03e07ef6c3301ab40ff4133f54b8512ae550e88a931b4a5a7e88bc1e2bd806c7d6266fd709a5e8c56d2a88a3e1ea38fec984b006a842a2eef29b34961bfdb468f4ca
+S = 735186ebf08d505161a8bab36786138414bb5ca2f4025289af237a40f8d0963df9117b619f83d9a98dfcf74b8f001a4a742c85ae018c3b51f16eb5015ba7027cb9a0d0b9e6b65c08ba58b671a9b3dd62107bbd5ae932784d328cdb2e1a551eb67e9d33ff1cf9bffdb223afd75d3650459fdb58143cd4490981efb0b3fe36f642e1837a5d95c3d444af73729dd1a5e9937b8114a28e065d1081f061049e650e45ff5ccf75c246e2e9433b27e79a1b06f7b6b57f9b009e97168a61297cfd0a8156d026a6bf8c3764d0b715c619d856b061df35725498d86cec25f7e1da65b99d9ecbb9a1a6364252e4790d97ea0ffd6234b515929b5ef22676c243d386ebb90a22e67a0e1d1094dddf7721099868c31326814887b646ca52a2c4bcd43f7c71399e7d13e19de688ae5c20463df5965d8255a3e6928d614b601274b757cfacdd4002d9ba8b248ae700d8776475d79d0a55ed4241c9919a3c44dfb9a1f5d0fec7ca341774c596144c38174af59af6deb8937a7d14c459b5d768a977445dafee1a4eeb
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = a9579cce619ebade345e105a9214b938a21f2b7191c4211b2b75d9d2a853805dc8f1eb8f225b876ab857938bd0ea8cc2ff1ee90087030976e3f46afb9f1b1bae6d3874dd769d0426ee7dcbdceb67a9ad770e1781e34b15a45f656328c88ff485c1b2a083056d195afc5b20178c94f94131761cbd50a52defc8502e22cbb6f42a
+S = 603ff63ff638f1ad410e266d82a04c6d475416a0470d97f483c0c99e8fc7212d61e02cc8b4493c9a9dac711d2a8edf196a26563866d68fb04849e82db0f9741f721f2ba4e9db62f6ecfe3b87ebe7feed0c9e2dd46c3f9252d4c122c6bf1bf4ce215ba82fe7c5a91249da70dd30fc9c8ac8b3bb2810b4ff38bfacc13fd41f6fa26507a055e0f1242f18ea8ed8a702d265f893cb4eb61a3dc8e18777157552a1c58db14349a0d0a2a900a0a1f4de863fbadb063ad2a9e526a0a8c3bdcfca5524c181637b1c4a574809fb45b2e4f06f3f89f4ccfb30217b32fc484bb908276d659a0d9a3e7e3fbd46565a0924f918b16b2d6527ec4b5d1d6ef6d6720f3e00485e87de61ed49ed13e85ca6a10d46d4ca4839f486621cca48a7f955a878c4785d55de96facbb91b6ea12e9e4fe4beed00141b0372a3812465e65030f4fb8ddd58701aa3da27d26feb8644f7c80b8ee2a3c3b20a516c7f0b068b503fbb65d3f3b84b253466a887314aa8eb9d85cd035bf8dbb178ebd8d5496fd1b68432457c78c69cad
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = c3287c23b613aefc2425a8b8317d647a447816bac56d0c99259bd9711f5fb2b13eab18e8a0b3b81ff9e98f6cda2c51c4343c0c1118720884c0aef32dd3903ac9e5ebbadb3d7698fedcc56d79bb78a71453b32c2a62ce4000ed4da85581120f3abfd1aa2418c51840d4a18c0659ca2d11aac3bd2e2ee879b3b3604112b24df9ad
+S = 878b9a443921bc7d720e3e288e8f39e550113e01d04fb1635a26f796fb8b161d5b758cff914a2441d8350f8d3922aa5615edfd86501c9a05c210c93a1ae04ff761151dc8d652fb5509ed100999d2bf6e40b1bbb64cf6c5d8e067b445daf567137cb8f0863996de8de9a647f982c9e21a787ee8d72657a2dd42ec9fec49ea1c3345cf004e94594a064b6b6b222845d64c935b539d3fd2d535fe0e47ac6746028e748556c2d88e4d40707e74a1c0cad5cd95dad263efd3ca637ac6b8f78ddf7ba81e443b836d85a83dbe843bd6271e45d842e1bb241c9c18805f37bc19838ba2bc6cd38401dce0cc9780306ea8a87d43110b3e395bbfb81c3ba45ce1cd71596ed27c03e2090a7ee81f60119e187adff0d96acfbaac38f7cb503039ead9cf9550ded5693d3c257406dd0bc061d451bd81d64f969b7c2b84619f0dd82481781eaf5b8fc82a3ac5b9fc20b42f86d4225a435b903d2258f5cf693d1b5c6a5d144f7f4eab9e70de2f3879f68e4c1c7a38dda63e6186534fcd78d58db709bf57a78a848c
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = d54c51f90b278c1c602bb54a23419a62c2e8527229352ed74a17eda6fde02f4b0b012d708515a6215b221d2d291b41cf54a9ad8d562ad16156fb3017fcf2cdf6832fdfa21015cc41429355dd0aa80e09bd2612c867b6f4aa631cf93828bc8492665dd157522ee6c53d06c7226cf0ea5a24e7eae904de7ffb9804aed22a453d69
+S = 265749f7afb1e1d16492eebcee9f5004234e1dcb95b832d14165992f4d1c49d518ba15a6b3adedfd803287cf60ce8c915882e2c78d69ffc46fdecef008e5d7f146e38f268efe49065ddb6fd7969a842189b9d7b3ccb32d62aa05e87e932930f7a1775c338736d9bc8f36521609d8be0c29fdd1728430a537f0a2b9b9fef2cd9f0946c221c08aaa0270e3187ee5c518cfeb00169e7718b01ac0faef097e9cb6a4df3e87a5548a6c3d9f1ba230ee1caa01297e5f17d1be1d776552f36638cff13ab73a1058fe7c1eee28c76a145e9ff9b17074963c22c6435b6c5a619a6f39df94ce348b244320b207a9117e98b9aa5a8c58516d39c71878c4ecfd741ce6e51222fcd92ad32d70c3b92cbbe301dacddf2ec3aec21fdd38a7e110f4f5448577b9546f1a7cd71a35670c1ca47a9199437cbbc65926cd17dddd2c0c3b1ffebe682be616e638839744a147ea897885afefbe6f0e37d4e482dd005f4ff199d0d033bb753380780c90228a87d14d8dbfb829a195b5d8b2dbd67c9eedac48ae639c158eb3
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = 57724b7062193d22f2b6bfd18461d87af122c27bf06093a5dd9c1d92b95f123971706cbf634b0b911ecfa0af6937cb4b884b8092bad7afca065d249d3707acb426df79883742c7752692c011042c9dbb7c9a0f775b09ddf950fdceffef43c9e4fc283b72e7e8b9f99369e79d5b2998f4577536d1dbdd655a41e4e361e9fcb2f1
+S = 84a21a5cc060d141ba9caeca77fd04be8ba8270235e9948d0706dca77413ce7f0811da8b2f5372f8ff5a2eb2bbeae43752c5d1c1e3877992a49574899a6ec9d2a9483156540322fdaa66eec4a2601c281ea5ae996190853644b48231bc22729f32c2188e5f5f7b5056fd3e99ccca3effcb9793343f52a9ee60217d1c492102534a334c1c60a9c4ed63ae861bec7de9898c2dde026d9a029e7d9fe44d552cd3763b8ec3f4371f4e682315657d72a888913d15e1a84a981b3d8d437589a6deb37d14e86aaa365124bf165045040b1f959accff35565205d0ee72bc56d273d1973410774cea7735ca79c6bcb256b54fef0172e058ba91619c66bc45e11b6bcc0f68b529ec3a4133598bcf09c9c4bb0f874c7095f3ebbf85a5f669bb3717eef929fb1c22943268c310282e8842840aecfdc942a468045b02595bb16336634da20ca0b8d758cd30a2b7a0bd0e3e2a6f30f36a1422adfed88e211485066d6c0fa5c986f1dc5b4c1d965021dcc24b3f729f07c02b47af75d01f49da3dea0f1bdd6b4c0f
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = bf5ff776122898e22333fb6da96d2a87a3e6c4e63f28fe7afbc8e8a40a3af2a3f9e9ae4f9287d70901a293f23579f55b890dc67da47b856a9d88ac44637e35ad5d375d7e4d77a8bc7a7f25c80edef3d5bd8b049fa731215b80ca2ee9ee6fb051326e8c6d0b9e11e3d7ef3957fc452cde868706b512f2da33eab4f7fc71b66a78
+S = 86ece9321faf1387de6afa7b1e16c2127e71e6472e093708f0ac4b40e6efb30eedc546907182798535ad6b88ae4a6f8c4fae429d225058294ef76d44ca81defdadd12cea16c58c660a4d158cb6728545307f5a6234c3aa16ae6d989b0b788cc4c18b08c89b57fe302ca6560affc57bd533bdec6ae90fc37167c4355b07c6c7c7aa2bdaf96002832d62c2dd090c61cb8658ecc0e224964b50b9abf1b4271869a8951d81cd5b46af4ead70b0454c01a7229ef2ff27599c7370e747988b45b9a8148575d73014166082947c97e8730d5458ff4a4606b1185f1bfd476e8fea2d1d7fb5d14a061f90e438ce5e36b489b5873b7400ed779ec82adfdc2d9314d6e6547dec3be9853359821e6f6d853c2292f1731789002033ecb46cfc3a7f197a18a677574fcf6870d7e47db874cff258f0f6589386fd9667af292c315ffd849bf71749ef1b4fc5a3fdf39e2782f986bc8f523162c0016c51702513ed17c8f68672cf425fd6ef8b6c8e983bd2128ce4614085e7fb216af7ff01501941f23ffbce556f14
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = 61b6dd24903672621810cbe3342497a6b298b524f7cd50e342914f483596ecad9122a2b341094dd99ad98d4ee1546b040d233f06cfc8d10bd0d5be4b3a5b1d9179a663924327847dd5b25bd380ea4c7965f9280c7d845074dcdd1ebc367b8020a2a8e6689e7a5f755304fe1a1bcd832d418237dd08e71845ee13364231dd5d82
+S = 57d827593ad09f00005ff1ba4521a9ab2717fe34d7af12d7ef5dc07814cb93257a2903cedf0a80704b16fd8aa9dbd06fe3d96fcc7be3843ea161e80ca56f3ef6f760dfc7f1704ed4a50142267b87d244c71fc72102112fe4ea801c82c631edd9d917808c0a1f1c81a9de859dd87569898cba76b35702232aa492850739ec0371b0342318b92eefc45e6ae8547a604d9a15c2829ea85533d6d23fb61ef569be63779d3d2c7cd3bfbc26df02616b7bdbbc0b4e2b5ebba7ec93886a369d10b7bfc0e7f56e7b7ccc814880baa634f4afd874a841d40cdf9c8f117535650b55129b8913d53417bdaf163d68e7044ac011a55ac0e1afd9279d46d31ef83a0bb4a7dbe70bde4b33396750b676576497e202e40cd1401fd6cb08878a6c22db61404b4c2aa88072f7a4851d9faaf016a60a7a49147fc234ad67f8375a90069c274aaddaea43df6292ccdf7daab5f5113070f8ca5e7f43c791acc7e1737cbc311bd5714abb66561703b9ac3629bb10bd1b7709f081840eb3e939c69657ea8f7cfd596b0265
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+SHAAlg = SHA512
+Msg = dcc271b1bb2e50ebc23330be36539d50338baf2e9d7a969358c677e8bcbc7787433615c485c2bc2e670098128f4caa411b9d171392adc6ac1a5b297eec4d5b0f06d96cfd1f26f93fe08effad5147f0c3924307a2cb54d95765942e607b040e6c8b731f6372a22ea697a50b98668c9a5d004327e230b7fa1da23a2b964f29b826
+S = 0ac938ab04bf4efa587e34143436ce608ad089420956a72b23103fea769c03f02c3a0db764cd5bf3cc8518565b7efff70c74cc653665dc06e7f1d584e967ba193a70f5e3f7416ed0d4d5dc0e761b24ac8a8be172eb95691f02244379c9aeda8a9f760e061fd476b063b5ededa56bed819fb7136a4604879a92b2cd35507fd49b7d478fbd24c764aa5bc535a6abd7bff5c7692035620597f6329a454ce9188731c4e74d56c5bdef11372540b958cf2f8c42cbdbf915e0c07c77f04b05d876afbc3f2c205a4048826319184d650a243d192fbe35a163ab8ea84a001dd7c1472988a78042cf9fffd96f6948f0e692fc3f3b1c9c13de4b7a021be25c80606e1105cd56815d27c45fef995b1fea36e2e12aafc4a69924785c4855c50c61b1f43be9a1adfd8d7ff2ef5240dcfe5ea4613db4ad085bb0a6fb8627b1ed94dd164a4d9c4c9f375983734f9d2c35ec69d6d7421157d8658dcec1bf6599ea94280a63422376bfabf1b9f730292c498c953654401743c9e6bc499446759484d93e28d5f9f486
+SaltVal = 2d0c49b20789f39502eefd092a2b6a9b2757c1456147569a685fca4492a8d5b0e6234308385d3d629644ca37e3399616c266f199b6521a9987b2be9ee783
+
+# CAVS 17.6
+# "FIPS186-4 - SigGen RSA PKCS#1 RSASSA-PSS" information for "testverforgen"
+# Combinations selected:Mod Size 2048 with SHA-512/224(Salt len: 0); SHA-512/256(Salt len: 0);; Mod Size 3072 with SHA-512/224(Salt len: 0); SHA-512/256(Salt len: 0);
+# Generated on Mon May 11 14:15:38 2015
+
+[mod = 2048]
+
+n = abf44a770836fee434fc7bf17b06428a7cb50d27213facac88fb38d3a29ee81669d18e71daa3c78fd89774a223e7a15df4216290c4fda8e15a00088d4071b682f3121c45e25d93b03b2332a9f1a0772018548302f60b2d366528b2364a8962c8bf0ab64e87e1d6ae13432038e3f9e9fd8eb37aef736a19987c259106f4cbbcc4ed6a4d679fa9422489092cc4f12b17d974fe799477995b8cfa3494bc5b426ec3b2d8c02373969630c003e08a42e5e62072dfcb1183ea5364513e6e357bd6c47d69c41767a304b7e7ba115f348963b49b02f34c87e17f5fdd29674dc125d333a4c0c6ba96a5b8afb4e4f785d2e9eecb0165e7f2bbb464e2a65f03baec25d7f519
+
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009b34af
+d = 1fd04b94cdfa3cdb225082a261b12b739ae7c359148acd5ac0899b54347eea93e1375aac688e3a2e6a40a4f4010126edf569a039566b315784bb6a3b3e370e89694f4e6d94608df9e1fc086eb9b3c283fcb7aaff7011e2d5a6f0aa56f2fd64d7dd75abce5e37247c6cccec7cb04e0b5e597020c7f63cce7dd7f84564a6c0fa8d73813d187878271d74cf8b696ff676204847cffa599f61cc3ae39fc1805be01fa2308011b7b1f1c39be87869b7faea7bf22d7fb2adffee26b364014554f6cf31e98d3fb68175731af23355048a22e9a3de432fe434f88cf0689aaba5aefbff08b9d996d92152a5bab5a650c73a1db065b8fcd4a9e260c69b7c806cadda8b0c4b
+
+SHAAlg = SHA512224
+Msg = 877b48928e3fae877f436179c74fd2a7fbb3e4f7be96f2e5e68b14bfda659e143e4dea6ad311582f98bf92f2367315d39a6ded38e466bfc280240d80924db6629879bcf04b8a4a3bc540f614e908437d00156a5da0b25a78d2d7fd9d73fabd21db27478dbd538e944eee1348aab7658d73d4e3cdbb22c9ed24ca6b804515bb3b
+S = a08596d43d483c01d959691c1b8d5bb22bb6e1bdb250a8a4d7d4c192e33389baf5328e84d8262115d5ed0eb1bfaa509285dcd17bb4da684e3fab339bf356d74a26e785e1c4e6b2b17518ed0fe796c86ed0b5be64b571f0abf19667e98656054edd3b1bd20c6aedb17b39aabfc5542673fb73bd9614ea37ac4dfd22dbdb1a55d3028984e65475d14caaf7088004555adc39b3cad91526b3812c943c2504bc9145b784f8ae534b6ac6d1395beaaa3d80467bf9b83ec0cd2edf31e50c582cd035b44215779393543e250dbf1c789e248bf980fe4ecfe23c84c78230db169a3b1f2959f63cc6a6950cbb30c91f7bd68fe8298c3c1619af9ee413169e5942626bfa92
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 6c2cdf5fcbb2a735f76045a50c35cc43db0cb86be0c48085759d6f8844e5afbd02d5a7c65bb687de28472062e863fa916edfa090d7b23fb0bf586ff4b57851ceebc4da2a32206ead2607b13fa62b9ac7885cc9358aab1ac68bcf7a83fbc8f90c90c221933a3b862b5a689f432fd5d46d904dd865e1f9394e40cb363eff1ed0fd
+S = 2c9796e896b6a034ad2bd39ff85fbd2764280f38e4a4e7ea7e369ef65b5cc43226ec9615be328330b2e598ab6e407808c44cce49c89d02adef349af24ac5c279e1ea6eb5d7930a612559ec8607e159be5df95f6df6227a4d55a6b4e75be5b7ca59f93c7c93d2c1fa1f25c4acf8e55fc920d4e21b84ad71d4601e3cf68cbca1b41ecdd2b770134d336e6a9c02e4531fc4bf8bbfd157e1d50a633e0b22c49eba6dbfad2743d0f586d49c9cd74bbe725f6633fddfc73b06fdf4c8673d4c723e0d81e5578e186af059e1e62197e270f7fccd97506b5d9bcf9e17463efe6ac15e3f1b7fe2addb1dd49732575676bbeef8339ce96a8800657d1d7bf8adb9ce5ff380af
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 64be9e2354f13bec61d7a59ac983318890be155dcf0764314fd840f1562b4b04c13d5e2e53927eb54d390bc33f513b0c1dccc7b09573e463a02a75cb58767f29093cdd3c8acc3563ce1d2a01b65ad325299e6c6b67fd4c1d9ac3179eaf00350963448315a1a7483c0b0c6a1cd7a7e21ddcbd6d54ecab84a7652a8f3203d156ea
+S = 57457c844156d5e608579f117e87f9721dfb86c72de9b464dff60201e81a5095b891e5c2d5cd1d902bb3b75881f930edbb3a955bc35a102202b6676637792d22135cc7bc67411258bc3a5a4d0bdd5bc2e2362e6bbef30cb40573e4cd404f374090a1b0417c9659244e33878f297006b3113635af5713f24d971f32fa2be633ee7bf12c4539ffede0026cbb9eeecc8312f375d1a4c8676cc51a9f26fbf64926adea4a1a3746a4276e5d4d2f282e81007ec0e498e54ffb2e7a318ab21f5a10d6c7f4d52c4723f22fc51ee4899221f7cab15477326bebfd031a771e937e3754be3695227ffed0f87677c0fce2fba40345b7f77c86ae04ec5cecb34bbc62112fd957
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 40c62273c4b139e7807d1f987b9dc8c0da351bb9628a971039b83cdaeca3a94bb62f828400b414ad24ac3c4476af84b485a2902a9e2bb9a49267f74bb9e0040237b9be3f7e2cce19153787a397911079fee3c6982135dc737ca644433061d39e4acca04b4803ad55da84c95ee52cb436cd6285acf49249a47edded6a580e5e46
+S = 3e6a0621cfaa5ff9c896ded65fa0480a86cfd22c7367bb11721b912441eefcc4f43fd6c60bc519c72d2ae3ec7c945b15d0a664b6183224cf08d9a14b3b30fafbf7fa90a582f68fa428fd1cd6c3c76400a4c0a1a256616bcc3494b2d96354ce0e31d6421299cfe56a8764f0ba6f97f77f063c3feb66e0d3bc89d174bd039b239edd553be0c677d7cdd1b1245563453e619c4673f7480bdce096c4a7344e7ed335d284cee291798fba609e16a06133b63891ca9c293dcee039af1fafda36fdce52f10d24bbca8756659bdb1b09297c95561b94362f85898fcb9bd90496ce1ea4b0db316d0057ea12f770d2d61fa5a1ed01f517cb439d7a3cc5a70ff961e9d51231
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = ca89b42f3a534fb6dd079bd8a463b1581c512197f15f94abb26fb0b0d3af3c63f8cc85ed716300fc00b93018e3abca350ee81884b95d9b8f1af1f485747305d250d053f30a8aae89906515ac6764d481eff3ef0fe766c34e33a2eb81dd1a61c65bfee5ec10aea3841575103b3874156745dc6fdf8561561085eb5c4d188e9967
+S = 6c6b9d1a5aa486e6f9b9cc83edf8390bdb1e9086d3600698ad2c56980f249860e73975b51fadfe64f4383f99b545714da25b246b8feee234af16f43f7822fef569851817ad669ac75d311ed82aaf0d31987b885bacab8886e4f53da93fb208d94dd7767172e22ca9d1c9677f1484e21bb71bc6a01c1db8eb95f5b2ecf0624bbfa048141022a781e3959935290fd477d95c2999bd0dc08a92614f7eff0d11cf56afd3ff05646d47a00559238131099532b425fd44830ed2af8677e539a135dfaf8a0f86e9da0bd614a59a22a1c009d303d623fd178d935d9322f9840c9b58494c1e689237f81ceca727b09203b72f750da314c9bc583978c34010e9af7cd0aa5f
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 847c8d5f082149677d5c0816e9ec20bc6e39e5ad1fdb1ce71260b3f4b64aaf12675865924007ed7e3157d47e51d211fc75cb3a8701e4f875fed3b9cd6d65a464dbc2d24536f4bb56dfa3ee390022067120b0d9c6f5f7f2ea79d9425c406c128d08433c4292f09b39b0c6c00fa0e4e661986f2832a21ef28caafcb66ad569e0d6
+S = 6e332aada45368149e434a5fd56aabd1034c2387d662b323c6d00919f90808b75d011a9418f8e876e1142008b2c637c94887cdd6d9341375934efa022cbd372a8573afbc2f221c2b25814de43708b9e3068f685f7a08c422bd65911f4609ee059f9e1e4a6658838192ffeb221d16a5bcb099d37d0032b04fafe84fd4e535153fcc980b4c2e8ce8473ad184191cdece6d8b3d06c88af24e80eabcac5c38ed36bd790d5cac562bb62b92f270d9c269c7f4a38b4db96b661733e5bcc0928184b6bef1b9d96de1dafbde41d481cf683fdf43f41793a54a82cfbfc9e17cf60e7d46d8c7323a1308aa4c1efd53e7ca9b6adce17612ce87872b11165122df1a18a92c5e
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 32c9805889b6208134896c8e74cdd00d3511b4954046514db268c3adad615f894d2a464bde333a804c05b196da2628e3173cbaea0f76f1dabe28dc58cab5627e71b2d524bf48cb5e05da294588e880fb76349de91e235b4b5f65bcef61d8383984aa556b96bf78234952fb26e4de7f5b383f841bd61437a87f698afadc938ac2
+S = 28f10bb4f6f9bf3c5e33bdb9c0f48cf583bda58b2cecf1917ea450f59951da191e8f77a05929efa6c8eb324629a21e9e894ad9a45b48e967c7f2aed3a44bc68200535901ce342d36a2e1a8785c353119975ef38a0064877d3b67a220ac6ced595e1ff351902e065c65ec94238b4d5d18b9b4c146489b1ac2c2cc70c159dfff13d13b05254355af3381499c2b2072e20e6dfcaf3b89f46d0154cce353f4b5b1a51b0586417ef824d00090f9e71ea274a7e12073482f467c6e7d383d9ca027c0fbb51db4e0139227c2f6775132c4c75c9548f0f139c3473be03d35c8f3054b5920aedf7e9e0bd3b0d21d271ab77414b75f3ad11283a47a35a54392464e50053bc8
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = e631de1cbe356af118de8a7808be1c6c6f012bfccff362715dc2c7105884a6429a7bcaf26d98f3379f3f8533d94a7e3b2c50aa37ed271a4cc3a7d2b9feb1c2ff2a70f845e4df13faed8cfbbc7d9bcf79da0d1fd428435cca83bd8c954b2842d0bf98ceddce12b184294d54dc9db9f96fa0c1f1992a4d0f31c68c5e6be8f00ffd
+S = 1d2da7020c7f307dfc97d775ad8d1a218761fb9d55c632398a63ecb2eac7712899362dd8e373226ae0955c8d7a37ae75fe74bf42d8af0e6c4f61a532c1fbb9223b22cf2de1283a7b4f00cf2ee473f79de7b364327e3443dbbf2983312b5df9a2b64b9c8c1ba67b568ca24b37ebf695a1080b2f1c472bb965c3b49fae480486d5ad082b6c649241b9fbd031cc679ea683c446bd131c7060ee77140df1eb4fbc28948ac47f6f500f3d27c4aa76ae50c3ea8ae1f1dbfe8de2df42a93c112994264ba5e6a5c67aca13c485c326fadb4a44d35337916588bc57ec45908b5f27a0d05d8fe5b2fce109fc7e0e2b2eddd936bb4a116aa2ee6fb5ec2f39d476a0973e9add
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 607889b7ba0071c5840960147da438d3ad0e51c754d41190203abd2ea2de8ec30399089af3a68769e3061bd3742295312fb3e29276df9800baa4cf06ef7a326f3d34564ff9284a48d38f6f06512f890c7c3717b3d96ae06f9a7fcf5516c800da77131bdeb2cee1e9bd6e04b4fc113cebfc61973163bc116527936423ff10218e
+S = 5c318b9e83c78bb1a3a26a3e6bbf619ca566ca0fbcffd4b382163c7deada6c095fbe3be8f7501e5b09b8ea4cd70b50d519b7d8572ce60e354d193ed584e499e4fdab6bc66e7c10faa8eb097a11c7c02180afec545a69e78b128441ff1fb3ca59258bd702b34a30e39a31bde69b50eb312f9aac82c8b5013a57edead1c4a8250158639d637b3ecde9c1764bae8177e596e8da98ba9bada550c7a59ea662f12de60dc965c9c08f85bfd179560e65c56394c98a0eb476e405539717ec667a0f29f0a63b57df171a60e76ffce83338d37b1234af79623654f911bf38df146b8efd8ef3e4d9e0303674cdde2be7f7a05ab67c4ff01492ec61c9cabf608070fd4b5542
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 8dc8f2d43a54d5da6080bb26c0d59b2621cf91d4a3e2d4de50bbe804f4c815c22efa1730c8ca1726447adaa3b79d3970dbd9d1005fecfb9b81edffbcdfd484b78a3d4b9e5d691d668d8602468030b460e33753a3f7a35af02bf5d27bf0b0c675c918f6e8a13acfe2622c9bd5c396f63e62718185120fda24765ccb0ccf63c144
+S = 42b530b315fb5507cf9a361b45eb179442992c1e6b3df9c405c44fa8f07f6bdb12c7929f08308e65a1aa4a8ce69c72002144801c1cc50ff1b55418ad24a4c853fbc3faf025f6fb592c768eae48ddbfe1485904c87cdc5a0bc6e27cfd21a5bc482c2455fb32bac168de1104939ce006b3005dc4c99dc6e13a03b3eec838f3a7f4151b470212b45cf946338750554ac3ac553e3c0a746e3c435a05f44639f912177187fbbbab58ec8ae1f5d148d1a3b0f7946876f99b844e17377d62cd4c38e88ba387bcc92a72c855c5b827df8597c38e01d3ecf0ac4b51d5c1f54bc0a6e5a8f5765b6788bdf866e090512a16283dcb689169851d04fec33f890df7dae82ddaa2
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = b75c5176eb13776150b26d43a11b6120219154828312216f07e7bb98e779b6d3f16609cb75d412f66106dac8ab2d9b27ef807f1e5a8eabd5c6d37cc1268a101825c309880ab58d28df5591afd22858e4db5536559ffe9a4c95d04cff67d9f2079b9ad913725ef2de10ca1b5edeb4a03f2d39028f1c09f7bbbb06b1ba700e6388
+S = 83855773c5c8d64c4d84a92b82259da5bc6ad0a6a1cdc001bcda472b41a98841bc85ff46692c9556e51001a0d6566d7e48776166e2ed69ce386d96e544bd498d0f58ec68f1a5739db424b43e1aac84bff459528c0928a04eecd6e199bc568cf376d6abfac1eff0993404ba4a40c8a80cc55d068b6fe5a7709a9b39e60686098f3289623feff411fdf1b333ef66d1b40e44f1041a05a7c53ab88e4a95a78b24ed821f774f748b80cb9f782c8cfd33882347361843723acd1b2366480423dcb953d22ad1a30329e042ae0e9264464a281a51fad7b5466e94c3438cb675bbc5be781511dc512a8c155ed09bb8b6ef66db604618e83e718bfafcd5d882676afc273b
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 6315b1755461ac2790fc33cc32a1e41a6bcc1b8727cdbb01ed1b2be007ec9e19e40298b4bac8ae806f9d8d05ba703dba868da77897b6552f6f767ad873b232aa4a810a91863ec3dc86db53359a772dd76933c2fb904248938c40ba3bdac5206d5c3910f4ffea75a39b5b8f461be03bd9dd6775f85c991b970c22f3f3854cf0c8
+S = 406231681c7ad1cf287f97daa602eca3547eb0e1ad196aa94c833fba93e95dcbe7f6fd71158940d4c1df03d86cb44ce4746c333444c385110dc431c9006140274ab49d66789a87507b025511d166bd9c42f20f62a407cbe473c7da815ff282d5d727898dac2e8ef735e1720dbdffac02e7956ddde13e355211c5922daaff52ab95c40cec6a4b3de46087319dc62354e156834d0b8431026b8607e079714ffeb9397706449900908adb26de948ad1960915b2fe26b47747a7bf034bedfdcb37fc57938c2f40a9de9683e78906da005c305acea3f6c1a186fba5bd36508cf0976d45204c3a2d90bb2f14f7b5d441d372b2e1c65ff9e774f01adc72f392c989d40d
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 4088572485b70f746faf4998c4a7b79057bd4999413196fe6fd17d315db40c1a202ba0afaaf54ec54ab28225729ae6e3bd6f86eb30b031ddc110221b1527e0208e6662138550779bd4e765f69865d045352dde2a9a019995c67595db8aa4d2099121e3779f3150a016373a30be6f3d5fc5df9b7e058b96cf86e91d9a4494ab7d
+S = 27572f4dc4785c626fa30adf0fc67202babb69fa731378e9aa30072fa70c9d5cc54494136d394e57bd380c5503debd0d041030617c9f3cb45915e6037c183699c708f24dc1c34de0b0d3395ec4f7f23d959e2a6536824bb6457e7bfaf9006ae23970b0b5b356204fdec8a134c15dab604edb79f91c9c676500a11c62deab67953d4fc01f633d7c159927ca44da0a41c748cd7871395e60028366e69257adfeb4f079a4f11903d1c46a4387bd29f3c4f2b135bf1f683c2d1dc62761d65c84a0d914bf22a0af025810ea9f75e0a50c6c1df1cc07212df625bc6f4ae70754dbaf7a6a41a46b8c2318260ef098220517b9cbadba89f918c895f52f48bf146aa3e177
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 29bcd97286a17dced9b367f4039f9f977d507790470f1f2521ef748cfe6819abb642c922fbb4eb8b8ece6700b214b9dee26c44c9bf3ae8f14cc9d6935deda3c24de69c67f0885a87c89996c47c7b3e27850ac71c2bc8c6beb038ba55cb872c1d5871fb4a4d63f148f0dd9947471b55f7d0f4ab907302e016b503c8db2e7fdc45
+S = 84183b2f03a27954833e90ccd8ce5dacf6d1b68fbc87862f48b113dd1e50c395ac3c86eeaa0a8b0c6909f47eb798987b24a69b3c1b114652c5fec23584db9dd5eaae0ea8ff9498c6942b7ecb51bb0969710b3a47b9e41380826d54668bc8eaf5da5c46c836689a950630df22adc5eb6f6a3acba79e5c11bef042070ce695ad92e9a45f9c831d237e439d284f7f62d52902a995651c3c0fa8729d7954c937eff7c77d106536b2042e2d6ce7840b1d1e0772b9fa5f23d1450133b11729e1478d20e5fbf1f38a3c95d938bdca362ce947d2aab1b9ecfcd4fc8876434c1bf845e810aeb0b1d9117376f0b93d35084bd435701b70fdfc6930d754a1f7b1e120750e56
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 6259622d0aea50b8a69ee33aae19f7ad84469d7258a91b4249f13467cccda92c5201ff9225b98344931d8ccd4f25000914af19d98bcf691b6f661cdaeff67ec154b4bdd6e3dfef6505515639a554e312dab6fa54c62075fdbea3ebd9aa9432f9af9a22610c059c014261cbe7784baab21d84c74acf4446ce7cd128cec74fcebb
+S = 0bb0c8cf7aa68abe7d1f3f65166bbd110b8d371f859312afed10241fe007a7cb977d01275d512a97d70d9b114b082e61516043b1958ab759bd86e0efc52b13b6c449c3fd4fd122737ad0d51244a83ddc7d4da6f66a6c56fc5e724c264ef627717ca28439ea8fe9b444d56ef096010142e21b910c10d0ad662cbe45b71c550783d0216ded08bb6dc5aa238023d953d7b6eaa5943452561e48dcd340ff41e989f19a76c99f0f3ee2bd1951e5623c9fdd32373982c1da91bab73833516b51107a13b2e8908465d9c1a91d3cdda4f9ccce1db3fa6b6a7ac23eeaa4c95f77ccab558377331420075bf1d1946abe139331a0818aecb32a6cf9e65ba8979bb5627d22c5
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 356a946ad7f0f8997ea518b8e36d19e7f97f253cd1bc6cb5ba3e6971ac336720e7ec43b9d731736b3bd847d586966f798514be6e43452e562af823906aa9f4af9f9da72aae2efc54ef63ae8f92c3f5bd3b6b4ff8f05f8083351ed7007579b4e3a4a44726238e9a3fe46ed24fce9eb29c63ad6041a0b06c2424d80e29954aafa5
+S = a995981fc9e3022e31e8f1e951ff4e1597bb614789a40dec0347f17ce3511df0882b60becadbb34d7ab3ed74f58dc539bbe5910b9060facbdc815859b2f6fe8069b710b1919913bc143081ffeb7af33a50858bcb0e985660f5e9fac4fa9c39afa76e7a57a160f1cf8143cc09d8758109635588469aaf0ef3cfaba3e815b2712e9ec1b6acc0e0c887187414b70fa546df49eb45f4ae9ca1743311b4d4f11d22d3934f1a3a11aa700f7b99b517586ca1d7c1f4e2e44a75a4c1b9c864d9b0a176c7ef08ffd1f4e10c9f9c8efa926605b15dd110a6d6c83b75ea445c07b5756289e69d0daf9478f468ab3de45b1e5151ad7c0afdda46bd55e8cd92c25c8e9e43691a
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = abd35f9e6bd9bc82151b770a8dbbbffb9a37a672f433d4c79e7978b6753e85c10aa71ad0ad8b411bca7bdd4979ffded95023b7c27b3212560fc2c26c9cf0f9be02edbb9085ba9293232f840824424228f486a2c42ef24f29f9e4bf46976566113baf2a261bed16b1c741528fb90b53b02d694fc033faf40602e8598c8f253580
+S = 63271499bfb0661dc5b28e39e19a7c1dd03f740ec9af3babaf739b2650af5eb876665cf7fa2c684eff47dcc1536d4f74040abd27380462886f1d558e92fc8760ae05f99db35705051f9ec765440a43c429d2064c8e51e23fc35432de3f0b5f4b712d2d6f06e0f73e5165df0ef27f5326f88732ed215e291dac2eb511190a8d14a8fff9ba10e69e4d2d3064746b8b8674b75048f54859eca43a62988f003f49ae87d36bf4404fa7cef5d30416f254fb044b420f949fb189dc431f3e43887fad4896956f5e16faeb67264cb02e29b3317abbe9312ec25bd2fa06e84178a39fa541e3510d28f35f90a206ba4734afa349528f2eb24c213699ff9953ff0b5cc7ad6f
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 1fba005c70aace58878615351e7472e6f0939b1f6ddeaa5db354b826ba56ae92ce50580a439bbb5064a2a9bfac4492d5397a9dee7d3af752379b6b72a139346febdb0fdce95394c509a6c5f0876de862e47b922594c00549f76dbb298a5943f05fa44c5bca9a00c05eda934f17b71b98d9dea24d19397949da14d0d2dc7f841b
+S = 248bea977c17b32876452b645309dc7bf989cf60090de1451e9776d09107eaa4c29897ed6c45e74a0042e8d82846e3ea15a3c09c1bd4b9a7c0a482ccfac324aeab4e209ac3738801084b8706f603413bbf5bf7fc10aeaf2f690792a27e47462f842a2213bdd46e2f006489d6f7f030daf32b0bab6f7c15854ab95870620b289a170ad4d8922b263f82e47e4f06c51af2b021eaf0448a7b3ecb731ea94a0822945868229b8e2a1981d81aac6315b2de197e2963f349ba5cea98147eecb3a8673250366038b5b73b2c43f589e08bad52ea817ab7e5c888e4dc41dd484b3d7439f53657749c5f12fd443ff863c11dbb9ac11aa0f475da16d76918affa68452a0732
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 73228209ad875ca1b92e458b47d68f24594f5e4e52395d5b500eaf2ebc63299c206abe1838bc3a904b553492bbe03db3dc365e310221c2d7de65af210a01bba1e2b23ca196b9000a7dde3e85acb5cddfc82094b218154242dea13fa5e82de2276201e4ecee0614d7f7d04dab41dba570c515e819bd9d4563fbcb46007e7006f5
+S = 96db5837e5644d02af09f74a91e12d9aec84f68e7c2f5b3228ec17e00ee25806ccf7f705b5c82166d8a043c8a4110fd289210a559e93b8ad9839bcbf18a3a79767d3617729d8c318d7e2019a330d7816a8e6cd637819aa7ace36df615853ff90253cad34d7b8aeaf86208e6154c8c691632982096d380631693dcae3492eaa6ff8ffc3454f3602bca6ec93cf3d56d338b7f1ae45d9afd12d1c0338fa73694a61c3c2b019bf444cdea8eac94245b089cf9caa8aa6fae776d43941a143532fde33348818b620bc1bea4e791909d7b64f44474a0c1c20c9ef4d0c467d4f9371927e2c8d2bba4cd8618fccf5f91bbba1336ce49b2f5de13b8f4d792d70a070b306ff
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 09d1932d2a8376d487b833ca5f43a09ed741b379414eebf79df9eb356075692c7591463d82e9fe0c6c5e43921dc5e56e85dcf57cde822aa93527830626812e1be780a97d888527a378cf35f54c359d26bc1b8bc4ee9fee0df8132105a0b0cbc565880416c4bdb93eb4f1511a73fd906d84e6bc78f90dffcbeea50d5a566a06d3
+S = 78248f02a777283a462dc6fcf94d7f0b0c4e6f10622af034f38f326469e0ad1bd8efc22bb441f9e7a8cda25c851a7aa6d690819cc6ff163fa3c0ebd583392256621a21dc8bbc193060b51eb194f8295438b10f0bf774f2eb48d030b6b6206cbe791698e89c71da2ba3c05b78996709904b3288fc6e2d5bb5929eab74e9b028092b45dd4acf11edfdf49aa8259c9a639868b70f0273c69991ca088855b3d1c7fb534d54bf8e507a33966b0185b0bd5204592515fd402da922ba68a6834e4b7176df5eb3114efa32dc5d328480b2cd0c018c783be87b267ff2c595a0392a6d920b023c21620aa58ebae4b0cff347ddf08418189cd16047a80dca087c8e0abe2907
+SaltVal = 00
+
+
+[mod = 3072]
+
+n = a9d6499f2f8bd5c848194a6b444ea48700b13a1988753cbd187d6e5ad8b99347a27a0f0c3bdc038e74b8dab1a958fb1988377de00e4a1c8b9fde61df9cbf6c6df20c57d1ebb99988208784cb2ccf067e4c1bd269f74d8b897896aaf7e4901b7861143440f054c7f53f0e3a29248677d707e4624e4e2c5d075b98bf0a18be780905a1588aa3440ce2d5760ecc767b1c43cbd00924428478923fbe6f4602fce36184d21fb895b04e6a8cde5f0b8798110cb0497155be5336b9fbc0529ab9980c85ba0edcb4af2dbc7cd268b2f699d15f2a7e91510fd782c581672dfc1d1ca8e798f70ee56080db77470118cfc398efa728471e5c4ffdadddfb3232251e1bf61e295acf80d874ccc2ec052ac1806276f98eaf25d2f9156853ea3f27a3f0ad6b9cff46b0deed82fd9f5175b6f845768b45881fb5e584129033161232a4da5375a719729c8f427390c2859997a5ac21bfc7c4cb3c433d29265a19399868a8c16744bbb5e44350c8b2b3acf766966ee04e91db3b564081d7b456d9d78d46ac438577bb
+
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fdecf
+d = 18402aa33d47f27bd0a21ff764132aa93da95e75e6d5fcd038b0bc89c94ca0fc65ff7d4145d50dec72d0a6d4a2ab331b5cdef5977db2251bd3ab0da528193f5c47afd4432525d075866c1543489a925352d97e91af471bb918176f9f4c6ff91d98560b073df25ccb850fb6bf6a1cfebb895e11e500f51cd55e3ff85203e753be3797fadba4e710ac1838fc1917ac12b4a8d01acf9d9fb1092f95ea861288ca4b618793754d2ecbec3d165e08133bf61e12ce799d5757811cc9fe1b2e63c9fd19b4f11390f8dcdc85667239cb77627e9307054a65a2dcd5411ea468adc6602eb9e71892c4a32fa1f353dd3c9559d2bf2f5f3731045745879e1b5a4de46c5aea1380016823eb48e4e2e0f5845407f03c2c34ec6cd09604d87c36f31c2f09b194f77ac27b56dce1bc582c55c439897876f49e8da0f6f15fd355e05e2254cc67c34671182622424dac86f680f08eb326a146e494d127168c4ff0b223c12cf761cf1ad2ed6cc5def7ff28b912b8a2cd313083950284bd7170839a4828f672ef22efdf
+
+SHAAlg = SHA512224
+Msg = c642a5a32850266844f96a1800a11c42fe728f80c1f0ffab11d41a4ba017be51ed4d050969347f4ad98dbef0fb2a188b6c49a859c920967214b998435a00b93d931b5acecaf976917e2e2ac247fe74f4bdb73b0695458f530d0033298bc8587d8054acdc93c793a5fc84b4762d44b8e4b8664e6f6d8673b4c250f0e579962477
+S = 341bec7948589d9deb40c0a65d17864229a7d221243883d1b10aff74181ff0a07db7d74e0b99203e668cacbb89b184e7e613e1129f6b61f7487beba7f1a9d5db81457c8c6269f2fc35972554dea977a73b42e6e9ed880bae8c66190bdf8937f1084a15c2a14f78784836ff566dd83533147c85773a10324a39d19e91abdc172542aa24b92ee09bb72d3ffb446ebd9ff61503e9629f09af6bd0903d484a6d8fef4b85759c932b67ac36bf65a691d42ef422e3e350e5779fa8e717641d8181a2543f7cb8162d41812b5560b8e178086666bdc7f9d3797959731718e8c9808967ca61d1657f07a28e523caef586c1894f66482b4d2f7c31a5247f0cbc4587b3c1aeeb9b32cc9f5d9907c47067a69aa0e1ba174c46ac15c1687f12287899413ab549f48a590c50a69bcab9498b0e48e220d5137efb4fbcf8b511ba9c20d8c5ebbe41459375956236bc87b208c10df1caa3f5ec349185bf4e89b6edddb6467056e197679390598abf8ef0ab98a5f2ecb6361cb895c6b9fd0ebf28eea48ffc5f2ae034
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 0de36b28a6f8ce5e2b3cce3560ad862b5c5bd37ef61263f07b390fc7a2fa6b19c1a49b46404d68c64ebb9325d485684ba7759701023140b1331a4d6d94750433bdc9dc70f88790c2f6f07302c0340382efd7c09320593f4ba3167a85736b6a286b1ad8adb6f070db88a517d50b037e579d4af73d38d4884531f53e152625c480
+S = 9f4647d2c195b9d468bcfef71577ce312ea4249f9f97cbe11b45951b55d0f7a3ec7911a6a82b3b365c8b63b9567b8180a434d652ccb9397002e9016ca4e4565b60e960a5bfe5f861627879a2864cb4f27b377fe3b42540fb71a4b385e69f089bfa3da3eae608329a533bfd8822a0c2e33c9d4372ee0fa6b72820cfe700e68f7cd3c30ea5380269384fb01628d83a56452fd94cae62a17294dc42dd25fc83250e0f90e1c0693d7e95270c220cc206d68ce8f01127b9be0f05fe51f2dc1191887367c880bda23bf815b980074a4427e9bb587b771dc782eebb805cb5d3cbce4b4e0fde6f79f4770e911aaa7fd07b5a2d52ea1b7a2258d1dbdeb5b59915a55e859657604d4367d68a20d8c6fb2f26ce98b4e8695b9da0ed2473aecf6a118e5781bcb189542b77705a37155cdde702fbaa04ee8bb687c3995c0bf7e3a350c0acba2862e6b41d7edff4747d0d52e7645f3731ac4fbe32ca97ab76956190314ad86c83f04feb36e1ad5f73fa1fc291ecca8458d725d61ad0e0203292e3c08753b09ea6
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 15984a7560c9bc4d8e5deb3e807cee541d42022ba5c27b10424b0163e1eaf83f3f2f405e47341f369bdc7b6871594d5ba0f15224fa0104aadd42c807054b6931a457c5d9b549c6938ded9438b3810988f1746614ab6d445c708fcd34cffc2b6c6c9741af530f99ac8b199e74effc0c233953a4c3600e246d24bb76b1e6042839
+S = 47f0f2e59c57d1368d8f7af9fbd9a276ba5664b7cceed05453af3a19e39221753a483afbb69b0ad2c3cb9eeba8a89b15fab2176c4d6f23d49901e755b26bcaa023a2d204ec3f9b1b86e884f915206e9700f1e3440c72ee82ef9cc9586e614bfcffe5f1ce5c1e88ca395dffe17092661763dd1f59342e85da7164877f34435549cc2f46beae3bda75cad2bb6245d95a78f42c35543df768fedc82c0c3eba0f8c9f0a9c9c49acf0659bb31c15e48f5210b40c2c908a7d16b741149f7a99ab662fb93ff03d2e1d1a9c747431a3bde0fc6bda2ca97ff0702c566a802850193f6015541b192d025fb4a066ac86fc3fac60dc126c8aab7407f96c57a9036f8c87101804f63d533bc27030108e9d818a0e781fccf84b1843491d2014d80e504499ffcc9652fae595536eeab6025e4349afbbbc39d98ef3651f9e396e440e10720d0088ddac25aa74c9678daa7009b27831455d724b92a7f385e30ce01348df8953757574d75db554253d6f0a98f44b6e1545bac6ba2ea9089ef53d50e74bf660f31a579
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 6ecef36b3e3f3eeec7b2fcafd5d3fad44a0cc643c09f715a6ff294e15129913c85fa1be5f2bdf91a2cc306d39be97df7da6d73cf5d00a5bb571c7424da972eb140798fbecb0b880a88303eaf79f85658f27370ae44c3f113997506931f12e61769f057dc124e7324a3a0ac2cb6280e5d5cc6c4c6bd11decafea6511668c13fd7
+S = 8dfb3af8566d416b0651852316ca2dbf80b4eedb88bbee9c616760cfea3b6460877d7e63d745c634b3c775498148566ab5c71c69bd476dc2d5db0b5914e1d649ee7648a0dcedcb0132616a696cb665bb872792f1e2e7880ce29ef4226de033b84c0a518a6b1805dbe164ff176fd252e8d784f4696967f444e585e087a1e694a123f0d7e10b1e5ad4894d9ee43107f32665be9ce11ebfb4b722f9e2c6b151a8dd8695156ee1e98f228556c8dc47dfe029ec22fb5c4cf96d8c4c190de823509f57a9674578d705e35d9423449e0519f056a04c47eaa042204d064dff84bf0c6f7e77478c93c4fa2a17fa617b51db9b3ef021501cedce2948119b015200e3f79dec13ebf5d872a9c24f4388e6fea5930e0fce2353543c5de84299d7cb30c7b92bca46a75e5f1d589cc6cf9012ba8754bc288127ca7a47338c2479b560ba66be39333888a3fb408fa6bffa87ae363c2b8dd17ee8091add784cac3d84f7ef9d31829b2bfb9f960918e8a9a703635f2b817dd4d33e34af595460f25d20952513390a4d
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 9d3851f81c9bcdd9bf1b49abb051cdedc3ce75d79eb0ba911d73f2a2f5091aab972cd45557f3ac88cda39fde7bc8de57b185cf4eae2955ab0802515b4e7669fdeb4f08de4d57a52847254956b4364beb5e405e641ec2cf6b44e0074d386e57ae624bf57c48f04121f6484dfda3c39d1391a62b0235a5ae3898b31c62fd196e26
+S = 8ad5a0410d3321c6db10825bb6cb6aff9b535ece860e234af1a765598deba1a3c0f9bcae8026d15fcdefa062465e24262f06444a0a3507742c867d35ea39df96d791970b2feed352987c70c138c7ec51555a6c74f86c7f2289881e10f1e97621397b1ff9664720f9d86ebe6baa42e0fadcacdaaaf72e0973e1d7f282818629697b2fc1bf513e52542ed79d9df500488582ca5bb27811a1f5cc22e9387ff1eb37e09cca5eca7599a17117cc58a5ed1cfb1cd09843a0ab617cdcaafb7657b166a6e2fc994506d728f1b4092fdd6c413922c4224ca9cf13bfde332f26659f93dfae176eeea066a4c5ab6f839c109a227f57b1bdbc7c282d4e683974bfd07184dde9af2ad9e0d5480c18680200cc7a4796188c970ded598610069709b7e57986087c583e46e19469956de5b7a2ec55d800db0483581cf1adface34db109fc1a32b2700a55722a920527511b3afcbe5205ae167f592b5e825770fd412f4c80a76fcaa18f49356dd9512a784350cd312b0b978234c178fa6db7523622fdec936b6ea65
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = d2d812b3558e77320d0a5ac5e028764a08cc74d517d10f4739427622bacdf19bc874c8f1798661fe10cea80c7c0ab3e9219fa73edb8ad51c409a29d826dcc5196657e92fdffa16a6bdd3731bfb826f4f26eca87a64340ce2b6e73dab7a763af134ea3d148dd3df539c81829d6577f0a39f1d4032bbb5fac021907b45bd829a4c
+S = 0c928fde1ba0d751a3416a9945a6d2d92348dcbded370d44ea2fd798d3909d616111cd7d7c1d53d213b94ff485a2c83a61eac10cfa52f5502d077b16b845c7d647fed022bca6ac5662ca71c9c7556750ee421cf3ca83c09227c95739cc1b9b2bd2d04ba65743b719aec6316f8d2a03b0bf09b79c56fa6c78180fb404253fb351945a3967303056a5d9d40640ae3d9089b894415a13dd525b9e68a0c431b0e2d97d99d88b20c63e8b44aff02b6ee7d6e919633e9b66f7cd4767993617ec29dd27714c10aa24fada7fdd3ca4c1f7eeef473e2426d59925337b1c0bcc5a408127c379cf0e5a3b003b15eebab349f1fa1744c0890cdc826bb498eda3d8f595f3b4d068e0c1670fd96e1d4ebec885322defa6ae3cf58501e9a23446004ac7301cfd239807fb03796dd5e07ab33f64bcadf2a51b41daac5e7030b3507b819627d67309ba591361a414964e109e98ccf9aa12b4f855c9f248d9c3546ba5553bd2fc355125375ed8ee5cd75ad32d44fcb58584670b397e8d7797fef0e0cb6968be1532a3
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 80a5889f08f13fe823fc42b0939ae58fdd448de4376bb8c7a70c3d3f6a85d4b593a7d8a9f40c4ca441aa1d6e73a9a6806b7279bcd8095d5c5a9c9329e85c5eed6f8bc22abbd68b0c9be6919d40323b38e7174240b82ab711edcd48373600bfdf5c7acb8a25f9030979d628a5c2dcaa9e995a6ed79e77cfcfa7c6e3d31e1aff72
+S = 0aa0c1be7e36c187a5cd2c0720fe266794df19bee8623dd1291717396abaa02093ca436b76f9cb335b70a19e7712714312eba39c60eecd78748a7cec932f7dbf10daeb18160bd5926e6c5dbcb3e74111521d637f460b6f44b1a3df562f0c93d0fae165fd2e48c03251c95983fa1e6ab61249dafa206cd476cb7fbf672e7084bb358c221b2e94ee268e41b96d32a83a481aba41560e81ffd2e6a3087d88b0e3433255217370b7be41299b0888ea570b74c3cd063c0f02bfcb6ebf77ed4221cfc4d7d3909b7bc087c7a5f0787cfe3dea8f84106488261af265243eb395219acee63011a11d49027703e8a7c11f397925ef0812611be315d209c3138e32238c3755a2021b28706f33f2f8f3f03df24790f013dbccff8455e38e460555818d44f3c400e3105a6464e3955df9f9435bb6b34dbb18ad3477831b45ca84be381f52c2699932e0d9e51fe043be5246d66f6e27892a42fe9d91a258de9da71e0b059e4a34ee683c363f09ce14881d8d34facb67499f0c4e6d98442bb1996f8c4df939a592
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = ee436b6a38d986c178896a803f6e5146bdc518ccd8acf3c7802a60103c705902095ece2365495207a7fc157291fc12bd2811897bc301b05c639fa6514204a8f0af1d871b186659dc69f46f9495b988557104448cc947dce3ae1d0f650d8b60e386867e977ab60408667a622d702c1bd540a632471105de2508ad8596c48de8a3
+S = 37773bb5e8fd6f59b29cd58b5aa6ae9a94b9a317ee96d045ae5450dfea51b0dfef5f82d364349769bcafb987186a163a4091b4d4caae5a961afdfad05e0ede656c10f2914e20b73865e6809b081410b539ee7b0c077803c27e315bb3dc6c40fd05409f306a2d6a6600f6051d974a108d96c54c8dfa33a346799209beedc46842579cd9d668cb809b7c305e8941709ab005cdfeaadf4df17eba04b9f976546a83ae155c66c7f391b5f978509e515356c925df1d41f56db3d4f980ad8dd86408460b772d5ef8fe9b634aa092664085fe750debfe7863052db8124eb8deeb9f2bf4f5f78648c327925bab1cf8e62405b6f38ee85271e5575d42fd0c4f0c9cd0caf8ca22393f8209fbb692731fb2f5e8b0051149651efc83e8ae1a7c979611c0254fce70b78ad81bd4ff8a8988478492e07e12a80c020a42684e57f5c0d55790eaef9756b7f8e4504bf577909eea870a0b2d859f4dac1e2784f3eabaabde6534dc13c23ca3fb4e2ddbef9afd1dee1fbac74470d23ea8ea51b6191cd160f157070c91
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = a0f16e1a5ea9b152f46a250fb197b26adab0e8829f7794c44e519169c7eee13f302cfcadea3968f1c3f88aad6da7bca22fbea0bbda1ab34dff5a259d5f8ae8a3a3ff070d4d813987efb0b63a9aa049929ac7a6456019ff91c071d2c55d330502612f344371c94a9be0574ebe22cb80c38492a5281bbc9f17fa5c40e7a83260e6
+S = 32d142de909db1cc8aa6bc7648c3dbe15cf37c51c5c68b68e631eeca93cb59c3cb063f70ad68bd5c48341fa36d8050ce0d05c691d21b91ee172dd201bd7fdb12e4938e16488990d9fd73efd1223d2502a55c7444e03ab5acca23be2a8ba0af2b3e2281f08de6eee5dd6c3b7a9e6cb94b1e9c5a0eec16b3aefb4f19656d36a555f299811df683107fa7d23834e2aa2fc33a72b7b9a1a8a46ceebd51304fac650e3364c7852b5a339c14be424de63d879b3e5baa97d25a83089cec27963f15ed05dd01aa670b22e12f33c692e3944e60e7d2760e34f05c52de4b983977bf54cfc20a953f631917556609d9f1ad99822c3f522aa9559976ce43cd299cb2fc36e3ac4a462ad2fdd18e30f69b284e720ab073eabeaf3a8b703f1626f722711fb607a0bfdbc282acedb642d780db89de0b01436d41cf48680dd9da79620e2dc862e6fb89d6afa6d9446c8c203d239f888e2cae4c080487f7bc8e290c4cbf283f1b6605d3f3d97b1d725357631b729e0cb01ac1df37a773d0ed6c41143cd8d90d325a7d
+SaltVal = 00
+
+
+SHAAlg = SHA512224
+Msg = 947fca2fdd2e5fd21080e50c45804dd61b9a6697f4feafa362456a01dc57f171b68c4dad501105f08d8e34b58605dec180fe84631ce1f6fbcea369b990a4c9a7d8d851eac7265845a30d6ede878da745594537b2fdd93f8ec896e7353859adfbe2acfd6dab3301d93b47ba10afe0506a8eb8a60bffad326539670cfe3a3c4473
+S = 4a9bf3cd69369cebe2346d866aa502765983d52221a26b33528c97fb8b3e33bc8386619012f3eb0c21326798f63be2969fdb853cc19fa1788649be7b59445f5fa8118f5228080d3e80f5e71405b7ecf0f12ad153fec738ddf8196ed174a3d066297d90f0224eeae935af243b04ff39172d61609ce6d46c8490478c5b2240b85830c2e8e4d4c18188277fe9b8318260d7463845f86ef172fb607eaf3ab65eb871016269242ec4de6700e163f3711c237c07ee181477ea6d8e5f01c1519fb4f4bf18b68b58e0e849895b85eadd1ad9c8f5a59c1e6161f23fc1274fd428dd2c446a5764d7163e3852d742c7fd599fd71a47a87bb52b1ce2180b9f028fc0104847b8f6fa8428a4b5830415e58d7ccc5f5d0316d9af988b75bb81814ce47591247ab6f392d7b79f0842664bb7a666dc376461a92c74abbc72925685bf4de29def70890c8127445cf1820060e6378fb9aafb32ac4e4573f0c7cfeb8b1d2abf27e77aacb06fc96deaaac3d42ed91e23b3d187a36e1355df5b7340db434d0ecab713df08
+SaltVal = 00
+
+SHAAlg = SHA512256
+Msg = dede9344f021a6bfaab1f31a1156bae87cd631d9ec0477de9bf9c98dd8a2f8c8117b1a99329980612eeee932dac9f579029cdde0b7026072e60001002f8b6fc4f34b4545af9ff37a89e1fc3229eb63b4cada5fa2911256231d8209405f290d8facd87a0f103ae754e61395e4a5c5eae0fd1821e7233a413769054b151181b870
+S = 552e173156b6a9fad3e7a696b0aebf594d2c4c8cfea3b3d5cc16398b1c88d4257faa9398bbf1bd96cde845411e4b0e46f062b0cb6d02300246b6788c50300a399f5f55c89ed1a7d5f7ce95c0e1b4446f0bb11c3fedf79cad0ecadac9b3304ec734ebaf63588a7701355aa715d16ed9e2a3b338abd5a96b12bd3a7a28555440e1d22e010350fa329dab5d08aaa53c23f344962cc71d6a00593344d16b6b8d92e41fb68dc3fe321374a17146c1b1d33d434725f9c9716d3afc0cc0fcca755725b95931e9539282271423fb329bcd482c8388b8b79c6a24593586616a7380d5fa7ccba2dee30151ac8ef92150459c630c05ea15ec907964bdde7167a6c6491facacd8e7bcae2e564612e2bcaba4459f10c1cd6e5c608774165d2ff11752a88e1e2394f8750229ecc82173d7aa57e6f8a4b20b7e9f676dbef75229c281468d7c1a3c0be1a71987161bc469140f9c224d67e01ece5da69f09f0ec282500ddd351806791f4b363c35920f00e02c2fd49bda9ff7d5111d38d1aacbc3f795cfc2679148c
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = ed654056cf27081d61fa37d5a91b2940e7194001cb38c417e613eea55f863ff4e7cb16baeee3829d173855f3ea807acccae48832266296aff370521059e24d69ac0d99599f2d968fb404098df7c46eacec2f9061c6fd56bed97ee03c5280d2b72673f0ba48cbecfd1fa67b2c37afaeea3742801613d1ac4d8286c1b0b32977e7
+S = 2694ab79aa110de26e5bb0c5738280c13e4c4075d850f7bc249076f1b4bef6d189cd55c1207d77915ca19513f110a7dfa2e595f6a840fe45a996ac8ff2fae2aeda666ede3148df4cf4112725ea4c638b7393e52ae1e8c756cd139ebad9f69b7a5e2d6ef65dd06248b06669fd4a90cf6a6f957fc6923e1bd2cafe73a798f7473eb25c153a5d003002e036782e41ae7c3a9c2176ee59e9c3b4957d6f7dcadbf3a033da5ff4cd980f638ce0b49bd0ec1468511a91d31ab25978282058426874aa5e4a3228a6758962280340db921cd727137545cdff946d39db072183770edc815eda2dea83667f1a426cd1510419703078faac7dd6a593789c95ae8c206510fd5a653c58d2e158d6b3a4d50444679583f8009217c72a076f78da6074a7758be3d894f7fb0cd6054df29af04acc53df1c6f6af544e363698da5c72af039f2fd52f51eee27051bacaeafedd56b433ae144e52203b838d0a550aac92f1d7640f7e27c0b07e4421f4b2e87674c1c94c4028886032836c3f9d4fc573a62301b3e938e68
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 78a462d13bced2fa9b5f4b5096b0d09a6c54b9a150fa06356495f470e4bbce3fa14b061db253842266313e3d7df809be9715ae17ec3241e33e5aae270c5e95d80978589ecc2f72d8c97a0ae08028c790f47fe7055f248ba2243b555805ce3525967380dbf1294323ac84d6c1080ab41a6bdc89f311998d7bfe7f118c37d3572e
+S = 6cde4917f5580de2a552238f2a866f34dba7817ccb913cf83e7b1fdb24f9768afb88d372a06fb01f1b904819e2c612d0d4b7dbb07484deb12a5135cdb7bacb79ca29aca60d3d5be245844efc15bb3d8fefb07f5e34b87c7bff61e5f68b71b55f5e7c41f88305100a3326e6dede69e8f9f5ed98de0fe5b3da716511188b4915c5e17b876d4e69c080da9ac3890499f9fb0c3af999a0f53f751c19736a17753e3de0e4bf597302f717424ccd628de245dd2f58dea65cf8ba70291f9ead1d11e68a83518ac9f43fd95eb308083ca5b1a9c750dd71a24e6604b752157eaa4ec12bde9cd10e5e6d2fe74bcef128059d260c9d3e43500099aa9df1bd1fc351878efb7d5e9096af9a453328a2bc4aa4d6cd95f16769bc5a639bfc3429a1ee3424680c74f558e0e716f18961e49b6f818f5ef2fb91b665835f703d3354aa3af41dd219b30162e58acdd0c42991d5929fcba63901681128bf10367df4caabdd3f788c3284d45b15f09a12031c2d79e3df43ff9c0c844332a458295417c9d1b5920b2b8c11
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 0bffa55ea33452b4cb7e729d75952abe7f73e0ed35c0e847188e607cde46586eb9e237fbdc5d59163c68fd1d935f5f66ab7b211cd949ef49c75b6333773d26ec85aa5925ad0033438cf2ebb5ab7dd884b91dd72b1840edaa9cfb2dd68ffcdcf3f8c0d4841c0626624683030cc4d7dd3e32c0c9c5fb8d28911cd6860c2b6bc2aa
+S = 090aedc468b0fbc38c4dbdab04a683f174c6896b0d1063f87adc78f2152aa4e74b728e370aa9e766a4ee80b569a8abf9cd9891f68832f8e6f05561dc8ae111ead42be07e10bbcf5430e062fb6b49ab61e7cf3cd9c58ec79094e1db324903df577b509e9b29a5f95d8a7ef2b252ad7f48d16c08fa273e389738c457b36651097a859329d04be44d529bf75c41d1d14562537ecf3e919221e22a05fd9d2c9d775793f4d69614c8f9e8bbeaf7faa75f046a1ede659f15674fd2c89de67c64f99d2c29715a188932831beaa73e93273a17730067289c161a9c217b5a60c6c38473a4e2c2b62f93fcc99963a8dffdcb7ff0d36fb03d913e72e024b22e2f1c87d79c3801dfef2b5c17e0b3189db14100f7c31eee6dd92454adebef3237a6f50f1c5966ba4e44a012afd4c98f171009b31daee4ab671ae8b669e71d65e7c79181c7d31079766f578c923293405472a6fbbb121355260394e890697bf2f39f552cd5bcafb0670661dd31b531843a89e5566845873c6d05acec03ce1aeafd0e2b4fe8af97
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 48031877336bb181d872f7dd7c9d6ecdeadd556965b433e8e299b21b749eb03a085094e352dede60077e03294d0d77a970f50b45d654799b355b3d0703f4a76c2ea72f310ebe088998a7f8f8d49b6613917db5875705d05c9d1d067b3c8b196e24d191684d515685f1b57e52f98e6490b53bfa35cf0d60b482a9b57e07ad2dc9
+S = 8e1e2ecd1b9b955fef52b996b25a20aa00c0bce4d6cbf8d2d3d9e6711411fa6b89a950a8168c43676050aa9a1d09461cb286891082e34aeb1693ba10bffc8669128009a480eb79b51ce708f31f31559d2111c3df4a1096cd8d3002ba24a4be18443f260d1c31ce4850b767fde5820645fdf1b6768c1c4edfe4c743ecaa656c4f26cd81a10df845bc7f109b7aba8b2b9ddf67eef88b3e715cfca8368c85c80949338007aebab6b821308e2bc5a1edbda48408f9a214d8694913da474135bb9a3e1ad6f9dfc30c78338b43f503ce62977bd34bea7eb3da52627c508db66ba80c02ea8c6082cfc0f06b2f47532f79f7364cce2ca80e24e65ad63620d1beb58ddf9ec940cc7896465f986a6bd5688ecb1099604f41f964722cc8aecbb31295b8ea02d7e71c4650183456c6d5f1a4dbb0e46407cce598174f5f42358d1948fdf5723b66839c35730c66b9beb04affedbd0624ebdea47e3f27f1ac7da98fa19a5210eb97961c6165c2f133651b74f6e6309bac135073034f0af5c3db8953b021c32de0
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 7d462b2bd2ddec9aae0c50d9ee912f304c8f3276d331e5d497900dcba2d73b7831a5a11721b225c7a4b6b48c3886d99ada808ed1762a5284a3167b7e8d09ce47325b4da3d2a1505ca08ad741be071f6f68af73cf706145e0ea2b7db7286a1144e933d6d6cdf296e10c516200685c293660e28a79a71ee771d496bb7d5b442df7
+S = 2845dae6c700ae0b12b4ee09387f532c1df75e4d4d6b8ec2baacfa66d5baac53257b09b090587e0b8e524c366c3b330f668a7b3229f7b16776a598b48e9018c04f074b75abd30d016af665d9f8a8fbf81fede76c3102cf15de174ab69d8160bb28637b257636e7ea69bee46c128afc57bf2c8d1fd639e01d049997c90d286d75f82121ab51fa9d92951724d32725e559961de1345fac18dafc9b472e235dd32bbcda8dd544ff01338189dc191d69141a79b39b7edb56adb48cbdb2e370a0425beb78cfa980e30b92daddabd9e10dac6f13ab0d5a29cabba60d5d637ac9c6abfaeded5672941761d3eeec3763951823b86b4df20838f7170cfe509deff4b1597c5fe3785df0a0a62d70e7fb75f183f6f73a134b4d89004a559edba910157068157e29e25b10c18aa37d1569a484387218712c847a8aad93023fe00cdc71e55aab46ea371bc52fc0496139cf30c7a53e6cf043ef0b9aea086efdba8fd2cbd15c6b82493cae581500040821ccceebbe51de2a2b356006afacb90cbd39f3cee7c99a
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 8ea2309acbdbf827b4af0a7f418741e147392587a474bc2abc5ea3c92a7b5ca7afd1ea936e4a9b6b5c5926e3f2e0f5832552c4ef97156b6b0f2af89e270f019644e4390dcbce40eb9299c00c95a1b542ebf20c9ef8ae70ebe3af617c4a6e862835234492492e8fae3fb60080949028278162251b2d0872b3223604eafd5f9262
+S = 3f5094a438d4bcdd51b54860f3d0e74f87350a0b230b125a7d7ba6c7782f5a38841a3c4dc89e2c51262f355661517184803f0324c83f54453bc3852348cea3683e48013222261bf28c5e1ed47c4f63f1bff0998f7551f71e427c5aca89e8b6558f802a7bfefdaa9c2834a08535d4b8ffc8734fd7d3e3eb903b50a96ba79eec6d114deb6e8cb1a3d301edb343b1f280fb1d6619f5aa980ab98c7fbe423854715226dfa87d2a065b0f77df1d3cc0f724af3764f1dd27dcc763c856c8b2ba64820fec6b8e3e837f31115aa36de077a54c3eb3d91b9bd162468a9036332cadbd295574fa57608ce24161d17a6421dc7425cd31f610fa4835d120a225fc0cba537b96ee5c03b135b62fe14fc95e10dea7a277cbeea8ce3364f284c691573e05fcb58f64b96634d9b49d13a9b271770e521abf4f6b67240a47f76a5cb30ddf33cfd6b0b608509e83b06f3166a8b544979520b5d7ffdcdd9520ea92a2437f33631c82d10ad722da93d16e873e5a279a77edf90924db213067ec94332c447e56b4c86a28
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 81dd6c87d05cef3d2ff53f42830ff45ccbb9af3a47425ba9e003b20bc480030451b03376349803b0d21f90e2e71d20d46cb51bd8bfe558fefe5b9a86b38a5b9bb7fec83e50ec0c809d0ed1f434ad04640900d9c392b4106328cc7668b1abae7d7c6f31c56c819414596a0a60b3e929726842f1e108d80a4128fe4d98040b8611
+S = 5be4d75ed981159652b7794287be96d502cf7705618f590ae7209b7e43df10276009014eb0b101f1aa216af8ed4bd3406e0c98bcca7642324e4727d501d50d8d7e4aa071711bf387ec926eeff74d985078560157f05f4f95c4ae0e1f2adc512f076ae1920a3c197e928c591b7bf3376f0d854ee7c243f08dbb8451ae2547d8f1fcc7f776541f8a98a8d93c50096ae44b366e2a0ac1f8747871676a742f14fea1de0bf2c2857c7d3911b9a5166a3122941d0df4ad80a091fbcc1a700bf381d59a25b0546b2e24c702e33e0216d0c2b800409f84797040373e1f61e0ba73e1c6bbec397dfbca4ce399fef9f48064eca462c3fb0a01c47644e07b43bccf077ba2f0c30be391805f09180c6d996c41ef79bfa2f6ea8fc39db007cf122ec29746f9b4a322a62ac22d5216c77682801921324e72d542a8ab8b6e624da5156e2ace2d7cbcf09200056657369797d1c194b08ee073e7b3b302321611f8706f82924b5c6f5a5a3bc6e1fcfc381555a0350cba6152bda463313ed0f6353e99f05125141236
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = ef2d179cb22c7b89dd1c9f86f007b01630b0bb27a981cda074c559393617d98fe91ab878df6b709303d4f02463c3401febfa678373878de9fdf75d5d37c7ad6c481b617ec8b28c67101ad938b5202a5b4f8b7edf7f0a1810306ade4b1c0cff109297d85977ea192a8c55236aee08b5f1e3cbc8e2d3f0b73b9586a3aaedd016a3
+S = 131d2cdb1a5ef38ad4ed19ebca4b8cc14533bbde7039c957c026c6ccd82a6d1d6088949a88dde506b94fe8cf679a352ba505b982ba9e6c91cecc62c3da3592ac39505ef43e77feedc2b1e4b749a37d56e8fa55b6b579927248bf6a669d61be6923db46062a97ade441a0c43a68cbcec4dbd440a08ee9355aade4327eb18a4fca6bf73b23a557a27074a588e704d9687a1a66d2be3b9851d9fb7869228213e39a6173d60b3f5f2ddeb3fb6bf8ec85dfcfc6685eda41390ea8f8390f9336b181c39e779b930bc93c2867414a4382f47ecd713531425b9fe6ee1573827cde76c01e34d5918d8754a37777fab7d63111970ab806caf53cae6976a1d8409ffb47309d651bb22ab90d474c52bb42367e6a44cee2fb76d2e61b9b2f1fa31e1673f68c8affb551990d5e2ba369b4614cefda05bf21209c44b4033d754b43a8a5585274b6cd198e99b2a17f69c57fe283f3a8f573e7bb92348973acab578a56f4d0a742442c3cbcc323ace0b1605834add2b8d759537c8b773a60f175d7bef555dd15fd08
+SaltVal = 00
+
+
+SHAAlg = SHA512256
+Msg = 2393f956864f57c5dd9cbcf27d89ca8da2772d1c0e2b68a7f321d4b51323e578261bb0457c26aa47e3e9b373cb2853bea894438e98e52f6f4629ba080e5cc34d6238e6f66c4e462ff4568a9185c42651cb9cdcb7408682d20825056b18a5ae379e93a4509df2b3e6d88b4b32f284ccacd334007e4e36e93800bcbec57b26309e
+S = 523cfd39492fdc70370d02763e2185abdbaa5ed331694a52ee7ad0382c4d2aa0c78b0fd0bc0d7debdef5b471dfe5c59962fca60a0b1d7cf68f1cf2d44ef8d9e110abb4e1531a9cb26bf4b585d486fd6ef5ee4d7eb7b6e4d6a930090d0d9d201ecab88fcf5c4c9231fbd5fe4285538ff85554073f9e49b084ba6c03ee6d6966afa029318b07dbea55a1570911579149efe87d67391e665b52774bc498a9f7194b4f0d304c8adf0998461ad7e1902ddcc0f7c326f7d5062f7c32f8d7e0fd3b5189b2ccda6451b7a93db018c93baad28ad871a464a4f0da5a32c81f645a77f9e1b6da16aaf96eb32fcf7d658e1846aad21f85f4af856b9853adf16f5cf5b7ea1ac2136fc13fb735df03b010ae854068bc758e3b875c319df322cba923f4ee6668087d59d80f2e55fdf6e44e5f2dfa1e747d0fb8bb3542d5466c47a2324334c8f5d4edb5a1fcc760a2c71d79b4146cd9d6821d92c308b58ac48502da31a63cc525157d63b25fd59f31a73b5398ecafe12739af44c2f441dc47b93f7f4d10c4b2e484
+SaltVal = 00
index baf013d..a6557dc 100644 (file)
@@ -37,6 +37,7 @@
 #define MINIMUM_POOL_SIZE 16384
 static size_t pool_size;
 static size_t chunk_size;
+static int in_fips_mode;
 
 static void
 test_secmem (void)
@@ -44,12 +45,16 @@ test_secmem (void)
   void *a[28];
   void *b;
   int i;
+  int i_max;
 
   memset (a, 0, sizeof a);
 
   /* Allocating 28*512=14k should work in the default 16k pool even
-   * with extra alignment requirements.  */
-  for (i=0; i < DIM(a); i++)
+   * with extra alignment requirements.
+   */
+  i_max = DIM(a);
+
+  for (i=0; i < i_max; i++)
     a[i] = gcry_xmalloc_secure (chunk_size);
 
   /* Allocating another 2k should fail for the default 16k pool.  */
@@ -76,13 +81,13 @@ test_secmem_overflow (void)
     {
       a[i] = gcry_xmalloc_secure (chunk_size);
       if (verbose && !(i %40))
-        xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
+        xgcry_control ((GCRYCTL_DUMP_SECMEM_STATS, 0 , 0));
     }
 
   if (debug)
-    xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
+    xgcry_control ((PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0));
   if (verbose)
-    xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
+    xgcry_control ((GCRYCTL_DUMP_SECMEM_STATS, 0 , 0));
   for (i=0; i < DIM(a); i++)
     xfree (a[i]);
 }
@@ -103,7 +108,7 @@ outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
   been_here = 1;
 
   info ("outofcore handler invoked");
-  xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
+  xgcry_control ((PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0));
   fail ("out of core%s while allocating %lu bytes",
        (flags & 1)?" in secure memory":"", (unsigned long)req_n);
 
@@ -120,6 +125,14 @@ main (int argc, char **argv)
   long int pgsize_val = -1;
   size_t pgsize;
 
+  if (getenv ("GCRYPT_IN_ASAN_TEST"))
+    {
+      /* 'mlock' is not available when build with address sanitizer,
+       * so skip test. */
+      fputs ("Note: " PGM " skipped because running with ASAN.\n", stdout);
+      return 0;
+    }
+
 #if HAVE_MMAP
 # if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
   pgsize_val = sysconf (_SC_PAGESIZE);
@@ -171,31 +184,35 @@ main (int argc, char **argv)
     die ("version mismatch; pgm=%s, library=%s\n",
          GCRYPT_VERSION, gcry_check_version (NULL));
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-  xgcry_control (GCRYCTL_INIT_SECMEM, pool_size, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INIT_SECMEM, pool_size, 0));
+  /* This is ignored in FIPS Mode */
   gcry_set_outofcore_handler (outofcore_handler, NULL);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
 
   /* Libgcrypt prints a warning when the first overflow is allocated;
    * we do not want to see that.  */
   if (!verbose)
-    xgcry_control (GCRYCTL_DISABLE_SECMEM_WARN, 0);
+    xgcry_control ((GCRYCTL_DISABLE_SECMEM_WARN, 0));
 
 
   test_secmem ();
-  test_secmem_overflow ();
+  if (!in_fips_mode)
+    test_secmem_overflow ();
   /* FIXME: We need to improve the tests, for example by registering
    * our own log handler and comparing the output of
    * PRIV_CTL_DUMP_SECMEM_STATS to expected pattern.  */
 
   if (verbose)
     {
-      xgcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
-      xgcry_control (GCRYCTL_DUMP_SECMEM_STATS, 0 , 0);
+      xgcry_control ((PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0));
+      xgcry_control ((GCRYCTL_DUMP_SECMEM_STATS, 0 , 0));
     }
 
   info ("All tests completed.  Errors: %d\n", error_count);
-  xgcry_control (GCRYCTL_TERM_SECMEM, 0 , 0);
+  xgcry_control ((GCRYCTL_TERM_SECMEM, 0 , 0));
   return !!error_count;
 }
index 2b33520..96d5f97 100644 (file)
@@ -608,7 +608,7 @@ static void
 check_extract_param (void)
 {
   /* This sample data is a real key but with some parameters of the
-     public key modified.  */
+     public key modified.  u,i,I are used for direct extraction tests. */
   static char sample1[] =
     "(key-data"
     " (public-key"
@@ -624,6 +624,12 @@ check_extract_param (void)
     "   (q #20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
     "))"
     " (private-key"
+    "  (u +65537)"
+    "  (i +65537)"
+    "  (I -65535)"
+    "  (i0 1:0)"
+    "  (flaglist foo     bar (sublist x) test 2:42)"
+    "  (noflags)"
     "  (ecc"
     "   (curve Ed25519)"
     "   (p #7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED#)"
@@ -635,6 +641,7 @@ check_extract_param (void)
     "   (n #1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED#)"
     "   (q #30B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62#)"
     "   (d #56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276#)"
+    "   (comment |QWxsIHlvdXIgYmFzZTY0IGFyZSBiZWxvbmcgdG8gdXM=|)"
     ")))";
 
   static char sample1_p[] =
@@ -665,6 +672,7 @@ check_extract_param (void)
     "20B37806015CA06B3AEB9423EE84A41D7F31AA65F4148553755206D679F8BF62";
   static char sample1_d[] =
     "56BEA284A22F443A7AEA8CEFA24DA5055CDF1D490C94D8C568FE0802C9169276";
+  static char sample1_comment[] = "All your base64 are belong to us";
 
   static struct {
     const char *sexp_str;
@@ -814,10 +822,16 @@ check_extract_param (void)
   const char *paramstr;
   int paramidx;
   gpg_error_t err;
-  gcry_sexp_t sxp;
+  gcry_sexp_t sxp, sxp1;
   gcry_mpi_t mpis[7];
   gcry_buffer_t ioarray[7];
   char iobuffer[200];
+  char *string1, *string2;
+  int aint0, aint1, aint2;
+  unsigned int auint;
+  long along1, along2;
+  unsigned long aulong;
+  size_t asize;
 
   info ("checking gcry_sexp_extract_param\n");
   for (idx=0; tests[idx].sexp_str; idx++)
@@ -1049,8 +1063,125 @@ check_extract_param (void)
   gcry_free (ioarray[0].data);
   gcry_mpi_release (mpis[0]);
 
+  sxp1 = gcry_sexp_find_token (sxp, "comment", 7);
+  if (!sxp1)
+    fail ("gcry_sexp_nth_string faild: no SEXP for comment found");
+  else
+    {
+      char *comment = gcry_sexp_nth_string (sxp1, 1);
+
+      if (!comment)
+        fail ("gcry_sexp_nth_string faild: no comment found");
+      else
+        {
+          if (strcmp (comment, sample1_comment))
+            fail ("gcry_sexp_sscan faild for base64");
+          xfree (comment);
+        }
+
+      gcry_sexp_release (sxp1);
+    }
+
+  info ("checking gcry_sexp_extract_param new modes\n");
+
+  memset (mpis, 0, sizeof mpis);
+
   gcry_sexp_release (sxp);
+  err = gcry_sexp_new (&sxp, sample1, 0, 1);
+  if (err)
+    die ("converting string to sexp failed: %s", gpg_strerror (err));
+
+  err = gcry_sexp_extract_param (sxp, "key-data!private-key",
+                                 "%s'curve'+p%s'comment'"
+                                 "%uu%di%dI%d'i0'"
+                                 "%luu%ldi %ldI"
+                                 "%zui",
+                                 &string1, mpis+0, &string2,
+                                 &auint, &aint1, &aint2, &aint0,
+                                 &aulong, &along1, &along2,
+                                 &asize,
+                                 NULL);
+  if (err)
+    fail ("gcry_sexp_extract_param new modes failed: %s", gpg_strerror (err));
+
+  if (!string1)
+    fail ("gcry_sexp_extract_param new modes: no curve");
+  else if (strcmp (string1, "Ed25519"))
+    {
+      fail ("gcry_sexp_extract_param new modes failed: curve mismatch");
+      gcry_log_debug ("expected: %s\n", "Ed25519");
+      gcry_log_debug ("     got: %s\n", string1);
+    }
+
+  if (!mpis[0])
+    fail ("gcry_sexp_extract_param new modes failed: p not returned");
+  else if (cmp_mpihex (mpis[0], sample1_p))
+    {
+      fail ("gcry_sexp_extract_param new modes failed: p mismatch");
+      gcry_log_debug    ("expected: %s\n", sample1_p);
+      gcry_log_debugmpi ("     got", mpis[0]);
+    }
+
+  if (auint != 65537)
+    fail ("gcry_sexp_extract_param new modes failed: auint mismatch");
+  if (aint1 != 65537)
+    fail ("gcry_sexp_extract_param new modes failed: aint1 mismatch");
+  if (aint2 != -65535)
+    fail ("gcry_sexp_extract_param new modes failed: aint2 mismatch");
+  if (aint0)
+    fail ("gcry_sexp_extract_param new modes failed: aint0 mismatch");
+  if (aulong != 65537)
+    fail ("gcry_sexp_extract_param new modes failed: aulong mismatch");
+  if (along1 != 65537)
+    fail ("gcry_sexp_extract_param new modes failed: along1 mismatch");
+  if (along2 != -65535)
+    fail ("gcry_sexp_extract_param new modes failed: along2 mismatch");
+  if (asize != 65537)
+    fail ("gcry_sexp_extract_param new modes failed: asize mismatch");
+
+
+  gcry_free (string1);
+  gcry_free (string2);
+  gcry_mpi_release (mpis[0]);
+
 
+  info ("checking gcry_sexp_extract_param flag list\n");
+
+  gcry_sexp_release (sxp);
+  err = gcry_sexp_new (&sxp, sample1, 0, 1);
+  if (err)
+    die ("converting string to sexp failed: %s", gpg_strerror (err));
+
+  err = gcry_sexp_extract_param (sxp, "key-data!private-key",
+                                 "%#s'flaglist''noflags'",
+                                 &string1, &string2,
+                                 NULL);
+  if (err)
+    fail ("gcry_sexp_extract_param flag list failed: %s", gpg_strerror (err));
+
+  if (!string1)
+    fail ("gcry_sexp_extract_param flaglist: no flaglist");
+  else if (strcmp (string1, "foo bar () test 42"))
+    {
+      fail ("gcry_sexp_extract_param flag list failed: wrong list");
+      gcry_log_debug ("expected: %s\n", "foo bar ( ) test 42");
+      gcry_log_debug ("     got: %s\n", string1);
+    }
+
+  if (!string2)
+    fail ("gcry_sexp_extract_param flaglist: no second flaglist");
+  else if (strcmp (string2, ""))
+    {
+      fail ("gcry_sexp_extract_param flag list failed: wrong list");
+      gcry_log_debug ("expected: '%s'\n", "");
+      gcry_log_debug ("     got: '%s'\n", string2);
+    }
+
+  gcry_free (string1);
+  gcry_free (string2);
+
+
+  gcry_sexp_release (sxp);
 }
 
 
@@ -1130,6 +1261,7 @@ int
 main (int argc, char **argv)
 {
   int last_argc = -1;
+  int loop = 0;
 
   if (argc)
     {
@@ -1164,29 +1296,49 @@ main (int argc, char **argv)
           verbose = debug = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--loop"))
+        {
+          argc--; argv++;
+          if (argc)
+            {
+              loop = atoi (*argv);
+              argc--; argv++;
+            }
+        }
       else if (!strncmp (*argv, "--", 2))
         die ("unknown option '%s'", *argv);
     }
 
   if (debug)
-    xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
-  xgcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
-  xgcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0));
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM_WARN));
+  if (getenv ("GCRYPT_IN_ASAN_TEST"))
+    {
+      fputs ("Note: " PGM " not using secmem as running with ASAN.\n", stdout);
+    }
+  else
+    {
+      xgcry_control ((GCRYCTL_INIT_SECMEM, 16384, 0));
+    }
   if (!gcry_check_version (GCRYPT_VERSION))
     die ("version mismatch");
   /* #include "../src/gcrypt-int.h" indicates that internal interfaces
      may be used; thus better do an exact version check. */
   if (strcmp (gcry_check_version (NULL), GCRYPT_VERSION))
     die ("exact version match failed");
-  xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
-  xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
-
-  basic ();
-  canon_len ();
-  back_and_forth ();
-  check_sscan ();
-  check_extract_param ();
-  bug_1594 ();
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  do
+    {
+      basic ();
+      canon_len ();
+      back_and_forth ();
+      check_sscan ();
+      check_extract_param ();
+      bug_1594 ();
+    }
+  while (!error_count && loop--);
 
   return error_count? 1:0;
 }
diff --git a/tests/t-x448.c b/tests/t-x448.c
new file mode 100644 (file)
index 0000000..f5f49e5
--- /dev/null
@@ -0,0 +1,626 @@
+/* t-x448.c - Check the X488 computation
+ * Copyright (C) 2019 g10 Code GmbH
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "stopwatch.h"
+
+#define PGM "t-x448"
+#include "t-common.h"
+#define N_TESTS 9
+
+static int in_fips_mode;
+
+static void
+print_mpi (const char *text, gcry_mpi_t a)
+{
+  gcry_error_t err;
+  char *buf;
+  void *bufaddr = &buf;
+
+  err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
+  if (err)
+    fprintf (stderr, "%s: [error printing number: %s]\n",
+             text, gpg_strerror (err));
+  else
+    {
+      fprintf (stderr, "%s: %s\n", text, buf);
+      gcry_free (buf);
+    }
+}
+
+
+static void
+show_note (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!verbose && getenv ("srcdir"))
+    fputs ("      ", stderr);  /* To align above "PASS: ".  */
+  else
+    fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+  va_end (arg_ptr);
+}
+
+
+/* Convert STRING consisting of hex characters into its binary
+   representation and return it as an allocated buffer. The valid
+   length of the buffer is returned at R_LENGTH.  The string is
+   delimited by end of string.  The function returns NULL on
+   error.  */
+static void *
+hex2buffer (const char *string, size_t *r_length)
+{
+  const char *s;
+  unsigned char *buffer;
+  size_t length;
+
+  buffer = xmalloc (strlen(string)/2+1);
+  length = 0;
+  for (s=string; *s; s +=2 )
+    {
+      if (!hexdigitp (s) || !hexdigitp (s+1))
+        return NULL;           /* Invalid hex digits. */
+      ((unsigned char*)buffer)[length++] = xtoi_2 (s);
+    }
+  *r_length = length;
+  return buffer;
+}
+
+static void
+reverse_buffer (unsigned char *buffer, unsigned int length)
+{
+  unsigned int tmp, i;
+
+  for (i=0; i < length/2; i++)
+    {
+      tmp = buffer[i];
+      buffer[i] = buffer[length-1-i];
+      buffer[length-1-i] = tmp;
+    }
+}
+
+
+/*
+ * Test X448 functionality through higher layer crypto routines.
+ *
+ * Input: K (as hex string), U (as hex string), R (as hex string)
+ *
+ * where R is expected result of X448 (K, U).
+ *
+ */
+static void
+test_cv_hl (int testno, const char *k_str, const char *u_str,
+              const char *result_str)
+{
+  gpg_error_t err;
+  void *buffer = NULL;
+  size_t buflen;
+  gcry_sexp_t s_pk = NULL;
+  gcry_mpi_t mpi_k = NULL;
+  gcry_sexp_t s_data = NULL;
+  gcry_sexp_t s_result = NULL;
+  gcry_sexp_t s_tmp = NULL;
+  unsigned char *res = NULL;
+  size_t res_len;
+
+  if (verbose > 1)
+    info ("Running test %d\n", testno);
+
+  if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 56)
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "k", "invalid hex string");
+      goto leave;
+    }
+
+  mpi_k = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
+  if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k)))
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "data", gpg_strerror (err));
+      goto leave;
+    }
+
+  if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 56)
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "u", "invalid hex string");
+      goto leave;
+    }
+
+  /*
+   * The procedure of decodeUCoordinate will be done internally
+   * by _gcry_ecc_mont_decodepoint.  So, we just put the little-endian
+   * binary to build S-exp.
+   *
+   * We could add the prefix 0x40, but libgcrypt also supports
+   * format with no prefix.  So, it is OK not to put the prefix.
+   */
+  if ((err = gcry_sexp_build (&s_pk, NULL,
+                              "(public-key"
+                              " (ecc"
+                              "  (curve \"X448\")"
+                              "  (q%b)))", (int)buflen, buffer)))
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "pk", gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer);
+  buffer = NULL;
+
+  err = gcry_pk_encrypt (&s_result, s_data, s_pk);
+  if (in_fips_mode)
+    {
+      if (!err)
+        fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d",
+              testno);
+      if (verbose > 1)
+        info ("not executed in FIPS mode\n");
+      goto leave;
+    }
+  if (err)
+    fail ("gcry_pk_encrypt goto leavefailed for test %d: %s", testno,
+          gpg_strerror (err));
+
+  s_tmp = gcry_sexp_find_token (s_result, "s", 0);
+  if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len)))
+    fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value");
+  else
+    {
+      char *r, *r0;
+      int i;
+
+      r0 = r = xmalloc (2*(res_len)+1);
+      if (!r0)
+        {
+          fail ("memory allocation for test %d", testno);
+          goto leave;
+        }
+
+      for (i=0; i < res_len; i++, r += 2)
+        snprintf (r, 3, "%02x", res[i]);
+      if (strcmp (result_str, r0))
+        {
+          fail ("gcry_pk_encrypt failed for test %d: %s",
+                testno, "wrong value returned");
+          info ("  expected: '%s'", result_str);
+          info ("       got: '%s'", r0);
+        }
+      xfree (r0);
+    }
+
+ leave:
+  xfree (res);
+  gcry_mpi_release (mpi_k);
+  gcry_sexp_release (s_tmp);
+  gcry_sexp_release (s_result);
+  gcry_sexp_release (s_data);
+  gcry_sexp_release (s_pk);
+  xfree (buffer);
+}
+
+/*
+ * Test X448 functionality through the API for X448.
+ *
+ * Input: K (as hex string), U (as hex string), R (as hex string)
+ *
+ * where R is expected result of X448 (K, U).
+ *
+ */
+static void
+test_cv_x448 (int testno, const char *k_str, const char *u_str,
+                const char *result_str)
+{
+  gpg_error_t err;
+  void *scalar;
+  void *point = NULL;
+  size_t buflen;
+  unsigned char result[56];
+  char result_hex[113];
+  int i;
+
+  if (verbose > 1)
+    info ("Running test %d\n", testno);
+
+  if (!(scalar = hex2buffer (k_str, &buflen)) || buflen != 56)
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "k", "invalid hex string");
+      goto leave;
+    }
+
+  if (!(point = hex2buffer (u_str, &buflen)) || buflen != 56)
+    {
+      fail ("error building s-exp for test %d, %s: %s",
+            testno, "u", "invalid hex string");
+      goto leave;
+    }
+
+  err = gcry_ecc_mul_point (GCRY_ECC_CURVE448, result, scalar, point);
+  if (in_fips_mode)
+    {
+      if (err != GPG_ERR_NOT_SUPPORTED)
+        fail ("gcry_ecc_mul_point is not expected to work in FIPS mode for test %d: %s",
+              testno, gpg_strerror (err));
+      if (verbose > 1)
+        info ("not executed in FIPS mode\n");
+      goto leave;
+    }
+  if (err)
+    fail ("gcry_ecc_mul_point failed for test %d: %s", testno,
+          gpg_strerror (err));
+
+  for (i=0; i < 56; i++)
+    snprintf (&result_hex[i*2], 3, "%02x", result[i]);
+
+  if (strcmp (result_str, result_hex))
+    {
+      fail ("gcry_ecc_mul_point failed for test %d: %s",
+            testno, "wrong value returned");
+      info ("  expected: '%s'", result_str);
+      info ("       got: '%s'", result_hex);
+    }
+
+ leave:
+  xfree (scalar);
+  xfree (point);
+}
+
+static void
+test_cv (int testno, const char *k_str, const char *u_str,
+         const char *result_str)
+{
+  test_cv_hl (testno, k_str, u_str, result_str);
+  test_cv_x448 (testno, k_str, u_str, result_str);
+}
+
+/*
+ * Test iterative X448 computation through lower layer MPI routines.
+ *
+ * Input: K (as hex string), ITER, R (as hex string)
+ *
+ * where R is expected result of iterating X448 by ITER times.
+ *
+ */
+static void
+test_it (int testno, const char *k_str, int iter, const char *result_str)
+{
+  gcry_ctx_t ctx = NULL;
+  gpg_error_t err;
+  void *buffer = NULL;
+  size_t buflen;
+  gcry_mpi_t mpi_k = NULL;
+  gcry_mpi_t mpi_x = NULL;
+  gcry_mpi_point_t P = NULL;
+  gcry_mpi_point_t Q;
+  int i;
+  gcry_mpi_t mpi_kk = NULL;
+
+  if (verbose > 1)
+    info ("Running test %d: iteration=%d\n", testno, iter);
+
+  gcry_mpi_ec_new (&ctx, NULL, "X448");
+  if (in_fips_mode)
+    {
+      if (ctx)
+        fail ("gcry_mpi_ec_new should fail in FIPS mode for test %d",
+              testno);
+      if (verbose > 1)
+        info ("not executed in FIPS mode\n");
+      return;
+    }
+  Q = gcry_mpi_point_new (0);
+
+  if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 56)
+    {
+      fail ("error scanning MPI for test %d, %s: %s",
+            testno, "k", "invalid hex string");
+      goto leave;
+    }
+  reverse_buffer (buffer, buflen);
+  if ((err = gcry_mpi_scan (&mpi_x, GCRYMPI_FMT_USG, buffer, buflen, NULL)))
+    {
+      fail ("error scanning MPI for test %d, %s: %s",
+            testno, "x", gpg_strerror (err));
+      goto leave;
+    }
+
+  xfree (buffer);
+  buffer = NULL;
+
+  P = gcry_mpi_point_set (NULL, mpi_x, NULL, GCRYMPI_CONST_ONE);
+
+  mpi_k = gcry_mpi_copy (mpi_x);
+  if (debug)
+    print_mpi ("k", mpi_k);
+
+  for (i = 0; i < iter; i++)
+    {
+      /*
+       * Another variant of decodeScalar448 thing.
+       */
+      mpi_kk = gcry_mpi_set (mpi_kk, mpi_k);
+      gcry_mpi_set_bit (mpi_kk, 447);
+      gcry_mpi_clear_bit (mpi_kk, 0);
+      gcry_mpi_clear_bit (mpi_kk, 1);
+
+      gcry_mpi_ec_mul (Q, mpi_kk, P, ctx);
+
+      P = gcry_mpi_point_set (P, mpi_k, NULL, GCRYMPI_CONST_ONE);
+      gcry_mpi_ec_get_affine (mpi_k, NULL, Q, ctx);
+
+      if (debug)
+        print_mpi ("k", mpi_k);
+    }
+
+  {
+    unsigned char res[56];
+    char *r, *r0;
+
+    gcry_mpi_print (GCRYMPI_FMT_USG, res, 56, NULL, mpi_k);
+    reverse_buffer (res, 56);
+
+    r0 = r = xmalloc (113);
+    if (!r0)
+      {
+        fail ("memory allocation for test %d", testno);
+        goto leave;
+      }
+
+    for (i=0; i < 56; i++, r += 2)
+      snprintf (r, 3, "%02x", res[i]);
+
+    if (strcmp (result_str, r0))
+      {
+        fail ("X448 failed for test %d: %s",
+              testno, "wrong value returned");
+        info ("  expected: '%s'", result_str);
+        info ("       got: '%s'", r0);
+      }
+    xfree (r0);
+  }
+
+ leave:
+  gcry_mpi_release (mpi_kk);
+  gcry_mpi_release (mpi_k);
+  gcry_mpi_point_release (P);
+  gcry_mpi_release (mpi_x);
+  xfree (buffer);
+  gcry_mpi_point_release (Q);
+  gcry_ctx_release (ctx);
+}
+
+/*
+ * X-coordinate of generator of the X448.
+ */
+#define G_X ("0500000000000000000000000000000000000000000000000000000000000000" \
+             "000000000000000000000000000000000000000000000000")
+
+/*
+ * Test Diffie-Hellman in RFC-7748.
+ *
+ * Note that it's not like the ECDH of OpenPGP, where we use
+ * ephemeral public key.
+ */
+static void
+test_dh (int testno, const char *a_priv_str, const char *a_pub_str,
+          const char *b_priv_str, const char *b_pub_str,
+          const char *result_str)
+{
+  /* Test A for private key corresponds to public key. */
+  test_cv (testno, a_priv_str, G_X, a_pub_str);
+  /* Test B for private key corresponds to public key. */
+  test_cv (testno, b_priv_str, G_X, b_pub_str);
+  /* Test DH with A's private key and B's public key. */
+  test_cv (testno, a_priv_str, b_pub_str, result_str);
+  /* Test DH with B's private key and A's public key. */
+  test_cv (testno, b_priv_str, a_pub_str, result_str);
+}
+
+
+static void
+check_x448 (void)
+{
+  int ntests;
+
+  info ("Checking X448.\n");
+
+  ntests = 0;
+
+  /*
+   * Values are cited from RFC-7748: 5.2.  Test Vectors.
+   * Following two tests are for the first type test.
+   */
+  test_cv (1,
+           "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121"
+           "700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3",
+           "06fce640fa3487bfda5f6cf2d5263f8aad88334cbd07437f020f08f9"
+           "814dc031ddbdc38c19c6da2583fa5429db94ada18aa7a7fb4ef8a086",
+           "ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239f"
+           "e14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f");
+  ntests++;
+  test_cv (2,
+           "203d494428b8399352665ddca42f9de8fef600908e0d461cb021f8c5"
+           "38345dd77c3e4806e25f46d3315c44e0a5b4371282dd2c8d5be3095f",
+           "0fbcc2f993cd56d3305b0b7d9e55d4c1a8fb5dbb52f8e9a1e9b6201b"
+           "165d015894e56c4d3570bee52fe205e28a78b91cdfbde71ce8d157db",
+           "884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7"
+           "ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d");
+  ntests++;
+
+  /*
+   * Additional test.  Value is from second type test.
+   */
+  test_cv (3,
+           G_X,
+           G_X,
+           "3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a"
+           "4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113");
+  ntests++;
+
+  /*
+   * Following two tests are for the second type test,
+   * with one iteration and 1,000 iterations.  (1,000,000 iterations
+   * takes too long.)
+   */
+  test_it (4,
+           G_X,
+           1,
+           "3f482c8a9f19b01e6c46ee9711d9dc14fd4bf67af30765c2ae2b846a"
+           "4d23a8cd0db897086239492caf350b51f833868b9bc2b3bca9cf4113");
+  ntests++;
+
+  test_it (5,
+           G_X,
+           1000,
+           "aa3b4749d55b9daf1e5b00288826c467274ce3ebbdd5c17b975e09d4"
+           "af6c67cf10d087202db88286e2b79fceea3ec353ef54faa26e219f38");
+  ntests++;
+
+  /*
+   * Last test is from: 6.  Diffie-Hellman, 6.2.  Curve448
+   */
+  test_dh (6,
+           /* Alice's private key, a */
+           "9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28d"
+           "d9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b",
+           /* Alice's public key, X448(a, 5) */
+           "9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c"
+           "22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0",
+           /* Bob's private key, b */
+           "1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d"
+           "6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d",
+           /* Bob's public key, X448(b, 5) */
+           "3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b430"
+           "27d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609",
+           /* Their shared secret, K */
+           "07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282b"
+           "b60c0b56fd2464c335543936521c24403085d59a449a5037514a879d");
+  ntests++;
+
+  /* three tests which results 0. */
+  test_cv (7,
+           "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121"
+           "700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3",
+           "00000000000000000000000000000000000000000000000000000000"
+           "00000000000000000000000000000000000000000000000000000000",
+           "00000000000000000000000000000000000000000000000000000000"
+           "00000000000000000000000000000000000000000000000000000000");
+  ntests++;
+
+  test_cv (8,
+           "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121"
+           "700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3",
+           "01000000000000000000000000000000000000000000000000000000"
+           "00000000000000000000000000000000000000000000000000000000",
+           "00000000000000000000000000000000000000000000000000000000"
+           "00000000000000000000000000000000000000000000000000000000");
+  ntests++;
+
+  test_cv (9,
+           "3d262fddf9ec8e88495266fea19a34d28882acef045104d0d1aae121"
+           "700a779c984c24f8cdd78fbff44943eba368f54b29259a4f1c600ad3",
+           "feffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+           "feffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+           "00000000000000000000000000000000000000000000000000000000"
+           "00000000000000000000000000000000000000000000000000000000");
+  ntests++;
+
+  if (ntests != N_TESTS)
+    fail ("did %d tests but expected %d", ntests, N_TESTS);
+  else if ((ntests % 256))
+    show_note ("%d tests done\n", ntests);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options]\n"
+                 "Options:\n"
+                 "  --verbose       print timings etc.\n"
+                 "  --debug         flyswatter\n",
+                 stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strncmp (*argv, "--", 2))
+        die ("unknown option '%s'", *argv);
+    }
+
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
+  if (!gcry_check_version (GCRYPT_VERSION))
+    die ("version mismatch\n");
+  if (debug)
+    xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0));
+  xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0));
+  xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0));
+
+  if (gcry_fips_mode_active ())
+    in_fips_mode = 1;
+
+  start_timer ();
+  check_x448 ();
+  stop_timer ();
+
+  info ("All tests completed in %s.  Errors: %d\n",
+        elapsed_time (1), error_count);
+  return !!error_count;
+}
index 38b18b9..2355859 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <gcrypt.h>
 
+#define PGM "testapi"
+#include "t-common.h"
 
 #define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\
                  exit(2);} while(0)
@@ -86,7 +92,7 @@ test_genkey ( int argc, char **argv )
     (void)argc;
     (void)argv;
 
-    xgcry_control( GCRYCTL_INIT_SECMEM, 16384, 0 );
+    xgcry_control ( (GCRYCTL_INIT_SECMEM, 16384, 0) );
     rc = gcry_sexp_build ( &s_parms, NULL, "(genkey(dsa(nbits %d)))", nbits );
     rc = gcry_pk_genkey( &s_key, s_parms );
     if ( rc ) {
diff --git a/tests/testdrv.c b/tests/testdrv.c
new file mode 100644 (file)
index 0000000..816eae0
--- /dev/null
@@ -0,0 +1,888 @@
+/* testdrv.c - Test driver to run all tests w/o using the Makefile.
+ * Copyright (C) 2021 g10 Code GmbH
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifndef HAVE_W32_SYSTEM
+# include <unistd.h>
+# include <fcntl.h>
+# include <sys/wait.h>
+#endif
+#include <gpg-error.h> /* For some macros.  */
+
+#include "stopwatch.h"
+
+#define PGM "testdrv"
+
+/* Flags for testpgms.  */
+#define LONG_RUNNING 1
+
+/* This is our list of tests which are run in this order.  */
+static struct {
+  const char *name;
+  const char *pgm;
+  const char *args;
+  unsigned int flags;  /* e.g. LONG_RUNNING */
+} testpgms[] =
+  {
+   { "version"     },
+   { "t-secmem"    },
+   { "mpitests"    },
+   { "t-sexp"      },
+   { "t-convert"   },
+   { "t-mpi-bit"   },
+   { "t-mpi-point" },
+   { "curves"      },
+   { "t-lock"      },
+   { "prime"       },
+   { "basic"       },
+   { "basic-disable-all-hwf", "basic", "--disable-hwf all" },
+   { "keygen"      },
+   { "pubkey"      },
+   { "hmac"        },
+   { "hashtest"    },
+   { "t-kdf"       },
+   { "keygrip"     },
+   { "fips186-dsa" },
+   { "aeswrap"     },
+   { "pkcs1v2"     },
+   { "random"      },
+   { "dsa-rfc6979" },
+   { "t-ed25519"   },
+   { "t-cv25519"   },
+   { "t-x448"      },
+   { "t-ed448"     },
+   { "benchmark"   },
+   { "bench-slope" },
+   { "hashtest-256g",  "hashtest", "--gigs 256 SHA1 SHA256 SHA512 SM3",
+     LONG_RUNNING },
+   { NULL }
+  };
+
+/* Extra files needed for the above tests.  */
+static const char *extratestfiles[] =
+  {
+   "t-ed25519.inp",
+   "t-ed448.inp",
+   NULL
+  };
+
+
+/* A couple of useful macros.  */
+#ifndef DIM
+# define DIM(v)                     (sizeof(v)/sizeof((v)[0]))
+#endif
+#define DIMof(type,member)   DIM(((type *)0)->member)
+#define xfree(a)      free ((a))
+#define spacep(p)   (*(p) == ' ' || *(p) == '\t')
+
+/* If we have a decent libgpg-error we can use some gcc attributes.  */
+#ifdef GPGRT_ATTR_NORETURN
+static void die (const char *format, ...)
+  GPGRT_ATTR_UNUSED GPGRT_ATTR_NR_PRINTF(1,2);
+static void fail (const char *format, ...)
+  GPGRT_ATTR_UNUSED GPGRT_ATTR_PRINTF(1,2);
+static void info (const char *format, ...) \
+  GPGRT_ATTR_UNUSED GPGRT_ATTR_PRINTF(1,2);
+static void printresult (const char *format, ...) \
+  GPGRT_ATTR_UNUSED GPGRT_ATTR_PRINTF(1,2);
+#endif /*GPGRT_ATTR_NORETURN*/
+
+
+#ifndef TESTDRV_EXEEXT
+# ifdef HAVE_W32_SYSTEM
+#  define TESTDRV_EXEEXT ".exe"
+# else
+#  define TESTDRV_EXEEXT ""
+# endif
+#endif
+#ifdef HAVE_W32_SYSTEM
+# define MYPID_T HANDLE
+# define MYINVALID_PID INVALID_HANDLE_VALUE
+#else
+# define MYPID_T pid_t
+# define MYINVALID_PID ((pid_t)(-1))
+#endif
+
+/* Standard global variables.  */
+static int verbose;
+static int debug;
+static int error_count;
+static int die_on_error;
+static int long_running;
+static char **myenviron;
+static int testcount, failcount, passcount, skipcount;
+
+#ifdef HAVE_W32_SYSTEM
+static char *
+my_stpcpy (char *a, const char *b)
+{
+  while (*b)
+    *a++ = *b++;
+  *a = 0;
+
+  return a;
+}
+#endif /*HAVE_W32_SYSTEM*/
+
+/* Reporting functions.  */
+static void
+die (const char *format, ...)
+{
+  va_list arg_ptr ;
+
+  /* Avoid warning.  */
+  (void) debug;
+
+  fflush (stdout);
+#ifdef HAVE_FLOCKFILE
+  flockfile (stderr);
+#endif
+  fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format) ;
+  vfprintf (stderr, format, arg_ptr);
+  va_end (arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+#ifdef HAVE_FLOCKFILE
+  funlockfile (stderr);
+#endif
+  exit (1);
+}
+
+static void *
+xmalloc (size_t n)
+{
+  char *p = malloc (n);
+  if (!p)
+    die ("malloc failed");
+  return p;
+}
+
+static void *
+xcalloc (size_t n, size_t m)
+{
+  char *p = calloc (n, m);
+  if (!p)
+    die ("calloc failed");
+  return p;
+}
+
+static char *
+xstrdup (const char *s)
+{
+  size_t n = strlen (s);
+  char *p = xmalloc (n+1);
+  strcpy (p, s);
+  return p;
+}
+
+
+static void
+fail (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  fflush (stdout);
+#ifdef HAVE_FLOCKFILE
+  flockfile (stderr);
+#endif
+  fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  va_end (arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+#ifdef HAVE_FLOCKFILE
+  funlockfile (stderr);
+#endif
+  if (die_on_error)
+    exit (1);
+  error_count++;
+}
+
+
+static void
+info (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  if (!verbose)
+    return;
+  fflush (stdout);
+#ifdef HAVE_FLOCKFILE
+  flockfile (stderr);
+#endif
+  fprintf (stderr, "%s: ", PGM);
+  va_start (arg_ptr, format);
+  vfprintf (stderr, format, arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stderr);
+  va_end (arg_ptr);
+#ifdef HAVE_FLOCKFILE
+  funlockfile (stderr);
+#endif
+}
+
+
+static void
+printresult (const char *format, ...)
+{
+  va_list arg_ptr;
+
+  fflush (stdout);
+#ifdef HAVE_FLOCKFILE
+  flockfile (stdout);
+#endif
+  va_start (arg_ptr, format);
+  vfprintf (stdout, format, arg_ptr);
+  if (*format && format[strlen(format)-1] != '\n')
+    putc ('\n', stdout);
+  va_end (arg_ptr);
+  fflush (stdout);
+#ifdef HAVE_FLOCKFILE
+  funlockfile (stdout);
+#endif
+}
+
+
+/* Tokenize STRING using the set of delimiters in DELIM.  Leading
+ * spaces and tabs are removed from all tokens.  The caller must free
+ * the result. Returns a malloced and NULL delimited array with the
+ * tokens.  */
+static char **
+strtokenize (const char *string, const char *delim)
+{
+  const char *s;
+  size_t fields;
+  size_t bytes, n;
+  char *buffer;
+  char *p, *px, *pend;
+  char **result;
+
+  /* Count the number of fields.  */
+  for (fields = 1, s = strpbrk (string, delim); s; s = strpbrk (s + 1, delim))
+    fields++;
+  fields++; /* Add one for the terminating NULL.  */
+
+  /* Allocate an array for all fields, a terminating NULL, and space
+     for a copy of the string.  */
+  bytes = fields * sizeof *result;
+  if (bytes / sizeof *result != fields)
+    die ("integer overflow at %d\n", __LINE__);
+  n = strlen (string) + 1;
+  bytes += n;
+  if (bytes < n)
+    die ("integer overflow at %d\n", __LINE__);
+  result = xmalloc (bytes);
+  buffer = (char*)(result + fields);
+
+  /* Copy and parse the string.  */
+  strcpy (buffer, string);
+  for (n = 0, p = buffer; (pend = strpbrk (p, delim)); p = pend + 1)
+    {
+      *pend = 0;
+      while (spacep (p))
+        p++;
+      for (px = pend - 1; px >= p && spacep (px); px--)
+        *px = 0;
+      result[n++] = p;
+    }
+  while (spacep (p))
+    p++;
+  for (px = p + strlen (p) - 1; px >= p && spacep (px); px--)
+    *px = 0;
+  result[n++] = p;
+  result[n] = NULL;
+
+  if (!((char*)(result + n + 1) == buffer))
+    die ("bug at %d\n", __LINE__);
+
+  return result;
+}
+
+
+#ifdef HAVE_W32_SYSTEM
+/* Helper functions for Windows. */
+static char *
+build_w32_commandline_copy (char *buffer, const char *string)
+{
+  char *p = buffer;
+  const char *s;
+
+  if (!*string) /* Empty string. */
+    p = my_stpcpy (p, "\"\"");
+  else if (strpbrk (string, " \t\n\v\f\""))
+    {
+      /* Need to do some kind of quoting.  */
+      p = my_stpcpy (p, "\"");
+      for (s=string; *s; s++)
+        {
+          *p++ = *s;
+          if (*s == '\"')
+            *p++ = *s;
+        }
+      *p++ = '\"';
+      *p = 0;
+    }
+  else
+    p = my_stpcpy (p, string);
+
+  return p;
+}
+
+/* Build a command line for use with CreateProcess.  This function
+ * either terminates the process or returns a malloced string.  */
+static char *
+build_w32_commandline (const char *pgmname, char **argv)
+{
+  int i, n;
+  const char *s;
+  char *buf, *p;
+
+  s = pgmname;
+  n = strlen (s) + 1 + 2;  /* (1 space, 2 quoting) */
+  for (; *s; s++)
+    if (*s == '\"')
+      n++;  /* Account for to be doubled inner quotes.  */
+  for (i=0; argv && (s=argv[i]); i++)
+    {
+      n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting) */
+      for (; *s; s++)
+        if (*s == '\"')
+          n++;  /* For doubling inner quotes.  */
+    }
+  n++;  /* String terminator.  */
+
+  buf = p = xmalloc (n);
+  p = build_w32_commandline_copy (p, pgmname);
+  for (i=0; argv && argv[i]; i++)
+    {
+      *p++ = ' ';
+      p = build_w32_commandline_copy (p, argv[i]);
+    }
+
+  return buf;
+}
+
+static HANDLE
+w32_open_null (int for_write)
+{
+  HANDLE hfile;
+
+  hfile = CreateFileW (L"nul",
+                       for_write? GENERIC_WRITE : GENERIC_READ,
+                       FILE_SHARE_READ | FILE_SHARE_WRITE,
+                       NULL, OPEN_EXISTING, 0, NULL);
+  if (hfile == INVALID_HANDLE_VALUE)
+    die ("can't open 'nul': ec=%lu\n", (unsigned long)GetLastError());
+  return hfile;
+}
+
+#endif /*HAVE_W32_SYSTEM*/
+
+
+/* Fork and exec the PGMNAME using ARGV as arguments (w/o pgmmname)
+ * and return the pid at PID.  If ENVP is not NULL, add these strings
+ * as environment variables.  Return -1 on severe errors. */
+static int
+my_spawn (const char *pgmname, char **argv, char **envp, MYPID_T *pid)
+{
+#ifdef HAVE_W32_SYSTEM
+  int rc;
+  SECURITY_ATTRIBUTES sec_attr;
+  PROCESS_INFORMATION pi = { NULL };
+  STARTUPINFO si;
+  char *cmdline;
+  char *pgmnamefull = NULL;
+  char **saveenviron = NULL;
+  int i;
+
+  /* Prepare security attributes.  */
+  memset (&sec_attr, 0, sizeof sec_attr );
+  sec_attr.nLength = sizeof sec_attr;
+  sec_attr.bInheritHandle = FALSE;
+
+  if (!(strlen (pgmname) > 4 && !strcmp (pgmname+strlen(pgmname)-4, ".exe")))
+    {
+      pgmnamefull = xmalloc (strlen (pgmname) + 4 + 1);
+      strcpy (my_stpcpy (pgmnamefull, pgmname), ".exe");
+      pgmname = pgmnamefull;
+    }
+
+  /* Build the command line.  */
+  cmdline = build_w32_commandline (pgmname, argv);
+
+  memset (&si, 0, sizeof si);
+  si.cb = sizeof (si);
+  si.dwFlags = STARTF_USESTDHANDLES;
+  si.hStdInput  = w32_open_null (0);
+  if (verbose)
+    si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
+  else
+    si.hStdOutput = w32_open_null (1);
+  si.hStdError  = GetStdHandle (STD_ERROR_HANDLE);
+
+  if (envp)
+    {
+      for (i=0; envp[i]; i++)
+        ;
+      saveenviron = xcalloc (i+1, sizeof *saveenviron);
+      for (i=0; envp[i]; i++)
+        saveenviron[i] = xstrdup (envp[i]);
+      for (i=0; envp[i]; i++)
+        putenv (envp[i]);
+    }
+
+  if (debug)
+    info ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline);
+  if (!CreateProcess (pgmname,       /* Program to start.  */
+                      cmdline,       /* Command line arguments.  */
+                      &sec_attr,     /* Process security attributes.  */
+                      &sec_attr,     /* Thread security attributes.  */
+                      TRUE,          /* Inherit handles.  */
+                      (CREATE_DEFAULT_ERROR_MODE
+                       | GetPriorityClass (GetCurrentProcess ())
+                       | CREATE_SUSPENDED | DETACHED_PROCESS),
+                      NULL,          /* Environment.  */
+                      NULL,          /* Use current drive/directory.  */
+                      &si,           /* Startup information. */
+                      &pi            /* Returns process information.  */
+                      ))
+    {
+      fail ("CreateProcess failed: ec=%lu\n", (unsigned long)GetLastError());
+      rc = -1;
+    }
+  else
+    rc = 0;
+
+  if (saveenviron)
+    {
+      for (i=0; saveenviron[i]; i++)
+        xfree (saveenviron[i]);
+      xfree (saveenviron);
+    }
+  xfree (cmdline);
+  CloseHandle (si.hStdInput);
+  if (!verbose)
+    CloseHandle (si.hStdOutput);
+  xfree (pgmnamefull); pgmname = NULL;
+  if (rc)
+    return rc;
+
+  if (debug)
+    info ("CreateProcess ready: hProcess=%p hThread=%p"
+          " dwProcessID=%d dwThreadId=%d\n",
+          pi.hProcess, pi.hThread,
+          (int) pi.dwProcessId, (int) pi.dwThreadId);
+
+  /* Process has been created suspended; resume it now. */
+  ResumeThread (pi.hThread);
+  CloseHandle (pi.hThread);
+
+  *pid = pi.hProcess;
+  return 0;
+
+#else /*!HAVE_W32_SYSTEM*/
+
+  char **arg_list;
+  int i, j;
+  int fd;
+
+  /* Create the command line argument array.  */
+  i = 0;
+  if (argv)
+    while (argv[i])
+      i++;
+  arg_list = xcalloc (i+2, sizeof *arg_list);
+  arg_list[0] = strrchr (pgmname, '/');
+  if (arg_list[0])
+    arg_list[0]++;
+  else
+    arg_list[0] = xstrdup (pgmname);
+  if (argv)
+    for (i=0,j=1; argv[i]; i++, j++)
+      arg_list[j] = (char*)argv[i];
+
+
+  *pid = fork ();
+  if (*pid == MYINVALID_PID)
+    {
+      fail ("error forking process: %s\n", strerror (errno));
+      return -1;
+    }
+
+  if (!*pid)
+    {
+      /* This is the child. */
+      if (envp)
+        for (i=0; envp[i]; i++)
+          putenv (xstrdup (envp[i]));
+
+      /* Assign /dev/null to stdin. */
+      fd = open ("/dev/null", O_RDONLY);
+      if (fd == -1)
+        die ("failed to open '%s': %s\n", "/dev/null", strerror (errno));
+      if (fd != 0 && dup2 (fd, 0) == -1)
+        die ("dup2(%d,0) failed: %s\n", fd, strerror (errno));
+      /* Assign /dev/null to stdout unless in verbose mode. */
+      if (!verbose)
+        {
+          fd = open ("/dev/null", O_RDONLY);
+          if (fd == -1)
+            die ("failed to open '%s': %s\n", "/dev/null", strerror (errno));
+          if (fd != 1 && dup2 (fd, 1) == -1)
+            die ("dup2(%d,1) failed: %s\n", fd, strerror (errno));
+        }
+
+      /* Exec the program.  */
+      execv (pgmname, arg_list);
+      info ("exec '%s' failed: %s\n", pgmname, strerror (errno));
+      _exit (127);
+      /*NOTREACHED*/
+    }
+
+  /* This is the parent. */
+  xfree (arg_list);
+  return 0;
+#endif /*!HAVE_W32_SYSTEM*/
+}
+
+
+/* Wait for PID and return its exitcode at R_EXITCODE.  PGMNAME is
+ * only used for diagnostics.  */
+static int
+my_wait (const char *pgmname, MYPID_T pid, int *r_exitcode)
+{
+  int rc = -1;
+
+#ifdef HAVE_W32_SYSTEM
+  HANDLE procs[1];
+  DWORD exc;
+  int code;
+
+  if (pid == MYINVALID_PID)
+    die ("invalid pid passed to my_wait\n");
+
+  procs[0] = (HANDLE)pid;
+  code = WaitForMultipleObjects (1, procs, TRUE, INFINITE);
+  switch (code)
+    {
+    case WAIT_TIMEOUT: /* Should not happen.  */
+      fail ("waiting for process %p (%s) to terminate failed: timeout\n",
+            pid, pgmname);
+      break;
+
+    case WAIT_FAILED:
+      fail ("waiting for process %p (%s) to terminate failed: ec=%lu\n",
+            pid, pgmname, (unsigned long)GetLastError ());
+      break;
+
+    case WAIT_OBJECT_0:
+      if (!GetExitCodeProcess (procs[0], &exc))
+        {
+          fail ("error getting exit code for process %p (%s): ec=%lu\n",
+                pid, pgmname, (unsigned long)GetLastError ());
+        }
+      else
+        {
+          *r_exitcode = (int)exc;
+          rc = 0;
+        }
+      break;
+
+    default:
+      fail ("WaitForMultipleObjects returned unexpected code %d\n", code);
+      break;
+    }
+  CloseHandle ((HANDLE)pid);
+
+#else /*!HAVE_W32_SYSTEM*/
+
+  int i, status;
+
+  if (pid == MYINVALID_PID)
+    die ("invalid pid passed to my_wait\n");
+
+  while ((i=waitpid (pid, &status, 0)) == MYINVALID_PID
+         && errno == EINTR)
+    ;
+
+  if (i == MYINVALID_PID)
+    {
+      fail ("waiting for process %d (%s) to terminate failed: %s\n",
+            (int)pid, pgmname, strerror (errno));
+    }
+  else if (!i)
+    {
+      die ("waitpid returns unexpected code 0\n");
+    }
+  else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
+    {
+      fail ("error running '%s': probably not installed\n", pgmname);
+    }
+  else if (WIFEXITED (status) && WEXITSTATUS (status))
+    {
+      *r_exitcode = WEXITSTATUS (status);
+      rc = 0;
+    }
+  else if (!WIFEXITED (status))
+    {
+      info ("error running '%s': terminated\n", pgmname);
+      rc = 1;
+    }
+  else
+    {
+      *r_exitcode = 0;
+      rc = 0;
+    }
+
+#endif /*!HAVE_W32_SYSTEM*/
+
+  return rc;
+}
+
+
+static void
+run_one_test (int idx)
+{
+  MYPID_T pid;
+  int exitcode, rc;
+  const char *name = testpgms[idx].name;
+  const char *pgm = testpgms[idx].pgm;
+  char **args;
+
+  if (!pgm)
+    pgm = name;
+
+  testcount++;
+  if ((testpgms[idx].flags & LONG_RUNNING)
+      && !long_running)
+    {
+      printresult ("SKIP: %s\n", name);
+      skipcount++;
+      return;
+    }
+
+  args = testpgms[idx].args? strtokenize (testpgms[idx].args, " ") : NULL;
+  rc = my_spawn (pgm, args, myenviron, &pid);
+  xfree (args);
+  if (rc)
+    {
+      printresult ("FAIL: %s (error invoking test)\n", name);
+      failcount++;
+      return;
+    }
+  rc = my_wait (pgm, pid, &exitcode);
+  if (rc < 0)
+    {
+      printresult ("FAIL: %s (error running test)\n", name);
+      failcount++;
+    }
+  else if (rc)
+    {
+      printresult ("FAIL: %s (test crashed)\n", name);
+      failcount++;
+    }
+  else if (exitcode == 77)
+    {
+      printresult ("SKIP: %s\n", name);
+      skipcount++;
+    }
+  else if (exitcode == 1)
+    {
+      printresult ("FAIL: %s\n", name);
+      failcount++;
+    }
+  else if (exitcode)
+    {
+      printresult ("FAIL: %s (exit code %d)\n", name, exitcode);
+      failcount++;
+    }
+  else
+    {
+      printresult ("PASS: %s\n", name);
+      passcount++;
+    }
+}
+
+
+
+static void
+runtests (char **argv)
+{
+  int i;
+
+  if (argv && *argv)
+    {
+      for ( ; *argv; argv++)
+        {
+          for (i=0; testpgms[i].name; i++)
+            if (!strcmp (testpgms[i].name, *argv))
+              {
+                run_one_test (i);
+                break;
+              }
+          if (!testpgms[i].name)
+            {
+              fail ("requested test '%s' not found\n", *argv);
+              testcount++;
+            }
+        }
+    }
+  else /* Run all tests.  */
+    {
+      for (i=0; testpgms[i].name; i++)
+        run_one_test (i);
+    }
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  int listtests = 0;
+  int i;
+  const char *srcdir;
+
+  if (argc)
+    { argc--; argv++; }
+
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [options] [tests_to_run]\n"
+                 "Options:\n"
+                 "  --verbose       print timings etc.\n"
+                 "  --debug         flyswatter\n"
+                 "  --list          list all tests\n"
+                 "  --files         list all files\n"
+                 "  --long          include long running tests\n"
+                 , stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--list"))
+        {
+          listtests = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--files"))
+        {
+          listtests = 2;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--long"))
+        {
+          long_running = 1;
+          argc--; argv++;
+        }
+      else if (!strncmp (*argv, "--", 2))
+        die ("unknown option '%s'", *argv);
+    }
+
+  srcdir = getenv ("srcdir");
+
+  myenviron = xcalloc (2, sizeof *myenviron);
+  myenviron[0] = xstrdup ("GCRYPT_IN_REGRESSION_TEST=1");
+#ifndef HAVE_W32_SYSTEM
+  if (!access ("libgcrypt-standalone-tests", F_OK))
+    myenviron[1] = xstrdup ("LD_LIBRARY_PATH=.");
+#endif
+
+  if (listtests == 1)
+    {
+      for (i=0; testpgms[i].name; i++)
+        {
+          printf ("%s", testpgms[i].name);
+          if (testpgms[i].pgm || testpgms[i].args)
+            printf (" (%s %s)",
+                    testpgms[i].pgm? testpgms[i].pgm : testpgms[i].name,
+                    testpgms[i].args? testpgms[i].args : "");
+          if (testpgms[i].flags)
+            {
+              putchar (' ');
+              putchar ('[');
+              if (testpgms[i].flags)
+                fputs ("long", stdout);
+              putchar (']');
+            }
+          putchar ('\n');
+        }
+    }
+  else if (listtests == 2)
+    {
+      for (i=0; testpgms[i].name; i++)
+        printf ("%s%s%s\n",
+                strcmp (TESTDRV_EXEEXT, ".exe")? "":".libs/",
+                testpgms[i].pgm? testpgms[i].pgm : testpgms[i].name,
+                TESTDRV_EXEEXT);
+      for (i=0; extratestfiles[i]; i++)
+        printf ("%s%s%s\n",
+                srcdir? srcdir :"",
+                srcdir? "/" :"",
+                extratestfiles[i]);
+    }
+  else
+    {
+      start_timer ();
+      runtests (argv);
+      stop_timer ();
+
+      printresult ("%d tests run, %d succeeded, %d failed, %d skipped.\n",
+                   testcount-skipcount, passcount, failcount, skipcount);
+      if (testcount != passcount + failcount + skipcount)
+        printresult ("Warning: Execution of some tests failed\n");
+
+      info ("All tests completed in %s.  Errors: %d\n",
+            elapsed_time (1), error_count + failcount);
+    }
+
+  for (i=0; myenviron[i]; i++)
+    xfree (myenviron[i]);
+  xfree (myenviron);
+
+  return !!error_count;
+}
index 7e68cd6..9d3a3c2 100644 (file)
@@ -145,9 +145,9 @@ main (int argc, char **argv)
         }
     }
 
-  xgcry_control (GCRYCTL_SET_VERBOSITY, (int)verbose);
+  xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose));
 
-  xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0));
   if (strcmp (GCRYPT_VERSION, gcry_check_version (NULL)))
     {
       int oops = !gcry_check_version (GCRYPT_VERSION);
@@ -157,10 +157,9 @@ main (int argc, char **argv)
         exit (1);
     }
 
-  xgcry_control (GCRYCTL_PRINT_CONFIG, NULL);
+  xgcry_control ((GCRYCTL_PRINT_CONFIG, stdout));
 
   test_get_config ();
 
-
   return 0;
 }